前面几篇介绍了 Deep Agents 的整体架构、Planning 和 Tools。Agent 已经能够拆解任务、调用工具。

然而,当 Agent 执行复杂任务时,多步骤会产生中间结果,此时,需考虑大量中间结果应该放在哪里。

Deep Agents 引入 Filesystem,为 Agent 提供一个可读写的工作空间。Agent 可以把资料、笔记和中间结果保存为文件,需要时再读取。

本文重点介绍 Filesystem 的作用、核心 API、运行机制,以及如何在实际项目中使用。

一、为什么 Agent 需要文件系统

普通 Agent 通常通过 Messages 保存交互过程。

例如:

代码片段Text
User: 分析三个技术方案

Agent: 调用工具获取方案 A
Tool: 返回 5000 字

Agent: 调用工具获取方案 B
Tool: 返回 8000 字

Agent: 调用工具获取方案 C
Tool: 返回 6000 字

Agent: 开始比较分析

模型需要在上下文中处理这些材料。随着任务推进,后续产生的分析、修改和工具结果又会继续增加上下文长度。

这会带来几个问题:

  • 上下文膨胀:大量历史材料持续占用 Token。
  • 信息难以定位:需要重新查找某项结果时,只能依赖历史消息。
  • 中间结果难以复用:同一份分析需多次重复生成。
  • 任务恢复困难:对话被压缩后,原始细节可能不会再保留。

为了解决上述问题,可引入文件系统(Filesystem)。

引入 Filesystem 后,Agent 可以采用另一种方式:

代码片段Text
/workspace/
├── sources/
│   ├── solution-a.md
│   ├── solution-b.md
│   └── solution-c.md
├── analysis/
│   ├── comparison.md
│   └── risks.md
└── report.md

搜索得到的资料放在 sources/,分析过程放在 analysis/,最终结果写入 report.md。

模型不必在每次推理时都重新读取全部资料。它可以先查看目录,再选择需要的文件或片段。

这里有一个重要区别:Messages 记录 Agent 的交互过程,Filesystem 保存 Agent 的工作内容。

文件系统不会自动减少所有 Token 消耗。只有当 Agent 将信息写入文件,并在后续按需读取时,才能真正减少不必要的上下文占用。

二、Deep Agents 的 Filesystem

Deep Agents 提供的是一套虚拟文件系统接口。

它允许 Agent 使用类似操作系统的方式管理文件,但这些文件不一定存储在本地磁盘上。

整体结构如下:

代码片段Text
             Deep Agent
                 |
                 v
        FilesystemMiddleware
                 |
       +---------+---------+
       |         |         |
    read_file write_file  grep ...
       |         |         |
       +---------+---------+
                 |
                 v
            Backend
                 |
        +--------+--------+
        |        |        |
      State    Store    Local

这里涉及两个关键组件。

1. FilesystemMiddleware:提供操作能力

FilesystemMiddleware 是 Deep Agents 的内置中间件。

它负责向模型提供文件操作工具,处理工具调用,并将实际读写操作交给 Backend。

使用 create_deep_agent() 时,框架默认集成这一能力。

2. Backend:负责文件读写与存储

Backend 决定文件实际保存在哪里。

例如:

  • StateBackend:保存到 LangGraph State。
  • FilesystemBackend:操作真实文件系统。
  • StoreBackend:使用 LangGraph Store。
  • CompositeBackend:根据路径将操作交给不同 Backend。

默认使用 StateBackend()。因此,Agent 写入 /workspace/report.md,并不意味着磁盘上会出现同名文件。

文件路径是 Agent 使用的逻辑地址,实际存储方式由 Backend 决定。

这也是为什么需要把 Filesystem 和 Backend 分开。前者解决如何操作文件,后者解决文件保存在哪里。

三、Filesystem 的核心 API

Deep Agents 提供了一组内置文件工具。

