LangChain 怎样为工具调用保留中间消息
LangChain 的工具调用不是“模型输出一段文字、工具再返回一段文字”这么简单。要让下一次模型调用知道刚才调用了哪个工具,应用需要保留消息序列:用户消息、带有 tool_calls 的 AIMessage、带有对应 tool_call_id 的 ToolMessage,以及后续模型消息。
官方地址:https://docs.langchain.com/oss/python/langchain/messages
最实用的做法是把 agent 返回的 result["messages"] 当作中间状态保存,而不是只取最后一条 content。这样既能继续对话,也能在日志或持久化层中追踪工具调用的对应关系。
为什么中间消息不能只保存最终文本
LangChain 的消息对象同时承载角色、内容和元数据。模型决定调用工具时,工具调用信息位于 AIMessage.tool_calls;工具执行后的结果则用 ToolMessage 回传。只保存最终回答,会丢掉工具名、参数和调用标识,下一次模型就无法可靠地把结果对应回原调用。

这条消息链应被视为一个整体:AIMessage 说明模型提出了什么调用,ToolMessage 说明该调用得到什么结果。二者之间最关键的连接不是文本相似,而是调用 ID。
旧写法的问题:只取最后一条消息
下面这种写法适合只展示最终答案,却不适合保留中间状态:
# 只取最终文本,工具调用名称和参数会被丢掉 final_text = result["messages"][-1].content print(final_text)
它的问题不在于最后一条消息一定错误,而在于它把“展示结果”和“保存状态”混在一起。展示时可以读取最后一条;保存时应保留整个列表,并按消息类型提取需要的字段。
新规则:从 agent 返回值保留完整 messages
使用 create_agent 时,返回值包含消息状态。下面的示例只做消息收集,不把示例输出描述成已经在本机运行的结果:
from langchain.agents import create_agent
from langchain.tools import tool
from langchain.messages import AIMessage, ToolMessage
@tool
def lookup_weather(city: str) -> str:
"""返回一个供示例使用的天气结果。"""
# 工具返回值会进入 ToolMessage.content,保持结果可序列化
return f"{city}:晴,26℃"
agent = create_agent(
model="openai:gpt-5-nano",
tools=[lookup_weather],
system_prompt="你是一个会使用工具的助手",
)
result = agent.invoke({
"messages": [{"role": "user", "content": "查询上海天气"}]
})
# 保存完整消息列表,而不是只保存最后的回答文本
messages = result["messages"]
for message in messages:
if isinstance(message, AIMessage):
print("AI 调用:", message.tool_calls)
elif isinstance(message, ToolMessage):
print("工具结果:", message.content)
这里的核心只有两点:messages 是可继续交给模型的上下文,AIMessage 与 ToolMessage 则让应用可以分别记录模型调用和工具结果。若只需要展示最终答案,再从列表末尾读取即可。
手动续接工具结果时,调用标识必须对应
如果应用没有直接使用 agent 循环,而是自己执行工具并把结果交回模型,必须把 ToolMessage.tool_call_id 设置为 AIMessage.tool_calls 中对应调用的 id:
from langchain.messages import AIMessage, HumanMessage, ToolMessage
ai_message = AIMessage(
content=[],
tool_calls=[{
"name": "lookup_weather",
"args": {"city": "上海"},
"id": "call_weather_001",
}],
)
# 真实工具执行后,把同一个 id 写回结果消息
tool_message = ToolMessage(
content="上海:晴,26℃",
tool_call_id="call_weather_001",
)
messages = [
HumanMessage("查询上海天气"),
ai_message,
tool_message,
]
# 下一次模型调用接收的是完整的消息关系
response = model.invoke(messages)

