Install any skill in seconds. Free to start, no credit card required.
Get Started Free →理解 LangGraph:用于构建有状态、长期运行 Agent 的低级编排框架,具有持久执行、流式传输和人机交互能力
.claude/skills/majiayu000-langgraph-overview/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | -24% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 76% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 131% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 13% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 6% | 0% |
name: langgraph-overview description: 理解 LangGraph - 用于构建有状态、长期运行 Agent 的低级编排框架,具有持久执行、流式传输和人机交互能力
LangGraph 是一个低级编排框架和运行时,用于构建、管理和部署长期运行的、有状态的 Agent。它受到 Klarna、Replit 和 Elastic 等公司的信任,用于生产 Agent 工作负载。
关键特性:
LangGraph 非常适合当您需要:
当您满足以下条件时考虑替代方案:
| 需求 | 使用 LangGraph | 使用 LangChain | 使用 Deep Agents | |------------|---------------|---------------|-----------------| | 快速原型开发 | ❌ | ✅ | ✅ | | 自定义编排逻辑 | ✅ | ❌ | ⚠️ (有限) | | 持久执行 | ✅ | ⚠️ (通过 LangGraph) | ✅ | | 人机交互 | ✅ | ⚠️ (通过 LangGraph) | ✅ | | 状态持久化 | ✅ | ❌ | ✅ | | 生产部署 | ✅ | ⚠️ (与 LangGraph 一起使用) | ✅ | | 学习曲线 | 高 | 低 | 中 |
LangGraph 将 Agent 工作流建模为图,具有三个核心组件:
| 能力 | 描述 | |-----------|-------------| | 持久执行 | Agent 在故障中持久存在并从检查点恢复 | | 流式传输 | 执行期间的实时更新(状态、令牌、自定义数据) | | 人机交互 | 暂停执行以供人工审查和干预 | | 持久化 | 线程级别和跨线程的状态管理 | | 时间旅行 | 从执行历史中的任何检查点恢复 |
受 Google 的 Pregel 系统启发:
typescriptimport { ChatAnthropic } from "@langchain/anthropic"; import { tool } from "@langchain/core/tools"; import { SystemMessage, HumanMessage, AIMessage, ToolMessage } from "@langchain/core/messages"; import { StateGraph, StateSchema, MessagesValue, ReducedValue, START, END } from "@langchain/langgraph"; import { z } from "zod"; // 1. 定义工具 const multiply = tool(({ a, b }) => a * b, { name: "multiply", description: "Multiply two numbers", schema: z.object({ a: z.number().describe("First number"), b: z.number().describe("Second number"), }), }); const add = tool(({ a, b }) => a + b, { name: "add", description: "Add two numbers", schema: z.object({ a: z.number().describe("First number"), b: z.number().describe("Second number"), }), }); // 2. 使用工具初始化模型 const model = new ChatAnthropic({ model: "claude-sonnet-4-5-20250929", temperature: 0, }); const toolsByName = { [add.name]: add, [multiply.name]: multiply }; const tools = Object.values(toolsByName); const modelWithTools = model.bindTools(tools); // 3. 定义状态 const MessagesState = new StateSchema({ messages: MessagesValue, llmCalls: new ReducedValue( z.number().default(0), { reducer: (x, y) => x + y } ), }); // 4. 定义节点 const llmCall = async (state) => { const response = await modelWithTools.invoke([ new SystemMessage("You are a helpful assistant."), ...state.messages, ]); return { messages: [response], llmCalls: 1, }; }; const toolNode = async (state) => { const lastMessage = state.messages.at(-1); if (lastMessage == null || !AIMessage.isInstance(lastMessage)) { return { messages: [] }; } const result = []; for (const toolCall of lastMessage.tool_calls ?? []) { const tool = toolsByName[toolCall.name]; const observation = await tool.invoke(toolCall); result.push(observation); } return { messages: result }; }; // 5. 定义路由逻辑 const shouldContinue = (state) => { const lastMessage = state.messages.at(-1); if (!lastMessage || !AIMessage.isInstance(lastMessage)) { return END; } if (lastMessage.tool_calls?.length) { return "toolNode"; } return END; }; // 6. 构建和编译图 const agent = new StateGraph(MessagesState) .addNode("llmCall", llmCall) .addNode("toolNode", toolNode) .addEdge(START, "llmCall") .addConditionalEdges("llmCall", shouldContinue, ["toolNode", END]) .addEdge("toolNode", "llmCall") .compile(); // 7. 调用 agent const result = await agent.invoke({ messages: [new HumanMessage("What is 3 * 4?")], }); for (const message of result.messages) { console.log(`[${message._getType()}]: ${message.content}`); }
typescriptimport { MemorySaver } from "@langchain/langgraph"; // 创建检查点器用于状态持久化 const checkpointer = new MemorySaver(); // 使用检查点器编译 const agent = new StateGraph(MessagesState) .addNode("llmCall", llmCall) .addNode("toolNode", toolNode) .addEdge(START, "llmCall") .addConditionalEdges("llmCall", shouldContinue, ["toolNode", END]) .addEdge("toolNode", "llmCall") .compile({ checkpointer }); // 添加检查点器 // 第一轮对话 const config = { configurable: { thread_id: "1" } }; await agent.invoke( { messages: [new HumanMessage("Hi, I'm Alice")] }, config ); // 第二轮 - agent 记住上下文 await agent.invoke( { messages: [new HumanMessage("What's my name?")] }, config );
typescript// 流式传输状态更新 for await (const chunk of await agent.stream( { messages: [new HumanMessage("Calculate 5 + 3")] }, { streamMode: "updates" } )) { console.log(chunk); } // 流式传输 LLM 令牌 for await (const chunk of await agent.stream( { messages: [new HumanMessage("Hello!")] }, { streamMode: "messages" } )) { console.log(chunk); } // 多种流式模式 for await (const [mode, chunk] of await agent.stream( { messages: [new HumanMessage("Help me")] }, { streamMode: ["updates", "messages"] } )) { console.log(`${mode}:`, chunk); }
✅ 节点逻辑:将任何异步函数定义为节点 ✅ 状态模式:自定义状态结构和 reducer ✅ 控制流:添加条件边、循环、分支 ✅ 持久化层:选择检查点器(MemorySaver、SQLite、Postgres) ✅ 流式模式:配置要流式传输的数据 ✅ 中断:在任何点添加人机交互 ✅ 递归限制:控制最大执行步数 ✅ 工具和模型:使用任何 LLM 或工具提供程序
❌ 核心图执行模型:基于 Pregel 的运行时是固定的 ❌ 超级步行为:无法更改节点的批处理方式 ❌ 消息传递协议:内部通信是预定义的 ❌ 检查点模式:内部检查点格式是固定的 ❌ 图编译:无法修改编译逻辑
typescript// ❌ 错误 - 使用检查点器但没有 thread_id await agent.invoke({ messages: [...] }); // 状态未持久化! // ✅ 正确 - 始终提供 thread_id await agent.invoke( { messages: [...] }, { configurable: { thread_id: "user-123" } } );
typescript// ❌ 错误 - 消息将被覆盖,而不是追加 const BadState = new StateSchema({ messages: z.array(BaseMessageSchema), // 没有 reducer! }); // ✅ 正确 - 使用 MessagesValue 进行自动消息处理 import { MessagesValue } from "@langchain/langgraph"; const GoodState = new StateSchema({ messages: MessagesValue, // 正确处理消息更新 });
typescript// ❌ 错误 - StateGraph 不可执行 const builder = new StateGraph(State).addNode("node", func); await builder.invoke(...); // 错误! // ✅ 正确 - 必须先编译 const graph = builder.compile(); await graph.invoke(...);
typescript// ❌ 错误 - 没有退出条件的循环 builder .addEdge("nodeA", "nodeB") .addEdge("nodeB", "nodeA"); // 无限循环! // ✅ 正确 - 添加到 END 的条件边 const shouldContinue = (state) => { if (state.count > 10) { return END; } return "nodeB"; }; builder.addConditionalEdges("nodeA", shouldContinue);
typescript// ❌ 错误 - 忘记 await const result = agent.invoke(...); // 返回 Promise! console.log(result.messages); // undefined // ✅ 正确 - 始终 await const result = await agent.invoke(...); console.log(result.messages); // 可以工作!
bash# npm npm install @langchain/langgraph # yarn yarn add @langchain/langgraph # pnpm pnpm add @langchain/langgraph # 与 LangChain 一起使用(可选但常见) npm install @langchain/core # 生产持久化 npm install @langchain/langgraph-checkpoint-postgres
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 41,294 | 18,419 | -55% | 1 | 1 | 0% | 7,243 | 5,537 | -24% | 0 | 0 | — |
case-02 | fail→pass | 21,166 | 15,574 | -26% | 1 | 1 | 0% | 3,596 | 6,322 | +76% | 0 | 0 | — |
case-03 | fail→pass | 21,488 | 24,298 | +13% | 1 | 1 | 0% | 3,011 | 6,954 | +131% | 0 | 0 | — |
case-04 | pass→pass | 11,229 | 7,662 | -32% | 1 | 1 | 0% | 2,065 | 4,365 | +111% | 0 | 0 | — |
case-05 | fail→pass | 26,993 | 11,646 | -57% | 1 | 1 | 0% | 3,672 | 4,147 | +13% | 0 | 0 | — |
case-14 | pass→pass | 21,625 | 13,013 | -40% | 1 | 1 | 0% | 3,054 | 5,495 | +80% | 0 | 0 | — |
case-06 | pass→pass | 8,601 | 6,372 | -26% | 1 | 1 | 0% | 1,612 | 4,165 | +158% | 0 | 0 | — |
case-07 | fail→pass | 20,965 | 5,323 | -75% | 1 | 1 | 0% | 3,713 | 3,933 | +6% | 0 | 0 | — |
case-08 | pass→pass | 5,928 | 4,041 | -32% | 1 | 1 | 0% | 1,099 | 3,788 | +245% | 0 | 0 | — |
case-09 | fail→pass | 15,013 | 6,682 | -55% | 1 | 1 | 0% | 1,534 | 4,031 | +163% | 0 | 0 | — |
case-10 | pass→pass | 9,413 | 8,740 | -7% | 1 | 1 | 0% | 769 | 3,687 | +379% | 0 | 0 | — |
case-11 | pass→pass | 6,862 | 9,854 | +44% | 1 | 1 | 0% | 1,237 | 3,910 | +216% | 0 | 0 | — |
case-12 | pass→pass | 4,556 | 4,328 | -5% | 1 | 1 | 0% | 813 | 3,768 | +363% | 0 | 0 | — |
case-13 | pass→pass | 17,763 | 10,517 | -41% | 1 | 1 | 0% | 2,102 | 3,999 | +90% | 0 | 0 | — |
case-15 | pass→pass | 7,086 | 8,866 | +25% | 1 | 1 | 0% | 1,360 | 3,742 | +175% | 0 | 0 | — |
case-16 | pass→pass | 15,873 | 14,810 | -7% | 1 | 1 | 0% | 1,890 | 4,826 | +155% | 0 | 0 | — |
case-17 | pass→pass | 15,813 | 14,790 | -6% | 1 | 1 | 0% | 1,978 | 4,857 | +146% | 0 | 0 | — |
case-18 | pass→pass | 5,071 | 7,504 | +48% | 1 | 1 | 0% | 928 | 3,439 | +271% | 0 | 0 | — |
case-19 | pass→pass | 24,147 | 23,168 | -4% | 1 | 1 | 0% | 3,676 | 6,647 | +81% | 0 | 0 | — |
case-20 | pass→pass | 16,066 | 16,048 | -0% | 1 | 1 | 0% | 3,131 | 5,286 | +69% | 0 | 0 | — |
case-21 | pass→pass | 10,087 | 12,499 | +24% | 1 | 1 | 0% | 1,657 | 4,275 | +158% | 0 | 0 | — |
case-22 | pass→pass | 6,515 | 6,076 | -7% | 1 | 1 | 0% | 1,140 | 4,068 | +257% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +27 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.