「LangChain」LangChain 的底层架构与实现原理是什么?
0 前言
本文内容整理自公众号「小林面试笔记」的文章 3. LangChain 的底层架构与实现原理是什么?,用于记录与总结 LangChain 框架相关的核心面试知识点。
「LangChain 的底层架构与实现原理是什么?」,可以这样作答:
当前 LangChain v1 更像一套面向 Agent 的分层开发框架,而不是把 Prompt 串成 Chain 的工具:底层的
langchain-core定义 Message、Model、Tool 和 Runnable 等标准协议,各模型厂商的独立集成包负责把请求与响应适配到这些协议,应用层因此能用统一方式切换模型和工具;执行层中 Runnable 统一了同步、异步、批处理和流式调用,步骤固定的流程用 LCEL 组合,需要模型自主选择工具的任务则用create_agent。
create_agent会把模型节点和工具节点编译成 LangGraph 状态图:模型读取消息后生成 AIMessage,若其中含tool_calls,运行时执行对应工具,把结果包装成带相同调用 ID 的 ToolMessage 写回状态;模型再次读取工具结果并继续判断,直到生成最终回答。Agent 的循环就这样以「消息进出图、状态驱动边」的方式跑起来,而不是裸写一个 while 循环。在这套架构里分工明确:State 保存会变化的消息与业务状态,Runtime 提供可信上下文和长期 Store,Middleware 负责模型或工具调用前后的权限、重试、摘要与人工审批,LangGraph 负责路由、检查点、暂停恢复和长时间运行。一句话概括:LangChain 用标准协议统一组件,用
create_agent提供高层 Agent 入口,再由 LangGraph 承担有状态的执行运行时。
把 LangChain 说出「串 Chain 的工具」,是很多人的第一反应——但那只是早期最表面的用法,面试官一句「不同模型怎么统一?工具结果怎么回到模型?状态和循环由谁管理?」就能问住。这道题真正的考察点是:能不能从一次 Agent 请求出发,把各层如何协作讲清楚。这篇按「解决了什么 → 分几层 → 各层怎么协作 → 数据放哪 → 谁来扩展 → 谁来运行」的顺序把它讲透。
1 LangChain 解决了什么问题
先想清楚:没有 LangChain 行不行?直接调用一家模型厂商的 SDK 并不难,难的从来不是第一次调用,而是应用复杂之后。
一家厂商的响应格式、工具调用结构、流式返回方式都是一套;业务还要自己接 Prompt、接工具、管状态、做重试和追踪。两个模型之间,同样是「让模型调用一个天气工具」,A 厂商和 B 厂商的请求结构可能完全不同——一旦换模型,厂商专属字段已经散落在业务代码的各个角落,改到想哭。
LangChain 的核心思路是:在差异之上定义稳定接口。把「各家 SDK 的说法」翻译成一套公共协议,厂商集成做翻译,应用只依赖协议——就像全世界的电器插头各有各的形状,但插座接口统一之后,换电器只需要换插头。这样模型、工具、运行时都能相对独立地演进,应用层不跟着任何一家 SDK 反复改动。
2 一图看懂:LangChain v1 的四层架构
理解 LangChain v1,抓住四层就够(下面这张表格讲职责边界,不是严格的单向调用顺序):
| 层次 | 主要职责 | 典型对象 |
|---|---|---|
| 核心协议层 | 统一组件的数据结构与调用接口 | Message、Runnable、Model、Tool |
| 集成适配层 | 屏蔽模型、向量库和外部服务差异 | langchain-openai 等独立集成包 |
| Agent 开发层 | 提供高层 Agent 组装与扩展能力 | create_agent、Middleware、Structured Output |
| 编排运行层 | 管理状态、循环、路由、持久化和恢复 | LangGraph Runtime |

两层之间还有一条贯穿始终的横线——可观测性:通过运行事件和 Trace 记录模型调用、工具调用、耗时和异常,出了问题能顺着日志一步步查到是哪个环节。
顺带提醒一个容易误读的点:「协议层在最下面」不等于「越上层依赖越下层」是严格的调用链。比如模型和编译后的 Agent 都遵循 Runnable 调用方式(协议层的东西),但它们在架构里承担的角色完全不同——分层讲的是职责边界,不是调用顺序。
3 核心协议:Message、Tool 与 Runnable 如何统一
langchain-core 里类很多,但最值得理解的不是类名数量,而是一条数据如何从用户走到模型、再进入业务系统。这条路上要回答三个问题。
统一「传什么」——Message。 用户输入是 HumanMessage、模型输出是 AIMessage、工具执行结果是 ToolMessage。不同厂商原本各有一套消息格式,适配成 Message 之后,上层就不用跟着每家 SDK 的类反复改动——数据表达统一了。
划清边界——Tool。 模型能看到的只有工具的名称、描述和参数 Schema,它只能提出「我想调用哪个工具、参数是什么」;真正执行 Python 函数或外部服务的仍是应用程序。这是个刻意为之的边界:权限校验和副作用必须留在应用侧,模型只是「提议」者,不是「执行」者。这和工具调用的通用闭环一脉相承——模型决定调用、应用负责执行、结果再回传。
统一「怎么执行」——Runnable。 光有消息和工具还不够,三者要进入同一条流程,还需要统一的执行语义:Runnable 提供 invoke(同步)、异步调用、批处理和流式输出。对步骤已经确定的流程,就能用 LCEL(LangChain 表达式语言)把组件像管道一样串起来:
1 | |
这样看就很清楚了:Message 统一数据表达,Tool 划清模型与业务动作的边界,Runnable 统一执行方式——三者连起来以后,LangChain 才不只是替换模型 SDK 的薄封装。
但注意,上面的 LCEL 流程每一步都由开发者提前定死;Agent 不一样,它允许模型根据上下文自己决定要不要调用工具、下一步做什么——这就是下一节的主角。
4 Agent 的执行循环:一次请求怎么跑起来
Agent 的核心不是一次模型调用,而是模型和工具之间可能重复多轮的执行循环:
1 | |
(上面的伪代码对应的正是下图中的循环。)

