← 返回藏书阁

AgentOps A2A:确认不等于身份,completed 不等于业务成功

wiki/ai/sources/agentops-a2a-confirmation-principal-and-terminal-state.md
分类:ai / sources · 更新:2026-09-22 09:12

AgentOps A2A:确认不等于身份,completed 不等于业务成功

知识点轴:A2A / MCP Gateway / harness-runtime / sandbox-security / benchmark-evaluation。 固定版本的教学参考实现,非企业部署证明。最值得迁移的是两条断言:匿名调用即使走完确认流程也不能获得写权限;安全拒绝可以是协议 completed,但绝不是业务操作成功。

为什么值得深挖

在 Hermes 委托远程 agent、或让网关统一暴露工具时,最容易误认的是“用户点了确认,所以允许执行”和“任务 completed,所以订单/服务已改好”。这个案例把 Card、身份传递、SQLite task store、确认工具和独立业务状态放在同一条可审查链路上,能直接转成内部集成测试,而不只是 A2A hello-world。

与 A2A-Agent2Agent-Protocol 的发现/任务合同、MCP-Gateway-Runtime 的逐跳凭据互补;尤其补足 microsoft-a2a-adapter-host-ownership 留给应用 host 的身份和写操作责任。

一阶机制:授权是不同条件的交集

  1. 确认只表示批准了某项提议,不建立网络调用人的真实身份。
  2. 身份由可信入口验证;调用方能自填的 contextId、用户名或 header 都不能自证。
  3. 归属把当前 verified subject 绑定到 invocation/task,而非“有人登录过”。
  4. 副作用必须在可验证的业务状态中体现,不能仅看模型文字或协议终态。

固定 43c9cc4771ca45257b6fb8de3052ba329785c4af 的具体实现:

边界已读源码机制不能据此声称什么
Gateway → appconfig-auth.yaml 的 A2A route strict JWT 校验 issuer/audience;set x-verified-subject: jwt.sub 覆盖来客值示例 JWT issuer/自签证书不是企业 IdP,配置未部署
HTTP → A2A CallContext先 MarkNetwork,再读可选 trusted header;重复值400、配置后缺失/非法值401;interceptor 将 subject 提升到协议 User字符串格式校验不是验JWT;直连后端仍能伪造受信header
确认 → toolvalidatedApproval 验 confirmation、user/session/invocation;网络匿名拒绝,已认证 principal 必须匹配 invocation user合成 A2A user/context 不是写权限;本地 in-process 是另一信任域
Task storeGet/Update 以 id+owner过滤;Update还绑version;List拒绝无owner并按owner筛选匿名模式不具备多用户保密承诺,SQLite不证明跨节点接管
业务写 → audit模拟服务更新与 audit insert 在同一事务闭包,invocation/action/target作幂等键这是模拟业务SQLite,不是实际重启服务或跨系统 exactly-once

可信header默认未设置时不读取任意身份头,但请求仍被标为网络来源,所以写工具能够 fail-closed。公开 Card/probe GET 与 protocol POST 认证在应用层分开;网关外层 route 仍可另加认证,不能把应用公开 GET 推导为外部无需登录。

最有价值的正反例:两次 completed,两个业务结局

作者的 TestUnauthenticatedA2AConfirmationCannotMutateTheRealStore 使用 scripted LLM、真实 guarded tool 和临时SQLite:先到 input-required,随后提交 confirmed,协议最终为 completed refusal;断言服务仍 down、audit行数为零,并检查工具拒绝证据。

正例 TestAuthenticatedA2AConfirmationMutatesAndAuditsTheRealStore 在两次HTTP请求都绑定同一 subject;断言模拟服务 operational、audit.approved_by 为该 subject。这比只查最终文本更能区分“拒绝工作正常”和“业务操作成功”。不过 fixture 明确把通用 guard 做直通、redactor做恒等函数,并不覆盖整套安全插件或网关认证。

因此建议评测同时保存 protocol_state、business_outcome、authorization_outcome,不要把它们揉成一个 success。相关测量边界见 Agent-Benchmarks、redagentbench-state-grounded-safety-measurement。

流、持久化与退出的边界

  • Card承载0.3兼容与1.0接口;http.go 将两种 binding接到同一handler。endpoint来自advertised host,不是bind wildcard;仍需真实 Card/客户端兼容验证。
  • A2A SSE task事件与模型token流是两层开关;客户端不能把partial text当终态。仓库有REST/A2A归一化Turn对照fixture,未在本机执行。
  • drain用 WithTimeout(WithoutCancel(ctx), DrainTimeout),避免拿已取消context进行零时长等待。它只减少中断,不能保证窗口外任务完成。
  • 持久task、协议终态、模拟业务副作用与审计各自验收;不能从SQLite和drain推导生产恢复/可用性保证。

本轮证据层级

  • 已读完整课程A2A章;固定仓库源码按身份、确认、store、协议测试、gateway auth、事务与event-folding选段深读;原始HTML、整仓tar及hash归档。
  • 实际离线执行:12项源码条件/顺序断言;6项从固定源码提取的精确SQL在合成内存行上的检查:owner可读、非owner不可读、越权/旧version更新零行、正确更新一行、owner与version终态正确。
  • 未执行Go测试:本机Go1.19.13无法解析仓库 go 1.26.8 与 tool block,禁网兼容性探针exit1,测试尚未开始。没有改go.mod来伪造可运行性;SQL fixture不是上游suite替代品。
  • 未启动模型、A2A listener、agentgateway、容器或云资源;未取得本轮live Card/auth/task/stream回执。课程中的PASS是作者展示,不是本机测试结果。

对 Hermes / llm-wiki 的行动启发与未解问题

  1. 隔离集成用例应让匿名确认、别人的task、身份切换恢复都失败,并读回业务状态;合法同subject确认必须仍能成功。
  2. 把网关“认证并覆盖header”和后端“只允许可信入口访问”一起验;只实现前者仍可能被直连绕过。
  3. 学习其黑盒事件折叠与mock状态验收,不照搬本地Ollama/整套Go平台;用户现有云端API路线不变。
  4. 下一轮需在合适工具链的隔离环境跑原测试,再补真实网关header覆盖/重复头/直连负例、断流后tasks/get和取消后的独立终态。Harness-Engineering 与 AI-Knowledge-Point-Radar 记录这个证据缺口,不把源码存在升级为部署安全。

来源

写入记录

  • 2026-09-22 09:08 CST:新增确认/身份/归属/业务终态深析;固定源码、SQL检查与Go版本阻塞分层记录,连接A2A、网关和评测主概念。