with one click
langgraph-graph-api
使用 StateGraph、节点、边、START/END 节点和 Command API 构建图,结合控制流与状态更新
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Menu
使用 StateGraph、节点、边、START/END 节点和 Command API 构建图,结合控制流与状态更新
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Based on SOC occupation classification
Mac 系统深度清理和优化工具。使用 Mole (mo 命令) 执行系统清理、磁盘分析、应用卸载、系统优化等任务。 触发场景(当用户提到以下任一内容时使用此 skill): - 清理 Mac、清理磁盘、释放空间、清理缓存、清理系统 - 卸载应用、删除应用、移除应用及其残留 - 磁盘分析、查看磁盘占用、大文件查找、空间分析 - 系统优化、系统维护、刷新系统、重建缓存 - 系统状态、系统监控、CPU/内存/磁盘监控 - 清理 node_modules、清理构建产物、清理项目依赖 - 清理安装包、删除 dmg/pkg 文件 - Mac 清理工具、类似 CleanMyMac 的功能 - "我的 Mac 太慢了"、"磁盘空间不足"、"电脑卡顿" - 即使没有明确说 "Mole",只要涉及上述场景就应使用
快速搭建和配置 pnpm monorepo 项目结构,包含 TypeScript、tsup 构建、私有 npm registry 配置。当用户需要"创建 monorepo"、"初始化 monorepo 项目"、"配置 pnpm workspace"、"设置 monorepo 构建"、"monorepo setup"时使用。特别适合需要统一管理多个包、配置构建工具、处理 TypeScript 路径问题的场景。即使用户只是说"帮我搭建项目结构"或"配置构建",如果涉及多包管理也应该使用此 skill。
智能拆分暂存区的代码变更为多个符合 Conventional Commits 规范的逻辑提交。当用户需要将大量变更按逻辑关系分组提交时使用,比如"拆分这些提交"、"把暂存区的变更分成多个 commit"、"按功能分别提交"、"split commits"等场景。特别适合处理包含多个模块、多种类型文件(配置、代码、测试、文档)的复杂变更集。
OKR 优化与质量评估专家。当用户需要:(1) 评估现有 OKR 的质量,(2) 优化模糊或不可量化的关键结果,(3) 检查 OKR 是否符合核心原则(聚焦、可量化、有挑战),(4) 将任务型 KR 转化为结果型 KR,(5) 提供具体的改进建议时使用。触发词包括"帮我优化 OKR"、"检查这个 OKR"、"这个 KR 写得好吗"、"如何量化这个目标"。
基于 git commits 自动生成 CHANGELOG.md 变更日志。支持语义化版本、分类整理、多格式输出。触发场景包括"生成变更日志"、"更新 CHANGELOG"、"版本记录"。
GitHub PR 代码审查技能。检查代码质量、安全性、性能和最佳实践,生成结构化审查报告。触发场景包括"审查 PR"、"代码检查"、"review pull request"。
| name | langgraph-graph-api |
| description | 使用 StateGraph、节点、边、START/END 节点和 Command API 构建图,结合控制流与状态更新 |
| language | js |
LangGraph Graph API 允许您将 Agent 工作流定义为由节点(函数)和边(控制流)组成的有向图。这提供了对 Agent 编排的细粒度控制。
核心组件:
| 需求 | 边类型 | 何时使用 |
|---|---|---|
| 始终转到同一节点 | addEdge() | 固定、确定性流 |
| 基于状态路由 | addConditionalEdges() | 动态分支逻辑 |
| 扩散到多个节点 | Send API | Map-reduce、并行执行 |
| 更新状态并路由 | Command | 在单个节点中组合逻辑 |
LangGraph 使用受 Google Pregel 启发的消息传递模型:
节点是异步函数,它们:
const myNode = async (state: State): Promise<Partial<State>> => {
// 节点只是异步函数!
return { key: "updated_value" };
};
| 边类型 | 描述 | 示例 |
|---|---|---|
| 静态 | 始终路由到同一节点 | addEdge("A", "B") |
| 条件 | 基于状态/逻辑路由 | addConditionalEdges("A", router) |
| 动态 (Send) | 扩散到多个节点 | new Send("worker", {...}) |
| Command | 状态更新 + 路由 | new Command({ goto: "B" }) |
import { StateGraph, StateSchema, START, END } from "@langchain/langgraph";
import { z } from "zod";
// 1. 定义状态
const State = new StateSchema({
input: z.string(),
output: z.string(),
});
// 2. 定义节点
const processInput = async (state: typeof State.State) => {
return { output: `Processed: ${state.input}` };
};
const finalize = async (state: typeof State.State) => {
return { output: state.output.toUpperCase() };
};
// 3. 构建图
const graph = new StateGraph(State)
.addNode("process", processInput)
.addNode("finalize", finalize)
.addEdge(START, "process") // 入口点
.addEdge("process", "finalize") // 静态边
.addEdge("finalize", END) // 出口点
.compile();
// 4. 执行
const result = await graph.invoke({ input: "hello" });
console.log(result.output); // "PROCESSED: HELLO"
import { StateGraph, StateSchema, ConditionalEdgeRouter, START, END } from "@langchain/langgraph";
import { z } from "zod";
const State = new StateSchema({
query: z.string(),
route: z.string(),
result: z.string().optional(),
});
const classify = async (state: typeof State.State) => {
if (state.query.toLowerCase().includes("weather")) {
return { route: "weather" };
}
return { route: "general" };
};
const weatherNode = async (state: typeof State.State) => {
return { result: "Sunny, 72°F" };
};
const generalNode = async (state: typeof State.State) => {
return { result: "General response" };
};
// 路由器函数
const routeQuery: ConditionalEdgeRouter<typeof State, "weather" | "general"> = (state) => {
return state.route as "weather" | "general";
};
const graph = new StateGraph(State)
.addNode("classify", classify)
.addNode("weather", weatherNode)
.addNode("general", generalNode)
.addEdge(START, "classify")
// 基于状态的条件边
.addConditionalEdges(
"classify",
routeQuery,
["weather", "general"] // 可能的目标
)
.addEdge("weather", END)
.addEdge("general", END)
.compile();
const result = await graph.invoke({ query: "What's the weather?" });
import { StateGraph, StateSchema, Command, START, END } from "@langchain/langgraph";
import { z } from "zod";
const State = new StateSchema({
count: z.number(),
result: z.string(),
});
const nodeA = async (state: typeof State.State) => {
const newCount = state.count + 1;
if (newCount > 5) {
// 转到 nodeC
return new Command({
update: { count: newCount, result: "Going to C" },
goto: "nodeC"
});
} else {
// 转到 nodeB
return new Command({
update: { count: newCount, result: "Going to B" },
goto: "nodeB"
});
}
};
const nodeB = async (state: typeof State.State) => {
return { result: `B executed, count=${state.count}` };
};
const nodeC = async (state: typeof State.State) => {
return { result: `C executed, count=${state.count}` };
};
const graph = new StateGraph(State)
.addNode("nodeA", nodeA, { ends: ["nodeB", "nodeC"] }) // 指定可能的路由
.addNode("nodeB", nodeB)
.addNode("nodeC", nodeC)
.addEdge(START, "nodeA")
.addEdge("nodeB", END)
.addEdge("nodeC", END)
.compile();
const result1 = await graph.invoke({ count: 0 });
console.log(result1.result); // "B executed, count=1"
const result2 = await graph.invoke({ count: 5 });
console.log(result2.result); // "C executed, count=6"
import { StateGraph, StateSchema, Send, ReducedValue, START, END } from "@langchain/langgraph";
import { z } from "zod";
const State = new StateSchema({
items: z.array(z.string()),
results: new ReducedValue(
z.array(z.string()).default(() => []),
{ reducer: (current, update) => current.concat(update) }
),
final: z.string().optional(),
});
const fanOut = (state: typeof State.State) => {
// 将每个项目发送到工作节点
return state.items.map(item =>
new Send("worker", { item })
);
};
const worker = async (state: { item: string }) => {
// 处理单个项目
return { results: [`Processed: ${state.item}`] };
};
const aggregate = async (state: typeof State.State) => {
// 合并结果
return { final: state.results.join(", ") };
};
const graph = new StateGraph(State)
.addNode("worker", worker)
.addNode("aggregate", aggregate)
.addConditionalEdges(START, fanOut, ["worker"])
.addEdge("worker", "aggregate")
.addEdge("aggregate", END)
.compile();
const result = await graph.invoke({ items: ["A", "B", "C"] });
console.log(result.final); // "Processed: A, Processed: B, Processed: C"
import { StateGraph, StateSchema, ConditionalEdgeRouter, START, END } from "@langchain/langgraph";
import { z } from "zod";
const State = new StateSchema({
count: z.number(),
maxIterations: z.number(),
});
const increment = async (state: typeof State.State) => {
return { count: state.count + 1 };
};
const shouldContinue: ConditionalEdgeRouter<typeof State, "increment"> = (state) => {
if (state.count >= state.maxIterations) {
return END;
}
return "increment";
};
const graph = new StateGraph(State)
.addNode("increment", increment)
.addEdge(START, "increment")
.addConditionalEdges("increment", shouldContinue, ["increment", END])
.compile();
const result = await graph.invoke({ count: 0, maxIterations: 5 });
console.log(result.count); // 5
import { MemorySaver } from "@langchain/langgraph";
const checkpointer = new MemorySaver();
const graph = new StateGraph(State)
.addNode("nodeA", nodeA)
.addEdge(START, "nodeA")
.addEdge("nodeA", END)
.compile({
checkpointer, // 启用持久化
interruptBefore: ["nodeA"], // 在节点之前设置断点
interruptAfter: ["nodeA"], // 在节点之后设置断点
});
✅ 定义自定义节点(任何异步函数) ✅ 在节点之间添加静态边 ✅ 添加带自定义逻辑的条件边 ✅ 使用 Command 进行组合的状态/路由 ✅ 使用条件终止创建循环 ✅ 使用 Send API 扩散(map-reduce) ✅ 设置断点(interruptBefore/After) ✅ 自定义状态模式 ✅ 指定检查点器用于持久化
❌ 修改 START/END 节点行为 ❌ 更改超级步执行模型 ❌ 修改消息传递协议 ❌ 覆盖图编译逻辑 ❌ 绕过状态更新机制
// ❌ 错误
const builder = new StateGraph(State).addNode("node", func);
await builder.invoke({ input: "test" }); // 错误!
// ✅ 正确
const graph = builder.compile();
await graph.invoke({ input: "test" });
// ❌ 错误 - "missingNode" 未添加到图中
const router = (state) => "missingNode";
builder.addConditionalEdges("nodeA", router, ["missingNode"]);
// ✅ 正确 - 添加所有可能的目标
builder.addNode("missingNode", func);
builder.addConditionalEdges("nodeA", router, ["missingNode"]);
ends 参数// ❌ 错误 - 未指定 ends
const nodeA = async (state) => {
return new Command({ goto: "nodeB" });
};
builder.addNode("nodeA", nodeA); // 使用 Command 时出错!
// ✅ 正确 - 指定可能的目标
builder.addNode("nodeA", nodeA, { ends: ["nodeB", "nodeC"] });
// ❌ 错误 - 无限循环
builder
.addEdge("nodeA", "nodeB")
.addEdge("nodeB", "nodeA"); // 无路可出!
// ✅ 正确 - 到 END 的条件边
const shouldContinue = (state) => {
if (state.count > 10) return END;
return "nodeB";
};
builder.addConditionalEdges("nodeA", shouldContinue, ["nodeB", END]);
// ❌ 错误 - 结果将被覆盖
const State = new StateSchema({
results: z.array(z.string()), // 没有 reducer!
});
// ✅ 正确 - 使用 ReducedValue
import { ReducedValue } from "@langchain/langgraph";
const State = new StateSchema({
results: new ReducedValue(
z.array(z.string()).default(() => []),
{ reducer: (current, update) => current.concat(update) }
),
});
// ❌ 错误 - 无法路由回 START
builder.addEdge("nodeA", START); // 错误!
// ✅ 正确 - 使用命名的入口节点代替
builder.addNode("entry", entryFunc);
builder.addEdge(START, "entry");
builder.addEdge("nodeA", "entry"); // 可以
// ❌ 错误 - 忘记 await
const result = graph.invoke({ input: "test" });
console.log(result.output); // undefined (Promise!)
// ✅ 正确
const result = await graph.invoke({ input: "test" });
console.log(result.output); // 可以工作!