协作约 13 分钟

注册与发现中心

两层目录:先按 Agent Card 找到逻辑能力,再用服务端签名的路由句柄解析到具体实例;不新鲜、不健康的条目不会被发现。

依据 agent-solution 0.1.3 · main@bf702bc9(2026-11-03)核实

为什么需要注册中心

网关收到"找交期承诺智能体"的请求,得知道两件事:有没有这样的智能体、现在该打到哪台机器上。registry-discovery-center(下文简称 RDC)把这两件事分成两个平面:

平面回答接口关键字段
逻辑 Agent Card谁能做这件事POST /api/registry/discover不含实例地址
运行时实例路由现在打到哪个实例GET /instances/...、POST /route-handle/resolve不透明的 routeHandle
源码RDC READMEagent-solution/common/agent-bus/registry-discovery-center/README.md@bf702bc9

数据存在 PostgreSQL,用行级安全(RLS)做租户隔离。

逻辑发现:层层过滤

一次 discover 请求要带租户,以及 agentId / serviceId / 技能 ID 至少一项,还可以带版本、技能标签等约束:

{
  "context": { "tenantId": "sales", "callerRef": "gateway", "requestId": "req-1" },
  "agentId": "delivery-promise",
  "limit": 5,
  "constraints": { "contractVersion": "1.0.0", "requiredSkillTags": ["order"] }
}
说明

示意请求,字段结构取自 README,智能体名称是本站案例里的示例值。

发现引擎按这个顺序过滤,每一步落空都有明确的结果:

  1. 按选择器查登记 → 查不到:NO_MATCH
  2. 只留 REGISTERED → 没有:NO_MATCH
  3. 只留新鲜度为 FRESH 的(排除 STALE_CARD、STALE_SOURCE)→ 没有:NO_MATCH
  4. 按版本约束过滤 → 没有:VERSION_UNAVAILABLE
  5. 按执行约束过滤 → 没有:CONSTRAINT_UNAVAILABLE
  6. 去重、分页 → SUCCESS
源码StructuredDiscoveryEngine.discoveragent-solution/common/agent-bus/registry-discovery-center/src/main/java/com/openjiuwen/rdc/service/StructuredDiscoveryEngine.java:44@bf702bc9

区分"找不到""版本不对""约束不满足",调用方才能给用户一个准确的说法,而不是笼统的失败。

实例路由:只给句柄,不给地址

按智能体、按服务、按能力列实例时,响应里有 routeHandle 和健康状态,但不暴露 endpointUrl。能被列出来的实例要同时满足:

  • 状态是 ONLINE 或 DEGRADED(DRAINING 正在摘流,不再接新请求)
  • 最近 15 秒内有心跳
源码发现可见性过滤agent-solution/common/agent-bus/registry-discovery-center/src/main/java/com/openjiuwen/rdc/repository/JdbcAgentRegistryRepository.java:105@bf702bc9

网关拿着句柄调 resolve,才得到真正的地址。统一 API 的句柄格式是:

rh1: + base64url(内容 JSON) + . + base64url(HMAC-SHA256 签名)

内容里带着租户。解析时与调用方租户比对,不一致就拒绝并审计。所以句柄伪造不了、改不了、跨租户用不了。

源码RouteHandleIssueragent-solution/common/agent-bus/registry-discovery-center/src/main/java/com/openjiuwen/rdc/core/RouteHandleIssuer.java:33@bf702bc9

这也带来一条运维要求:签名密钥必须是至少 32 个字符的私有随机值,同一集群的副本共用,未配置或用了公开的开发默认值会拒绝启动;换密钥后,旧句柄全部失效,调用方要重新发现。

说明

RDC 里还保留了一个旧版的 v2: 句柄编解码(没有签名),README 的 API 速查也还写着"仅接受 v2:"。统一 API 的签发器注释明确说旧格式"按设计不兼容"。接入时以你实际调用的接口版本为准。

实例从哪来

正式环境不靠实例自己"推送注册",而是由部署发现(DeploymentDiscoveryProvider)按对账周期(配置示例是 30 秒)从部署侧拉取;开启后,推送式 POST /register 直接返回 410。注册表以部署系统为唯一来源,健康状态再由探活更新。

小结

  • 逻辑 Card 和实例路由分成两层:先找"谁能做",再找"打到哪"。
  • 发现只返回已登记且新鲜的 Card;实例要在线且 15 秒内有心跳。
  • 路由句柄由服务端签名、带租户,调用方只能拿来解析,不能伪造或跨租户使用。

源码出处

链接指向固定提交,仓库后续更新不影响这里的行号。

过关测验

  1. 1. 逻辑发现接口 /api/registry/discover 会返回实例的访问地址吗?

  2. 2. 一个 Agent Card 被判为 STALE_CARD(数据已不可靠),发现时会怎样?

  3. 3. 为什么路由句柄要由服务端签名,并且把租户写进去?

通关条件

  • ○ 测验全部答对