news 2026/9/10 12:17:20

OmniRoute A2A Server 接入指南:Agent-to-Agent Protocol v0.3 智能路由代理服务详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
OmniRoute A2A Server 接入指南:Agent-to-Agent Protocol v0.3 智能路由代理服务详解

OmniRoute A2A Server 接入指南:Agent-to-Agent Protocol v0.3 智能路由代理服务详解

【免费下载链接】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

本文基于仓库文档 docs/i18n/ar/docs/frameworks/A2A-SERVER.md(阿拉伯语版)与 docs/frameworks/A2A-SERVER.md(英文原版)整理编写,并以仓库源码 src/app/a2a/route.ts、src/lib/a2a/taskManager.ts 等实现细节交叉验证。

OmniRoute 作为统一 AI 网关,除了标准的 OpenAI 兼容 API 之外,还提供了一面完整的Agent-to-Agent(A2A)协议服务,让其他 Agent 框架可以把 OmniRoute 当作一个"智能路由代理"来调用——把提示词交给它,由它完成模型选型、配额检查、成本预估与回退容错。本文面向希望在 Claude Code、自研 Agent 或任意支持 JSON-RPC/SSE 的程序中接入 OmniRoute A2A Server 的开发者,读完你将掌握:如何发现 Agent Card、如何完成认证与开关启用、四个核心 JSON-RPC 方法的完整调用格式与响应结构、六个内置技能的能力边界、任务生命周期与 TTL 机制,以及如何用 Python / TypeScript 在 10 行代码内完成首个调用。

A2A 服务的双面形态:JSON-RPC 主入口与 REST 辅助接口

