CrewAI 多智能体框架接入统一 API

最后更新: 2026-07-16

CrewAI 的 LLM 类直接接受 base_url 和 api_key。模型 ID 前面加 openai/ 前缀让请求说 chat completions,base_url 填 https://api.kkaiapi.com/v1,一个团队里的每个 Agent 都能持有目录里不同的模型,全部走一个 Key。

先说结论:LLM 加 openai/ 前缀和 base_url

CrewAI 通过它的 LLM 类配置模型:model 参数填一个带 openai/ 前缀的 ID,base_url 指向 https://api.kkaiapi.com/v1,再加上 api_key。把这个实例交给一个 Agent,这个 Agent 执行的每个任务都会走标准 /v1/chat/completions 经网关跑。 前缀承载了路由决定。CrewAI 的模型层跑在 LiteLLM 上,LiteLLM 靠模型字符串解析供应商客户端;openai/claude-sonnet-4-6 强制走对着你 base_url 的 OpenAI 协议客户端,claude-sonnet-4-6 作为 model 字段被转发。同样的三个值也能来自环境变量(OPENAI_API_BASE、OPENAI_API_KEY、OPENAI_MODEL_NAME),给那些代码保持通用的部署用。 一个必须提前说清楚的坑:裸 claude-* ID 会被 LiteLLM 无视 base_url,直接路由到 Anthropic 官方接口。CrewAI 打包并锁定了自己的 LiteLLM 版本,这个行为是上游的,不是配置错误,openai/ 前缀是唯一能保证请求走你网关的方式。

import os
from crewai import Agent, LLM

llm = LLM(
    model="openai/claude-sonnet-4-6",   # 前缀 + 目录里任意 ID
    base_url="https://api.kkaiapi.com/v1",
    api_key=os.environ["KKAIAPI_KEY"],
)

researcher = Agent(
    role="研究员",
    goal="收集并浓缩资料",
    backstory="做事细致,凡事都注明出处。",
    llm=llm,
)

一个团队怎么花掉 token

CrewAI(GitHub 上的 crewAIInc,约 5.6 万星标)把工作组织成一个由角色专精的 Agent 组成的团队,按顺序执行任务,或者在 hierarchical 模式下由一个管理者调度。每个 Agent 的每一轮都是一次 chat-completions 调用,带着这个 Agent 的角色提示词、任务描述、之前任务积累的上下文和工具 schema。一个带工具调用的五任务团队不会只发五次请求;每一次工具调用、每一次任务内的迭代都是一次往返,真实数量往往是几十次。 这也是为什么按 Agent 分配模型是这里最要紧的功能。llm 参数是按 Agent 设置的,一个团队可以在判断力集中的地方放旗舰模型,在走量的地方放快速模型,因为每个 LLM 实例共用同一个 base_url 和 Key,这一切都在一个端点上。hierarchical 模式下,同样的逻辑适用于经 manager_llm 设置的管理者槽位,这是整个团队里杠杆最大的一次模型选择:它负责拆解、分派、评估所有事情。 CrewAI 把加了前缀之后的模型字符串原样转发,所以一个团队内部混用厂商就是不同 Agent 上不同的 ID:Claude 负责规划,DeepSeek 负责总结,Qwen 负责翻译,底下是同一个计费面。

完整配置:一个混合模型团队

下面这个模式是多数生产团队最后收敛到的形状:决策集中的席位放强模型,走量的席位放快速模型,一个共享的端点定义让路由逻辑只活在一个地方。 生成参数(temperature、max_tokens)设在 LLM 实例上,所以一个要求确定性的抽取任务和一个更发散的写作任务可以共用同一个 ID,行为却不同。CrewAI 只支持 Python,没有 JS 版本要配置。

import os
from crewai import Agent, Crew, Task, LLM

