跳到正文
openrouter blog·· 1 天前精選AI 評分69

LangChain 與 CrewAI:與 OpenRouter 原生路由的協調比較

LangChain vs CrewAI: Orchestration Compared to OpenRouter-Native Routing

AI 導讀

本文說明 LangChain 與 CrewAI 在多模型協調方面的差異,並示範如何將 OpenRouter 原生路由與這兩個框架結合。

  • 三層架構:工作流協調、模型路由、供應商路由。
推薦理由

文章說明多模型協調的三層架構,並示範如何將 OpenRouter 與 LangChain 或 CrewAI 結合,對構建可擴充的 LLM 工作流十分實用。

正文 · AI 翻譯

你在工作流程中需要多於一個模型。一個成本較低的模型處理例行呼叫,較強的模型處理困難的任務。像 LangChain 與 CrewAI 的代理框架是構建此功能的一種方式。兩者都提供協調層,但組織方式不同。LangChain 的執行環境 LangGraph 為你提供明確的狀態與控制流程。CrewAI 則以角色為基礎的代理與事件驅動流程來組織工作。

兩個框架在你構建具備規劃、保持狀態、呼叫工具或委派工作功能的代理時都很有幫助。若你只需要為每一步選擇模型並在失敗時回退,完整的協調框架會加入你不會使用的部份。

本文比較 LangChain 與 LangGraph、CrewAI,以及 OpenRouter 原生路由,依各自執行的工作。它展示了直接對 OpenRouter 寫出的相同兩步驟流程以及通過 LangChain 寫出的流程,說明我們的 Agent SDK 位於兩者之間的位置,並說明如何在需要同時使用協調與路由時,將 OpenRouter 放在任一框架之下。

TL;DR

  • 多模型協調包含三個層次。工作流程協調涵蓋規劃、狀態、記憶與委派。模型路由是為一次呼叫選擇模型並在返回錯誤時回退。供應商路由則是選擇哪個供應商端點提供你選擇的模型。
  • LangGraph 與 CrewAI 進行工作流程協調。OpenRouter 處理模型路由與供應商路由。兩者互不取代。
  • OpenRouter 的 models 引數是一個有序的回退列表。當第一個模型返回錯誤時,我們嘗試下一個。回退是錯誤驅動的,並不評估答案品質。
  • 我們的 Agent SDK 處理中間情境,即帶驗證、串流與停止條件的有界多輪工具迴圈,且不使用持久化圖或基於角色的工作團隊。
  • LangChain 擁有專用的 ChatOpenRouter 整合,CrewAI 透過其 LLM 類別將 OpenRouter 作為供應商進行檔案說明。你可以保留任一框架的協調功能,並將 OpenRouter 作為底層模型層使用。

三層共稱為一個名稱

「多模型協調」這個詞涵蓋三個不同的決策。將它們分開可以縮短框架比較。

工作流程協調 是規劃、狀態、記憶與委派。你將任務拆分為步驟,跨回合與跨執行保持狀態,暫停以供人類審查,並將子任務交給其他代理。LangGraph 與 CrewAI 為此層設計。

模型路由 是選擇哪個模型處理特定呼叫,以及該模型返回錯誤時的處理方式。OpenRouter 的 models 引數在一個請求欄位中處理此問題。

供應商路由 是選擇哪個供應商端點提供你已選擇的模型。OpenRouter 上的許多模型由多個供應商提供。對每個請求,我們在符合條件的供應商中選擇,且對包含工具的請求,Auto Exacto 會依照工具呼叫效能重新排序這些供應商。供應商路由永遠不會改變你所要求的模型。

Diagram of three layers. Workflow orchestration at the top covers planning, state, memory, human review, and delegation, and is provided by LangGraph, CrewAI, or the OpenRouter Agent SDK for bounded tool loops. Model routing in the middle covers choosing a model per call and error-driven fallback through the OpenRouter models list. Provider routing at the bottom covers choosing a provider endpoint for the chosen model, with Auto Exacto reordering providers on tool-calling requests.

一個工作流程可能需要三者。規劃邏輯決定下一步,模型路由決定使用哪個模型,供應商路由決定哪個端點提供該模型。你不需要第一層就能得到後兩層。models 列表和若干 if 陳述式即可在沒有代理框架的情況下在模型之間進行路由。