从源码结构看,A2A 表面(surface)分为两个层面,职责各有分工:

  • JSON-RPC 2.0,入口为POST /a2a,是规范的(canonical)入口点,定义在 src/app/a2a/route.ts。message/sendmessage/streamtasks/gettasks/cancel四个方法都在这里分发。
  • REST 辅助接口,位于/api/a2a/*之下,面向仪表盘与外部工具,提供状态查询、任务列表、任务取消等操作。

任务由A2ATaskManager统一管理(src/lib/a2a/taskManager.ts,默认 5 分钟 TTL);技能(Skill)通过 src/lib/a2a/taskExecution.ts 中的A2A_SKILL_HANDLERS注册表分发执行。

端口说明:文档中的示例统一使用http://localhost:20128作为 A2A Server 监听地址,实际端口以你启动 OmniRoute 时的配置为准。

Agent Discovery:通过 Agent Card 发现能力

任何 A2A 客户端的第一步都是发现对端能力。OmniRoute 按照 A2A 规范暴露了一个标准的发现端点:

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

该端点返回Agent Card,其中描述 OmniRoute 的能力(capabilities)、可用技能(skills)以及认证要求(authentication requirements)。外部 Agent 可以先读取这份卡片,再决定调用哪个技能。

据官方文档说明,Agent Card 中的version字段取自process.env.npm_package_version,因此每次发版时都会与package.json自动同步,不会出现版本号漂移。Agent Card 也应与实时更新的 352+ 供应商目录保持对齐,其中的供应商数量与 free/no-auth 元数据均来自运行时注册表。

认证机制与启用开关

Bearer Token 认证

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

Authorization: Bearer YOUR_OMNIROUTE_API_KEY

从 src/lib/a2a/authenticate.ts 的authenticateA2ARequest实现可以看出认证的完整判定逻辑,分为三层:

  1. 若全局启用了REQUIRE_API_KEY策略(isRequireApiKeyEnabled()为真),则请求必须携带有效的 OmniRoute API Key(通过isValidApiKey校验)。
  2. 若未启用强制策略、但配置了环境变量OMNIROUTE_API_KEY,则用timingSafeEqual做常数时间比对,防止时序侧信道攻击。
  3. 若服务器上既未启用强制 Key、也未配置任何 Key,则认证直接放行——这是与/v1一致的"本地优先、免钥(keyless)"默认姿态。

此外,resolveA2AOwner会对调用方的 API Key 做 SHA-256 哈希并取前 32 位十六进制字符作为任务的"所有者 ID",用于任务可见性隔离(对应安全公告 GHSA-jcm5-6wpp-wjj8):带所有者的任务仅对该所有者可见,而免钥调用产生的任务对所有调用者可见。

Endpoints 开关:A2A 默认关闭

A2A 功能由Endpoints 页面中的 A2A 开关控制,默认处于关闭状态。未启用时的行为(对应 src/app/a2a/route.ts 的rejectIfA2ADisabled):

  • GET /api/a2a/status返回status: "disabled"online: false
  • POST /a2a的 JSON-RPC 调用返回HTTP 503,错误码为 JSON-RPC 标准扩展码-32000,消息为A2A endpoint is disabled. Enable it from the Endpoints page.

对应的单元测试见 tests/unit/a2a-enabled-route.test.ts。

JSON-RPC 2.0 核心方法

所有方法都遵循 JSON-RPC 2.0 规范:请求体包含jsonrpc: "2.0"idmethodparams四个字段。下面逐一说明。

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的三个字段说明:

字段说明
skill要调用的技能 ID,缺省时路由到smart-routing(源码中params?.skill || "smart-routing"
messages消息数组,每项为{ role, content };兼容 A2A v1.0 的message.contentmessage.parts[]形态
metadata可选,透传给技能的附加参数,例如modelcomborole

成功响应示例:

{ "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是 OmniRoute A2A 最具价值的输出:

  • routing_explanation:人类可读的路由决策说明,例如选择了哪个模型、经由哪个供应商、延迟与成本;
  • cost_envelope:成本信封,给出预估成本(estimated)与实际成本(actual)及币种;
  • resilience_trace:韧性追踪,逐条记录primary_selectedfallback等事件,完整还原回退链路;
  • policy_verdict:策略裁定,说明该请求是否在预算与配额限制之内。

message/send的执行路径上,源码还会对smart-routing技能调用 src/lib/a2a/routingLogger.ts 的logRoutingDecision记录路由决策,供后续分析与审计。

message/stream:SSE 流式输出

message/streammessage/send参数完全一致,但响应改为Server-Sent Events(SSE),适合需要实时展示生成内容的场景:

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 源码可以看到三个关键实现细节:

  • chunk 事件state: "working"状态下逐块推送chunk(文本片段);
  • heartbeat 心跳:每 15 秒发送一条: heartbeat <ISO 时间>注释行保活,防止代理或负载均衡器断开空闲连接;
  • 完成事件:任务结束时推送state: "completed"并携带完整metadata

流式路径通过executeA2ATaskWithState(见 src/lib/a2a/taskExecution.ts)包装,任务执行期间还会尝试收集记忆命中(memory hits,可通过OMNIROUTE_A2A_MEMORY_HITS=0关闭)写入task.metadata.memoryHits,纯为可观测性用途,不会注入技能提示词。

tasks/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"}}'

tasks/get在返回前会检查任务是否已过期:若任务处于submittedworking状态且已超过expiresAt,会先将其标记为failed(消息为Task expired)。同时执行所有者可见性校验——带所有者的任务对其他调用方返回"Task not found",避免 IDOR 探测(对应 tests/unit/a2a-task-owner-idor.test.ts)。

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"}}'

tasks/cancel先将任务从submitted/working迁移到cancelled,随后技能执行线程会在executeA2ATaskWithState捕获状态迁移异常并保留原始错误,确保取消不会破坏正在进行的写路径。

版本兼容性提示:源码中还实现了一层A2A v1.0 与 v0.3 的兼容层(src/app/a2a/route.ts 顶部的V1_METHOD_ALIASES):v1.0 客户端使用SendMessage/SendStreamingMessage方法名同样可以调用,且同步响应会被重塑为 v1.0 的task.status.message.parts[].text形态。因此 a2a-sdk 1.x、Hermes 等 v1.0 客户端可以直接接入,v0.3 客户端不受影响。

可用技能(Skills)清单

OmniRoute 通过 src/lib/a2a/taskExecution.ts 的A2A_SKILL_HANDLERS注册了 6 个 A2A 技能,每个技能模块位于 src/lib/a2a/skills/ 目录下:

技能ID说明标签示例问法
Smart Routingsmart-routing使用 OmniRoute 的组合引擎与评分机制,将提示词路由到最优供应商/组合routing, providers"Route this prompt via the best model"
Quota Managementquota-management报告各供应商配额状态,帮助调用方决定何时限流或切换quota, providers"Check quota for anthropic"
Provider Discoveryprovider-discovery列出已安装的供应商及其能力、免费额度标记、OAuth 状态providers, discovery"What providers are available?"
Cost Analysiscost-analysis基于目录与近期用量估算一次请求/一段对话的成本cost, usage"Estimate cost for this conversation"
Health Reporthealth-report聚合各供应商的熔断器、冷却、锁定状态health, resilience"Show health status of all providers"
List Capabilitieslist-capabilities返回完整的 45 项 Agent 技能目录(23 项 API + 21 项 CLI + 1 项 config)为 Markdown 表格,附带原始 SKILL.md URL 供上下文注入catalog, discovery, skills"List all OmniRoute capabilities"

每个技能的实现都对应一个独立模块,例如:

  • src/lib/a2a/skills/smartRouting.ts(executeSmartRouting
  • src/lib/a2a/skills/quotaManagement.ts
  • src/lib/a2a/skills/providerDiscovery.ts
  • src/lib/a2a/skills/costAnalysis.ts
  • src/lib/a2a/skills/healthReport.ts
  • src/lib/a2a/skills/listCapabilities.ts

list-capabilities 技能详解

对于需要在发送 API 调用前先了解 OmniRoute 暴露了哪些能力的外部 Agent 而言,list-capabilities尤其有用。它返回一个结构化的 Markdown 表格 artifact:

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

从 src/lib/a2a/skills/listCapabilities.ts 源码可见:

  • 数据来自getCatalog()computeCoverage()(定义于 src/lib/agentSkills/catalog.ts);
  • 每行包含rawUrl列,Agent 可以立即抓取完整的 SKILL.md 注入上下文;
  • 响应的metadata.totalSkills反映目录规模(当前为 45 项),metadata.coverage分别给出 API(23)/CLI(21)/config(1)的覆盖统计。

REST 辅助 API:面向仪表盘与工具链

/a2a是规范的 JSON-RPC 入口,而下列 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 发现)公开,缓存 3600 秒
/api/a2a/tasksPOST入站委派(inbound delegation)到 OmniConductor 舰队Bearer 与OMNIROUTE_API_KEY+a2aEnabled

其中最后一个端点值得单独说明:入站 Conductor 委派允许外部 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?skill=conductor查看。

任务生命周期与 TTL

A2A 任务的状态机如下:

submitted → working → completed → failed → cancelled
  • 任务默认在5 分钟后过期(可配置);
  • 终态为completedfailedcancelled
  • 事件日志记录每一次状态迁移。

上述状态机在 src/lib/a2a/taskManager.ts 中有完整实现:

  • VALID_TRANSITIONS表严格约束合法迁移(例如completed之后不能再次迁移);
  • createTask生成 UUID v4 任务 ID,并将input.metadata做浅拷贝写入任务自身的metadata运行时袋,避免运行时写入污染调用方原始输入;
  • 每次状态迁移都会:
    1. 追加TaskEvent(时间戳 + 状态 + 可选消息);
    2. 通过事件总线发出agent.task.updated事件(供编排画布监听,且监听器异常绝不会拖垮写路径);
    3. 尽力持久化到 SQLite 历史表(src/lib/db/a2aTasks.ts 的upsertA2ATask/appendA2ATaskEvent),失败仅告警不阻断。

TTL 配置

TTL 在A2ATaskManager构造函数中配置(src/lib/a2a/taskManager.ts,constructor(ttlMinutes: number = 5),默认 5 分钟)。要自定义,只需 forkA2ATaskManager实例化并传入不同值,例如new A2ATaskManager(15)即为 15 分钟 TTL。

后台定时器每60 秒清理一次过期任务:

  • 非终态且超过expiresAt的任务被标记为failed(消息TTL expired);
  • 终态且超过 2 倍 TTL 的任务从内存 Map 中删除;
  • 历史表按OMNIROUTE_A2A_HISTORY_RETENTION_DAYS(默认 30 天)清理,每天最多触发一次。

错误码对照表

遵循 JSON-RPC 2.0 标准错误码约定,并扩展了两个 A2A 专用错误码:

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

HTTP 状态码与 JSON-RPC 错误码的映射(见 src/app/a2a/route.ts 的jsonRpcError):-32600→ 400,-32601→ 404,-32603→ 500,其余返回 200;-32000(端点禁用)返回 503。

集成示例:Python 与 TypeScript

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);

两个示例都只依赖标准 HTTP 客户端,无需额外 SDK。注意:流式场景请改用message/stream并监听 SSE 事件。

扩展新技能:从零注册一个 A2A Skill

如果你需要让 OmniRoute 的 A2A 面暴露自有能力,可以按以下五步扩展:

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

  2. 注册处理器:在 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); }, };
  3. 暴露到 Agent Card:在src/app/.well-known/agent.json/route.tsskills数组中追加:

    { "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,覆盖成功路径与错误路径(仓库现有测试可参考 tests/unit/a2a-cost-analysis-numeric-fallback.test.ts、tests/unit/a2a-routing-logger.test.ts 等)。

  5. 更新文档:在本文档的 Available Skills 表中补充新技能条目。

延伸阅读与源码索引

  • 协议总览:官方文档 A2A-SERVER.md、AGENT_PROTOCOLS_GUIDE.md
  • 技能目录体系:AGENT-SKILLS.md、SKILLS.md
  • 关键源码:src/app/a2a/route.ts(路由分发与 v1.0 兼容层)、src/lib/a2a/taskManager.ts(任务状态机与 TTL)、src/lib/a2a/taskExecution.ts(技能注册表)、src/lib/a2a/authenticate.ts(认证)、src/lib/a2a/streaming.ts(SSE 流式)
  • 单元测试:仓库tests/unit/a2a-*.test.ts系列覆盖启用开关、认证、任务所有权隔离、历史持久化、v1.0 兼容等场景

OmniRoute 的 A2A Server 把路由决策、配额管理、成本估算、健康报告与韧性追踪这些网关核心能力,封装成了标准 JSON-RPC 方法与可发现的技能目录。无论是把 OmniRoute 接入自研 Agent 编排、交给 Conductor 舰队做代码委派,还是让外部 Agent 在调用前先完成能力发现,这面 A2A 表面都提供了开箱即用的协议级入口——你只需要一个 API Key 和一次POST /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, RTK+Caveman compression saves 15-95% tokens, MCP/A2A, Desktop/PWA. Built by 550+ contributors项目地址: https://gitcode.com/GitHub_Trending/om/OmniRoute

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 12:14:31

JAVA毕业设计-基于SpringBoot+Vue的画师接单约稿系统的设计与实现 基于SpringBoot+Vue的艺术约稿交易平台的设计(源码+LW+部署文档+全bao+远程调试+代码讲解等)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/9/10 12:13:44

3D-CT肺结节检测实战:从LUNA16复现到端到端流程

简介&#xff1a;基于Python的3D-CT影像肺结节检测项目&#xff0c;源自个人毕设&#xff0c;答辩评分98分&#xff0c;完整涵盖源码、数据集与项目说明&#xff0c;面向计算机、通信、人工智能、自动化等专业的学生、老师或从业者&#xff0c;可作为期末大作业、课程设计或毕业…

作者头像 李华
网站建设 2026/9/10 12:13:34

计算机JAVA毕设实战-基于 SpringBoot、Vue 的线上画师约稿平台搭建与开发【完整源码+LW+部署说明+演示视频,全bao一条龙等】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/9/10 12:13:19

CANN/GE模型执行V2接口

aclmdlExecuteV2 【免费下载链接】ge GE&#xff08;Graph Engine&#xff09;是面向昇腾的图编译器和执行器&#xff0c;提供了计算图优化、多流并行、内存复用和模型下沉等技术手段&#xff0c;加速模型执行效率&#xff0c;减少模型内存占用。 GE 提供对 PyTorch、TensorFlo…

作者头像 李华