
OmniRoute A2A Server 接入指南通过 Agent-to-Agent 协议 v0.3 将智能路由、配额与健康能力开放给任意 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/OmniRoute本文基于 docs/i18n/pl/docs/frameworks/A2A-SERVER.md 编写并对照其英文权威版 docs/frameworks/A2A-SERVER.md 与仓库源码核实细节。OmniRoute 的 A2A Server 把整个 AI 网关包装成一个一等公民 Agent任何支持 Agent-to-Agent ProtocolA2Av0.3 的编排器LangChain、CrewAI、AutoGen 或自定义 Agent都可以通过一个POST /a2a的 JSON-RPC 2.0 端点把任务委托给 OmniRoute 的智能路由引擎、配额管理、成本分析等技能并拿到带routing_explanation、cost_envelope、resilience_trace、policy_verdict的可观测元数据。读完本文你将掌握如何发现 OmniRoute AgentAgent Card、如何调用四个 JSON-RPC 方法、六大内置技能的使用方式、任务生命周期与 TTL、错误码语义以及如何扩展一个新的 A2A Skill。A2A 表面的两张脸JSON-RPC 与 RESTA2A 能力面由两个互补的接口组成JSON-RPC 2.0入口POST /a2a是 A2A 的规范canonical入口点负责技能执行的全部语义。路由实现在 src/app/a2a/route.ts支持四个方法message/send同步执行、message/streamSSE 流式、tasks/get查询任务、tasks/cancel取消任务。REST 辅助入口/api/a2a/*为仪表盘与外部工具提供状态查询、任务列表、任务取消等辅助能力见 src/app/api/a2a/tasks/route.ts 与 src/app/api/a2a/status/route.ts。在底层任务由A2ATaskManagersrc/lib/a2a/taskManager.ts统一跟踪默认 TTL 为 5 分钟技能通过 src/lib/a2a/taskExecution.ts 中的A2A_SKILL_HANDLERS注册表分发。整体架构发现 → 委托 → 执行 → 内部网关转发可参考 src/lib/a2a/README.md 中给出的架构图。Agent 发现读取 Agent CardA2A 协议要求每个 Agent 在/.well-known/agent.json暴露一张Agent Card描述自身能力、技能与认证要求。OmniRoute 默认监听http://localhost:20128curl http://localhost:20128/.well-known/agent.json返回的 Agent Card 包含name、description、url指向/a2a、version、capabilitiesstreaming: true、pushNotifications: false、skills数组以及authenticationschemes: [api-key]apiKeyHeader: Authorization。Agent Card 是动态生成的实现见 src/app/.well-known/agent.json/route.tsversion字段直接取自process.env.npm_package_version回退值为1.8.1因此每次发布时都会与package.json自动保持同步skills数组在 6 个内置技能基础上还会通过getFleetSkills()追加 OmniConductor 编排集群的 fleet 技能集群未配置或离线时为空数组卡片依然有效响应带有Cache-Control: public, max-age3600即公开缓存 1 小时顺带说明Agent Card 的描述文本中仍写有 36 个提供者、list-capabilities描述写有 42 个技能 等旧数值这与当前运行时注册表的真实目录规模存在已知漂移文档中已记录为待单独更新的 TODO当前源码里 6 个内置技能 fleet 技能的形态以 taskExecution.ts 为准。认证与启用开关认证所有/a2a请求都要求在Authorization头携带 API KeyAuthorization: Bearer YOUR_OMNIROUTE_API_KEY认证逻辑集中在 src/lib/a2a/authenticate.ts 的authenticateA2ARequest()JSON-RPC 与 REST 任务面共用同一实现避免两处逻辑漂移。其判定顺序若开启了REQUIRE_API_KEY特性开关必须提供有效 API Key否则拒绝作为例外仪表盘会话 Cookie 可被放行以支持 A2A Playground若未开启强制开关但配置了OMNIROUTE_API_KEY用timingSafeEqual做常量时间比较防止时序侧信道泄露密钥对应测试见 tests/unit/a2a-auth-timing-safe.test.ts若服务端既未要求也未配置 API Key直接放行keyless local-first 默认姿态即文档所说未配置 API Key 时认证被绕过。认证失败时JSON-RPC 返回错误码-32600Unauthorized。启用开关A2A 默认是关闭的由Endpoints → A2A开关控制存储于settings.a2aEnabled。未启用时GET /api/a2a/status返回status: disabled与online: false对POST /a2a的 JSON-RPC 调用返回HTTP 503与 JSON-RPC 错误码-32000错误信息提示到 Endpoints 页面开启。对应的守卫逻辑在 src/app/a2a/route.ts 的rejectIfA2ADisabled()中启用状态由 src/app/api/a2a/status/route.ts 读取settings.a2aEnabled true时为ok并附带任务统计与 Agent Card 摘要。JSON-RPC 2.0 方法详解所有方法都走POST /a2a请求体为标准的 JSON-RPC 2.0 信封jsonrpc: 2.0idmethodparams。路由的完整处理流程见 src/app/a2a/route.ts为认证 → 解析 JSON失败返回-32700→ 校验jsonrpc/method失败返回-32600→ 检查启用开关失败返回-32000/503→ 解析调用者 owner → 分发到具体方法。协议兼容层/a2a还内置了 A2A 1.0 兼容层——1.0 将方法改名为SendMessage/SendStreamingMessage并改变了同步响应结构OmniRoute 通过V1_METHOD_ALIASES将这两个 1.0 方法名映射回message/send/message/stream并把 v0.3 的顶层artifacts/metadata重排成 1.0 客户端期望的task.status.message.parts[].text。v0.3 客户端不受影响。相关测试见 tests/unit/a2a-v1-compat-10839.test.ts。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} } }响应示例{ 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 } } } }几个值得注意的路由行为源码佐证若params.skill缺省默认使用smart-routingmessages兼容两种形态规范的messages[]数组或 legacy 的message.content/message.parts见toMessageArray()的归一化逻辑消息缺失时返回-32602Invalid params技能不存在时返回-32601Method or skill not found技能执行抛错时任务被标记为failed响应返回-32603Internal error对于smart-routing成功后会额外调用logRoutingDecision()src/lib/a2a/routingLogger.ts把路由决策写入统计供仪表盘分析。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:{...}}}SSE 的实现位于 src/lib/a2a/streaming.ts心跳每 15 秒发送一条: heartbeat ISO时间注释行保持连接存活分块技能产出以working状态的chunk事件逐条发出对非流式技能做模拟分片完成最后一个事件为completed状态并携带metadata失败/取消以failed状态事件携带metadata.error结束响应头为text/event-stream、Cache-Control: no-cache, no-transform、Connection: keep-alive、X-Accel-Buffering: no流式任务通过beginStream()/endStream()计入activeStreams统计客户端中断AbortSignal会立即发出取消失败事件并关闭流。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}}任务不存在时返回-32601Task not foundtaskId缺失时返回-32602。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 作用域从 taskManager.ts 与 authenticate.ts 可以看到对应安全修复 GHSA-jcm5-6wpp-wjj8每个任务携带ownerAPI Key 的SHA-256 哈希前 32 位十六进制仪表盘会话调用者为dashboardkeyless 调用者为undefined带 owner 的任务只对同 owner 可见/可取消/可列出tasks/get、tasks/cancel与 REST 列表都会按 owner 过滤防止 IDOR 探测取消他人任务与任务不存在返回相同的 not found 错误相关测试见 tests/unit/a2a-task-owner-idor.test.ts。内置技能Available SkillsOmniRoute 暴露 6 个 A2A 技能全部在 src/lib/a2a/taskExecution.ts 的A2A_SKILL_HANDLERS中注册每个技能的模块位于 src/lib/a2a/skills/通过动态import()按需加载SkillID描述Tags示例Smart Routingsmart-routing使用 OmniRoute 的 combo 引擎 评分体系将 prompt 路由到最优 provider/comborouting, providersRoute this prompt via the best modelQuota Managementquota-management报告各 provider 的配额状态帮助调用方决定何时限流/切换quota, providersCheck quota for anthropicProvider Discoveryprovider-discovery列出已安装的 provider含能力、free-tier 标记与 OAuth 状态providers, discoveryWhat providers are available?Cost Analysiscost-analysis基于价格目录 近期 usage 估算单次请求/会话成本cost, usageEstimate cost for this conversationHealth Reporthealth-report聚合各 provider 的 circuit breaker、cooldown、lockout 状态health, resilienceShow health status of all providersList Capabilitieslist-capabilities以 Markdown 表格返回完整 Agent Skills 目录附 SKILL.md 原始 URL 供上下文注入catalog, discovery, skillsList all OmniRoute capabilities关于技能数量与 provider 数量的数值漂移文档表格与 Agent Card 描述文本中写有 42 个技能、36 providers 等旧值而当前源码 listCapabilities.ts 中的目录覆盖为23 API 21 CLI 1 config 共 45 项metadata.coverage硬编码这些总数。文档已明确记录这是待更新项引用时请以运行时目录为准。smart-routing技能的 metadata 参数与返回值smart-routing是使用最频繁的技能。其metadata支持以下参数见 src/lib/a2a/skills/smartRouting.ts 与 src/lib/a2a/README.md参数类型默认值说明modelstringauto目标模型如claude-sonnet-4、gpt-4o或auto交给路由引擎combostring当前激活 combo指定要走某个 combo通过x-combo头传给内部/v1/chat/completionsbudgetnumber无本次请求的成本上限USD超过则policy_verdict.allowedfalserolestring无任务角色提示coding、review、planning、analysis、debugging、documentation返回字段字段说明artifacts[].contentLLM 响应文本metadata.routing_explanation人类可读的路由决策说明选中模型、provider、延迟、成本metadata.cost_envelope预估 vs 实际成本estimated/actual/currencymetadata.resilience_trace事件数组primary_selected触发回退时追加fallback_neededmetadata.policy_verdict请求是否被允许及原因预算/配额检查从源码看smartRouting.ts内部会把请求转发给 OmniRoute 自身的/v1/chat/completions携带 30 秒超时与内部 API Key返回的provider、cost、fallbacksTriggered等字段被整理进上述元数据。list-capabilities技能详解对于需要在发送 API 调用之前先探测 OmniRoute 能力的外部 Agentlist-capabilities特别有用。它会返回一张结构化 Markdown 表格制品| 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与目录大小保持一致。实现见 src/lib/a2a/skills/listCapabilities.ts目录数据来自 src/lib/agentSkills/catalog.ts。技能目录的完整说明参见 AGENT-SKILLS.md。辅助 REST APIJSON-RPC 端点/a2a是 A2A 的规范入口下面的 REST 端点则面向仪表盘与外部工具提供辅助访问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 集群入站委托Conductor PRD RF5Bearer vsOMNIROUTE_API_KEYa2aEnabled关于 REST 任务列表GET /api/a2a/tasks支持state仅接受五个合法状态值、skill、limit1–200默认 50、offset默认 0查询参数返回{ tasks, total, limit, offset }management 或 keyless 姿态可见全部任务裸 API Key 必须有效且按 owner 过滤见 src/app/api/a2a/tasks/route.ts。关于入站委托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 技能可被委托且metadata.conductor.repo.url必填集群基于 git 仓库工作。该路由使用服务端CONDUCTOR_ORCHESTRATOR_TOKEN回退CONDUCTOR_HUB_TOKEN转调到 hub 的POST /v1/tasks返回201 { conductor_task_id, state: submitted }任务状态经 SSE→A2A 镜像回流可通过GET /api/a2a/tasks?skillconductor查询。任务生命周期与 TTL任务状态机src/lib/a2a/taskManager.ts 的VALID_TRANSITIONS严格约束submitted → working → completed → failed → cancelled关键行为默认 TTL 5 分钟任务在ttlMinutes构造A2ATaskManager时传入默认 5后过期。submitted/working状态的任务过期后会被自动标记为failed消息为 TTL expired后台清理每 60 秒扫一次过期任务cleanupExpired()终态任务在超过2×TTL后从内存移除终态不可转移completed、failed、cancelled均为终态任何非法迁移都会抛错事件日志每次状态迁移都会写入events数组含时间戳、状态、可选消息并发布agent.task.updated事件总线消息供编排画布订阅best-effort 不阻塞写入路径历史持久化任务状态可写入 SQLite 历史表best-effort保留天数由OMNIROUTE_A2A_HISTORY_RETENTION_DAYS控制默认 30 天每日最多清理一次任务 IDUUID v4randomUUID()。若要自定义 TTL可以 forkA2ATaskManager的实例化并传入不同值例如new A2ATaskManager(15)表示 15 分钟 TTL同时可注入自定义持久化层。单例入口getTaskManager()使用默认 5 分钟。错误码代码含义-32700解析错误JSON 无效-32600无效请求 / 未授权-32601未找到方法或技能-32602无效参数-32603内部错误-32000A2A 端点已禁用注意 HTTP 状态码的映射并非固定-32600→ 400、-32601→ 404、-32603→ 500、其余为 200错误体现在 JSON-RPCerror字段中而-32000禁用固定返回 HTTP 503。此外 src/lib/a2a/README.md 还扩展记录了-32001任务未找到到-32005无可用 provider等业务错误码。集成示例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);更完整的场景化客户端含 Agent 发现、budget约束、SSE 流式解析、任务轮询取消、LangChain 自定义 LLM 包装、Go 客户端等见 src/lib/a2a/README.md。扩展指南添加一个新的 A2A Skill按以下 5 步即可为 OmniRoute 增加一个新技能这也是A2A_SKILL_HANDLERS与 Agent Card 的扩展路径1. 创建技能文件src/lib/a2a/skills/your-skill.ts导出异步函数(task: A2ATask) Promise{ artifacts, metadata }参照现有技能如smartRouting.ts的形状export async function executeYourSkill(task: A2ATask) { // 读取 task.input.messages / task.input.metadata // 产出 artifacts: [{ type: text, content }] 与 metadata return { artifacts, metadata }; }2. 注册 handler在src/lib/a2a/taskExecution.ts的A2A_SKILL_HANDLERS中追加条目采用动态 import 保持按需加载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.ts 的skills数组追加{ id: your-skill, name: Your Skill, description: Brief, intent-focused description, tags: [routing, quota], examples: [Sample natural-language invocation] }4. 编写测试创建tests/unit/a2a-your-skill.test.ts覆盖 happy path 与 error path仓库现有 A2A 测试可作参考如 tests/unit/a2a-enabled-route.test.ts、tests/unit/a2a-route-require-api-key.test.ts、tests/unit/a2a-memory-hits.test.ts。5. 更新文档在本文档及 src/lib/a2a/README.md的 Available Skills 表格中登记新技能。补充任务执行中的内存检索观测从 src/lib/a2a/taskExecution.ts 可以看到一个值得注意的机制任务执行前会做一次纯观测用途的记忆检索collectMemoryHits对应 Orchestration Canvas 任务 C2——检索到的记忆从不注入技能 prompt只镜像到task.metadata.memoryHits与memory_hits历史事件供仪表盘展示该任务参考了哪些记忆。可用OMNIROUTE_A2A_MEMORY_HITS0完全关闭检索有 1500ms 截止时间MEMORY_RECALL_TIMEOUT_MS超时或失败均静默降级为[]绝不拖垮主任务。A2A 技能通过/v1/chat/completions等内部端点与 OmniRoute 网关联动形成外部 Agent → A2A 技能 → 网关路由引擎 → 最优 provider的完整链路。【免费下载链接】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),仅供参考