LangChain 與 LangGraph

LangChain 目前的檔案說明有兩個不同角色的產品。LangChain 是代理框架,提供模型、工具與代理迴圈的抽象與整合。LangGraph 是其底層的低階協調執行環境,著重於耐久執行、串流、人機互動與持久化。你可以不使用 LangChain 直接使用 LangGraph,而 LangChain 的預建代理則執行於 LangGraph 上。

LangGraph 將工作流程建模為節點圖。你可以在同一圖中混合使用決定性、手動編碼的步驟與模型驅動的步驟。持久化由兩個元件提供。checkpointer 會為執行緒儲存圖狀態,提供對話連續性、容錯、時間旅行,以及人機審查的基礎。store 則將應用資料儲存在圖狀態之外,以實現長期、跨執行緒的記憶。interrupt() 函式會在節點的任何位置暫停執行,透過 checkpointer 儲存狀態,並等待你以 Command 重新啟動,讓人員可以在執行繼續前審核、編輯或拒絕該步驟。

這種控制的代價是你必須自行描述控制流程。每個節點、邊、狀態列位、checkpointer 與中斷都是你編寫並維護的程式碼。若你需要一個多步驟管線,且每個節點都可檢查與可續行,LangGraph 能提供結構;若你只是需要模型呼叫並具備回退功能,那麼它已超出需求。

CrewAI

CrewAI 的檔案說明瞭兩個基礎構件。Crew 是代理團隊,每個代理都有角色、目標與背景故事,並負責執行指定任務。Crew 以順序流程執行任務,任務輸出成為下一個任務的上下文;或以階層流程執行,管理模型或管理代理負責指派與協調任務。當 allow_delegation 啟用時,代理可相互委派;每個代理都有一個 max_iter 限制,預設為 20,並可選擇性設定 max_execution_time。

Flows 是環繞 Crew 的結構化、事件驅動層。Flow 定義步驟、在步驟間流動的狀態,以及控制流程,包括條件邏輯、迴圈與分支。每個 Flow 例項攜帶一個唯一 ID 的狀態物件,並在執行期間持久化。CrewAI 的說明將 Flow 視為應用的骨幹,而 Crew 為 Flow 內的工作單元。

CrewAI 的模型更像是任務描述,而非圖結構定義。你投入更多精力於角色、目標與任務字串,較少在節點連結上。這與 LangGraph 的不同取捨,而非其縮小版。Crew 讓代理自行決定完成任務的方式,Flow 則是你重新掌握控制權的地方。

Comparison

LangChain and LangGraphCrewAIOpenRouter direct
Built for以圖為基礎的協調,具備明確的狀態、持久化與人機審查以角色為基礎的代理團隊,嵌入事件驅動的 Flow每次呼叫選擇模型、錯誤驅動的回退與供應商路由
多模型支援是,節點或代理各自擁有一個模型物件是,每個代理、Crew 或管理者各自擁有一個 LLM是,每個請求都有一個 models 列表
規劃、記憶與委派是,明確於圖、checkpointer 與 store是,透過代理、流程與 Flow 狀態否,僅提供路由
串流是是,在 Crew 級別使用 stream=True是,每個請求
人機審查interrupt() 伴隨 checkpointer由你撰寫的 Flow 邏輯未提供
你撰寫的內容節點、邊、狀態模式與持久化設定代理、任務、Crew 與 Flow 定義請求主體

OpenRouter 原生路由

“Native” 這裡指的是不使用任何框架。你會對 https://openrouter.ai/api/v1/chat/completions 傳送請求,並在 models 引數中以優先順序列出你的模型,剩餘流程由我們處理。若第一個模型回傳錯誤,我們會嘗試列表中的下一個模型。預設情況下,任何錯誤都能觸發回退,包括上下文長度驗證錯誤、過濾模型的審核標記、速率限制以及停機。若回退模型也回傳錯誤,我們將回傳該錯誤。請求的價格以最終提供服務的模型計算,回應中的 model 欄位會告訴你是哪一個模型。

