如果只是调用一次大模型,代码通常并不复杂:准备 Prompt,发送给模型,再拿到返回结果。

但当需求变成“先判断问题,再查询数据,根据结果继续执行,必要时调用多个工具,并记住前面的信息”,单次 LLM 调用就不够了。开发者需要管理模型、工具、上下文、执行状态、异常处理以及整个调用循环。

这正是 AI Agent 要解决的问题。

LangChain 的作用,可以理解为把这些能力组织成一套统一的 Agent 开发框架。理解它不需要先记大量 API,先掌握 Model、System Prompt、Tools、Agent Loop、State / Memory、Middleware、Structured Output 这 7 个概念,就能建立完整的认识。

一、整体结构

AI Agent 可以简单理解为:由大模型负责判断下一步做什么,并能够使用外部工具持续执行任务的程序。

普通 LLM 调用通常是:

代码片段Text
用户输入 → 模型 → 返回结果

而 Agent 更接近:

代码片段Text
用户输入

模型判断

是否需要工具?

调用工具

获得结果

再次交给模型判断

……

最终答案

也就是说,两者最大的区别不是有没有 Prompt,而是有没有一个持续运行的决策—执行循环

LangChain 当前通过 create_agent() 提供 Agent 的高层入口。它负责把模型、工具、状态、中间件等组件组装起来,底层则使用 LangGraph 的图运行时执行整个 Agent 循环。

因此可以把相关层级大致理解为:

代码片段Text
应用程序

LangChain Agent

Model / Tools / Middleware / Memory

LangGraph Runtime

LangChain 更关注“怎样方便地搭建 Agent”,LangGraph 则提供更底层的状态、节点、边和执行能力。

理解这个关系之后,再看下面 7 个概念就会清楚很多。

二、模型与提示词

第一个概念是模型(Model)

模型是 Agent 的决策中心。它负责阅读当前上下文,理解用户目标,并决定是直接回答,还是调用某个工具。

LangChain 对不同模型提供了统一接口。例如可以直接通过模型标识创建 Agent:

代码片段Python
from langchain.agents import create_agent
 
agent = create_agent(
    model="openai:gpt-5.5",
    tools=[]
)

也可以先创建具体模型对象,再交给 Agent。这样更方便配置温度、超时、Token 数量等参数。

和 Model 紧密相关的是第二个概念:系统提示词(System Prompt)

模型决定“怎么思考”,System Prompt 则规定“应该按照什么规则工作”。

例如:

代码片段Python
agent = create_agent(
    model="openai:gpt-5.5",
    tools=[],
    system_prompt="""
你是一个库存管理助手。
回答库存问题时必须以系统查询结果为准,
不得自行猜测库存数量。
"""
)

这里真正解决的问题,不是让 Prompt 写得更长,而是明确 Agent 的行为边界。

实际项目中,模型看到的不只有 System Prompt,还包括消息历史、可用工具、当前状态以及输出格式等。这些内容共同构成模型每一次调用时的上下文。LangChain 将这部分工作归入 Context Engineering,也就是上下文工程。

三、工具与调用

第三个概念是工具(Tool)

LLM 本身主要负责语言理解和生成,并不能访问你的数据库、内部 API 或业务系统。

如果希望 Agent 查询库存,就需要把查询库存的能力包装成 Tool。

代码片段Python
from langchain.tools import tool
 
@tool
def get_stock(product: str) -> int:
    """查询指定商品当前库存数量。"""
    stocks = {
        "机械键盘": 12,
        "无线鼠标": 5,
    }
    return stocks.get(product, 0)

这里的函数并不是由开发者直接决定什么时候调用。

LangChain 会把工具的名称、参数和描述提供给模型。模型结合用户问题判断是否需要调用,以及应该传入什么参数。工具执行后的结果又会重新放回 Agent 上下文,让模型继续判断下一步。

于是:

代码片段Text
“机械键盘还有库存吗?”

可能被转换为:

代码片段Text
调用 get_stock(product="机械键盘")

得到:

代码片段Text
12

模型再根据这个结果生成最终回答。

这也是 Tool Calling 与普通函数调用的重要区别:函数由程序流程决定调用,Agent Tool 通常由模型根据当前任务决定是否调用。

四、Agent循环

第四个概念是 Agent Loop

如果只理解 Tool,而没有理解 Agent Loop,很容易把 Agent 看成“会自动调用函数的聊天机器人”。

