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.
Document control
| 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
| 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
1. Purpose and scope
[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
| 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
| 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
| # | 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 |
- 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
| 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
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
| 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 |
- [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
| 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:
{
"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
| 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 |
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
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
| 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
| 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
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
The public card for the worked example, with one interface per binding
and the security scheme wrapped by its type key:
{
"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
| 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
| 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
| 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 |
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.