A2A 委托取证:输出字节绑定不等于父方授权
A2A 委托取证:输出字节绑定不等于父方授权
结论与深度判断
《Attesting Outputs and Delegation Ancestry in Multi-Agent AI Systems》补上一个容易混淆的边界:子 agent 签了结果,只证明某个签名方认领这些字节;子方引用父方,也不等于父方同意这次委托。 跨 deployer 的关系需要父子双方对同一条具体边共同签署,结果本身还要在真正的输出出口绑定。
知识点轴:A2A / MCP Gateway / harness-runtime / benchmark-evaluation / sandbox-security。值得正式入库,不是因为又一个协议名,而是论文给出 Agent Card → A2A → MCP → 结果签名的作者实验回执、具体失败条件和可审查测试。09-07 曾因原文读取失败留下候选,本次补回;不是声称它今天刚发布。
为什么对 Hermes 重要
用户未来若让研究、coding、发布 agent 跨服务委托,最终收到一段“任务已完成”或一个文件 hash,仍不知道:谁实际发布了这些内容?上游是否授权了这个下游?中间跳是否被删掉?这分别归属 A2A-Agent2Agent-Protocol 的任务协作、MCP-Gateway-Runtime 的跨域身份治理与 Harness-Engineering 的结果验收,不能靠同一个签名一并解决。
两层机制
输出绑定:签名器必须站在释放边界
部署方 runtime 在交付前观察实际输出字节,计算 SHA-256,并签署包含 output_hash、deployer、实例、有效期、nonce、parent reference、ancestry depth 等字段的记录。agent 不持有签名密钥,也不自行填写“已验证”字段。验证方用自己的受信公钥目录核对 key_id、签名、有效期、nonce 和收到的原始字节。
签名不能证明语义正确、无 prompt injection 或业务已成功;若 runtime 忠实签了恶意输出,它只是留下更好的取证。与 spa-plan-first-label-preserving-persistent-agents 的执行前信息流约束互补:一个负责限制什么可以发生,一个负责证实交付了什么。
祖先关系:哈希连续性不等于双边同意
| 结构 | 未泄露密钥时的主要作用 | 子方密钥泄露后声称任意父方 |
| 签名链表 | 子节点签入父节点摘要,识别删改、拼接 | 子方可自行重新签署父引用,不证明父方同意 |
| Merkle-chain | 增加祖先承诺/潜在局部证明能力 | 仍只有子方授权,不能补上父方同意 |
| 双签 DAG | 父子双方签同一 domain-separated edge manifest | 缺少未泄露父方的签名则应拒绝 |
双签覆盖父 receipt 摘要和完整子记录(构造签名时排除正在生成的签名列表),包括输出、nonce、有效期和 co-signer policy,防止把有效签名挪到另一条边。代价是父签名服务必须在线;拒绝或超时要 fail closed。若父子密钥同时泄露,或同一个 deployer 的全部密钥被控制,保证不再成立。
实践证据:到底运行了哪一种 A2A
本轮读取 arXiv 2608.30387v1 全文、匿名 artifact 的 README、两个 unit-test 文件和 artifacts/current/e12_mcp_a2a_llm/results.json。匿名站网页提取失败后,公开 file API 可读。没有运行该项目的 pytest、模型、Docker 或 AWS 部署。
E12 的作者记录生成于 2026-08-31T06:45:57.583259+00:00,环境源摘要为 b2aaf6465a501db7b5dd044b11081f0f6a7ddac009461e1f56e6c09d694125ba。它实际声明:
- Agent Card:
/.well-known/agent-card.json;card_protocol_version = 0.3。 - A2A:JSON-RPC 2.0,方法
message/send;不能记作 A2A v1 conformance。 - MCP:Python SDK
1.27.2,Streamable HTTP,工具get_evidence。 - 三个 loopback 进程:parent signer、child A2A agent、MCP tool;child 再调用作者的本地 Ollama。这里的本地模型是来源实验配置,不建议用户安装本地模型。
- 每个条件预热 10 次后记录 30 个任务:无证据、签名链表、双签 DAG。作者文件分别记作 not_applicable、accepted、accepted;无证据的 not_applicable 不能算密码学验证通过。
本机实际核查:解析 90 条作者 trial,90 个 task_id 唯一;逐条重算 output 的 SHA-256 和 UTF-8 字节长度,90/90 均匹配。每组确有 30 条,双签组记录 30 次 accepted。仅子密钥的受控伪造案例在记录中为:链表 accepted、双签 rejected,后者原因指向 parent co-signature invalid。这是归档数据内部一致性核验,不是本机重新运行完整签名 verifier,也不能证明这些实验确在作者声称的机器执行。
论文报告双签组端到端均值 813.1 ms、无证据组 770.8 ms;包含该本地配置的 discovery、A2A、MCP、模型和验证。另一项三可用区 AWS 测量与它不是同一 cohort,且排除 TLS/mTLS、KMS、模型及生产授权服务,不能将其延迟包装为生产接入成本。
测试断言比测试标题更重要
test_deployer_verifier.py明确断言 output mismatch、revoked/unknown key、expiry、同一 verifier 第二次 nonce 重放、祖先长度不匹配等 reason。- 其中 replay 测试用同一个
InMemoryNonceStore的两次 verify;注释提到不同服务,实际断言不能证明跨 verifier 防重放。 test_baselines.py::TestKeyCompromiseSignedDAG.test_cross_deployer_resists修改父节点、伪造另一个签名并保留不再匹配的 primary signature,最后仅断言ChainVerifyError。它不是“仅缺父方授权”这一原因的隔离测试,不能独自支撑所有 child-key 结论;该区别必须和 E12 的具体受控案例分开。
这延续 a2a-tck-conformance-coverage-and-security-boundaries 的原则:实际输入、assertion、判定原因与执行记录比测试名字更有证据价值。
可迁移做法与未解决边界
- 未来 A2A 接入先固定 Card hash/协议版本、调用主体、父子 deployer、任务 ID 和交付字节;业务完成再查独立系统状态,不让签名替代 verifier。
- 需要双边委托授权时,明确签什么、谁签、何时拒绝;OTel trace 关联 ID 不是授权签名,也不是不可抵赖证明。
- 真正的长期部署仍需处理公钥准入、轮换、撤销传播、共享 replay 状态和隐私;不将自动发现的公钥直接加入信任目录。
per_session/per_turn/per_tool_call/per_n_tokens在原型里只是签名字段,缺少 session/sequence/tool-call 等实现,不能声称已防流片重排或跨会话搬用;本地 JSON 排序也不等于完整 JCS 跨语言规范化。
论文有限 mutation 矩阵的零接受属于实现一致性样本,不是开放环境安全保证;Agent-Benchmarks 应分别记录作者原始运行、归档校验、本机重放以及安全能力覆盖。
原始入口
写入记录
- 2026-09-11 09:09 CST:新增双层取证机制分析;核对 A2A 0.3、E12 作者逐任务数据及具体测试断言,完成本机 90 条输出 hash/字节长度校验,明确未执行外部系统或完整签名验证。