
多模型编排的三层框架、模型路由与提供商路由原文OpenRouter Blog - 《LangChain vs CrewAI: Orchestration Compared to OpenRouter-Native Routing》https://openrouter.ai/blog/insights/langchain-vs-crewai-orchestration-compared-to-openrouter-native-routing/做 Agent 应用时「多模型」很容易被当成一件事接几个模型写个 if-else 挑一个。真到要落地才发现这里混着三件不同的事——谁负责拆任务、谁负责在模型之间切换、谁负责给同一个模型挑服务端点。三层揉成一层代码会越写越难改分开看很多「我是不是得上 LangGraph」的纠结能自己回答。下面按 OpenRouter 10 月 2 日那篇对比文的结构把三层摊开再给出可以直接跑的最小代码。一、先分清三层职责层回答的问题由谁负责工作流编排任务怎么拆、状态放哪、哪一步要人看、子任务交给谁LangGraph、CrewAI模型路由这一次调用打哪个模型它报错之后怎么办请求里的 models 参数提供商路由已经选定的模型由哪个端点来服务OpenRouter 自动完成三层是三种不同的问题混在一个「模型选择器」里写后面任何一层要改都得动同一坨代码。分开之后三层可以各自替换。二、工作流编排层LangGraph 和 CrewAI 给了什么这一层解决的是「长任务怎么活下去」两个主流框架走的是两条路。2.1 LangGraph把工作流画成图LangGraph 把工作流建模成一张节点图确定性的人写步骤和模型驱动的步骤可以混在同一张图里。它靠两个组件解决持久化Checkpointer按 thread 保存图的状态中断后可以从断点继续Store把应用数据存在图状态之外跨 thread 复用状态interrupt()在图里任意位置暂停等人审批后继续。它的取舍很清楚控制权完全在你手里代价是节点、边、状态 schema、持久化配置都得自己写。2.2 CrewAI用角色和任务描述替代图CrewAI 的心智模型更接近「写一张任务单」而不是「画一张图」Crew一组 Agent每个有 role、goal、backstory按分配的任务推进流程可以是 sequential顺序也可以是 hierarchical带管理者allow_delegation打开后 Agent 之间可以互相委派每个 Agent 有max_iter上限默认 20还可以设 max_execution_timeFlow包在 Crew 外面的结构化、事件驱动层。官方把 Flow 定位成应用的骨架Crew 是里面的工作单元。你花的力气更多在 role / goal / task 这三段文字上更少在连节点上。代价是把更多执行路径的决定权交给了 Agent 自己。三、模型路由层一个列表就能覆盖大部分需求这一层不需要框架。直接请求 chat/completions 端点把候选模型按优先级写进 models 参数剩下的交给服务端第一个模型报错就试下一个。默认情况下任何错误都能触发回退包括上下文长度校验失败、被过滤模型的审核拦截、限流、服务不可用。计费按最终提供服务的那个模型算响应里的 model 字段告诉你是哪一个。fallback 只对错误生效它不判断第一个模型的答案好不好。这句话是整个话题里最容易误会的地方想要「答案质量不达标就升级」那是工作流编排层的活得自己在代码里判。最小可跑的例子官方原文示例# 直接请求 OpenRouter用 models 列表做优先级回退importosimportrequestsdefroute(models:list[str],prompt:str)-tuple[str,str]:responserequests.post(https://openrouter.ai/api/v1/chat/completions,headers{Authorization:fBearer{os.environ[OPENROUTER_API_KEY]}},# models 是有序回退列表第一个报错就用下一个json{models:models,messages:[{role:user,content:prompt}]},timeout120,)response.raise_for_status()bodyresponse.json()# 返回值里带上是哪个模型真正服务的方便埋点returnbody[choices][0][message][content],body[model]draft,draft_modelroute([anthropic/claude-sonnet-5,openai/gpt-5.6-sol],Draft a one-paragraph summary of what a model fallback list does.,)review,review_modelroute([openai/gpt-5.6-sol,anthropic/claude-sonnet-5],fReview this draft for accuracy and suggest one improvement:\n\n{draft},)print(fdraft by{draft_model}, review by{review_model})print(review)这段代码里三个参数值得记一下models 是有序列表越靠前越优先timeout 给足示例取 120 秒因为回退意味着可能真的跑完一次才失败返回值直接取 model 字段。拿到它以后建议立刻打点——回退率、回退最终命中哪个模型是判断这条链健不健康的第一手数据。同样的两步流程换成 LangChain写法是给每个模型对象挂 fallbacks# 同样的事情换成 LangChain编排由框架管模型层仍然走 OpenRouterfromlangchain_openrouterimportChatOpenRouter drafterChatOpenRouter(modelanthropic/claude-sonnet-5).with_fallbacks([ChatOpenRouter(modelopenai/gpt-5.6-sol)])reviewerChatOpenRouter(modelopenai/gpt-5.6-sol).with_fallbacks([ChatOpenRouter(modelanthropic/claude-sonnet-5)])draftdrafter.invoke(Draft a one-paragraph summary of what a model fallback list does.)reviewreviewer.invoke(fReview this draft for accuracy and suggest one improvement:\n\n{draft.content})print(review.content)对比两段代码能看出分工一个是你自己写调用顺序一个是框架替你管流程。模型层的部分用哪些模型、出错怎么退两边完全一样。四、提供商路由层同一个模型不同端点一个模型在 OpenRouter 上往往有多个提供商在服务。提供商路由换的是端点不是模型你请求的是同一个模型系统在符合条件的提供商里挑一个。当请求里带工具时Auto Exacto 默认生效按吞吐、工具调用成功率、基准数据重排提供商顺序。这一层平时不需要你操心但对 Agent 场景有两层含义工具调用密集的链路端点质量会直接影响成功率而这类重排发生在「你已经选定的模型」内部不会悄悄换成另一个模型。五、中间那一段带边界的工具循环很多 Agent 既不需要一张持久化的图也不需要一支带角色的团队只需要一个「有上限的多轮工具循环」。OpenRouter 的 Agent SDK 就是冲这一段来的示例为官方 TypeScript 代码// 有界的多轮工具循环停止条件写在调用里import{OpenRouter,tool,stepCountIs,maxCost}fromopenrouter/agent;import{z}fromzod;constclientnewOpenRouter({apiKey:process.env.OPENROUTER_API_KEY});constresultclient.callModel({model:anthropic/claude-sonnet-5,input:What time is it in Tokyo?,tools:[tool({name:get_time,description:Get the current time in a timezone,inputSchema:z.object({timezone:z.string()}),execute:async({timezone})({time:newDate().toLocaleString(en-US,{timeZone:timezone}),}),}),],// 什么时候停步数上限或成本上限先到先停stopWhen:[stepCountIs(5),maxCost(0.5)],});consttextawaitresult.getText();console.log(text);stepCountIs(5)和maxCost(0.5)是停止条件不是消费上限——原文特意点明了这一点达到条件循环就停别把它当成账单封顶。该 SDK 里还有一个openrouter:subagent能力标注为 beta。六、对照表与选型建议LangGraphCrewAI直接路由为谁而生显式状态、持久化、人工审批的图式编排事件驱动 Flow 里的角色制 Agent 团队每次调用选模型、错误驱动回退、提供商路由多模型支持每个节点或 Agent 一个模型对象每个 Agent、Crew 或 manager 一个 LLM每个请求一个 models 列表规划、记忆、委派有写在图、Checkpointer、Store 里有通过 Agent、流程与 Flow 状态没有只有路由流式输出有有Crew 级别有按请求人工介入interrupt Checkpointer自己写 Flow 逻辑不提供你要写什么节点、边、状态 schema、持久化配置Agent、Task、Crew、Flow 定义一个请求体选型上原文的建议很实际先做小承诺。想不清楚需不需要框架就先用 models 列表把一个两步流程跨两个模型跑通再判断是不是真需要上面那层。两层不互相替代也不需要为了拿到下面两层而先引入框架——一个列表加几个 if 就能在多模型间路由。反过来如果你已经在用 LangChain 或 CrewAI也没必要换掉LangChain 有专门的ChatOpenRouter集成CrewAI 通过 LLM 类把 OpenRouter 当 provider。保留框架的编排把模型与提供商路由放在下面一层是更常见的组合。七、给 Agent 开发学习者的启示真正的分界线不是「用不用框架」而是「状态要不要跨轮、跨运行活下去」。需要人工审批、需要断点续跑、需要把子任务稳定地派给不同 Agent就上编排层只要一次请求内把活干完一个 models 列表往往就够了多引入一层只是多一层要维护的东西。另外两条可以直接拿来用的经验回退策略要按错误类型梳理一遍别默认「所有错误都该回退」——比如内容审核拦截回退到另一个模型大概率还是被拦白白多花一次调用工具调用链路的成功率要跟端点质量一起看工具密集时这类差异会被放大。小结多模型编排是三层工作流编排负责规划、状态、记忆与委派LangGraph 用图换来显式控制CrewAI 用角色与 Flow 换来更少的连边工作模型路由负责选模型和在报错时回退一个 models 列表即可提供商路由负责在同一个模型的多个端点间挑选并在带工具时优先工具调用质量。三层可以拆开用也可以叠起来用——先判断题目的边界再决定要不要框架。文中模型名与代码来自 OpenRouter 原文示例框架与 SDK 的具体版本请以官方文档为准此处未验证最新版本。