LangChain DeepAgents 完全指南

文章目录

一句话概括

Deep Agents 是一个开箱即用的 AI Agent 框架

想象一下,你要做一个 AI 助手,通常需要自己组装很多零件:prompt、工具、上下文管理...但 Deep Agents 帮你把这些都准备好了,你只需要几行代码,就能得到一个功能强大的 AI Agent。

它受 Claude Code 启发,旨在打造一个"通用目的"的 AI 助手,能够帮你完成各种复杂任务。

普通的 LLM 只能对话。但"深度 Agent"可以做更多:

  • 规划 - 使用 write_todos 工具来分解任务、跟踪进度
  • 文件系统访问 - 读取、写入、编辑文件,搜索代码
  • Shell 执行 - 运行命令(带沙箱隔离)
  • 子 Agent - 使用 task 工具委托工作给专门的子 Agent
  • 智能默认 - 内置的 prompt 教模型如何有效使用这些工具
  • 上下文管理 - 自动摘要长对话,大输出保存到文件

项目架构一览

这个项目是一个 monorepo(单体仓库),包含多个独立版本管理的包:

复制代码
deepagents/
├── libs/
│   ├── deepagents/    # 核心 SDK(Python)
│   ├── cli/           # 命令行工具
│   ├── acp/           # Agent Context Protocol 支持
│   ├── evals/         # 评估套件
│   └── partners/      # 第三方集成
├── examples/          # 示例项目
└── .github/           # CI/CD 配置

核心组件详解

Deep Agents SDK (libs/deepagents/)

这是整个项目的心脏。它是一个 Python 包,提供了创建"深度 Agent"的所有能力。

快速开始
python 复制代码
from deepagents import create_deep_agent

agent = create_deep_agent()
result = agent.invoke({"messages": [{"role": "user", "content": "Research LangGraph and write a summary"}]})

就这几行代码!你得到了一个可以规划、读写文件、管理上下文的完整 Agent。

核心模块

SDK 的代码结构:

复制代码
deepagents/
├── graph.py              # 创建 Agent 的主入口 (create_deep_agent)
├── _models.py            # 模型解析 (resolve_model, get_default_model)
├── base_prompt.md        # 基础提示词模板
├── middleware/           # 中间件(核心逻辑)
│   ├── __init__.py       # 导出和中间件工厂函数
│   ├── _utils.py         # 工具函数
│   ├── filesystem.py     # 文件系统工具 (ls, read, write, edit, glob, grep)
│   ├── memory.py         # 记忆系统 (AGENTS.md)
│   ├── skills.py         # 技能系统 (SKILL.md)
│   ├── subagents.py      # 同步子 Agent 管理
│   ├── async_subagents.py # 异步子 Agent 管理
│   ├── summarization.py  # 上下文摘要(长对话压缩)
│   └── patch_tool_calls.py # 工具调用修补
└── backends/             # 后端实现
    ├── __init__.py       # 导出和后端工厂
    ├── protocol.py       # 协议定义 (BackendProtocol, SandboxBackendProtocol)
    ├── state.py          # 内存状态后端
    ├── filesystem.py     # 真实文件系统后端
    ├── sandbox.py        # 沙箱执行后端 (支持 execute 命令)
    ├── local_shell.py    # 本地 Shell 后端
    ├── composite.py      # 组合后端
    ├── langsmith.py      # LangSmith 后端
    ├── store.py          # 持久化存储后端
    └── utils.py          # 后端工具函数

核心文件说明

文件 作用
graph.py create_deep_agent() 入口函数
middleware/filesystem.py 提供文件操作和执行命令工具
middleware/subagents.py 提供 task 工具调用子代理
middleware/summarization.py 自动压缩长对话
backends/protocol.py 定义后端接口规范
backends/sandbox.py 远程沙箱执行环境

核心入口:create_deep_agent

所有 Magic 从 create_deep_agent 函数开始。打开 graph.py,我们来看这个核心函数。

函数签名

python 复制代码
def create_deep_agent(
    model: str | BaseChatModel | None = None,
    tools: Sequence[BaseTool | Callable | dict[str, Any]] | None = None,
    *,
    system_prompt: str | SystemMessage | None = None,
    middleware: Sequence[AgentMiddleware] = (),
    subagents: Sequence[SubAgent | CompiledSubAgent | AsyncSubAgent] | None = None,
    skills: list[str] | None = None,
    memory: list[str] | None = None,
    response_format: ResponseFormat | None = None,
    context_schema: type[Any] | None = None,
    checkpointer: Checkpointer | None = None,
    store: BaseStore | None = None,
    backend: BackendProtocol | BackendFactory | None = None,
    interrupt_on: dict[str, bool | InterruptOnConfig] | None = None,
    debug: bool = False,
    name: str | None = None,
    cache: BaseCache | None = None,
) -> CompiledStateGraph:

这个函数接受很多参数,但不要被吓到------它们都有合理的默认值。

参数详解

