揭秘 DeepAgents 源码:打造具备企业级能力的 AI 智能体核心架构

前言

在大模型应用开发中,从零构建一个具备文件操作、子 Agent 协作、上下文管理、容错修复等全维度能力的智能体(Agent),往往需要大量的底层封装和踩坑。而 DeepAgents 框架正是为解决这一痛点而生 —— 它基于 LangChain/LangGraph 生态,通过高度封装的中间件体系,让开发者一行代码就能创建出具备生产级能力的 “深度 Agent”,无需重复造轮子。

本文将深度拆解 DeepAgents 框架的核心源码,从create_deep_agent核心构建函数,到子 Agent 协作、文件系统操作、工具调用容错三大核心中间件,带你彻底搞懂企业级 AI 智能体的底层实现逻辑,掌握从 “基础 Agent” 到 “深度 Agent” 的增强秘诀。

代码链接:https://github.com/langchain-ai/deepagents

在这里插入图片描述

1.deepagents-master/libs/deepagents/deepagents/graph.py

一、核心需求理解

deepagents 框架下的核心构建函数 create_deep_agent,用于快速创建一个功能完备的“深度Agent”——集成了任务规划、文件系统操作、子Agent调用、状态缓存、人工介入等核心能力,默认基于 Claude Sonnet 4 模型,是对 LangChain 基础 Agent 的增强封装。

二、代码详细解析

1. 整体功能概述

这段代码的核心是 create_deep_agent 函数,作用是:

  • 封装 LangChain 的 create_agent 函数,快速构建一个“深度Agent”;
  • 内置一系列核心中间件,让Agent具备任务清单管理、文件系统操作、子Agent调用、对话总结、Prompt缓存、悬空工具调用修复、人工介入 等能力;
  • 提供灵活的配置项(模型、工具、后端、缓存、中断规则等),适配不同场景;
  • 默认使用 Anthropic Claude Sonnet 4 模型,优化了上下文总结策略,支持高token容量。
2. 核心依赖与常量说明
组件/常量 作用
BASE_AGENT_PROMPT 基础系统提示,告知Agent可使用标准工具完成用户目标,会拼接至自定义系统提示后
get_default_model() 返回默认模型(Anthropic Claude Sonnet 4-5 20250929,最大tokens=20000)
第三方中间件 来自 LangChain/Anthropic:
- HumanInTheLoopMiddleware:人工介入中间件
- TodoListMiddleware:任务清单管理
- SummarizationMiddleware:对话总结(避免上下文超限)
- AnthropicPromptCachingMiddleware:Anthropic Prompt缓存(节省成本)
自定义中间件 来自 deepagents:
- FilesystemMiddleware:文件系统操作(ls/read/write/edit等)
- PatchToolCallsMiddleware:修复悬空工具调用
- SubAgentMiddleware:子Agent调用能力
3. 核心函数解析
(1)get_default_model():获取默认模型
def get_default_model() -> ChatAnthropic:
    return ChatAnthropic(
        model_name="claude-sonnet-4-5-20250929",
        max_tokens=20000,
    )
  • 作用:返回预配置的 Anthropic Claude Sonnet 4 模型实例;
  • 关键配置:指定最新版模型、最大输出tokens=20000(适配长文本生成)。
