LangGraph Crash Course · Python OSS
面向工程落地的速成版:把企业最常问的 LangGraph 问题,映射到可执行的图、状态、持久化、人机中断、记忆与评测方法。
写在前面:这篇文章的“企业高频问题”来自公开生产场景的共性抽象,不是单一公司的封闭题库。时间基准为 2026-04-24。
很多人第一次接触 LangGraph,重点会放在“把图连起来”。
但企业面试与真实项目更关心的是另一组问题:状态如何恢复、故障如何重试、人工如何介入、输出如何约束、多 Agent 何时该上。
TL;DR
| 你会被问什么 | 面试官真正想验证什么 |
|---|---|
| 为什么要 LangGraph,不直接 while loop | 你是否理解“可控 agent runtime”而不是“demo 脚本” |
checkpointer 和 thread_id 怎么设计 | 你是否能处理中断恢复与多会话隔离 |
interrupt 放在哪一层 | 你是否能做 Human-in-the-loop 的审批闭环 |
| 结构化输出怎么防半截 JSON | 你是否懂 schema 约束与降级路径 |
| 多 Agent 什么时候值得上 | 你是否懂复杂度收益比,而不是盲目拆节点 |
| 线上怎么排障 | 你是否有观察性与回放调试思维 |
阅读路径
如果你是第一次系统用 LangGraph,建议按下面顺序读:
- 先看“最小可运行范式”,把
State + Router + Checkpoint + Interrupt跑通。 - 再看“企业最常问的 7 个问题”,建立面试与项目的统一答题框架。
- 最后刷附录分组题库,按岗位重点背诵 A/B/E 三组。
一、10 分钟建立 LangGraph 心智模型
把 LangGraph 想成“图形化的 agent runtime”更准确。它不只负责调一次模型,而是管理一条有状态的执行路径。
| 概念 | 你要掌握的最小定义 | 企业常追问 |
|---|---|---|
| State | 一次执行过程中可读可写的共享状态 | 字段怎么演进,如何避免状态污染 |
| Node | 一个确定职责的执行单元 | 节点粒度怎么定,如何避免上帝节点 |
| Edge | 节点间转移规则 | 路由为何可解释,失败路径在哪 |
| Checkpoint | 图执行快照 | 如何恢复,恢复到哪一步 |
| Thread | 多轮会话上下文容器 | thread_id 规则、并发隔离、清理策略 |
| Interrupt | 人工审批中断点 | 谁审批、超时怎么办、恢复命令是什么 |
官方文档把 LangGraph 的核心收益定义为 durable execution、human-in-the-loop、comprehensive memory、debugging with LangSmith。这四项正好对应企业面试的高频问题轴。
二、最小可运行范式(Python)
下面是一个最小的生产思维版本:
有状态、有路由、有持久化、有中断点、可恢复。
from typing import Literal, TypedDict
from langgraph.checkpoint.memory import InMemorySaver
from langgraph.graph import END, START, StateGraph
from langgraph.types import interrupt
class ChatState(TypedDict):
user_query: str
need_approval: bool
approved: bool
answer: str
def router(state: ChatState) -> Literal["approval_gate", "finalize"]:
if state["need_approval"] and not state["approved"]:
return "approval_gate"
return "finalize"
def approval_gate(state: ChatState) -> ChatState:
decision = interrupt(
{
"kind": "approval",
"reason": "sensitive_action",
"question": "Allow this action?",
}
)
return {**state, "approved": bool(decision)}
def finalize(state: ChatState) -> ChatState:
if state["need_approval"] and not state["approved"]:
return {**state, "answer": "Rejected by reviewer."}
return {**state, "answer": f"Done: {state['user_query']}"}
graph = StateGraph(ChatState)
graph.add_node("approval_gate", approval_gate)
graph.add_node("finalize", finalize)
graph.add_conditional_edges(START, router)
graph.add_edge("approval_gate", "finalize")
graph.add_edge("finalize", END)
compiled = graph.compile(checkpointer=InMemorySaver())
config = {"configurable": {"thread_id": "tenant-a:user-42:chat-001"}}
result = compiled.invoke(
{
"user_query": "Delete stale records",
"need_approval": True,
"approved": False,
"answer": "",
},
config,
)
print(result["answer"])这段代码值得记住的不是 API 名字,而是顺序:
- 先定义状态契约,再写节点逻辑。
- 先固定路由边界,再引入模型决策。
- 先接入 checkpoint,再谈故障恢复。
这张图讲的不是“节点怎么连线”这么简单,而是 LangGraph runtime 怎么把一条生产级执行链真正拼完整。你可以把它理解成五件套:主流程、状态持久化、人工审批、失败恢复、可观测性。
-
主干流程:上面这条线是
START -> Router Node -> Tool Node -> END。START接收输入,通常会同时带上thread_id;Router Node先用规则做确定性判断,必要时再让模型兜底决定下一步;Tool Node才是真正执行外部动作的位置,例如写库、发消息、调用第三方 API;最后END输出最终结果。关键点不是“有几个节点”,而是把决策节点和副作用节点分开,这样路由、审批、恢复都会更清晰。 -
Checkpoint:中间蓝框表示状态快照持久化。
persist state snapshot的意思是把当前state和执行位置一起存下来;resume by thread_id表示后续可以靠thread_id找回同一条执行链继续跑。它解决的不是日志留痕,而是可恢复执行:进程重启、长流程跨轮、人工审批后继续,都依赖这层。 -
Interrupt Gate (HITL):右侧红框表示 Human-in-the-Loop。它的作用是在高风险动作前显式暂停,等人工给出批准、拒绝或补充信息,再恢复图执行。这也是为什么
interrupt(...)最好放在“外部副作用发生之前”,而不是藏在工具内部;否则流程虽然能停,但审批边界不清楚,也不利于审计。 -
Failure Handling:右下角棕框强调生产系统不能把所有错误都当成一种错误处理。可恢复失败通常是超时、瞬时依赖故障、可重试工具异常,这类问题适合
retry或从 checkpoint 恢复;不可恢复失败则要升级告警、人工接管,必要时执行补偿动作。换句话说,LangGraph 的价值不只是“失败了”,而是“失败后按类型进入不同路径”。 -
Observability Signals:左下角绿框是线上排障和评测的基础。至少要采集节点延迟、重试次数、路由决策、工具错误这些信号,它们会直接决定你能不能 replay 一次故障现场、能不能做回归检查、能不能知道问题到底出在路由、工具还是生成层。很多团队的问题不是图没搭出来,而是图跑起来后不可解释、不可回放、不可比较。
一句话看完整张图:LangGraph 不只是把节点串起来执行,而是围绕 thread_id + checkpoint 搭出了一套可暂停、可恢复、可审批、可观测的 agent runtime。
如果你要把这张图记成面试回答,可以直接压缩成一句:LangGraph 的生产价值不在“图”本身,而在 durable execution、HITL、failure recovery 和 observability 这几层 runtime 能力。
三、为什么这些问题“企业高频”
截至 2026-04,官方公开案例覆盖客服、招聘、代码助手、安全运营、地产等多行业场景。
业务不同,但追问结构高度一致:稳定性、可控性、可恢复、可观测。
| 企业会问什么 | 本质上在验证什么 | 对应能力 |
|---|---|---|
| 进程重启后如何继续 | 你是否有 durable execution 思维 | checkpointer + thread_id |
| 人工审批怎么接入 | 你是否能做风控闭环 | interrupt |
| 输出如何稳定入库 | 你是否有结构化约束意识 | schema / structured output |
| 多 agent 如何不失控 | 你是否懂复杂度治理 | rule route + worker 边界 |
| 出问题怎么定位 | 你是否具备运维与评测意识 | tracing + replay + regression |
公开案例里常见的名字包括 Klarna、Replit、Elastic、LinkedIn、Uber、GitLab、AppFolio、Rakuten、BlackRock、Cisco Outshift。公司不同,问题同构。
四、企业最常问的 7 个 LangGraph 问题
问题 1:为什么 checkpointer 在生产里不是可选项
短答:没有 checkpoint,就没有真正意义上的 durable execution。进程重启、超时重试、人工审批恢复都会变脆弱。
工程落点:
- 每次图执行都要绑定
thread_id。 - 关键节点后持久化,确保“重放不是重算全部”。
- 将恢复策略写进运行手册,而不是只存在代码注释里。
高频误区:把“日志里能看到上一步输出”误当成“可恢复”。
问题 2:thread_id 到底怎么设计
短答:thread_id 不是随机字符串,而是会话隔离主键,通常包含租户、用户、会话三个维度。
工程落点:
- 推荐稳定格式:
tenant:user:session。 - 同一会话复用同一
thread_id,跨会话必须换新 ID。 - 为归档和清理预留可解析维度,不要用不可读 UUID 直接裸放。
高频误区:前端每次请求都新建一个 thread_id,导致记忆断裂。
问题 3:interrupt 应该放在哪一层
短答:放在“高风险动作之前”,例如写库、发消息、下单、执行外部副作用工具前。
工程落点:
- 将中断点建模为显式节点,不要藏在工具函数内部。
- 审批结果也写入状态,保证审计可追溯。
- 设计超时策略:超时默认拒绝还是降级文本答复。
高频误区:把 HITL 做成前端弹窗逻辑,后端图状态无感知。
问题 4:结构化输出怎么防“半截 JSON”
短答:用 schema 驱动输出,并提供 fallback,不能只靠 prompt 写“请严格输出 JSON”。
工程落点:
- 关键链路使用结构化输出能力(schema / model)。
- 解析失败时返回可恢复错误结构,而不是直接抛 500。
- 将“传输协议正确”和“语义字段正确”分开验证。
高频误区:只做 json.loads 成功判断,不做字段级校验。
问题 5:多 Agent 什么时候值得上
短答:当子任务有稳定职责边界,且能并行或独立演进时才值得上;否则先单图多节点。
工程落点:
- 优先“一个 supervisor + 明确 worker”模式。
- 先通过路由规则消化 70% 简单请求,再用模型兜底复杂路由。
- 观察指标:延迟、token 成本、失败率、可解释性是否实质改善。
高频误区:为了“看起来先进”过度拆 worker,结果调试复杂度爆炸。
问题 6:记忆到底怎么分层
短答:至少分三层:执行态(state)、会话态(thread/checkpoint)、跨会话长期态(store/profile/cache)。
工程落点:
- 执行态只存本次流程必需字段。
- 会话态解决多轮连续性与恢复。
- 长期态只保留高价值稳定偏好,不把整段对话全量写入。
高频误区:把所有历史无差别堆进 prompt,导致成本高、噪声大。
问题 7:线上怎么排查“答得不对”
短答:先拆层定位:路由层、工具层、检索层、生成层,不要一上来换模型。
工程落点:
- 记录每个节点输入输出与耗时。
- 对失败样本做回放,定位首个偏离节点。
- 维护最小回归集,升级提示词或模型前后都跑一遍。
高频误区:把所有问题都归因到“模型能力不够”。
五、生产化最小清单
如果你只有一周时间把 demo 拉到可上线,这份最小清单够用。
- 每条执行链都显式绑定
thread_id。 - 图必须启用
checkpointer,并验证恢复路径。 - 高风险节点前配置
interrupt审批。 - 关键输出使用 schema 校验并定义 fallback。
- 路由优先规则化,模型只处理不确定场景。
- 全链路记录节点耗时、错误类型、重试次数。
- 建立至少 20 条高价值回归样本。
- 将“可恢复失败”与“不可恢复失败”分开处理。
六、附录:面试题和解答(分组题库)
A 组:架构与运行时(6 题)
A1. LangGraph 和传统 AgentExecutor 的核心区别是什么
- 30 秒短答:LangGraph 把 agent 执行过程显式图化并状态化,天然支持可恢复、可中断、可路由,而不仅是线性调用链。
- 面试官追问点:你如何定义节点边界和状态字段。
- 高频误区:只回答“功能更多”,但说不出 runtime 价值。
A2. 什么时候应该用图,什么时候一个循环就够
- 30 秒短答:需要显式分支、恢复、中断审批、可观测节点时用图;纯线性一次性任务用循环足够。
- 面试官追问点:复杂度门槛怎么评估。
- 高频误区:把所有任务都图化。
A3. 节点应该按业务拆还是按技术层拆
- 30 秒短答:先按职责拆,再按可独立失败和可独立观测原则微调,不按文件夹结构机械拆。
- 面试官追问点:你如何避免“上帝节点”。
- 高频误区:节点过粗导致不可调试,或过细导致调度成本高。
A4. 边路由规则和模型路由如何配合
- 30 秒短答:规则路由先处理高置信场景,模型路由兜底长尾不确定场景。
- 面试官追问点:规则命中率与误路由率如何平衡。
- 高频误区:全量依赖模型路由,成本和波动都高。
A5. 为什么说 thread_id 是运行时主键
- 30 秒短答:它绑定会话状态和 checkpoint,决定恢复、追踪与隔离边界。
- 面试官追问点:跨设备同一会话如何一致。
- 高频误区:把
thread_id和 request_id 混用。
A6. 如何给非技术面试官解释 LangGraph 价值
- 30 秒短答:把“智能回答”变成“可管理流程”,能暂停审批、失败恢复、定位问题。
- 面试官追问点:对业务 KPI 有何直接影响。
- 高频误区:只讲术语,不讲风控与成本收益。
B 组:可靠性与可控性(6 题)
B1. Durable execution 的必要条件是什么
- 30 秒短答:稳定状态模型 + checkpointer + 可重入节点逻辑。
- 面试官追问点:重复执行如何做到幂等。
- 高频误区:有日志就以为可恢复。
B2. 中断恢复为什么不能靠前端重发请求
- 30 秒短答:前端重发无法保证图状态连续性,审批语义也会丢;恢复应基于持久化状态。
- 面试官追问点:恢复后从哪一节点继续。
- 高频误区:重放全部步骤导致副作用重复触发。
B3. 如何处理工具调用超时
- 30 秒短答:在节点层定义超时与重试策略,超限后走降级分支并保留可观测错误码。
- 面试官追问点:哪些错误可重试,哪些不可重试。
- 高频误区:统一无限重试。
B4. 如何防止高风险工具被误调用
- 30 秒短答:高风险工具白名单 + 参数校验 + interrupt 审批三道关。
- 面试官追问点:紧急场景如何旁路审批。
- 高频误区:只做提示词警告,不做系统级限制。
B5. 如何定义可恢复失败与不可恢复失败
- 30 秒短答:可恢复失败指重试后状态一致且无副作用放大;不可恢复失败需人工介入或补偿流程。
- 面试官追问点:补偿动作如何设计。
- 高频误区:所有失败都自动重试。
B6. 线上事故后第一件事做什么
- 30 秒短答:冻结可疑变更并抽样回放,先找“首个偏离节点”再定责。
- 面试官追问点:如何避免事故复发。
- 高频误区:先改 prompt 再定位。
C 组:多 Agent 与工具编排(6 题)
C1. 什么时候必须上 supervisor-worker
- 30 秒短答:当任务天然有分工且需要并行或独立迭代时,例如检索、分析、写作链路明显分离。
- 面试官追问点:拆分后怎么衡量收益。
- 高频误区:单任务也硬拆多 agent。
C2. Worker 输出为什么必须结构化
- 30 秒短答:结构化才能被上游可靠消费,减少 supervisor 对自由文本的脆弱解析。
- 面试官追问点:字段变更如何兼容。
- 高频误区:worker 只返回一段自然语言。
C3. 并行 worker 结果冲突怎么处理
- 30 秒短答:定义仲裁策略,例如优先级、证据打分或 finalizer 合并规则。
- 面试官追问点:冲突证据如何展示给用户。
- 高频误区:简单拼接所有结果。
C4. 为什么需要工具调用预算
- 30 秒短答:防止循环调用和成本失控,预算是 agent 系统的止损器。
- 面试官追问点:预算耗尽后如何优雅降级。
- 高频误区:只限制 token,不限制工具次数。
C5. 工具 schema 设计最重要的原则是什么
- 30 秒短答:参数可验证、语义单一、失败可观测。
- 面试官追问点:版本升级如何不破坏老调用。
- 高频误区:一个工具承载多个业务语义。
C6. 如何降低模型选错工具的概率
- 30 秒短答:缩小工具集合、强化工具描述差异、增加路由规则和拒答分支。
- 面试官追问点:离线如何评估工具选择质量。
- 高频误区:把所有工具都注册给同一个节点。
D 组:记忆与长期状态(5 题)
D1. 短期记忆和长期记忆怎么划线
- 30 秒短答:短期记忆服务当前会话任务完成,长期记忆只保留稳定偏好与高价值事实。
- 面试官追问点:长期记忆更新触发条件是什么。
- 高频误区:把整段对话原样长期存储。
D2. 会话变长后上下文成本怎么控
- 30 秒短答:摘要压缩 + 关键事实提取 + 检索增强,而不是全量拼接历史。
- 面试官追问点:摘要漂移如何纠正。
- 高频误区:每轮都把历史完整送入模型。
D3. 缓存和长期记忆的关系是什么
- 30 秒短答:缓存解决重复查询性能,长期记忆解决跨会话个性化,两者目标不同。
- 面试官追问点:缓存失效策略如何定。
- 高频误区:把缓存命中当作用户记忆。
D4. 多租户下记忆隔离怎么做
- 30 秒短答:命名空间至少带租户维度,读取和写入都做租户校验。
- 面试官追问点:迁移租户数据如何审计。
- 高频误区:只在 UI 层做隔离,存储层无隔离键。
D5. 何时应该删除记忆
- 30 秒短答:用户撤回授权、事实过期、风险信息变更时应触发删除或失效。
- 面试官追问点:删除后如何保证不再被召回。
- 高频误区:只标记软删除,检索仍可命中。
E 组:评测与线上排障(5 题)
E1. LangGraph 项目最小评测集怎么建
- 30 秒短答:覆盖主流程、长尾、失败恢复、审批中断四类样本,先小后全。
- 面试官追问点:样本更新节奏如何定。
- 高频误区:只用 happy path 做评测。
E2. 如何判断问题在路由层还是生成层
- 30 秒短答:先看节点轨迹与工具调用,再看最终生成;路由错通常在前半链路就可见。
- 面试官追问点:你会记录哪些关键字段。
- 高频误区:直接改提示词掩盖路由缺陷。
E3. 为什么要做回放测试
- 30 秒短答:回放可以复现实例输入与状态,定位回归是由模型、提示词还是路由变更引起。
- 面试官追问点:回放如何保证数据脱敏。
- 高频误区:线上出错后只看聚合指标。
E4. 你如何定义“上线可接受”
- 30 秒短答:功能正确率、失败恢复率、审批漏检率、延迟和成本都要达标,不能只看回答流畅度。
- 面试官追问点:阈值如何制定。
- 高频误区:只做人工主观打分。
E5. 模型升级时最容易出什么问题
- 30 秒短答:工具选择分布漂移、结构化输出偏移、长尾路由策略失效。
- 面试官追问点:如何做灰度与回滚。
- 高频误区:升级后不跑历史回归集。
七、面试速答总纲(可直接背)
- LangGraph 的核心价值是把 agent 变成可管理运行时,不是只会“多步调用”。
- 生产系统先回答可控性问题,再回答模型能力问题。
checkpointer + thread_id + interrupt是工程三件套。- 路由优先规则化,模型兜底长尾。
- 评测必须覆盖失败与恢复路径,而不是只测成功样本。
参考资料
- LangGraph Overview: https://docs.langchain.com/oss/python/langgraph/overview
- LangGraph Case Studies: https://docs.langchain.com/oss/python/langgraph/case-studies
- LangGraph Durable Execution: https://docs.langchain.com/oss/python/langgraph/durable-execution
- LangGraph Persistence: https://docs.langchain.com/oss/python/langgraph/persistence
- LangGraph Interrupts: https://docs.langchain.com/oss/python/langgraph/interrupts
- Thinking in LangGraph: https://docs.langchain.com/oss/python/langgraph/thinking-in-langgraph
- Workflows and agents: https://docs.langchain.com/oss/python/langgraph/workflows-agents