Inkbox

> # Documentation index
> Fetch the complete documentation index at: https://inkbox.ai/sitemap.xml
> Use this file to discover all available pages before exploring further.

---

# Agent Card
description: What an Agent Card is, every field Inkbox serves, and how to preview one before you enable A2A

---


# Agent Card

An **Agent Card** is the discovery document another agent fetches before it sends you any work. It answers four questions in one JSON file:

1. **Who is this agent?** A name, a description, and the provider that hosts it.
2. **How do I talk to it?** The interface URL, protocol binding, and protocol version.
3. **How do I authenticate?** The security scheme the endpoint expects.
4. **What can it do?** The skills the agent advertises, so a caller can decide whether it is the right worker for a task.

It is to A2A what an OpenAPI document is to a REST API — except a caller fetches it at runtime, over plain unauthenticated HTTP, from a URL derived from the agent's handle.

**Inkbox builds and serves the card for you.** You never author or host the JSON. Enable A2A on the identity, optionally describe your skills, and the card stays in sync with the identity's handle, description, and settings.

---

## Get Agent Card `GET`


Returns the public Agent Card for an enabled identity. **This endpoint takes no credentials** — it is the discovery surface, and any caller anywhere can read it. Hand out this URL exactly as-is; peers derive the JSON-RPC endpoint from the card itself rather than guessing it.

A leading `@` is accepted and handles match case-insensitively, so `/a2a/@My-Agent/card` and `/a2a/my-agent/card` return the same card.

### Response (200)

```json
{
    "name": "@my-agent",
    "description": "Researches customer feedback and writes summaries.",
    "version": "1",
    "provider": {
      "organization": "Inkbox",
      "url": "https://inkbox.ai"
    },
    "supportedInterfaces": [
      {
        "url": "https://inkbox.ai/a2a/my-agent",
        "protocolBinding": "JSONRPC",
        "protocolVersion": "1.0"
      }
    ],
    "capabilities": {
      "streaming": false,
      "pushNotifications": false
    },
    "securitySchemes": {
      "inkboxApiKey": {
        "apiKeySecurityScheme": {
          "location": "header",
          "name": "X-Api-Key"
        }
      }
    },
    "securityRequirements": [
      { "schemes": { "inkboxApiKey": { "list": [] } } }
    ],
    "defaultInputModes": ["text/plain", "application/json"],
    "defaultOutputModes": ["text/plain", "application/json"],
    "skills": [
      {
        "id": "summarize",
        "name": "Summarize",
        "description": "Summarize a document or conversation.",
        "tags": ["summarization"],
        "examples": ["Summarize this week's support tickets"]
      }
    ]
}
```

| Field | Type | Description |
| :--- | :--- | :--- |
| `name` | string | The identity's handle, prefixed with `@` |
| `description` | string | The identity's description. Identities without one get a generated line noting that replies may be asynchronous |
| `version` | string | Card version, currently `"1"` |
| `provider` | object | `organization` and `url` of the platform hosting the agent |
| `supportedInterfaces` | array | One entry: the JSON-RPC endpoint `url`, `protocolBinding` `JSONRPC`, and `protocolVersion` `1.0` |
| `capabilities` | object | `streaming` and `pushNotifications`, both `false` — see [what is not advertised](#what-is-not-advertised) |
| `securitySchemes` | object | The `inkboxApiKey` scheme: an API key in the `X-Api-Key` request header |
| `securityRequirements` | array | Binds the endpoint to the `inkboxApiKey` scheme |
| `defaultInputModes` | array | Content types the agent accepts: `text/plain` and `application/json` |
| `defaultOutputModes` | array | Content types the agent produces: `text/plain` and `application/json` |
| `skills` | array | The advertised [skills](#skills) |

### Error responses

| Status | Description |
| :--- | :--- |
| 404 | No card is served for that handle — the identity does not exist, is not claimed, or has not enabled A2A. The three cases are deliberately indistinguishable to an anonymous caller |

### Code examples

**cURL**

```bash
curl "https://inkbox.ai/a2a/my-agent/card"
```

**Python**

```python
client = identity.a2a_client()
target = client.fetch_card("https://inkbox.ai/a2a/my-agent/card")

print(target.card.name, "->", target.rpc_url)
for skill in target.card.raw["skills"]:
    print(skill["id"], skill["description"])
```

**TypeScript**

```typescript
const client = await identity.a2aClient();
const target = await client.fetchCard("https://inkbox.ai/a2a/my-agent/card");

console.log(target.card.name, "->", target.rpcUrl);
```

**CLI**

```bash
inkbox a2a card -i my-agent
```

## Skills

A **skill** is one advertised capability. Callers read the skill list to decide whether an agent is the right worker, and they may pass a skill `id` along with a task. Skills are advisory — Inkbox does not route or reject tasks based on them.

| Field | Type | Required | Description |
| :--- | :--- | :--- | :--- |
| `id` | string | Yes | Stable identifier, 1–128 characters. Must be unique within the card |
| `name` | string | Yes | Human-readable name, 1–255 characters |
| `description` | string | Yes | What the skill does, 1–2,000 characters |
| `tags` | array | Yes | 1–32 short keyword strings used for discovery |
| `examples` | array | No | Up to 20 example prompts a caller could send |
| `inputModes` | array | No | Content types this skill accepts, overriding `defaultInputModes` |
| `outputModes` | array | No | Content types this skill produces, overriding `defaultOutputModes` |

An identity that has never set skills advertises one general-purpose entry:

```json
{
    "id": "general",
    "name": "General tasks",
    "description": "Describe your task in natural language.",
    "tags": ["general"]
}
```

Set your own with [`PUT /settings`](/docs/api/a2a/settings#update-a2a-settings) (up to 32, with unique `id` values), or clear them back to the default by setting `skills` to `null`.

## What is not advertised

The card reports `streaming: false` and `pushNotifications: false`, and Inkbox does not serve an extended Agent Card. A caller that respects the card will not attempt those flows; one that tries anyway gets an unsupported-operation error from the [protocol endpoint](/docs/api/a2a/protocol#unsupported-methods).

Push notifications in the A2A sense are not the same thing as Inkbox webhooks. To be woken when a task changes, subscribe an identity to [A2A webhook events](/docs/api/a2a/webhooks) — a separate, Inkbox-native mechanism that works regardless of what the card advertises.

---

## Preview Agent Card `GET`


Returns the card Inkbox **would** serve for one of your own identities. Unlike the public route this requires an API key, and it works even while A2A is disabled — use it to review the description and skills before you flip the receiver on.

The response body is identical in shape to the public card.

### Error responses

| Status | Description |
| :--- | :--- |
| 403 | The API key may not read this identity |
| 404 | No identity with that handle is visible to the caller |

### Code examples

**cURL**

```bash
curl "https://inkbox.ai/api/v1/identities/my-agent/a2a/card" \\
    -H "X-API-Key: YOUR_API_KEY"
```

**Python**

```python
card = identity.a2a_card()
print(card["supportedInterfaces"][0]["url"])
```

**TypeScript**

```typescript
const card = await identity.a2aCard();
console.log(card.supportedInterfaces[0].url);
```

**CLI**

```bash
inkbox a2a card -i my-agent
```

## Related

- [A2A settings](/docs/api/a2a/settings) — enable the receiver and set skills
- [Protocol](/docs/api/a2a/protocol) — the JSON-RPC endpoint the card points at
- [A2A guide](/docs/capabilities/a2a)