如果一次 AIMessage 含有多个工具调用,就要为每个结果建立独立的 ToolMessage,逐一匹配各自的 ID。不能用“最后一次调用”或工具名称猜测对应关系。
兼容边界:content、artifact 与持久化
ToolMessage.content 是发送给模型的工具结果;若应用还需要保存检索文档编号、原始响应或渲染信息,可以把这类不必直接进入模型上下文的附加数据放入 artifact,并在业务层按需序列化。
因此可以按三层保存:第一层是完整 messages,用于继续调用;第二层是每条消息的类型、调用 ID 和内容,便于日志检索;第三层是 artifact 等应用侧数据,服务展示或审计。跨请求、跨线程的长期保留还需要接入自己的存储或 LangGraph 的持久化能力,不能把一次 invoke 返回值自动当成永久数据库。
最终采用建议很简单:展示回答时取末条消息,恢复上下文时保存完整消息列表,手动回填工具结果时严格复用调用 ID。这样既保留中间消息,也不会把工具结果错接到另一条调用上。
常见问题
只保存 AIMessage 可以吗?不建议。模型发出的调用和工具返回的结果是一对关系,缺少 ToolMessage 后,后续上下文不完整。
artifact 会自动发送给模型吗?不应这样假设。把需要模型理解的结果放在 content,应用侧附加数据再单独放进 artifact。
为什么工具结果必须带 tool_call_id?它用来对应 AIMessage 中具体的调用 ID;多个工具并行调用时尤其不能省略。
Hugging Face Tokenizers 怎样保存自定义词表
- 上一篇
- Hugging Face Tokenizers 怎样保存自定义词表
- 下一篇
- LlamaIndex 怎样把元数据加入向量检索过滤
-
- 科技周边 · 人工智能 | 58分钟前 | API · 人工智能 · vLLM max_tokens 推理服务
- vLLM 怎样为在线服务设置请求最大 Token 数
- 326浏览 收藏
-
- 科技周边 · 人工智能 | 1小时前 | 人工智能 · 评估指标 MLFlow 模型版本 Model Registry 机器学习实验
- MLflow 怎样记录模型版本和评估指标
- 313浏览 收藏
-
- 科技周边 · 人工智能 | 1小时前 | 人工智能 · Profiling ONNX Runtime 算子耗时 推理性能 JSON trace
- ONNX Runtime 怎样生成算子级延迟 profiling JSON
- 178浏览 收藏
-
- 科技周边 · 人工智能 | 1小时前 |
- LlamaIndex 怎样把元数据加入向量检索过滤
- 334浏览 收藏
-
- 科技周边 · 人工智能 | 1小时前 | 自定义词表 tokenizer Hugging Face Tokenizers tokenizer.json
- Hugging Face Tokenizers 怎样保存自定义词表
- 311浏览 收藏
-
- 科技周边 · 人工智能 | 1小时前 | Transformers bitsandbytes BitsAndBytesConfig 4bit量化
- BitsAndBytesConfig 怎样查看 4bit 量化参数
- 205浏览 收藏
-
- 科技周边 · 人工智能 | 1小时前 | 缓存 · snapshot_download Hugging Face Hub hf_hub_download revision
- Hugging Face Hub 怎样下载指定提交版本的模型文件
- 415浏览 收藏
-
- 科技周边 · 人工智能 | 1小时前 |
- Hugging Face Hub 怎样为私有模型配置访问令牌
- 127浏览 收藏
-
- 科技周边 · 人工智能 | 1小时前 |
- OpenAI API 流式响应怎样按事件类型更新界面
- 228浏览 收藏
-
- 科技周边 · 人工智能 | 1小时前 |
- scikit-learn ColumnTransformer 怎样让数值与类别特征分别预处理
- 459浏览 收藏
-
- 科技周边 · 人工智能 | 1小时前 |
- scikit-learn DummyClassifier 怎样建立分类基线
- 189浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- PubMedQA
- 深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
- 764次使用
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 760次使用
-
- LMArena
- LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
- 842次使用
-
- HELM
- 深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
- 813次使用
-
- MMBench
- MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
- 641次使用
-
- 量化模型本地推理的显存估算方法
- 2026-10-17 501浏览
-
- 本地大模型反复输出同一句话怎么调整生成参数
- 2026-09-06 501浏览
-
- Python 调用大模型时如何用结构化输出校验 JSON:从解析失败到可重试
- 2026-08-29 501浏览
-
- AI写作工具免费版安装教程(含豆包Clawdbot)
- 2026-05-30 501浏览
-
- WPS AI能自动生成PPT吗?输入主题一键制作演示文稿
- 2026-05-27 501浏览