def gateway_llm(model_id: str, **kwargs) -> LLM:
    return LLM(
        model=f"openai/{model_id}",
        base_url="https://api.kkaiapi.com/v1",
        api_key=os.environ["KKAIAPI_KEY"],
        **kwargs,
    )

analyst = Agent(
    role="分析师",
    goal="推理证据,得出结论",
    backstory="谨慎、多疑,凡事都展示推理过程。",
    llm=gateway_llm("claude-opus-4-7", temperature=0.2),
)
summarizer = Agent(
    role="总结员",
    goal="快速且忠实地浓缩输入",
    backstory="简明、精确。",
    llm=gateway_llm("deepseek-v4-flash"),
)

crew = Crew(
    agents=[analyst, summarizer],
    tasks=[
        Task(description="分析季度数据。", agent=analyst,
             expected_output="带推理过程的关键发现。"),
        Task(description="把发现写成一页简报。", agent=summarizer,
             expected_output="一页简报。"),
    ],
)
print(crew.kickoff())

按席位选模型

因为每个席位都共用一个端点和 Key,重新调整团队就是每个 Agent 改一次字符串。诚实的评估方式是固定住任务,换一个席位的 ID,拿输出质量对比按 Key 的用量差值;团队调用频繁到足以让席位级别的选择在账单上看得很清楚。

  • hierarchical 模式下的管理者,以及任何分析师类 Agent,承载团队的判断力;claude-opus-4-7 或 gpt-5.5 属于这里,因为一次错误的拆解或错误的判断会在下游每个任务上被放大
  • 做检索消化、总结、格式化、翻译的工作 Agent 是走量席位;deepseek-v4-flash 和 qwen3.7-max 能让单任务成本保持平坦
  • 重度用工具的 Agent 需要函数调用能力可靠的 ID;工具 schema 复杂时,claude-sonnet-4-6 是可靠的中间档
  • 在抽取和判定这类席位上把 temperature 设低(0.1-0.3),创造力留给写作席位;这个参数设在每个 LLM 实例上,免费就能表达出来

主力模型价格

价格按 kkaiapi 中文区实时价格计算,单位 ¥/1M tokens(输入/输出)。

实时价格以 /pricing 为准
模型模型 IDkkaiapi 价格(输入/输出)适合席位
Claude Opus 4.7claude-opus-4-7¥5 / ¥25管理者、分析师
Claude Sonnet 4.6claude-sonnet-4-6¥3 / ¥15重度工具调用
GPT-5.5gpt-5.5¥4 / ¥25管理者对比
DeepSeek V4 Flashdeepseek-v4-flash¥0.9 / ¥1.8走量工作 Agent
Qwen 3.7 Maxqwen3.7-max¥10.8 / ¥32.4翻译类工作 Agent

翻车点与版本锁定

漏掉前缀会绕开你的端点。model="claude-sonnet-4-6" 这样裸写,LiteLLM 会按名字解析出 Anthropic 客户端,你的 base_url 不再生效;请求会发去一个厂商主机,带着错的 Key,鉴权失败。报错提到厂商 SDK 而不是你的网关,就是这个坑。openai/ 前缀不是装饰,是路由指令。 环境变量部分覆盖。环境里设了 OPENAI_API_BASE,同时一个显式的 LLM 实例传了不同的 base_url,这本身是可行的配置;真正的混乱出现在部分 Agent 拿到了显式实例、另一部分落到环境默认值的时候。给整个代码库定一个统一约定,上面的工厂函数模式就是那个显式的约定。 记忆的 Embedding 是单独一件事。Crew 的记忆功能会为检索把文本 Embedding 化,配置在它自己的 embedder 设置里,不是 Agent 的 llm 上。把 Agent 流量挪到网关不会挪动 Embedding;除非你刻意决定,否则让 embedder 配置留在原来的供应商上。 LiteLLM 是 CrewAI 打包并锁定的。CrewAI 打包并锁定了自己的 LiteLLM 依赖,单独装一个不同版本的 litellm 可能在不同机器上产生不一样的解析行为。在依赖清单里锁定 crewai 本身,让它管理自己的 LiteLLM,升级时一起升。 跨任务的上下文累积。后面的任务会接收前面任务的输出作为上下文,所以一个早期任务输出很长的团队,会在后面的席位上推送越来越大的提示词。如果用量视图里团队后段的调用意外偏贵,先在上游给 expected_output 设长度上限,而不是往下游堆更大的模型。

