尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

OmniRoute A2A Server 实战指南:以 Agent-to-Agent 协议暴露智能路由能力

OmniRoute A2A Server 实战指南:以 Agent-to-Agent 协议暴露智能路由能力 OmniRoute A2A Server 实战指南以 Agent-to-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 将自身 AI 网关的智能路由、配额管理、健康监测等能力通过 Agent-to-AgentA2A协议 v0.3 封装为标准 JSON-RPC 2.0 接口让 Claude、Codex、Cline 等外部 Agent 可以直接以对 Agent 说话的方式调用网关能力。本文基于 docs/frameworks/A2A-SERVER.md 展开结合 src/app/a2a/route.ts、src/lib/a2a/taskManager.ts 等源码完整讲解 Agent 发现、认证、六个 JSON-RPC 方法、六大 Skills、任务生命周期与错误码并给出可直接复制的 Python / TypeScript 集成示例。读完本文你将掌握如何以标准 A2A 协议对接 OmniRoute将 352 个 Provider、1200 模型的智能路由能力无缝接入自己的 Agent 工作流。一、双面接口总览JSON-RPC 与 RESTA2A 协议是 Google 发起的 Agent 互操作开放协议OmniRoute 在其之上实现了一层智能路由 Agent表面。从源码结构看A2A 表面surface共有两个入口见 docs/frameworks/A2A-SERVER.mdJSON-RPC 2.0位于POST /a2a是规范意义上的唯一入口实现于 src/app/a2a/route.ts。所有 Agent 间的消息收发、任务查询与取消都走这里。REST 辅助接口位于/api/a2a/*供仪表盘与外部工具查看状态、任务列表与执行取消。任务由A2ATaskManager统一管理src/lib/a2a/taskManager.ts默认 TTL 5 分钟技能则通过A2A_SKILL_HANDLERS注册表分发src/lib/a2a/taskExecution.ts。二、Agent Discovery让其他 Agent 找到你A2A 协议要求每个 Agent 通过 Agent Card 描述自身能力。OmniRoute 在标准路径/.well-known/agent.json暴露 Agent Cardcurl http://localhost:20128/.well-known/agent.json返回内容描述 OmniRoute 的能力、技能列表与认证要求。该 Agent Card 是动态生成的实现于 src/app/.well-known/agent.json/route.ts有两个值得注意的细节版本号自动同步version字段取自process.env.npm_package_versionroute.ts#L17因此每次发布package.json版本号变化时Agent Card 会随之自动更新无需手工维护。与运行时注册表保持对齐技能列表基于可用组合combos动态生成卡片中还包含来自 OmniConductor 集群的 fleet skills有约 60 秒缓存集群未配置或离线时该字段为空数组不影响卡片整体可用性。Agent Card 中的capabilities.streaming为true表明该 Agent 支持流式输出。三、启用开关默认关闭A2A 端点由Endpoints端点→ A2A开关控制默认禁用。这是重要的安全前提具体行为如下见 docs/frameworks/A2A-SERVER.md禁用时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标志为 false 时直接拦截所有方法调用。四、AuthenticationBearer Token 认证所有/a2a请求都需要通过Authorization头携带 API KeyAuthorization: Bearer YOUR_OMNIROUTE_API_KEY认证逻辑统一收敛在 src/lib/a2a/authenticate.ts 的authenticateA2ARequest中其判定顺序如下若开启了REQUIRE_API_KEY模式isRequireApiKeyEnabled()必须携带有效 OmniRoute Key否则拒绝若配置了OMNIROUTE_API_KEY环境变量请求头中的 Bearer Token 必须与之精确匹配使用timingSafeEqual进行常数时间比较防时序侧信道攻击authenticate.ts#L16-L21若两者都未配置认证被绕过进入本地优先keyless模式——这也是出厂默认行为。此外同一文件中的resolveA2AOwner会将调用方 API Key 的 SHA-256 前缀32 位 hex作为任务的 owner 标识用于任务可见性隔离对应安全公告 GHSA-jcm5-6wpp-wjj8带 owner 的任务只对同一 owner 可见/可取消无 key 的任务对所有调用方可见相关验证见 tests/unit/a2a-task-owner-idor.test.ts。五、JSON-RPC 2.0 Methods 详解POST /a2a统一处理 JSON-RPC 2.0 请求。下面是四个标准方法的完整说明。5.1message/send— 同步执行向指定 skill 发送消息并等待完整响应。返回结果中包含任务状态、artifacts 以及路由决策元数据。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 } } } }这些元数据字段并非凭空而来而是由smart-routing技能的实现 src/lib/a2a/skills/smartRouting.ts 真实产出routing_explanation由实际路由结果拼装格式为Selected model via provider provider (latency: msms, cost: $cost)cost_envelope.estimated基于prompt_tokens / 1_000_000 × 3.0的粗略估算美元resilience_trace记录primary_selected事件当上游触发 fallback 时追加fallback_needed事件policy_verdict当params.metadata中传入budget时对实际成本做预算校验allowed反映是否在预算内。5.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:{...}}}流式实现的底层细节在 src/lib/a2a/streaming.ts心跳机制每 15 秒发送一行: heartbeat ISO时间注释行防止代理/网关断开空闲连接streaming.ts#L58-L60分块事件技能完成后artifacts 被逐个封装为chunk事件发出对非流式技能做模拟流式输出终止事件以state: completed 完整metadata收尾异常路径则发出state: failed取消支持监听AbortSignal客户端断开或主动中止时立即发送Cancelled失败事件并关闭流响应头Content-Type: text/event-stream、Cache-Control: no-cache, no-transform、X-Accel-Buffering: no禁用 Nginx 等反向代理的缓冲保证逐字推送。5.3tasks/get— 查询任务状态按任务 ID 查询状态与产物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}}实现上getTask会先检查expiresAt若任务已过期且仍处于submitted/working会先将其置为failedTask expired再返回taskManager.ts#L231-L241。5.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}}cancelTask在变更前先做 owner 校验且对任务不存在与任务存在但不属于你返回相同的not found错误防止 IDOR 探测taskManager.ts#L268-L278。5.5 兼容 A2A 1.0 客户端v1.0 ↔ v0.3 兼容层值得注意的是src/app/a2a/route.ts 内置了一个 A2A 1.0 ↔ 0.3 兼容层1.0 将message/send改名为SendMessage、message/stream改名为SendStreamingMessage且同步响应的读取位置也不同1.0 客户端读task.status.message.parts[].text而 OmniRoute 0.3 返回顶层artifacts/metadata。该兼容层对 1.0 方法名做别名映射并把同步响应重塑为 1.0 的Task结构使得 a2a-sdk 1.x、Hermes 等 1.0 客户端可以不改代码直接调用0.3 客户端则完全不受影响。相关验证见 tests/unit/a2a-v1-compat-10839.test.ts。六、Available SkillsOmniRoute 暴露的六大技能OmniRoute 通过A2A_SKILL_HANDLERS注册表src/lib/a2a/taskExecution.ts暴露 6 个技能每个技能模块位于 src/lib/a2a/skills/ 目录SkillID说明Tags调用示例Smart Routingsmart-routing使用组合引擎 评分将提示词路由到最优 Provider/Comborouting, 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 表格返回完整的 45 项 Agent Skills 目录23 API 21 CLI 1 config及 SKILL.md 原始链接catalog, discovery, skillsList all OmniRoute capabilitiesAgent Card 与实时的 Provider 目录保持一致当前运行时注册表维护 352 个 Provider 的元数据免费/免认证标志均来自运行时注册表。list-capabilities技能详解对于需要在发送 API 调用前先摸清 OmniRoute 能力的外部 Agentlist-capabilities尤其有用。它返回结构化 Markdown 表格 artifact每行包含 ID、名称、类别、区域、端点/命令与原始 URL| 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技能目录体系见 docs/frameworks/AGENT-SKILLS.md。七、REST API辅助面JSON-RPC 端点/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 CardA2A 发现公开缓存 3600s/api/a2a/tasksPOST入站委托给 OmniConductor 集群Bearer vsOMNIROUTE_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? } } }。只有 Conductor 集群技能即 Agent Card 上公布的技能可被委托且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查看。八、Task 生命周期与 TTL任务状态机如下submitted → working → completed → failed → cancelledTTL任务在ttlMinutes后过期默认 5 分钟由A2ATaskManager构造函数配置taskManager.ts#L139-L150。如需自定义可以new A2ATaskManager(15)实例化一个 15 分钟 TTL 的管理器后台清理每 60 秒执行一次过期清理非终止状态的任务过期后标记为failedTTL expired终止状态任务在超过 2× TTL 后从内存移除历史表清理按OMNIROUTE_A2A_HISTORY_RETENTION_DAYS默认 30 天保留且每天最多 purge 一次终止状态completed、failed、cancelled事件日志每次状态转换都会追加到task.events同时通过emit(agent.task.updated, ...)广播给编排画布best-effort监听器抛错不会破坏任务写入路径并发流计数beginStream/endStream维护activeStreams统计可在getStats()中查询。状态转换的合法性由VALID_TRANSITIONS表强制校验非法跳转如completed → working会抛错。任务 ID 使用 UUID v4randomUUID()内存 Map 是活跃任务的真相来源同时通过 DI 接缝将历史写入 SQLite对应src/lib/db/a2aTasks.ts测试注入 fake 以避免触碰真实数据库。九、Error CodesJSON-RPC 错误码Code含义-32700解析错误JSON 无效-32600无效请求 / 未授权-32601方法或技能不存在-32602参数无效-32603内部错误-32000A2A 端点已禁用HTTP 状态码映射规则route.ts#L136-L141-32600→ 400-32601→ 404-32603→ 500其余返回 200 并在 JSON-RPCerror对象中携带错误信息-32000禁用场景返回 HTTP 503。十、Integration Examples开箱即用的集成代码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);注意请求体同时支持params.messages消息数组与params.message单条消息两种形态params.message还兼容{ content }与{ parts: [...] }两种结构方便接入不同生态的 Agent SDK见 route.ts#L80-L121 的toMessageArray归一化逻辑。十一、扩展新 Skill源码级接入指南如果你希望 OmniRoute 的 A2A 表面暴露自定义技能文档给出了完整流程对应文件均已存在可参照创建技能文件在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覆盖正常路径与错误路径。仓库已有 11 个 A2A 相关测试可作参考涵盖认证tests/unit/a2a-auth-timing-safe.test.ts、启用开关tests/unit/a2a-enabled-route.test.ts、任务持久化tests/unit/a2a-task-persistence.test.ts、owner 隔离tests/unit/a2a-task-owner-idor.test.ts与 1.0 兼容层等更新文档在本文档对应的技能表中补充新条目。十二、补充实现细节内存命中Memory Hits在执行技能前A2A 任务会尝试做一次仅用于观测的内存召回src/lib/a2a/taskExecution.ts以任务最后一条 user 消息为查询在 1.5 秒时限MEMORY_RECALL_TIMEOUT_MS内检索内存命中结果以memoryHits写入task.metadata并记录memory_hits历史事件供仪表盘展示该任务参考了哪些记忆。关键在于召回的命中文案截断到 200 字符绝不注入技能提示词或影响行为可通过环境变量OMNIROUTE_A2A_MEMORY_HITS0一键关闭任何召回失败都静默降级为[]绝不拖垮任务主链路对应测试见 tests/unit/a2a-memory-hits.test.ts。总而言之OmniRoute 的 A2A Server 用标准 JSON-RPC 2.0 Agent Card 发现机制把网关最核心的路由决策、配额、健康与成本能力开放给了任意 A2A 客户端。结合 src/lib/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),仅供参考
返回列表