CrewAI 请求到底走到哪一层
如果你看到下面任一报错,99% 是这个坑:
BadRequestError: LLM Provider NOT provided.
litellm.exceptions.BadRequestError: ...
openai.AuthenticationError: Error code: 401
LLMException: Failed to call LLM provider
并且你的 CrewAI 配置类似:
from crewai import LLM
llm = LLM(model="claude-opus-4-7", base_url="https://中转/v1", api_key="sk-xxx")
注意 model="claude-opus-4-7" 没有前缀——就是这里出问题。
排查步骤
先加 openai/ 前缀
# 错
llm = LLM(model="claude-opus-4-7", ...)
# 对
llm = LLM(model="openai/claude-opus-4-7", ...)
再检查 base_url 末尾路径
LiteLLM 内部会自动拼 /v1/chat/completions,所以你传的 base_url 不应该带 /v1 尾巴:
# 错(双重 /v1)
base_url="https://api.xxx.com/v1"
# 对
base_url="https://api.xxx.com"
(有的中转方文档写带 /v1,那是给 openai SDK 直接用的,LiteLLM 链路要去掉。)
最后重跑测试
from crewai import LLM, Agent
llm = LLM(
model="openai/claude-opus-4-7",
base_url="https://api.your-relay.com",
api_key="sk-xxx",
)
agent = Agent(role="tester", goal="say hi", llm=llm)
print(llm.call([{"role": "user", "content": "hi"}]))
如果返回正常字符串,问题解决。
为什么会这样(原理)
CrewAI 不自己实现 provider 通信,而是把 LLM 调用委托给 LiteLLM(访问于 2026-05-19)。LiteLLM 是一个 provider 抽象层,内部维护 100+ provider 的 schema 转换,通过 model 字段的前缀决定走哪个 provider 的代码路径:
| 前缀 | 走哪个 provider | 协议 |
|---|---|---|
| openai/ | OpenAI 兼容路径 | POST /v1/chat/completions |
| anthropic/ | 原生 Anthropic API | POST /v1/messages |
| azure/ | Azure OpenAI | Azure 特殊路径 |
| bedrock/ | AWS Bedrock | AWS SigV4 签名 |
| 无前缀 | 报错或猜测 | 不可靠 |
国内 99% 中转方走 OpenAI 兼容协议(/v1/chat/completions),哪怕你调的是 Claude Opus 4.7,中转方在背后把请求翻译成 Anthropic 原生协议再发给上游。所以前缀写 openai/,model 名写 claude-opus-4-7,组合起来是 openai/claude-opus-4-7。
按 LiteLLM Providers 文档(访问于 2026-05-19),这是设计上的明确约定,不是 bug。
常见报错与修复
| 报错 | 原因 | 修复 |
|---|---|---|
LLM Provider NOT provided | 前缀漏了 | 加 openai/ 前缀 |
401 Unauthorized | LiteLLM 默认走 Anthropic 协议,但 key 是中转的 OpenAI 格式 | 加 openai/ 前缀 |
404 Not Found | base_url 末尾带 /v1 导致双重路径 | base_url 去掉 /v1 |
model not found | 中转方对模型名映射不同(如要 opus-4.7) | 中转后台看支持的 model 名 |
timeout | base_url 域名解析慢或中转方限流 | 换近的中转节点或换更高档套餐 |
继续查 CrewAI LiteLLM
按 CrewAI LLMs 文档(访问于 2026-05-19),CrewAI 0.30+ 才稳定支持 custom LLM 实例。老版本(< 0.28)的 model 字段解析逻辑可能跟 LiteLLM 1.0+ 不兼容,新项目建议都用最新版,前缀一律加。
剥离 CrewAI 直接用 LiteLLM 单测:
from litellm import completion
resp = completion(
model="openai/claude-opus-4-7",
api_base="https://api.your-relay.com",
api_key="sk-xxx",
messages=[{"role": "user", "content": "hi"}],
)
LiteLLM 通了 CrewAI 不通,问题在 CrewAI 配置层;LiteLLM 也不通,问题在中转方或网络。看 verbose 日志:import litellm; litellm.set_verbose = True,会打印完整请求 URL、header、body,瞬间能看出实际走的是哪个 provider 路径。
还没恢复时,单独查 CrewAI LiteLLM
如果上面 3 步 + 进阶排查都没修好,可能是中转方本身的兼容性问题(streaming 截断、tool_use 协议不完整、模型名映射错位)。建议:
- 换一家明确支持 OpenAI 兼容 + CrewAI / LiteLLM 测试通过的中转
- 优先选「主推 GPT-5.5 / Claude 4.7」的中转,它们一般对最新协议跟得紧
- 选一条独立开发者用得起的 Claude 4.7 / GPT-5.5 中转,把 CrewAI、Claude Code、Cursor 都打包到一条线路,排错时只用排查一家