LangGraph
一句话定位
LangGraph 不是一个像 Claude Code / opencode 那样的单体 CLI agent harness,而是一个通用的图编排 + 持久化执行引擎(内部代号 “Pregel”,BSP/bulk-synchronous-parallel 模型),create_react_agent 只是搭在这套引擎之上的一个”预制件”(prebuilt),且在这个 commit 里已带 legacy 色彩——LangChain 官方更推荐的新入口是另一个包 langchain.agents.create_agent。
核心架构总览
Monorepo,独立版本化的子库(libs/),本次分析针对 commit be999ad38a8443a2a64d468e33c1228ca5aede4f:
libs/langgraph/(核心引擎,langgraph包 = 1.2.7)——状态图编译器、Pregel 执行循环、channels(状态归约)、checkpoint 挂接、streaming。libs/prebuilt/(langgraph-prebuilt= 1.1.0)——create_react_agent(ReAct 风格工具调用循环)、ToolNode(工具派发)、ValidationNode。libs/checkpoint/(langgraph-checkpoint)——抽象BaseCheckpointSaver(短期/线程持久化)、BaseStore(长期/跨线程记忆)、BaseCache(节点级 memoization)。仓库内只带内存参考实现。libs/checkpoint-sqlite/、libs/checkpoint-postgres/——具体 checkpointer/store 后端。Redis/MongoDB/Oracle 版本是独立 pip 包(如langgraph-checkpoint-redis),不在本仓库内(据官方 memory 文档确认)。libs/cli/(langgraph-cli)——开发服务器/部署工具:把一张图构建成 Docker 镜像跑成 HTTP 服务(LangGraph Platform/Server)。这是本仓库里最接近”沙箱”的东西——是部署容器,不是逐工具调用的执行沙箱。libs/sdk-py/、libs/sdk-js/——面向已部署 LangGraph Server 的客户端 SDK,其中包含服务端 Auth 类(认证/鉴权 hook)——“安全/权限”维度具体落地的地方。
关键范围事实:这个 commit 里大量”agent 形状”的功能(AgentState/AgentStatePydantic TypedDict、HumanInterrupt/HumanInterruptConfig/ActionRequest 这套 HITL 审批类型)都带 @deprecated(...) 装饰器,指向 langchain.agents / langchain.agents.interrupt(另一个更新的包)。langgraph.prebuilt.create_react_agent 仍可用但偏 legacy。多 agent supervisor/swarm 模式不在本仓库内,官方放在独立仓库 langchain-ai/langgraph-supervisor-py(经搜索确认存在,本轮未克隆读取)。仓库内 docs/ 目录已只剩一个重定向文件 docs/llms.txt,官方文档实际托管在 docs.langchain.com——本次分析对该站点做了两次活取(memory、observability 两页)。
Agent Loop(主循环 / 何时继续何时停)
两层结构:
- 通用引擎层:Pregel 的 BSP “superstep” 循环,
libs/langgraph/langgraph/pregel/_loop.py(1988 行)。PregelLoop.tick()计算下一批可执行任务 → 检查interrupt_before→ 执行任务 →after_tick()应用写入、打 checkpoint、检查interrupt_after。循环终止条件:任务队列为空(status="done"),或step > stop(stop = step + recursion_limit + 1,pregel/_loop.py:1701,1961),触发GraphRecursionError(抛出点在pregel/main.py:3017-3026,另一处校验在pregel/main.py:2578)。这是硬性递归上限,与具体 agent 逻辑无关。 - ReAct agent 特定的”继续/停止”:
libs/prebuilt/langgraph/prebuilt/chat_agent_executor.py::should_continue(第 831 行)——若最后一条AIMessage没有tool_calls则停(跳转 END 或 post-hook/structured-response 节点);否则为每个 tool call 派发一个Send("tools", ...)(并行执行)。另有一个软性早停_are_more_steps_needed(第 620 行):remaining_steps(用户可配置的 per-state 计数器,独立于recursion_limit)低于 1-2 时强制提前返回”步数不够”的回复,专门为了给”直接返回工具结果”的收尾留出余量。
记忆与上下文管理(压缩、长期记忆、会话持久化)
- 短期(线程作用域):
BaseCheckpointSaver+ 具体后端(InMemorySaver、SqliteSaver、PostgresSaver;Redis/Mongo/Oracle 为独立包)——按thread_id持久化完整图状态快照,支撑多轮对话与可恢复执行。 - 长期(跨线程):
BaseStore(libs/checkpoint/langgraph/store/base/__init__.py)——分层命名空间(namespace: tuple[str,...])的 KV 存储,可选接语义搜索索引(InMemoryStore(index={"embed":..., "dims":...}),官方 memory 文档确认)。节点/工具内通过runtime.store.get/put/search访问。 - 上下文窗口管理(原生、非学习型):
trim_messages(基于 token 预算的滑窗,来自langchain_core)与RemoveMessage/REMOVE_ALL_MESSAGES(通过add_messagesreducer 永久删除,libs/langgraph/langgraph/graph/message.py)。摘要压缩不是 langgraph core 原生能力——官方文档示例里的SummarizationNode/RunningSummary是从独立的langmem包导入的;langgraph 只提供机制(用户自写summarize_conversation节点 +RemoveMessage裁剪),不内置摘要器。 pre_model_hook/post_model_hook(chat_agent_executor.py)是 prebuilt ReAct agent 里每次模型调用前后的既定插入点,用于裁剪/摘要/护栏。
工具体系(定义/调用协议/注册/权限)
- 工具是普通 Python callable 或
BaseTool(langchain-core)实例;ToolNode(libs/prebuilt/langgraph/prebuilt/tool_node.py:622,全文件 2030 行)把一组工具包装成图节点。 - 派发:模型最后一条
AIMessage的tool_calls一一映射为工具执行,通过get_executor_for_config并行执行(concurrent.futures/asyncio)。 - 注册/schema:标准 langchain
@tool装饰函数自动生成 JSON schema,模型侧通过.bind_tools(tools)绑定(chat_agent_executor.py:586)。 - 特殊注入注解:
Annotated[T, InjectedState]/Annotated[T, InjectedStore]——让工具接收图状态或 store 对象作为参数,但对模型的工具 schema 隐藏这些参数(tool_node.py约 1753、1829 行)。 - 类权限原语:工具可以返回
Command对象而非普通值,直接修改图状态或触发goto——这是工具自行实现审批/路由逻辑的组合点;langgraph core 没有独立的声明式工具权限清单(对比 opencode 的通配符权限引擎)。 - 错误处理:
handle_tool_errors参数支持 bool/str/异常类型/tuple/callable;默认策略(_default_handle_tool_errors,第 383 行)捕获参数校验类错误并包装为ToolMessage,但真正的执行错误会继续向上抛出。
Prompt 设计(系统提示结构、动态组装)
create_react_agent 的 prompt 参数(Prompt 类型别名,第 121 行)接受:None(裸消息)、str(包装成单条 SystemMessage 前置)、SystemMessage、callable (state) -> LanguageModelInput(完全动态,可读 state/context)、或完整 Runnable。_get_prompt_runnable(第 137 行)据此构建 RunnableCallable。
没有固定的多段式系统提示模板(不像 Claude Code/opencode 那样内置”environment/skills/reminders”结构)——prompt 组装完全交给用户;langgraph 只提供注入点 + Runtime[ContextT](.context)支持按次调用动态取值(如按调用切换模型家族,见 libs/cli/examples/graphs/agent.py)。
Router / 编排(任务分解、多 agent、子 agent)
- 核心原语均在
libs/langgraph/langgraph/types.py:Send(node, arg)——向同一/不同节点派发自定义 per-branch 状态(并行 map-reduce、并行工具调用);Command(update=..., resume=..., goto=..., graph=Command.PARENT)——更新状态 + 跳转节点,可选跳到父图(这是子图/子 agent 能够操纵调用方图状态的机制基础,即多 agent”handoff”的底层实现)。 - 子图组合:一个编译好的
StateGraph(CompiledStateGraph)可以作为节点加入另一张图(满足 node/Runnable 协议)——这是层级化多 agent 系统的组合机制,在graph/state.py中有结构性确认(子图 checkpointer 继承相关注释,约 283、1187 行)。 - 本仓库内没有内置的 supervisor/swarm/planner。官方 supervisor 模式在独立仓库
langchain-ai/langgraph-supervisor-py(经搜索确认,本轮未克隆,超出本 dossier 范围,留作交叉引用)。通用条件路由通过add_conditional_edges(node, routing_fn, path_map)(graph/state.py:969)实现,should_continue、route_tool_responses、post_model_hook_router(均在chat_agent_executor.py)都是这个机制的实例。
Skill / 插件体系
未找到 / 不适用。 在 libs/langgraph 和 libs/prebuilt 里没有找到 skill 文件加载、插件 manifest 发现机制,没有类似 Claude Code 的 SKILL.md 或 opencode 插件 Hooks 接口的等价物。LangGraph 的可扩展性模型是”写一个 Python 节点/工具/子图,接进图里”——组合发生在代码层面,不是运行时发现插件。
自进化能力(自我改进 / 学习型记忆 / eval 驱动纠错)
langgraph core 内未找到 / 不适用。 在 libs/langgraph 和 libs/prebuilt 全库搜索未发现反思循环、自我改进机制或 eval 门控的自动纠错(唯一相关命中是 tool_node.py:572 一处无关的注释用语 “injection without repeated reflection”,并非功能)。BaseCache(节点 memoization)与 checkpoint “time travel”(get_state_history/update_state,pregel/main.py:1479,2530)支持人工调试/回溯与分叉过去状态,不是自动化自我纠错。这个维度确实未实现——LangGraph 是编排基座,任何自我改进循环都要由用户以普通图节点的形式自行搭建。
可观测性(日志 / trace 格式)
- 原生/本地:
stream_mode="debug"发出结构化的TaskPayload/CheckpointPayload事件(libs/langgraph/langgraph/pregel/debug.py::map_debug_tasks、map_debug_checkpoint)——含 task id/name/input/触发条件、过滤后的 config tags、checkpoint 元数据。除这套 streaming 事件 schema 和 checkpointer 持久化的内容外,没有专有的落盘日志/trace 文件格式。 - 一等观测产品是 LangSmith(独立 SaaS,不在本仓库内):通过
LANGSMITH_TRACING=true+LANGSMITH_API_KEY启用;langsmith.tracing_context()上下文管理器支持选择性/动态 tracing 及每次调用的 project/tags/metadata;LangChainTracer回调可配anonymizer=create_anonymizer([...]),在数据进入 LangSmith 前做脱敏(如遮蔽 SSN)。此结论来自对https://docs.langchain.com/oss/python/langgraph/observability的活取确认,已存档于key-files/official-doc-observability.md。
安全与权限(审批门、密钥管理)
libs/langgraphcore 内没有节点/工具级别的权限引擎(对比某些 harness 的逐工具通配符审批规则)。- 服务端鉴权/授权确实存在,位于
libs/sdk-py/langgraph_sdk/auth/__init__.py(875 行):Auth类——@auth.authenticatehandler 校验 bearer token 返回MinimalUserDict{identity, permissions};@auth.on/@auth.on.threads.create/.read/.search/@auth.on.store等——针对每种资源(runs|threads|crons|assistants|store,类型定义见auth/types.py的AuthContext)、每种动作的细粒度授权回调,可返回布尔值允许/拒绝,或返回FilterType字典做行级作用域过滤(如{"owner": ctx.user.identity})。通过部署配置langgraph.json的"auth": {"path": "./auth.py:my_auth"}接入,由 LangGraph Server 强制执行,而非开源图执行库本身。 - 工具调用的人机审批门通过通用的
interrupt()原语实现(types.py:811,抛出GraphInterrupt,要求有 checkpointer,通过Command(resume=...)恢复),配合(本 commit 已弃用、迁往langchain.agents.interrupt)的HumanInterrupt/HumanInterruptConfig形状——allow_ignore/allow_respond/allow_edit/allow_accept四个标志位描述待处理动作的可交互方式(libs/prebuilt/langgraph/prebuilt/interrupt.py)。
沙箱与执行隔离
在图执行层面未实现。 节点就是普通的 in-process Python callable(同步或异步),没有针对节点/工具执行的 OS 级沙箱、seccomp、容器或虚拟机隔离。libs/langgraph/langgraph/_internal/_timeout.py 明确写明同步节点”无法在进程内安全取消”,即超时是尽力而为/仅异步生效,不是靠进程隔离强制执行。本仓库内唯一的容器/隔离边界在部署层:libs/cli/langgraph_cli/docker.py 构建 Docker 镜像(默认带 Postgres 服务)把整张图跑成 HTTP 服务——隔离的是部署的服务,不是单次运行内的逐工具调用。
与模型的协同设计
Runtime[ContextT]+StateGraph/create_react_agent上的context_schema,让节点/prompt 构建函数可以按每次调用的任意上下文分支(例如libs/cli/examples/graphs/agent.py里AgentContext{model: Literal["anthropic","openai"]}在ChatAnthropic/ChatOpenAI实例间切换)。create_react_agent的model参数既可以是静态BaseChatModel,也可以是动态 callable(state, runtime) -> LanguageModelLike,按次调用解析(_resolve_model/_aresolve_model,第 599-618 行)——支持依据 state 在对话中途换模型。- 结构化输出(
response_format参数,接受”(system_prompt, schema)“元组或裸 schema)通过.with_structured_output()实现,作为独立图节点加入(generate_structured_response),而非揉进主循环——这是刻意把”工具调用轮次”和”结构化输出轮次”分离的设计选择。 - langgraph core 本身不内置任何模型专属 prompt 模板或模型家族分支逻辑(不像 opencode 那样按模型家族维护独立
.txtprompt 文件)——这类逻辑留给用户的promptcallable/Runtime自行处理。
轨迹利用(session/trajectory 是否反哺训练/评测)
本仓库内未实现。 LangGraph 通过 checkpoint 持久化完整状态历史(get_state_history、update_state/fork,pregel/main.py:1479,2530),支持”time travel”式回放/调试和从任意历史 checkpoint 分叉,但这是人工的开发者调试工具,不是自动把轨迹回灌进模型训练或 eval harness 的流水线。LangSmith(外部产品)捕获的 trace 数据理论上可以通过 LangSmith 自身产品面转成 eval 数据集,但这个机制在本仓库之外,本次会话未验证(超出范围,记为”在 langgraph/langgraph 仓库内未找到”)。
与同类 harness 的关键差异(1-3 条,概述)
- 定位不同:LangGraph 是通用图编排/持久化执行引擎,不是单体 agent CLI——
create_react_agent只是众多可能的图拓扑之一,且在本 commit 中已偏 legacy(官方新入口langchain.agents.create_agent是另一个包)。这与 Claude Code/opencode 等”agent 循环即产品本体”的 harness 形成结构性差异。 - 安全模型分层:工具执行层没有权限引擎/沙箱,安全边界完全推到部署层(Docker 容器)和服务层(LangGraph Server 的
Auth类),核心库本身对”允许这个工具跑吗”没有意见。 - 可观测性外包给独立 SaaS:原生只有
stream_mode="debug"这一种事件流,没有专有本地 trace 文件格式;生产级可观测性依赖外部产品 LangSmith,这点与自带完整本地日志/trace 系统的 harness不同。 - 跨 harness 系统对比留待 synthesis 阶段。
原始源码定位
- repo: https://github.com/langchain-ai/langgraph
- commit/version analyzed:
be999ad38a8443a2a64d468e33c1228ca5aede4f(langgraphcore = 1.2.7,langgraph-prebuilt= 1.1.0) - 关键文件列表(相对仓库根目录):
libs/langgraph/langgraph/pregel/_loop.pylibs/langgraph/langgraph/pregel/_algo.pylibs/langgraph/langgraph/pregel/main.pylibs/langgraph/langgraph/pregel/debug.pylibs/langgraph/langgraph/types.pylibs/langgraph/langgraph/runtime.pylibs/langgraph/langgraph/graph/message.pylibs/langgraph/langgraph/errors.pylibs/langgraph/langgraph/_internal/_retry.pylibs/langgraph/langgraph/_internal/_timeout.pylibs/langgraph/langgraph/channels/*.pylibs/prebuilt/langgraph/prebuilt/chat_agent_executor.pylibs/prebuilt/langgraph/prebuilt/tool_node.pylibs/prebuilt/langgraph/prebuilt/interrupt.pylibs/checkpoint/langgraph/checkpoint/base/__init__.pylibs/checkpoint/langgraph/store/base/__init__.pylibs/checkpoint/langgraph/cache/base/__init__.pylibs/sdk-py/langgraph_sdk/auth/__init__.pylibs/sdk-py/langgraph_sdk/auth/types.pylibs/cli/langgraph_cli/docker.pylibs/cli/langgraph_cli/cli.pylibs/cli/examples/graphs/agent.py
一手源存档(sources/)
/Users/zhao/projects/self-wiki/ai-research/sources/harness/langgraph/ 下:
NOTES.md—— Stage 1 完整调研笔记(本页写作的直接依据)key-files/pregel/_loop.py、_algo.py、main.py、errors.py、runtime.py、types.py、graph_message.pykey-files/prebuilt/chat_agent_executor.py、tool_node.py、interrupt.pykey-files/checkpoint/checkpoint_base.py、store_base.py、cache_base.pykey-files/sdk-auth/auth_init.py、auth_types.pykey-files/examples/simple_agent_example.pykey-files/official-doc-add-memory.md(活取自 docs.langchain.com)key-files/official-doc-observability.md(活取自 docs.langchain.com)