哪些人会把 CrewAI 接到一个网关上

  • 跑混合厂商团队的团队,旗舰判断席位和快速走量席位并存,不用给每家厂商维护一套 SDK 和凭证
  • 构建定时或产品化团队的开发者,一份纯环境变量配置和一个密钥能干净地对接 CI 和容器部署
  • 评估团队组成的工程师,每个候选席位分配只是改一个字符串,按 Key 用量自动定价
  • 运营重度调用的 hierarchical 团队的成本敏感方,管理者加工作 Agent 会放大请求数,一个计费面能让花费保持清晰可见
  • 手头没有某家厂商官方支付渠道的开发者,充值即用不需要海外卡

验证接入与排查首次 kickoff

接线 Agent 之前先列出网关的模型;openai/ 后面的 ID 必须和提供的某个 ID 精确匹配,版本后缀也算。 首次 kickoff 的失败很有规律。报错提到某个厂商 SDK,说明一个裸的、没加前缀的模型字符串被按名字路由了。对你的网关报 401,说明那个 LLM 实例(或环境回退)里的 Key 不对;打印失败实例实际生效的两个值。模型不存在的报错是 ID 拼错了。团队在工具调用中途卡住,通常是一个函数调用能力弱的模型放在了重度用工具的席位上,先把这个席位换成更强的 ID,再去排查工具本身。 团队跑起来之后,kkaiapi 控制台会显示每次请求的模型、token 数和花费。对 hierarchical 团队来说,这是最快看出管理者对工作 Agent 调用比例、以及到底哪个席位真正扛账单的地方。

curl -s https://api.kkaiapi.com/v1/models \
  -H "Authorization: Bearer $KKAIAPI_KEY" | head -50

常见问题

CrewAI 里不同 Agent 能用不同厂商的模型吗?

能。llm 参数是按 Agent 设置的,每个 LLM 实例带着自己的模型字符串。经一个网关端点,一个 Claude 分析师、一个 DeepSeek 总结员、一个 Qwen 翻译员能共存在同一个团队里,共用同一个 Key。

模型字符串为什么要加 openai/ 前缀?

CrewAI 的模型层用 LiteLLM 从模型字符串解析供应商客户端。openai/ 前缀强制走对着你 base_url 的聊天补全客户端。一个裸的 claude-* ID 会被解析到 Anthropic 客户端,忽略你的端点。

哪些环境变量能在不动代码的情况下配置 CrewAI?

OPENAI_API_BASE 配端点,OPENAI_API_KEY 配 Key,OPENAI_MODEL_NAME 配默认模型(要带前缀)。没显式传 llm 构建的 Agent 会落到这几个默认值,适合容器化部署。

hierarchical 模式下 manager_llm 应该设成什么?

你能跑的最强推理模型,通常是 claude-opus-4-7 或 gpt-5.5。管理者负责拆解工作、分派任务、评估结果,它的错误会在整个团队里被放大,而工作席位的错误影响是局部的。

团队记忆功能也走网关吗?

Memory 的 Embedding 调用单独通过 embedder 设置配置,不走 Agent 的 llm。Agent 聊天流量挪到网关,除非你刻意迁移,否则 embedder 留在原有供应商上。

版本应该怎么锁?

锁定 crewai,让它管理自己打包的 LiteLLM 版本,两者一起升级能避免不同环境之间的供应商解析差异。把团队用的模型 ID 和结果一起记下来,就像记录随机种子一样,带版本号的目录 ID 能让运行结果可复现。