消息协议与共享状态

本节目标

区分消息、事件和权威状态;设计可关联、可去重、可版本化的协作数据,而不是依靠对话文本猜测进度。

三类数据不要混用

  • 消息(message):一个参与者给另一个参与者的请求或响应。
  • 事件(event):已经发生的事实,例如 task_started、tool_failed。
  • 状态(state):根据已接受事件得出的当前权威视图,例如任务为 running、预算剩余 3。

聊天记录不是可靠状态库。消息可能重复、乱序或丢失;自然语言也难以做并发控制。把关键状态写入结构化存储,由运行时更新,Agent 只能提出变更。

消息信封

{
  "message_id": "M-104",
  "trace_id": "R-7",
  "task_id": "T-20",
  "sender": "manager",
  "recipient": "researcher",
  "type": "task_request",
  "schema_version": "1",
  "created_at": "2026-07-13T04:00:00Z",
  "idempotency_key": "R-7:T-20:attempt-1",
  "payload_digest": "sha256:...",
  "payload": {"goal": "collect evidence"},
  "evidence_refs": []
}
  • message_id 唯一标识一次消息;它回答“这份消息是否已经看过”。
  • trace_id 串起整个用户请求。
  • task_id 串起子任务的多次尝试。
  • schema_version 支持协议演进。
  • idempotency_key 标识同一个逻辑意图;payload_digest 在声明的序列化算法、版本与数值规则下绑定载荷/产物。只有两者都相同才是可忽略的重复投递。
  • evidence_refs 指向原始证据,避免层层摘要后无法核验。

重复不是冲突

消费者不能只见到“同一个 key”就静默保留第一次结果。应保存 (task_id, idempotency_key, payload_digest, digest_scheme_version):

  • 同 key、同 digest:记录 duplicate,复用已验收结果;
  • 同 key、不同 digest:不选择“最后写入获胜”,冻结为 needs_review,保留两份摘要/受保护证据引用、状态版本和到达顺序,并让对外 result 明确变为不可信;
  • 新 key 到达已终态任务:作为迟到结果记录,不倒退状态;若它试图改变已验证业务副作用,仍须进入对账流程。

needs_review 是本课程运行时的安全扩展,不是声称 A2A 定义了这个状态。A2A 规范仅说明 Send Message 可以用 messageId 识别重复,并定义 WORKING、COMPLETED、FAILED、INPUT_REQUIRED、AUTH_REQUIRED 等互操作任务状态;内部协调器仍须定义自己的结果冲突和人工对账合同。课程模拟器用 Python 的排序键 JSON 序列化作本地教学 digest,不是跨语言 canonical-JSON 标准;跨进程实现必须固定并测试自己的 digest scheme/version。A2A 规范(访问于 2026-07-22)

单一事实源

为每种事实指定唯一权威位置:

事实权威源非权威副本
任务状态调度器状态库Agent 对话摘要
预算用量计费/运行时记录Agent 自报
文件版本仓库哈希/版本号“已保存”消息
用户审批审批记录模型推断

多个 Agent 可读取,但写入应受角色权限和状态机约束。若需要并发写,使用期望版本(compare-and-swap):只有提交时版本仍等于读取版本才成功,否则重新读取并合并。

状态机比自由文本可靠

最小任务状态可为:

pending -> ready -> running -> succeeded
                       |-> retry_wait -> ready
                       |-> failed
                       |-> denied
                       |-> waiting_human
任何状态 -> needs_review: 同一意图出现互斥结果/receipt
needs_review -> ready 或 canceled: 有权限的人基于保留证据作出新决定
任何非终态 -> canceled

只允许白名单迁移。例如 succeeded 不应被迟到的 failed 消息覆盖;但同一幂等意图被证明产生互斥结果时,允许升级到 needs_review,而不是悄悄隐藏矛盾。每次迁移记录旧状态、新状态、原因、执行者、时间与 state_version。多个 worker 恢复同一 run 时,还要使用与 Agent 核心的 lease_version 和 state_version 一致的提交条件。

A2A 与 MCP 的层次

截至 2026-07-22,A2A 规范页的 latest released version 为 1.0.0;规范定义 Agent Card、Task、Message、Part、Artifact 等互操作概念,并要求协商 Major.Minor 协议版本而不把 patch 用于兼容协商。该事实会继续变化。A2A 面向独立 Agent 间发现与任务协作,MCP 更侧重模型/Agent 连接工具、资源和提示。学习概念时可借鉴其数据模型,但不应把某个协议当成所有内部协作的必需依赖。

错误与排查

  • 重复执行:检查是否有幂等键、已版本化的 payload/receipt digest scheme、消费者去重表和副作用提交记录。
  • 同键不同结果被吞掉:检查是否把 key 当作完整意图;应冻结并人工对账,不能只保留先到或后到的自然语言答案。
  • 状态倒退:检查迟到事件是否携带版本,状态机是否拒绝非法迁移。
  • 证据丢失:检查消息是否只转述结论,没有 evidence_refs。
  • 敏感信息扩散:按接收者最小化 payload,日志中做字段级脱敏。

练习与自测

为“研究者把事实表交给作者”设计消息信封,并说明事实表自身放在哪里。自测:消息队列显示已投递是否等于任务完成?重放同一消息时怎样证明不会重复发布?

下一步

继续 冲突、同步与失败恢复。

参考资料