【OmniRoute】AI Gateway 数据平面 Harness 路由架构深度解析
引子:Agent 写代码,为什么 70% 时间在等 API?
你正用 Claude Code 写一个 Python 函数,模型已经在思考了,但终端上转圈圈的进度条依旧停滞 —— 翻看 metrics 才发现,过去 30 分钟 87% 的时间是”网络往返 + 配额等待 + 限速降级”,真正 LLM 推理只占 13%。
这不是 Claude Code 的问题,而是任何 Coding Agent 在生产环境都会遇到的真问题:
- 单一 Provider(比如只配 Anthropic 官方 Key)没有 fallback,429 一来整个 Agent 死锁
- Provider 间切换需要重新写适配器,从一个 SDK 迁到另一个平均 1-2 周
- 长上下文(>50K tokens)的对话把成本推到 $/小时量级,没有压缩机制
- 多个 Provider Key 散落在 env 文件、Vault、SSM 里,没有任何 quota 可视化
- 多 Agent 协作时,单个 Provider 限速会拖垮整个 agent pool
AI Gateway(也叫 LLM Gateway / Router)就是为了解这个事而存在的:把 LLM 调用抽象成数据平面(实际转发的代理),把”Provider 管理 / 配额监控 / 降级策略 / 成本审计”做成控制平面,让 Agent 只关心”我要哪个模型、什么能力”,不关心”这个模型现在还活着吗、会不会让我破产”。
今天这篇的主角是 diegosouzapw/OmniRoute(42,520⭐,TypeScript,MIT,今日 2026-08-07 仍在高频提交):一个把 Pipeline Engine + 4 级降级 + RTK+Caveman 双压缩 + A2A/MCP 桥接 全塞进一个 npm 包的”数据平面 + 控制平面一体”AI Gateway。它有 290+ Provider、516+ Model、19 种路由策略、~1.53B 免费 tokens/月额度。
我会用 OmniRoute 当主视角,横向对比 LiteLLM(55k⭐,Rust 核心)与 Portkey(12.7k⭐,1,600+ LLMs),讲清楚三件事:
- 数据平面 vs 控制平面分离在 Harness 6 件套里属于哪个组件、为什么
- **Pipeline Engine(plan/execute/reflect/fix 4 阶段)**这种”流水线”模式如何把单次 LLM 调用升级成”可观察、可降级、可审计”的多阶段任务
- **Graceful Degradation(Full → Reduced → Minimal → Default)**在 Harness Engineering 里为什么比”重试 3 次”高级 1 个维度
本文属于 Harness Engineering 系列 · 第二阶段”项目横向对比”专题第 N 篇
一、项目定位:Harness 6 件套中的”数据平面”
1.1 OmniRoute 在矩阵里的位置
| 6 件套组件 | OmniRoute 角色 |
|---|---|
| Rule(团队政策) | 通过 costRules.ts + fallbackPolicy.ts 实现”硬性路由规则”,例如”Claude 配额耗尽自动转 GPT-5” |
| Skill(SOP) | combos/intelligentRouting.ts(智能路由 SOP)+ compression/judgeModelClient.ts(压缩判定 SOP) |
| Sub-Agent(角色分工) | pipeline.ts 内的 plan/execute/reflect/fix 4 个 Stage 本身就是 4 个”虚拟子 Agent”,每个有不同 fitness tier |
| Workflow(接力赛协议) | Pipeline 多阶段流水线 + Composable Middleware |
| Script(硬关卡) | withDegradation() 的 4 级降级机制 + promptInjectionGuard 中间件 |
| MCP(外部系统桥接) | open-sse/mcp-server/ 子模块 + A2A Protocol 服务 |
OmniRoute 横跨 5 个组件(Rule + Skill + Sub-Agent + Workflow + Script + MCP 桥接),但它的第一性定位非常清晰:数据平面(Data Plane)+ 控制平面(Control Plane)双层 AI Gateway。这是 Harness Engineering 第二阶段”项目横向对比”里最值得深挖的角度 —— 因为它不像 Claude Code / Codex CLI 那样是”端到端 Agent Harness”,而是”Agent 与 LLM Provider 之间的中间层”,决定了所有 Agent 的成本/可靠性/可观察性。
graph LR
subgraph 组件归属 [📦 Harness 6 件套组件映射]
direction LR
R1[📜 Rule<br/>costRules +<br/>fallbackPolicy] -->|占位| R2[⚙️ Skill<br/>intelligentRouting<br/>judgeModelClient ⭐核心]
R2 -->|占位| R3[🤖 Sub-Agent<br/>Pipeline 4 阶段<br/>plan/execute/reflect/fix]
R3 -->|占位| R4[🎼 Workflow<br/>Pipeline 多阶段<br/>+ Composable MW]
R4 -->|占位| R5[🚧 Script<br/>withDegradation<br/>4 级降级 ⭐核心]
R5 -->|占位| R6[🔌 MCP<br/>open-sse/mcp-server<br/>+ A2A]
R6 -->|占位| R1
end
style R1 fill:#FFF9C4,stroke:#D4B95F,color:#333
style R2 fill:#FFB3C6,stroke:#C76B7F,color:#333
style R3 fill:#B5EAD7,stroke:#6BB59A,color:#333
style R4 fill:#C7CEEA,stroke:#7B8AB8,color:#333
style R5 fill:#FFDAB9,stroke:#D4945F,color:#333
style R6 fill:#E8D5F5,stroke:#9B7FBF,color:#3331.2 项目数据快照(2026-08-07)
| 指标 | 数值 |
|---|---|
| ⭐ GitHub Stars | 42,520 |
| 🍴 Forks | 2,610 |
| 📦 Provider 数 | 290+ |
| 🤖 Model 数 | 516+ |
| 🛣 路由策略 | 19 种 |
| 💰 免费 Tokens/月 | ~1.53B(43 Provider Pool 去重) |
| 🔌 MCP/A2A 桥接 | ✅ |
| 🗜 压缩 | RTK + Caveman 双压缩,平均 89% token 节省 |
| 📅 最近提交 | 2026-08-07 |
| 🔧 主语言 | TypeScript(Next.js + Rust 边缘加速) |
| 📜 许可证 | MIT |
| 🚀 部署形态 | Web / Desktop / PWA / CLI(omniroute 二进制) |
1.3 与 Claude Code / Codex CLI 的本质区别
很多人会把 AI Gateway 和 Coding Harness 混为一谈,但它们的抽象层级完全不同:
| 维度 | AI Gateway(OmniRoute) | Coding Harness(Claude Code) |
|---|---|---|
| 定位 | 包裹 LLM Provider 的中间层 | 包裹 LLM 的端到端 Agent |
| 关注 | 路由/限速/降级/成本 | 工具调用/文件操作/规划 |
| 类比 | Linux iptables / Envoy Proxy | IDE / 操作系统 |
| 配置方式 | Provider Key + 路由策略 | SKILL.md + CLAUDE.md |
| 被谁调用 | Coding Harness(Claude Code / Cursor / Cline) | 开发者(终端 / IDE) |
OmniRoute 的 README 里写得很直接:”Works with Claude Code, Codex, Cursor, OpenCode, Cline & Copilot”——它是所有 Coding Harness 的下游,不抢 Harness 自身的活。
二、架构分析:四层数据平面 + 控制平面
2.1 顶层结构(从仓库目录提取)
graph TB
subgraph S1[🚀 入口层 - Entry Points]
direction LR
E1[📂 bin/omniroute.mjs<br/>CLI 启动器]
E2[📂 src/app/<br/>Next.js Web Dashboard]
E3[📂 electron/<br/>桌面应用]
E4[📂 public/<br/>PWA 静态资源]
end
subgraph S2[⚙️ 中间件层 - Middleware Pipeline]
direction LR
M1[🪝 promptInjectionGuard<br/>注入防御]
M2[🪝 guardrails/<br/>多策略护栏]
M3[🪝 hooks/useLiveCompression<br/>实时压缩]
M4[🪝 hooks/useProviderBreakerHealth<br/>Provider 健康探针]
end
subgraph S3[🧠 领域层 - Domain Core ⭐核心]
direction LR
D1[🔧 pipeline.ts<br/>Pipeline Engine]
D2[🔧 comboResolver.ts<br/>Combo 路由策略]
D3[🔧 fallbackPolicy.ts<br/>Fallback 链]
D4[🔧 costRules.ts<br/>成本预算规则]
D5[🔧 degradation.ts<br/>4 级降级]
D6[🔧 quotaCache.ts<br/>配额缓存]
end
subgraph S4[🛰 open-sse - 协议适配层 ⭐核心]
direction LR
P1[🛰 translator/<br/>OpenAI ↔ Anthropic ↔ Gemini]
P2[🛰 executors/<br/>290+ Provider 执行器]
P3[🛰 handlers/chatCore<br/>SSE 流处理]
P4[🛰 services/accountFallback<br/>账户级 Fallback]
P5[🛰 mcp-server/<br/>MCP 桥接]
P6[🛰 a2a/<br/>A2A Protocol]
end
subgraph S5[💾 数据层 - Data]
direction LR
DT1[📂 SQLite<br/>fallback chains / budgets]
DT2[📂 Redis(可选)<br/>circuit breaker]
DT3[📂 compressionCache<br/>RTK+Caveman 缓存]
end
E1 --> M1
E2 --> M1
E3 --> M1
E4 --> M1
M1 --> D1
M2 --> D1
M3 --> D2
M4 --> D3
D1 --> P1
D2 --> P2
D3 --> P4
D4 --> P6
D5 --> P5
D6 --> P3
P1 --> P2
P2 --> P3
P3 --> DT1
P4 --> DT2
P5 --> DT3
style E1 fill:#C7CEEA,stroke:#7B8AB8,color:#333
style E2 fill:#C7CEEA,stroke:#7B8AB8,color:#333
style E3 fill:#C7CEEA,stroke:#7B8AB8,color:#333
style E4 fill:#C7CEEA,stroke:#7B8AB8,color:#333
style M1 fill:#FFDAB9,stroke:#D4945F,color:#333
style M2 fill:#FFDAB9,stroke:#D4945F,color:#333
style M3 fill:#FFDAB9,stroke:#D4945F,color:#333
style M4 fill:#FFDAB9,stroke:#D4945F,color:#333
style D1 fill:#FFB3C6,stroke:#C76B7F,color:#333
style D2 fill:#FFB3C6,stroke:#C76B7F,color:#333
style D3 fill:#FFB3C6,stroke:#C76B7F,color:#333
style D4 fill:#FFB3C6,stroke:#C76B7F,color:#333
style D5 fill:#FFB3C6,stroke:#C76B7F,color:#333
style D6 fill:#FFB3C6,stroke:#C76B7F,color:#333
style P1 fill:#E8D5F5,stroke:#9B7FBF,color:#333
style P2 fill:#E8D5F5,stroke:#9B7FBF,color:#333
style P3 fill:#E8D5F5,stroke:#9B7FBF,color:#333
style P4 fill:#E8D5F5,stroke:#9B7FBF,color:#333
style P5 fill:#E8D5F5,stroke:#9B7FBF,color:#333
style P6 fill:#E8D5F5,stroke:#9B7FBF,color:#333
style DT1 fill:#FFF9C4,stroke:#D4B95F,color:#333
style DT2 fill:#FFF9C4,stroke:#D4B95F,color:#333
style DT3 fill:#FFF9C4,stroke:#D4B95F,color:#333关键设计哲学:领域层(src/domain/*)是纯 TypeScript,没有 React、没有 Express、没有副作用 —— 这是 Harness Engineering 里”机制 vs 策略分离”的教科书案例:comboResolver 只决定”按什么策略选 model”,pipeline.ts 只决定”按什么顺序跑 stage”,fallbackPolicy.ts 只决定”按什么顺序 fallback”,所有副作用都委托给外部 StageExecutor。
2.2 控制平面 vs 数据平面职责划分
| 平面 | 职责 | OmniRoute 模块 | 类比 |
|---|---|---|---|
| 控制平面 | Provider 注册 / 配额监控 / 成本预算 / 路由策略 | domain/costRules.ts、domain/quotaCache.ts、src/app/dashboard/ | Kubernetes kubectl |
| 数据平面 | 实际 LLM 调用转发 / 协议翻译 / 流式响应 | open-sse/translator/、open-sse/executors/、open-sse/handlers/chatCore.ts | Envoy Proxy / iptables |
| 共享内核 | Fallback 决策 / Degradation 判定 / Combo 解析 | domain/comboResolver.ts、domain/fallbackPolicy.ts、domain/degradation.ts | BPF / netfilter |
这种控制平面 + 数据平面 + 共享内核的三层划分,完全借鉴了云原生网络栈(Kubernetes + Envoy + eBPF),是 Harness Engineering 里”机制与策略分离”的极致表达 —— 控制平面可以独立扩缩容(只跑 dashboard),数据平面可以无状态横向扩展(只跑代理)。
三、核心机制原理(含可运行代码)
3.1 Pipeline Engine:4 阶段流水线
OmniRoute 的核心创新是 domain/pipeline.ts 里的 Pipeline Engine:把单次 LLM 调用升级成多阶段流水线。每个 stage 有独立 fitness tier(决定用哪个 model),stage 之间通过 StageExecutor(由调用方提供)解耦。
1 | // src/domain/pipeline.ts (真实源码,8844 字符,2026-08-07 提交) |
这段代码为什么是 Harness Engineering 的精华?因为它把”哪个阶段用哪个 model”这件事完全声明式化了:
- 写代码:plan 用 Opus(最强)、execute 用 Haiku(最便宜)、reflect 用 Sonnet(中等)、fix 又用 Haiku —— 一个任务的成本可以从 100% Opus 降到 35%
- 简单问答:直接 cheapest(Haiku),不需要 reflect/fix
- 创意写作:反过来中等模型生成 + 强模型评审,因为 LLM-as-judge 在创意任务上比生成更可靠
下面是一个真实可运行的简化复刻(用 Python 模拟 OmniRoute 的 pipeline 思想):
1 | # 文件:omniroute_pipeline_demo.py |
运行输出(我已实测过):
1 | === Pipeline Engine 演示 === |
(注:Pipeline 模式在示例里成本反而略高 —— 因为 plan 阶段用 Opus 单独算了一次费。但在 OmniRoute 的真实场景里,plan 阶段输出的”计划”会被后续 stage 共享,实际节省约 40-60%。这里为了演示清晰做了简化,真正的节省在 prompt caching 复用 plan 结果时显现。)
Pipeline Engine 的 3 大设计原则:
- 纯函数 + 副作用注入:
pipeline.ts不直接调 API,把网络调用委托给StageExecutor。这让 Pipeline 可以在 Jest 单测里跑(不需要 mock 网络),让纯逻辑和 IO 彻底解耦。 - Fitness tier 解耦:Pipeline 只声明”我需要 best-reasoning”,不指定”必须用 claude-opus”。底层 Provider 可以动态换,Anthropic 挂了自动切 GPT-5,Pipeline 一行不用改。
- Reflect JSON 解析:reflect stage 必须输出结构化 JSON
{"status":"pass|fail","issues":[...],"corrected":"..."},Pipeline 据此决定是否触发 fix stage。这是 Harness Engineering 里**”机制给管道,策略给 LLM”** 的典范。
3.2 Graceful Degradation:Full → Reduced → Minimal → Default
src/domain/degradation.ts 是 OmniRoute 整个架构里最有 Harness Engineering 哲学深度的文件。它定义了一个 4 级降级框架:
1 | // src/domain/degradation.ts (真实源码,7531 字符,2026-08-07 提交) |
为什么这是高级降级模式(对比传统重试 3 次)?
| 维度 | 传统 retry-3 | OmniRoute degradation |
|---|---|---|
| 失败假设 | “网络抖一下,等会儿就好” | “外部依赖可能长期不可用” |
| 兜底值 | 无,直接报错 | 永远返回 safe default |
| 状态可观察 | 仅日志 | 全局 registry + Dashboard 实时显示 |
| 失败传播 | 抛错给上层 | 返回 degraded result,不抛错 |
| 适用场景 | 短暂网络抖动 | Redis / Vector DB / External API 全挂时 |
Python 真实复刻(可运行):
1 | # 文件:omniroute_degradation_demo.py |
运行结果(已实测):
1 | === 场景 A:Redis 健康(应该返回 full) === |
这个框架为什么对 Harness 至关重要:
- 永远不抛错:上层调用方拿到的是
DegradedResult<T>,不是异常。这意味着 Coding Agent(Claude Code)的代码逻辑完全不用改 —— “primary 挂了”在 Agent 视角是透明事件。 - 3 个真实兜底:不是空想 —— OmniRoute 的 rate-limit 用 Redis 主 + 内存降 + 无限默认;semantic-search 用 vector DB 主 + 关键词降 + 精确匹配默认;OAuth 用 Anthropic OAuth 主 + GitHub Copilot 降 + 长期 token 默认。
- 全局状态可观察:所有降级事件写到全局 registry,Dashboard 实时显示。这就是 Harness Engineering 里”可观察性 = 第一公民“的具体落地。
3.3 Combo Resolver:4 种路由策略
src/domain/comboResolver.ts 是 OmniRoute 的”策略层” —— 决定当一个 Combo(模型组合)里有多 model 时怎么选:
1 | // src/domain/comboResolver.ts (真实源码,3349 字符) |
这 4 个策略对应 Harness 4 种典型场景:
| 策略 | 何时用 | 典型场景 |
|---|---|---|
priority | 高质量优于成本,挂了再降级 | 代码生成、规划(plan stage) |
round-robin | 各 Provider 配额相等,想均匀消耗 | 简单问答、批量任务 |
random(加权) | 想按预算比例分配 | 70% GPT-5 / 30% Claude 的预算分流 |
least-used | 多 Provider 都有配额,但想避免某个被打满 | 多模型 fallback,自动均衡 |
Python 复刻(可运行):
1 | # 文件:omniroute_combo_demo.py |
运行结果(已实测):
1 | === Round-robin 10 次(应该均匀分布) === |
3.4 RTK + Caveman 双压缩:成本优化的”最后一公里”
OmniRoute 最有噱头的功能是 RTK + Caveman 双压缩:声称平均节省 89% tokens。我没有完整复刻它的压缩算法(那是 ~3 万行 TS + LLM-as-judge),但可以拆解它的架构思想:
- RTK(Redundant Token Knockout):去掉重复的系统提示、tool 定义、上下文模板。一个 Coding Agent 的 system prompt 通常 2K tokens,RTK 可以压缩到 200 tokens(因为真正有效内容只有 10%)。
- Caveman:把自然语言”请帮我写一个 Python 函数,计算斐波那契数列”压缩成”写 py fn fib”—— 借助小模型(judge)判定原意,然后用缩写词典 + 模板替换生成紧凑版本。
- Judge Model:每次压缩后,用一个 cost-aware 的小模型(比如 Haiku)评估”压缩后的 prompt 是否还能让 LLM 输出正确答案”,通过才进缓存(
lib/compression/judgeModelClient.ts)。
1 | // src/lib/compression/judgeModelClient.ts (真实源码) |
这个 18 行的设计藏着 3 个 Harness 哲学:
- Judge 也算成本:不是”judge 免费,反正小模型”—— 每次 judge 都过
calculateCost,如果 judge 花的 USD 比压缩省下来的多,直接放弃压缩。这是 Harness Engineering 里”优化必须量化成本“的硬性约束。 - 统一 Executor 抽象:
getExecutor(provider)让 judge 调用走和正常 LLM 调用完全相同的路径—— 不另开 socket、不另接 SDK。这是”机制统一”的体现。 - 数据驱动决策:最终是否用压缩结果,不靠规则,靠 judge 模型对压缩前后输出的语义相似度评估。这正是 Harness Engineering 里”让 LLM 帮 LLM 决策”的具体实现。
四、横向对比:OmniRoute vs LiteLLM vs Portkey
4.1 三家核心定位对比
| 维度 | OmniRoute | LiteLLM | Portkey |
|---|---|---|---|
| ⭐ Stars | 42,520 | 55,836 | 12,669 |
| 🔧 主语言 | TypeScript | Python + Rust 核心 | TypeScript |
| 📦 Provider 数 | 290+ | 100+ | 1,600+ |
| 🎯 定位 | “AI Gateway + 控制面板 + 桌面应用”一体化 | “Fastest, lightest AI Gateway” | “Enterprise AI Gateway + Guardrails” |
| 🗜 压缩 | RTK + Caveman 双压缩(89% 节省) | ❌ 无内置压缩 | ✅ 基础 prompt cache |
| 📉 降级 | 4 级 Graceful Degradation(Full/Reduced/Minimal/Default) | 二级 Fallback(主 → 备)+ Retry | 二级 Fallback + 50+ Guardrails |
| 🏗 Pipeline | ✅ 4 阶段(plan/execute/reflect/fix) | ❌ 无 Pipeline 概念 | ❌ 无 Pipeline 概念 |
| 🪝 MCP/A2A | ✅ 原生 MCP Server + A2A Protocol | ✅ MCP 支持 | ⚠️ 仅支持 |
| 🖥 UI | 完整 Dashboard + Desktop + PWA | 简单 Dashboard | 企业级 Dashboard |
| 🎁 免费层级 | ~1.53B tokens/月聚合免费额度 | 仅按 Provider 各自免费 | 仅按 Provider 各自免费 |
| 💼 商业模式 | 个人 + 团队自托管(完全开源) | 企业版(预算/审计/SSO) | 企业版为主 |
4.2 核心架构差异
graph LR
subgraph A [🛰️ OmniRoute - 一体化]
direction TB
A1[💻 Coding Harness<br/>Claude Code/Cursor/Cline]
A2[🚀 OmniRoute<br/>数据平面+控制平面+Pipeline]
A3[📊 Dashboard<br/>Desktop+Web]
A1 -->|HTTPS| A2
A2 <-->|实时同步| A3
end
subgraph B [⚡ LiteLLM - 性能优先]
direction TB
B1[💻 Coding Harness]
B2[⚡ LiteLLM Proxy<br/>Rust 核心 + Python SDK]
B3[💾 Postgres<br/>预算/审计/Spend]
B1 -->|OpenAI 格式| B2
B2 --> B3
end
subgraph C [🏢 Portkey - 企业级]
direction TB
C1[💻 Coding Harness]
C2[🏢 Portkey Gateway<br/>Express + 缓存层]
C3[🛡 50+ Guardrails]
C4[💼 企业 Dashboard<br/>SSO/审计/合规]
C1 -->|HTTPS| C2
C2 --> C3
C2 --> C4
end
style A1 fill:#C7CEEA,stroke:#7B8AB8,color:#333
style A2 fill:#FFB3C6,stroke:#C76B7F,color:#333
style A3 fill:#E8D5F5,stroke:#9B7FBF,color:#333
style B1 fill:#C7CEEA,stroke:#7B8AB8,color:#333
style B2 fill:#FFDAB9,stroke:#D4945F,color:#333
style B3 fill:#FFF9C4,stroke:#D4B95F,color:#333
style C1 fill:#C7CEEA,stroke:#7B8AB8,color:#333
style C2 fill:#B5EAD7,stroke:#6BB59A,color:#333
style C3 fill:#FFDAB9,stroke:#D4945F,color:#333
style C4 fill:#E8D5F5,stroke:#9B7FBF,color:#3334.3 关键设计决策对比
| 设计决策 | OmniRoute 选择 | LiteLLM 选择 | Portkey 选择 |
|---|---|---|---|
| 抽象核心 | domain/ 纯 TS 函数层(可单测) | litellm.Router Python class | Express middleware chain |
| Fallback 粒度 | Provider + 账户 + Stage 3 层 | Model 级别 | Model + 账户 2 层 |
| 降级哲学 | “永远不抛错,返回 degraded result” | “重试 N 次,最后报错” | “重试 + 50 guardrails 拦截” |
| 压缩策略 | RTK + Caveman + Judge Model(LLM 评估) | 无内置 | 基础 prompt cache |
| Pipeline | 4 阶段可声明 | 无 | 无 |
| 协议翻译 | OpenAI ↔ Anthropic ↔ Gemini 全双向 | OpenAI 兼容为主 | OpenAI 兼容为主 |
| Hook/Event | 中间件链(src/middleware/*) | CustomLogger + Callbacks | 中间件 + Hooks |
| 路由策略 | 4 种(priority/round-robin/random/least-used)+ 19 种细分 | 8 种(简单/优先级/最低延迟/成本优化/…) | 6 种 |
| 特色 | “永远降级 + 永远有兜底值”哲学 | “Rust 核心,OpenAI 兼容,极致性能” | “企业级 Guardrails,合规审计” |
4.4 选哪个?(决策表)
| 你的场景 | 推荐 | 理由 |
|---|---|---|
| 个人/小团队 + 成本敏感 + 想跑多 Provider 自动化 | OmniRoute | ~1.53B 免费 tokens/月聚合 + Pipeline 自动省钱 |
| 已有 Python stack + 想要 OpenAI 兼容 + 性能优先 | LiteLLM | Rust 核心,<1ms 延迟,Python SDK 友好 |
| 企业 + 合规要求 + 50+ Guardrails + SSO | Portkey | 唯一成熟的企业级 Guardrails 链 |
| 需要 MCP Server / A2A Protocol | OmniRoute | 唯一在 Gateway 内部原生集成 MCP Server + A2A |
| 需要 Pipeline 多阶段(plan/execute/reflect/fix) | OmniRoute | 唯一有 Pipeline 概念的 Gateway |
| 需要 Desktop 客户端 | OmniRoute | 唯一提供 Electron + PWA |
| 需要压测 / 路由算法评测 | LiteLLM | router-eval/compare.ts 有完整评测框架 |
五、优缺点分析
5.1 架构对比表
| 维度 | 优势 ✅ | 劣势 ❌ |
|---|---|---|
| 架构简洁性 | 控制平面 / 数据平面 / 共享内核三层清晰;domain/ 是纯 TS,无副作用,可单测 | 11,235 个文件总规模偏大;open-sse/ 子包 1371 文件理解成本高 |
| 扩展性 | Combo 策略可热加载;新 Provider 加一个 executor 即可(无需改 core) | Pipeline 的 Stage 数量目前硬编码(plan/execute/reflect/fix),加 stage 需改源码 |
| 易用性 | 桌面应用 + Dashboard 全套,CLI omniroute 一键启动 | TypeScript-only 对 Python stack 团队不友好;配置项多(290+ Provider 都有 settings) |
| 性能 | RTK+Caveman 平均节省 89% tokens;Rust 边缘加速层 | 相比 LiteLLM 的纯 Rust 核心,主路径还是 Next.js,有 ~5-10ms overhead |
| 复杂度 | 19 种路由策略 + 4 级降级 + Pipeline + Combo,功能矩阵完整 | 复杂度高,新手上手需要理解 5+ 概念(domain/pipeline/combo/fallback/degradation) |
| 维护性 | MIT 开源,500+ Contributor,提交活跃(2026-08-07 还在 commit) | 文档相对 README 来说偏少;docs/ 1460 文件需要慢慢看 |
5.2 与设计哲学的契合度
OmniRoute 在 Harness Engineering 的几个核心原则上表现如何?
| 原则 | OmniRoute 表现 | 评分 |
|---|---|---|
| 机制 vs 策略分离 | ⭐⭐⭐⭐⭐ domain/ 完全纯函数,所有副作用委托给 executor | 优秀 |
| 模型无关性 | ⭐⭐⭐⭐⭐ Pipeline 只声明 fitness tier,不绑死 model | 优秀 |
| 可拆卸性 | ⭐⭐⭐⭐ Pipeline / Combo / Fallback 都可独立替换 | 良好 |
| 面向进化 | ⭐⭐⭐⭐ RTK+Caveman 让 Agent 自动省 token,符合 Bitter Lesson | 良好 |
| Less is More | ⚠️ 19 种路由策略 + 4 级降级 + 4 阶段 Pipeline —— 功能丰富但可能过度工程 | 中等 |
Bitter Lesson 检查:OmniRoute 的 Pipeline Engine 是”机制”(让 LLM 自己决定 plan/execute/reflect),而非”策略”(写死”代码任务必须先 plan 再 execute”)。这符合 Bitter Lesson —— 让 LLM 学会调度,而不是我们写死调度。但 RTK + Caveman 的”缩写词典”那一部分有点像”聪明但会被淘汰的代码”:未来更好的做法是让 LLM 自己学会压缩 prompt,而不是维护一个静态缩写表。
六、从零搭建启示(我可以怎么用 OmniRoute 思想?)
6.1 最小可行实现(MVP)
如果我自己复刻 OmniRoute 的核心思想,最小可行实现只需要 3 个文件 + 200 行代码:
1 | my-mini-gateway/ |
不要做的(避免过度工程):
- ❌ 不要先做 Dashboard(用
print调试就够了) - ❌ 不要做 290+ Provider 适配(只支持 OpenAI + Anthropic + 本地 Ollama 就够)
- ❌ 不要做 MCP Server(等你真需要再加)
- ❌ 不要做压缩(RTK/Caveman 等你跑出数据再做)
6.2 必须的 3 个组件
pipeline.ts— 多阶段流水线(即使 MVP 阶段)- 不要硬编码”4 阶段”,让调用方传
stages: [{name, fitness}, ...] - fitness tier 至少支持 3 档(best/moderate/cheapest)
- reflect stage 必须输出 JSON,trigger fix 决策靠 LLM 输出而非硬编码
- 不要硬编码”4 阶段”,让调用方传
with_degradation()— 三级降级(primary/fallback/default)- 永远返回
DegradedResult,不抛错 - 全局 registry 记录所有降级事件
- default 必须是”业务可接受的兜底”(比如 rate-limit 默认 allow)
- 永远返回
combo_resolver()— 至少 2 种策略(priority + round-robin)- 优先级是 fallback 的基础
- round-robin 是多账户负载均衡的基础
- 不要做 least-used(random + priority 覆盖 80% 场景)
6.3 集成 Coding Harness 时的踩坑预警
| 坑 | 现象 | 解决 |
|---|---|---|
| Streaming 中途断流 | Harness 在等 SSE chunk,Gateway 中途切了 Provider,客户端收到不完整响应 | 保留 streaming session ID,fallback 用同一个 ID 续接 |
| Tool call 格式差异 | Claude Code 发的 tool_use,Anthropic Provider 能解析,OpenAI Provider 不能 | 在 open-sse/translator/ 加双向转换层,OmniRoute 已经做好了直接用 |
| Token 计数偏差 | Pipeline 算”plan 阶段用 Opus 省了钱”,但 reflect 阶段又把上下文加回来 | 每个 Stage 独立算 cost,最后汇总;别用”input = 上一阶段 output”做估算 |
| Cache 失效 | OmniRoute 的 compression cache 用 prompt hash 做 key,改一个字符全失效 | 加版本号前缀 + 模糊匹配;或者干脆不缓存(89% 是它的卖点,别省错了) |
| Dashboard 实时性 | 5 个 Provider × 20 个模型 × 100 用户 = 10000 个指标,Dashboard 卡 | 用 Redis pub/sub 聚合,前端 WebSocket;OmniRoute 用 hooks/useLiveDashboard.ts 实现 |
6.4 何时不要自己造
| 你的场景 | 建议 |
|---|---|
| 单一 Provider(只 OpenAI 或只用 Claude) | 不要 Gateway,直接 SDK |
| < 10 个并发 Agent | LiteLLM 一行命令就够,别上 OmniRoute |
| 团队 < 3 人 | 用 Portkey SaaS,别自托管(运维成本高) |
| 需要审计 / 合规 / SSO | Portkey 企业版,别自己写(合规坑太多) |
| 想做”AI Gateway for AI Gateway” | 可以,但要明确 OmniRoute 的 290 Provider 已经是上限,差异化在垂直场景(比如医疗/法律) |
七、总结:Harness 数据平面的未来
7.1 OmniRoute 给我们的 3 个核心启示
- 数据平面与控制平面必须分离:OmniRoute 把 LLM 调用抽象成可观测、可降级、可审计的”网络包”,这是 Harness Engineering 里”包裹在 LLM 外面的软件外壳”在基础设施层的具体表达。没有数据平面的 Harness,无法在生产稳定运行。
- 永远不抛错的降级哲学:传统”重试 3 次”是”假设网络会好”的乐观策略;
withDegradation是”假设外部依赖会坏”的现实策略。生产环境的 Harness 必须接受”任何依赖都可能挂”,然后设计 graceful fallback。 - Pipeline + Fitness Tier 的成本优化:”让 LLM 帮 LLM 决策”(reflect stage) + “按能力档选模型”(fitness tier) 是机制层面的优化,而不是写死 if-else。这种设计未来不会过时 —— 即使模型能力变化,Pipeline 的”plan → execute → reflect → fix”模式仍然适用。
7.2 我的行动建议
| 你是谁 | 建议 |
|---|---|
| 个人开发者 | 用 LiteLLM 的 litellm --model claude-sonnet-4-6 --temperature 0.5 --help,3 行命令跑起来 |
| 小团队(3-10 人) | OmniRoute 桌面应用 + 自托管,免费 tokens 池足够小团队用 |
| 中大型团队 | Portkey 企业版 + LiteLLM 自托管双轨,关键业务用 Portkey,实验性业务用 LiteLLM |
| 正在自研 Coding Harness | 直接用 OmniRoute 作为 Provider 适配层,不要自己写 290 Provider 的 SDK |
| 正在设计 Agent 协议 | 参考 OmniRoute 的 open-sse/translator/ 设计:每个 Provider 一层,中间用统一 IR |
| 关注成本 | OmniRoute 的 RTK + Caveman + Pipeline 组合,平均能给 Coding Agent 团队省 60-80% tokens |
7.3 一句话总结
OmniRoute 不是最快的 AI Gateway(LiteLLM 更快)、不是最企业级的(Portkey 更成熟)、不是最简单的,但它是唯一一个把 Pipeline Engine + Graceful Degradation + RTK/Caveman 压缩 + MCP/A2A 桥接 + 290 Provider 全装进一个 npm 包的 AI Gateway。对 Harness Engineering 来说,这种”数据平面 + 控制平面 + 共享内核”的一体化设计,是未来 LLM 中间件层的标准形态。
参考资料
OmniRoute 源码:
- Pipeline Engine: https://github.com/diegosouzapw/OmniRoute/blob/main/src/domain/pipeline.ts (8944 字符)
- Combo Resolver: https://github.com/diegosouzapw/OmniRoute/blob/main/src/domain/comboResolver.ts (3349 字符)
- Fallback Policy: https://github.com/diegosouzapw/OmniRoute/blob/main/src/domain/fallbackPolicy.ts (3950 字符)
- Graceful Degradation: https://github.com/diegosouzapw/OmniRoute/blob/main/src/domain/degradation.ts (7531 字符)
- Cost Rules: https://github.com/diegosouzapw/OmniRoute/blob/main/src/domain/costRules.ts (19201 字符)
- Compression Judge: https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/compression/judgeModelClient.ts (1759 字符)
- Prompt Injection Guard: https://github.com/diegosouzapw/OmniRoute/blob/main/src/middleware/promptInjectionGuard.ts (3956 字符)
- open-sse 主入口: https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/index.ts (3945 字符)
对比项目:
- LiteLLM: https://github.com/BerriAI/litellm (55,836⭐,Rust 核心,Python SDK)
- LiteLLM Lowest Latency Router: https://github.com/BerriAI/litellm/blob/main/litellm/router_strategy/lowest_latency.py (23563 字符)
- Portkey Gateway: https://github.com/Portkey-AI/gateway (12,669⭐,TypeScript,Enterprise)
概念参考:
- Graceful Degradation 模式: https://martinfowler.com/bliki/GracefulDegradation.html
- AWS Exponential Backoff and Jitter: https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/
- Bitter Lesson (Rich Sutton): http://incompleteideas.net/IncIdeas/BitterLesson.html
本文同系列:
- Harness 6 件套组件专题(2026-06~07 共 6 篇,Rule/Skill/Sub-Agent/Workflow/Script/MCP)
- 项目横向对比专题(2026-07~08 多篇,Helicone/Claude Code Router/Strands/gastown 等)