① 四概念:A2A 的四块积木
MCP 管「调工具」,A2A 管「委派任务」。A2A = 四样东西。
Agent Card
我是谁(能力发现)
→
Task
帮我做件事(异步追踪)
→
Message
执行中说什么(交互)
→
Artifact
做完了,这是结果
核心差异 vs 传统 RPC:任务可以跑 30 分钟,中间可交互(input_required 多轮补充信息)——不是一次同步调用,是带状态机的异步任务。
② Agent Card:端点发现(能力 vs 实例)
Nacos 发现「实例」、Agent Card 发现「能力」——编排者把请求向量化,和各 Card 的 examples 做相似度匹配选 Agent。
GET /.well-known/agent-card.json →
{ "name": "K8s Diagnostic Agent",
"capabilities": { "streaming": true },
"skills": [{ "id": "pod_diagnosis", "name": "Pod 故障诊断",
"examples": ["payment-service Pod 一直重启", "Pod 日志显示 OOMKilled"] }] }
关键认知:skills[].examples 不是给人看的,是给编排 Agent 做语义匹配的。capabilities.streaming 声明决定后续用轮询还是推送——先看能力再选交互方式。
③ Task 状态机
Task 是协议核心——异步、可交互、可取消。
submitted→
working⇄
input_required→
completed/
failed/
canceled
为什么不能同步?
- 子 Agent 可能要跑 30 分钟
- 任务中间可能要问用户补充信息(input_required)
- 同步等待 = 资源锁死 + 超时失控
异步 = 轮询或推送
- 支持 streaming → 订阅 SSE 推送
- 不支持 → 指数退避轮询 GET /tasks/{id}
④ 完整委派时序
从发现到取回产物,一条完整链路。
Orchestrator -->> K8sAgent: GET /.well-known/agent-card.json(发现能力)
K8sAgent -->> Orchestrator: Agent Card(pod_diagnosis 匹配)
Orchestrator -->> K8sAgent: POST /tasks {description, sessionId, context}
K8sAgent -->> Orchestrator: 202 {taskId, state:"submitted"}
K8sAgent -->> Orchestrator: (SSE) state:"working", progress:"60%"
loop 多轮
Orchestrator -->> K8sAgent: GET /tasks/{taskId}
K8sAgent -->> Orchestrator: state:"working"(或 input_required)
end
K8sAgent -->> Orchestrator: state:"completed", artifacts:[{name:"report.md", url:"..."}]
⑤ 生产四坑 + 选型
| 坑 | 根因 | 教训 |
| payload 过大 | Task 报文走 HTTP,默认体积限制 | 大内容走 Artifact 引用(url),Task 只传引用+摘要 |
| 超时设计 | 把 A2A 当同步 RPC 用 | 创建 Task 后轮询/订阅推送,绝不阻塞等待 |
| 轮询 vs 推送 | 不知道对方是否支持 streaming | 先看 capabilities.streaming,支持则订阅 SSE,否则指数退避轮询 |
| 会话隔离缺失 | 没传 sessionId,多用户 Task 串了 | Task 必须携带 sessionId 隔离会话 |
选型:SubAgent vs A2A?同一进程/语言内协作用 SubAgent(共享上下文、直接函数调用);跨进程/跨语言/跨组织用 A2A(协议解耦、能力发现、异步追踪)。MCP 管「调工具」、A2A 管「委派任务」——一个 Agent 用 MCP 接入工具、用 A2A 接入别的 Agent,两者是 Agent 网络的两条腿。