OmniRoute A2A 服务器接入指南:用 Agent-to-Agent 协议将 AI 网关暴露为智能路由 Agent
2026/9/13 17:59:46 网站建设 项目流程

OmniRoute A2A 服务器接入指南:用 Agent-to-Agent 协议将 AI 网关暴露为智能路由 Agent

【免费下载链接】OmniRouteNever stop coding. Free MIT AI gateway: one endpoint, 352 providers (150+ free), 1200+ models Kimi, Claude, GPT, Gemini, GLM, DeepSeek, MiniMax. Works with Claude Code, Codex, Cursor, OpenCode, Cline & Copilot. Quota-aware auto-fallback, RTK+Caveman compression saves 15-95% tokens, MCP/A2A, Desktop/PWA. Built by 550+ contributors项目地址: https://gitcode.com/GitHub_Trending/om/OmniRoute

OmniRoute 内置 A2A(Agent-to-Agent Protocol v0.3)服务器,将整个 AI 路由网关封装成一个可供其他 Agent 直接调用的"智能路由 Agent"。本文基于 docs/frameworks/A2A-SERVER.md(含其 韩语译本)并结合仓库源码,完整讲解 A2A 端点的发现、认证、JSON-RPC 方法、内置技能、任务生命周期、错误码与多语言调用示例。读完本文,你将能够用curl、Python 或 TypeScript 让任意 Agent 通过 OmniRoute 完成智能路由、配额查询、成本分析等任务。

Agent 发现:读取 Agent Card

任何符合 A2A 协议的客户端,第一步都是通过/.well-known/agent.json发现对端 Agent 的能力。OmniRoute 在默认端口20128上提供该端点:

curl http://localhost:20128/.well-known/agent.json

返回的 Agent Card 描述 OmniRoute 的能力、技能(Skills)和认证要求。该端点由 src/app/.well-known/agent.json/route.ts 动态生成,其中:

  • version字段直接取自process.env.npm_package_version,每次发版自动与package.json保持同步;
  • url指向/a2a(即 JSON-RPC 规范入口);
  • capabilities.streamingtruepushNotificationsfalse,表示当前实现支持流式响应、不支持主动推送;
  • skills数组声明的每个技能都与A2A_SKILL_HANDLERS(见下文"可用技能")一一对应。

此外,A2A 端点还通过OPTIONS请求返回 CORS 头(Access-Control-Allow-Methods: POST, OPTIONS),方便浏览器端 Agent 跨域调用,实现位于 src/app/a2a/route.ts。

认证与开关

Bearer API Key

所有/a2a请求都需要在Authorization头中携带 API Key:

Authorization: Bearer YOUR_OMNIROUTE_API_KEY

认证逻辑集中在 src/lib/a2a/authenticate.ts 的authenticateA2ARequest中,采用与/v1一致的分层策略:

  1. 若开启了强制 API Key(REQUIRE_API_KEY),则必须提供合法 OmniRoute Key;
  2. 否则若设置了OMNIROUTE_API_KEY环境变量,则按该 Key 校验(使用timingSafeEqual恒定时间比较);
  3. 若服务端既未要求也未配置 Key,则跳过认证——这是与/v1相同的"本地优先(local-first)"默认姿态。

同时,resolveA2AOwner会对调用方 API Key 做 SHA-256 哈希(截取前 32 位)作为任务归属标识,用于将任务读写限定到同一调用方(安全加固 GHSA-jcm5-6wpp-wjj8):无 Key 调用创建的任务对所有调用方可见,带 Key 创建的任务仅同 Key 可见。

启用开关

A2A 由Endpoints(端点)→ A2A开关控制,默认关闭。关闭状态下:

  • GET /api/a2a/status返回status: "disabled"online: false(实现见 src/app/api/a2a/status/route.ts);
  • POST /a2a发起 JSON-RPC 调用会收到 HTTP 503 与 JSON-RPC 错误码-32000("A2A endpoint is disabled"),该判断依据设置项settings.a2aEnabled,见 src/app/a2a/route.ts 中的rejectIfA2ADisabled

JSON-RPC 2.0 方法