实际上,Agent 最重要的机制是循环执行。

一次任务可能经历:

代码片段Text
Model

Tool

Model

Tool

Model

Final Answer

例如用户提出:

查询机械键盘库存,如果超过 10 件,告诉我是否可以接一个 8 件的订单。

模型第一次并不知道库存,因此调用 get_stock()

工具返回 12。

结果重新进入模型后,模型发现:

代码片段Text
12 > 10

同时:

代码片段Text
12 >= 8

于是停止工具调用,给出最终答案。

LangChain 的 create_agent() 会自动建立这种循环。当模型继续产生 Tool Call 时,Agent 执行工具;当模型不再要求调用工具并产生最终输出时,循环结束。底层执行过程由 LangGraph 管理。

这一步实际上把开发者从大量手写流程代码中解放了出来。

否则你需要自己处理:

代码片段Python
while True:
    response = call_model()
 
    if response.has_tool_call:
        result = execute_tool()
        append_result(result)
    else:
        break

而真实项目还会涉及多工具、失败重试、状态保存、调用限制等问题,循环很快就会变复杂。

五、状态与记忆

第五个概念是状态(State)与记忆(Memory)

Agent 在执行过程中需要不断保存数据。例如:

代码片段Text
用户说了什么
模型返回了什么
调用了哪个工具
工具返回了什么
当前执行到哪一步

这些数据构成 Agent 的 State。

LangChain Agent 默认会维护消息状态,因此同一次执行过程中,模型可以看到前面的 Tool Message 和对话消息。

但如果希望第二次调用还能记住第一次的信息,就需要持久化。

LangChain 的短期记忆以线程为范围,可以通过 Checkpointer 保存 Agent State。

例如:

代码片段Python
from langgraph.checkpoint.memory import InMemorySaver
 
checkpointer = InMemorySaver()
 
agent = create_agent(
    model="openai:gpt-5.5",
    tools=[get_stock],
    checkpointer=checkpointer
)

调用时指定同一个 thread_id

代码片段Python
config = {
    "configurable": {
        "thread_id": "user-001"
    }
}

同一个线程后续执行时,就可以继续读取之前的状态。

需要注意,State 不等于长期记忆

短期记忆通常服务于当前会话线程;如果希望跨会话保存用户偏好、档案或长期知识,LangChain 还提供基于 Store 的长期记忆机制。

可以简单记成:

代码片段Text
State / Checkpointer
→ 当前会话发生了什么

Store
→ 跨会话长期保存什么

六、中间件机制

第六个概念是中间件(Middleware)

当 Agent 从演示代码进入真实项目后,很快会出现新的需求:

代码片段Text
模型失败时自动重试
工具调用失败时统一处理
调用危险工具前需要审批
对敏感信息进行过滤
限制最大模型调用次数
上下文太长时自动摘要
根据任务动态选择模型或工具

如果把这些逻辑全部塞进 Tool 或 Prompt,Agent 会越来越难维护。

Middleware 的作用,就是在 Agent 生命周期的关键位置插入控制逻辑,而不需要改写整个 Agent Loop。

例如可以在模型调用前处理上下文,在工具执行前检查权限,在模型返回后验证结果。

LangChain 还提供了多种内置 Middleware,包括摘要、Human-in-the-loop、模型调用限制、工具调用限制、重试、PII 检测等。

因此可以把它理解成:

代码片段Text
Agent Loop

    ├── before model
    ├── model
    ├── after model
    ├── before / wrap tool
    ├── tool
    └── after tool

Middleware 并不是另一个 Agent,也不是独立 Runtime,而是嵌入 Agent 执行过程中的扩展机制。

七、结构化输出

第七个概念是结构化输出(Structured Output)

很多 Agent 教程最后只打印一段自然语言:

代码片段Text
机械键盘目前库存 12 件,可以接受 8 件订单。

但真实系统往往不能只依赖这句话。

前端、数据库或后续业务逻辑可能更希望得到:

代码片段JSON
{
  "product": "机械键盘",
  "stock": 12,
  "can_accept_order": true
}

这就是 Structured Output 要解决的问题。

LangChain 可以通过 response_format 指定 Pydantic Model、Dataclass、TypedDict 或 JSON Schema,让 Agent 最终返回可验证的数据结构。结果会保存在 Agent State 的 structured_response 中。

例如:

代码片段Python
from pydantic import BaseModel
 
class StockDecision(BaseModel):
    product: str
    stock: int
    can_accept_order: bool

