
OmniRoute A2A Server 接入指南基于 Agent-to-Agent 协议的智能路由 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-AgentA2A协议 v0.3 的形式将自身的智能路由能力开放为可被任何 AI Agent 调用的标准化服务通过POST /a2a上的 JSON-RPC 2.0 接口外部 Agent 可以执行提示词路由、配额查询、成本估算、健康巡检与能力发现等技能。阅读本文后你将掌握 A2A Server 的启用方式、认证模型、四大 JSON-RPC 方法、六个内置技能、任务生命周期与错误码约定并能通过 curl、Python 与 TypeScript 三种方式完成端到端集成。一、A2A 服务总览一个入口两种表面从源码结构看OmniRoute 的 A2A 表面由两个互补的部分构成详见 英文主文档JSON-RPC 2.0入口为POST /a2a是面向 Agent 的规范入口其实现位于 src/app/a2a/route.ts。它承载message/send、message/stream、tasks/get、tasks/cancel四个方法并负责技能分派与任务状态管理。REST挂载于/api/a2a/*面向仪表盘与外部工具提供状态查询、任务列表、任务详情、取消等辅助能力。任务由A2ATaskManager统一管理src/lib/a2a/taskManager.ts默认 5 分钟 TTL技能通过 src/lib/a2a/taskExecution.ts 中的A2A_SKILL_HANDLERS注册表进行动态分派。整条链路贯彻任务有状态、路由可解释、策略可审计的设计理念。二、快速启用发现端点与开关控制2.1 启用 A2AA2A 默认是关闭的由Endpoints → A2A开关控制。当开关关闭时GET /api/a2a/status返回status: disabled与online: false所有对POST /a2a的 JSON-RPC 调用返回HTTP 503并附带 JSON-RPC 错误码-32000A2A endpoint is disabled。该开关对应的运行时检查位于 src/app/a2a/route.ts 的rejectIfA2ADisabled它读取settings.a2aEnabled同样的禁用即拒绝逻辑也应用在 REST 任务路由上。启用后即可开始调用。2.2 Agent 发现Agent DiscoveryA2A 协议要求 Agent 先获取目标服务的 Agent CardOmniRoute 将其暴露在标准位置curl http://localhost:20128/.well-known/agent.json返回的 Agent Card 描述 OmniRoute 的能力、技能列表与认证要求。值得注意的是Agent Card 中的version字段直接取自process.env.npm_package_version见 src/app/.well-known/agent.json/route.ts 第 13 行因此每次发布都会与package.json自动保持同步不会出现文档版本与运行版本漂移。该端点公开可访问并带有 3600 秒的缓存头。三、认证模型Bearer Token 与三种姿势所有/a2a请求都要求通过Authorization请求头携带 API KeyAuthorization: Bearer YOUR_OMNIROUTE_API_KEY认证逻辑集中在 src/lib/a2a/authenticate.ts 的authenticateA2ARequestJSON-RPC 与 REST 两条表面共享同一实现避免二者再次出现安全姿态漂移。其判定顺序为若启用了REQUIRE_API_KEY与/v1管线一致的强制模式请求必须携带有效的 OmniRoute API Key否则拒绝若未启用强制模式但配置了OMNIROUTE_API_KEY环境变量进行常量时间比较timingSafeEqual防止时序侧信道若既未强制也未配置任何 Key认证被旁路采用无密钥本地优先keyless local-first姿态允许访问——这也是开箱即用的默认行为。此外src/lib/a2a/authenticate.ts 的resolveA2AOwner会基于调用方 API Key 的 SHA-256 前 32 位哈希生成稳定的 owner 标识用于任务可见性隔离对应安全通告 GHSA-jcm5-6wpp-wjj8带 owner 的任务仅对同一 owner 可见无密钥姿态下创建的任务保持全量可见。四、JSON-RPC 2.0 方法详解所有方法统一 POST 到http://localhost:20128/a2a请求体遵循 JSON-RPC 2.0 规范jsonrpc: 2.0、id、method、params。路由的完整解析、参数校验与错误映射见 src/app/a2a/route.ts。4.1message/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} } }响应结构{ 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 } } } }参数细节结合源码确认skill技能 ID缺省时回退为smart-routing见 src/app/a2a/route.tsmessages消息数组也兼容 A2A 规范的单对象形式{ message: { role, content } }以及旧版{ message: { parts: [...] } }toMessageArray统一归一化src/app/a2a/route.tsmetadata.model目标模型缺省为auto交由路由引擎决策metadata.combo可选指定组合comboID会以x-combo请求头透传给/v1/chat/completions见 src/lib/a2a/skills/smartRouting.tsmetadata.budget可选预算上限USDpolicy_verdict.allowed会依据实际成本与预算的比较结果给出判定。源码级的执行流水线src/app/a2a/route.ts为createTask创建submitted状态任务 →updateTask置为working→ 调用A2A_SKILL_HANDLERS[skill]处理器 → 成功则置为completed并写入 artifacts失败则置为failed并返回-32603。若技能为smart-routing还会调用 src/lib/a2a/routingLogger.ts 记录路由决策日志任务类型、combo、选中 provider、模型、成本等。4.2message/stream— SSE 流式响应与message/send参数一致但返回 Server-Sent EventsSSE实现实时流式输出适合延迟敏感或需要逐步呈现的场景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:{...}}}SSE 事件序列化与头信息定义在 src/lib/a2a/streaming.ts流开启后每15 秒发送一条: heartbeat注释行保持连接存活正文按 chunk 逐个推送working状态事件最后以携带metadata的completed或异常时的failed事件收尾响应头包含Content-Type: text/event-stream、Cache-Control: no-cache, no-transform与X-Accel-Buffering: no防止反向代理缓冲。流式执行经由executeA2ATaskWithState包装src/lib/a2a/taskExecution.ts同一状态机在流式路径下同样生效。4.3tasks/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}}params.taskId兼容params.id必填任务不存在或不属于当前 owner 时返回-32601。查询时若发现任务已过期且仍处于非终态会先将其标记为failed原因Task expired再返回最新状态见 src/lib/a2a/taskManager.ts。4.4tasks/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 可见性检查先校验再变更防止越权取消他人的任务IDOR 探测无法区分不存在与不属于你成功后任务进入cancelled终态。兼容性说明路由层还内置了A2A v1.0 ↔ v0.3 兼容层src/app/a2a/route.ts将 1.0 的方法名SendMessage/SendStreamingMessage别名到 0.3 方法并把同步响应重组为 1.0 客户端期望的task.status.message.parts[].text形状。使用 a2a-sdk 1.x 或 Hermes 等 1.0 客户端的调用方可以不改代码直接接入。五、内置技能Available SkillsOmniRoute 目前向 Agent 暴露 6 个 A2A 技能全部在 src/lib/a2a/taskExecution.ts 的A2A_SKILL_HANDLERS中注册每个技能模块位于 src/lib/a2a/skills/SkillID说明Tags示例Smart Routingsmart-routing通过 OmniRoute 的组合引擎 打分机制将提示词路由到最优 provider/combo并返回路由解释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 原始 URL 供上下文注入catalog, discovery, skillsList all OmniRoute capabilities以最常用的smart-routing为例其执行逻辑src/lib/a2a/skills/smartRouting.ts为读取任务消息与model/combo/budget元数据 → 携带 30 秒超时的AbortSignal请求 OmniRoute 自身的/v1/chat/completionsx-combo头透传 combo→ 从响应中提取模型、provider、实际成本、token 用量 → 组装四元元数据routing_explanation形如Selected claude-sonnet via provider anthropic (latency: 1200ms, cost: $0.0030)的人类可读路由解释cost_envelope{ estimated, actual, currency: USD }estimated 按输入 token 数 × $3.0/M 粗略估算resilience_trace事件数组记录primary_selected若响应带有fallbacksTriggered则追加fallback_neededpolicy_verdict预算策略裁决allowed依据actualCost budget未传 budget 时视为放行。list-capabilities对希望先发现再调用的外部 Agent 尤其有用它返回带| ID | Name | Category | Area | Endpoints/Commands | Raw URL |表头的 Markdown 表格每行包含rawUrl列供 Agent 直接拉取完整 SKILL.mdmetadata.totalSkills镜像目录规模当前 45 项实现见 src/lib/a2a/skills/listCapabilities.ts。完整的技能目录概念可参阅 AGENT-SKILLS.md。六、REST 辅助接口POST /a2a是规范的 A2A 入口此外/api/a2a/*提供面向仪表盘与外部工具的管理接口EndpointMethod说明认证/api/a2a/statusGET服务器状态、已注册技能公开/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 舰队Bearer 或OMNIROUTE_API_KEYa2aEnabled任务列表接口src/app/api/a2a/tasks/route.ts支持statesubmitted/working/completed/failed/cancelled五态白名单校验、skill、limit1–200默认 50、offset过滤并按创建时间倒序返回{ tasks, total, limit, offset }。入站 Conductor 委派POST /api/a2a/tasks同时支持将外部 Agent 的编码任务委派给 OmniConductor 舰队Conductor PRD RF5。请求体形如{ skill: conductor | conductor-cli-profile, messages: [{role, content}], metadata: { conductor: { repo: { url, base_ref? }, mode?, cli?, model? } } }其中metadata.conductor.repo.url为必填舰队在 git 仓库上工作仅 Agent Card 上公布的 Conductor 舰队技能可被委派路由借助服务端CONDUCTOR_ORCHESTRATOR_TOKEN回退CONDUCTOR_HUB_TOKEN转发到 hub 的POST /v1/tasks返回201 { conductor_task_id, state: submitted }任务状态经 SSE→A2A 镜像回流可通过GET /api/a2a/tasks?skillconductor观察。七、任务生命周期与 TTL7.1 状态机submitted → working → completed → failed → cancelled状态转换在白名单VALID_TRANSITIONSsrc/lib/a2a/taskManager.ts中显式声明submitted可转向working/failed/cancelledworking可转向三个终态终态不可再迁移非法迁移会抛出异常。每次迁移都会向任务的events事件日志追加一条{ timestamp, state, message? }记录事件日志完整追踪每一次状态变迁通过事件总线发布agent.task.updated供编排画布消费监听器抛错不会中断任务写入路径尽力而为地持久化到 SQLite 历史表src/lib/db/a2aTasks.ts失败仅告警不阻断内存态。7.2 TTL 与历史保留任务在expiresAt后过期默认5 分钟在A2ATaskManager构造函数中配置src/lib/a2a/taskManager.ts参数ttlMinutes 5。需要自定义时可 forkA2ATaskManager的实例化并传入不同值例如new A2ATaskManager(15)即为 15 分钟 TTL。后台定时器每60 秒清扫一次将非终态过期任务置为failed原因TTL expired并将已处于终态超过 2×TTL 的任务从内存中移除。历史表按OMNIROUTE_A2A_HISTORY_RETENTION_DAYS环境变量保留默认 30 天每日最多清理一次。7.3 可观测性细节执行包装器executeA2ATaskWithState还会进行记忆命中收集仅观测用途绝不注入提示词以任务最后一条role user消息为查询向记忆后端检索最多 5 条记忆将key/type/200 字符截断摘要写入task.metadata.memoryHits并落一条memory_hits历史事件通过OMNIROUTE_A2A_MEMORY_HITS0可一键关闭该路径见 src/lib/a2a/taskExecution.ts。八、错误码约定Code含义-32700解析错误无效 JSON-32600无效请求 / 未授权-32601方法或技能不存在-32602参数无效-32603内部错误-32000A2A 端点已禁用除 JSON-RPC 错误码外HTTP 状态也有明确映射见 src/app/a2a/route.ts-32600→ 400-32601→ 404-32603→ 500-32000→ 503其余为 200。参数缺失的典型场景如messages与message.content均未提供返回-32602并附中文友好的提示文案。九、端到端集成示例9.1 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])9.2 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);两份示例中result.artifacts[0].content是技能生成的正文result.metadata.routing_explanation则是路由决策解释——外部 Agent 可以把它作为可审计的路由证据透传给最终用户。十、扩展如何新增一个技能A2A 的技能体系是开放可扩展的遵循以下五步即可挂载新技能详见 英文主文档 的 Adding a New 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, name, description, tags, examples }其中description需以意图为中心撰写便于外部 Agent 理解调用时机编写测试tests/unit/a2a-your-skill.test.ts覆盖正常路径与错误路径仓库现有测试如tests/unit/a2a-route-require-api-key.test.ts、tests/unit/a2a-task-owner-idor.test.ts可作为参考模板更新文档在本文档的 Available Skills 表中登记新技能。结语OmniRoute 的 A2A Server 把智能路由 配额治理 成本控制 韧性巡检打包成一个符合 Agent-to-Agent 协议 v0.3 的标准服务面Agent 通过一次 Agent Discovery 即可获知全部能力随后用统一的 JSON-RPC 调用完成路由、配额、成本、健康与能力发现等任务并通过任务状态机、TTL 清理、owner 隔离与可审计元数据获得可靠的执行保证。若你的 Agent 需要与多模型提供商编排协作这份接口契约可以直接作为编排层的标准连接点更多关于 OmniRoute Agent 技能目录的上下文注入方式可继续阅读 AGENT-SKILLS.md 与 A2A 相关架构文档。【免费下载链接】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),仅供参考