回退機制會對錯誤作出反應。它不會評估第一個模型的答案是否正確。若你想讓更強大的模型審核較弱模型的輸出,那是你程式碼中的第二個步驟,而非 models 列表所能做到的。

以兩步驟流程為例,先用一個模型草擬,然後用另一個模型審核草稿;若第一個模型回傳錯誤,兩步驟皆會回退。直接針對 OpenRouter 寫成,這樣就只需要一個函式和兩個 models 列表。

import os

import requests


def route(models: list[str], prompt: str) -> tuple[str, str]:
    response = requests.post(
        "https://openrouter.ai/api/v1/chat/completions",
        headers={"Authorization": f"Bearer {os.environ['OPENROUTER_API_KEY']}"},
        json={"models": models, "messages": [{"role": "user", "content": prompt}]},
        timeout=120,
    )
    response.raise_for_status()
    body = response.json()
    return body["choices"][0]["message"]["content"], body["model"]


draft, draft_model = route(
    ["anthropic/claude-sonnet-5", "openai/gpt-5.6-sol"],
    "Draft a one-paragraph summary of what a model fallback list does.",
)
review, review_model = route(
    ["openai/gpt-5.6-sol", "anthropic/claude-sonnet-5"],
    f"Review this draft for accuracy and suggest one improvement:\n\n{draft}",
)
print(f"draft by {draft_model}, review by {review_model}")
print(review)

若要將某一步驟送至不同模型,你只需更改列表。由於我們的 API 相容 OpenAI,所有聊天模型都可使用相同的聊天完成請求格式,而模型變更只需改變一個字串。服務其他端點的模型,例如嵌入、影片、文字轉語音或語音轉文字,則使用各自的請求格式。

同樣的流程在 LangChain 中使用專用的 ChatOpenRouter 模型類別。你為每一步建立一個模型物件,並用 LangChain 的 with_fallbacks 包裝每個物件,使失敗的呼叫會重試下一個模型物件,最後透過 invoke 呼叫結果。

from langchain_openrouter import ChatOpenRouter

drafter = ChatOpenRouter(model="anthropic/claude-sonnet-5").with_fallbacks(
    [ChatOpenRouter(model="openai/gpt-5.6-sol")]
)
reviewer = ChatOpenRouter(model="openai/gpt-5.6-sol").with_fallbacks(
    [ChatOpenRouter(model="anthropic/claude-sonnet-5")]
)

draft = drafter.invoke("Draft a one-paragraph summary of what a model fallback list does.")
review = reviewer.invoke(
    f"Review this draft for accuracy and suggest one improvement:\n\n{draft.content}"
)
print(review.content)

兩種版本都以相同的兩步驟、相同的兩個模型、相同的回退順序進行路由。差異在於回退執行的位置。在直接版本中,我們在單一請求內於伺服器端執行回退;在 LangChain 版本中,框架會在你的流程中捕捉失敗呼叫並傳送第二個請求。對於使用 LangChain 的 create_agent 構建的代理,框架還提供 ModelFallbackMiddleware,在主模型失敗時嘗試其他模型。框架版本為你提供模型物件和共用的 invoke 介面,這正是你在有圖形、檢查點或工具管理集時所需要的結構。若沒有,則為額外負擔。

透過我們的路由(無論哪種版本)會帶來三項功能。每一次回應都會包含一個 usage 物件,內含 token 數量與以信用計算的成本,且不需要額外引數,讓你能在決定是否採用分層設定前先了解每一次呼叫的成本。Prompt caching 在支援的模型上可降低重複上下文的費用。若請求包含工具,Auto Exacto 會預設執行。它會根據吞吐量、工具呼叫成功率與基準資料重新排序你選擇模型的供應商,讓工具呼叫落在有良好工具呼叫紀錄的供應商,而不需要你額外設定。Auto Exacto 改變的是供應商順序,而非模型。

直接路由不會規劃、跨回合保持狀態,也不決定哪些子任務分配給哪個代理。這是工作流程編排層,而 models 列表並不提供此功能。下一個層級不一定是完整框架。

The OpenRouter Agent SDK