(2)create_deep_agent():构建深度Agent(核心)
① 入参处理(关键参数)
参数 作用 默认值
model Agent 使用的模型 默认调用 get_default_model() 返回 Claude Sonnet 4
tools Agent 可调用的工具列表 None(仅使用中间件内置工具)
system_prompt 自定义系统提示 None(仅使用 BASE_AGENT_PROMPT
middleware 额外追加的中间件 空元组
subagents 自定义子Agent列表 None(空列表)
interrupt_on 触发人工介入的工具规则 None(无人工介入)
checkpointer/store/cache 状态持久化/存储/缓存 None(无持久化)
backend 文件系统/执行沙箱后端 None(基础文件操作)
debug 调试模式 False
② 核心逻辑步骤
  1. 模型初始化

    • 若未传模型,使用默认 Claude Sonnet 4;
    • 若传字符串(如 "anthropic:claude-3-5-sonnet-20240620"),通过 init_chat_model 初始化;
  2. 上下文总结策略配置

    if (model.profile is not None and ... "max_input_tokens" ...):
        trigger = ("fraction", 0.85)  # 输入tokens达85%时触发总结
        keep = ("fraction", 0.10)     # 总结后保留10%的上下文
    else:
        trigger = ("tokens", 170000)  # 固定tokens阈值触发总结
        keep = ("messages", 6)        # 总结后保留6条消息
    
    • 自适应配置对话总结的触发条件和保留策略,避免上下文超限;
    • 优先基于模型的 max_input_tokens 按比例触发,否则使用固定阈值。
  3. 内置中间件组装(核心能力)
    deepagent_middleware 列表按顺序集成了以下核心中间件,赋予Agent关键能力:

    中间件 核心能力 应用范围
    TodoListMiddleware() 管理任务清单(write_todos工具) 主体Agent
    FilesystemMiddleware(backend=backend) 文件系统操作(ls/read_file/write_file/edit_file/glob/grep/execute) 主体Agent
    SubAgentMiddleware(...) 子Agent调用能力 主体Agent(子Agent也继承该中间件)
    SummarizationMiddleware(...) 对话总结(避免上下文超限) 主体Agent + 子Agent
    AnthropicPromptCachingMiddleware(...) Anthropic Prompt缓存(重复Prompt不重复计费) 主体Agent + 子Agent
    PatchToolCallsMiddleware() 修复悬空工具调用 主体Agent + 子Agent
    HumanInTheLoopMiddleware(...) 按规则触发人工介入 主体Agent(若配置 interrupt_on

    其中 SubAgentMiddleware 的关键配置:

    • 子Agent默认继承主体模型、工具、后端;
    • 子Agent也内置任务清单、文件系统、总结、缓存、工具调用修复能力;
    • 启用通用子Agent(general_purpose_agent=True)。
  4. 中间件扩展

    • 若传入自定义 middleware,追加到内置中间件后;
    • 若配置 interrupt_on,添加人工介入中间件。
  5. Agent创建与配置

    return create_agent(
        model,
        system_prompt=拼接BASE_AGENT_PROMPT,
        tools=tools,
        middleware=deepagent_middleware,
        ...  # 其他配置
    ).with_config({"recursion_limit": 1000})
    
    • 调用 LangChain 的 create_agent 创建基础Agent;
    • 拼接系统提示(自定义提示 + 基础提示);
    • 设置递归限制为1000(允许Agent嵌套调用工具/子Agent的最大次数);
    • 返回编译后的 CompiledStateGraph(可直接调用的Agent实例)。
4. 核心能力清单

通过该函数创建的深度Agent默认具备:

  1. 任务管理:通过 write_todos 工具管理任务清单;
  2. 文件操作:支持 ls/read/write/edit/glob/grep 等文件操作,execute 工具可运行shell命令(需沙箱后端);
  3. 子Agent调用:通过 task 工具调用自定义/通用子Agent处理复杂任务;
  4. 上下文管理:自动总结超长对话,避免模型上下文超限;
  5. 成本优化:Anthropic Prompt缓存,重复Prompt不重复计费;
  6. 容错性:修复悬空工具调用,保证状态一致性;
  7. 人工介入:可配置工具调用触发人工审核;
  8. 高扩展性:支持自定义模型、工具、中间件、后端、缓存等。
5. 使用示例
from deepagents.agents import create_deep_agent
from deepagents.backends.state import StateBackend

# 创建基础深度Agent
agent = create_deep_agent(
    model="anthropic:claude-3-5-sonnet-20240620",  # 自定义模型
    backend=StateBackend,  # 文件系统后端
    interrupt_on={"execute": True},  # 执行shell命令时触发人工介入
    debug=True,  # 开启调试
)

# 调用Agent处理任务
result = agent.invoke({
    "messages": [{"role": "user", "content": "在当前目录创建一个test.py文件,写入一个质数判断函数,并用execute工具运行测试"}]
})
关键点回顾
  1. 核心目标:封装 LangChain Agent,快速构建具备“任务管理+文件操作+子Agent+上下文总结+缓存+容错”的深度Agent,默认适配 Anthropic Claude 模型;
  2. 核心特性
    • 内置多类核心中间件,无需手动集成;
    • 自适应上下文总结策略,适配不同模型的token限制;
    • 子Agent继承主体能力,支持独立处理复杂任务;
    • 支持人工介入、状态持久化、缓存等企业级特性;
  3. 核心价值:降低复杂Agent的构建成本,开箱即用具备生产级能力(文件操作、子Agent、成本优化、容错)。
适用场景
  • 需处理文件操作的自动化任务(如代码生成/分析、文档处理);
  • 复杂多步骤任务(需子Agent拆分处理);
  • 长对话场景(需自动总结上下文);
  • 需成本优化的 Anthropic 模型使用场景;
  • 需人工介入审核敏感操作(如shell执行)的场景。

2.deepagents-master/libs/deepagents/deepagents/middleware/subagents.py

一、核心需求理解

你希望我详细解释这段 Python 代码的整体功能、核心逻辑和关键模块,这段代码是 LangChain 框架下用于为主体 Agent 提供子 Agent(SubAgent)能力的中间件(Middleware),核心是通过一个 task 工具实现子 Agent 的创建、调用和结果返回。

二、代码详细解析

1. 整体功能概述

这段代码实现了一个 SubAgentMiddleware(子Agent中间件),核心作用是:

  • 为主体 Agent 新增一个 task 工具,用于创建和调用临时的子 Agent;
  • 子 Agent 可独立处理复杂、多步骤、高上下文消耗的任务(如专项研究、代码分析、内容审核);
  • 子 Agent 运行完成后仅返回精简结果给主体 Agent,避免主体上下文膨胀;
  • 支持自定义子 Agent(指定专属工具、系统提示、模型),也提供默认的通用子 Agent。
2. 关键数据结构定义
类/类型 作用 核心字段
SubAgent(TypedDict) 子 Agent 的配置规格(未编译) name(名称)、description(描述)、system_prompt(系统提示)、tools(专属工具)、model(专属模型)、middleware(专属中间件)、interrupt_on(人工介入配置)
CompiledSubAgent(TypedDict) 已编译的子 Agent 规格 namedescriptionrunnable(可运行的 LangChain Runnable 实例)
3. 核心常量说明
  • DEFAULT_SUBAGENT_PROMPT:默认子 Agent 的系统提示,告知子 Agent 可使用工具完成用户目标;
  • _EXCLUDED_STATE_KEYS:子 Agent 与主体 Agent 交互时排除的状态键(如 messages 需单独处理,todos 无统一规约);
  • TASK_TOOL_DESCRIPTIONtask 工具的默认描述(含使用场景、示例、注意事项),支持 {available_agents} 占位符替换为子 Agent 列表;
  • TASK_SYSTEM_PROMPT:主体 Agent 的补充系统提示,告知如何使用 task 工具调用子 Agent;
  • DEFAULT_GENERAL_PURPOSE_DESCRIPTION:默认通用子 Agent 的描述(具备主体 Agent 所有工具,用于通用复杂任务)。
4. 核心函数解析
(1)_get_subagents:创建子 Agent 实例
  • 入参:默认模型、默认工具、默认中间件、子 Agent 配置列表、是否启用通用子 Agent 等;
  • 核心逻辑
    1. 若启用通用子 Agent,先创建一个默认的通用子 Agent(继承主体的模型/工具/中间件);
    2. 遍历自定义子 Agent 配置:
      • 若为已编译的 CompiledSubAgent,直接提取 runnable
      • 若为未编译的 SubAgent,使用 create_agent 编译为 Runnable 实例(合并默认+自定义中间件、工具、模型);
    3. 收集子 Agent 的名称→Runnable 映射,以及子 Agent 的描述列表;
  • 返回值(子Agent字典, 子Agent描述列表)
(2)_create_task_tool:创建 task 工具
  • 核心作用:封装子 Agent 调用逻辑,生成 LangChain 的 StructuredTool 实例;
  • 关键内部函数
    函数 作用
    _return_command_with_state_update 处理子 Agent 运行结果:过滤排除的状态键,提取最后一条消息作为 ToolMessage 返回给主体 Agent
    _validate_and_prepare_state 校验子 Agent 类型是否存在,准备子 Agent 的运行状态(过滤排除的状态键,构造仅含任务描述的 HumanMessage)
    task(同步)/atask(异步) task 工具的核心执行逻辑:
    1. 校验子 Agent 类型合法性;
    2. 准备子 Agent 运行状态;
    3. 调用子 Agent 并获取结果;
    4. 封装结果为 Command 返回给主体 Agent
  • 返回值StructuredTool 实例(名称为 task,包含同步/异步执行函数)。
(3)SubAgentMiddleware 类(核心中间件)

继承自 LangChain 的 AgentMiddleware,是对外暴露的核心类,关键方法/逻辑如下:

__init__ 初始化方法
  • 入参处理:默认模型(必传)、默认工具(默认空列表)、默认中间件(默认 None)、自定义子 Agent 列表(默认空列表)、是否启用通用子 Agent(默认 True)等;
  • 核心操作:调用 _create_task_tool 创建 task 工具,挂载到中间件的 tools 属性(中间件会自动将该工具添加到主体 Agent);
  • 可选操作:设置 system_prompt(默认使用 TASK_SYSTEM_PROMPT,告知主体 Agent 如何使用 task 工具)。
wrap_model_call/awrap_model_call 方法
  • 作用:拦截主体 Agent 的模型调用请求,修改其系统提示;
  • 逻辑:若设置了 system_prompt,将其追加到主体 Agent 的原有系统提示后(或直接替换),确保主体 Agent 知晓 task 工具的存在和使用方式;
  • 区别:wrap_model_call 同步,awrap_model_call 异步(适配 LangChain 异步流程)。
5. 核心工作流程(以通用子 Agent 为例)

主体Agent接收到复杂任务

调用task工具,指定subagent_type=general-purpose,传入任务描述

task工具校验子Agent类型

准备子Agent运行状态(过滤排除的状态键,构造仅含任务描述的消息)

调用通用子Agent的Runnable实例

子Agent独立执行任务(调用工具、多步推理)

子Agent返回运行结果

过滤结果状态,提取最后一条消息作为ToolMessage

将结果返回给主体Agent

主体Agent基于子Agent的精简结果继续处理(如汇总、回复用户)

6. 使用示例(简化版)
from langchain.agents import create_agent
from langchain.agents.middleware.subagents import SubAgentMiddleware

# 1. 创建主体Agent,挂载SubAgentMiddleware
agent = create_agent(
    model="openai:gpt-4o",  # 主体Agent的模型
    tools=[],  # 主体Agent的基础工具
    middleware=[
        SubAgentMiddleware(
            default_model="openai:gpt-4o",  # 子Agent默认模型
            default_tools=[],  # 通用子Agent的工具(与主体一致)
            general_purpose_agent=True,  # 启用通用子Agent
            # 可选:自定义子Agent
            subagents=[
                {
                    "name": "content-reviewer",
                    "description": "用于审核生成的内容",
                    "system_prompt": "你是内容审核专家,需检查内容的准确性和合规性",
                    "tools": [],  # 审核专属工具
                }
            ]
        )
    ]
)

# 2. 调用主体Agent,触发task工具调用子Agent
result = agent.invoke({
    "messages": [{"role": "user", "content": "研究LeBron James的成就并生成报告"}]
})
7. 关键特性总结
  • 隔离性:子 Agent 有独立的上下文,避免主体 Agent 的上下文膨胀;
  • 并行性:支持同时调用多个子 Agent 处理独立任务(如同时研究3位球星);
  • 灵活性:可自定义子 Agent 的模型、工具、系统提示,适配不同场景;
  • 简洁性:子 Agent 仅返回最终结果,无需暴露中间步骤,减少主体负担;
  • 易用性:通过中间件无缝集成到 LangChain Agent 流程,无需修改主体逻辑。

核心要点回顾

  1. 核心目标:为主体 Agent 提供子 Agent 能力,通过 task 工具调用临时子 Agent 处理复杂、高上下文消耗的独立任务;
  2. 核心流程:中间件初始化时创建 task 工具→主体 Agent 调用 task 工具指定子 Agent 类型和任务→子 Agent 独立运行→返回精简结果给主体;
  3. 关键特性:子 Agent 上下文隔离、支持自定义子 Agent、结果精简返回、适配同步/异步调用。

3.deepagents-master/libs/deepagents/deepagents/middleware/filesystem.py

这段代码实现了一个为AI智能体(Agent)提供文件系统操作能力的中间件(Middleware),核心是封装了一系列文件操作工具(如列出文件、读写文件、编辑文件、文件搜索、执行命令等),并集成了后端存储、状态管理、大结果处理等能力,让智能体能够安全、规范地与文件系统交互。


核心模块与功能拆解

1. 基础类型与工具函数
  • FileData 类型:定义文件内容和元数据(创建时间、修改时间)的数据结构,用于统一管理文件信息。
  • _file_data_reducer:文件状态合并函数,支持文件删除(将值设为 None 时从状态中移除),适配 LangGraph 的状态管理机制。
  • _validate_path:路径安全校验函数,核心作用是:
    • 阻止目录遍历攻击(过滤 ..~ 等危险字符);
    • 拒绝 Windows 绝对路径(保证虚拟文件系统路径格式统一);
    • 规范化路径(统一为 / 开头、使用正斜杠);
    • 支持路径前缀白名单校验。
2. 工具定义与生成器

代码为智能体提供了7类核心工具,每个工具都有同步/异步实现,并通过生成器函数封装:

工具名 功能描述
ls 列出指定目录下的所有文件,返回路径列表(支持结果截断)
read_file 读取文件内容,支持分页(offset/limit)、超长行截断,返回带行号的内容
write_file 写入新文件(覆盖/创建),返回操作结果并更新状态
edit_file 精准替换文件内容(支持单例/全量替换),需先读取文件才能编辑
glob 按通配符模式查找文件(如 **/*.py 匹配所有Python文件)
grep 在文件中搜索文本,支持不同输出模式(仅文件路径/匹配内容/匹配数量)
execute 在沙箱环境执行Shell命令(仅支持实现 SandboxBackendProtocol 的后端)

每个工具生成器(如 _ls_tool_generator)的核心逻辑:

  • 接收后端实例/工厂函数,解析并校验路径;
  • 调用后端对应的文件操作方法;
  • 格式化结果(截断、添加状态信息、处理错误);
  • 返回结构化的工具对象(StructuredTool)。
3. 中间件核心类 FilesystemMiddleware

这是代码的核心入口,实现了 AgentMiddleware 接口,主要能力包括:

(1)初始化逻辑
  • 默认为 StateBackend(内存临时存储),也支持自定义后端(如持久化存储、沙箱后端);
  • 加载所有文件工具,支持自定义工具描述;
  • 配置大结果阈值(tool_token_limit_before_evict),用于处理超大工具返回结果。
(2)模型调用包装(wrap_model_call/awrap_model_call
  • 动态生成系统提示词:包含文件工具使用说明,若后端支持执行则添加 execute 工具说明;
  • 过滤工具:若后端不支持执行,自动移除 execute 工具,避免智能体调用失败。
(3)工具调用包装(wrap_tool_call/awrap_tool_call
  • 处理超大工具结果:当工具返回内容超过阈值时,将内容写入 /large_tool_results/ 目录,并返回提示信息(告知智能体通过 read_file 分页读取);
  • 兼容同步/异步工具调用,统一处理 ToolMessageCommand 类型的返回结果。
(4)后端适配
  • _get_backend:解析后端实例(支持工厂函数动态生成);
  • _supports_execution:检查后端是否支持命令执行,保证 execute 工具的安全性。
4. 辅助功能
  • truncate_if_too_long:截断超长结果,避免超出大模型上下文;
  • format_grep_matches/format_content_with_line_numbers:格式化工具返回结果,提升可读性;
  • sanitize_tool_call_id:清洗工具调用ID,避免路径注入。

  1. 核心价值:为AI智能体提供安全、标准化的文件系统操作能力,支持临时/持久化存储、沙箱命令执行,适配LangChain/LangGraph生态;
  2. 安全设计:路径校验防遍历、编辑前必须读取文件、超大结果自动存储,避免安全风险和上下文溢出;
  3. 灵活性:支持自定义后端、自定义工具描述、动态系统提示词,适配不同使用场景(如纯文件操作、带命令执行的沙箱环境)。

该代码的典型使用场景是构建具备“代码编写/调试/执行”能力的AI智能体,例如让智能体读取代码文件、修改内容、执行测试命令等。

4.deepagents-master/libs/deepagents/deepagents/middleware/patch_tool_calls.py

一、核心需求理解

你希望我详细解释这段代码的功能,这段代码是 LangChain 框架下的 PatchToolCallsMiddleware 中间件,核心作用是修复消息历史中“悬空的工具调用(dangling tool calls)”,避免 Agent 因未完成的工具调用导致逻辑异常。

二、代码详细解析

1. 整体功能概述

这段代码实现了一个 PatchToolCallsMiddleware(工具调用补丁中间件),核心解决的问题是:

  • Agent 在执行过程中可能会生成包含工具调用的 AI 消息(AIMessage),但这些工具调用可能因外部中断(如用户新消息)、执行失败等原因未被处理(即没有对应的 ToolMessage 回应);
  • 这类“悬空”的工具调用会导致 Agent 状态不一致、后续逻辑出错(如一直等待工具返回);
  • 该中间件在 Agent 运行前扫描消息历史,为所有悬空的工具调用自动补充一个“取消状态”的 ToolMessage,确保消息历史的完整性和 Agent 逻辑的连贯性。
2. 核心概念说明
术语 含义
工具调用(Tool Call) Agent 生成的、指令调用某个工具的请求(如调用 search 工具查信息),存储在 AIMessagetool_calls 字段中
悬空工具调用(Dangling Tool Call) 有工具调用请求,但没有对应的 ToolMessage(工具返回消息)的情况
ToolMessage 工具执行完成/失败后返回的消息,需关联对应的工具调用 ID(tool_call_id
Overwrite LangGraph 中的类型,用于标识“覆盖状态中的某个字段”(这里是覆盖 messages 字段)
3. 核心逻辑拆解
(1)类定义与继承
class PatchToolCallsMiddleware(AgentMiddleware):
    """Middleware to patch dangling tool calls in the messages history."""
  • 继承自 LangChain 的 AgentMiddleware,是 Agent 生命周期的中间件,可拦截 Agent 运行前/后的状态;
  • 注释明确其核心作用:修补消息历史中悬空的工具调用。
(2)before_agent 方法(核心)
def before_agent(self, state: AgentState, runtime: Runtime[Any]) -> dict[str, Any] | None:
    """Before the agent runs, handle dangling tool calls from any AIMessage."""
    messages = state["messages"]
    if not messages or len(messages) == 0:
        return None

    patched_messages = []
    # 遍历消息并处理悬空工具调用
    for i, msg in enumerate(messages):
        patched_messages.append(msg)
        # 仅处理包含工具调用的AI消息
        if msg.type == "ai" and msg.tool_calls:
            for tool_call in msg.tool_calls:
                # 检查当前AI消息之后是否有对应的ToolMessage
                corresponding_tool_msg = next(
                    (msg for msg in messages[i:] if msg.type == "tool" and msg.tool_call_id == tool_call["id"]),
                    None,
                )
                # 若没有对应的ToolMessage,补充一个“取消状态”的ToolMessage
                if corresponding_tool_msg is None:
                    tool_msg = (
                        f"Tool call {tool_call['name']} with id {tool_call['id']} was "
                        "cancelled - another message came in before it could be completed."
                    )
                    patched_messages.append(
                        ToolMessage(
                            content=tool_msg,
                            name=tool_call["name"],
                            tool_call_id=tool_call["id"],
                        )
                    )

    return {"messages": Overwrite(patched_messages)}
  • 触发时机:Agent 运行 之前before_agent 是 AgentMiddleware 的生命周期方法);
  • 输入参数
    • state:Agent 的当前状态(核心包含 messages 字段,即消息历史);
    • runtime:LangGraph 的运行时实例(此处未使用,仅为参数要求);
  • 核心步骤
    1. 提取状态中的消息历史,若为空则直接返回;
    2. 遍历每条消息,先将原始消息加入 patched_messages
    3. 若当前消息是 AI 类型且包含工具调用:
      • 对每个工具调用,检查该消息之后的所有消息中是否有对应的 ToolMessage(通过 tool_call_id 匹配);
      • 若未找到对应的 ToolMessage,则创建一个提示“工具调用被取消”的 ToolMessage,追加到 patched_messages
    4. 返回覆盖后的消息列表(使用 Overwrite 标识需替换原状态的 messages 字段)。
4. 工作流程示例

假设消息历史原本是这样(存在悬空工具调用):

[
    HumanMessage(content="查一下今天的天气"),  # 用户消息
    AIMessage(                                # AI消息,包含工具调用
        content="",
        tool_calls=[{"id": "call_123", "name": "search", "args": {"query": "2026-01-14 北京天气"}}]
    ),
    HumanMessage(content="算了,不查了")       # 用户新消息,导致之前的工具调用悬空
]

经过中间件处理后,消息历史变为:

[
    HumanMessage(content="查一下今天的天气"),
    AIMessage(tool_calls=[{"id": "call_123", "name": "search"...}]),
    ToolMessage(                              # 新增的补丁消息
        content="Tool call search with id call_123 was cancelled - another message came in before it could be completed.",
        name="search",
        tool_call_id="call_123"
    ),
    HumanMessage(content="算了,不查了")
]
5. 核心价值
  • 状态一致性:确保每个工具调用都有对应的 ToolMessage,避免 Agent 因“等待工具返回”陷入死循环;
  • 容错性:处理用户中断、工具执行超时等异常场景,让 Agent 能正确感知工具调用的最终状态;
  • 无侵入性:作为中间件运行在 Agent 执行前,无需修改 Agent 核心逻辑,仅修补消息历史。

关键点回顾

  1. 核心目标:修复 Agent 消息历史中“悬空的工具调用”,为未被处理的工具调用补充取消状态的 ToolMessage
  2. 触发时机:Agent 运行前(before_agent 方法);
  3. 核心逻辑:扫描消息历史→识别包含工具调用的 AI 消息→检查是否有对应 ToolMessage→无则补充取消消息→覆盖原消息列表。

适用场景

  • Agent 可能被用户中断(如发送新消息)导致工具调用未完成;
  • 工具执行超时/失败,未生成对应的 ToolMessage;
  • 需保证 Agent 状态一致性,避免因悬空工具调用导致逻辑异常。
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