工具主要作用
ls列出目录中的文件
read_file读取文件内容
write_file创建或覆盖文件
edit_file修改文件中的指定内容
glob根据文件名模式查找文件
grep搜索文件内容
delete删除文件或目录
execute执行 Shell 命令,需要支持执行的 Backend

其中,delete 需要 Deep Agents 0.7 或更新版本,并且取决于 Backend 是否支持。execute 也不是普通 Filesystem 默认具备的能力。

这些工具由 Agent 调用,不需要手工注册。

下面的参数示例表示模型发起的工具调用,并非文件对象的方法。

1. ls:了解工作空间

代码片段JSON
{
  "path": "/workspace"
}

调用 ls 后,Agent 可以获得目录下的文件信息,例如名称、大小和修改时间。

实际工作中,Agent 应先了解已有文件,再决定需要读取什么,避免重复生成资料。

2. read_file:按需读取内容

代码片段JSON
{
  "file_path": "/workspace/sources/solution-a.md",
  "offset": 0,
  "limit": 80
}

read_file 支持按行分页读取。

  • file_path:文件路径。
  • offset:从哪一行开始读取。
  • limit:本次读取的行数。

对于几千行的日志或长文档,Agent 可以先读取前面几十行,再根据需要继续读取其他部分。

返回内容包含行号,便于定位资料和修改位置。

3. write_file:创建工作成果

代码片段JSON
{
  "file_path": "/workspace/analysis/summary.md",
  "content": "# 分析结果\n\n方案 A 的实现成本较低。"
}

write_file 用于创建新文件,也可以完全替换已有文件。

需要注意:write_file 不是追加操作。

当目标文件已经存在时,新内容会覆盖原来的内容。因此,对于已经生成的报告,不宜每次修改都重新写入全文。

4. edit_file:局部修改

代码片段JSON
{
  "file_path": "/workspace/analysis/summary.md",
  "old_string": "方案 A 的实现成本较低。",
  "new_string": "方案 A 的初期实现成本较低,但维护成本仍需评估。"
}

edit_file 通过精确字符串匹配完成替换。

默认要求 old_string 在文件中唯一。如果需要替换所有匹配项,可以设置 replace_all=True。

实际使用时,应先通过 read_file 确认原文,再进行修改。否则容易因为空格、换行或内容变化导致匹配失败。

5. glob 与 grep:定位目标文件

当工作空间包含大量文件时,逐个读取效率很低。

glob 根据文件路径模式进行匹配:

代码片段Text
/workspace//*.md

它可以帮助 Agent 找出工作空间中的 Markdown 文件。

grep 则用于搜索文件内容,例如查找包含“风险”或“数据库连接”的文件。

两者的区别很简单:glob 找文件,grep 找内容。

综合起来,上述工具处理顺序是:

代码片段Text
ls / glob
    ↓
grep
    ↓
read_file
    ↓
edit_file

先缩小范围,再读取和修改。这样既减少无效工具调用,也能降低误操作的概率。

四、实战:让 Agent 管理自己的工作文件

我们构建一个简单的需求分析 Agent。

任务是读取两份材料,分别保存原文,提取关键问题,最后生成需求分析报告。

1. 安装依赖

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

同时配置 API KEY。

2. 创建 Agent

代码片段Python
from deepagents import create_deep_agent
from deepagents.backends import StateBackend
from langgraph.checkpoint.memory import MemorySaver
 
 
def get_material(name: str) -> str:
    """读取指定名称的演示材料。"""
    materials = {
        "requirements": (
            "用户希望支持批量导入任务、"
            "任务状态跟踪和失败重试。"
        ),
        "operations": (
            "系统需要保留操作日志,"
            "限制并发任务数量,"
            "并提供失败告警。"
        ),
    }
    return materials.get(name, "未找到材料")
 
 
agent = create_deep_agent(
    model="openai:gpt-5.5",
    tools=[get_material],
    backend=StateBackend(),
    checkpointer=MemorySaver(),
    system_prompt="""
你是一名需求分析助手。
 
工作规范:
1. 使用 get_material 获取原始材料。
2. 将材料分别保存到 /workspace/sources/。
3. 将分析结果保存到 /workspace/analysis.md。
4. 根据分析生成 /workspace/report.md。
5. 修改已有文件前先读取文件。
6. 不要编造原始材料中不存在的事实。
7. 完成后给出报告路径和主要结论。
""",
)

