# A2A Agent Card and Interface Specification: [Agent name]

> Specification for an AI agent exposed to other agents over the
> Agent2Agent (A2A) protocol: identity and metadata, skills,
> capabilities, protocol bindings, security schemes, supported
> operations, task lifecycle, messages, parts and artifacts, streaming
> and push notifications, errors, versioning and discovery, an example
> Agent Card, security considerations and a conformance checklist.
> Written against the A2A Protocol Specification **1.0.1** (May 2026, a
> patch release of 1.0.0 from March 2026 with an unchanged `a2a.proto`;
> the protocol version used on the wire is `1.0`), whose
> normative definition is the `a2a.proto` file in the specification
> repository. A2A is a Linux Foundation project and, since August 2026,
> a hosted project of the Agentic AI Foundation. Check the current
> release at a2a-protocol.org before you start. Replace every
> `[bracketed]` value and every row marked *Example*.

<!--
Guidance: How to use this template
- Write one document per agent you expose. It is the contract other
  teams and organisations build against, and the source for the Agent
  Card you publish.
- Field names in this template are the JSON (camelCase) names from the
  1.0 data model. The protobuf definition uses snake_case for the same
  fields. Copy names exactly; a client ignores or rejects a misspelt key.
- Enum values are serialised as their full names, for example
  `TASK_STATE_WORKING` and `ROLE_USER`. Versions before 1.0 used
  different names and shapes; if you must serve 0.3 clients, say so in
  section 2 and test both.
- Everything a remote client sends you is untrusted input, and everything
  you return may be read by another model. Section 15 is not optional.
- Related documents: AI agent specification (`ai-data/ai-agent-spec`)
  for the agent's internals, MCP server specification (`ai-data/mcp-server-spec`) for the tools behind it, Multi-agent system  design (`ai-data/multi-agent-system-design`) for the system it belongs
  to, Agent tool and permission design (`ai-data/agent-tool-permission-design`), Agentic threat model (`ai-data/agentic-threat-model`).
-->

## Document control

<!-- Guidance: Record the agent version, the A2A protocol version it implements and the people who approve interface changes. The Agent Card `version` and this document's version are different things; record both. -->

| Field | Value |
|---|---|
| Document ID | [A2A-SPEC-001] |
| Agent name | [Name as in the Agent Card `name`] |
| Agent version (card `version`) | [1.0.0] |
| Document version | [0.1] |
| A2A specification | 1.0.1 (protocol version `1.0`) |
| Older protocol versions served | [None / 0.3 on a separate interface] |
| Status | [Draft / In review / Approved / Deprecated] |
| Owner | [@agent-owner] |
| Approvers/reviewers | [@api-review], [@security-engineer], [@platform-engineer] |
| Public Agent Card URL | [`https://agent.example.com/.well-known/agent-card.json`] |
| Classification | [Public / Internal / Confidential] |
| Last updated | YYYY-MM-DD |
| Related documents | [Agent specification], [MCP server specifications], [Threat model], [Runbook] |

### Approvals

| Role | Name | Decision | Date |
|---|---|---|---|
| Agent owner | [@name] | [Approve / Approve with conditions / Reject] | YYYY-MM-DD |
| API review | [@name] | [Decision] | YYYY-MM-DD |
| Security | [@name] | [Decision] | YYYY-MM-DD |
| Identity and access management | [@name] | [Decision] | YYYY-MM-DD |

## Revision history

<!-- Guidance: Record every change to the card, skills, interfaces or security requirements. Removing a skill or interface, or tightening security, is a breaking change for clients. -->

| Version | Date | Author | Change summary |
|---|---|---|---|
| 0.1 | YYYY-MM-DD | [@name] | First draft |
| 1.0 | YYYY-MM-DD | [@name] | *Example:* First release with JSON-RPC and HTTP+JSON interfaces |
| 1.1 | YYYY-MM-DD | [@name] | *Example:* Added push notifications and a signed card |

## Contents

<!-- Guidance: Keep aligned with the headings below. -->

