跨 Agent 通信:怎么说话、传什么、何时上协议
一句话定义:多 Agent 的难点不在「多开几个模型」,而在 跨 Agent 通信 ——谁对谁说、说什么格式、同步还是异步、同进程还是跨系统、失败了怎么兜底。
前置阅读:01-多智能体协作、02-多智能体概念体系与学习要点。
配套:同目录 03-LangGraph Supervisor 实战(进程内消息传递落地);跨系统协议见 13-进阶/10-Agent协议与形态前沿。
1. 为什么「通信」要单独成篇
01 / 02 已列出消息传递、黑板、跨系统协议等名词,但工程上真正卡住的是:
| 问题 | 若不解决会怎样 |
|---|---|
| 传自然语言还是结构化字段? | 下游解析失败、字段丢失、难自动化 |
| 共享一整段对话,还是只交产物? | 上下文膨胀、污染、成本爆炸 |
| 同步等回复,还是异步投递? | 延迟不可控,或时序/竞态难排 |
| 同进程状态图,还是跨服务协议? | 选型错位:要么过度工程,要么无法互通 |
| 消息可观测吗? | 协作失败无法复盘 |
一句话: 拓扑决定「谁跟谁连」,通信决定「连上之后怎么协作」。 后者决定可调试性与可扩展性。
单 Agent:大脑内部「想」→ 调 Tool → 写回自己的上下文
多 Agent:大脑 A 「委托 / 交接 / 回报」→ 大脑 B 的上下文(或共享区)
下文的 LLM /ˌel el ˈem/ ( Large Language Model /lɑːdʒ ˈlæŋɡwɪdʒ ˈmɒdl/ ,大语言模型)指推理体;通信层应尽量少依赖「模型自觉遵守约定」,多依赖 schema / 协议校验。
2. 两层范围:进程内 vs 跨系统
先分清你在做哪一层,再选机制——混为一谈最容易过度设计。
| 范围 | 典型形态 | 通信载体 | 何时用 |
|---|---|---|---|
| 进程内 / 同运行时 | 一张图里的多个节点、同一 Crew / GroupChat |
共享状态、内存消息、函数返回值 | 同一产品、同一团队、同一部署单元 |
| 跨进程 / 跨服务 | 独立服务、不同语言/框架、不同组织 | HTTP /ˌeɪtʃ tiː tiː ˈpiː/ ( Hypertext Transfer Protocol /ˈhaɪpəˌtekst ˈtrænsfɜː prəˈtəʊkɒl/ )、队列、 RPC /ˌɑːr piː ˈsiː/ ( Remote Procedure Call /rɪˈməʊt prəˈsiːdʒə kɔːl/ )、标准化 Agent 协议 | 能力分属不同系统、需独立扩缩/鉴权 |
本仓库 03 示例属于 进程内消息传递 (共享 messages + Supervisor 路由)。跨厂商、跨仓库互通则落到 A2A /ˌeɪ tə ˈeɪ/ ( Agent2Agent /ˈeɪdʒənt tə ˈeɪdʒənt/ ,Agent 间通信协议;亦称 Agent-to-Agent)(见 §8)。
flowchart TB
subgraph InProc["进程内协作"]
S[Supervisor] --> W1[Worker A]
S --> W2[Worker B]
W1 & W2 --> ST[(Shared State / messages)]
end
subgraph Cross["跨系统协作"]
C[Client Agent] -->|发现 Agent Card| AC[Remote Agent]
C -->|SendMessage / Task| AC
AC -->|Artifact / Message| C
end
InProc -.->|需要时再升级| Cross
原则: 默认先把进程内通信做对(契约清晰、可观测、有终止); 只有出现「对方不在我进程里 / 不在我框架里」时,再上跨系统协议。
3. 四种通信载体(怎么「连」)
对应 02 §2.2,这里补「怎么选、怎么落地」。
3.1 消息传递( message passing /ˈmesɪdʒ ˈpɑːsɪŋ/ )
Agent 之间显式发消息:自然语言回合,或带 schema 的结构化包。
- 优点 :边界清晰、易审计(每条消息可落日志)、易做黑盒委托。
- 缺点 :若无路由中枢,点对点易成网状;纯自然语言难解析。
- 落地 :AutoGen 对话轮次;LangGraph 把节点输出写成
AIMessage追加进共享列表(见03)。
3.2 共享黑板( blackboard /ˈblækbɔːd/ )
公共区域挂「当前已知事实 / 中间产物」,各角色按规则读写。
- 优点 :汇聚信息自然(研究笔记 → 写作素材);解耦「谁写的」与「谁读的」。
- 缺点 :写权限失控 → 状态污染 ;只增不减 → 状态膨胀 。
- 落地 :共享文档/对象仓库;MetaGPT 式「环境 + 产物文件」;研究流水线的 shared notes。
3.3 共享状态( shared state /ʃeəd steɪt/ )
图式编排里的全局可变状态(路由字段、计数器、产物指针等),比黑板更「程序化」。
- 优点 :类型可约束、与图边条件天然配合;适合生产可控流。
- 缺点 :多写者竞态;把整段对话塞进状态会迅速变贵。
- 落地 :LangGraph
Annotation/StateGraph;关键字段与「对话全文」分离设计。
3.4 任务队列( task queue /tɑːsk kjuː/ )
编排者投递任务,Worker 领取、执行、回写结果。
- 优点 :天然并行、易扩容、失败可重试/进死信。
- 缺点 :要处理幂等、顺序、超时;对「强对话感」协作不直观。
- 落地 :Map-Reduce 式批量子任务;后台 Agent Worker 池。
| 载体 | 耦合度 | 可观测 | 并行 | 典型坑 |
|---|---|---|---|---|
| 消息传递 | 中 | 高(逐条) | 视拓扑 | NL 难解析 |
| 黑板 | 低~中 | 中(看快照) | 高 | 污染 / 膨胀 |
| 共享状态 | 高 | 中(看 diff) | 中 | 竞态、塞太多 |
| 任务队列 | 低 | 高(任务生命周期) | 很高 | 幂等与乱序 |
4. 三条正交轴(怎么「说」)
载体解决「管道」,这三条轴解决「语义与时序」。可任意组合,选型时逐条拍板。
4.1 同步 vs 异步
| 同步 | 异步 | |
|---|---|---|
| 行为 | 发完等结果再继续 | 投递后继续干别的,结果回调/轮询 |
| 适合 | 强依赖链、要立刻决策下一步 | 长耗时工具、可并行子任务 |
| 风险 | 尾延迟叠加、易「全员空等」 | 时序乱、需关联 taskId / 相关 ID |
进程内 Supervisor 循环多是 逻辑同步 (等 Worker 写回再路由);跨服务常用 异步 Task (提交 → 轮询/订阅状态)。
4.2 黑盒 vs 白盒
| 黑盒协作 | 白盒协作 | |
|---|---|---|
| 可见内容 | 只看对方最终输出 / 约定字段 | 共享中间推理、工具轨迹、草稿 |
| 适合 | 权限隔离、降噪、跨信任域 | 调试、联合评审、需溯源 |
| 风险 | 难解释「为什么错」 | 上下文污染、泄密、token 暴涨 |
生产默认: 黑盒交接 + 结构化产物; 调试期或同信任域评审可临时开白盒轨迹。
4.3 自然语言 vs 结构化
| 自然语言通信 | 结构化通信 | |
|---|---|---|
| 形态 | 对话回合、自由文本 | JSON /ˈdʒeɪsən/ ( JavaScript Object Notation /ˌdʒɑːvəskrɪpt ɒbˈdʒekt nəʊˈteɪʃn/ )/ Schema / 协议 Part |
| 适合 | 探索性辩论、人对齐 | 生产编排、自动路由、校验与重试 |
| 风险 | 丢字段、歧义、难测 | 契约过刚、演进要版本化 |
口诀: 人对人用自然语言;Agent 对 Agent 的「合同」用结构化。 自然语言可以包在某个文本字段里,但信封(谁、任务 ID、状态、产物类型)必须结构化。
5. 交接模式( handoff /ˈhændɒf/ ):谁发起、传什么
「通信」在运行时往往落成几种固定交接形状。
5.1 中枢转发( Hub relay /hʌb rɪˈleɪ/ )
Worker 不直接互聊 ;都写回共享通道,由 Supervisor 读全量(或摘要)再派下一个。
User → Supervisor → WorkerA →(写回 messages)→ Supervisor → WorkerB → … → FINISH
- 本仓库
03就是此模式。 - 优点 :路由集中、终止好控、审计简单。
- 缺点 :中枢成瓶颈;共享
messages若不做摘要会膨胀。
5.2 直接对等( peer-to-peer /ˌpɪə tə ˈpɪə/ )
Agent 知道彼此地址/名字,点对点发消息(网状拓扑)。
- 优点 :灵活协商、少一层转发。
- 缺点 :路由与终止难;易死锁/无限互怼;生产少作为默认。
5.3 把 Agent 当 Tool( Agent-as-Tool /ˈeɪdʒənt əz tuːl/ )
上层把下游 Agent 封装成一次函数调用:call_research_agent(query) → report。
- 优点 :心智模型简单;与单 Agent + Tools 平滑过渡(见
01§7)。 - 缺点 :默认同步;下游若再拆多 Agent,延迟与成本要预算。
5.4 产物交接( artifact handoff /ˈɑːtɪfækt ˈhændɒf/ )
不传「整段思维链」,只传约定产物:文件路径、结构化报告、检索命中 ID 列表等。
- 优点 :抗污染、易版本化、易给人在环审核。
- 缺点 :要先定义产物 schema 与存储位置。
推荐默认组合:
Hub relay + 结构化信封 + 黑盒产物交接 ;辩论/探索阶段再局部放开自然语言白盒。
6. 消息契约:建议最小字段集
无论自研还是套框架,建议每条跨 Agent 消息(或任务)至少能回答:谁、为啥、传什么、怎么收尾。
{
"message_id": "uuid",
"trace_id": "同一用户请求贯穿全程",
"from": "supervisor",
"to": "researcher",
"intent": "research",
"payload": {
"goal": "……",
"constraints": ["不超过 5 条来源", "中文输出"],
"inputs": { "query": "……", "context_refs": ["doc:12"] }
},
"expect": {
"schema": "ResearchReportV1",
"deadline_ms": 30000
},
"reply_to": "supervisor",
"correlation_id": "parent-task-id"
}
| 字段族 | 作用 |
|---|---|
message_id / trace_id |
去重、幂等、全链路追踪 |
from / to / reply_to |
路由与回报 |
intent |
接收方选策略 / 选工具,避免纯靠读长文猜意图 |
payload |
任务输入;尽量引用 ID,少贴大段原文 |
expect.schema |
产出合同;便于校验与自动重试 |
deadline / 超时策略 |
防死等(见失败模式) |
通信压缩 :长历史先摘要或只传 context_refs,再让接收方按需拉取——这是防膨胀的第一刀。
7. 主流框架里「通信」分别长什么样
| 框架 | 通信长什么样 | 结构化程度 | 备注 |
|---|---|---|---|
| LangGraph | 节点读写共享 State;边/条件边路由 | 高(状态 schema) | 生产可控;本仓库 03 |
| AutoGen | GroupChat 轮流自然语言发言 |
低~中 | 原型快;生产常改显式路由 |
| CrewAI | Task 结果沿 Process 传递(sequential / hierarchical) | 中 | 角色流水线清晰 |
| MetaGPT | 消息总线 + 产物文件 + SOP /ˌes əʊ ˈpiː/ ( Standard Operating Procedure /ˈstændəd ˈɒpəreɪtɪŋ prəˈsiːdʒə/ ) | 中高 | 软件公司式协作 |
对照学习时抓住一句:
框架差异首先是 通信与状态模型 的差异,其次才是「有几个角色模板」。
8. 跨系统标准:A2A(Agent 连 Agent)
8.1 先回答:A2A 是不是「Agent 通信标准协议」?
是。 A2A 是一套 开放标准协议 :约定不同厂商、不同框架写成的 Agent,如何互相 发现能力、委托任务、交换结果 。
把它想成:
| 层级 | 标准在管什么 | 类比 |
|---|---|---|
| MCP /ˌem siː ˈpiː/ ( Model Context Protocol /ˈmɒdl ˈkɒntekst ˈprəʊtəkɒl/ ) | Agent 怎么连 工具 / 数据 | 电脑插外设的 USB-C |
| A2A | Agent 怎么连 另一个 Agent | 公司之间下工单的「统一工单格式」 |
注意边界:
- A2A 管的是 跨系统 / 跨组织 的互操作合同,不是 LangGraph 进程内两个节点怎么共享
messages(那是 §3–§5)。 - 它规定的是 怎么发现、怎么发消息、任务状态怎么走 ,并不规定对方内部用不用 ReAct、用哪个模型。
- 生态仍在演进;落地前以 a2a-protocol.org 为准。
当对方是 另一个服务里的 Agent 时,若每人私定一套 JSON,会重演「工具集成 M×N」——A2A 就是来消掉这种点对点定制的。
8.2 例子:你们是 OTA,对外暴露「卖机票」能力
更贴业务的站位:你们公司是 OTA /ˌəʊ tiː ˈeɪ/ ( Online Travel Agency /ˈɒnlaɪn ˈtrævl ˈeɪdʒənsi/ ,在线旅行社),自己有搜票、验价、占座、出票等能力。问题变成——
外部 Agent(企业差旅助手、银行 App 助手、别家超级助手……)怎么接到我们卖机票的能力?
答案分两层:
| 调用方是什么 | 你们通常暴露什么 | 要不要 A2A |
|---|---|---|
| 传统业务系统 / 移动 App / 开放平台合作方 | 已有 B2B/开放 REST /rest/ ( Representational State Transfer /ˌreprɪzenˈteɪʃənl steɪt ˈtrænsfɜː/ ,表述性状态转移)订票接口 | 不必 为了 A2A 而 A2A |
| 另一个 Agent(要发现能力、多轮澄清、异步长任务) | 在既有订票能力外包一层 A2A Server | 值得考虑 |
A2A 不是取代你们的订票中台,而是给「Agent 调用方」多开一扇 标准工单门 :门后面还是你们原来的运价、库存、支付与风控。
角色怎么摆
| 角色 | 谁 | 协议身份 |
|---|---|---|
| 外部助手 | 合作方的差旅/出行 Agent | A2A Client (来下工单的) |
| 你们的订票 Agent | 封装 OTA 卖机票能力的服务 | A2A Server (接工单的) |
| 你们内部系统 | 运价引擎、库存、支付、风控…… | MCP 工具或既有 RPC (不直接暴露给外部 Agent) |
外部 Agent ──A2A──► 你们「订票 Agent」 ──MCP/内部接口──► 搜票/验价/出票中台
(Client) (Server + Agent Card) (核心交易能力,黑盒)
没有 A2A 时(每个 Agent 合作方一套私对接)
差旅助手A ──私有字段/回调──► 你们开放平台
银行助手B ──另一套封装────► 你们开放平台
超级助手C ──第三套 SDK───► 你们开放平台
开放平台 API 仍有价值;痛点是:每个「Agent 产品」都要重新理解你们的同步/异步、验价占座流程、错误码 ,集成成本随 Agent 合作方数量线性涨。
有 A2A 时(Agent 合作方走同一套发现与委托)
sequenceDiagram
participant U as 终端用户
participant Trip as 外部差旅助手<br/>A2A Client
participant Card as 你们 OTA<br/>Agent Card
participant Fly as 你们订票 Agent<br/>A2A Server
participant Core as 搜票/出票中台
U->>Trip: 下周三上海→北京,直飞优先
Trip->>Card: GET /.well-known/agent-card
Card-->>Trip: 名片:我会搜票/占座/出票、鉴权方式、接口在哪
Trip->>Fly: SendMessage(结构化委托)
Fly-->>Trip: 返回 Task(submitted → working)
Fly->>Core: 内部调搜票/验价(MCP 或 RPC)
Core-->>Fly: 候选航班
Fly-->>Trip: Task completed + Artifact(航班方案)
Trip-->>U: 汇总成一句人话 + 待确认选项
U->>Trip: 订第一班
Trip->>Fly: 同一 Task 或新 Message:确认出票
Fly->>Core: 占座/支付/出票
Fly-->>Trip: Artifact(票号/行程单)
分步对应到协议对象(站在 OTA 服务方 看):
发布名片(Agent Card)——你们要交付的第一件东西
在约定地址挂出:「我是某某 OTA Flight Agent;skills 含search_flights/book_flight;要带合作方 Token;接口 URL……」。
→ 外部 Agent 先发现你会什么 ,再决定要不要委托,而不是先读一本私有对接文档硬编码。接工单(Message → Task)
外部助手发来一条标准消息(示意,非完整报文):
{
"role": "user",
"parts": [
{
"type": "text",
"text": "2026-08-12 上海虹桥→北京首都,直飞优先,经济舱,预算 1500 元内,返回 2 个方案供确认"
}
]
}
你们的订票 Agent 创建 Task (有 ID、状态:已提交 → 进行中 → 完成/失败/取消)。验价锁价、出票等长耗时可异步推进,Client 轮询或订阅即可。
黑盒执行(核心交易不外泄)
Agent 内部 再调搜票、运价、支付、风控——可用 MCP 包一层工具,或直接打现有中台。
对外部助手不可见。A2A 坚持 opaque execution /əˈpeɪk ˌeksɪˈkjuːʃn/ (不透明执行):对方只看约定 skills 与产物,看不到你们库存策略与私有工具。交回产物(Artifact)
Task 完成时返回结构化结果(示意):
{
"name": "flight_options",
"parts": [
{
"type": "data",
"data": {
"options": [
{ "flight": "MU5137", "depart": "08:00", "price_cny": 1280 },
{ "flight": "CA1501", "depart": "12:30", "price_cny": 1410 }
]
}
}
]
}
用户确认后,外部助手再发「订第一班」;你们走占座/出票,再回票号 Artifact。多轮澄清(改日期、要行李额)也落在同一套 Message/Task 模型里,而不是另开一套回调协议。
OTA 落地时常见选型(避免用错层)
| 场景 | 建议 |
|---|---|
| App/H5/开放平台合作方继续下单 | 保持现有 REST/开放平台 ,不必强行改成 A2A |
| 要让「别家的 Agent」稳定调用卖机票能力 | 在中台外包 订票 A2A Server + 发布 Agent Card |
| 你们自己 App 里的客服 Agent 调自家搜票 | 进程内编排或内部 RPC 即可,不必绕一圈公网 A2A |
| 订票 Agent 内部接支付、风控、航班动态 | MCP 或内部服务 ,不要把中台接口直接当 A2A 暴露 |
和本仓库 03 示例的差别
03 LangGraph Supervisor |
本例(OTA + A2A) | |
|---|---|---|
| 工人在哪 | 同一进程、同一张图里的节点 | 对外可发现的订票 Agent 服务 |
| 怎么说话 | 写共享 messages 状态 |
标准 Card + Message + Task + Artifact |
| 要不要 A2A | 不用 | 仅当调用方是 外部 Agent 时值得上 |
一句话: 你们已有的「卖机票中台」继续当发动机;A2A 是给外部 Agent 用的标准方向盘与工单格式。
8.3 与 MCP 的分工
| MCP | A2A | |
|---|---|---|
| 连什么 | Agent ↔ 工具 / 数据源 | Agent ↔ Agent |
| 类比 | AI 应用的「USB-C」接外围能力 | Agent 之间的「统一工单 / 业务委托协议」 |
| 典型对象 | Tools / Resources / Prompts | Agent Card / Task / Message / Artifact |
| OTA 落点 | 订票 Agent 对内 调搜票/支付/风控 | 外部助手 对外 委托你们订票 Agent |
二者互补,不是二选一:对外 A2A Server,对内 MCP(或原中台 RPC)。
8.4 核心对象(概念级)
以官方数据模型为准(细节随版本演进,实现前查 规范):
| 对象 | 作用 | 在 §8.2 OTA 例子里 |
|---|---|---|
| Agent Card | 远端发布的能力名片:身份、skills、接口、鉴权 | 你们挂出的「我会搜票/出票」 |
| Task | 有生命周期的工作单元(可查询、可取消、可订阅) | 一笔「上海→北京出方案/出票」工单 |
| Message | 一轮交互:role + 多个 Part |
外部助手的委托、用户确认「订第一班」 |
| Part | 最小内容块:文本 / 文件引用 / 结构化数据等 | 一段说明,或一段航班 JSON |
| Artifact | 任务产出物(由 Parts 组成) | flight_options / 票号行程单 |
常见操作心智:发现 Card → SendMessage / 流式发送 → 用 Task 状态跟踪 → 取 Artifact。
8.5 何时上 A2A,何时别上
值得上 :
- 要把卖机票能力开放给 外部 Agent 生态(如 §8.2),需要标准发现与鉴权。
- 希望换框架不换协作合同。
- 任务长、需异步状态机(验价锁价 / 待支付 / 出票 / 取消)。
先别上 :
- 调用方不是 Agent,只是 App 或传统 B2B——继续开放平台 REST。
- 仍在同一进程、同一 LangGraph/Crew 里就能闭环(用 §3–§5 即可)。
- 只有两个内部服务且契约极稳——可先用内部 RPC + 自研 schema,待生态成熟再映射到 A2A。
03 文末 P3「跨进程 A2A」指的就是:Worker 不再是图内节点,而是可独立部署的 A2A Server;对 OTA 而言,常常是「对外的订票 Agent」这一层。
8.6 普通 Agent 怎么「加上」A2A?
核心心态: A2A 是外壳(协议适配层),不是重写大脑。
你现有的 LangGraph / 自研 ReAct / 订票工作流 原样保留 ;外面再包一层「会讲 A2A」的 HTTP 服务。
┌─────────────────────────────────────────────┐
│ A2A 外壳(新增) │
│ · 发布 Agent Card │
│ · 实现 SendMessage / Task 状态机 │
│ · 鉴权、HTTPS、可选流式 │
└─────────────────┬───────────────────────────┘
│ 把 Message.parts 转成你原来的输入
▼
┌─────────────────────────────────────────────┐
│ 原来的普通 Agent(不动或只加适配函数) │
│ · 推理循环 / 图 / 业务工作流 │
│ · 对内继续 MCP / 中台 RPC │
└─────────────────────────────────────────────┘
先分清你要加的是哪一侧:
| 目标 | 你变成 | 做什么 |
|---|---|---|
| 让别人来调你 | A2A Server | 挂 Card + 接 SendMessage + 跑原 Agent + 回 Artifact |
| 让你去调别人 | A2A Client | 拉对方 Card + sendMessage + 等 Task/Artifact |
OTA 卖机票对外:主要做 Server 。你们自己的超级助手还要调酒店/保险 Agent:再兼 Client 。
做成 A2A Server 的五步(最常见)
写清 Agent Card(名片)
名称、描述、skills(如search_flights/book_flight)、对外 URL、输入输出 MIME、鉴权方式。
约定路径常见为/.well-known/agent-card(或以当前规范为准)。实现「执行器适配」
官方 SDK 里通常叫AgentExecutor(名随语言/SDK 而变):- 入:A2A 的
RequestContext(里面有用户 Message、taskId…) - 做:抽出文本/结构化 Part → 调用 你原来的
runAgent(input)/graph.invoke(...) - 出:通过事件总线发布 Task 状态(
submitted→working→completed/failed)和 Artifact
- 入:A2A 的
挂上传输层
A2A 跑在常见 Web 栈上( JSON-RPC /ˌdʒeɪsən ˈɑːr piː ˈsiː/ 、HTTP+JSON、可选 gRPC)。
Node 侧可用官方@a2a-js/sdk;Python 等亦有对应 SDK。用 Express/FastAPI 把 Card 与sendMessage路由挂出去即可。接鉴权与网络安全
Card 里声明securitySchemes;生产走 HTTPS + 合作方 Token / OIDC。
不要把未鉴权的订票 Agent 暴露到公网。发布与联调
部署服务 → 用 A2A Client(或 Inspector)拉 Card → 发一条试探 Message → 核对 Task/Artifact。
联调通过后再给合作方 Agent 基址。
示意(TypeScript 骨架,突出「调用原 Agent」,非完整可运行工程):
// 伪代码:外壳适配,大脑仍是你原来的 agent
class FlightAgentExecutor /* implements AgentExecutor */ {
async execute(ctx, eventBus) {
const text = extractText(ctx.userMessage); // 从 A2A Message.parts 取出
eventBus.publish({ state: "working", taskId: ctx.taskId });
// ★ 关键:调用已有普通 Agent / 工作流,而不是在这里重写业务
const result = await myExistingFlightAgent.run(text);
eventBus.publish({
kind: "artifact",
name: "flight_options",
parts: [{ kind: "data", data: result }],
});
eventBus.publish({ state: "completed", taskId: ctx.taskId });
eventBus.finished();
}
}
// 另:挂 Agent Card + DefaultRequestHandler + Express 路由
// app.get('/.well-known/agent-card', ...)
// app.post('/a2a/...', sendMessageHandler)
做成 A2A Client 的三步(去调别人)
- 拿到对方基址 →
GETAgent Card,确认 skills 与鉴权。 - 用 SDK 的 Client(如
ClientFactory.createFromUrl)发sendMessage。 - 同步等结果,或按 Task 状态轮询/订阅流式事件,把 Artifact 接回你自己的编排。
// 伪代码:普通编排里多一步「标准委托」
const client = await factory.createFromUrl("https://partner.example/flight-agent");
const task = await client.sendMessage({
message: {
role: "user",
parts: [{ kind: "text", text: "上海→北京 下周三 直飞 两方案" }],
},
});
// 再根据 task / artifacts 继续你的 Supervisor 逻辑
和「把 Agent 包成 Tool」有何不同?
| 做法 | 形态 | 局限 |
|---|---|---|
| Agent-as-Tool | 下游被压成一次函数调用 | 难做多轮澄清、长任务、标准发现 |
| A2A 外壳 | 下游仍是完整 Agent(Task 生命周期) | 多一层服务运维,但互操作标准 |
官方也强调:别把 Agent 只当 Tool 封一层就完事;要协作就用 A2A 让它以 Agent 身份 被发现和委托。
落地检查清单
- 原 Agent 已有稳定入参/出参(方便适配,不必对外暴露内部 trace)
- Card 上的 skills 与真实能力一致,示例问法写清楚
- Task 状态会推进,失败有
failed+ 可读原因 - 出票等高风险动作有鉴权、审计、幂等(同一
taskId/messageId不重复扣款) - 对内中台仍走 MCP/RPC,没有把数据库连接串暴露进 Artifact
9. 通信失败模式与治理
| 失败 | 表现 | 通信侧对策 |
|---|---|---|
| 死锁 | 互相等对方先回复 | 超时、deadline、打破循环等待;中枢统一调度 |
| 活锁 / 无限辩论 | 一直在说话但无进展 | max_round、无进展检测、仲裁者终裁 |
| 契约漂移 | 字段名/含义悄悄变 | schema 版本化、校验失败即拒收并重试/升级 |
| 幻觉当事实传播 | 上游胡编被下游当真 | 黑盒产物 + 校验点;关键字段要证据引用 |
| 上下文膨胀 | 共享历史滚雪球 | 摘要、refs、按角色裁剪可见窗口 |
| 越权读写黑板 | 工人改了不该改的全局字段 | 写权限最小化;分「私有状态 / 共享产物」 |
| 不可复现 | 发言顺序随机 | 生产用显式路由,少用「LLM 选下一个说话者」 |
| 跨系统半成功 | 远端完成了但本地没接到 | trace_id + 幂等 + 可重入的 GetTask |
可观测底线: 每条跨 Agent 消息可关联到同一 trace_id ,并能回答「谁在何时对谁说了什么、对方回了什么」。接 可观测性与 LLMOps。
10. 设计决策清单(动手前)
- 范围是进程内还是跨系统?跨系统是否真的需要 A2A?
- 若上 A2A:做 Server、Client,还是两边都做?原 Agent 的适配入口清晰吗?(§8.6)
- 载体选消息 / 黑板 / 共享状态 / 队列中的哪一种(或组合)?
- 同步还是异步?超时与取消谁负责?
- 黑盒产物还是白盒轨迹?生产默认是前者吗?
- 信封是否结构化?
expect.schema写清了吗? - 交接是 Hub relay、Peer、Agent-as-Tool,还是 Artifact handoff?
- 有没有
max_round/ 终止条件 / 预算上限? - 共享区写权限与膨胀对策有吗?
- 消息与决策能否按
trace_id复盘?
11. 学习要点
- 多 Agent 的工程核心是 通信 + 状态 + 终止 ,不是角色昵称数量。
- 先分清 进程内 与 跨系统 ;前者用 State/消息/队列做对,后者再考虑 A2A。
- 三条轴要显式选择:同步/异步、黑盒/白盒、自然语言/结构化。
- 生产默认: 中枢转发 + 结构化信封 + 黑盒产物。
- MCP 连工具,A2A 连 Agent ;OTA 对外暴露卖机票给外部 Agent = A2A Server,对内调中台 = MCP/RPC(见 §8.2)。
- 给普通 Agent「加 A2A」= 外包协议壳(Card + Executor + 传输),不是重写大脑(见 §8.6)。
- 没有契约与可观测的「多 Agent 聊天」,通常只是更贵的单线程糊涂账。
12. 参考资料
- 本目录
01/02/03;13-进阶与工程化/06-多智能体进阶.md、10-Agent协议与形态前沿.md - Anthropic, "Building Effective Agents"(多 Agent 审慎使用)
- AutoGen / CrewAI / MetaGPT / LangGraph 官方多 Agent 文档
- A2A Protocol Specification
- a2a-js SDK(把现有 Agent 挂成 A2A Server/Client)
- Anthropic MCP 文档(与 A2A 对照:02-MCP协议)
本文缩写
| 缩写 | 音标 | 全拼 | 中文 |
|---|---|---|---|
| A2A | /ˌeɪ tə ˈeɪ/ | Agent2Agent | Agent 间通信协议 |
| MCP | /ˌem siː ˈpiː/ | Model Context Protocol | 模型上下文协议 |
| LLM | /ˌel el ˈem/ | Large Language Model | 大语言模型 |
| JSON | /ˈdʒeɪsən/ | JavaScript Object Notation | JS 对象表示法 |
| HTTP | /ˌeɪtʃ tiː tiː ˈpiː/ | Hypertext Transfer Protocol | 超文本传输协议 |
| RPC | /ˌɑːr piː ˈsiː/ | Remote Procedure Call | 远程过程调用 |
| SOP | /ˌes əʊ ˈpiː/ | Standard Operating Procedure | 标准作业程序 |
| OTA | /ˌəʊ tiː ˈeɪ/ | Online Travel Agency | 在线旅行社 |
| REST | /rest/ | Representational State Transfer | 表述性状态转移 |
| JSON-RPC | /ˈdʒeɪsən ˈɑːr piː ˈsiː/ | JSON Remote Procedure Call | JSON 远程过程调用 |
评论
评论加载中…