智能体身份与鉴证

11 分钟读完

S3
深入解析 · 智能体安全

"是哪个智能体在调用我"在 2026 年有三个答案——一张签名的 Agent Card 证明是谁发布了它,运行时鉴证证明此刻是谁在调用,一份可验证凭证证明第三方为其担保了什么——而它们是互补的,不是相互竞争的。

一旦智能体开始调用其他智能体的工具,"这是哪个智能体"就不再是修辞性的问题,而变成一个真金白银系于其上的授权问题。三种机制在不同的层上回答它:签名的 Agent Card 证明一张卡片的静态真实性(开放的 A2A #1672 提案),运行时鉴证把一次特定请求绑定到一个特定的智能体实例(OATR 提案——Ed25519 JWT、RFC 8785 规范化 JSON、请求哈希的重放防护),可验证凭证则让第三方跨信任域为一个智能体担保(W3C DID/VC,被 Google 的 AP2 用于可审计的同意)。Visa 的 Trusted Agent Protocol 又加上了 RFC 9421 HTTP 消息签名,把每次请求锁定到一个商户页面上。本文讲的是这套分类学、内部智能体与跨组织智能体各自的最小可用身份,以及为何这些当中没有一个是已批准的标准。

STEP 1

"哪个智能体"背后藏的三个问题。

策略即代码那一篇假设了网关已经知道是哪个智能体在请求。这个假设,在一个智能体跨组织边界去调用另一个智能体的工具的那一刻就破了。"这是哪个智能体"听起来像一个问题,但它其实是三个,各自有不同的答案与不同的失败模式——而把它们混为一谈,正是你最终信任了一个本该拒绝的请求的原因。

第一个是谁发布了这个东西——智能体所对外宣称的静态身份,在任何请求发生之前。第二个是此刻是谁在调用我——发出这次特定调用的那个特定实例的运行时身份,而这是一个静态凭证无法证明的,因为一张泄露的卡片可以被任何人重放。第三个是第三方为其担保了什么——一个不是由智能体自己、而是由一个依赖方已经信任的签发者所主张的声明,这是在没有共享身份提供方的域之间建立信任的唯一途径。卡片真实性、运行时鉴证、以及第三方鉴证依次回答这三者,而它们是互补的:你按威胁模型来组合它们,而不是三选一。

有一条告诫贯穿下面每一节:这些当中没有一个是已批准的标准。A2A 的那几块是开放提案,W3C 的工作是社区组与学术阶段,而只有传输层的签名建立在已发布的 RFC 之上。把它们当作生态正在收敛的方向,而不是今天就能拿来承载关键信任的货架。

STEP 2

签名的 Agent Card(静态真实性)。

一张 Agent Card 是描述一个 A2A 智能体是什么、能做什么的元数据文档——名称、技能、端点、能力——它是客户端在发现阶段、决定是否要跟这个智能体对话之前所抓取的东西。如果那张卡片没有签名,任何能给你送一份文档的人都能声称自己是任何一个智能体,而在发现跨越了一条你不掌控的边界的那一刻,这就是个问题。卡片签名回答第一个问题:它让客户端能验证它所抓取的卡片确由它所声称的那一方发布、且在传输中未被改动。

被讨论的这个具体机制是一个开放提案,把这一点说准确很要紧。A2A 的 #1672 issue 提议在 Agent Card 上加一个可选的 verifiedIdentity 字段,好让一张卡片能携带其发布者的密码学证明。截至撰写时,它是一个开放的 GitHub issue——没有已合并的拉取请求、没有已采纳的标签——而人们所指向的那个具体的"AgentID / ECDSA P-256"签名方案,可追溯到一个第三方项目 getagentid.dev,而非任何 A2A 项目所批准的东西。所以诚实的说法是:卡片签名是个对的主意、并且有一个活跃的提案在推它,但目前还没有一个 A2A 采纳的卡片签名标准。如果你今天就去签卡片,你是在押一个未必会最终落地的方案。

即便被完全采纳,一张签名的卡片也只回答那个静态问题。它证明卡片是真实的;它并不证明正在向你发出实时请求的实体就是那张卡片所描述的那个。一张签名的卡片是一件可泄露、可重放的物件——把它复制走,你就能出示一个有效签名而并非那个智能体。"这张卡片是真的"与"这个调用者此刻就是那个智能体"之间的这道缝,正是下一层所要合上的,也正是为何对任何带副作用的东西而言,卡片签名是一个必需的下限、而非一个充分的答案。

STEP 3

运行时鉴证:OATR。

运行时鉴证把一次单独的请求绑定到一个单独的智能体实例上,好让依赖方不只能判断存在一张有效卡片、还能判断这次调用此刻确实来自那个持有对应密钥的智能体。A2A 讨论区里的那个提案是 OATR——Open Agent Trust Registry——而它,跟 #1672 一样,是一个提案、而非一份已批准的规范。它仍然值得研究,因为它的形状正是"逐请求的智能体身份"正在走向的地方。

OATR 把一份鉴证构造成一个 Ed25519 签名的 JWT,带有一个用于区分的类型头(typ: agent-attestation+jwt)。其声明用 JCS——RFC 8785 的 JSON 规范化方案——来规范化 JSON,好让签名方与验证方无论键序或空白如何,都对字节相同的字节做哈希。关键在于,这份鉴证把三样东西绑在一起:卡片指纹(这个实例在主张哪张卡片)、智能体实例 id(哪个正在运行的实例)、以及请求本身的一个哈希。最后这个绑定挫败了重放——因为签名覆盖了那次特定请求的哈希,一份被截获的鉴证无法被重新贴到另一个请求上,而一个 nonce 加一个时间戳则界定了连同一个请求也能被重发的那个窗口。OATR v1.2.0(2026 年 3 月末)还发布了枚举化的拒绝原因码,好让一个拒绝某份鉴证的验证方返回一个机器可读的原因、而非一个不透明的失败。

下面是一份 OATR 鉴证的形状——一个 JWT 头与声明——调用者会把它随请求一起出示:

{
  "typ": "agent-attestation+jwt",
  "alg": "EdDSA"
}
.
{
  "iss": "did:web:agents.acme.example",
  "sub": "urn:agent:repo-triage",
  "instance_id": "inst-7f3a91c2",
  "card_fingerprint": "sha256:9b1c…e40d",
  "request_hash": "sha256:c7a2…18ff",
  "nonce": "n-4471aa02",
  "iat": 1777650442,
  "exp": 1777650502
}

request_hashnonce 是承重字段:它们让这份鉴证恰好只能用一次、恰好用于这一次请求、恰好来自这一个实例。一张签名的卡片回答"这是不是一个真实的智能体";一份 OATR 鉴证回答"这个真实的智能体是不是就是在这次请求上调用我的那个"——这才是授权真正需要的问题。它是那张静态卡片的运行时补充,而两者互不替代。

STEP 4

可验证凭证(跨域信任)。

签名的卡片与运行时鉴证都只让一个智能体对自己作出声明,而当你所对话的那一方与你没有先前关系、也没有共享身份提供方时,这就一文不值——正是那个跨组织的情形,此时"相信我,我给自己的卡片签了名"毫无分量。可验证凭证恰好针对这一点:一个声明由一个依赖方已经信任的签发者作出,关于一个主体(那个智能体),而依赖方验证的是签发者的签名、而非智能体的自我主张。

其构件是 W3C 标准轨与社区的工作、而非智能体专属的。一个去中心化标识符(DID)给每个智能体一个自持有、锚定于账本的标识符,没有哪个中心化注册表能把它从你脚下撤销掉,而可验证凭证让第三方就那个 DID 签发签名的声明——"由一个有资质的组织运营""被授权交易至某个额度"。这里的那个学术提案锚定每个智能体的 DID、并在其上叠加第三方签发的 VC,恰恰是为了让跨域信任不需要一个中心化的身份提供方,而一个 W3C Agent Identity 社区组正在攻这个问题——这正是要传达的状态:真实、活跃、社区组阶段,而非一份完成的、已批准的标准。Google 的 AP2 是那个值得一提的生产级采用者,用 W3C 可验证凭证来为智能体发起的交易捕获可审计的用户同意;AP2 与智能体商务那一篇讲了那条同意链在一次支付流里是如何运作的。

要抓住的区别是信任的方向。卡片签名与鉴证是智能体在对自己作出主张,其可信程度永远只等于那个智能体本身。一份可验证凭证是一个受信第三方在对那个智能体作出主张,正是它让一个处在不同信任域里的依赖方能够接受那个声明。对任何跨越组织边界、且带着后果的东西而言,自我主张是不够的——你需要一个依赖方已经信任的人来担保过。

STEP 5

商务:Visa TAP 与 RFC 9421。

支付是身份不再抽象的地方,也是这里唯一一个建立在已发布 RFC 而非提案之上的层。Visa 的 Trusted Agent Protocol 用 RFC 9421 HTTP 消息签名来对一个智能体向商户发出的每次请求签名,好让商户能验证该请求确实来自一个已注册、受信的智能体,且未被伪造或重放。与 A2A 的卡片和鉴证提案不同,RFC 9421 是一个用于对 HTTP 消息签名的、已批准的 IETF 标准;TAP 是 Visa 把它应用到智能体商务上的产物。

TAP 在原始签名之上所加的是绑定。一个签名覆盖一组被选定的组件——方法、路径、选中的头、一个创建时间戳、一个 key id、以及一个会话标识符——而 TAP 用这些把每次请求锁定到一个特定的商户站点与页面上,好让一个在某个页面上被截获的签名请求无法被重放到另一个页面,而时间戳加会话 id 则把它界定为单次使用。发布时就有合作伙伴在列,Akamai 也在 2026 年加入——有用的信号在于,这是那个背后带着真实生产级商务分量的身份层,因为它解决了一个商户直接能感受到的问题:把一个合法的购买智能体与一个机器人区分开。

下面是那个把请求锁定到其目标上的 RFC 9421 签名输入的形状——被覆盖的组件、以及让签名成为单次可用的元数据:

Signature-Input: sig1=("@method" "@authority" "@path" \
    "content-digest" "@query-param";name="page"); \
    created=1777650442; keyid="visa-agent-8f2a"; \
    nonce="req-90c14e"; tag="tap-v1"
Signature: sig1=:MEUCIQD…snip…kQ2gc=:

被覆盖的组件才是要点:因为 @authority@path、以及那个 page 查询参数都在签名之内,这个签名只对那个确切的商户、路径、页面有效——把它挪到别处,验证就会失败。这就是请求锁定,而它是 OATR 用一个请求哈希所构建的那种重放防护的商务级版本。

STEP 6

最小可用身份。

你不会到处都把这四层都部署上——你按请求所跨越的那条边界来匹配机制。组织性的问题是:信任要走多远,以及搞错了会赔上多少钱。

对一个在你所掌控的网络内部调用另一个智能体的内部智能体而言,最小可用身份是朴素的:一张签名的卡片,好让调用者的静态身份可验证,再加上网络策略——双向 TLS、一张服务网格、白名单路由——去从一开始就约束谁能触及谁。你已经拥有那个运行时与那张网络,所以一张签名卡片所留下的残余风险,被你所持有的控制界定住了;对高价值的内部动作而言,运行时鉴证是一个合理的追加,但它不是那个挡在你与灾难之间的东西。

对一个跨组织的智能体、尤其是一个在转账的智能体而言,那个下限要高得多,因为那些环境里的网络控制一概不适用、而对手方也不在你的信任域里。那里你会想要请求签名,好让每次调用都被绑定、不可重放——商务情形里用 RFC 9421,或更一般地用 OATR 式的运行时鉴证——再加上一份可验证凭证,好让一个对手方所信任的第三方为那个智能体担保过。光有签名的卡片是不够的:一张泄露的卡片会被重放,而一张没有人担保的卡片对一个陌生人来说什么也证明不了。

无论你选哪种组合,那份签名的身份都不会止步于门口——它成了那份持久记录的一部分。是谁的密钥给一次请求签了名、它主张了哪个卡片指纹、它出示了哪份凭证:这些都是一次智能体运行所产出的那份防篡改回执的输入,好让一个动作日后能被归因到一个特定的、经过验证的身份、而不是一句匿名的"智能体干的"。这是本组讲决策回执与审计那一篇的领域,签名的身份在那里落到下游。而本文开篇的那条告诫,正是要用来收尾的:为方向而建——卡片签名、运行时鉴证、第三方凭证、请求锁定的传输——但把它当作会移动的地面来跟踪,因为在 2026 年,这些机制是提案与社区草案、而非已定的标准,你今天接进去的那一个,未必就是最终胜出的那一个。