第 06 章

Harness 能力

Agent Harness 是多种能力的组合,用于简化长时间运行 Agent 的构建

从规划、文件系统、权限、子 Agent 到人工介入——一次搞懂 Harness 全貌

为什么需要它

构建一个长时间运行的 Agent,你面临哪些挑战?

裸写 Agent 的困境

  • 任务多步骤执行,没有结构化的任务追踪
  • 文件读写散落在各处,没有统一的虚拟文件系统
  • Agent 随意读写文件,没有权限控制
  • 大任务塞在一个上下文里,Token 爆了就崩
  • 关键操作没人审批,出了错只能事后补救

Harness 的解法

  • write_todos 维护结构化任务列表,进度一目了然
  • 可插拔后端的虚拟文件系统,统一 ls/read/write
  • 声明式权限规则,首次匹配,按需放行或拒绝
  • 子 Agent 隔离 + 自动压缩摘要,Token 在控制范围内
  • interrupt_on 在关键工具调用前暂停,等人确认
问题核心:长时间运行的 Agent 不是"多调几次 LLM"就够了。你需要任务规划、文件管理、权限控制、上下文压缩、人工审批——这些"工程化"能力全部由 Harness 提供。

Harness 全景

Agent Harness 包含八大核心能力

规划能力

write_todos 维护任务列表,跟踪 pending / in_progress / completed 状态。

虚拟文件系统

可插拔后端,支持 ls、read、write、edit、glob、grep 六大操作。

文件系统权限

声明式规则控制读写,首次匹配生效,保护敏感文件。

任务委派

子 Agent 隔离上下文、可并行、专业化分工、Token 效率更高。

上下文管理

自动压缩、摘要和卸载,让 Agent 在 Token 限制内运行。

代码执行

沙箱后端提供 Shell 环境,解释器提供 QuickJS 运行时。

人工介入

指定工具调用处暂停,等人审批或修改后继续执行。

配置档案

按提供者或模型声明配置包,切换模型不改调用代码。

两大附加能力:Skills(技能)采用渐进式展示,按需加载领域知识;Memory(记忆)始终加载持久化上下文,跨对话保持一致行为。
图:Harness 八大核心能力全景

规划能力

用 write_todos 维护结构化的任务列表

长时间运行的 Agent 需要跟踪自己"做到哪了"。Harness 提供 write_todos 工具,让 Agent 把复杂工作拆成可追踪的步骤。

功能特性

  • 每个任务有三种状态:'pending'、'in_progress'、'completed'
  • 任务列表持久化在 Agent 状态中,不会丢失
  • 帮助 Agent 组织复杂的多步骤工作
  • 适用于长时间运行的任务和规划场景

适用场景

  • 多文件代码重构——追踪每个文件的修改进度
  • 数据处理流水线——追踪每个阶段的状态
  • 研究型任务——追踪每个信息源的调研进度
  • 任何需要"先规划再执行"的复杂任务
核心价值:Agent 不再是"一口气干完"的模式,而是能像人一样列待办、标进度、逐步推进。这让长时间运行的任务变得可控、可观测。
卸甲:上面说"像人一样",这只是帮你理解。实际上 Agent 没有"意识",它只是根据系统提示中的 write_todos 工具描述,在每一步选择调用哪个工具来更新任务列表。这和人脑的任务管理机制完全不同。

虚拟文件系统

可插拔后端提供六大文件系统操作

白话:Agent 要读写文件,总得有个统一的办法。虚拟文件系统就是这套"统一办法"——不管文件存在内存里、磁盘上、还是云端,Agent 都用同一套命令操作。至于背后存在哪,由后端决定。

虚拟文件系统是 Harness 的基础设施,Skills、Memory、代码执行和上下文管理都依赖它。

