教程
AI Agent 如何自动发现另一个 Agent?从 Agent Registry、A2A Agent Card 到 JSON Capability Discovery 完整解析
发现失败时,先问走的是哪一跳:搜目录、拉名片,还是已经握着域名却 GET 错了路径。
上一篇 Agent Card 字段教程 把 1.0 必填表摊开了。今天不重填字段,也不重讲 Registry 是目录。编排者的下一问是:我怎么从「需要会办退货的同事」走到一张可调用的 Card?官方答案在 A2A Agent Discovery:策略有三条,Card 只有一种。规范不规定策展目录的查询 API,见同一页的 Considerations。Google Cloud 的目录是其中一种落地,形状对照 Registry JSON schemas。本文按 hop 走查。横向委托和向下调工具的分层,见 A2A vs MCP,今天不重讲。
发现不是协议,Card 才是被找到的东西
A2A 标准化的是自述,不是电话本。远程 Agent 把能力写成 JSON 名片;客户端用这张卡判断适不适合、怎么连、发什么 Task。发现方法随环境变:公网、企业目录、开发机写死,三条都能到同一份 Card。把「发现」说成又一种对话协议,评审会先走偏。协议仍是 A2A;变的是你从哪一扇门走进 well-known 或目录。
官方发现页上的「Role of the Agent Card」仍用 0.3 口气提到顶层 url。新卡按 1.0:端点在 supportedInterfaces,见 v1.0 变更。发现 hop 读到旧字段,不要当 1.0 主合同。字段怎么写,上一篇已经写过。今天只问:这张卡是从哪一跳到手里的,到了之后先核哪几个键。
发现成功,不等于可以 tools/call。对面仍是不透明 Agent。你选出 skill、挑好接口,发送的是 Task。把搜索命中当成函数表,多轮澄清会撑破 arguments。MCP 那一跳怎么核参数,见站内 Schema 文。今天停在「找到谁、凭什么认定他会办这件事」。
| 策略 | 你事先知道什么 | 下一跳 |
|---|---|---|
| Well-known URI | 域名或主机 | GET /.well-known/agent-card.json |
| 策展目录 | 技能关键词 / 标签 | 查目录,再拉 Card 或引用 |
| 直接配置 | URL 或整张卡 | 跳过搜索,直接读卡 |
三条官方策略,先选路再走路
Well-known 适合公开 Agent,或域名受控的发现。路径跟 RFC 8615:https://{agent-server-domain}/.well-known/agent-card.json。客户端已经知道或能推出域名,发 HTTP GET,拿到 JSON。实现简单,自动化友好。名片里有敏感技能或内网 URL,这个 GET 本身就要鉴权,不能把内网端点裸挂在公网。
策展目录适合企业或市场:中间服务收一批 Card,客户端按 skills、tags、provider、capabilities 查询,目录返回匹配的卡或引用。好处是治理和按能力搜。代价是你要养这份目录。A2A 没有规定目录 API。Google Agent Registry、社区 registry、自建目录,查询形状各写各的。不要拿一份「通用 discover JSON」去校验三家。
直接配置适合紧耦合、私有 Agent、开发机。卡 URL 写在环境变量、配置文件或专有 API。关系静态时最省事;Card 一变,客户端要跟着改。生产里把「开发机写死」当成唯一发现面,就是 2025 年通讯录。三条路可以并存:目录负责搜到谁,well-known 负责目录挂了还能读名片,配置负责启动时的种子主机。
手里有域名:GET well-known
最干净的 hop 只有三步。① 得到域名,例如 returns.agents.example.com。② GET https://returns.agents.example.com/.well-known/agent-card.json。③ 响应是一张过 1.0 Schema 的 Card。路径写错、HTTP 换成内部别名、证书主机名对不上,故障单上会写成「发现失败」,其实 Card 是好的,GET 没打到。
规范建议 Card 端点带缓存头。Cache-Control: max-age=… 让中间层和客户端少打满卡;ETag 可用 version 或内容哈希。过期后先条件请求(If-None-Match),不要每次无条件拉全文。服务器没给缓存头,客户端可以自己设一个合理默认,但不能永久缓存一张会改 skills 的卡。
公开卡够编排者选型即可。敏感技能、内网第二端点,放到认证后的扩展卡。capabilities.extendedAgentCard 为真,才去拉第二份。发现 hop 不要在未认证时假设扩展卡存在。目录按身份选择性返回不同 Card,和 well-known 上一张对所有人相同的卡,是两种披露,评审里要分开写。
手里有目录:搜 tags,再拉 Card
没有域名、只有一句「找会分类退货的同事」时,走策展目录。查询吃的是 Card 上的 skills[].tags 和技能名,不是你幻灯片上的拓扑。Google 项目内的编排者、Gemini Enterprise、Agent Gateway 按技能关键词找登记项——这是产品行为,不是 A2A 标准 RPC。社区或其他云各有各的 search。评审夹具里只断言「查询 → 命中列表 → 每条带 cardUrl 或内嵌 Card」,不要把某一家的路径写成规范。
目录返回引用时,下一跳仍是 well-known 或目录给出的 Card URL。返回内嵌 Card 时,仍要用 1.0 Schema 核一遍:登记成功不等于字段合法。NO_SPEC 那种只有主机、没有 skills 的条目,搜索面是空的——#5 写过,今天只提醒:关键词 hop 打在空索引上,不是协议坏了。
目录挂了,并不自动等于发现结束。手里若已有域名,客户端仍应 GET well-known。把目录当成唯一真相,等于把发现面单点化。种子配置里留一两个稳定主机,目录恢复后再做关键词搜索,比「目录 500 就停摆」更接近规范写的三条并存。
命中之后:对 skills,挑接口,发 Task
搜索命中只说明「可能是他」。编排者还要对 skills[]:id 是否就是你要委托的那类事,tags 是否真的命中查询词,description 的边界是否接受。不要用 MCP inputSchema 去套 skill。1.0 的提示是 examples 和 MIME。选错 skill 再发 Task,失败发生在委托,不在发现;但夹具要把「命中 ≠ 选定」写成两步。
选定之后读 supportedInterfaces。第一项是首选。客户端按自己会的绑定挑:JSONRPC、GRPC、HTTP+JSON。挑不到共同绑定,发现成功、通话失败。0.3 顶层 url 不要当 1.0 主端点。能力旗标也要看:streaming 为假还订流式,规范要求回能力错误,不是默默改成 unary。
下面是一份走查夹具,不是任何一家目录的官方 API。它把查询、命中、首选接口收成 JSON,方便和仓库里的 Card 并排 diff。下一步才是 message/send。校验清单和签名留给更后面一篇。
{
"kind": "discovery-trace",
"note": "CI/review fixture — not an official A2A or Google Registry API",
"query": {
"tags": ["returns", "classify"]
},
"strategy": "curated-registry",
"hits": [
{
"name": "Returns Specialist",
"cardUrl": "https://returns.agents.example.com/.well-known/agent-card.json",
"matchedTags": ["returns", "classify"],
"skillId": "classify-return"
}
],
"selected": {
"skillId": "classify-return",
"preferredInterface": {
"url": "https://agents.example.com/returns/a2a",
"protocolBinding": "JSONRPC",
"protocolVersion": "1.0"
},
"next": "message/send"
}
}
| 这一跳 | 输入 | 你该断言什么 |
|---|---|---|
| 搜目录 | tags 或技能名 | 命中列表非空,且带引用 |
| 拉 well-known | 域名或 cardUrl | JSON parse,过 1.0 Schema |
| 选型 / 挑接口 | 完整 1.0 Card | skill id 对上,接口客户端会说 |
缓存、过期与夹具
Card 改得不勤:加技能、改鉴权才会动。发现面却会脏。目录索引滞后,well-known 已是新 version,搜索还指向旧 tags。夹具至少两份:目录命中快照,和刚 GET 到的 Card。keywords 对不上,先查 tags 和索引延迟,再查是不是 1.0 客户端读了 0.3 卡。
{
"hop": "well-known",
"method": "GET",
"url": "https://returns.agents.example.com/.well-known/agent-card.json",
"requestHeaders": {
"If-None-Match": "1.0.3"
},
"response": {
"status": 304,
"etag": "1.0.3",
"cacheControl": "max-age=3600"
}
}
规范写:敏感数据必须鉴权,推荐带外动态凭证,不要把静态密钥写进 Card。发现夹具里出现 token、内网密码,评审直接打回。公开卡按会被拉取来写。扩展卡的缓存跟会话走,不要和公开卡的 max-age 混成一个桶。
也不要把 Plugin SKILL.md 或 MCP tools/list 当成发现源。同一仓库里的 Coding Agent 怎么长技能,是箱子的事;另一个团队的退货 Agent 怎么被找到,是 Card 的事。混进同一份「capability.json」,三跳失败会算到同一行。
浏览器里即可完成:JSON 格式化看走查夹具和 Card 能否 parse;JSON Schema 校验核命中后的 1.0 Card;JSON Diff对比目录快照和刚拉到的 Card,抓 tags / 接口 drift。数据不离开本机。延伸阅读:Agent Card 字段教程、Registry 总览。签名与校验清单读下一篇实战。
相关文章:A2A Agent Card JSON Schema、Google Agent Registry、A2A vs MCP。
常见问题 FAQ
有了目录,还要不要 GET well-known?
要。目录消费 Card,不替代 Card。规范把 well-known 写成公开发现的标准路径。目录挂了,拿得到域名的客户端仍应读名片。
A2A 有没有标准的「搜索 Agent」RPC?
没有。发现页写明:当前规范不规定策展目录的 API。各家目录自己定义查询。标准的是 Card 的形状和 well-known 路径。
搜到了能不能直接 tools/call?
不能。命中是发现结果。对面是不透明 Agent,走 Task。确定性参数留给 MCP 工具,不要写进发现 hop。
缓存多久算合理?
先听服务器的 Cache-Control 和 ETag。没给头,用短默认,过期走条件请求。技能或鉴权一变,version 应变,客户端不该抱着旧 tags 做生产路由。
总结与下一步
2026 年说「自动发现另一个 Agent」,可以收成三跳:选策略、拿到 Card、按 skills 和接口决定要不要委托。目录是其中一扇门,不是协议本身。
落地顺序:公开 Agent 先挂对 well-known;要按关键词找,再接入某一家目录并自备查询夹具;命中后核 1.0 Card 再发 Task。字段怎么写读上一篇;目录是什么读 #5;校验与签名读更后面一篇。用 JSONVue 对走查 JSON 和仓库 Card。