在直接路由與完整框架之間,我們的 Agent SDK,即 @openrouter/agent 套件。聊天完成是無狀態的。你傳送訊息並得到一次回應。將其轉換為代理意味著執行一個迴圈,模型請求工具呼叫,你的程式碼驗證引數並執行工具,結果回傳給模型,迴圈重複直到工作完成。Agent SDK 將該迴圈打包為一個 callModel 函式。

你可以使用 tool() 助手和 Zod 模式定義工具,SDK 會處理驗證、執行以及跨回合的對話狀態。停止條件如 stepCountIs 與 maxCost 限制迴圈。每個條件在步驟完成後檢查,因此 maxCost 會在達到閾值的那一步之後停止迴圈,而非阻止該步驟,且預設 SDK 會再進行一次模型回合以產生最終答案。將 maxCost 視為停止規則,而非消費上限。串流已內建,你亦可將遠端 MCP 伺服器作為工具來源。

import { OpenRouter, tool, stepCountIs, maxCost } from "@openrouter/agent";
import { z } from "zod";

const client = new OpenRouter({ apiKey: process.env.OPENROUTER_API_KEY });

const result = client.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: new Date().toLocaleString("en-US", { timeZone: timezone }),
      }),
    }),
  ],
  stopWhen: [stepCountIs(5), maxCost(0.5)],
});

const text = await result.getText();
console.log(text);

SDK 使用 TypeScript 編寫,Python 與 Go 版本保持同步。它提供帶驗證、串流與停止條件的受限工具迴圈。它不提供持久化圖、檢查點或基於角色的團隊。

在單一請求內進行委派時,openrouter:subagent 伺服器工具允許模型在生成過程中將自包含任務交給工作者模型。工作者可為 OpenRouter 上任何模型。每個任務獨立,工作者僅看到任務描述,且不保留任務間記憶。伺服器工具仍處於測試階段,API 與行為可能變更。

SDK 亦支援人類審核與在該迴圈內持久化對話狀態。工具可設定 requireApproval 以在執行前暫停,且 StateAccessor 在 callModel 呼叫之間持久化訊息、審核與工具結果。它不提供帶明確轉換與檢查點的持久化圖,亦無跨代理團隊協調功能。若需要這些功能,則應升級至 LangGraph 或 CrewAI。

在 LangChain 或 CrewAI 下使用 OpenRouter

不必在框架與閘道之間做選擇。你保留框架的規劃、狀態與委派,並將 OpenRouter 作為其下方的模型層。

使用 LangChain,我們維護一個專用的 integration。Python 的 langchain-openrouter 套件與 JavaScript 的 @langchain/openrouter 套件為你提供一個 ChatOpenRouter 模型,你可以將代理與圖表指向它。LangChain 的檔案目前將 Python integration 標記為 beta。

from langchain_openrouter import ChatOpenRouter

model = ChatOpenRouter(
    model="anthropic/claude-sonnet-5",
    temperature=0,
    model_kwargs={"models": ["anthropic/claude-sonnet-5", "openai/gpt-5.6-sol"]},
)

ChatOpenRouter 物件傳送一個 model 值。若要在 LangChain 下使用我們的伺服器端回退,請將 models 清單透過 model_kwargs 傳遞,該套件會將其展開到請求主體中。若未提供,回退由框架處理,如上方 with_fallbacks 範例所示。

使用 CrewAI,你可以用我們的端點配置其 LLM 類別。CrewAI 的 LLM documentation 列出 OpenRouter 為使用 LiteLLM 的供應商,因此你安裝 crewai[litellm] extra,將模型 slug 字首為 openrouter/,並傳入我們的基礎 URL 與你的金鑰。

import os

from crewai import LLM

llm = LLM(
    model="openrouter/anthropic/claude-sonnet-5",
    base_url="https://openrouter.ai/api/v1",
    api_key=os.environ["OPENROUTER_API_KEY"],
)

CrewAI 範例設定單一模型。供應商路由適用於每一次請求,改變哪個模型處理某一步即為更改 slug。伺服器端模型回退僅在請求攜帶 models 清單時適用,而 CrewAI 檔案未說明如何傳遞此欄位。無論如何,你的圖表或團隊皆可按設計運作,切換至不同模型即為設定變更,而非新增供應商整合或每個模型使用獨立 API 金鑰。

選擇層級

