con un clic
langgraph-graph-api
使用 StateGraph、节点、边、START/END 节点和 Command API 构建图,结合控制流与状态更新
Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Menú
使用 StateGraph、节点、边、START/END 节点和 Command API 构建图,结合控制流与状态更新
Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Basado en la clasificación ocupacional SOC
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); // 可以工作!