协作治理约 14 分钟

agent-gateway 入口治理

请求进入智能体之前要过的检查:鉴权、租户、参数、幂等、审计;之后按配置直连运行时或经事件总线转发。

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

网关站在哪里

企业里的业务系统(销售、客服、门户)不直接调智能体,而是先进 agent-gateway。它接收 A2A JSON-RPC 请求(POST /a2a),做完治理检查,再把请求转给真正的运行时:

转发模式走法
direct(默认)先问注册中心要路由,再直连运行时的 /a2a(HTTP / SSE)
bus经事件总线两跳转发到运行时(下下关讲)
源码agent-gateway READMEagent-solution/common/agent-bus/agent-gateway/README.md@bf702bc9

网关是独立部署的 Spring Boot 服务,跟注册中心、运行时都只通过 HTTP 打交道,没有进程内耦合。

五道检查

步骤做什么拒绝时
G1 鉴权校验 Authorization: Bearer 令牌401 AUTH_MISSING / AUTH_INVALID
G2 租户从凭据取权威租户,丢弃调用方自报的租户头403 TENANT_UNRESOLVED
G3 参数校验 JSON-RPC 信封、方法、消息结构,绑定 agentIdVALIDATION_*
G4 幂等创建类请求按"租户 + messageId"去重409 冲突
G5 审计通过、拒绝都记一条审计事件审计失败不阻断已通过的请求

G1 → G3 由 GovernancePipeline.run 按固定顺序执行,根路径入口和按智能体分路径的入口共用这一份代码,保证两条入口不会走偏。任一步拒绝,先写审计、再把错误抛出去。

源码GovernancePipeline.runagent-solution/common/agent-bus/agent-gateway/src/main/java/com/openjiuwen/gateway/governance/GovernancePipeline.java:94@bf702bc9

鉴权是 fail-closed:没有配置凭据时,所有请求都返回 401。

租户:只认凭据

String authoritative = principal.tenantId();
if (authoritative == null || authoritative.isBlank()) {
    throw new GovernanceException(HttpStatus.FORBIDDEN, "TENANT_UNRESOLVED", ...);
}
// 自报的租户被有意丢弃,以凭据为准
return authoritative;

节选自源码,省略了错误消息参数,注释改写为中文。

源码TenantResolver.resolveagent-solution/common/agent-bus/agent-gateway/src/main/java/com/openjiuwen/gateway/governance/tenant/TenantResolver.java:37@bf702bc9

这和上一个模块里"租户字段只是标签"呼应:真正可信的租户来自鉴权,不来自请求本身。

幂等:重试不会建出两个任务

网络超时后重发是常态。G4 只对创建类请求(还没有 taskId 的)生效:

情况结果
没带 messageId跳过去重
第一次出现登记为"处理中",继续转发
同键、同内容、已完成回放第一次的结果,不再转发
同键、同内容、还在处理409 IDEMPOTENCY_IN_FLIGHT
同键、内容不同409 IDEMPOTENCY_PAYLOAD_MISMATCH

内容指纹取请求的 params 部分并排序序列化,JSON-RPC 的 id 不算在内,所以客户端重试时换了 id 也能正确回放。创建失败时会释放这个键,允许重试。

源码A2aDispatcher 幂等分支agent-solution/common/agent-bus/agent-gateway/src/main/java/com/openjiuwen/gateway/facade/A2aDispatcher.java:136@bf702bc9
注意

当前幂等记录存在单个网关进程的内存里,源码注释明确说多实例部署需要共享存储,不在本版范围内。生产上多副本部署网关时,要自己补这一块。

读响应:别只看状态码

网关有两种错误形态:

  • 方法级错误:一律 HTTP 200 + JSON-RPC error 信封,比如参数校验失败 -32602
  • 治理错误:根路径入口用非 2xx 状态码 + 统一错误体(401、413、503 等);分路径入口则同样包装成 HTTP 200 + JSON-RPC error

所以接入方判断业务结果,必须解析响应体。

动手:预测网关的处理

模拟器加载中…

小结

  • 网关在智能体前面做五道检查:鉴权、租户、参数、幂等、审计,前三步顺序固定。
  • 租户只认凭据,自报的租户头直接丢弃。
  • 创建类请求按"租户 + messageId"去重:已完成就回放,内容不同就报冲突。
  • 判断成功与否要解析响应体,HTTP 200 不等于业务成功。

源码出处

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

过关测验

  1. 1. 调用方在 X-Tenant-Id 里写了别的租户,网关怎么处理?

  2. 2. 创建类请求的幂等键是什么?

  3. 3. 网关返回 HTTP 200,是否说明业务成功?

通关条件

  • ○ 完成模拟器任务(0/4)
  • ○ 测验全部答对