这里有三个重要配置。

tools 注册业务工具,负责获取材料。

backend=StateBackend() 提供虚拟文件存储。

checkpointer=MemorySaver() 在当前进程中保存线程检查点,让相同线程的后续调用能够接着使用之前的状态。

3. 执行任务

代码片段Python
config = {
    "configurable": {
        "thread_id": "analysis-001"
    }
}
 
result = agent.invoke(
    {
        "messages": [{
            "role": "user",
            "content": (
                "分析 requirements 和 operations "
                "两份材料,并形成需求报告。"
            )
        }]
    },
    config=config,
)
 
print(result["messages"][-1].content)

按照系统提示,Agent 应依次获取资料、写入文件、分析并生成报告。

预期的工作空间结构如下:

代码片段Text
/workspace/
├── sources/
│   ├── requirements.md
│   └── operations.md
├── analysis.md
└── report.md

目录中的文件由 Agent 在运行时生成,实际调用顺序取决于模型决策。

4. 在后续对话中复用文件

代码片段Python
result = agent.invoke(
    {
        "messages": [{
            "role": "user",
            "content": (
                "读取 /workspace/report.md,"
                "补充一个实施优先级建议。"
            )
        }]
    },
    config=config,
)
 
print(result["messages"][-1].content)

因为使用相同的 thread_id 和 Checkpointer,Agent 可以继续访问该线程先前保存的文件状态。

这里的 MemorySaver 仅适合开发与演示。进程结束后,这些数据不会自动成为持久化文件。

另外,Agent 是否真的调用了文件工具、是否正确生成报告,需要通过工具调用记录和实际文件状态验证,不能只检查模型的最终回答。

五、工程实践:怎样设计工作空间

有了文件操作能力,不代表 Agent 自己就能有效管理工作内容。

真正影响执行质量的,是文件如何组织、什么时候写入、什么时候读取。

1. 按内容用途划分目录

对于一个 Research Agent,可以采用如下结构:

代码片段Text
/workspace/
├── sources/         # 原始材料
├── notes/           # 阅读笔记
├── analysis/        # 分析结果
├── drafts/          # 报告草稿
└── final/           # 最终成果

这种结构比将所有内容写入一个 research.md 更容易维护。

原始材料通常不应随意修改;分析文件可以反复更新;最终报告则应明确版本。

通过目录划分,可以让 Agent 知道不同文件分别承担什么作用。

2. 区分原始证据和分析结论

例如,研究某个框架性能时,不能只保存:

代码片段Text
框架 A 性能更好。

应该同时保留测试条件:

代码片段Text
测试环境:Python 3.13
并发数量:100
请求数量:10000

框架 A:平均延迟 120ms
框架 B:平均延迟 145ms

以上数值仅为示例。

如果没有原始数据,后续 Agent 无法判断结论是否可靠,也无法在测试条件变化后重新分析。

工程中建议遵循一个原则:原始资料保留证据,分析文件记录判断,最终报告面向交付。

3. 用小文件管理阶段成果

一个复杂任务通常包含多个步骤:

代码片段Text
收集资料
   ↓
整理事实
   ↓
比较方案
   ↓
识别风险
   ↓
形成结论

每个阶段都可以形成独立文件。

例如:

代码片段Text
analysis/
├── facts.md
├── comparison.md
└── risks.md

当某一步出现问题时,只需要重新处理相关文件,而不必重复生成全部内容。

这种设计还方便 Subagent 协作。不同 Subagent 可以负责不同研究方向,将成果写入共享工作空间,主 Agent 再汇总。

不过,共享文件也意味着可能发生写入冲突。并行任务最好各自使用独立路径,由主 Agent 统一合并结果。

六、文件系统如何改善 Context 管理