创建 Agent 时:

代码片段Python
agent = create_agent(
    model="openai:gpt-5.5",
    tools=[get_stock],
    response_format=StockDecision
)

这样 Agent 的最终结果就不再只是供人阅读的文本,还能直接参与程序逻辑。

这也是开发 Agent 时很容易被忽略的一点:自然语言适合人与 Agent 交流,结构化数据更适合 Agent 与系统交流。

八、完整示例

把前面的概念组合起来,可以得到一个很小但完整的 Agent。

先安装依赖:

代码片段Bash
pip install -U langchain langchain-openai

LangChain 当前要求 Python 3.10 及以上;不同模型提供商的集成通常安装在独立 Provider Package 中,例如 OpenAI 使用 langchain-openai

下面实现一个库存 Agent:

代码片段Python
from pydantic import BaseModel
from langchain.agents import create_agent
from langchain.tools import tool
from langgraph.checkpoint.memory import InMemorySaver
 
 
@tool
def get_stock(product: str) -> int:
    """查询指定商品当前库存数量。"""
    stocks = {
        "机械键盘": 12,
        "无线鼠标": 5,
    }
    return stocks.get(product, 0)
 
 
class StockDecision(BaseModel):
    product: str
    stock: int
    can_accept_order: bool
 
 
agent = create_agent(
    model="openai:gpt-5.5",
    tools=[get_stock],
    system_prompt="""
你是库存管理助手。
判断是否能够接单时,必须先查询实际库存。
只有库存数量大于等于订单数量时才能接单。
""",
    response_format=StockDecision,
    checkpointer=InMemorySaver(),
)
 
 
result = agent.invoke(
    {
        "messages": [
            {
                "role": "user",
                "content": "客户想订购 8 个机械键盘,可以接单吗?"
            }
        ]
    },
    {
        "configurable": {
            "thread_id": "order-001"
        }
    }
)
 
print(result["structured_response"])

运行结果

示例输出如下:

代码片段Text
product='机械键盘' stock=12 can_accept_order=True

从这个结果可以看到,代码本身并没有写:

代码片段Python
get_stock("机械键盘")

真正的执行过程是:

代码片段Text
用户提出订单需求

模型理解任务

决定调用 get_stock

Tool 返回 12

结果写回 Agent State

模型继续判断

生成 StockDecision

Agent Loop 结束

Model 负责判断,System Prompt 规定规则,Tool 获取外部数据,Agent Loop 负责持续执行,State 保存过程信息,Structured Output 则把最终结果转换成程序可直接使用的数据。

这几部分组合起来,才形成一个完整的 Agent。

九、使用边界

理解 LangChain 之后,还需要避免另一个误区:并不是所有 LLM 应用都需要 Agent。

如果业务流程完全确定,例如:

代码片段Text
读取文件
→ 提取文本
→ 调用模型总结
→ 保存数据库

这种流程用普通代码或固定 Workflow 往往更合适。因为每一步都已经由开发者确定,没有必要让模型判断下一步。

Agent 更适合那些执行路径无法在开发时完全确定的任务,例如:

代码片段Text
根据问题决定查询哪个数据源
根据搜索结果决定是否继续搜索
根据用户意图选择不同工具
根据执行结果动态调整下一步

如果只需要模型生成文本,直接调用 Model 就够了。

如果需要模型在有限工具之间自主决策,可以使用 LangChain Agent。

如果工作流包含大量明确的分支、并行节点、循环和人工审批,而且希望精确控制每一步,则可以进一步使用更底层的 LangGraph。

这种选择比单纯比较哪个框架“更强”更有意义。

十、总结

本文介绍的 7 个概念,我们可以用一条执行链将这些概念串起来:

代码片段Text
System Prompt + State

      Model

决定是否调用 Tool

     Tool Result

更新 State / Memory

Middleware 控制执行过程

继续 Agent Loop

Structured Output

由此可以看出,LangChain 并不是简单地给大模型增加几个工具,而是把模型决策、工具执行、上下文状态和运行控制组织成一个持续执行的 Agent 系统。

实际学习时,可以先从“一个模型 + 一个 Tool + create_agent()”开始,观察模型为什么调用工具、工具结果怎样重新进入模型。理解这条最小 Agent Loop 之后,再逐步加入 Memory、Middleware 和 Structured Output,会比一开始研究复杂多 Agent 架构更容易建立清晰认识。