工具功能使用场景
ls 列出目录中的文件及元数据(大小、修改时间) 浏览项目结构、查找目标文件
read_file 读取文件内容(带行号),支持大文件分页,支持多模态 查看代码、读取文档、查看图片/视频/音频
write_file 创建新文件 生成代码文件、写入配置、保存输出
edit_file 精确字符串替换(支持全局替换) 修改代码中的特定部分、批量重命名
glob 按模式匹配文件(如 **/*.py) 批量查找特定类型的文件
grep 搜索文件内容,支持多种输出模式 查找函数定义、定位 bug 位置
execute 运行 Shell 命令(仅沙箱后端可用) 安装依赖、运行测试、调用 CLI

多模态文件扩展名支持

read_file 对以下扩展名的文件返回多模态内容块而非纯文本:

类型支持的扩展名
图像 .png .jpg .jpeg .gif .webp .heic .heif
视频 .mp4 .mpeg .mov .avi .flv .mpg .webm .wmv .3gpp
音频 .wav .mp3 .aiff .aac .ogg .flac
文档 .pdf .ppt .pptx

隐藏文件工具

用 excluded_tools 对模型隐藏特定工具,而非移除中间件

某些场景下你不希望 Agent 直接操作文件系统。正确做法是通过 Harness 配置档案的 excluded_tools 隐藏工具接口,中间件仍保留在原位。

from deepagents import HarnessProfile, register_harness_profile

# 注册配置档案:对指定模型隐藏所有文件系统工具
# 隐藏工具接口(excluded_tools)而非移除中间件,其他依赖文件系统的功能不受影响
register_harness_profile(
    "anthropic:claude-sonnet-4-6",              # 目标模型:仅对该模型生效
    HarnessProfile(
        excluded_tools=frozenset(               # frozenset 确保配置不可变
            {"ls", "read_file", "write_file", "edit_file", "glob", "grep"}
        ),                                      # 隐藏后模型看不到这些工具,但中间件仍保留
    ),
)

错误做法

  • 通过 excluded_middleware 移除 FilesystemMiddleware
  • 这会破坏 Harness 其他依赖文件系统的能力
  • 可能导致运行时错误,排查困难

正确做法

  • 用 excluded_tools 隐藏模型可见的工具接口
  • 中间件保留在原位,其他功能不受影响
  • 需要时可以通过配置档案随时恢复
设计原则:Harness 的能力之间有依赖关系。隐藏工具接口是"关闭可见性",移除中间件是"拆除基础设施"。前者安全可逆,后者危险不可控。

文件权限

声明式规则控制 Agent 可以读写哪些文件和目录

权限规则在创建 Agent 时通过 permissions= 参数传入,按声明顺序评估,首次匹配生效。

规则结构

  • operations:"read" 或 "write"
  • paths:glob 模式匹配路径
  • mode:"allow" 或 "deny"
  • 如果没有规则匹配,默认允许操作

典型用法

  • 将 Agent 限制在 /workspace/ 目录中
  • 保护敏感文件(如 .env、凭证文件)
  • 为子 Agent 设置比父 Agent 更窄的访问权限
  • 阻止 Agent 修改自身配置或代码
注意:权限规则不适用于沙箱后端——沙箱通过 execute 工具支持任意命令执行,需要使用后端策略钩子来控制。如需自定义验证逻辑,请使用 add_policy_hooks。

任务委派

主 Agent 创建临时子 Agent 处理隔离的多步骤任务

白话:主 Agent 接到一个复杂任务,它不必自己干完所有步骤。它可以调用 task 工具,创建一个"临时工"(子 Agent)去干,自己继续做其他事。临时工干完活只交一份最终报告,中间过程不污染主 Agent 的工作台。

主 Agent 拥有 task 工具,调用时创建一个具有独立上下文的全新 Agent 实例,自主执行完毕后返回单一结果报告。

上下文隔离

子 Agent 的工作不会污染主 Agent 的上下文。大量中间步骤在子 Agent 中消化,主 Agent 只看到最终结果。

并行执行

多个子 Agent 可以并发运行,充分利用计算资源,加快整体任务完成速度。

专业化分工

子 Agent 可以拥有不同的工具和配置。一个做代码审查,一个做测试,各司其职。

Token 效率

大量子任务的上下文被压缩为一个最终报告,主 Agent 的上下文窗口不被撑爆。

子 Agent 是无状态的:它不能发送多条消息,只能执行完毕后返回一份报告。如果你需要多轮交互,应该在主 Agent 层面处理。

不使用子 Agent 运行

在没有 task 工具的情况下运行 Agent

某些场景下你可能不希望 Agent 自行委派任务——例如在简单任务中避免额外开销,或需要完全控制执行流程。

禁用方式

  • 通过 HarnessProfile 的 excluded_tools 移除 task 工具
  • 不要通过 subagents= 传入同步子 Agent
  • 异步子 Agent 不受影响,仍然正常工作

禁止的做法

  • 不要尝试通过 excluded_middleware 移除 SubAgentMiddleware
  • 这是被故意禁止的——移除中间件会破坏 Harness 的其他依赖
  • 正确做法是隐藏工具接口,而非拆除底层中间件
设计原则:与隐藏文件系统工具的思路一致——用 excluded_tools 关闭"可见性",而非用 excluded_middleware 拆除"基础设施"。异步子 Agent 不受同步子 Agent 配置的影响,仍然可以正常使用。

上下文管理

在 Token 限制内处理长时间运行任务,同时保留关键信息

Harness 自动管理上下文,使 Deep Agent 能够在 Token 限制内持续工作。四大机制协同运作:

输入上下文

系统提示、Memory、Skills 和工具提示共同塑造 Agent 启动时的知识范围。这些构成了 Agent 的"初始认知"。

自动压缩

内置的卸载和摘要功能让上下文在任务执行过程中始终在窗口限制内。旧信息被摘要,新信息保留原样。

子 Agent 隔离

繁重的工作被隔离在子 Agent 中,仅返回结果给主 Agent。这是最有效的上下文压缩手段。

长期记忆

通过虚拟文件系统实现跨线程的持久化存储。Agent 在不同对话中可以访问之前积累的知识。

核心价值:支持超过单个上下文窗口的多步骤任务,保持最相关的信息在作用域内,无需手动裁剪。通过自动摘要和卸载大幅减少 Token 消耗。
图:四大上下文管理协作流程

代码执行

两种执行方式:沙箱后端(Shell)和解释器(QuickJS)

沙箱后端 — execute 工具

  • 在隔离环境中执行 Shell 命令
  • 支持安装依赖、运行测试、调用 CLI
  • 可访问操作系统文件系统
  • 实现 SandboxBackendProtocolV2 时自动启用
  • 适合:需要完整系统操作能力的场景

解释器 — eval 工具

  • 在限定的 QuickJS 运行时中运行 JavaScript
  • 不支持 Shell 访问、包安装
  • 不支持文件系统和网络访问
  • 确定性执行,安全可控
  • 适合:循环、批量处理、数据转换
// 选择指南:
// - 需要安装依赖、运行测试 → 沙箱后端
// - 需要循环处理、数据转换 → 解释器
// - 需要编程式工具调用     → 解释器
// - 需要操作系统文件系统   → 沙箱后端
安全提示:沙箱后端提供的是隔离环境,但仍可执行任意 Shell 命令。在生产环境中,务必配合权限规则和策略钩子使用,限制可执行的命令范围。
图:沙箱与解释器双轨执行

人工介入

在指定工具调用处暂停执行,等待人工审批或修改

Harness 可以在特定工具调用前暂停 Agent,让人工确认后才继续。这个功能通过 interrupt_on 参数启用。

from deepagents import create_deep_agent

# 在指定工具调用前暂停 Agent,等待人工审批后继续
agent = create_deep_agent(
    model="anthropic:claude-sonnet-4-6",
    interrupt_on={
        "edit_file": True,   # 每次编辑文件前暂停(支持审批/拒绝/编辑参数)
        "write_file": True,  # 每次写入文件前暂停
    }
)

配置方式

  • 将 interrupt_on 传给 create_deep_agent
  • 参数是工具名称到中断配置的映射
  • 暂停后可以提供审批消息或修改工具输入

适用场景

  • 为破坏性操作设置安全门控
  • 执行昂贵 API 调用前的用户验证
  • 交互式调试和实时指导 Agent 行为
按需启用:人工介入不是全有或全无。你可以只对特定工具启用,让 Agent 在高风险操作前停下来,低风险操作自动执行。

技能系统

渐进式加载的领域知识和专门工作流

Skills 遵循 Agent Skills 标准,每个技能是一个包含 SKILL.md 的目录,提供指令、元数据和附加资源。

渐进式展示

  • Agent 启动时只读取 SKILL.md 的 frontmatter
  • 判断对当前任务有用时才加载完整内容
  • 不相关的技能不消耗 Token

与 Memory 的区别

  • Memory 始终加载,Skill 按需加载
  • Memory 存偏好和约定,Skill 存操作指南
  • Memory 跨对话持久化,Skill 提供即时能力

技能内容

  • SKILL.md 包含指令和元数据
  • 可包含额外脚本和参考文档
  • 可包含模板和其他资源文件

核心优势

  • 按需加载,减少 Token 消耗
  • 模块化、可复用的 Agent 能力
  • 提供专业知识而不污染系统提示

记忆系统

持久化上下文文件,跨对话保持一致的 Agent 行为

Memory 文件通常包含编码风格、偏好设置、约定和指南,帮助 Agent 理解你的代码库并遵循偏好。

// Memory 使用 AGENTS.md 文件格式
// 记忆文件在每次调用时都会加载(与 Skills 的按需加载不同)
const agent = create_deep_agent({
    model: "anthropic:claude-sonnet-4-6",
    memory: [
        "./AGENTS.md",             // 项目级偏好(编码风格、常用命令等)
        "./docs/conventions.md",   // 编码约定(命名规则、目录结构等)
    ]
});

工作原理

  • 使用 AGENTS.md 文件提供持久化上下文
  • 记忆文件始终被加载(与 Skills 的渐进式不同)
  • 文件存储在 Agent 的后端中
  • Agent 可以根据交互更新记忆

典型内容

  • 用户偏好:语言风格、代码风格
  • 项目指南:架构约定、命名规则
  • 领域知识:业务术语、常用模式
  • 反馈积累:Agent 从交互中学到的经验
始终可用:与 Skills 的"按需加载"不同,Memory 文件在每次对话中都完整加载,确保 Agent 行为在不同会话间保持一致。适用于"每次都需要知道"的信息。

配置档案

按提供者或模型声明配置包,切换模型不改代码

Harness 配置档案(HarnessProfile)是声明式的配置包,在模型确定后自动应用。你不需要为每个 Agent 单独写设置代码。

from deepagents import HarnessProfile, register_harness_profile

# 提供者级别配置——对 openai 的所有模型生效
register_harness_profile(
    "openai",                                   # 只写提供者名称,不指定具体模型
    HarnessProfile(
        system_prompt_adjustment="请用简洁的中文回答。",  # 追加到系统提示末尾
        excluded_tools=frozenset({"execute"}),           # 所有 openai 模型都禁用 Shell 执行
    )
)

# 模型级别配置——仅对特定模型生效,会与提供者级别配置合并
register_harness_profile(
    "openai:gpt-5.4",                           # 提供者:模型 格式,更精细的控制
    HarnessProfile(
        system_prompt_adjustment="你是一个专业的代码审查助手。",  # 覆盖提供者级别的调整
    )
)

工作原理

  • 以提供者名称或 provider:model 键注册
  • create_deep_agent 自动查找并应用
  • 提供者级和模型级配置合并生效

核心用途

  • 集中管理默认配置和工具覆盖
  • 切换模型时调用代码保持不变
  • 通过入口点发布可复用的配置插件

本章回顾

Harness 是长时间运行 Agent 的工程化基础设施

八大核心能力

  • 规划:write_todos 追踪任务状态
  • 文件系统:可插拔后端的六大操作
  • 权限:声明式规则,首次匹配
  • 子 Agent:上下文隔离、并行执行
  • 上下文管理:自动压缩、长期记忆
  • 代码执行:沙箱 + 解释器双模式
  • 人工介入:按工具粒度的审批门控
  • 配置档案:声明式、可合并的配置包

两个附加能力

  • Skills(技能):渐进式展示,按需加载领域知识和工作流。用 SKILL.md 定义,只在相关时才加载。
  • Memory(记忆):始终加载的持久化上下文。用 AGENTS.md 定义,跨对话保持一致行为。

后续章节预告

  • 模型选择与配置
  • 上下文工程深入
  • 后端系统详解
  • 子 Agent 高级用法
  • 沙箱与解释器
  • 权限与安全
核心结论:Harness 不是让 Agent "更聪明",而是让 Agent "更可控"。它提供的规划、权限、上下文管理、人工介入等能力,让长时间运行的 Agent 从"能跑"变成"可靠运行"。