Filesystem 的另一个重要作用,是与 Context Engineering 配合。

假设某次搜索返回了几万字资料。

使用文件系统后,可采用以下流程:

代码片段Text
工具返回大量内容
        ↓
保存原始结果
        ↓
提取关键内容
        ↓
后续按需读取

Deep Agents 的 FilesystemMiddleware 还支持自动转存过大的工具结果,并用文件路径提示替代完整内容,使 Agent 后续可以通过 read_file 分段读取。

但这里需要区分两件事。

文件存储负责保留信息,Context 管理负责选择当前需要哪些信息。

如果 Agent 每次都把所有文件重新读入上下文,即使使用 Filesystem,也无法解决上下文膨胀问题。

因此,实际工程中应让 Agent 优先查看目录、搜索相关内容,再读取需要部分的内容。

七、易忽略的问题

1. 文件不等于长期记忆

Agent 将内容写入文件,不代表它下次启动时一定能够读取。

默认 StateBackend 的文件保存在当前线程状态中。跨调用恢复依赖 Checkpointer,跨线程共享则需要其他存储方案。

即使文件可以持久化,Agent 也需要知道文件存在,并在合适的时候读取。

因此,Filesystem、Persistence 和 Memory 虽然有关联,但解决的问题不同。

2. 虚拟文件不等于真实磁盘文件

默认 StateBackend 中的 /workspace/report.md 只是虚拟路径。

如果需要让 Agent 处理真实项目文件,可以配置 FilesystemBackend:

代码片段Python
from deepagents.backends import (
    CompositeBackend,
    FilesystemBackend,
    StateBackend,
)
 
backend = CompositeBackend(
    default=StateBackend(),
    routes={
        "/workspace/": FilesystemBackend(
            root_dir="./agent-workspace",
            virtual_mode=True,
        )
    },
)

再将这个 backend 传给 create_deep_agent()。

这样,/workspace/ 下的文件操作会映射到指定的本地目录,而框架内部产生的临时文件仍由默认 StateBackend 管理。

这里也要注意:本地文件操作与 Shell 执行是两种不同能力。使用 FilesystemBackend 不会自动赋予 Agent 执行任意命令的权限。

3. 控制修改和删除权限

write_file 能覆盖文件,delete 可以删除文件甚至递归删除目录。

因此,不能只依赖提示词要求 Agent 小心操作。

对于只需读取资料的任务,可以限制 FilesystemMiddleware 暴露的工具:

代码片段Python
from deepagents.middleware import FilesystemMiddleware
 
filesystem = FilesystemMiddleware(
    backend=backend,
    tools=[
        "read_file",
        "ls",
        "glob",
        "grep",
    ],
)

将该实例传入 create_deep_agent(middleware=[filesystem]),就可以隐藏写入、编辑、删除和执行工具。

这项工具白名单能力需要 Deep Agents 0.7 或更新版本。

对于需要修改真实文件的任务,还应结合路径权限、人工审批以及独立运行环境控制风险。

4. 不要把工作空间当作无限存储

文件虽然不必全部进入模型上下文,但依然存在存储成本。

特别是大量搜索结果、日志和自动转存的工具输出,可能持续积累。

实际系统应关注文件大小、数量、生命周期和清理策略。

临时资料与需要长期保留的成果应采用不同的保存策略,避免工作空间随着任务次数增加而失去可维护性。

总结

Filesystem 是 Deep Agents 处理复杂任务的重要基础能力。

它让 Agent 能够把资料、笔记、分析和最终成果保存为文件,并通过 ls、read_file、write_file、edit_file、glob 和 grep 等工具管理工作内容。

这套机制的价值,在于让任务执行过程中的信息具有明确的位置、结构和复用方式。配合合理的目录设计与按需读取策略,可以减少重复处理,并为长任务和多 Agent 协作提供支持。

不过,文件系统只定义操作方式,不决定数据必须保存在哪里。实际项目还需要选择合适的 Backend,处理持久化、隔离和安全边界。