LangChain / LangGraph / CrewAI 是怎么调用 Claude 的
约 1319 字大约 4 分钟
ClaudeLangChainLangGraphCrewAI
2026-07-13
很多人以为用 LangChain / LangGraph / CrewAI 搭 agent,就等于"用了某种更高级的 Claude 集成方式"。其实不是。这三个框架最终都是在 Anthropic 的 POST /v1/messages(Messages API)上包一层——要么直接用官方 anthropic SDK,要么经过 LiteLLM 中转。
它们和 Claude Agent SDK(原 Claude Code SDK)的本质区别只有一句话:agent 循环(工具调用循环)由框架自己的 Python 代码跑,而不是交给 Anthropic 跑。
本文拆开讲清楚这层关系,以及"只是调 API"意味着什么代价。
分层关系
你的代码
└─ LangChain / LangGraph / CrewAI ← agent 循环、状态、编排都在这层(框架侧)
└─ langchain-anthropic / LiteLLM ← 适配器:把统一接口翻译成 Anthropic 的请求
└─ anthropic SDK(或 raw HTTP)
└─ POST /v1/messages ← 真正跟 Claude 说话的地方不管上层封装看起来多"智能",最底下永远是一个一个独立的 messages.create 请求。Messages API 本身是无状态的——每一轮都要把完整对话历史重新发过去,框架帮你维护这份历史而已。
1. LangChain —— ChatAnthropic
装 langchain-anthropic,它内部就是持有一个 anthropic.Anthropic() 客户端。
from langchain_anthropic import ChatAnthropic
llm = ChatAnthropic(model="claude-opus-4-8", max_tokens=4096)
resp = llm.invoke("用一句话解释 CAP 定理")
# invoke() 内部 ≈ client.messages.create(model=..., messages=[...], max_tokens=...)工具调用也只是翻译:你用 LangChain 的 @tool / bind_tools,它把工具 schema 转成 Anthropic 的 tools 参数;Claude 返回 tool_use 块,LangChain 再把它包成一个 AIMessage(tool_calls=[...])。
llm_with_tools = llm.bind_tools([get_weather]) # → 请求里的 tools=[...]
ai_msg = llm_with_tools.invoke("北京天气?")
# Claude 回 stop_reason="tool_use" → LangChain 解析成 ai_msg.tool_calls注意
这里没有循环。执行工具、把结果塞回去、再问一次——要么你自己写,要么交给 LangGraph / AgentExecutor。循环逻辑始终在 Python 侧。
2. LangGraph —— 循环在图里
LangGraph 是建在 LangChain 之上的状态机 / 图编排层。对 Claude 的调用还是那个 ChatAnthropic,LangGraph 只负责"调完之后走哪条边"。
from langgraph.prebuilt import create_react_agent
from langchain_anthropic import ChatAnthropic
agent = create_react_agent(
ChatAnthropic(model="claude-opus-4-8"),
tools=[get_weather],
)
agent.invoke({"messages": [("user", "北京天气怎样?")]})create_react_agent 内部就是一个循环:
调 Claude → 若返回 tool_use 就执行工具 → 把 tool_result 加进 state → 再调 Claude
↑____________________|
直到 stop_reason == "end_turn"这个 while 循环是 LangGraph 的 Python 代码,每一轮都是一次独立的 messages.create,由框架维护完整对话历史再发过去。
3. CrewAI —— 经过 LiteLLM 中转
CrewAI 默认不直接用 anthropic SDK,而是走 LiteLLM 做统一多 provider 适配:
from crewai import Agent
agent = Agent(
role="研究员",
goal="...",
llm="anthropic/claude-opus-4-8", # "anthropic/" 前缀是 LiteLLM 的路由约定
)LiteLLM 看到 anthropic/ 前缀,就把 CrewAI 的通用消息格式翻译成 Anthropic 的 POST /v1/messages 请求发出去。CrewAI 的多 agent 协作、任务分派全在 CrewAI 自己这层,Claude 每次只是被当成一个"给我下一步输出"的无状态推理端点。
关键区别:agent 循环归谁管
这才是它们和 Claude Agent SDK 的分水岭。
| 这三个框架 | Claude Agent SDK | |
|---|---|---|
| 谁跑 agent 循环 | 框架的 Python 代码 | Anthropic 的运行时(SDK 内置 tool runner,或 Managed Agents 服务端) |
| 工具执行环境 | 你的进程 | 你的进程,或 Managed Agents 的托管容器 |
| bash / 文件 / 子 agent / 上下文压缩 | 自己拼 | SDK / 服务端开箱即用 |
| 换 provider | 改一行 model 字符串 | 绑定 Claude |
一句话:框架帮你把 Claude 当成一个可替换的推理引擎来编排;Agent SDK 则把整套 agent harness(工具循环、内置工具、子 agent、上下文管理)直接给你。
抽象的代价:为什么说"只是调 API"
因为这些框架要跨 provider 统一接口,Claude 的专有能力常常被拉平,或需要绕路(model_kwargs / extra_body 透传)才能用到:
- adaptive thinking / effort:
thinking={"type":"adaptive"}、output_config={"effort":"xhigh"}这些不是通用参数,得手动透传。 - prompt caching:
cache_control断点、缓存命中的成本优化,在统一抽象里基本用不上,得手动构造 content block。 - 服务端工具:web search、code execution、MCP connector 这些"Anthropic 托管、声明即用"的 server 工具,框架的通用 tool 抽象一般接不上。
- 模型专有行为:比如会话中途的 system message、refusal fallback 机制等,通用层几乎不会暴露。
怎么选
一个经验判断:
- 要深度用 Claude 的 agentic 能力(server 工具、prompt caching、托管容器、子 agent)→ Claude Agent SDK 更省事,专有能力开箱即用。
- 只是把 Claude 当一个可替换的推理引擎,重点在自己的编排逻辑(多 provider、复杂状态机、多 agent 协作)→ LangGraph / CrewAI 更合适。
两者不是替代关系:如果编排框架成熟、只是想接入 Claude,用 LangChain 一行 model 字符串即可;如果核心诉求就是"让 Claude 自主地跑一大段 agentic 任务",那绕过通用抽象、直接用 Agent SDK 反而更简单也更能发挥模型能力。
一句话总结
LangChain / LangGraph / CrewAI 里的 Claude 集成,本质是在
POST /v1/messages上包一层适配器,agent 循环跑在框架侧;Agent SDK 则把 agent 循环和工具运行时交给了 Anthropic。理解这一点,就不会再把"用了 LangChain"误当成"用了更强的 Claude 能力"。