1. [Purpose and scope](#1-purpose-and-scope)
2. [Protocol baseline and governance](#2-protocol-baseline-and-governance)
3. [Agent identity and metadata](#3-agent-identity-and-metadata)
4. [Interfaces and protocol bindings](#4-interfaces-and-protocol-bindings)
5. [Capabilities and extensions](#5-capabilities-and-extensions)
6. [Skills](#6-skills)
7. [Security schemes and authentication](#7-security-schemes-and-authentication)
8. [Supported operations](#8-supported-operations)
9. [Task lifecycle and states](#9-task-lifecycle-and-states)
10. [Messages, parts and artifacts](#10-messages-parts-and-artifacts)
11. [Streaming and push notifications](#11-streaming-and-push-notifications)
12. [Error handling](#12-error-handling)
13. [Versioning, discovery and caching](#13-versioning-discovery-and-caching)
14. [Example Agent Card](#14-example-agent-card)
15. [Security considerations](#15-security-considerations)
16. [Conformance checklist](#16-conformance-checklist)
17. [Glossary and references](#17-glossary-and-references)

## 1. Purpose and scope

<!-- Guidance: Say what the agent does for other agents, who may call it and what it deliberately does not do. Remote agents are opaque: clients see only the card and the protocol, so the scope written here is what they rely on. -->

[Describe what the agent offers and to whom.] *Example:* The Invoice
Reconciliation Agent matches supplier invoices against purchase orders
and goods receipts for business customers of [Company], and returns a
reconciliation report. It is called by customers' procurement agents and
by our own finance assistant. It does not approve or pay invoices.

| Item | Value |
|---|---|
| Callers | *Example:* Customer procurement agents (external), internal finance assistant |
| Tenancy | *Example:* Multi-tenant; each customer is a tenant |
| Data handled | *Example:* Invoices, purchase orders, supplier names; Confidential |
| Out of scope | *Example:* Payments, supplier onboarding, tax advice |
| Human contact | *Example:* [support address] for interface questions |

## 2. Protocol baseline and governance

<!-- Guidance: Pin the specification you implement and note how you will track changes. A2A uses Major.Minor for the protocol version on the wire; patch numbers do not affect compatibility and should not appear in requests or cards. -->

| Item | Value |
|---|---|
| Specification | Agent2Agent (A2A) Protocol Specification 1.0.1, https://github.com/a2aproject/A2A/blob/v1.0.1/docs/specification.md (current version: https://a2a-protocol.org/latest/specification/) |
| Normative source | `specification/a2a.proto` in https://github.com/a2aproject/A2A (tag v1.0.1, identical to v1.0.0) |
| Protocol version on the wire | `1.0` in `protocolVersion` of each interface and in the `A2A-Version` request header |
| Requests without `A2A-Version` | Treated as version 0.3 by the specification; [reject with `VersionNotSupportedError` / serve 0.3 interface] |
| SDK used | [*Example:* Official A2A SDK for [language], version [x.y.z]] |
| Governance | Linux Foundation project; hosted by the Agentic AI Foundation (AAIF) since August 2026; specification licensed under Apache License 2.0 |
| Change tracking | [*Example:* Watch specification releases; review each minor release within 30 days] |

## 3. Agent identity and metadata

<!-- Guidance: Fill the top-level Agent Card fields. Required fields in 1.0 are name, description, supportedInterfaces, version, capabilities, defaultInputModes, defaultOutputModes and skills. Write the description for a calling model: what the agent is for and when to use it. -->

| Field | Required | Value | Notes |
|---|---|---|---|
| `name` | Yes | *Example:* Invoice Reconciliation Agent | Human-readable name |
| `description` | Yes | *Example:* Matches supplier invoices to purchase orders and receipts and reports mismatches | Shown to users and models |
| `supportedInterfaces` | Yes | See section 4 | Ordered list; first entry is preferred |
| `provider.organization` | Yes if `provider` given | *Example:* Example Finance Services Ltd | |
| `provider.url` | Yes if `provider` given | *Example:* `https://www.example.com` | |
| `version` | Yes | *Example:* 1.0.0 | Version of this agent, not of A2A |
| `documentationUrl` | No | *Example:* `https://docs.example.com/agents/invoice-recon` | |
| `iconUrl` | No | *Example:* `https://agent.example.com/icon.png` | |
| `capabilities` | Yes | See section 5 | |
| `securitySchemes` | No | See section 7 | Map of scheme name to scheme |
| `securityRequirements` | No | See section 7 | Requirements for the whole agent |
| `defaultInputModes` | Yes | *Example:* `application/json`, `text/plain`, `application/pdf` | Media types accepted |
| `defaultOutputModes` | Yes | *Example:* `application/json`, `text/plain` | Media types returned |
| `skills` | Yes | See section 6 | At least one skill |
| `signatures` | No | See section 13.3 | JWS signatures over the card |

## 4. Interfaces and protocol bindings

<!-- Guidance: List each endpoint as an entry of supportedInterfaces with its URL, protocolBinding and protocolVersion. Core binding values are JSONRPC, GRPC and HTTP+JSON; a custom binding is identified by a URI. Use HTTPS (TLS) in production. -->

| # | `url` | `protocolBinding` | `protocolVersion` | `tenant` | Notes |
|---|---|---|---|---|---|
| 1 | *Example:* `https://agent.example.com/a2a/v1` | `JSONRPC` | `1.0` | [Not used / tenant ID] | Preferred |
| 2 | *Example:* `https://agent.example.com/a2a/rest` | `HTTP+JSON` | `1.0` | | REST style, media type `application/a2a+json` |
| 3 | *Example:* `https://grpc.agent.example.com` | `GRPC` | `1.0` | | Internal callers only |

Binding notes to verify:

- **JSON-RPC:** JSON-RPC 2.0 over HTTP; method names equal the operation
  names (for example `SendMessage`); streaming uses Server-Sent Events
  (`text/event-stream`).
- **HTTP+JSON:** resource-style paths such as `POST /message:send` and
  `GET /tasks/{id}`; streaming uses Server-Sent Events.
- **gRPC:** service `A2AService` in package `lf.a2a.v1`; streaming uses
  server-streaming RPCs.
- **Tenant:** when `tenant` is set on an interface, requests carry the
  same opaque value; do not use it as the only isolation control.

## 5. Capabilities and extensions

<!-- Guidance: Declare only what you implement. A client that sees streaming: true will call streaming operations, and you must not answer them with an error. -->

| Field | Value | Notes |
|---|---|---|
| `capabilities.streaming` | *Example:* true | `SendStreamingMessage` and `SubscribeToTask` supported |
| `capabilities.pushNotifications` | *Example:* true | Push notification config operations supported (section 11) |
| `capabilities.extendedAgentCard` | *Example:* true | Authenticated callers can fetch a richer card |
| `capabilities.extensions` | *Example:* one entry | See table below |

| Extension `uri` | `description` | `required` | `params` |
|---|---|---|---|
| *Example:* `https://example.com/a2a/extensions/cost-estimate/v1` | Returns an estimated processing cost before work starts | false | `{"currency": "EUR"}` |

Clients activate extensions per request with the `A2A-Extensions` header
(a comma-separated list of extension URIs). If an extension is marked
`required: true`, clients that do not support it receive
`ExtensionSupportRequiredError`.

## 6. Skills

<!-- Guidance: One entry per distinct thing the agent can do. id, name, description and tags are required. Give examples a calling model can imitate, and narrow inputModes and outputModes where a skill differs from the defaults. Pitfall: one vague skill called "assistant" that tells callers nothing. -->

| `id` | `name` | `description` | `tags` | `inputModes` | `outputModes` | Skill `securityRequirements` |
|---|---|---|---|---|---|---|
| `reconcile-invoice` *(Example)* | Reconcile invoice | Matches one invoice to its purchase order and receipts; returns matched lines and mismatches | invoice, reconciliation, procurement | `application/pdf`, `application/json` | `application/json` | `oauth`: `invoices:reconcile` |
| `explain-mismatch` *(Example)* | Explain mismatch | Explains in plain language why a line did not match | invoice, explanation | `application/json`, `text/plain` | `text/plain` | `oauth`: `invoices:read` |
| `batch-reconcile` *(Example)* | Batch reconciliation | Reconciles up to 500 invoices for a period and returns a report artifact | batch, report | `application/json` | `application/json`, `text/csv` | `oauth`: `invoices:reconcile` |

Skill examples (the `examples` field):

- `reconcile-invoice`: *Example:* "Reconcile invoice INV-2026-0042 from
  Example Office Supplies against PO-77120."
- `explain-mismatch`: *Example:* "Why did line 3 of INV-2026-0042 not
  match?"
- `batch-reconcile`: *Example:* "Reconcile all invoices received in
  September 2026 for supplier SUP-0193."

## 7. Security schemes and authentication

<!-- Guidance: Declare every scheme in securitySchemes and state which are required in securityRequirements, for the agent and per skill. Supported scheme types in 1.0 are API key, HTTP authentication, OAuth 2.0, OpenID Connect and mutual TLS. Implicit and password OAuth flows are deprecated; use authorization code (with PKCE), client credentials or device code. Credentials are never sent inside A2A messages. -->

| Scheme name | Type (JSON key) | Key settings | Used for |
|---|---|---|---|
| `oauth` *(Example)* | `oauth2SecurityScheme` | `flows.clientCredentials` with `tokenUrl` and `scopes`; `oauth2MetadataUrl` set | Agent-to-agent calls |
| `oidc` *(Example)* | `openIdConnectSecurityScheme` | `openIdConnectUrl` | Calls on behalf of a signed-in user |
| `mtls` *(Example)* | `mtlsSecurityScheme` | Client certificate issued by [CA] | Internal gRPC callers |

| Scope | Grants |
|---|---|
| `invoices:read` *(Example)* | Read reconciliation results for the caller's tenant |
| `invoices:reconcile` *(Example)* | Start reconciliation tasks for the caller's tenant |

Authentication rules:

- [*Example:* Access tokens must have this agent as audience and a
  lifetime of 15 minutes or less.]
- [*Example:* The tenant is derived from the token, never from message
  content.]
- [*Example:* `GetExtendedAgentCard` requires a valid token from a scheme
  in the public card; it returns the `batch-reconcile` skill only to
  callers with `invoices:reconcile`.]
- [*Example:* When a task needs a credential the caller has not supplied,
  the task moves to `TASK_STATE_AUTH_REQUIRED` with a message explaining
  what is needed; the credential itself is obtained out of band.]

## 8. Supported operations

<!-- Guidance: Mark each core operation as supported or not and note limits. Operations tied to an undeclared capability must return the matching error, for example PushNotificationNotSupportedError. -->

| Operation (JSON-RPC method) | HTTP+JSON | Supported | Limits and notes |
|---|---|---|---|
| `SendMessage` | `POST /message:send` | *Example:* Yes | Blocking by default; `returnImmediately: true` returns at once |
| `SendStreamingMessage` | `POST /message:stream` | *Example:* Yes | Stream closes at a terminal state |
| `GetTask` | `GET /tasks/{id}` | *Example:* Yes | `historyLength` honoured, maximum 50 |
| `ListTasks` | `GET /tasks` | *Example:* Yes | Cursor pagination; only the caller's tasks |
| `CancelTask` | `POST /tasks/{id}:cancel` | *Example:* Yes | Batch tasks cancel between invoices |
| `SubscribeToTask` | `GET /tasks/{id}:subscribe` | *Example:* Yes | First event is the current Task |
| `CreateTaskPushNotificationConfig` | `POST /tasks/{taskId}/pushNotificationConfigs` | *Example:* Yes | Maximum 3 configs per task |
| `GetTaskPushNotificationConfig` | `GET /tasks/{taskId}/pushNotificationConfigs/{id}` | *Example:* Yes | |
| `ListTaskPushNotificationConfigs` | `GET /tasks/{taskId}/pushNotificationConfigs` | *Example:* Yes | |
| `DeleteTaskPushNotificationConfig` | `DELETE /tasks/{taskId}/pushNotificationConfigs/{id}` | *Example:* Yes | |
| `GetExtendedAgentCard` | `GET /extendedAgentCard` | *Example:* Yes | Authentication required |

Each HTTP+JSON path also has a tenant-prefixed form (for example `/{tenant}/message:send` in
the specification's path templates) when an interface uses `tenant`.

### 8.1 Example request (JSON-RPC)

A client starts a reconciliation with a structured data part:

```json
{
  "jsonrpc": "2.0",
  "id": "req-7",
  "method": "SendMessage",
  "params": {
    "message": {
      "messageId": "9f1c2e7a-4b1d-4c55-9a43-1d0f8e2b6c10",
      "role": "ROLE_USER",
      "parts": [
        {"text": "Reconcile this invoice against its purchase order."},
        {"data": {"invoiceId": "INV-2026-0042", "purchaseOrderId": "PO-77120"}, "mediaType": "application/json"}
      ]
    },
    "configuration": {"acceptedOutputModes": ["application/json"], "returnImmediately": true}
  }
}
```

## 9. Task lifecycle and states

<!-- Guidance: Describe how your agent moves tasks through states and what the client must do in each. Terminal states accept no further messages. Interrupted states wait for the client. Decide when you answer with a direct Message instead of creating a Task. -->

| State | Kind | When this agent uses it | Client action |
|---|---|---|---|
| `TASK_STATE_SUBMITTED` | Active | *Example:* Task accepted and queued | Wait, poll, stream or await push |
| `TASK_STATE_WORKING` | Active | *Example:* Matching in progress | Same |
| `TASK_STATE_INPUT_REQUIRED` | Interrupted | *Example:* PO number missing or ambiguous | Send a message with the same `taskId` |
| `TASK_STATE_AUTH_REQUIRED` | Interrupted | *Example:* Caller lacks a scope needed for a linked ERP lookup | Obtain authorization out of band, then continue |
| `TASK_STATE_COMPLETED` | Terminal | *Example:* Report artifact produced | Read artifacts |
| `TASK_STATE_FAILED` | Terminal | *Example:* Unrecoverable processing error | Read status message; may retry with a new task |
| `TASK_STATE_CANCELED` | Terminal | *Example:* Caller cancelled | None |
| `TASK_STATE_REJECTED` | Terminal | *Example:* Request outside scope or policy | Read reason; do not retry unchanged |

```mermaid
stateDiagram-v2
  [*] --> SUBMITTED
  SUBMITTED --> WORKING
  SUBMITTED --> REJECTED
  WORKING --> INPUT_REQUIRED
  INPUT_REQUIRED --> WORKING: client sends message
  WORKING --> AUTH_REQUIRED
  AUTH_REQUIRED --> WORKING: authorization obtained
  WORKING --> COMPLETED
  WORKING --> FAILED
  WORKING --> CANCELED: CancelTask
  WORKING --> REJECTED
  COMPLETED --> [*]
  FAILED --> [*]
  CANCELED --> [*]
  REJECTED --> [*]
```

The diagram drops the `TASK_STATE_` prefix for readability. Direct
`Message` replies (no task) are used for: [*Example:* `explain-mismatch`
answers under 2 seconds]. Related tasks share a `contextId`; a follow-up
may list earlier tasks in `referenceTaskIds`.

## 10. Messages, parts and artifacts

<!-- Guidance: Define what content you accept and return. Each Part carries exactly one of text, raw (bytes, base64 in JSON), url or data (any JSON value), with optional mediaType, filename and metadata. Artifacts are outputs with an artifactId and parts. Validate media types against your declared modes. -->

### 10.1 Accepted input parts

| Content | Part field | `mediaType` | Limits | Validation |
|---|---|---|---|---|
| Instructions *(Example)* | `text` | `text/plain` | 4,000 characters | Treated as data for the agent's model, not as system instructions |
| Invoice reference *(Example)* | `data` | `application/json` | Schema `ReconcileRequest` v1 | JSON Schema, unknown fields rejected |
| Invoice file *(Example)* | `raw` | `application/pdf` | 10 MB | Type sniffing, malware scan |
| Invoice file link *(Example)* | `url` | `application/pdf` | HTTPS only | Allow-listed hosts; SSRF checks |

### 10.2 Artifacts returned

| `name` | Parts | Description | Streaming |
|---|---|---|---|
| `reconciliation-report` *(Example)* | `data` (`application/json`) | Matched lines, mismatches, totals | Sent once at completion |
| `batch-report` *(Example)* | `data` (`application/json`) plus `raw` (`text/csv`) | Batch results | Chunks with `append` and `lastChunk` on `TaskArtifactUpdateEvent` |

Artifact and message `extensions` lists name any extension URIs that
contributed content. Do not place secrets or other tenants' data in
`metadata`.

## 11. Streaming and push notifications

<!-- Guidance: Describe how clients receive updates. Streams begin with the Task, then status and artifact events, and close at a terminal state. Push notifications POST the same StreamResponse shape to a client webhook. Treat webhook URLs from clients as hostile until validated. -->

| Aspect | Design |
|---|---|
| Streaming events | `task`, `statusUpdate` (`TaskStatusUpdateEvent`), `artifactUpdate` (`TaskArtifactUpdateEvent`), or `message` for direct replies |
| Resubscription | `SubscribeToTask` on any non-terminal task; first event is the current Task |
| Push config fields | `url` (required), `id`, `taskId`, `token`, `authentication` (`scheme`, `credentials`) |
| Push delivery | *Example:* At least once; 15 s timeout; exponential backoff for 1 h; stop after 10 consecutive failures |
| Webhook validation | *Example:* HTTPS only; reject private, loopback and link-local addresses after DNS resolution; per-tenant allow-list of domains |
| Webhook authentication | *Example:* Bearer token from `authentication.credentials`, plus the per-config `token` echoed for the receiver to check |
| Client duties (to document for callers) | Return HTTP 2xx, process idempotently, check the task ID, verify the sender |

## 12. Error handling

<!-- Guidance: Use the A2A error types and their binding mappings so clients can react programmatically. Give actionable messages without internal details. -->

| A2A error | JSON-RPC code | HTTP | gRPC | When this agent returns it |
|---|---|---|---|---|
| `TaskNotFoundError` | -32001 | 404 | `NOT_FOUND` | *Example:* Unknown task or task of another tenant |
| `TaskNotCancelableError` | -32002 | 400 | `FAILED_PRECONDITION` | *Example:* Task already terminal |
| `PushNotificationNotSupportedError` | -32003 | 400 | `FAILED_PRECONDITION` | Only if `pushNotifications` is false |
| `UnsupportedOperationError` | -32004 | 400 | `FAILED_PRECONDITION` | *Example:* Message sent to a terminal task |
| `ContentTypeNotSupportedError` | -32005 | 400 | `INVALID_ARGUMENT` | *Example:* Part media type not accepted by the skill |
| `InvalidAgentResponseError` | -32006 | 500 | `INTERNAL` | *Example:* Agent produced a response that failed validation |
| `ExtendedAgentCardNotConfiguredError` | -32007 | 400 | `FAILED_PRECONDITION` | Only if declared but not configured |
| `ExtensionSupportRequiredError` | -32008 | 400 | `FAILED_PRECONDITION` | Required extension not activated |
| `VersionNotSupportedError` | -32009 | 400 | `FAILED_PRECONDITION` | `A2A-Version` not served on the interface |

Standard JSON-RPC errors (for example -32602 invalid params and -32603
internal error) are used for malformed requests. Map authentication
failures to HTTP 401 and authorization failures to 403 on HTTP bindings.

## 13. Versioning, discovery and caching

<!-- Guidance: Decide how clients find the agent, how you sign and cache the card and how you evolve it. Agent version and protocol version change independently. -->

### 13.1 Discovery

| Method | Detail |
|---|---|
| Well-known URI | `https://[domain]/.well-known/agent-card.json` returns the public card |
| Registry or catalogue | [*Example:* Internal agent registry entry [ID]] |
| Direct configuration | [*Example:* Partners receive the card URL in onboarding] |
| Extended card | `GetExtendedAgentCard` for authenticated callers |

### 13.2 Versioning policy

- Agent `version` follows semantic versioning: removing a skill, an
  interface or an accepted media type, or adding a required security
  requirement, is a major change.
- New protocol versions are added as new `supportedInterfaces` entries
  before old ones are removed; old interfaces stay for [6] months.
- Clients send `A2A-Version: 1.0`; requests for unsupported versions get
  `VersionNotSupportedError`.

### 13.3 Signing and caching

| Aspect | Design |
|---|---|
| Card signature | *Example:* JWS with ES256; protected header includes `alg`, `kid` and `jku`; payload is the card canonicalised with RFC 8785 after removing default-valued fields and the `signatures` field |
| Key publication | *Example:* JWKS at `https://agent.example.com/.well-known/jwks.json`; keys rotated yearly with overlap |
| Cache headers | *Example:* `Cache-Control: max-age=3600`; `ETag` derived from `version` and content hash |
| Client guidance | Honour HTTP caching; revalidate with `If-None-Match`; verify at least one signature before trusting the card |

## 14. Example Agent Card

<!-- Guidance: Publish exactly this shape at the well-known URI, with real values. Validate it against the schema generated from a2a.proto before release. The signature value below is a placeholder. -->

The public card for the worked example, with one interface per binding
and the security scheme wrapped by its type key:

```json
{
  "name": "Invoice Reconciliation Agent",
  "description": "Matches supplier invoices to purchase orders and goods receipts and reports mismatches. Use it when an invoice must be checked before approval.",
  "supportedInterfaces": [
    {"url": "https://agent.example.com/a2a/v1", "protocolBinding": "JSONRPC", "protocolVersion": "1.0"},
    {"url": "https://agent.example.com/a2a/rest", "protocolBinding": "HTTP+JSON", "protocolVersion": "1.0"}
  ],
  "provider": {"organization": "Example Finance Services Ltd", "url": "https://www.example.com"},
  "version": "1.0.0",
  "documentationUrl": "https://docs.example.com/agents/invoice-recon",
  "capabilities": {"streaming": true, "pushNotifications": true, "extendedAgentCard": true},
  "securitySchemes": {
    "oauth": {
      "oauth2SecurityScheme": {
        "description": "Client credentials for partner agents",
        "flows": {
          "clientCredentials": {
            "tokenUrl": "https://auth.example.com/oauth2/token",
            "scopes": {"invoices:read": "Read reconciliation results", "invoices:reconcile": "Start reconciliation tasks"}
          }
        },
        "oauth2MetadataUrl": "https://auth.example.com/.well-known/oauth-authorization-server"
      }
    }
  },
  "securityRequirements": [{"schemes": {"oauth": {"list": ["invoices:read"]}}}],
  "defaultInputModes": ["application/json", "text/plain", "application/pdf"],
  "defaultOutputModes": ["application/json", "text/plain"],
  "skills": [
    {
      "id": "reconcile-invoice",
      "name": "Reconcile invoice",
      "description": "Matches one invoice to its purchase order and receipts and returns matched lines and mismatches.",
      "tags": ["invoice", "reconciliation", "procurement"],
      "examples": ["Reconcile invoice INV-2026-0042 from Example Office Supplies against PO-77120."],
      "inputModes": ["application/pdf", "application/json"],
      "outputModes": ["application/json"],
      "securityRequirements": [{"schemes": {"oauth": {"list": ["invoices:reconcile"]}}}]
    },
    {
      "id": "explain-mismatch",
      "name": "Explain mismatch",
      "description": "Explains in plain language why an invoice line did not match.",
      "tags": ["invoice", "explanation"],
      "examples": ["Why did line 3 of INV-2026-0042 not match?"],
      "inputModes": ["application/json", "text/plain"],
      "outputModes": ["text/plain"]
    }
  ],
  "signatures": [
    {"protected": "[base64url JWS protected header]", "signature": "[base64url signature]"}
  ]
}
```

## 15. Security considerations

<!-- Guidance: Cover the risks specific to exposing an agent: authorization on every operation, tenant isolation, untrusted content, webhooks, card integrity and abuse. Map each to a control and a test. For agentic risk names see the OWASP Top 10 for Agentic Applications 2026, especially ASI07 Insecure Inter-Agent Communication. -->

| ID | Concern | Control | Test |
|---|---|---|---|
| A2A-SEC-001 | Authorization on every operation | Check scope and tenant on each call, before any lookup that could reveal whether another tenant's task exists | Cross-tenant test suite |
| A2A-SEC-002 | Task enumeration | Unguessable task IDs; `ListTasks` scoped to caller; `TaskNotFoundError` for other tenants' tasks | Fuzz task IDs |
| A2A-SEC-003 | Prompt injection through parts | Text and file content passed to the model as data; tools behind the agent follow the [Agent tool and permission design] | Injection fixture set |
| A2A-SEC-004 | SSRF through `url` parts and webhooks | HTTPS only; block private, loopback and link-local ranges after resolution; allow-lists | SSRF test cases |
| A2A-SEC-005 | Card spoofing or tampering | Signed card, HTTPS, key rotation; clients told to pin and verify | Signature verification test |
| A2A-SEC-006 | Sensitive data in the extended card | No internal URLs or credentials in any card | Card review checklist |
| A2A-SEC-007 | Resource exhaustion | Size limits per part, rate limits per client, cap on concurrent tasks per tenant | Load test |
| A2A-SEC-008 | Push credential leakage | Per-config tokens treated as secrets, rotated, unique per config | Secret scanning, review |
| A2A-SEC-009 | Logging of sensitive content | Log IDs, states and sizes, not part contents; mask tokens | Log review |
| A2A-SEC-010 | Transport security | TLS 1.2 or later (prefer 1.3) on every interface | TLS scan |

## 16. Conformance checklist

<!-- Guidance: Check every item before release and keep the evidence link. Items follow the requirements of the 1.0 specification as summarised here; read the specification for the normative wording. -->

| ID | Check | Evidence | Done |
|---|---|---|---|
| A2A-CONF-001 | Card served at `/.well-known/agent-card.json` with all required fields | [Validation output] | [ ] |
| A2A-CONF-002 | Field names and enum values match the 1.0 JSON form exactly | [Schema validation] | [ ] |
| A2A-CONF-003 | Each interface answers with its declared `protocolBinding` and `protocolVersion` | [Integration test] | [ ] |
| A2A-CONF-004 | `A2A-Version` honoured; unsupported versions return `VersionNotSupportedError` | [Test] | [ ] |
| A2A-CONF-005 | Declared capabilities implemented; undeclared ones return the matching error | [Test] | [ ] |
| A2A-CONF-006 | Streams start with the Task and close at a terminal state | [Test] | [ ] |
| A2A-CONF-007 | Messages to terminal tasks return `UnsupportedOperationError` | [Test] | [ ] |
| A2A-CONF-008 | `ListTasks` returns only the caller's tasks, sorted by last update, with `nextPageToken` always present | [Test] | [ ] |
| A2A-CONF-009 | Push notifications delivered at least once with configured authentication | [Test] | [ ] |
| A2A-CONF-010 | `GetExtendedAgentCard` requires authentication | [Test] | [ ] |
| A2A-CONF-011 | Card signature verifies with the published key | [Test] | [ ] |
| A2A-CONF-012 | Cache headers present on the card endpoint | [Test] | [ ] |
| A2A-CONF-013 | Security tests A2A-SEC-001 to A2A-SEC-010 pass | [Report] | [ ] |
| A2A-CONF-014 | Interoperability run with at least [two] independent clients or SDKs | [Report] | [ ] |

## 17. Glossary and references

<!-- Guidance: Define A2A terms for readers new to the protocol, and list the exact versions you implemented. -->

| Term | Meaning |
|---|---|
| A2A client | Application or agent that sends requests to a remote agent |
| A2A server (remote agent) | Agent that exposes an A2A endpoint and processes tasks |
| Agent Card | JSON document describing an agent's identity, interfaces, skills, capabilities and security requirements |
| Task | Stateful unit of work with an ID and a lifecycle |
| Context | Identifier that groups related tasks and messages |
| Part | Smallest unit of content: text, raw bytes, a URL or structured data |
| Artifact | Output of a task, made of parts |
| Protocol binding | Mapping of A2A operations onto a transport: JSON-RPC, gRPC or HTTP+JSON |
| Interrupted state | A non-terminal state waiting for the client: input required or authorization required |

References:

- Agent2Agent (A2A) Protocol Specification 1.0.1, https://github.com/a2aproject/A2A/blob/v1.0.1/docs/specification.md
- A2A specification repository and `a2a.proto`, https://github.com/a2aproject/A2A (release v1.0.0, March 2026; patch v1.0.1, May 2026)
- Agentic AI Foundation announcement of A2A as a hosted project, August 2026, https://aaif.io/blog/a2a-joins-aaif
- OWASP Top 10 for Agentic Applications for 2026, https://genai.owasp.org/resource/owasp-top-10-for-agentic-applications-for-2026/
- RFC 7515 JSON Web Signature; RFC 8785 JSON Canonicalization Scheme; RFC 9111 HTTP Caching

## Standard and licence note

Based on the Agent2Agent (A2A) Protocol Specification 1.0.1 and its
`a2a.proto` definition, published by the A2A project under the Linux
Foundation and licensed under Apache License 2.0
(https://www.apache.org/licenses/LICENSE-2.0). Field, enum, operation and
error names are reproduced exactly so that implementations interoperate;
all explanatory text is original and requirements are summarised rather
than quoted. The OWASP reference in section 15 is a citation only. Check
a2a-protocol.org for the current release and the normative wording
before implementing. Template licence: MIT.