A2A 规范入口是POST /a2a,统一使用 JSON-RPC 2.0 信封(jsonrpc: "2.0"+id+method+params)。路由层还内置了 A2A 1.0 兼容层:1.0 客户端使用的方法名SendMessageSendStreamingMessage会被自动映射到message/sendmessage/stream,响应也会被重塑为 1.0 的task.status.message.parts[].text结构,因此 a2a-sdk 1.x 等新老客户端可以无改动调用。

message/send—— 同步执行

向某个技能发送消息并等待完整响应:

curl -X POST http://localhost:20128/a2a \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_KEY" \ -d '{ "jsonrpc": "2.0", "id": "1", "method": "message/send", "params": { "skill": "smart-routing", "messages": [{"role": "user", "content": "Write a hello world in Python"}], "metadata": {"model": "auto", "combo": "fast-coding"} } }'

其中params支持三种消息形态:messages数组、单个message.content字符串,以及兼容旧版的message.parts数组(toMessageArray会统一归一化)。metadata可按技能透传额外参数(如modelcombobudget)。

响应:

{ "jsonrpc": "2.0", "id": "1", "result": { "task": { "id": "uuid", "state": "completed" }, "artifacts": [{ "type": "text", "content": "..." }], "metadata": { "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)", "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" }, "resilience_trace": [ { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." } ], "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" } } } }

从源码看(src/lib/a2a/skills/smartRouting.ts),smart-routing技能会把请求转发给网关自身的/v1/chat/completions(内部通过resolveOmniRouteBaseUrl()解析回环地址,携带OMNIROUTE_API_KEY,30 秒超时),随后组装出四段可观测元数据:

  • routing_explanation:实际选中的模型、提供者、延迟与成本;
  • cost_envelope:估算成本与真实成本(USD);
  • resilience_trace:主提供者选择及是否触发过备选回退;
  • policy_verdict:预算/配额策略裁决结果(metadata.budget用于设置预算上限)。

执行成功后,若技能为smart-routing,路由层还会把结果写入logRoutingDecision(路由决策日志),供控制台回放与统计。

message/stream—— SSE 流式执行

message/send相同,但通过 Server-Sent Events 实时返回增量结果:

curl -N -X POST http://localhost:20128/a2a \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_KEY" \ -d '{ "jsonrpc": "2.0", "id": "1", "method": "message/stream", "params": { "skill": "smart-routing", "messages": [{"role": "user", "content": "Explain quantum computing"}] } }'

SSE 事件流:

data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}} : heartbeat 2026-03-03T17:00:00Z data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}}

流式实现见 src/lib/a2a/streaming.ts:

  • 每 15 秒发送一次: heartbeat注释行保活(Nginx 等反代可配合X-Accel-Buffering: no头关闭缓冲);
  • 技能结果被拆成若干chunk事件(当前为对完整 artifacts 的模拟流式输出),最后发送携带metadatacompleted事件;
  • 支持通过req.signalAbortSignal中断连接,中断时发送failed事件;
  • 流开始/结束时调用beginStream/endStream更新任务管理器的活跃流计数。

tasks/get—— 查询任务状态

curl -X POST http://localhost:20128/a2a \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_KEY" \ -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}'

返回result.task(含状态、事件日志、artifacts)。若任务已过期且仍处于非终态,会先被标记为failed("Task expired"),见 src/lib/a2a/taskManager.ts 的getTask

tasks/cancel—— 取消任务

curl -X POST http://localhost:20128/a2a \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_KEY" \ -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}'

取消前会先做归属校验(不是自己的任务按"不存在"处理,避免 IDOR 探测),随后将任务置为cancelled("Cancelled by client")。

可用技能

OmniRoute 目前向 A2A 客户端暴露 6 个技能,全部注册在 src/lib/a2a/taskExecution.ts 的A2A_SKILL_HANDLERS中,每个技能模块位于 src/lib/a2a/skills/:

技能ID说明
Smart Routingsmart-routing通过 OmniRoute 的组合引擎与评分,将提示词路由到最优提供者/组合,返回路由解释、成本与韧性追踪
Quota Managementquota-management报告各提供者的配额状态,帮助调用方决定何时限流或切换提供者
Provider Discoveryprovider-discovery列出已安装提供者及其能力、免费层标记、OAuth 状态
Cost Analysiscost-analysis基于目录与近期用量估算单次请求/会话成本
Health Reporthealth-report聚合各提供者的熔断器、冷却、锁定状态
List Capabilitieslist-capabilities返回完整的 Agent Skills 目录(当前 45 项:23 API + 21 CLI + 1 配置),输出 Markdown 表格并附带原始 SKILL.md 链接

其中smart-routingquota-management是文档重点演示的两个技能,前者负责"把提示词路由给最优模型"(支持基于优先级、加权、轮询、成本优化等策略的组合路由),后者支持用自然语言查询各提供者配额、建议免费组合与配额排名。

Agent Card 应始终与运行时提供者目录保持一致:提供者数量、免费/免认证元数据均来自运行时注册表(registry),而非硬编码。

list-capabilities技能详解

list-capabilities对需要先探测 OmniRoute 能力再发请求的外部 Agent 尤其有用。它返回结构化的 Markdown 表格 artifact:

| ID | Name | Category | Area | Endpoints/Commands | Raw URL | | --- | --- | --- | --- | --- | --- | | omni-auth | Auth & Sessions | api | auth | POST /api/auth/login, ... | https://raw.githubusercontent.com/... | ...

每行包含rawUrl列,Agent 可立即抓取完整的 SKILL.md;metadata.totalSkills字段镜像目录大小(当前 45)。实现位于 src/lib/a2a/skills/listCapabilities.ts,与 AGENT-SKILLS.md 保持同步。

REST 辅助接口

POST /a2a是 A2A 的规范入口,除此之外还有一组供仪表盘与外部工具使用的 REST 辅助端点:

端点方法说明认证
/api/a2a/statusGET服务器状态、已注册技能公开
/api/a2a/tasksGET带过滤条件的任务列表management
/api/a2a/tasks/[id]GET按 ID 查询任务management
/api/a2a/tasks/[id]/cancelPOST取消运行中的任务management
/.well-known/agent.jsonGETAgent Card(A2A 发现,公开缓存 3600s)公开
/api/a2a/tasksPOST入站委托给 OmniConductor 集群(Conductor PRD RF5)BearerOMNIROUTE_API_KEY+a2aEnabled

其中POST /api/a2a/tasks用于外部 A2A Agent 把编码类工作委托给 OmniConductor 集群:请求体形如{ skill: "conductor" | "conductor-cli-<profile>", messages: [{role, content}], metadata: { conductor: { repo: { url, base_ref? }, mode?, cli?, model? } } },仅 Agent Card 上宣告的 Conductor 集群技能可被委托,且metadata.conductor.repo.url必填;路由层会使用服务端CONDUCTOR_ORCHESTRATOR_TOKEN(备选CONDUCTOR_HUB_TOKEN)转发到 Hub 的POST /v1/tasks,返回201 { conductor_task_id, state: "submitted" }

任务生命周期与 TTL

A2ATaskManager(src/lib/a2a/taskManager.ts)负责任务的完整生命周期管理:

submitted → working → completed → failed → cancelled
  • 任务默认 5 分钟过期(TTL 可配置,见下);
  • 终态为completedfailedcancelled
  • 每次状态迁移都会追加到事件日志(events数组),并同步持久化到 SQLite 历史表(upsertA2ATask/appendA2ATaskEvent,失败时静默降级,内存 Map 仍是活任务的唯一事实来源);
  • 状态迁移受VALID_TRANSITIONS约束,非法迁移直接抛错;
  • 后台定时器每 60 秒清扫过期任务:非终态过期任务置为failed("TTL expired"),终态任务在超过 2 倍 TTL 后从内存移除;
  • 历史表保留天数由环境变量OMNIROUTE_A2A_HISTORY_RETENTION_DAYS控制,默认 30 天,清扫节流为每 24 小时至多一次;
  • 并发流由activeStreams计数跟踪,可通过getStats()观测。

