一文搞懂 LangChain Message:从 4 种消息类型到 Agent 状态流转
如果你正在学习 LangChain 或基于 LangChain 搭建 Agent,那么「Message(消息)」是绕不开的第一道坎。
它既是模型的输入输出,也是对话的上下文单元,更是 Agent 状态机的"燃料"。
本文将带你系统掌握 Message 的全部要点:4 种消息类型 → 工具调用流程 → Agent 动态流转 → 进阶属性 State 与 additional_kwargs。
目录
- 一、什么是 Message?
- 二、消息的分类(4 种类型)
- 三、一次完整的对话流程
- 四、完整代码示例
- 五、Agent 中消息的动态过程
- 六、State 与消息的 additional_kwargs
- 七、核心要点速查表
- 总结
一、什么是 Message?
消息(Message) 是 LangChain 的核心概念之一。
它有两层含义:
- 作为 I/O:表示模型的输入和输出。
- 作为上下文单元:消息列表中的历史消息会作为当前调用的上下文,引导模型生成合适的回复。
可以这样理解:Message ≈ 大模型世界里"一句对话"的最小单位。把多条 Message 按顺序放进一个列表,就构成了模型能"看见"的全部对话历史。
二、消息的分类(4 种类型)
LangChain 主要支持以下 4 种消息类型:
| 消息类型 | 角色 | 主要作用 |
|---|---|---|
SystemMessage | 系统 | 设置指令,定义模型角色、语气和回答规则 |
HumanMessage | 用户 | 表示用户输入,可包含多模态内容 |
AIMessage | 助手 | 表示模型输出,可包含工具调用信息 |
ToolMessage | 工具 | 工具执行结果回传给模型 |
下面对每一种消息逐一拆解。
SystemMessage
一组初始指令,用于引导模型的整体行为。
常见用途:
- 设置对话基调
- 定义模型角色
- 指定回答方式
- 建立响应规范和限制
示例:
from langchain.messages import SystemMessage
SystemMessage(
"""你是一个编程助手,专门帮助用户解答编程相关问题。
请用清晰、准确的语言回答,并提供实用的代码示例。"""
)
💡 最佳实践:通常放在消息列表的最前面,作为全局规则贯穿整次会话。
HumanMessage
表示用户的输入和交互内容,是最"日常"的一类消息。
它可以包含:
- 文本、图像、音频、文件等任意多模态内容
- 多轮对话中的追问
示例:
from langchain.messages import HumanMessage
HumanMessage(
"我想学习 Python 中的列表推导式,能否详细解释一下并给出几个实用的例子?"
)
AIMessage
表示模型调用产生的输出。除了普通文本外,还可以包括:
- 多模态数据(图片、音频等)
- 工具调用(Tool Calls)
- 特定供应商的元数据(metadata,如 token 用量、响应耗时等)
示例:
from langchain.messages import AIMessage
AIMessage(
"""列表推导式是 Python 中一种简洁创建列表的方法。
基本语法是:[expression for item in iterable if condition]"""
)
ToolMessage
对于支持工具调用(Tool Calling)的模型,AI 消息可以包含工具调用指令,而 ToolMessage 用来把工具执行后的结果回传给模型。
ToolMessage 可以由两种方式产生:
- 工具自动生成(绝大多数情况)
- 用户手动创建(调试或自定义流程时)
完整工具调用示例:
from langchain.messages import SystemMessage, HumanMessage, AIMessage, ToolMessage
# 1. AI 发起工具调用(content 为空,专注在 tool_calls 上)
ai_message = AIMessage(
content=[],
tool_calls=[{
"name": "get_weather",
"args": {"location": "北京"},
"id": "call_123"
}]
)
# 2. 工具执行后,把结果回传给模型
tool_message = ToolMessage(
content="晴天,21°C",
tool_call_id="call_123"
)
关键字段说明:
content:AIMessage中为空表示这一轮不输出文字;ToolMessage中存放工具结果。tool_calls:列出要调用的工具列表。id/tool_call_id:每个调用都有唯一 ID,二者必须对应,是连接调用与结果的"桥梁"。
三、一次完整的对话流程
理解了 4 种消息之后,我们把它们串起来看一次完整的对话是如何发生的。
3.1 普通对话(无工具)
SystemMessage → 规定模型应该如何回答
↓
HumanMessage → 用户提出问题
↓
AIMessage → 模型给出回答
最简洁的三段式:系统设定 → 用户提问 → AI 回答。
3.2 包含工具调用的对话
① HumanMessage
"北京今天天气怎么样?"
↓
② AIMessage(content=[],发出工具调用)
tool_calls = [{ name: "get_weather", args: {北京}, id: "call_123" }]
↓
③ ToolMessage(工具执行结果)
content = "晴天,21°C", tool_call_id = "call_123"
↓
④ AIMessage(基于工具结果生成最终回答)
"北京今天是晴天,气温 21°C。"
注意这里出现了两条 AIMessage:第一条只"想"不"说"(负责发工具调用),第二条拿到工具结果后才真正输出给用户。
四、完整代码示例
把上述 4 种消息放进一个完整的 messages 列表里,就是一次对话的全部"原材料":
from langchain.messages import SystemMessage, HumanMessage, AIMessage, ToolMessage
messages = [
# 系统指令
SystemMessage(
"""你是一个编程助手,专门帮助用户解答编程相关问题。
请用清晰、准确的语言回答,并提供实用的代码示例。"""
),
# 用户提问
HumanMessage(
"""我想学习 Python 中的列表推导式,
能否详细解释一下并给出几个实用的例子?"""
),
# 模型回答
AIMessage(
"""列表推导式是 Python 中一种简洁创建列表的方法。
基本语法是:[expression for item in iterable if condition]"""
),
]
把这串 messages 喂给任意 ChatModel(例如 ChatOpenAI / ChatDeepSeek 等)即可得到下一次回答。
五、Agent 中消息的动态过程
如果说前三章是"静态视角"看消息,那这一章就进入"动态视角"——消息是怎么在 Agent 里流转的。
5.1 核心概念
当我们定义的 Agent 接收到用户的任务消息后,会依据已经定义好的:
- 工具(Tools)
- 过程结构(Workflow)
- 内部逻辑(Internal Logic)
不断轮转与更新 Agent 的 State(状态)。
我们称这一过程为 State(状态)。
5.2 一个具体案例
用户问题:
DeepSeek 在 2024–2025 年之间,用户增长了百分之多少?
Agent 回答:
DeepSeek 在 2024–2025 年之间,用户增长了 132%……
这个问题看似一句话,背后其实是"搜索 + 计算"的组合拳。下面我们把它拆成 6 个步骤。
5.3 消息流转的 6 个步骤
| 步骤 | 消息类型 | 动作 | 涉及组件 |
|---|---|---|---|
| ① | HumanMessage(原始问题) | 用户把问题发给 Agent | User → Agent |
| ② | AIMessage(搜索数据) | Agent 决定调用搜索工具 | Agent → 搜索工具 |
| ③ | ToolMessage(搜索结果) | 搜索工具返回结果 | 搜索工具 → Agent |
| ④ | AIMessage(数据计算) | Agent 决定调用计算器 | Agent → 计算器 |
| ⑤ | ToolMessage(计算结果) | 计算器返回结果 | 计算器 → Agent |
| ⑥ | AIMessage(最终回答) | Agent 把结果返回给用户 | Agent → User |
5.4 流程图
5.5 关键理解
- Agent 不只是一次性问答,而是会基于状态多轮循环。
- 每一步都产生一条消息(
HumanMessage/AIMessage/ToolMessage),并写入 State。 - State 持续累积,Agent 根据当前 State 决定下一步动作(思考、调用工具、回答用户)。
- 一次复杂任务 = 多次「思考 → 工具调用 → 工具结果」的循环。
📌 一句话总结:Agent = 模型 + 工具 + 不断更新的 State(消息历史)。
六、State 与消息的 additional_kwargs
这一章我们把镜头拉近一些,看消息对象本身还藏了哪些"进阶属性"。
6.1 State(状态)到底是什么?
State 是 LangGraph 中所搭建的 Agent 系统在处理数据时,维护和跟踪信息的载体——可以理解为系统的**"记忆"**。
- 在工作流、Agent 或图中,State 会随着进程的推进记录并更新其内部信息。
- State 中通常会保存
SystemMessage、HumanMessage、AIMessage等消息及其content。 - 它是 Agent 整个执行过程中的**「数据中心」**。
6.2 AIMessage 的 additional_kwargs
AIMessage 除了基础的 content 外,还提供一些附加属性 / 方法:
属性:
| 属性 | 类型 | 含义 |
|---|---|---|
tool_calls | list | 与该消息关联的工具调用列表 |
invalid_tool_calls | list | 与该消息关联的解析错误的工具调用 |
usage_metadata | typedict | 该消息的使用元数据(如 token 使用情况) |
content_blocks | list | 消息中标准化、结构化的 ContentBlock 字典 |
方法:
| 方法 | 返回值 | 用途 |
|---|---|---|
pretty_repr() | str | 返回该消息更易读的可视化呈现形式 |
tool_calls 的可视化示例:
========================= Ai Message =========================
Tool Calls:
calculate (call_i5S13RLjc3Hmeykk4Pq21TJ4)
Call ID: call_i5S13RLjc3Hmeykk4Pq21TJ4
Args:
expression: 125 * 48
internet_search (call_xoPATyIZWiT9IDyjrws3sIQo)
Call ID: call_xoPATyIZWiT9IDyjrws3sIQo
Args:
query: AI 最新发展
6.3 ToolMessage 的 additional_kwargs
ToolMessage 同样有自己专属的附加属性和方法:
属性:
| 属性 | 类型 | 含义 |
|---|---|---|
results | list | 工具的执行结果,列表内容由所定义工具决定 |
tool_call_id | str | 该消息所响应的工具调用唯一标识 |
status | Literal['success', 'error'] | 工具调用的结果状态(成功 / 失败) |
artifact | Any | 工具执行过程中产生的非传输内容,与工具定义时的 content_and_artifact 参数关联 |
方法:
| 方法 | 返回值 | 用途 |
|---|---|---|
coerce_args() | dict | 强制将模型参数转换为正确类型 |
6.4 AIMessage vs ToolMessage 对比
| 维度 | AIMessage | ToolMessage |
|---|---|---|
| 产生方 | 模型输出 | 工具执行后 |
| 核心作用 | 表达模型思考、发出工具调用 | 回传工具结果给模型 |
| 关键字段 | tool_calls、usage_metadata | tool_call_id、status、artifact |
| 专有方法 | pretty_repr() | coerce_args() |
| 错误处理 | invalid_tool_calls | status='error' |
6.5 类的继承关系
四种消息都继承自 LangChain 的 BaseMessage 基类:
其中:
SystemMessage/HumanMessage:保留基类的通用属性。AIMessage/ToolMessage:包含更多独特属性与特殊方法(如tool_calls、tool_call_id、pretty_repr()、coerce_args()等)。
七、核心要点速查表
| 章节 | 一句话总结 |
|---|---|
| 消息概念 | 4 种消息 = 模型的输入输出 + 对话上下文单元 |
| 对话流程 | System → Human → AI;涉及工具时 AI ↔ Tool 多次循环 |
| 动态过程 | 消息在 State 中累积 → 推动 Agent 决策 → 完成任务 |
| 属性方法 | AIMessage / ToolMessage 继承 BaseMessage,扩展工具调用相关属性与方法 |
关键记忆点
- 消息列表 = 对话上下文,所有历史消息共同影响下一次模型的回复。
SystemMessage通常放在列表最前面,作为全局规则。ToolMessage不是用户输入,而是工具执行后的结果回传。tool_call_id是连接AIMessage调用与ToolMessage结果的桥梁。- State = Agent 的记忆,记录所有消息和上下文。
AIMessage.tool_calls和ToolMessage.tool_call_id是配对关系,ID 必须一致。pretty_repr()方便调试查看消息内容。coerce_args()自动修正模型生成的参数类型。artifact可以携带不必传输给模型、但程序需要用到的中间结果(如下载的文件、二进制数据等)。- 工具调用让大模型不只靠自身知识回答,可借助外部能力获得更准确的结果。
总结
Message 是 LangChain 的"细胞",所有上层抽象——Agent、Chain、Tool Calling——最终都要落到 4 种消息对象上。
回顾一下本文的学习路径:
- 入门:理解
SystemMessage/HumanMessage/AIMessage/ToolMessage各自的角色与用法。 - 串联:掌握"普通对话"与"工具调用对话"两条基本流程。
- 动态视角:理解消息如何在 Agent 的 State 中累积、驱动 Agent 决策。
- 进阶属性:深入
AIMessage/ToolMessage的additional_kwargs,用好tool_calls、tool_call_id、artifact、pretty_repr()等"瑞士军刀"。
🎯 学习建议:先掌握 4 种消息的用途(第二、四章)→ 再理解 Agent 中的流转(第五章)→ 最后深入 AIMessage / ToolMessage 的特殊属性(第六章),由浅入深。
掌握了这套消息体系,你就已经具备了读懂 LangChain / LangGraph 源码的"语法基础"。下一篇我会写 State 在 LangGraph 中的具体实现(含 TypedDict 定义、Reducer 合并策略等),敬请期待。