教程
A2A 1.0 Agent Card JSON 实战:如何验证 Agent 能力描述、Skills Schema 与跨 Agent 通信数据?
校验失败时,先问绿的是哪一层:能 parse、过了生成 Schema,还是对照规范必填表。
上一篇 发现链路 把 well-known、目录、再对 Card 走完了。字段怎么写,见更早的 Agent Card 字段教程。今天不重填字段,也不重走 hop。手里已经有一张卡,或刚 GET 到一张卡,问的是:怎么断言它合法,以及发出去的 Task 会不会被对面当垃圾。规范原文在 A2A 1.0 规范 §4.4 与 §3.3.4。站点上的 a2a.json 自己写明:这是从 proto 抽出的非规范 JSON Schema 包。1.0 相对 0.3 的搬家见 v1.0 变更。
绿了不等于过了
把生成包丢进 Ajv,指针指到根对象,整包过了——评审里最常见的假绿。根对象不是一张 Card。$defs 里才有 AgentCard、AgentSkill、Task、Message。对整包根做校验,等于没校验。正确指针是 #/$defs/AgentCard。通信数据另指 #/$defs/Task 或 #/$defs/Message,不要拿名片 Schema 去套 Task。
即便指针对了,生成包也常缺 required。2026 年 9 月站点上的 AgentCard 与 AgentSkill 都写了 additionalProperties: false,却没有把规范表里的必填列进 required。空字符串的 name、缺 tags 的 skill,Ajv 仍可能绿。规范表才是必填源:name、description、version、supportedInterfaces、capabilities、defaultInputModes、defaultOutputModes、skills;每个 skill 还要 id / name / description / tags。
所以校验至少两遍。第一遍:能 parse,且对生成包的 AgentCard 不爆 extra key。第二遍:按规范表断言非空。只做第一遍,0.3 残留的顶层 url 会被 additionalProperties: false 抓住;缺 tags 的 skill 会漏网。只做第二遍、不对生成包,又抓不住乱加的 inputSchema。两遍都要。
| 这一层 | 它能抓住什么 | 它抓不住什么 |
|---|---|---|
| JSON.parse | 语法坏了、截断、尾逗号 | 形状对不对 |
生成包 #/$defs/AgentCard | 0.3 顶层 url、skill 上的 inputSchema | 规范必填是否写了 |
| 规范 §4.4 必填表 | 空 name、缺 tags、空 skills | 旗标与即将发送的操作是否一致 |
四层校验,一层只抓一类错
第三层是能力旗标。规范 §3.3.4 写明:streaming 为假还订流式,必须回 UnsupportedOperationError;pushNotifications 为假还配 webhook,必须回 PushNotificationNotSupportedError;extendedAgentCard 为假还拉扩展卡,同样是不支持。Schema 过了、必填也齐,客户端仍可能在下一跳被打回来。夹具要把「Card 合法」和「这次操作被旗标允许」写成两步。
第四层是通信数据。发出去的是 Task 或 Message,不是把 Card 再 POST 一遍。对面回 InvalidAgentResponseError,问题在响应形状,不在名片。MIME 要对 defaultInputModes / skill 覆盖的 inputModes;对不上,规范给的是 ContentTypeNotSupportedError。不要用 MCP inputSchema 去核 A2A skill——1.0 的 skill 提示是 examples 和 MIME。
生成包里还有 snake_case 的 patternProperties(supported_interfaces、default_input_modes)。规范 JSON 用 camelCase。新卡按规范表写 camelCase。CI 若同时收两套键名,Diff 会先脏。不要把 proto 字段名抄进公开名片,除非你明确在养兼容层,并且测试夹具里写明。
对 Card:指向 AgentCard,不要对整包根
仓库里钉一份 a2a.json,版本和站点发布的 bundle 对齐,CI 不要去打会漂的 latest URL。Ajv(或任何 2020-12 实现)的 schema 指针写 #/$defs/AgentCard。instance 是刚 GET 到的卡,或仓库里的 agent-card.json。输出 path 与 keyword。path 对不上夹具,先怀疑指针指错了定义,再怀疑卡。
第一遍最值钱的拒绝,是 extra key。1.0 的端点在 supportedInterfaces。顶层再写 url、protocolVersion、supportsAuthenticatedExtendedCard,生成包会因 additionalProperties: false 红。这是 0.3 残留,不是「多写点更安全」。字段教程已经写过搬家;今天只要求:校验器必须把这些键标成错误,而不是忽略。
接口项核三件:url 生产必须是绝对 HTTPS(gRPC 才是 host:port),protocolBinding 是客户端会说的绑定,protocolVersion 是 1.0 这类协议版本,不是 Agent 自己的 version。两项都叫 version,夹具要分开断言。第一项是首选——客户端挑得到共同绑定,通话才开始。
对 skills:规范必填,Schema 经常不问
生成包里的 AgentSkill 同样常常没有 required。缺 tags 的 skill,Ajv 可能绿,目录搜索面却是空的——发现文写过。今天的断言是:每个 skill 必须有非空 id、name、description,以及至少一项 tags。空 skills 数组过不了规范表。NO_SPEC 那种只有主机的条目,校验应在登记前就红,而不是等关键词 hop 打空。
skill 上不要出现 inputSchema。additionalProperties: false 会把它当 extra key。那是 MCP 工具的事,见站内 Schema 文。1.0 skill 给人看的是 examples 和 MIME。把函数参数表糊进名片,第一遍就应失败。失败发生在校验,比发 Task 之后再澄清便宜。
下面是一张会在第一遍或第二遍红的卡,不是「差一点就能用」的草稿。它混了 0.3 顶层 url、缺 tags 的 skill、以及 MCP 式 inputSchema。和仓库里的 Returns Specialist 并排 Diff,三处红应各落各的 path。
{
"name": "Returns Specialist",
"description": "Classifies return requests.",
"version": "1.0.3",
"url": "https://agents.example.com/returns/a2a",
"protocolVersion": "1.0",
"supportedInterfaces": [
{
"url": "https://agents.example.com/returns/a2a",
"protocolBinding": "JSONRPC",
"protocolVersion": "1.0"
}
],
"capabilities": {
"streaming": true
},
"defaultInputModes": ["text/plain"],
"defaultOutputModes": ["text/plain"],
"skills": [
{
"id": "classify-return",
"name": "Classify a return",
"description": "Decide the request type.",
"inputSchema": {
"type": "object",
"required": ["orderId"],
"properties": {
"orderId": { "type": "string" }
}
}
}
]
}
| 检查 | 失败长什么样 | 下一跳 |
|---|---|---|
| parse + AgentCard 指针 | 尾逗号;顶层 url;skill inputSchema | 修 JSON / 删 0.3 键 |
| 规范必填 / 非空 | 空 name;skill 无 tags;空 skills | 按 §4.4 补字段 |
| 旗标 vs 操作 | 不支持流还订流;未声明扩展卡还去拉 | 改客户端,或改 Card 旗标 |
对通信数据:Task 不是名片
Card 过了,才轮到 message/send。请求体按绑定走 JSON-RPC、gRPC 或 HTTP+JSON,里面的业务对象是 Message 或 Task,不是 AgentCard。用名片定义去校验请求,必红,而且红得没意义。生成包里另有 Task、Message、Part、Artifact。CI 为通信夹具换指针,不要复用 Card 那一行。
响应也要核。规范把不合约定的 Agent 回包收成 InvalidAgentResponseError。状态机是 submitted / working / completed / failed / canceled / rejected,以及中断态 input-required、auth-required。客户端把 completed 当唯一成功,会把「还要你补一句」写成故障。这些键不在名片上。发现成功、通话失败,故障单要写清是哪一层。
下面是一份校验报告夹具,不是任何一家目录或 A2A 的官方 RPC。它把四层结果收成 JSON,方便和仓库 Card、一次 message/send 的请求并排 diff。签名校验只断言形状:signatures[] 每项要有 protected 与 signature(RFC 7515 JWS)。真密钥、真验签留给安全评审,不要把私钥写进夹具。
{
"kind": "card-validation-report",
"note": "CI/review fixture — not an official A2A RPC",
"target": "agent-card.json",
"schema": {
"bundle": "https://a2a-protocol.org/latest/spec/a2a.json",
"pointer": "#/$defs/AgentCard",
"normative": false
},
"parse": true,
"schemaPass": false,
"schemaErrors": [
{ "path": "/url", "keyword": "additionalProperties" },
{ "path": "/skills/0/inputSchema", "keyword": "additionalProperties" }
],
"specChecks": [
{ "id": "required-name", "pass": true },
{ "id": "skills-tags-nonempty", "pass": false },
{ "id": "no-top-level-url", "pass": false }
],
"capability": {
"streaming": true,
"clientWillStream": true,
"ok": true
},
"next": "fix-card"
}
签名、夹具与本地对照
规范允许 signatures,形状跟 RFC 7515。有签名数组,先核两项必填字符串非空,再决定是否验签。没有数组,不等于卡非法——字段是可选的。公开卡按会被拉取来写:不要把静态密钥、内网密码写进 Card。扩展卡跟会话走,和公开卡不要共用一份「已校验」缓存。
也不要把 Plugin SKILL.md 或 MCP tools/list 丢进同一条 Card 校验。箱子里的技能是给本仓库 Coding Agent 的;对面 Agent 的自述是 Card。混进一份 capability.json,三层失败会算到同一行。
浏览器里即可完成:JSON 格式化看卡和报告能否 parse;JSON Schema 校验把官方 bundle 指到 AgentCard,再换指针核 Task;JSON Diff对比合法卡与故意红的卡,抓 extra key 和缺 tags。数据不离开本机。延伸阅读:Agent Card 字段教程、发现链路。目录是什么读 Registry 总览。
相关文章:A2A Agent Card JSON Schema、Agent 如何发现另一个 Agent、Google Agent Registry。
常见问题 FAQ
Ajv 对 a2a.json 绿了,还要不要第二遍?
要。站点 bundle 写明非规范,且生成定义常缺 required。规范表才是必填源。绿了只说明没踩 extra key 和类型。
能不能用同一份 Schema 校验 Card 和 Task?
不能。指针必须换。AgentCard 和 Task 是两个 $defs。拿名片套请求,失败信息会误导下一跳。
skill 能不能挂 JSON Schema 当入参?
1.0 的 skill 不收 inputSchema。那是 MCP 工具。生成包会把它当 extra key。确定性参数留给工具 hop,不要写进名片。
没有 signatures 算不算非法?
不算。规范里 signatures 可选。有数组,再核 JWS 两项必填。没有数组,仍按 §4.4 核必填和旗标。
总结与下一步
2026 年说「验证 Agent Card」,可以收成四层:parse、生成包指针、规范必填表、旗标与通信数据。目录和发现是进门,校验是能不能委托的门卫。
落地顺序:CI 钉住一份 a2a.json,指针写 AgentCard;再跑规范表非空断言;发 Task 前核对旗标和 MIME;通信夹具换 Task / Message 指针。字段怎么写读字段教程;怎么找到这张卡读发现文。用 JSONVue 对合法卡、红卡和报告。