其中 tool_call_id 非常重要:模型一轮可能请求多个工具(并行调用),工具结果必须通过调用 ID 与原请求对应,模型才知道每条结果属于哪次调用——就像同时发出几份快递,回执单上要写清楚是哪一单的签收。
create_agent 会根据模型、工具、系统提示词和中间件创建这套循环,但它返回的不是普通函数,而是编译后的 LangGraph 图。正因为是一张图,它才能在每一步保存状态、输出进度,并决定下一条执行边该走哪——这是后面几个章节都要用到的引子。
5 数据放在哪里:State、Context 与 Store
Agent 运行时要处理的数据不止消息一种。如果一股脑全塞进消息或 Prompt,没几下就把上下文撑爆,还分不清哪些是可信的、哪些是临时变的。当前运行时把数据分成三类:
| 数据 | 作用 | 示例 |
|---|---|---|
| State | 执行中不断变化的数据 | 消息、当前步骤、工具结果 |
| Context | 一次调用期间不变的可信依赖 | 用户 ID、租户、权限 |
| Store | 跨线程保存的数据 | 用户偏好、长期事实 |

把这三类分开放,收益很直接:可信的用户身份不需要让模型生成(它是 Context,不是让模型「猜」出来的);数据库连接之类的重资源不会被写进对话上下文;工具可以通过 Runtime 读取这些数据,而工具 Schema 里只暴露真正需要模型填写的参数——模型只看到它该填的空,看不到它不该碰的东西。
6 Middleware:模型与工具之间的扩展点
真实应用几乎都要做这些事:动态提示词、模型切换、工具筛选、重试、对话摘要、敏感信息处理、人工审批。如果全部塞进 Prompt 或 Tool,代码会很快纠缠成一团——于是有了 Middleware(中间件)。
Middleware 在模型和工具调用前后提供扩展点:
- 请求进入模型前:按用户身份生成系统提示词;历史消息太长时先做摘要再进模型;
- 模型决定调用工具后:先检查权限,敏感动作可以暂停,等待人工审批;
- 真正执行工具时:对临时网络故障做有上限的重试;
- 结果返回后:补上格式或安全校验。

