LangGraph 12:静态断点

前言

上一篇的 interrupt()动态人机协同:停在哪儿由代码运行时决定。
还有一类静态断点:编译图时声明「进入某节点前 / 离开某节点后」一律暂停,适合调试或固定审批闸门。
本文只讲 interrupt_before / interrupt_afterinvoke(None) 分步恢复。
bind_toolsToolNode 与工具循环见 《LangGraph 06:工具调用》。
下文需要 Python 3.12+,依赖用 uv 管理。

依赖

建议使用 Python 3.12 及以上。

1
2
3
4
uv init langgraph-static-interrupt
cd langgraph-static-interrupt
uv venv --python 3.12
uv add "langgraph>=1.0,<2.0" rich

静态断点同样需要 checkpointer 与稳定的 thread_id
本篇示例不调 LLM,无需配置模型密钥。

静态断点

compile 时传入节点名列表。
首次 invoke 会在第一个断点停下;之后用 invoke(None, config=...) 推进到下一闸门,直到跑完。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
from typing import TypedDict

from langgraph.checkpoint.memory import InMemorySaver
from langgraph.graph import END, START, StateGraph
from rich import print as rprint

class OverAllState(TypedDict):
final_res: str

def node_a(state: OverAllState) -> OverAllState:
return {"final_res": "node_a"}

def node_b(state: OverAllState) -> OverAllState:
return {"final_res": "node_b"}

def node_c(state: OverAllState) -> OverAllState:
return {"final_res": "node_c"}

builder = StateGraph(state_schema=OverAllState)
builder.add_node("node_a", node_a)
builder.add_node("node_b", node_b)
builder.add_node("node_c", node_c)
builder.add_edge(START, "node_a")
builder.add_edge("node_a", "node_b")
builder.add_edge("node_b", "node_c")
builder.add_edge("node_c", END)

graph = builder.compile(
checkpointer=InMemorySaver(),
interrupt_before=["node_a", "node_b"],
interrupt_after=["node_a", "node_b"],
)
config = {"configurable": {"thread_id": "static-1"}}

rprint(graph.invoke({}, config=config))
rprint(graph.invoke(None, config=config))
rprint(graph.invoke(None, config=config))
rprint(graph.invoke(None, config=config))

也可在单次 invoke(..., interrupt_before=..., interrupt_after=...) 里临时指定断点,不必写进 compile
注意:临时列表与编译期配置混用时,某次调用若省略断点参数,后续行为可能与预期不一致;联调时固定一种写法更稳妥。
并行图上声明多个静态断点时,各分支会各自卡在闸门,恢复顺序仍按 invoke(None) 逐步推进。

总结

  1. 静态断点:interrupt_before / interrupt_after + checkpointer;恢复用 invoke(None, config=...)
  2. 动态 interrupt() 适合业务审批;静态断点适合固定闸门与调试。
  3. 工具调用(bind_toolsToolNode、并行与包装)见 《LangGraph 06:工具调用》。