Agent-to-Agent 协议:用 Agent Card 发现能力,以任务为中心协作。
A2A 是让独立 Agent 互相发现、委派和协作的开放协议。服务方在 /.well-known/agent-card.json 暴露 Agent Card,声明名称、端点、能力、技能、传输方式和认证方案;客户端读取卡片后,通过 JSON-RPC、gRPC 或 HTTP+JSON 绑定发送消息,围绕 task 管理长任务、流式输出和产物。
任务有完整生命周期:TASK_STATE_SUBMITTED、WORKING、COMPLETED、FAILED、CANCELED、REJECTED,以及可恢复的 INPUT_REQUIRED、AUTH_REQUIRED。消息由 parts 组成,产物(artifact)可以分块追加;流式用 SSE,长任务可配置 push notification。
A2A 与 MCP 是互补关系:MCP 是“纵向”的 Agent-to-Tool 协议,把工具和数据源接给一个 Agent;A2A 是“横向”的 Agent-to-Agent 协议,让多个独立 Agent 跨进程、跨组织协作。需要工具就接 MCP,需要委派整个任务再用 A2A。
先发现并校验 Agent Card,生产环境必须使用 HTTPS:
curl -s https://agent.example.com/.well-known/agent-card.json | jq .
最小 Agent Card 需要声明端点、能力和技能;认证方案放在 securitySchemes:
{
"protocolVersion": "1.0",
"name": "order-agent",
"description": "处理订单查询与退款",
"url": "https://agent.example.com/a2a",
"capabilities": {"streaming": true, "pushNotifications": false},
"defaultInputModes": ["text/plain"],
"defaultOutputModes": ["application/json"],
"skills": [{"id": "order-status", "name": "订单查询", "description": "按订单号查询状态", "tags": ["order"]}],
"securitySchemes": {"bearer": {"type": "http", "scheme": "bearer"}},
"security": [{"bearer": []}]
}
用 JSON-RPC 发送消息并创建任务;messageId 要唯一,便于重试去重:
curl -s https://agent.example.com/a2a -H 'Content-Type: application/json' -H 'A2A-Version: 1.0' \
-d '{"jsonrpc":"2.0","id":1,"method":"SendMessage","params":{"message":{"messageId":"msg-1","role":"ROLE_USER","parts":[{"text":"查询订单 123"}]}}}'
按 task id 查询状态和历史:
curl -s https://agent.example.com/a2a -H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":2,"method":"GetTask","params":{"id":"task-1","historyLength":10}}'
取消仍在执行的任务;已完成的任务通常不能再取消:
curl -s https://agent.example.com/a2a -H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":3,"method":"CancelTask","params":{"id":"task-1"}}'
需要增量输出时用流式方法,并关闭 curl 缓冲:
curl -N https://agent.example.com/a2a -H 'Content-Type: application/json' -H 'Accept: text/event-stream' \
-d '{"jsonrpc":"2.0","id":4,"method":"SendStreamingMessage","params":{"message":{"messageId":"msg-2","role":"ROLE_USER","parts":[{"text":"生成报告"}]}}}'
REST 绑定使用 application/a2a+json 和资源式路径:
curl -s https://agent.example.com/message:send -H 'Content-Type: application/a2a+json' \
-d '{"message":{"messageId":"msg-3","role":"ROLE_USER","parts":[{"text":"查询订单 123"}]}}'
curl -s https://agent.example.com/tasks/task-1 -H 'Accept: application/a2a+json'
用 jq 检查卡片关键字段,避免发布缺技能或错误端点的卡片:
jq -e '.name and .url and (.skills | length > 0) and .capabilities' agent-card.json
认证凭据不要写进 Agent Card,客户端通过 Authorization 头单独传递:
curl -s https://agent.example.com/a2a -H "Authorization: Bearer $A2A_TOKEN" \
-H 'Content-Type: application/json' -d @send-message.json
/.well-known/agent.json,新规范是 /.well-known/agent-card.json;客户端要兼容两者或先探测。protocolVersion、传输方式和技能声明不匹配会导致请求被拒;客户端应先读卡片,不要硬编码端点和绑定。GetTask 需要 task id,不是 context id;两者混淆会查不到任务,context 只用于关联同一会话的多条任务。INPUT_REQUIRED 和 AUTH_REQUIRED 是中断态不是终态;客户端补充输入或凭据后要继续同一任务,而不是新建任务。AUTH_REQUIRED。append 和 lastChunk 语义,否则会覆盖前面内容或永远拼不完;按 artifact id 聚合。/.well-known/agent-card.json 获取;关键字段包括 name、description、url、protocolVersion、capabilities、skills、securitySchemes 和 security。COMPLETED、FAILED、CANCELED、REJECTED;INPUT_REQUIRED 和 AUTH_REQUIRED 是中断态,补充输入或凭据后可继续。