参数 类型 说明
model `str BaseChatModel
tools `Sequence[BaseTool Callable
system_prompt `str SystemMessage
middleware Sequence[AgentMiddleware] 额外的中间件
subagents `Sequence[SubAgent ...]`
skills `list[str] None`
memory `list[str] None`
checkpointer `Checkpointer None`
store `BaseStore None`
backend `BackendProtocol BackendFactory`
interrupt_on `dict[str, bool InterruptOnConfig]`

模型解析 (resolve_model)

Deep Agents 使用 provider:model 格式来指定模型,并提供 resolve_model 函数统一处理模型参数。内部通过 langchain.chat_models.init_chat_model() 初始化模型。

python 复制代码
from deepagents._models import resolve_model

# 支持的格式:
model = resolve_model("claude-sonnet-4-6")      # 简短名称:默认使用 Anthropic
model = resolve_model("openai:gpt-4o")           # OpenAI 模型 (使用 Responses API)
model = resolve_model("anthropic:claude-3-5-sonnet")  # 带前缀:明确指定提供商
model = resolve_model(existing_model)            # 直接传递模型实例

解析逻辑

  1. 如果已经是 BaseChatModel 实例,直接返回
  2. 如果以 openai: 开头,使用 OpenAI Responses API
  3. 其他情况使用 init_chat_model 初始化

支持的模型格式

格式 示例 说明
简短名称 claude-sonnet-4-6 默认使用 Anthropic
带前缀 anthropic:claude-3-5-sonnet 明确指定提供商
OpenAI openai:gpt-4o 使用 Responses API
模型实例 ChatAnthropic(...) 直接传递实例

默认模型

如果你不指定模型,默认使用 Claude Sonnet 4.6:

python 复制代码
def get_default_model() -> ChatAnthropic:
    return ChatAnthropic(
        model_name="claude-sonnet-4-6",
    )

默认后端

如果你不指定后端,默认使用 StateBackend(内存存储):

python 复制代码
backend = backend if backend is not None else (StateBackend)

基础系统提示

Deep Agents 有一个精心设计的基础系统提示,定义了 Agent 的核心行为:

python 复制代码
BASE_AGENT_PROMPT = """你是一个 Deep Agent,一个使用工具帮助用户完成任务的 AI 助手。你通过文本和工具调用来回复。用户可以实时看到你的回复和工具输出。

## 核心行为规范

- 简洁直接。除非被要求,否则不要过度解释。
- 永远不要添加不必要的开场白(如 "好的!"、"好问题!"、"我现在...")。
- 不要说 "我现在来做 X" --- 直接去做。
- 如果请求不明确,在行动前先提问。
- 如果被问及如何处理某事,先解释再行动。

## 专业客观

- 重视准确性而非验证用户的信念
- 当用户错误时礼貌地不同意
- 避免不必要的夸张、赞美或情感认同

## 执行任务

当用户让你做某事时:

1. **先理解** --- 阅读相关文件,检查现有模式。
2. **行动** --- 实现解决方案。
3. **验证** --- 检查你的工作是否符合要求。

持续工作直到任务完全完成。不要中途停止。"""

这个提示定义了 Agent 的行为准则

  • 简洁直接
  • 不说废话
  • 先理解再行动
  • 验证自己的工作

中间件系统:Deep Agents 的核心设计

这是 Deep Agents 最核心的设计。

1. 什么是中间件?

想象一下:你和 LLM 之间有一个"关卡",每次你发送消息给 LLM,或者收到 LLM 的响应时,都会经过这个关卡。

中间件就是这个关卡上的"拦截器"。

它可以在:

  • 消息发送给 LLM 之前拦截并修改
  • LLM 响应回来 之后拦截并处理
  • 工具被调用 之前 /之后做额外处理

2. 为什么需要中间件?

普通的工具函数只能在 LLM 调用 时被触发。但中间件可以在 LLM 调用之前拦截请求,做很多事情:

  1. 动态过滤工具 - 比如 FilesystemMiddleware 根据后端类型决定是否暴露 execute 工具
  2. 注入系统提示 - 比如 MemoryMiddlewareSkillsMiddleware 在每次调用时注入相关指令
  3. 转换消息 - 比如 SummarizationMiddleware 统计 token 数、截断旧内容、用摘要替换历史
  4. 维护跨轮状态 - 中间件可以读写跨 Agent 轮次持久化的状态字典

3. Deep Agents 的中间件架构

类层次结构

所有中间件都继承自 AgentMiddleware

python 复制代码
class AgentMiddleware(Generic[ContextT, ModelRequest, ModelResponse, ResponseT]):
    def wrap_model_request(self, request: ModelRequest) -> ModelRequest:
        """在请求发送给 LLM 之前调用"""
        return request

    def wrap_model_response(self, response: ModelResponse) -> ModelResponse:
        """在收到 LLM 响应后调用"""
        return response

    def wrap_tool_calls(self, tool_calls: list[ToolCallRequest]) -> list[ToolCallRequest]:
        """在工具调用执行前调用"""
        return tool_calls

    def wrap_tool_result(self, tool_name: str, result: Any) -> Any:
        """在工具执行后调用"""
        return result
关键钩子方法

AgentMiddleware 提供了多个钩子:

方法 调用时机 用途
before_agent Agent 执行前 初始化状态、加载数据
modify_request 修改请求 转换输入数据
wrap_model_call LLM 调用前后 拦截请求/响应
wrap_tool_call 工具调用前后 处理工具输入/输出
after_agent Agent 执行后 清理、保存状态

4. 中间件栈的构建

这是整个函数最复杂的部分。中间件的执行顺序非常关键。

创建 Agent 时中间件的应用顺序
复制代码
主 Agent:
1. TodoListMiddleware        # 任务规划
2. SkillsMiddleware          # 技能系统(如果启用)
3. FilesystemMiddleware      # 文件操作
4. SubAgentMiddleware        # 子 Agent
5. SummarizationMiddleware   # 上下文摘要
6. PatchToolCallsMiddleware  # 工具调用修补
7. AnthropicPromptCachingMiddleware # 提示缓存
8. MemoryMiddleware          # 记忆系统(如果启用)
9. HumanInTheLoopMiddleware  # 人在环中(如果启用)
1. 通用子 Agent 的中间件
python 复制代码
gp_middleware: list[AgentMiddleware[Any, Any, Any]] = [
    TodoListMiddleware(),           # 任务规划
    FilesystemMiddleware(backend=backend),  # 文件系统
    create_summarization_middleware(model, backend),  # 摘要
    PatchToolCallsMiddleware(),    # 工具调用修补
]

if skills is not None:
    gp_middleware.append(SkillsMiddleware(backend=backend, sources=skills))

gp_middleware.append(AnthropicPromptCachingMiddleware(...))

if interrupt_on is not None:
    gp_middleware.append(HumanInTheLoopMiddleware(interrupt_on=interrupt_on))

注意 :通用子代理(general-purpose)的中间件栈不包括 SubAgentMiddleware,因为它本身就是子代理。

2. 主 Agent 的中间件
python 复制代码
deepagent_middleware: list[AgentMiddleware[Any, Any, Any]] = [
    TodoListMiddleware(),
]

if skills is not None:
    deepagent_middleware.append(SkillsMiddleware(backend=backend, sources=skills))

deepagent_middleware.extend([
    FilesystemMiddleware(backend=backend),
    SubAgentMiddleware(backend=backend, subagents=inline_subagents),
    create_summarization_middleware(model, backend),
    PatchToolCallsMiddleware(),
])

if async_subagents:
    deepagent_middleware.append(AsyncSubAgentMiddleware(async_subagents=async_subagents))

if middleware:
    deepagent_middleware.extend(middleware)

# 缓存和记忆放在最后
# 原因:记忆更新不应该使 Anthropic 提示缓存前缀失效
deepagent_middleware.append(AnthropicPromptCachingMiddleware(...))
if memory is not None:
    deepagent_middleware.append(MemoryMiddleware(backend=backend, sources=memory))
if interrupt_on is not None:
    deepagent_middleware.append(HumanInTheLoopMiddleware(interrupt_on=interrupt_on))

3. 系统提示的组合

create_deep_agent 中,系统提示词会进行智能组合:

python 复制代码
if system_prompt is None:
    final_system_prompt = BASE_AGENT_PROMPT
elif isinstance(system_prompt, SystemMessage):
    final_system_prompt = SystemMessage(
        content_blocks=[*system_prompt.content_blocks,
                       {"type": "text", "text": f"\n\n{BASE_AGENT_PROMPT}"}]
    )
else:
    # String: simple concatenation
    final_system_prompt = system_prompt + "\n\n" + BASE_AGENT_PROMPT

4. 最终的 Agent 创建

python 复制代码
return create_agent(
    model,
    system_prompt=final_system_prompt,
    tools=tools,
    middleware=deepagent_middleware,
    response_format=response_format,
    context_schema=context_schema,
    checkpointer=checkpointer,
    store=store,
    debug=debug,
    name=name,
    cache=cache,
).with_config({
    "recursion_limit": 1000,
    "metadata": {
        "ls_integration": "deepagents",
        "versions": {"deepagents": __version__},
    },
})

递归限制

默认设置 recursion_limit=1000,这意味着 Agent 最多可以执行 1000 步(LLM 调用次数)。这是一个安全保护,防止无限循环。


中间件系统详解

1. TodoListMiddleware

功能:提供任务规划能力

提供的工具

  • write_todos - 创建、更新、删除待办事项

工作原理

  • 维护一个待办事项列表在 Agent 状态中
  • 每次 LLM 调用时,将待办事项注入系统提示
  • 工具调用后更新状态

注入到系统提示词的内容(动态生成):

markdown 复制代码
## 待办事项

你的当前待办列表:
- [ ] 阅读现有代码库
- [ ] 实现新功能
- [ ] 编写测试

使用 `write_todos` 工具更新你的待办列表.

每次 LLM 调用时,会将当前待办事项列表格式化后注入到系统提示中,让 Agent 随时了解任务进度。

2. FilesystemMiddleware

功能:提供文件系统操作能力

提供的工具

  • ls - 列出目录
  • read_file - 读取文件
  • write_file - 写入文件
  • edit_file - 编辑文件
  • glob - 文件名匹配
  • grep - 文本搜索
  • execute - 执行命令(需要沙箱后端)

工作原理

  • 根据后端类型动态决定提供哪些工具
  • 使用后端协议与实际存储交互
  • 处理文件路径验证、权限检查

关键实现细节

python 复制代码
class FilesystemMiddleware(AgentMiddleware[FilesystemState, ContextT, ResponseT]):
    state_schema = FilesystemState

    def __init__(self, backend, tool_token_limit_before_evict=20000):
        self.backend = backend
        self._tool_token_limit_before_evict = tool_token_limit_before_evict
        self.tools = [
            self._create_ls_tool(),
            self._create_read_file_tool(),
            self._create_write_file_tool(),
            self._create_edit_file_tool(),
            self._create_glob_tool(),
            self._create_grep_tool(),
            self._create_execute_tool(),
        ]

大结果驱逐机制

当工具返回结果过大时(超过 20000 token),自动将结果写入文件系统:

python 复制代码
def _process_large_message(self, message: ToolMessage, backend):
    # 检查是否超过阈值
    if len(content_str) > NUM_CHARS_PER_TOKEN * self._tool_token_limit_before_evict:
        # 写入文件系统
        file_path = f"/large_tool_results/{sanitized_id}"
        backend.write(file_path, content_str)

        # 返回预览和文件引用
        return ToolMessage(content=f"结果已保存到 {file_path}...")

注入到系统提示词的内容

markdown 复制代码
## 遵循惯例

- 编辑前先阅读文件 --- 在做出更改之前了解现有内容
- 模仿现有的风格、命名约定和模式

## 文件系统工具 `ls`, `read_file`, `write_file`, `edit_file`, `glob`, `grep`

你可以使用这些工具与文件系统交互。所有文件路径必须以 / 开头。

- ls: 列出目录中的文件(需要绝对路径)
- read_file: 从文件系统读取文件
- write_file: 向文件系统写入文件
- edit_file: 编辑文件系统中的文件
- glob: 查找匹配模式的文件(如 "**/*.py")
- grep: 在文件中搜索文本

## 大型工具结果

当工具结果太大时,可能会被卸载到文件系统而不是内联返回。在这种情况下,使用 `read_file` 分块检查保存的结果,或在 `/large_tool_results/` 中使用 `grep`。

当后端支持执行时额外注入

markdown 复制代码
## 执行工具 `execute`

你有一个 `execute` 工具用于在沙箱环境中运行 shell 命令。
使用此工具运行命令、脚本、测试、构建和其他 shell 操作。
3. SubAgentMiddleware

功能:提供子 Agent 委托能力

提供的工具

  • task - 调用子 Agent

工作原理

  • 在系统提示中注入可用子 Agent 的描述
  • 拦截 task 工具调用
  • 创建并运行子 Agent
  • 将结果作为 ToolMessage 返回给主 Agent

注入到系统提示词的内容

markdown 复制代码
## `task`(子代理生成器)

你有一个 `task` 工具来启动处理独立任务的短生命周期子代理。这些代理是临时的------它们只存在于任务期间并返回单个结果。

何时使用 task 工具:
- 当任务复杂且多步骤,可以完全独立委托时
- 当任务独立于其他任务,可以并行运行时
- 当任务需要集中推理或大量 token/上下文使用时

子代理生命周期:
1. 生成 → 提供清晰的角色、指令和预期输出
2. 运行 → 子代理自主完成任务
3. 返回 → 子代理提供单个结构化结果
4. 调和 → 将结果合并到主线程

可用子代理类型:
- general-purpose: 用于研究复杂问题的通用代理
- researcher: 用于搜索和收集信息的研究代理

Task 工具签名

python 复制代码
def task(
    description: str,  # 任务描述
    subagent_type: str,  # 子代理类型
    runtime: ToolRuntime,
) -> str | Command:
    # 1. 验证子代理类型
    # 2. 准备子代理状态
    # 3. 调用子代理
    # 4. 提取返回消息
    return _return_command_with_state_update(result, tool_call_id)
4. SummarizationMiddleware

功能:管理长上下文

工作原理

  • 跟踪对话的 token 数量
  • 当接近上下文窗口限制时:
    1. 调用 LLM 生成历史摘要
    2. 用摘要替换原始历史
    3. 继续处理当前请求

触发阈值:默认 80% 上下文使用率

注入到系统提示词的内容

markdown 复制代码
## 压缩对话工具 `compact_conversation`

你有一个 `compact_conversation` 工具。这个工具刷新你的上下文窗口以减少上下文膨胀和成本。

你应该何时使用这个工具:
- 当用户要求完全转向新任务,且之前的上下文可能无关时
- 当你已完成结果提取或综合,且之前的上下文不再需要时
5. SkillsMiddleware

功能:提供技能系统

工作原理

  • 扫描指定目录查找 SKILL.md 文件
  • 解析 YAML frontmatter 获取技能元数据
  • 在系统提示中注入可用技能列表(渐进式披露)
  • 按需读取完整技能内容

注入到系统提示词的内容

markdown 复制代码
## 技能系统

你有一个技能库,提供专业能力和领域知识。

**技能位置**:
- **用户技能**: `/skills/user/`
- **项目技能**: `/skills/project/`(更高优先级)

**可用技能**:
- **web-research**: 进行深入网络研究的结构化方法
  -> 可用工具: search, fetch
  -> 阅读 `/skills/user/web-research/SKILL.md` 获取完整说明

**如何使用技能(渐进式披露)**:
1. 识别技能何时适用:检查用户任务是否匹配技能描述
2. 阅读技能的完整说明:使用上面技能列表中的路径
3. 按照技能的说明执行:SKILL.md 包含分步工作流、最佳实践和示例
4. 访问支持文件:技能可能包含辅助脚本、配置或参考文档

技能元数据结构

python 复制代码
class SkillMetadata(TypedDict):
    path: str           # SKILL.md 文件路径
    name: str           # 技能名称(1-64 字符)
    description: str    # 技能描述(1-1024 字符)
    license: str | None
    compatibility: str | None
    metadata: dict[str, str]
    allowed_tools: list[str]
6. MemoryMiddleware

功能:提供持久记忆

工作原理

  • 加载 AGENTS.md 文件
  • 在系统提示中注入记忆内容
  • 每次请求时自动包含

注入到系统提示词的内容

markdown 复制代码
<agent_memory>
~/.deepagents/AGENTS.md
# 项目指南

- 所有新代码使用 TypeScript
- 遵循 src/ 中的现有代码风格
- 提交前运行测试

./project/AGENTS.md
# Agent 上下文

这是一个使用 Next.js 14 的 React 项目。
API 路由在 src/app/api/ 中
</agent_memory>

<memory_guidelines>
上面的 <agent_memory> 是从文件系统中的文件加载的。当你在与用户的交互中学习时,你可以通过调用 `edit_file` 工具保存新知识。

**从反馈中学习:**
- 你最主要的任务之一是从与用户的交互中学习。
- 当你需要记住某些东西时,更新记忆必须是你的第一个、立即的行动。
- 当用户说某些东西更好/更差时,捕获原因并将其编码为模式。

**何时更新记忆:**
- 当用户明确要求你记住某些东西时
- 当用户描述你的角色或你应该如何行为时
- 当用户对你的工作提供反馈时
- 当用户提供工具使用所需的信息时

**何时不更新记忆:**
- 当信息是临时的或短暂的时
- 当信息是一次性任务请求时
- 永远不要在任何文件或记忆中存储 API 密钥、访问令牌、密码
</memory_guidelines>
7. PatchToolCallsMiddleware

功能:修补工具调用

工作原理

  • 规范化工具参数
  • 处理参数类型转换
  • 添加默认参数值

是否修改系统提示词:否(该中间件只处理工具调用参数,不涉及提示词注入)

8. AnthropicPromptCachingMiddleware

功能:优化 Anthropic 模型的提示缓存

工作原理

  • 检测静态内容(系统提示、工具定义)
  • 使用 Anthropic 的提示缓存 API
  • 减少重复传输的 token

是否修改系统提示词:否(该中间件使用 API 层面的缓存机制,不修改提示词内容)

9. HumanInTheLoopMiddleware

功能:人在环中审批

工作原理

  • 配置哪些工具需要审批
  • 执行前暂停 Agent
  • 等待人类批准或修改
  • 继续执行或拒绝

是否修改系统提示词:否(该中间件在运行时拦截工具调用,不修改提示词)

10. AsyncSubAgentMiddleware

功能:提供异步子 Agent(远程 LangGraph 服务器)

工作原理

  • 在远程 LangGraph 服务器上启动后台任务
  • 提供异步任务管理工具
  • 支持任务状态检查、更新、取消

提供的工具

  • start_async_task - 启动后台任务
  • check_async_task - 检查任务状态
  • update_async_task - 更新任务指令
  • cancel_async_task - 取消任务
  • list_async_tasks - 列出所有任务

注入到系统提示词的内容

markdown 复制代码
## 异步子代理(远程 LangGraph 服务器)

你有一个异步子代理工具,可以在远程 LangGraph 服务器上启动后台任务。

#### 工具:
- `start_async_task`: 启动新的后台任务。立即返回任务 ID。
- `check_async_task`: 获取任务的当前状态和结果。
- `update_async_task`: 向正在运行的任务发送新指令。
- `cancel_async_task`: 停止正在运行的任务。
- `list_async_tasks`: 列出所有跟踪的任务及其实时状态。

#### 关键规则:
- 启动后,始终立即将控制权返回给用户。启动后永远不要自动检查。
- 永远不要循环轮询 `check_async_task`。
- 对话历史中的任务状态始终是过时的------始终调用工具获取当前状态。

可用异步子代理类型:
- my-agent: 异步子代理的描述

最终系统提示词结构

当用户调用 create_deep_agent() 时,最终发送给 LLM 的系统提示词按照以下顺序拼接:

markdown 复制代码
[用户自定义 system_prompt]

你是一个 Deep Agent,一个使用工具帮助用户完成任务的 AI 助手。用户可以实时看到你的回复和工具输出...

## 核心行为规范
- 简洁直接。除非被要求,否则不要过度解释。
- 永远不要添加不必要的开场白(如 "好的!"、"好问题!"、"我现在...")。
- 如果请求不明确,在行动前先提问。
- 如果被问及如何处理某事,先解释再行动。

## 专业客观
- 重视准确性而非验证用户的信念
- 当用户错误时礼貌地不同意
- 避免不必要的夸张、赞美或情感认同

## 执行任务
当用户让你做某事时...

## 待办事项
你的当前待办列表:
- [ ] 任务 1
- [ ] 任务 2

使用 `write_todos` 工具更新你的待办列表。

## 技能系统
你有一个技能库,提供专业能力和领域知识。

**技能位置**:
- **用户技能**: `/skills/user/`
- **项目技能**: `/skills/project/`(更高优先级)

**可用技能**:
- **web-research**: 进行深入网络研究的结构化方法
  -> 可用工具: search, fetch
  -> 阅读 `/skills/user/web-research/SKILL.md` 获取完整说明

**如何使用技能(渐进式披露)**:
1. 识别技能何时适用:检查用户任务是否匹配技能描述
2. 阅读技能的完整说明:使用上面技能列表中的路径
3. 按照技能的说明执行:SKILL.md 包含分步工作流、最佳实践和示例
4. 访问支持文件:技能可能包含辅助脚本、配置或参考文档

## 遵循惯例
- 编辑前先阅读文件 --- 在做出更改之前了解现有内容
- 模仿现有的风格、命名约定和模式

## 文件系统工具 `ls`, `read_file`, `write_file`, `edit_file`, `glob`, `grep`
你可以使用这些工具与文件系统交互。所有文件路径必须以 / 开头。
- ls: 列出目录中的文件(需要绝对路径)
- read_file: 从文件系统读取文件
- write_file: 向文件系统写入文件
- edit_file: 编辑文件系统中的文件
- glob: 查找匹配模式的文件(如 "**/*.py")
- grep: 在文件中搜索文本

## 大型工具结果
当工具结果太大时,可能会被卸载到文件系统而不是内联返回。在这种情况下,使用 `read_file` 分块检查保存的结果,或在 `/large_tool_results/` 中使用 `grep`。

## `task`(子代理生成器)
你有一个 `task` 工具来启动处理独立任务的短生命周期子代理。这些代理是临时的------它们只存在于任务期间并返回单个结果。

何时使用 task 工具:
- 当任务复杂且多步骤,可以完全独立委托时
- 当任务独立于其他任务,可以并行运行时
- 当任务需要集中推理或大量 token/上下文使用时

子代理生命周期:
1. 生成 → 提供清晰的角色、指令和预期输出
2. 运行 → 子代理自主完成任务
3. 返回 → 子代理提供单个结构化结果
4. 调和 → 将结果合并到主线程

可用子代理类型:
- general-purpose: 用于研究复杂问题的通用代理

## 压缩对话工具 `compact_conversation`
你有一个 `compact_conversation` 工具。这个工具刷新你的上下文窗口以减少上下文膨胀和成本。

你应该何时使用这个工具:
- 当用户要求完全转向新任务,且之前的上下文可能无关时
- 当你已完成结果提取或综合,且之前的上下文不再需要时

<agent_memory>
[memory 内容]
</agent_memory>

<memory_guidelines>
上面的 <agent_memory> 是从文件系统中的文件加载的。当你在与用户的交互中学习时,你可以通过调用 `edit_file` 工具保存新知识。

**从反馈中学习:**
- 你最主要的任务之一是从与用户的交互中学习。
- 当你需要记住某些东西时,更新记忆必须是你的第一个、立即的行动。
- 当用户说某些东西更好/更差时,捕获原因并将其编码为模式。

**何时更新记忆:**
- 当用户明确要求你记住某些东西时
- 当用户描述你的角色或你应该如何行为时
- 当用户对你的工作提供反馈时
- 当用户提供工具使用所需的信息时

**何时不更新记忆:**
- 当信息是临时的或短暂的时
- 当信息是一次性任务请求时
- 永远不要在任何文件或记忆中存储 API 密钥、访问令牌、密码
</memory_guidelines>

提示词组装顺序

  1. 用户自定义 system_prompt(如有)
  2. BASE_AGENT_PROMPT - Deep Agent 核心行为规范
  3. TodoListMiddleware - 待办事项(动态)
  4. SkillsMiddleware - 技能系统(如果有 skills 配置)
  5. FilesystemMiddleware - 文件系统工具说明
  6. SubAgentMiddleware - 子 Agent 工具说明
  7. SummarizationMiddleware - 上下文压缩工具
  8. AnthropicPromptCachingMiddleware - 缓存标记(API 层面)
  9. MemoryMiddleware - 记忆内容(如果有 memory 配置)

每个中间件通过 modify_requestwrap_model_call 方法将内容追加到系统消息末尾。


中间件的状态管理

每个中间件可以定义自己的状态类型:

python 复制代码
class MyMiddlewareState(AgentState):
    my_data: str
    counter: int

class MyMiddleware(AgentMiddleware):
    state_schema = MyMiddlewareState

    def wrap_model_request(self, request, state):
        # 读取状态
        current_count = state.get("counter", 0)

        # 修改状态
        state["counter"] = current_count + 1

        return request

私有状态属性

使用 PrivateStateAttr 标记不传播到父 Agent 的状态:

python 复制代码
from langchain.agents.middleware.types import PrivateStateAttr

class SkillsState(AgentState):
    skills_metadata: NotRequired[Annotated[list[SkillMetadata], PrivateStateAttr]]
    """不会传播到父 Agent"""

状态通过 LangGraph 的状态管理机制在轮次之间持久化。


子代理的自动添加

通用子代理的创建

如果没有提供名为 general-purpose 的子代理,会自动创建一个:

python 复制代码
GENERAL_PURPOSE_SUBAGENT: SubAgent = {
    "name": "general-purpose",
    "description": "General-purpose agent for researching complex questions...",
    "system_prompt": DEFAULT_SUBAGENT_PROMPT,
}

子代理中间件栈

每个子代理都会获得完整的中间件栈:

python 复制代码
subagent_middleware: list[AgentMiddleware[Any, Any, Any]] = [
    TodoListMiddleware(),
    FilesystemMiddleware(backend=backend),
    create_summarization_middleware(subagent_model, backend),
    PatchToolCallsMiddleware(),
]

# 添加技能(如果指定)
if subagent_skills:
    subagent_middleware.append(SkillsMiddleware(backend=backend, sources=subagent_skills))

# 添加用户自定义中间件
subagent_middleware.extend(spec.get("middleware", []))

# 添加提示缓存
subagent_middleware.append(AnthropicPromptCachingMiddleware(...))

默认工具

创建 Deep Agent 时,你不需要手动添加任何工具------以下工具默认可用:

1. 任务规划

  • write_todos - 管理待办事项列表

2. 文件操作

  • ls - 列出目录内容
  • read_file - 读取文件
  • write_file - 写入文件
  • edit_file - 编辑文件
  • glob - 文件名模式匹配
  • grep - 文本搜索

3. Shell 执行

  • execute - 运行 Shell 命令(需要支持沙箱的后端)

4. 子 Agent

  • task - 调用子 Agent

返回值

create_deep_agent 返回一个 CompiledStateGraph------这是 LangGraph 的编译状态图。

这意味着你可以:

1. 使用流式输出

python 复制代码
for chunk in agent.stream({"messages": [("user", "Hello")]):
    print(chunk)

2. 保存和恢复状态

python 复制代码
# 保存状态
config = {"configurable": {"thread_id": "my-session"}}
agent.invoke({"messages": [...]}, config)

# 恢复状态
agent.invoke({"messages": [("user", "继续")], config)

3. 与 LangGraph Studio 集成

python 复制代码
# 导出到 LangGraph Studio
agent.get_graph().draw_mermaid()

4. 结构化输出 (response_format)

使用 response_format 强制 Agent 返回特定格式:

python 复制代码
from langchain.agents.structured_output import ResponseFormat
from pydantic import BaseModel

class Answer(BaseModel):
    reasoning: str
    answer: str
    confidence: float

agent = create_deep_agent(
    response_format=ResponseFormat(
        schema=Answer,
        mode="json",  # 或 "xml"
    )
)

# Agent 必须返回符合 Answer 格式的 JSON
result = await agent.ainvoke({"messages": [("user", "什么是 2+2?")]})

支持的模式

  • json - JSON 格式输出
  • xml - XML 格式输出

5. 上下文模式 (context_schema)

定义 Agent 状态的结构:

python 复制代码
from typing import TypedDict

class MyAgentState(TypedDict):
    messages: list
    todo_items: list[str]
    current_task: str | None

agent = create_deep_agent(
    context_schema=MyAgentState,
)

这允许你:

  • 定义自定义状态字段
  • 类型安全的状态管理
  • 与 LangGraph 的状态管理集成

6. 缓存 (cache)

使用 LangGraph 缓存加速重复查询:

python 复制代码
from langgraph.cache import InMemoryCache

agent = create_deep_agent(
    cache=InMemoryCache(),
)

# 相同输入会直接从缓存返回

缓存类型

  • InMemoryCache - 内存缓存
  • 自定义缓存实现

7. 调试模式 (debug)

启用详细日志:

python 复制代码
agent = create_deep_agent(
    debug=True,  # 启用 LangGraph 调试日志
)

调试模式会输出:

  • Agent 决策过程
  • 工具调用详情
  • 状态变化
  • 中间件执行信息

8. 状态持久化 (checkpointer vs store)

Deep Agents 支持两种持久化机制:

Checkpointer - 对话状态持久化

保存整个对话状态,支持恢复:

python 复制代码
from langgraph.checkpoint.memory import MemorySaver
from langgraph.checkpoint.sqlite import SqliteSaver

# 内存检查点
agent = create_deep_agent(
    checkpointer=MemorySaver(),
)

# SQLite 持久化
agent = create_deep_agent(
    checkpointer=SqliteSaver.from_conn_string("./checkpoints.db"),
)

# 使用检查点
config = {"configurable": {"thread_id": "session-1"}}
result = await agent.ainvoke({"messages": [("user", "Hello")]}, config)

# 恢复会话
result = await agent.ainvoke({"messages": [("user", "Continue")]}, config)
Store - 命名空间存储

用于跨会话的持久化数据:

python 复制代码
from langgraph.store.memory import MemoryStore

agent = create_deep_agent(
    store=MemoryStore(),
)

# 存储数据
await agent.store.put(
    ("user_prefs", "theme"),
    {"value": "dark", "font_size": 14}
)

# 读取数据
result = await agent.store.get(("user_prefs", "theme"))

对比

特性 Checkpointer Store
用途 对话状态 持久化数据
范围 当前会话 跨会话
数据 完整状态 任意数据
典型场景 会话恢复 用户偏好、配置

后端系统:Agent 与外部世界的交互

Deep Agents 是一个可插拔的框架。不同的使用场景需要不同的后端:

  • 开发/测试 - 需要安全隔离,数据存在内存中
  • 生产环境 - 需要访问真实文件系统
  • 沙箱执行 - 需要在隔离环境中运行命令

后端系统抽象了这些差异,让同一套代码可以适配不同场景。

后端接口定义

所有后端都实现 BackendProtocol 接口。打开 backends/protocol.py 看看:

核心接口
python 复制代码
class BackendProtocol(Protocol):
    """所有后端必须实现的接口"""

    async def read_file(self, path: str) -> ReadResult:
        """读取文件"""
        ...

    async def write_file(self, path: str, content: str) -> WriteResult:
        """写入文件"""
        ...

    async def edit_file(self, path: str, old_string: str, new_string: str) -> EditResult:
        """编辑文件"""
        ...

    async def ls(self, path: str) -> LsResult:
        """列出目录"""
        ...

    async def glob(self, path: str, pattern: str) -> GlobResult:
        """文件名匹配"""
        ...

    async def grep(self, path: str, pattern: str, **kwargs) -> GrepResult:
        """文本搜索"""
        ...
沙箱协议

如果后端支持命令执行,还需要实现 SandboxBackendProtocol

python 复制代码
class SandboxBackendProtocol(BackendProtocol):
    """支持命令执行的后端"""

    async def execute(
        self,
        command: str,
        timeout: float = ...,
        context: dict | None = None
    ) -> ExecuteResult:
        """执行命令"""
        ...

内置后端实现

1. StateBackend(默认)

位置backends/state.py

特点

  • 所有数据存在内存中
  • 最安全,适合开发/测试
  • 不需要任何持久化

工作原理

python 复制代码
class StateBackend:
    """内存状态后端"""

    def __init__(self, runtime: Runtime | None = None):
        self._files: dict[str, FileData] = {}  # 文件存储
        self._runtime = runtime  # LangGraph runtime

    async def read_file(self, path: str) -> ReadResult:
        if path not in self._files:
            raise FileNotFoundError(f"File not found: {path}")
        return ReadResult(
            content=self._files[path].content,
            size=len(self._files[path].content),
        )

使用场景

  • 本地开发
  • 单元测试
  • 不需要持久化的场景
2. FilesystemBackend

位置backends/filesystem.py

特点

  • 访问真实文件系统
  • 需要配置根目录
  • 支持路径验证和安全检查

使用示例

python 复制代码
from deepagents.backends import FilesystemBackend

# 限制在项目目录
backend = FilesystemBackend(root_dir="/path/to/project")

# 限制在用户目录
backend = FilesystemBackend(root_dir="~")

安全考虑

  • 默认只能访问配置的根目录
  • 可以添加路径验证
  • 建议配合人在环中使用
3. LocalShellBackend

位置backends/local_shell.py

特点

  • 本地 Shell 命令执行
  • 支持超时设置
  • 可以捕获输出

使用示例

python 复制代码
from deepagents.backends import LocalShellBackend

backend = LocalShellBackend(
    timeout=30.0,  # 默认超时 30 秒
)

result = await backend.execute("ls -la")

安全考虑

  • ⚠️ 危险!可以执行任何命令
  • 建议只在受控环境使用
  • 建议配合人在环中使用
4. LangSmithSandbox

位置backends/langsmith.py

特点

  • LangSmith 远程沙箱
  • 完全隔离的环境
  • 自动清理

使用示例

python 复制代码
from deepagents.backends import LangSmithSandbox

backend = LangSmithSandbox(
    api_key=os.getenv("LANGSMITH_API_KEY"),
)
5. StoreBackend

位置backends/store.py

特点

  • 持久化存储
  • 基于 LangGraph Store
  • 支持命名空间

使用场景

  • 需要跨会话持久化
  • 复杂的数据结构
6. CompositeBackend

位置backends/composite.py

特点

  • 组合多个后端
  • 可以为不同操作指定不同后端
  • 灵活的路由逻辑

使用示例

python 复制代码
from deepagents.backends import CompositeBackend, FilesystemBackend, LangSmithSandbox

backend = CompositeBackend(
    # 文件操作使用真实文件系统
    file_backend=FilesystemBackend(root_dir="/project"),
    # 命令执行使用远程沙箱
    execute_backend=LangSmithSandbox(),
)
CompositeBackend 实现原理

CompositeBackend 通过路径前缀路由实现不同操作指定不同后端。

1. 初始化配置
python 复制代码
from deepagents.backends import CompositeBackend, StateBackend, StoreBackend

composite = CompositeBackend(
    default=StateBackend(runtime),           # 默认后端
    routes={
        "/memories/": StoreBackend(runtime),  # 路由到持久化存储
        "/cache/": FilesystemBackend(...),     # 路由到文件系统
    }
)
2. 路由匹配逻辑

关键函数 _route_for_path

python 复制代码
def _route_for_path(*, default, sorted_routes, path):
    # 按长度排序(最长优先),确保精确匹配
    for route_prefix, backend in sorted_routes:
        normalized_prefix = route_prefix if route_prefix.endswith("/") else f"{route_prefix}/"
        if path.startswith(normalized_prefix):
            # 匹配成功,剥离前缀后传递给目标后端
            suffix = path[len(normalized_prefix):]
            backend_path = f"/{suffix}" if suffix else "/"
            return backend, backend_path, route_prefix
    # 无匹配,使用默认后端
    return default, path, None
3. 路由流程

每个文件操作都会经过路由:

python 复制代码
def read(self, file_path: str, ...):
    # 1. 根据路径找到对应的后端和实际路径
    backend, stripped_key = self._get_backend_and_key(file_path)
    # 2. 委托给正确的后端处理
    return backend.read(stripped_key, offset=offset, limit=limit)
4. 路径重映射

当路由到子后端时,需要剥离路由前缀,返回时再还原:

复制代码
用户访问 /memories/notes.txt
        ↓
实际传递给 StoreBackend 的是 /notes.txt
        ↓
返回结果时再拼接回 /memories/notes.txt
5. 特殊处理
  • 根目录 /:聚合所有后端的文件列表
  • grep/glob:搜索所有后端并合并结果
  • execute:始终使用默认后端(不支持路由)

这种设计让同一个文件系统 API 可以透明地路由到不同的存储后端。

后端与中间件的交互

中间件通过后端协议与后端交互:

python 复制代码
class FilesystemMiddleware:
    def __init__(self, backend: BackendProtocol):
        self._backend = backend

    async def read_file(self, path: str):
        # 调用后端
        return await self._backend.read_file(path)

这种设计让中间件不需要关心数据存储在哪里。

如何选择后端?

场景 推荐后端
本地开发/测试 StateBackend(默认)
生产文件操作 FilesystemBackend
本地命令执行 LocalShellBackend
隔离执行 LangSmithSandbox
持久化存储 StoreBackend
混合需求 CompositeBackend

技能系统:自定义工作流

技能(Skills)是一种可重用的工作流 ,Agent 可以通过斜杠命令(如 /skill-name)调用它们。

想象一下:

  • 你有一个常用的代码审查流程
  • 你有一个常用的测试生成流程
  • 你有一个常用的文档生成流程

把这些流程封装成技能,Agent 就可以在需要时调用它们。

技能 vs 记忆

特性 技能 记忆
调用方式 按需(斜杠命令) 自动(始终加载)
用途 工作流 持久上下文
触发 用户显式调用 Agent 启动时
动态性 高度动态 相对静态

SKILL.md 格式

技能定义在 SKILL.md 文件中:

markdown 复制代码
# Skill Name

Description of what this skill does and when to use it.

## Steps

1. First step description
2. Second step description
3. Third step description

## Example

/example argument

字段说明

  • # Skill Name - 技能名称(用于斜杠命令)
  • Description - 描述,说明何时使用
  • Steps - 执行步骤
  • Example - 使用示例

技能系统架构

SkillsMiddleware

核心是 SkillsMiddleware,它:

  1. 扫描指定目录查找 SKILL.md 文件
  2. 解析技能定义
  3. 在系统提示中注入可用技能
  4. 拦截技能调用并执行

技能调用机制

1. 技能发现(Session 启动时)

每次 LLM 调用前,SkillsMiddleware 会:

  1. 扫描技能目录
  2. 加载所有 SKILL.md 文件
  3. 解析技能定义(YAML frontmatter)
  4. 注入到系统提示(渐进式披露)

关键:技能元数据只加载一次

python 复制代码
def before_agent(self, state, runtime, config):
    # 如果 skills_metadata 已存在,跳过加载
    if "skills_metadata" in state:
        return None

    # 从所有源加载技能
    for source_path in self.sources:
        source_skills = _list_skills(backend, source_path)
        all_skills[skill["name"]] = skill

    return SkillsStateUpdate(skills_metadata=skills)
2. 渐进式披露(每次 LLM 调用)

系统提示中只注入技能的元数据,不加载完整内容:

markdown 复制代码
**Available Skills**:
- **web-research**: Structured approach to conducting thorough web research
  -> Allowed tools: search, fetch
  -> Read `/skills/user/web-research/SKILL.md` for full instructions

Agent 需要使用技能时,会主动读取 SKILL.md 文件。

3. 技能调用流程
复制代码
用户: /web-research 最佳AI助手是什么?

1. SkillsMiddleware 识别斜杠命令
2. Agent 读取 /skills/user/web-research/SKILL.md
3. 执行技能定义的工作流
4. 返回结果
4. 按需加载的优势
  • 减少 Token 消耗:完整技能文档可能很大,按需加载避免每次都注入
  • 提高响应速度:初始提示更小,LLM 处理更快
  • 灵活性:Agent 可以根据任务选择性地读取相关技能
5. 技能执行

技能执行本质上是一个提示模板:

python 复制代码
# 技能调用时,生成如下提示:
f"""Execute skill: {skill_name}

{skill_description}

## Steps
{skill_steps}

Now execute this skill."""

记忆系统:持久上下文

记忆(Memory)是 Agent 启动时自动加载的持久上下文

与技能不同,记忆:

  • 始终加载(不需要显式调用)
  • 提供项目级上下文
  • 在每次对话中都可用的

AGENTS.md 规范

Deep Agents 支持 AGENTS.md 规范。

基本格式

markdown 复制代码
# Project Name

## Overview
Brief description of the project.

## Build Commands
- `npm install` - Install dependencies
- `npm run dev` - Start development server
- `npm test` - Run tests

## Code Style
- Use TypeScript
- 4 spaces for indentation
- Prefer functional components

## Architecture
- `/src/components` - UI components
- `/src/hooks` - Custom hooks
- `/src/utils` - Utility functions

常用章节

  • Overview - 项目概述
  • Build Commands - 构建命令
  • Code Style - 代码风格
  • Architecture - 架构说明
  • Testing - 测试指南
  • Deployment - 部署指南

MemoryMiddleware

工作原理
python 复制代码
class MemoryMiddleware(AgentMiddleware):
    def __init__(self, backend: BackendProtocol, sources: list[str]):
        self._backend = backend
        self._sources = sources

    def wrap_model_request(self, request, state):
        # 加载所有记忆文件
        memories = []
        for source in self._sources:
            content = load_agents_md(source)
            memories.append(content)

        # 注入到系统提示
        prompt = format_memory(memories)
        request = append_to_system_message(request, prompt)
        return request
使用方式
python 复制代码
agent = create_deep_agent(
    memory=[
        "~/.deepagents/AGENTS.md",      # 用户级记忆
        "./.deepagents/AGENTS.md",      # 项目级记忆
    ]
)

记忆来源

1. 用户级记忆

位置:~/.deepagents/AGENTS.md

包含:

  • 用户偏好
  • 常用命令
  • 个人习惯
2. 项目级记忆

位置:.deepagents/AGENTS.md

包含:

  • 项目特定配置
  • 构建命令
  • 代码规范
3. 环境级记忆

位置:可以在任何地方指定

python 复制代码
agent = create_deep_agent(
    memory=["/path/to/custom/AGENTS.md"]
)

记忆加载顺序

多个记忆文件按顺序加载,后面的会覆盖前面的:

python 复制代码
memory = [
    "~/.deepagents/AGENTS.md",      # 先加载
    "./.deepagents/AGENTS.md",      # 后加载(优先级高)
]

子代理系统:任务委托

子代理(SubAgent)是主 Agent 可以调用的专门 Agent

当你有一个复杂任务时,可以:

  1. 自己完成所有事情
  2. 把任务分解,委托给子代理

子代理的优势:

  • 专业化 - 每个子代理专注特定任务
  • 隔离 - 子代理有独立的上下文
  • 可复用 - 一次定义,多次使用

子代理类型

Deep Agents 支持三种类型的子代理:

1. SubAgent(声明式)

最常用的子代理类型,定义为一个配置字典:

python 复制代码
subagent = {
    "name": "reviewer",
    "description": "代码审查专家,帮助审查代码质量和安全问题",
    "system_prompt": """你是一个严格的代码审查专家。

    审查时关注:
    1. 代码风格一致性
    2. 错误处理
    3. 安全问题
    4. 性能问题
    5. 测试覆盖

    审查结果要具体、可操作。""",
    "tools": [some_tools],  # 可选:指定工具
    "model": "claude-sonnet-4",  # 可选:指定模型
    "skills": ["/reviewer/skills/"],  # 可选:子代理独立的技能
    "middleware": [...],  # 可选:额外的中间件
    "interrupt_on": {"edit_file": True},  # 可选:人在环中配置
}
子代理的技能

子代理的 skills 与主 agent 不共享,需要单独配置。每个子代理可以拥有自己独立的技能系统:

python 复制代码
agent = create_deep_agent(
    skills=["/main/skills/"],  # 主 Agent 的技能
    subagents=[
        {
            "name": "reviewer",
            "description": "代码审查专家",
            "system_prompt": "你是一个严格的代码审查专家...",
            "tools": [read_file, glob, grep],
            "model": "claude-sonnet-4",
            "skills": ["/reviewer/skills/"],  # 子代理独立的技能
        }
    ]
)

子代理的中间件栈构建过程:

python 复制代码
# graph.py 中的子代理中间件构建
subagent_middleware: list[AgentMiddleware[Any, Any, Any]] = [
    TodoListMiddleware(),
    FilesystemMiddleware(backend=backend),
    create_summarization_middleware(subagent_model, backend),
    PatchToolCallsMiddleware(),
]

# 添加子代理自己的技能(如果有)
subagent_skills = spec.get("skills")
if subagent_skills:
    subagent_middleware.append(SkillsMiddleware(backend=backend, sources=subagent_skills))

# 添加用户自定义中间件
subagent_middleware.extend(spec.get("middleware", []))

# 添加提示缓存
subagent_middleware.append(AnthropicPromptCachingMiddleware(unsupported_model_behavior="ignore"))
2. CompiledSubAgent(预编译)

使用已编译的 LangGraph 图:

python 复制代码
from langgraph.graph import StateGraph

# 创建一个预编译的子代理
subagent_graph = create_my_subagent()  # 返回 CompiledStateGraph

compiled_subagent = {
    "name": "researcher",
    "description": "研究助手,帮助收集和分析信息",
    "runnable": subagent_graph,
}
3. AsyncSubAgent(异步)

用于远程或后台执行的子代理:

python 复制代码
async_subagent = {
    "name": "background-worker",
    "description": "后台任务执行器",
    "graph_id": "my-deployment-id",  # LangSmith deployment ID
    "url": "https://...",
    "headers": {"Authorization": "Bearer ..."},
}

SubAgentMiddleware

工作原理
python 复制代码
class SubAgentMiddleware(AgentMiddleware):
    def __init__(self, backend, subagents):
        self._backend = backend
        self._subagents = subagents

    def wrap_model_request(self, request, state):
        # 注入子代理描述到系统提示
        subagent_descriptions = format_subagents(self._subagents)
        request = append_to_system_message(request, subagent_descriptions)
        return request

    def wrap_tool_calls(self, tool_calls, state):
        # 拦截 task 工具调用
        for call in tool_calls:
            if call.tool_name == "task":
                return self._execute_subagent(call, state)
        return tool_calls
task 工具参数
python 复制代码
{
    "name": "task",
    "description": "委托任务给子代理",
    "parameters": {
        "subagent": "子代理名称",
        "task": "任务描述",
        "context": {}  # 可选的上下文
    }
}

调用子代理

在对话中:

复制代码
用户: 帮我审查这段代码
Agent: (调用 reviewer 子代理)

或者显式调用:

复制代码
用户: 使用 reviewer 审查 src/utils.py

主代理与子代理的通信机制

主代理和子代理通过 task 工具调用进行通信。

通信流程
复制代码
主 Agent: "帮我搜索这个项目的架构"
         ↓
    调用 task 工具
         ↓
SubAgentMiddleware 拦截
         ↓
子 Agent 执行任务
         ↓
返回 ToolMessage 给主 Agent
关键代码实现

1. 任务调用

python 复制代码
def task(description, subagent_type, runtime):
    # 1. 获取子代理
    subagent = subagent_graphs[subagent_type]

    # 2. 准备子代理状态(隔离上下文)
    subagent_state = {k: v for k, v in runtime.state.items() if k not in _EXCLUDED_STATE_KEYS}
    subagent_state["messages"] = [HumanMessage(content=description)]

    # 3. 调用子代理
    result = subagent.invoke(subagent_state)

    # 4. 返回结果(转为 ToolMessage)
    return _return_command_with_state_update(result, runtime.tool_call_id)

2. 状态隔离(排除的键)

python 复制代码
_EXCLUDED_STATE_KEYS = {"messages", "todos", "structured_response", "skills_metadata", "memory_contents"}

子代理不继承主 Agent 的这些状态,确保独立上下文。

3. 结果返回

python 复制代码
def _return_command_with_state_update(result, tool_call_id):
    # 提取子代理返回的消息
    message_text = result["messages"][-1].text

    # 作为 ToolMessage 返回给主 Agent
    return Command(update={
        "messages": [ToolMessage(message_text, tool_call_id=tool_call_id)],
    })
通信特点
特性 说明
调用方式 同步/异步函数调用
状态传递 主 Agent → 子 Agent(排除敏感状态)
结果返回 子 Agent → 主 Agent(通过 ToolMessage)
上下文隔离 子代理有独立的 messages 列表
单向通信 子代理完成后,结果以工具结果形式返回

这种设计让子代理可以专注完成任务,返回简洁的结果给主 Agent 合成。


人在环中 (Human in the Loop)

人在环中 (Human in the Loop, HITL) 是一种安全机制,允许在危险操作执行前等待人类批准

这对于:

  • 防止意外删除文件
  • 防止执行危险命令
  • 审核敏感操作
  • 符合安全合规要求

工作原理

1. 配置需要审批的工具
python 复制代码
agent = create_deep_agent(
    interrupt_on={
        "edit_file": True,        # 编辑文件前需要批准
        "write_file": True,       # 写入文件前需要批准
        "execute": True,          # 执行命令前需要批准
    }
)
2. 执行流程
复制代码
Agent 决定执行危险操作
        ↓
暂停 Agent 执行
        ↓
显示操作详情给用户
        ↓
用户决定:批准 / 拒绝 / 修改
        ↓
继续执行或取消
3. 详细配置
python 复制代码
from langchain.agents.middleware import InterruptOnConfig

agent = create_deep_agent(
    interrupt_on={
        "edit_file": InterruptOnConfig(
            allow_continue=True,    # 允许跳过
            auto_approve=False,     # 不自动批准
        ),
        "execute": InterruptOnConfig(
            allow_continue=False,   # 不允许跳过
            auto_approve=False,
        ),
    }
)

HumanInTheLoopMiddleware

实现原理
python 复制代码
class HumanInTheLoopMiddleware(AgentMiddleware):
    def __init__(self, interrupt_on: dict[str, bool | InterruptOnConfig]):
        self._interrupt_on = interrupt_on

    def wrap_tool_calls(self, tool_calls, state):
        # 检查哪些工具需要审批
        for call in tool_calls:
            if call.tool_name in self._interrupt_on:
                # 暂停执行,返回审批请求
                return self._create_interrupt(call)
        return tool_calls
InterruptOnConfig
python 复制代码
class InterruptOnConfig:
    allow_continue: bool = True   # 允许用户选择"继续"跳过
    auto_approve: bool = False    # 自动批准(危险!)

检查点要求

人在环中功能需要配置检查点 (checkpointer)

python 复制代码
from langgraph.checkpoint.memory import MemorySaver

agent = create_deep_agent(
    checkpointer=MemorySaver(),
    interrupt_on={"edit_file": True},
)

原因:暂停后需要保存状态,批准后恢复执行。


上下文摘要:处理长对话

LLM 有上下文窗口限制(比如 200K token)。当对话很长时:

  • 会达到窗口限制
  • 性能下降
  • 成本增加

摘要机制可以在上下文即将满时:

  1. 将历史对话压缩成摘要
  2. 用摘要替换原始历史
  3. 继续处理当前请求

SummarizationMiddleware

python 复制代码
class SummarizationMiddleware(AgentMiddleware):
    def __init__(self, model, backend, threshold=0.8):
        self._model = model
        self._backend = backend
        self._threshold = threshold  # 触发摘要的阈值

    def wrap_model_request(self, request, state):
        # 计算当前 token 使用率
        token_count = count_tokens(request.messages)
        limit = get_context_limit(self._model)

        if token_count / limit > self._threshold:
            # 需要摘要
            summary = await self._summarize(request.messages)
            request.messages = self._replace_with_summary(summary)

        return request

摘要触发条件

默认当上下文使用率达到 80% 时触发:

python 复制代码
threshold = 0.8  # 80% 触发

摘要过程

1. 检测需要摘要
python 复制代码
# 计算当前消息的 token 数
token_count = estimate_token_count(messages)
max_tokens = get_model_max_tokens(model)

if token_count > max_tokens * threshold:
    # 需要触发摘要
2. 生成摘要

调用 LLM 生成历史摘要:

python 复制代码
summary_prompt = f"""请总结以下对话的要点:

{format_messages_for_summary(messages)}

请用简洁的语言总结:
1. 已经完成的任务
2. 当前进行中的任务
3. 重要的上下文信息
"""

summary = await model.invoke(summary_prompt)
3. 替换历史
python 复制代码
# 用摘要替换原始消息
summarized_messages = [
    SystemMessage(content=f"Previous conversation summary: {summary}"),
    *recent_messages,  # 保留最近的几个消息
]

文件系统卸载

除了内存摘要,还可以将历史卸载到文件系统:

python 复制代码
SummarizationMiddleware(
    model=model,
    backend=backend,
    offload_to_filesystem=True,  # 卸载到文件
    offload_dir="/path/to/offload",
)

架构设计理念

1. 开箱即用

Deep Agents 的核心理念是"batteries included"------你不需要自己组装零件,拿来就能用。

2. 可定制

虽然默认配置已经很好,但你可以在任何层面定制:

  • 替换模型
  • 添加工具
  • 修改提示
  • 配置子 Agent
  • 选择后端

3. 基于 LangGraph

所有 Agent 都是编译后的 LangGraph 图。这意味着你可以:

  • 使用流式输出
  • 与 LangGraph Studio 集成
  • 使用检查点保存状态
  • 使用任何 LangGraph 特性

4. Provider 无关

不依赖特定的 LLM 提供商。任何支持工具调用的模型都可以使用。


进阶配置与实战示例

安装

SDK
bash 复制代码
pip install deepagents
# 或
uv add deepagents
CLI
bash 复制代码
curl -LsSf https://raw.githubusercontent.com/langchain-ai/deepagents/main/libs/cli/scripts/install.sh | bash

第一个 Agent

python 复制代码
from deepagents import create_deep_agent

agent = create_deep_agent()
result = agent.invoke({"messages": [{"role": "user", "content": "Hello"}]})

添加自定义工具

python 复制代码
from deepagents import create_deep_agent

def get_weather(city: str) -> str:
    """获取城市天气"""
    return f"{city} 今天是晴天!"

agent = create_deep_agent(tools=[get_weather])

使用不同模型

python 复制代码
from langchain.chat_models import init_chat_model

# OpenAI
agent = create_deep_agent(model="openai:gpt-4o")

# Anthropic
agent = create_deep_agent(model="anthropic:claude-opus-4-6")

# 或直接传入模型实例
agent = create_deep_agent(model=init_chat_model("openai:gpt-4o"))

配置后端

python 复制代码
from deepagents.backends import FilesystemBackend

# 使用文件系统后端
agent = create_deep_agent(backend=FilesystemBackend(root_dir="/path/to/project"))

添加技能

python 复制代码
agent = create_deep_agent(skills=["/path/to/skills/"])

添加记忆

python 复制代码
agent = create_deep_agent(memory=["~/.deepagents/AGENTS.md"])

配置人在环中

python 复制代码
agent = create_deep_agent(
    interrupt_on={
        "edit_file": True,
        "execute": True,
    }
)

添加子代理

python 复制代码
agent = create_deep_agent(
    subagents=[
        {
            "name": "reviewer",
            "description": "代码审查专家",
            "system_prompt": "你是一个严格的代码审查专家...",
        }
    ]
)

使用检查点

python 复制代码
from langgraph.checkpoint.memory import MemorySaver

agent = create_deep_agent(checkpointer=MemorySaver())

# 保存状态
config = {"configurable": {"thread_id": "my-session"}}
agent.invoke({"messages": [...]}, config)

# 恢复状态
agent.invoke({"messages": [...]}, config)

完整示例

python 复制代码
from deepagents import create_deep_agent
from deepagents.backends import FilesystemBackend
from langgraph.checkpoint.memory import MemorySaver
from langchain.chat_models import init_chat_model

# 创建 Agent
agent = create_deep_agent(
    model="anthropic:claude-sonnet-4-6",
    tools=[my_custom_tool],
    backend=FilesystemBackend(root_dir="/project"),
    skills=["/skills/"],
    memory=["~/.deepagents/AGENTS.md"],
    subagents=[
        {
            "name": "reviewer",
            "description": "代码审查专家",
            "system_prompt": "你是一个专业的代码审查专家...",
        }
    ],
    interrupt_on={
        "edit_file": True,
        "execute": True,
    },
    checkpointer=MemorySaver(),
)

# 使用 Agent
result = agent.invoke({
    "messages": [{"role": "user", "content": "帮我审查代码"}]
})

总结

create_deep_agent 是整个 SDK 的核心入口。它:

  1. 设置默认配置 - 模型、后端、中间件
  2. 构建中间件栈 - 按正确顺序组合所有功能
  3. 组合系统提示 - 用户提示 + 基础提示
  4. 创建 LangGraph Agent - 返回可用的 Agent 图

中间件是 Deep Agents 灵活性的核心:

  1. 拦截请求/响应 - 在合适的位置做合适的事情
  2. 动态工具 - 根据上下文决定提供什么工具
  3. 状态持久化 - 跨轮次维护状态
  4. 组合能力 - 多个中间件可以组合使用

后端系统是 Deep Agents 灵活性的另一个关键:

  1. 接口抽象 - 统一的后端协议
  2. 多种实现 - 内存、文件系统、沙箱、远程
  3. 可组合 - 可以组合多个后端
  4. 可扩展 - 轻松添加自定义后端

理解了这个函数和中间件系统,你就理解了 Deep Agents 的一半。


示例项目

如果你想深入了解 Deep Agents 的实际使用,推荐参考 https://github.com/seanzhang-zhichen/deepagents-demo 项目。

相关推荐
拿泥more5 小时前
用 AI Agent 监控南理工通知公告
agent·skills·监控通知
深藏功yu名5 小时前
Day25:RAG检索+重排序保姆级入门!
人工智能·ai·pycharm·agent·rag·rerank
Rick19935 小时前
RAG和Agent是什么?
ai·agent
倾颜5 小时前
不只是接个计算器:我是怎么把 Tool Calling 做成可扩展骨架的
langchain·llm·next.js
无风听海16 小时前
LangGraph 深度解析:Node、Edge 与 Channel 的对应机制及执行驱动原理
langchain·edge
深藏功yu名18 小时前
Day24:向量数据库 Chroma_FAISS 入门
数据库·人工智能·python·ai·agent·faiss·chroma
DigitalOcean19 小时前
如何使用DigitalOcean Gradient 平台上的无服务器推理
aigc·agent
chaors20 小时前
Agent来了0x05:Self-Ask 回路验证
llm·agent·ai编程
鲲志20 小时前
别等 Sora 了!一代神话陨落?OpenAI 这一手“弃车保帅”我看懂了...
aigc·agent·sora