當不同代理可以使用不同模型時,使用 CrewAI 構建多代理系統會變得更有趣。
研究人員可能受益於快速、經濟的模型,分析師可能需要更強的推理模型,而撰稿者可能需要針對高品質長篇生成優化的模型。傳統上,將這些代理連接到不同供應商意味著要管理各自的 API 憑證、端點、SDK、計費系統以及供應商特定的設定。
更乾淨的架構是讓CrewAI 管理代理與工作流,而 CometAPI 管理模型存取。
CometAPI 在 https://api.cometapi.com/v1 提供與 OpenAI 相容的端點,因此應用程式可以透過共同的 API 介面,將請求路由到多個供應商的模型。其目前的快速入門文件也支援透過更換 API key 與 base URL 來使用標準的 OpenAI Python SDK。
在本教學中,你將建立一個包含三個代理的 CrewAI 工作流,配置如下:
- 用於研究的 Gemini 3.7 Flash
- 用於分析的 Claude Opus 5
- 用於最終寫作的 GPT-5.6
- 一組 CometAPI API key
- 一個 API base URL
- 每個代理的模型獨立配置
- 針對暫時性失敗的有界回退
- 用於生產恢復的 CrewAI 檢查點
- Token 與執行使用量追蹤
- 伺服端模型驗證
重要的架構邊界很簡單:
CrewAI 處理代理協調。CometAPI 處理模型存取。以模型 ID 定義路由。
什麼是 CrewAI 多代理模型路由?
CrewAI 是一個用於建立代理、任務、隊伍(Crew)與多代理工作流的 Python 框架。每個代理都可以有自己的 LLM 配置,而 Crew 負責協調這些代理如何執行任務與交換上下文。
CrewAI 目前的 LLM 配置支援顯式設定 model、api_key 與 base_url,包含自訂的與 OpenAI 相容的端點。
這使多模型架構變得直觀:
CometAPI │ https://api.cometapi.com/v1 │ ┌───────────────────┼───────────────────┐ │ │ │ Researcher Analyst Writer │ │ │ Gemini 3.7 Flash Claude Opus 5 GPT-5.6
從邏輯角度看,代理仍然是彼此獨立的,但其模型存取被集中管理。
這與宣稱所有模型可互換不同。與 OpenAI 相容的 API 提供共同的請求介面;但它並不保證相同的上下文限制、工具支援、推理控制、輸出行為、延遲或定價。
在設計生產路由時,這個區別很重要。
為何將 CometAPI 與 CrewAI 搭配?
主要優勢並非 CrewAI 突然變成多供應商框架。CrewAI 已經支援多個 LLM 供應商。
優勢在於可以將模型存取整合到一個 API 層後。
如果沒有統一的 API 層,三代理工作流可能是這樣:
| Agent | Provider | Credential | Integration |
|---|---|---|---|
| Researcher | Google API key | Provider-specific | |
| Analyst | Anthropic | Anthropic API key | Provider-specific |
| Writer | OpenAI | OpenAI API key | Provider-specific |
使用 CometAPI 後:
| Agent | Model | Credential | Endpoint |
|---|---|---|---|
| Researcher | Gemini 3.7 Flash | CometAPI key | CometAPI |
| Analyst | Claude Opus 5 | CometAPI key | CometAPI |
| Writer | GPT-5.6 | CometAPI key | CometAPI |
CometAPI 目前的快速入門文件描述其端點可作為 OpenAI API base URL 的即插即用替代,並透過同一服務列出來自多個供應商的模型。
這為應用程式帶來了有用的分層:
CrewAI
- 定義代理角色
- 定義任務
- 傳遞上下文
- 控制執行
- 管理代理迭代
- 處理隊伍層級的協調
CometAPI
- 提供共同的模型存取層
- 集中 API 驗證
- 透過模型 ID 提供路由
- 提供單一 API 端點
- 提供集中化的使用量與計費可見性
這個 CrewAI 工作流會產生什麼?
此範例建立三個按序執行的代理。
| CrewAI Agent | Primary Model | Fallback | Role |
|---|---|---|---|
| Market Researcher | gemini-3.7-flash | gpt-5.6 | 收集事實與研究 |
| Product Analyst | claude-opus-5 | gpt-5.6 | 綜合證據與權衡 |
| Technical Writer | gpt-5.6 | gemini-3.7-flash | 產出最終決策備忘錄 |
這是一個示例路由策略,並非基準排名。
為代理選擇合適的模型取決於:
- 任務複雜度
- 需要的上下文長度
- 工具使用
- 結構化輸出需求
- 延遲
- 可靠性
- Token 成本
- 輸出品質
- 應用特定的評估結果
一條有用的準則是:
為代理所執行的工作選擇模型,而不僅僅是依據供應商。
每個 CrewAI 代理應使用哪個模型?
在此範例中,模型分配遵循簡單的成本與能力策略。
Researcher:Gemini 3.7 Flash
研究通常涉及處理相對大量的資訊並產出精煉的中間結果。
因此,快速的模型對於高量研究任務很有幫助。
"researcher": "gemini-3.7-flash"
Analyst:Claude Opus 5
分析師的角色較窄但更偏重推理。它接收研究成果並將其轉化為建議。
"analyst": "claude-opus-5"
Writer:GPT-5.6
最終代理將研究與分析轉換成面向開發者的決策備忘錄。
"writer": "gpt-5.6"
重點不在於這三個具體分配。你的應用應該針對代表性任務評估候選模型,然後再固定路由策略。
開始前需要什麼?
你需要:
- Python 3.10+
- CrewAI
- OpenAI Python SDK 相容性
python-dotenv- 一組 CometAPI API key
- 你打算使用的模型 ID
CometAPI 目前的 Python 整合支援與 OpenAI 相容的 API,且官方的 CometAPI Python 套件以環境變數形式記錄 COMETAPI_KEY 與 COMETAPI_BASE_URL 的配置選項。
標準端點為:
https://api.cometapi.com/v1
在部署前,請確認所選的模型 ID 目前可用,並支援你的 CrewAI 工作負載所需的端點與參數。模型目錄與定價可能會改變。
如何安裝 CrewAI 與相依套件?
建立新的 Python 環境:
python -m venv .venv
啟用它:
source .venv/bin/activate
在 Windows:
.venv\Scripts\Activate.ps1
接著安裝相依套件:
pip install "crewai[openai]" openai python-dotenv
顯式使用 openai 是刻意的,因為下方的回退實作會直接匯入 OpenAI SDK 的例外類型。
在生產環境,請鎖定你測試過的版本,而非長期依賴浮動的最新版本。
例如:
crewai==YOUR_TESTED_VERSIONopenai==YOUR_TESTED_VERSIONpython-dotenv==YOUR_TESTED_VERSION
CrewAI 的 LLM 層正在積極演進,因此確切的建構子與供應商配置應以你的應用所使用的 CrewAI 版本為準。目前的 CrewAI 文件支援以自訂 base_url 與 API key 配置 LLM。
如何配置 CometAPI API key?
建立 .env 檔案:
COMETAPI_KEY=your_cometapi_keyCOMETAPI_BASE_URL=https://api.cometapi.com/v1
在 Python 中載入這些值:
import osfrom dotenv import load_dotenvload_dotenv()COMETAPI_KEY = os.environ["COMETAPI_KEY"]COMETAPI_BASE_URL = os.getenv( "COMETAPI_BASE_URL", "https://api.cometapi.com/v1",)
切勿將 .env 提交到 Git。
將其加入 .gitignore:
.env.venv/__pycache__/
API key 應保持為伺服端憑證。CometAPI 目前的快速入門指引同樣建議將金鑰存於環境變數,而非原始碼。
如何將 CrewAI 連接到 CometAPI?
CrewAI 的 LLM 物件可以接收模型名稱、API key 與自訂 base URL。
建立一個輔助方法:
from crewai import LLMdef cometapi_llm(model_id: str) -> LLM: return LLM( model=model_id, base_url=COMETAPI_BASE_URL, api_key=COMETAPI_KEY, timeout=60.0, max_retries=0, )
這比在每個代理中重複嵌入相同設定更好。
現在每個代理只需要一個模型 ID:
research_llm = cometapi_llm("gemini-3.7-flash")analysis_llm = cometapi_llm("claude-opus-5")writing_llm = cometapi_llm("gpt-5.6")
為何設定 max_retries=0?
理由是控制回退。
若底層 LLM 客戶端自動重試,而你的應用也實作回退,那麼一次失敗在回退邏輯執行前可能變為多個隱藏請求。
對於帶有明確路由的教學來說,讓應用決定何時重試或切換模型更乾淨。
如何定義模型路由策略?
將路由置於提示之外:
PRIMARY_MODELS = { "researcher": "gemini-3.7-flash", "analyst": "claude-opus-5", "writer": "gpt-5.6",}FALLBACK_MODELS = { "researcher": "gpt-5.6", "analyst": "gpt-5.6", "writer": "gemini-3.7-flash",}
這建立了清晰的設定邊界。
之後你可以將相同的映射移至:
- 環境設定
- YAML
- JSON
- 資料庫
- 功能旗標
- 內部模型路由服務
而無需重寫代理的提示。
如何建立三個 CrewAI 代理?
為每個代理建立一個 LLM 物件。
from crewai import Agentdef build_agents(model_map: dict[str, str]): researcher = Agent( role="Market Researcher", goal="Collect the facts needed to answer the topic", backstory=( "You create concise, source-aware research briefs " "and clearly separate facts from assumptions." ), llm=cometapi_llm(model_map["researcher"]), max_iter=3, allow_delegation=False, ) analyst = Agent( role="Product Analyst", goal="Turn research into a defensible recommendation", backstory=( "You identify evidence, assumptions, risks, " "and trade-offs before making recommendations." ), llm=cometapi_llm(model_map["analyst"]), max_iter=3, allow_delegation=False, ) writer = Agent( role="Technical Writer", goal="Produce a concise technical decision memo", backstory=( "You write clear technical explanations " "without unnecessary marketing language." ), llm=cometapi_llm(model_map["writer"]), max_iter=3, allow_delegation=False, ) return researcher, analyst, writer
模型分配現已完全獨立於代理的角色定義。
這正是讓模型路由實用的原因。
如何用順序任務串接代理?
建立三個任務:
from crewai import Taskdef build_tasks(researcher, analyst, writer): research_task = Task( description=( "Research this topic: {topic}. " "Return the key facts, uncertainties, " "and relevant sources that the analyst should consider." ), expected_output=( "A compact research brief containing facts, " "uncertainties, and source references." ), agent=researcher, ) analysis_task = Task( description=( "Using the research brief, analyze {topic}. " "Identify the strongest conclusion and explain " "the major trade-offs." ), expected_output=( "A decision outline with evidence, " "assumptions, risks, and trade-offs." ), agent=analyst, context=[research_task], ) writing_task = Task( description=( "Write a concise technical decision memo about {topic}. " "State the recommendation early and preserve " "important caveats." ), expected_output="A polished technical decision memo in Markdown.", agent=writer, context=[research_task, analysis_task], ) return research_task, analysis_task, writing_task
依賴鏈如下:
Topic ↓Research ↓Analysis ↓Final memo
分析師接收研究任務的輸出,而撰稿者接收研究與分析兩個上下文。
如何建立 Crew?
組合代理與任務:
from crewai import Crew, Processdef build_crew(model_map: dict[str, str]) -> Crew: researcher, analyst, writer = build_agents(model_map) research_task, analysis_task, writing_task = build_tasks( researcher, analyst, writer, ) return Crew( agents=[researcher, analyst, writer], tasks=[ research_task, analysis_task, writing_task, ], process=Process.sequential, verbose=True, )
現在模型路由完全由設定驅動。
將:
"researcher": "gemini-3.7-flash"
改成另一個支援的模型,不需要更改研究提示或任務定義。
CrewAI 的模型回退應該如何運作?
這是需要更謹慎的生產實作重點。
一個常見錯誤是:
Any error ↓Switch model
這太過激進。
例如,以下錯誤通常不應觸發模型回退:
400 Bad Request401 Unauthorized403 Forbidden404 Not Found422 Validation Error
切換模型無法修正無效的 API key 或格式錯誤的請求。
回退更適合用於暫時性失敗,例如:
408 Request Timeout429 Rate Limit500 Internal Server Error502 Bad Gateway503 Service Unavailable504 Gateway TimeoutConnection errorTimeout
因此,回退策略應該是:
僅對有界的暫時性失敗進行重試或切換模型,且僅在回退模型支援相同請求契約時進行。
如何偵測可重試的錯誤?
你可以使用 OpenAI SDK 的錯誤類別:
from collections.abc import Iteratorfrom openai import ( APIConnectionError, APIStatusError, APITimeoutError,)def exception_chain(error: BaseException) -> Iterator[BaseException]: current: BaseException | None = error seen: set[int] = set() while current is not None and id(current) not in seen: seen.add(id(current)) yield current current = ( current.__cause__ or current.__context__ )def should_fallback(error: BaseException) -> bool: for current in exception_chain(error): if isinstance( current, (APIConnectionError, APITimeoutError), ): return True if isinstance(current, APIStatusError): return ( current.status_code in {408, 429} or current.status_code >= 500 ) return False
這刻意排除了除 408 與 429 以外的 400 級別設定錯誤。
應該重試整個 Crew 還是僅失敗的代理?
有兩種不同的回退策略。
Crew 層級回退
最簡單的實作是:
Start crew ↓failure ↓change routing ↓run crew again
這容易理解,但可能重複已完成的任務。
例如:
Research → completedAnalysis → completedWriter → failed
完整的 kickoff() 重試可能執行:
Research → againAnalysis → againWriter → fallback
這會增加:
- token 使用量
- 延遲
- API 成本
- 潛在副作用
任務層級恢復
生產工作流應該對已完成的工作建立檢查點:
Research ↓checkpoint ↓Analysis ↓checkpoint ↓Writer fails ↓retry writer with fallback
CrewAI 目前提供檢查點能力,能在任務完成後儲存執行狀態,並允許在失敗後恢復執行。已記錄的檢查點行為會跳過已完成的任務,並從儲存狀態繼續向下游工作。
這對於昂貴或有副作用的工作流是更好的架構。
如何加入 CrewAI 檢查點?
對於生產工作流,在 crew 上啟用檢查點:
crew = Crew( agents=[researcher, analyst, writer], tasks=[ research_task, analysis_task, writing_task, ], process=Process.sequential, checkpoint=True, verbose=True,)
CrewAI 的檢查點系統可以在任務完成後持久化執行狀態,並從檢查點恢復 crew。
例如,恢復的執行可以使用:
from crewai import CheckpointConfigresult = crew.kickoff( from_checkpoint=CheckpointConfig( restore_from="./.checkpoints/checkpoint.json", ))
確切的檢查點配置應依你的專案所使用的 CrewAI 版本而定。
重要的架構要點是:
先檢查點,再回退。
這可避免因暫時性模型失敗而迫使重跑昂貴的已完成工作。
如何實作簡單的有界回退?
在教學中,你仍可以示範簡單的 Crew 層級回退。
def run_with_fallback(topic: str): routes = [ PRIMARY_MODELS, { **PRIMARY_MODELS, "writer": FALLBACK_MODELS["writer"], }, { **PRIMARY_MODELS, "analyst": FALLBACK_MODELS["analyst"], "writer": FALLBACK_MODELS["writer"], }, ] last_error = None for attempt, model_map in enumerate(routes, start=1): try: crew = build_crew(model_map) result = crew.kickoff( inputs={"topic": topic} ) return result, model_map except Exception as error: last_error = error if not should_fallback(error): raise if attempt == len(routes): raise print( f"Transient failure on attempt {attempt}. " f"Trying bounded fallback route.", flush=True, ) raise RuntimeError( "Crew execution failed after all fallback routes." ) from last_error
注意一個重要區別:
這不是宣稱已辨識出失敗的代理。
這是一個有界的 Crew 層級回退策略。
對於小型、無狀態的工作流,這可能可以接受。對於在研究、工具或副作用上昂貴的生產工作流,請使用基於檢查點的恢復。
如何追蹤 CrewAI 的 Token 使用量?
使用量追蹤應成為路由層的一部分,而非事後補救。
在執行結束時,檢視 CrewAI 的結果:
result, selected_models = run_with_fallback(topic)print("Selected models:")print(selected_models)print("Final result:")print(result.raw)print("Usage:")print(result.token_usage)
可用的具體使用欄位可能取決於 CrewAI 版本與執行路徑,因此請以部署版本所返回的結果物件作為真相來源。
一個生產級的使用紀錄理想上應包含:
job_idagentmodelinput_tokensoutput_tokenstotal_tokenslatency_msfallback_usedfallback_reasonstatuscreated_at
這可讓你回答例如:
哪個代理消耗了最多預算?
分析師多常回退?
哪個模型延遲最高?
每個工作流的成本是多少?
如何在代理層級控制成本?
當路由反映實際工作負載差異時,多模型路由最有用。
例如:
Researcher→ high volume→ lower-cost modelAnalyst→ low volume→ stronger reasoning modelWriter→ medium volume→ general-purpose production model
你也可以透過代理配置約束成本。
例如:
max_iter=3
限制代理的迭代迴圈。這不應被解讀為嚴格限制正好三次 API 呼叫或三個 Token 預算。
其他控管包含:
- 限制任務上下文
- 摘要化中間輸出
- 快取可重複的研究
- 限制最大輸入大小
- 在支援的情況下限制最大輸出 Token
- 限制工具呼叫
- 設定每位使用者預算
- 設定每個工作流預算
- 追蹤回退頻率
部署前如何驗證模型?
不要永遠硬編碼模型 ID。
模型可能會:
- 不可用
- 被重新命名
- 被棄用
- 被限制
- 能力改變
- 定價改變
- 與你的參數不相容
CometAPI 提供可程式化查詢的模型目錄端點,同時其公開的模型目錄可用於人工探索。
部署檢查可以這樣做:
curl -s \ https://api.cometapi.com/api/models \ -H "Authorization: Bearer $COMETAPI_KEY"
接著在部署前驗證你的配置模型 ID 是否存在。
例如,你的 CI 流程可以驗證:
gemini-3.7-flash → availableclaude-opus-5 → availablegpt-5.6 → available
不要以可用性檢查取代應用測試。模型存在於目錄中不代表代理所使用的每個參數、工具或輸出格式都受支援。
完整的 CrewAI 範例長什麼樣?
以下是整合的實作:
import jsonimport osimport sysfrom collections.abc import Iteratorfrom dotenv import load_dotenvfrom openai import ( APIConnectionError, APIStatusError, APITimeoutError,)from crewai import Agent, Crew, LLM, Process, Taskload_dotenv()COMETAPI_KEY = os.environ["COMETAPI_KEY"]COMETAPI_BASE_URL = os.getenv( "COMETAPI_BASE_URL", "https://api.cometapi.com/v1",)PRIMARY_MODELS = { "researcher": "gemini-3.7-flash", "analyst": "claude-opus-5", "writer": "gpt-5.6",}FALLBACK_MODELS = { "researcher": "gpt-5.6", "analyst": "gpt-5.6", "writer": "gemini-3.7-flash",}def cometapi_llm(model_id: str) -> LLM: return LLM( model=model_id, base_url=COMETAPI_BASE_URL, api_key=COMETAPI_KEY, timeout=60.0, max_retries=0, )def build_crew(model_map: dict[str, str]) -> Crew: researcher = Agent( role="Market Researcher", goal="Collect the facts needed to answer the topic", backstory=( "You create concise, source-aware research briefs " "and distinguish facts from assumptions." ), llm=cometapi_llm(model_map["researcher"]), max_iter=3, allow_delegation=False, ) analyst = Agent( role="Product Analyst", goal="Turn research into a defensible recommendation", backstory=( "You evaluate evidence, assumptions, risks, " "and trade-offs." ), llm=cometapi_llm(model_map["analyst"]), max_iter=3, allow_delegation=False, ) writer = Agent( role="Technical Writer", goal="Produce a concise technical decision memo", backstory=( "You write clear technical explanations " "without unnecessary hype." ), llm=cometapi_llm(model_map["writer"]), max_iter=3, allow_delegation=False, ) research_task = Task( description=( "Research this topic: {topic}. " "Return the key facts, uncertainties, " "and relevant sources." ), expected_output=( "A concise research brief with facts " "and open questions." ), agent=researcher, ) analysis_task = Task( description=( "Using the research brief, analyze {topic}. " "Identify the strongest conclusion and " "explain the major trade-offs." ), expected_output=( "A decision outline with evidence, " "assumptions, risks, and trade-offs." ), agent=analyst, context=[research_task], ) writing_task = Task( description=( "Write a concise technical decision memo " "about {topic}. State the recommendation early " "and preserve important caveats." ), expected_output=( "A polished technical decision memo in Markdown." ), agent=writer, context=[ research_task, analysis_task, ], ) return Crew( agents=[ researcher, analyst, writer, ], tasks=[ research_task, analysis_task, writing_task, ], process=Process.sequential, verbose=True, )def exception_chain( error: BaseException,) -> Iterator[BaseException]: current = error seen: set[int] = set() while current is not None and id(current) not in seen: seen.add(id(current)) yield current current = ( current.__cause__ or current.__context__ )def should_fallback(error: BaseException) -> bool: for current in exception_chain(error): if isinstance( current, ( APIConnectionError, APITimeoutError, ), ): return True if isinstance(current, APIStatusError): return ( current.status_code in {408, 429} or current.status_code >= 500 ) return Falsedef run_with_fallback(topic: str): routes = [ PRIMARY_MODELS, { **PRIMARY_MODELS, "writer": FALLBACK_MODELS["writer"], }, { **PRIMARY_MODELS, "analyst": FALLBACK_MODELS["analyst"], "writer": FALLBACK_MODELS["writer"], }, ] last_error = None for attempt, model_map in enumerate( routes, start=1, ): try: crew = build_crew(model_map) result = crew.kickoff( inputs={ "topic": topic, } ) return result, model_map except Exception as error: last_error = error if not should_fallback(error): raise if attempt == len(routes): raise print( f"Transient failure on attempt " f"{attempt}; trying fallback.", file=sys.stderr, ) raise RuntimeError( "No model route completed the crew." ) from last_errordef main(): topic = ( sys.argv[1] if len(sys.argv) > 1 else ( "Should a small SaaS add " "AI-generated meeting summaries?" ) ) result, selected_models = ( run_with_fallback(topic) ) output = { "selected_models": selected_models, "raw": result.raw, "tasks_output": [ task.raw for task in result.tasks_output ], "token_usage": str( result.token_usage ), } print( json.dumps( output, indent=2, default=str, ) )if __name__ == "__main__": main()
相較於原始版本,重要的改進是程式不再錯誤地暗示例外能識別出確切失敗的代理。
這明確是一個有界的 Crew 層級回退實作。
在生產環境,請將相同的路由策略與 CrewAI 檢查點結合。
如何執行 CrewAI 工作流?
將檔案儲存為:
crewai_multi_model.py
接著執行:
python crewai_multi_model.py \ "Should a small SaaS add AI-generated meeting summaries?"
成功的回應會包含類似以下資訊:
{ "selected_models": { "researcher": "gemini-3.7-flash", "analyst": "claude-opus-5", "writer": "gpt-5.6" }, "raw": "<final decision memo>", "tasks_output": [ "<research output>", "<analysis output>", "<writing output>" ], "token_usage": "<usage information>"}
具體回應與使用量取決於輸入、模型行為、CrewAI 版本與執行路徑。
如果可重試錯誤啟用了回退路由,selected_models 物件會顯示該次 Crew 執行所使用的路由。
生產環境的模型路由應如何設計?
生產路由策略應考量的不僅是模型品質。
一個有用的決策函數是:
Model Score =Quality+ Reliability+ Context Fit+ Tool Compatibility- Cost- Latency
你可以在多個層面實作。
基於成本的路由
Simple task → economical modelComplex task → premium model
基於延遲的路由
Interactive request → fast modelBackground workflow → higher-quality model
基於可靠性的路由
Primary model ↓transient failure ↓fallback model
基於任務的路由
Research → Model AAnalysis → Model BWriting → Model CCode → Model D
最後一種方法對 CrewAI 特別自然,因為該框架已經讓每個代理具有不同角色。
如何讓回退更安全?
健全的回退系統應遵循四條規則。
不要在驗證錯誤時回退
如果 API key 無效:
401
更換模型不會解決問題。
不要在格式錯誤請求時回退
如果請求無效:
400422
應修正請求。
不要無限回退
設定硬性限制:
MAX_FALLBACK_ATTEMPTS = 2
沒有上限的回退系統可能演變成昂貴的重試迴圈。
確保回退模型的請求相容性
回退模型必須支援代理所需的功能。
例如,若主模型需要特定工具或結構化輸出行為,回退模型必須支援相同契約。
與 OpenAI 相容並不意味著功能相容。
最常見的 CrewAI + CometAPI 錯誤是什麼?
| Symptom | Likely Cause | Fix |
|---|---|---|
| 401 Unauthorized | 無效或遺失的 API key | 檢查 COMETAPI_KEY;不要回退 |
| 400 Bad Request | 無效的請求參數 | 更正請求 |
| 404 Model Not Found | 陳舊的模型 ID | 檢查目前的模型目錄 |
| 408 Timeout | 暫時性的請求逾時 | 在有界策略內重試 |
| 429 Rate Limited | 請求過多 | 退避並重試 |
| 500–504 | 暫時性的伺服器/閘道失敗 | 使用有界回退 |
| Agent repeatedly retries | 隱藏的 SDK 重試 | 控制 max_retries |
| Completed tasks run again | 完整 Crew 重試 | 使用基於檢查點的恢復 |
| Different model behaves differently | 模型能力存在差異 | 獨立測試每個模型 |
| Unexpected CrewAI constructor error | 版本不相容 | 鎖定並驗證 CrewAI 版本 |
如何區分 CrewAI 錯誤與模型錯誤?
在除錯時這個區分很重要。
設定錯誤
Missing API keyInvalid model IDInvalid base URLUnsupported parameter
這些應快速失敗。
供應商/API 錯誤
401403404429500503
根據狀態需要不同處理。
應用錯誤
Agent output invalidTool returned malformed dataTask context missingSide effect failed
更換模型不一定能解決這些問題。
成熟的代理系統應分別處理:
configuration ↓API transport ↓model execution ↓agent logic ↓tool execution ↓application side effects
這比通用的:
except Exception: use_fallback()
安全得多。
如何保護外部副作用?
當代理不僅生成文字時,回退會變得更複雜。
例如,想像一個代理會:
- 建立資料庫紀錄
- 傳送電子郵件
- 呼叫外部 API
- 更新 CRM
如果模型在外部動作成功後逾時,重新執行整個 Crew 可能會重複該動作。
請使用:
- 等冪鍵(idempotency keys)
- 任務檢查點
- 交易邊界
- 執行 ID
- 穩健的任務狀態
- 明確的副作用確認
例如:
job_id = crew_run_123task_id = writer_456
將這些識別子與外部操作一併儲存,以便重試時能判斷該操作是否已發生。
如何監控多模型的 CrewAI 工作流?
至少記錄:
workflow_idagentmodeltaskstart_timeend_timelatencystatusfallback_usedfallback_reasoninput_tokensoutput_tokenstotal_tokens
不要記錄:
API keysprivate credentialsfull sensitive promptsprivate user dataunredacted model output
針對每個模型,監控:
可靠性
success ratetimeout rate5xx ratefallback rate
效能
p50 latencyp95 latencyp99 latency
成本
input tokensoutput tokenscost per taskcost per completed workflow
品質
task success ratehuman evaluationstructured-output validitytool-call success
這能將模型路由從硬編碼偏好轉變為可觀測的工程系統。
如何在直接供應商 API 與 CometAPI 之間做選擇?
取決於你的架構。
| Architecture | Credentials | Model Switching | Provider Integration | Centralized Routing |
|---|---|---|---|---|
| 直接供應商 API | 多組 | 自訂 | 高 | 否 |
| 單一供應商 | 一組 | 受限 | 低 | 受限 |
| CrewAI + CometAPI | 一組 CometAPI 憑證 | 基於模型 ID | 較低 | 是 |
若你的應用只需要一個供應商及其原生能力,直接整合可能非常合理。
若你的 CrewAI 應用需要多個供應商的模型,且你希望有一個存取層,CometAPI 會更具吸引力。
重點是 CometAPI 並不取代 CrewAI。
相反地:
CrewAIAgent orchestration ↓CometAPIModel access ↓Multiple models
每個層負責不同職責。
這個架構如何擴展?
一旦將路由策略從代理定義中分離,新增另一個模型不需要重建整個應用。
例如:
PRIMARY_MODELS = { "researcher": "gemini-3.7-flash", "analyst": "claude-opus-5", "writer": "gpt-5.6", "coder": "YOUR_CODE_MODEL",}
同一架構即可支援:
Research agentAnalysis agentCoding agentReview agentWriting agentFact-checking agent
每個代理可以使用不同模型,同時共享同一個 CometAPI 存取層。
下一步是讓路由動態化。
不再是:
"analyst": "claude-opus-5"
而是最終可以使用:
select_model( task="analysis", budget=budget, latency_target=latency_target,)
屆時,路由系統可以基於應用需求,從核准的模型中選擇。
CrewAI + CometAPI 的最佳生產架構是什麼?
對於小型工作流:
User Input ↓CrewAI ↓CometAPI ↓Models
對於生產環境:
┌───────────────┐ │ Model Catalog │ └───────┬───────┘ │ ▼User → CrewAI → Routing Policy → CometAPI │ │ │ │ │ ├── Gemini │ │ ├── Claude │ │ └── GPT │ │ │ ▼ │ Cost / Quality / │ Latency / Policy │ ▼ Checkpoints │ ▼ Usage Tracking
關鍵的生產元件包括:
- 模型允許清單
- 每代理路由
- 有界重試
- 任務檢查點
- 使用量追蹤
- 成本控制
- 模型相容性測試
- 可觀測性
- 等冪的副作用
這種架構遠比僅僅在 crew.kickoff() 外加上一層 try/except 堅實。
一把 CometAPI Key,不同模型,更清晰的代理角色
將 CrewAI 與 CometAPI 一起使用最有用的思考方式是兩個互補層。
CrewAI 定義代理做什麼。
CometAPI 定義這些代理如何存取模型。
這種分工讓你可以為高量研究代理分配快速模型,為分析代理分配更強推理模型,為最終撰稿者分配通用生產模型,而無需在工作流內維護各自的供應商整合。
最簡單的實作使用一把 CometAPI key 與一個與 OpenAI 相容的 base URL:
https://api.cometapi.com/v1
在生產環境,請更進一步:將模型路由放在配置中、在部署前驗證模型供應情況、僅對暫時性失敗使用有界回退、對已完成任務做檢查點、並為每次執行記錄模型與使用中繼資料。
這比只把 CrewAI 連到一個 LLM 更耐用:
CrewAI 協調代理。CometAPI 集中化模型存取。以模型 ID 控制路由。檢查點保護已完成的工作。使用量追蹤控制成本。
常見問題
CrewAI 能在同一個 crew 中使用多個 AI 模型嗎?
是的。為每個 CrewAI 代理指定不同的 LLM 配置。每個配置都可以指定自己的模型,同時使用相同的 CometAPI API key 與 base URL。
CrewAI 能連接到與 OpenAI 相容的 API 嗎?
是的。CrewAI 的 LLM 配置支援自訂 base_url 與 API key 以連接與 OpenAI 相容的端點。
使用 CometAPI 時,base URL 為:
https://api.cometapi.com/v1
我需要為 GPT、Claude 與 Gemini 準備不同的 API key 嗎?
透過 CometAPI 存取這些模型時,應用可以使用 CometAPI 的憑證與端點,而不需要在每個 CrewAI 代理中實作各自的供應商憑證。
一把 API key 是否代表模型具有相同能力?
不會。API 介面可以統一,但模型能力仍然不同。上下文窗口、工具支援、參數、輸出行為、延遲與定價都可能因模型而異。
當某個模型失敗時,我應該重試整個 CrewAI 工作流嗎?
只有在簡單、無狀態的工作流中。整個 Crew 重試可能會重複已完成任務並提升成本。對於生產工作流,請為已完成任務建立檢查點並在可行處從失敗部分恢復。
CrewAI 目前的檢查點功能旨在保留執行狀態並在失敗後恢復。
是否每個 CrewAI 例外都應觸發模型回退?
不應。驗證問題、格式錯誤的請求、無效的模型 ID 與不支援的參數通常需要調整設定,而非更換模型。
回退更適用於逾時、速率限制與暫時性 5xx 回應等有界的暫時性失敗。
我如何追蹤每個 CrewAI 代理的成本?
對每個任務記錄代理名稱、模型 ID、Token 使用量、延遲、執行狀態與回退資訊。使用這些資料計算每個代理與工作流的成本。
我可以動態更換分配給代理的模型嗎?
可以。將模型 ID 放在路由設定中,而不是直接嵌入代理定義。你的應用便可以根據成本、延遲、任務類型或可用性選擇模型。
CometAPI 是 CrewAI 的替代品嗎?
不是。兩者處於不同層。CrewAI 編排代理與任務,而 CometAPI 提供統一的模型存取層。
我在哪裡可以找到目前的 CometAPI 模型?
使用 CometAPI Model Directory 進行人工探索,並使用模型 API 進行程式化驗證。CometAPI 目前的快速入門頁面列出了 500+ 橫跨文字、影像、影片與音訊的模型。