一次请求从进入模型到离开 Agent,每个阶段都有清楚的扩展位置——像机场安检一样层层把关,而不是把所有检查塞进一个函数。特别要说明的是:Middleware 并不是另一套运行时,它运行在 create_agent 编译出的 LangGraph 内部,对执行行为做组合式扩展,不会把事情搞复杂。
7 LangGraph:有状态的执行运行时
回到面试官那句追问:「底层是不是一个 while 循环?」表面行为确实像——模型要调用工具就执行,不调用就退出。但只靠裸循环,两个生产级场景直接歇菜:
- 进程退出后中间状态找不回来:刚跑五轮工具调用,服务一重启,Agent 不知道自己在哪一步;
- 没法在敏感工具前暂停:比如「批量转账」这种动作,我们希望模型停下来等人工确认,甚至暂停几个小时再继续——裸 while 循环做不到。
LangGraph 把流程建模为 State + Node + Edge:State 保存状态,Node 执行模型或工具,Edge 决定下一步走哪条边。配合检查点保存每一步状态,就能支持中断恢复、人工介入、故障恢复和长时间运行。
还要破除一个常见误解:LangChain 和 LangGraph 不是简单的二选一关系。LangChain 提供高层组件和标准 Agent 架构(create_agent 就是它给的脚手架),LangGraph 提供底层执行能力(图、状态、检查点)。简单 Agent 直接用 create_agent 就够了;只有流程里需要复杂分支、并行、审批或精细状态控制时,才需要直接编写 LangGraph。一句话:LangChain 定协议,LangGraph 跑状态。
8 旧版 Chain 还能用吗
早期教程里的 LLMChain、ConversationChain 和各种旧式 Agent 执行器,如今都已经进了 langchain-classic——可以用于维护存量项目,但不再代表 LangChain v1 的主架构。新项目按这个边界选型:
| 场景 | 更合适的方式 |
|---|---|
| 固定的 Prompt、Model、Parser 流程 | Runnable + LCEL |
| 标准模型与工具循环 | create_agent |
| 复杂分支、并行、暂停恢复和人工审批 | 直接使用 LangGraph |
| 维护旧式 Chain 项目 | langchain-classic 后渐进迁移 |
所以新版探索路线很清晰:v1 的主线是「标准协议 + create_agent + LangGraph Runtime」,Runnable 与 LCEL 服务确定性流程,旧式 Chain 只留给存量项目。
9 面试总结
回答这道题,最大的雷就是把 LangChain 说成「把 Prompt 串成 Chain 的工具」——那是 2023 年的答案,不是 v1 的答案。先避开几个误区:
| 误区 | 正解 |
|---|---|
| LangChain 就是把 Prompt、模型、解析器串成 Chain | 那是早期最表面的用法;v1 是一套面向 Agent 的分层开发框架 |
| 底层就是一个 while 循环,模型要调工具就执行、不调就退出 | 表面行为相似,但生产级 Agent 还要状态、路由、持久化、中断恢复和人工介入,create_agent 底层运行在 LangGraph 上 |
| 记住「create_agent 底层是 LangGraph」就够了 | 这是结论不是架构题答案——Message、Tool、State、Context、Store、Middleware 的职责与协作才是考察点 |
| LangChain 和 LangGraph 二选一 | 分层关系:LangChain 给高层组件与标准 Agent 架构,LangGraph 给底层执行能力;简单 Agent 用 create_agent,复杂流程才手写 LangGraph |
| LLMChain 还是主角 | 已进 langchain-classic;v1 主线是「标准协议 + create_agent + LangGraph Runtime」 |
再按这张框架组织答案:
| 框架 | 要点 |
|---|---|
| 协议统一 | langchain-core 定义 Message、Tool、Runnable:Message 统一传什么,Tool 划清模型提议与应用执行(权限、副作用留在应用侧)的边界,Runnable 统一 invoke/异步/批处理/流式的执行方式;厂商用独立集成包适配 |
| 执行循环 | 用户消息进 State → 模型生成 AIMessage → 含 tool_calls 就经 Runtime 执行工具 → 结果按 tool_call_id 包装成 ToolMessage 写回 → 模型再判断,直到生成最终回答;create_agent 返回的是编译后的 LangGraph 图 |
| 数据职责 | State 保存执行中可变状态(消息、当前步骤、工具结果),Context 保存一次调用内不变的可信依赖(用户 ID、租户、权限),Store 保存跨线程长期数据(偏好、事实) |
| 扩展与运行 | Middleware 在模型与工具调用前后加权限、重试、摘要、人工审批;LangGraph 负责路由、检查点、暂停恢复与长时间运行 |
| 版本边界 | 确定性流程用 Runnable + LCEL;标准模型工具循环用 create_agent;复杂分支/并行/审批直接写 LangGraph;旧 Chain 仅维护存量 |
追问预案:
- 「模型怎么知道工具结果对应哪次调用?」——
tool_call_id:模型一轮可并行请求多个工具,工具结果通过调用 ID 与原请求对应,运行时把同 ID 的结果包装成对应 ToolMessage,模型按 ID 读取每条结果。 - 「LangGraph 的检查点怎么支撑人工审批?」——流程建模为 State + Node + Edge,检查点保存每一步状态;敏感工具节点前中断,状态持久化,人工审批通过后从该状态继续执行。
- 「Middleware 在什么时候执行?」——四个扩展时机:模型调用前(动态提示词、历史摘要)、决定调用工具后(权限检查、暂停审批)、工具执行中(限次重试)、结果返回后(格式与安全校验)。
- 「create_agent 和直接写 LangGraph 的区别?」——create_agent 是标准「模型-工具循环」的高层封装,编译成图即可用;只有需要复杂分支、并行、审批、精细状态控制时,才直接编写 LangGraph 自定义节点与边。
- 「LCEL 和 Agent 是什么关系?」——都建立在 Runnable 语义上:LCEL 组合的是步骤固定的确定性流程(
prompt | model | output_parser),Agent 则让模型自主决定是否调用工具、下一步做什么,LCEL 适合后者无法覆盖的确定场景。
参考
- 3. LangChain 的底层架构与实现原理是什么? | 小林面试笔记
- 2. 请你谈谈对 LangChain 中核心概念「Chain」的理解,以及它的核心作用与设计理念。 | 小林面试笔记(相关:Chain 概念与 v1 架构的演进关系)
- LangChain 官方文档:Overview
- LangChain 官方文档:Runtime
- LangChain 官方文档:Middleware
- LangGraph 官方文档:Overview
本文图片均来源于公众号「小林面试笔记」,版权归原作者所有。