如果你的直接實作開始累積狀態機、可恢復的檢查點、審批步驟與委派規則,你就會手動構建工作流程協調層,而框架則取代了本來你需要自行設計與維護的程式碼。這是我們的編輯指導,而非產品保證,且從應用程式必須擁有的行為開始。

  • 當工作流程已經明確,且你只需為每次呼叫選擇模型、加入備援列表或控制供應商路由時,請使用 OpenRouter 原生路由。
  • 若你需要受限的多輪工具迴圈,並具備驗證、串流與停止條件,而不需要持久化圖形或基於角色的工作團隊,請使用 OpenRouter Agent SDK。
  • 若你需要明確的狀態轉移、持久化、恢復、人為審查,或結合決定性與模型驅動步驟,請使用 LangGraph。
  • 當工作對應於專業代理、任務委派以及順序或分層協作,且環境應用程式需要結構化狀態與控制時,請使用 CrewAI。
  • 若你希望框架負責協調,OpenRouter 負責模型存取與供應商路由,並在框架轉發 models 列表時提供伺服器端模型備援,請將 OpenRouter 放在 LangGraph 或 CrewAI 之下。

結論

多模型協調包含三層。工作流程協調涵蓋規劃、狀態、記憶與委派,LangGraph 與 CrewAI 為此而設,且具有不同的權衡。LangGraph 讓你以明確圖形控制為代價自行編寫控制程式;CrewAI 以角色為基礎的代理與流程為代價,將更多執行路徑交給代理。模型路由與供應商路由是 OpenRouter 的功能,無論框架是否位於其上,我們都以相同方式處理。

如果你不確定專案處於哪一邊,先嘗試較小的承諾。使用 models 清單將兩步流程路由到兩個模型,先決定是否需要在其上層加框架。在為任何方式選擇模型時,models directory 讓你可依支援的引數過濾,包括 tools。

常見問題

我需要使用 LangChain 或 CrewAI 才能使用多個模型嗎?

不需要。若你的唯一需求是為一次呼叫選擇模型,並在第一個模型返回錯誤時備援至另一模型,OpenRouter 的 models 引數即可在一次請求中完成。若工作流程還需要規劃、持久化狀態、記憶、人為審查或代理間的委派,請選擇 LangGraph 或 CrewAI。

如何在一個代理工作流程中協調多個 LLM?

分層處理。對於跨步驟的規劃、狀態與委派,使用 LangGraph 或 CrewAI 等協調框架。對於選擇哪個模型處理每次呼叫,將有序的 models 列表傳送給 OpenRouter,讓我們在第一個模型返回錯誤時備援至下一個模型。我們也會為執行呼叫的模型選擇供應商端點。工作流程可同時使用兩者,框架位於上層,OpenRouter 位於下層作為模型層。

我可以將 OpenRouter 與 LangChain 或 CrewAI 一起使用,而不是選擇其中一個嗎?

是的。LangChain 在 Python 的 langchain-openrouter 套件中提供專用的 ChatOpenRouter 整合,JavaScript 的 @langchain/openrouter 套件也同樣。CrewAI 透過其使用 LiteLLM 的 LLM 類別,將 OpenRouter 記錄為提供者。在兩種情況下,框架保持編排功能,而 OpenRouter 提供模型存取與供應商路由。我們的伺服器端模型回退僅在請求攜帶 models 列表時執行,該列表由 ChatOpenRouter 透過其 model_kwargs 引數轉發。

採用 LangChain 或 CrewAI 會否將我鎖定於單一模型供應商?

不會,只要將框架指向 OpenRouter 而非單一供應商的 SDK。兩個框架都接受 OpenRouter 作為模型供應商,因此改變處理某一步驟的模型,只需在框架設定中更改模型字串,而不必重寫供應商整合。你仍可存取 OpenRouter 上的所有模型。

OpenRouter 的模型回退是否會評估答案的品質?

不會。回退是基於錯誤的。當你 models 列表中的第一個模型返回錯誤(例如上下文長度驗證錯誤、審核旗標、速率限制或停機),我們會嘗試列表中的下一個模型。成功的回覆將原樣返回,且回覆的 model 欄位會告訴你是哪個模型產生的。

參考文獻

來源:openrouter blog · openrouter.ai