自定义 TTL

默认 TTL 为 5 分钟,在A2ATaskManager构造函数处配置。如需调整,可自行 fork 实例化逻辑并传入不同值,例如new A2ATaskManager(15)得到 15 分钟 TTL。框架默认通过全局单例getTaskManager()提供 5 分钟实例,cleanupIntervalunref(),不会阻塞进程退出。

错误码

A2A 端点遵循 JSON-RPC 2.0 标准错误码约定:

代码含义
-32700解析错误(JSON 无效)
-32600无效请求 / 未授权
-32601方法或技能不存在
-32602参数无效
-32603内部错误(技能执行失败)
-32000A2A 端点已禁用

HTTP 状态码与错误码的映射:-32600→ 400,-32601→ 404,-32603→ 500,其余返回 200(错误信息在 JSON-RPCerror字段中)。

集成示例

Python(requests)

import requests resp = requests.post("http://localhost:20128/a2a", json={ "jsonrpc": "2.0", "id": "1", "method": "message/send", "params": { "skill": "smart-routing", "messages": [{"role": "user", "content": "Hello"}] } }, headers={"Authorization": "Bearer YOUR_KEY"}) result = resp.json()["result"] print(result["artifacts"][0]["content"]) print(result["metadata"]["routing_explanation"])

TypeScript(fetch)

const resp = await fetch("http://localhost:20128/a2a", { method: "POST", headers: { "Content-Type": "application/json", Authorization: "Bearer YOUR_KEY", }, body: JSON.stringify({ jsonrpc: "2.0", id: "1", method: "message/send", params: { skill: "smart-routing", messages: [{ role: "user", content: "Hello" }], }, }), }); const { result } = await resp.json(); console.log(result.metadata.routing_explanation);

扩展:如何新增一个技能

A2A 技能的扩展遵循固定流程(与A2A_SKILL_HANDLERS的模式一致):

  1. 创建技能文件:在src/lib/a2a/skills/下新建<your-skill>.ts,导出一个async (task: A2ATask) => Promise<{ artifacts, metadata }>函数,参考现有smartRouting.ts的形状;

  2. 注册处理器:在src/lib/a2a/taskExecution.tsA2A_SKILL_HANDLERS中追加条目:

    export const A2A_SKILL_HANDLERS = { // ...existing skills "your-skill": async (task) => { const skillModule = await import("./skills/yourSkill"); return skillModule.executeYourSkill(task); }, };
  3. 暴露到 Agent Card:在src/app/.well-known/agent.json/route.tsskills数组追加声明(含idnamedescriptiontagsexamples);

  4. 编写测试:在tests/unit/下新增a2a-<your-skill>.test.ts,覆盖成功路径与错误路径;

  5. 更新文档:将新技能补入本文档的可用技能表。

小结

OmniRoute 的 A2A 服务器以 JSON-RPC 2.0 为规范入口、Agent Card 为发现机制,让任何 A2A 客户端都能通过 Bearer Key 调用smart-routingquota-managementprovider-discoverycost-analysishealth-reportlist-capabilities六个技能,从而获得智能路由、配额洞察与健康巡检能力。任务由A2ATaskManager统一管理生命周期(5 分钟 TTL、终态事件日志、SQLite 历史持久化),配合 REST 辅助端点与 A2A 1.0 兼容层,可平滑嵌入现有 Agent 生态。相关实现可继续深入阅读 src/app/a2a/route.ts、src/lib/a2a/taskManager.ts、src/lib/a2a/taskExecution.ts 与 AGENT-SKILLS.md。

【免费下载链接】OmniRouteNever stop coding. Free MIT AI gateway: one endpoint, 352 providers (150+ free), 1200+ models Kimi, Claude, GPT, Gemini, GLM, DeepSeek, MiniMax. Works with Claude Code, Codex, Cursor, OpenCode, Cline & Copilot. Quota-aware auto-fallback, RTK+Caveman compression saves 15-95% tokens, MCP/A2A, Desktop/PWA. Built by 550+ contributors项目地址: https://gitcode.com/GitHub_Trending/om/OmniRoute

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询