
OmniRoute A2A Server 实战指南以 JSON-RPC 2.0 将智能路由网关接入 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, RTKCaveman compression saves 15-95% tokens, MCP/A2A, Desktop/PWA. Built by 550 contributors项目地址: https://gitcode.com/GitHub_Trending/om/OmniRouteOmniRoute 将自身封装为一个符合Agent-to-Agent Protocol v0.3的智能路由 Agent外部 Agent 可以通过POST /a2a的 JSON-RPC 2.0 接口调用 OmniRoute 的智能路由、配额管理、成本分析等能力而无需直接面对数百个上游 Provider 的差异。读完本文你将掌握 A2A 端点的发现机制、认证方式、四大 JSON-RPC 方法、六大 Skill 的调用形态以及任务生命周期、错误码、REST 辅助接口与 Python/TypeScript 两种集成写法并可据此把 OmniRoute 接入自己的 Agent 编排系统。本指南以仓库内 docs/frameworks/A2A-SERVER.md含 波斯语翻译版为核心骨架并结合src/app/a2a/route.ts、src/lib/a2a/taskManager.ts、src/lib/a2a/skills/smartRouting.ts等源码实现为你逐层拆解协议背后的真实代码逻辑。双面孔JSON-RPC 主入口与 REST 辅助接口A2A 表面surface在 OmniRoute 中有两个入口JSON-RPC 2.0POST /a2a协议的标准入口点处理message/send、message/stream、tasks/get、tasks/cancel四个方法实现在 src/app/a2a/route.ts。REST/api/a2a/*路径面向仪表盘与外部工具提供状态查询、任务列表、取消任务等辅助能力。任务由A2ATaskManager统一管理src/lib/a2a/taskManager.ts默认 5 分钟 TTLSkill 分发通过 src/lib/a2a/taskExecution.ts 中的A2A_SKILL_HANDLERS注册表完成每个 Skill 模块位于src/lib/a2a/skills/目录下。Agent Discovery向其他 Agent 展示能力清单按照 A2A 协议客户端首先通过标准发现端点获取 Agent Cardcurl http://localhost:20128/.well-known/agent.json返回的 Agent Card 描述了 OmniRoute 的能力capabilities、技能skills与认证要求。需要特别指出的是这份卡片是动态生成的name、description、url指向${baseUrl}/a2a与 6 个 Skill 条目由 src/app/.well-known/agent.json/route.ts 构造version字段取自process.env.npm_package_versionroute.ts#L17因此每次发版时自动与package.json保持同步无需手工维护capabilities.streaming: true向对端宣告本 Agent 支持流式响应若配置了 OmniConductor 编排中枢卡片还会附带 fleet skills 列表未配置时该段为空数组卡片依然有效。注意该端点响应带 3600 秒缓存Cache-Control缓存时间外部 Agent 无需高频刷新发现信息。认证Bearer Token 与 keyless 本地优先所有/a2a请求都要求通过Authorization头携带 API KeyAuthorization: Bearer YOUR_OMNIROUTE_API_KEY实际的认证判定逻辑在 src/lib/a2a/authenticate.ts 的authenticateA2ARequest中按优先级依次是REQUIRE_API_KEY姿态与/v1通道一致若开启了该特性则请求必须携带有效 Key显式配置的OMNIROUTE_API_KEY存在该环境变量时用恒定时间比较timingSafeEqual校验请求头中的 Key 是否与之相等keyless 本地优先两者都未启用时直接放行——即文档所述如果服务器未配置 API Key则认证被跳过。这是与/v1通道相同的默认行为local-first posture。同一个模块还提供resolveA2AOwnerauthenticate.ts#L49-L52对调用方的 API Key 取 SHA-256 哈希的前 32 个字符作为任务归属者 ID。任务创建者拥有该 owner 后其任务仅对该 owner 可见、可查、可取消对应安全通告 GHSA-jcm5-6wpp-wjj8 的修复而 keyless 场景下创建的 ownerless 任务对所有调用方保持可见。启用 A2A 端点默认关闭A2A 由Endpoints → A2A页面开关控制默认禁用。未启用时GET /api/a2a/status返回status: disabled且online: false对POST /a2a的 JSON-RPC 调用返回HTTP 503JSON-RPC 错误码为-32000A2A endpoint is disabled对应 src/app/a2a/route.ts 中rejectIfA2ADisabled的实现读数据库设置a2aEnabled非true即拒绝。而GET /api/a2a/status在启用时还会额外返回任务统计tasks、Agent Card 摘要agent与技能数组skills便于仪表盘一屏掌握 A2A 运行状态见 src/app/api/a2a/status/route.ts。JSON-RPC 2.0 方法详解所有方法统一 POST 到http://localhost:20128/a2a请求体遵循 JSON-RPC 2.0 规范。/a2a路由还实现了A2A v1.0 ↔ v0.3 兼容层route.ts#L21-L76v1.0 客户端使用的方法名SendMessage、SendStreamingMessage会被自动别名到 v0.3 方法同步响应的形状也会被重塑为 v1.0 的task.status.message.parts[]结构因此 a2a-sdk 1.x、Hermes 等 v1.0 客户端可以原样调用端点v0.3 客户端不受影响。message/send— 同步执行发送一条消息给指定 Skill并等待完整响应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} } }响应结构{ 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 } } } }metadata是smart-routing的核心价值所在它不仅返回生成内容还附带路由解释选了哪个模型、哪个 Provider、延迟与成本、成本信封预估 vs 实际USD、韧性轨迹主选、回退等事件序列与策略裁决是否在预算与配额限制内。从源码看executeSmartRoutingsrc/lib/a2a/skills/smartRouting.ts#L35-L88的内部流程是将请求转发到 OmniRoute 自身的/v1/chat/completions带 30 秒超时随后组装上述元数据——routing_explanation基于响应中的model与provider字段拼接resilience_trace在响应带fallbacksTriggered时追加fallback_needed事件policy_verdict则对比metadata.budget与实际成本给出裁决。请求方还可以通过metadata.model、metadata.combo显式指定模型与组合策略。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 事件序列依次为 chunk、heartbeat、completiondata: {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 秒发送一次心跳注释行createHeartbeat保持连接存活Skill 执行期间结果按 artifact 逐个以chunk事件发出createChunkEvent任务状态为working完成后发送携带metadata的completed事件createCompletionEvent若请求被中止或执行抛错分别发送failed事件createFailureEvent响应头通过SSE_HEADERS设置为text/event-stream、Cache-Control: no-cache, no-transform、Connection: keep-alive、X-Accel-Buffering: nostreaming.ts#L79-L84后者用于规避反向代理缓冲。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}}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}}两个方法在路由中的实现都做了 owner 作用域校验route.ts#L297-L319任务不属于当前调用方时cancelTask抛出的错误信息与任务不存在完全一致避免 IDOR 探测区分存在但不属于你与不存在。可用 Skills六大能力一览OmniRoute 暴露 6 个 A2A Skill全部在 src/lib/a2a/taskExecution.ts 的A2A_SKILL_HANDLERS中注册每个 Skill 模块位于src/lib/a2a/skills/SkillID说明Tags调用示例Smart Routingsmart-routing使用组合引擎 评分将提示词路由到最优 Provider/组合routing, providersRoute this prompt via the best modelQuota Managementquota-management报告各 Provider 配额状态帮助调用方决定何时限流/切换quota, providersCheck quota for anthropicProvider Discoveryprovider-discovery列出已安装 Provider 及其能力、免费额度标志、OAuth 状态providers, discoveryWhat providers are available?Cost Analysiscost-analysis结合目录与近期用量估算单次请求/对话的成本cost, usageEstimate cost for this conversationHealth Reporthealth-report聚合每个 Provider 的熔断器、冷却、锁定状态health, resilienceShow health status of all providersList Capabilitieslist-capabilities以 Markdown 表格返回完整的 Agent Skills 目录23 API 21 CLI 1 config附 SKILL.md 原始 URLcatalog, discovery, skillsList all OmniRoute capabilities其中list-capabilities对外部 Agent 尤其有用它返回结构化表格工件每行包含ID | Name | Category | Area | Endpoints/Commands | Raw URLrawUrl列让 Agent 可以立即抓取完整 SKILL.md 用于上下文注入metadata.totalSkills字段镜像目录规模当前为 45。实现见 src/lib/a2a/skills/listCapabilities.ts可进一步参考 AGENT-SKILLS.md。以quota-management为例src/lib/a2a/skills/quotaManagement.ts它并行请求/api/usage/quota与/api/combos10 秒超时归一化配额数据后根据自然语言查询中的关键词分类处理——包含 ranking/most quota/best 时按可用配额排序其余场景则解析具体 Provider 并返回配额明细与免费组合建议。任务生命周期与 TTLsubmitted → working → completed → failed → cancelled任务默认5 分钟过期可配置终态为completed、failed、cancelled每次状态迁移都会被事件日志记录。A2ATaskManagersrc/lib/a2a/taskManager.ts的底层细节TTL构造器参数ttlMinutes默认 5taskManager.ts#L139任务创建时写入expiresAt。若要自定义可 forkA2ATaskManager实例化并传入不同值例如new A2ATaskManager(15)即 15 分钟 TTL。后台每60 秒扫描一次过期任务cleanupExpired未进入终态的任务标记为failedTTL expired终态任务在超过 2 倍 TTL 后被移出内存 Map状态机校验VALID_TRANSITIONS定义了合法迁移taskManager.ts#L121-L127非法迁移会直接抛错持久化每次迁移通过persist写入历史表best-effortSQLite 不可用时仅记录警告内存 Map 仍是活跃任务的权威来源历史行按OMNIROUTE_A2A_HISTORY_RETENTION_DAYS默认 30 天保留清理节流为每 24 小时最多一次事件总线每次迁移同时向事件总线发出agent.task.updatedsource 标记为a2a供编排画布等监听方使用且监听器异常不会破坏任务写入路径并发统计beginStream/endStream维护活跃流计数getStats返回按状态分组的计数与最近任务时间。另外任务执行前会做一次纯可观测性的记忆命中收集collectMemoryHits见 taskExecution.ts#L69-L101以最后一条 user 消息为查询检索记忆后端命中结果仅镜像到task.metadata.memoryHits与memory_hits历史事件绝不注入 Skill 的提示词可通过环境变量OMNIROUTE_A2A_MEMORY_HITS0关闭该查询。错误码Code含义-32700解析错误非法 JSON-32600无效请求 / 未授权-32601方法或 Skill 不存在-32602参数无效-32603内部错误-32000A2A 端点未启用HTTP 状态映射遵循 route.ts#L136-L141 的规则-32600→ 400-32601→ 404-32603→ 500其余 → 200。REST 辅助接口JSON-RPC 端点/a2a是标准入口以下 REST 端点供仪表盘与外部工具使用EndpointMethod说明认证/api/a2a/statusGET服务器状态、已注册 Skill公开/api/a2a/tasksGET带过滤条件列出任务management/api/a2a/tasks/[id]GET按 ID 获取任务management/api/a2a/tasks/[id]/cancelPOST取消运行中的任务management/.well-known/agent.jsonGETAgent CardA2A 发现公开且缓存 3600s公开/api/a2a/tasksPOST入站委派到 OmniConductor 编排集群BearerOMNIROUTE_API_KEYa2aEnabled其中Conductor 入站委派POST /api/a2a/tasks允许外部 A2A Agent 通过 OmniRoute 把编码工作委派给 OmniConductor 集群请求体为{ skill: conductor | conductor-cli-profile, messages: [{role, content}], metadata: { conductor: { repo: { url, base_ref? }, mode?, cli?, model? } } }——仅 Agent Card 上公布的 Conductor fleet skills 可委派且metadata.conductor.repo.url必填集群在 git 仓库上工作。路由使用服务端CONDUCTOR_ORCHESTRATOR_TOKEN回退CONDUCTOR_HUB_TOKEN翻译到中枢的POST /v1/tasks返回201 { conductor_task_id, state: submitted }任务状态通过 SSE→A2A 镜像流回并可通过GET /api/a2a/tasks?skillconductor查看。集成示例两种语言一分钟接入Pythonrequestsimport 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])TypeScriptfetchconst 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);扩展如何添加一个新 Skill若你需要让外部 Agent 获得 OmniRoute 的更多能力可按下述步骤源于主文档路径均为仓库真实位置创建 Skill 文件src/lib/a2a/skills/your-skill.ts导出一个异步函数(task: A2ATask) Promise{ artifacts, metadata }参考smartRouting.ts的既有形态注册处理器在src/lib/a2a/taskExecution.ts的A2A_SKILL_HANDLERS中加入条目例如export const A2A_SKILL_HANDLERS { // ...existing skills your-skill: async (task) { const skillModule await import(./skills/yourSkill); return skillModule.executeYourSkill(task); }, };在 Agent Card 中暴露在src/app/.well-known/agent.json/route.ts的skills数组中追加{ id: your-skill, name: Your Skill, description: Brief, intent-focused description, tags: [routing, quota], examples: [Sample natural-language invocation] }编写测试tests/unit/a2a-your-skill.test.ts覆盖正常路径与错误路径文档化在主文档Available Skills表格中登记新 Skill。小结从协议到代码的完整链路OmniRoute 的 A2A Server 是一套完整、可观测的 Agent 间通信表面/.well-known/agent.json负责发现Bearer Token 负责鉴权POST /a2a承载 JSON-RPC 2.0 四大方法A2ATaskManager负责任务生命周期与 TTL 清理A2A_SKILL_HANDLERS负责 Skill 分发REST 辅助接口服务仪表盘与外部工具而 v0.3/v1.0 兼容层保证了新旧客户端均可直接接入。外部 Agent 通过smart-routing获得路由解释 成本信封 韧性轨迹 策略裁决四重元数据将路由决策从黑盒变成可审计的透明过程——这正是 A2A 场景下OmniRoute 作为智能路由 Agent的核心价值。进一步探索完整的协议文档见 docs/frameworks/A2A-SERVER.mdAgent 技能体系见 docs/frameworks/AGENT-SKILLS.mdA2A 与 MCP 的对照关系可参考 docs/frameworks/MCP-SERVER.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, RTKCaveman compression saves 15-95% tokens, MCP/A2A, Desktop/PWA. Built by 550 contributors项目地址: https://gitcode.com/GitHub_Trending/om/OmniRoute创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考