📚 什么是 Harness?

Harness(代理框架)是 DeepAgents 的运行时环境, 它不是一个简单的框架,而是一个完整的生产级 Agent 执行引擎

💡 Harness 核心特性
特性 说明 应用场景
文件系统工具 6 个内置文件操作工具 文档处理、代码工作
大结果驱逐 自动管理超大工具输出(20,000 Token) 避免上下文溢出
存储抽象 4 种可插拔存储后端 临时数据 + 持久化
子代理委派 通过 task 工具创建专门化 Agent 任务分解、并行执行
历史摘要 170,000 Token 自动压缩对话历史 长期运行 Agent
工具调用修复 检测并修复悬空工具调用 保证对话连贯性
待办列表 write_todos 工具追踪任务进度 复杂工作流管理
人工介入 特定工具调用前暂停等待审批 安全门控、成本控制
提示词缓存 Anthropic 模型缓存系统提示词 10 倍加速和成本降低
✨ Harness 核心理念

Harness 实现了"标准工具调用循环 + 生产级增强"的理念:

  • 核心循环:标准的请求 → 工具调用 → 结果处理
  • 增强层:自动结果监控、Token 管理、上下文优化、错误恢复
  • 存储抽象:可插拔的后端策略,无需改代码即可切换

🏗️ Harness 架构

Harness 采用分层架构,在标准 Agent 执行循环之上 添加了多个增强层:

graph TB User["用户请求"] --> Core["核心工具调用循环
Agent 执行引擎"] Core --> Enhance["增强层"] Enhance --> FileTools["文件系统工具
ls, read, write, edit, glob, grep"] Enhance --> ResultEviction["大结果驱逐
>20K Token 自动写入存储"] Enhance --> History["历史摘要
170K Token 自动压缩"] Enhance --> Repair["工具调用修复
悬空调用处理"] FileTools --> Storage["存储抽象层"] ResultEviction --> Storage Storage --> State["StateBackend
内存存储"] Storage --> FS["FilesystemBackend
磁盘存储"] Storage --> Store["StoreBackend
持久化存储"] Storage --> Composite["CompositeBackend
混合路由"] Core --> Advanced["高级特性"] Advanced --> Subagents["子代理委派
task 工具"] Advanced --> HITL["人工介入
审批门控"] Advanced --> Caching["提示词缓存
Anthropic 加速"] Advanced --> Todos["待办列表
write_todos"] style Core fill:#3b82f6,color:#fff style Enhance fill:#10b981,color:#fff style Storage fill:#f59e0b,color:#fff style Advanced fill:#8b5cf6,color:#fff

📁 文件系统工具

Harness 提供6 个内置文件操作工具,让 Agent 可以 像操作本地文件系统一样管理数据:

工具 功能 典型用途
ls 列出目录内容(带元数据) 浏览文件结构、查看大小和修改时间
read_file 读取文件内容(带行号和偏移) 加载已保存的搜索结果、读取中间数据
write_file 创建新文件 保存大量工具输出、临时数据
edit_file 精确字符串替换(支持全局替换) 修改配置、更新已保存数据
glob 基于模式的文件发现 查找特定类型的文件(*.txt, **/*.json)
grep 内容搜索(多种输出模式) 在文件中搜索关键字、提取信息
Python 🟢 基础
"""
文件系统工具 - Agent 自动使用示例
"""
from deepagents import create_deep_agent

# 创建 Agent(文件系统工具自动可用)
agent = create_deep_agent(
    model="gpt-4o",
    system_prompt="""你是数据分析助手。你可以:

1. 使用 write_file 保存大量搜索结果
2. 使用 read_file 加载已保存的数据进行分析
3. 使用 ls 查看已保存的文件
4. 使用 edit_file 更新数据
5. 使用 glob 查找特定文件
6. 使用 grep 搜索文件内容

工作流程:
- 收集数据 → write_file 保存
- 分析数据 → read_file 读取
- 更新数据 → edit_file 修改
"""
)

# Agent 会自动使用文件工具管理数据
result = agent.invoke({
    "messages": [{
        "role": "user",
        "content": "收集 2024 年 AI 研究的最新进展,保存到文件,然后分析趋势"
    }]
})

# Agent 执行流程:
# 1. 使用网络搜索收集信息
# 2. 使用 write_file 保存大量数据(避免上下文溢出)
# 3. 使用 read_file 逐步读取和分析
# 4. 生成最终报告

💾 存储后端

Harness 提供4 种可插拔的存储后端, 支持不同的数据持久化策略:

1. StateBackend(内存存储)

临时内存存储,数据保存在 Agent 状态中, 随对话一起 checkpoint。

Python 🟢 基础
"""
StateBackend - 内存存储(默认)
"""
from deepagents import create_deep_agent
from deepagents.harness import StateBackend

agent = create_deep_agent(
    model="gpt-4o",
    storage_backend=StateBackend()  # 数据保存在内存中
)

# 特点:
# - 数据随对话状态一起 checkpoint
# - 对话结束后数据消失
# - 适用于临时工作空间

2. FilesystemBackend(磁盘存储)

真实磁盘访问,支持路径验证、大小限制、 symlink 防护等安全特性。

Python 🟡 中级
"""
FilesystemBackend - 磁盘存储
"""
from deepagents.harness import FilesystemBackend

agent = create_deep_agent(
    model="gpt-4o",
    storage_backend=FilesystemBackend(
        root_path="/data/agent_workspace",  # 根目录
        max_file_size=10 * 1024 * 1024,     # 10MB 限制
        allow_symlinks=False                # 禁止符号链接
    )
)

# 特点:
# - 数据持久化到磁盘
# - 跨对话数据共享
# - 路径验证和安全检查
# - 适用于需要真实文件操作的场景

3. StoreBackend(持久化存储)

跨对话持久化,使用 LangGraph 的 BaseStore, 支持数据库存储。

Python 🟡 中级
"""
StoreBackend - 持久化存储
"""
from deepagents.harness import StoreBackend
from langgraph.store.memory import InMemoryStore

# 创建持久化 store
store = InMemoryStore()  # 可替换为 PostgresStore 等

agent = create_deep_agent(
    model="gpt-4o",
    storage_backend=StoreBackend(store=store)
)

# 特点:
# - 跨对话数据持久化
# - 支持数据库后端
# - 适用于知识库、长期记忆

4. CompositeBackend(混合路由)

最灵活的方案,根据路径前缀将不同路径路由到 不同的后端。

Python 🔴 高级
"""
CompositeBackend - 混合路由策略
"""
from deepagents.harness import (
    CompositeBackend,
    StateBackend,
    StoreBackend,
    FilesystemBackend
)

# 创建混合后端
composite = CompositeBackend(
    backends={
        "/tmp": StateBackend(),              # 临时数据 → 内存
        "/knowledge": StoreBackend(store),   # 知识库 → 持久化
        "/workspace": FilesystemBackend(root_path="/data")  # 工作区 → 磁盘
    },
    default_backend=StateBackend()  # 默认使用内存
)

agent = create_deep_agent(
    model="gpt-4o",
    storage_backend=composite
)

# 使用示例:
# - write_file("/tmp/search_results.txt", ...)    → 内存
# - write_file("/knowledge/faq.txt", ...)         → 持久化
# - write_file("/workspace/report.pdf", ...)      → 磁盘
# - write_file("other.txt", ...)                  → 默认内存
✨ 后端选择建议
后端 适用场景 数据生命周期
StateBackend 临时工作空间、单次对话 对话结束后消失
FilesystemBackend 真实文件操作、代码工作 持久化,手动删除
StoreBackend 知识库、跨对话共享 永久持久化
CompositeBackend 混合场景(推荐) 按路径分类

🔄 大结果驱逐

当工具输出超过20,000 Token时,Harness 会 自动将结果写入存储,并用文件引用替换原始输出。

graph LR Tool["工具调用
返回大量数据"] --> Check{"结果大小
> 20K Token?"} Check -->|否| Direct["直接返回
结果"] Check -->|是| Evict["驱逐到存储
write_file(data)"] Evict --> Replace["替换为引用
'结果已保存到 file.txt'"] Replace --> Agent["Agent 继续执行
需要时 read_file()"] Direct --> Agent style Tool fill:#3b82f6,color:#fff style Check fill:#f59e0b,color:#fff style Evict fill:#ef4444,color:#fff style Replace fill:#10b981,color:#fff
Python 🟡 中级
"""
大结果驱逐 - 自动管理
"""
from deepagents import create_deep_agent

# 场景:搜索工具返回大量结果
def massive_search(query: str) -> str:
    """搜索工具,可能返回超大结果"""
    # 假设返回 50,000 Token 的结果
    results = search_api(query, max_results=1000)
    return "\n".join([f"{i}. {r}" for i, r in enumerate(results)])

agent = create_deep_agent(
    model="gpt-4o",
    tools=[massive_search]
)

result = agent.invoke({
    "messages": [{
        "role": "user",
        "content": "搜索所有关于 LangChain 的文档"
    }]
})

# 执行过程:
# 1. Agent 调用 massive_search 工具
# 2. 工具返回 50,000 Token 的结果
# 3. Harness 检测到超过 20,000 Token 阈值
# 4. 自动执行 write_file("search_results.txt", data)
# 5. 将工具消息替换为:"搜索结果已保存到 search_results.txt"
# 6. Agent 看到文件引用,可以后续使用 read_file 读取

# 优势:
# - 避免上下文窗口溢出
# - Agent 可以选择性地读取部分数据
# - 自动化,无需手动管理

👥 子代理委派

主 Agent 可以使用内置的task 工具创建 独立的子代理来执行专门化任务。

Python 🔴 高级
"""
子代理委派 - task 工具使用
"""
from deepagents import create_deep_agent

# 主 Agent 的系统提示词
main_prompt = """你是项目经理 Agent。你可以:

1. 使用 task 工具委派专门化任务给子 Agent
2. 子 Agent 会独立执行,返回压缩的结果
3. 你可以并行创建多个子 Agent

示例:
- task("研究 LangChain 架构", agent_type="researcher")
- task("编写代码示例", agent_type="coder")
- task("生成测试用例", agent_type="tester")

每个子 Agent 都有独立的上下文,不会污染主 Agent 的对话历史。
"""

agent = create_deep_agent(
    model="gpt-4o",
    system_prompt=main_prompt
)

# 使用 Agent
result = agent.invoke({
    "messages": [{
        "role": "user",
        "content": """创建一个完整的 LangChain RAG 项目:
        1. 研究 RAG 最佳实践
        2. 编写代码实现
        3. 生成测试用例
        """
    }]
})

# Agent 执行流程:
# 1. 主 Agent 分析任务
# 2. 调用 task("研究 RAG 最佳实践", agent_type="researcher")
#    → 子 Agent 1 独立执行研究任务
#    → 返回压缩的研究报告
# 3. 调用 task("编写 RAG 代码", agent_type="coder", context="研究结果...")
#    → 子 Agent 2 独立编写代码
#    → 返回代码
# 4. 调用 task("生成测试用例", agent_type="tester", code="...")
#    → 子 Agent 3 生成测试
#    → 返回测试用例
# 5. 主 Agent 整合所有子 Agent 的结果,生成最终输出

# 优势:
# - 上下文隔离:每个子 Agent 有独立的对话历史
# - 并行执行:可以同时运行多个子 Agent
# - 专门化:每个子 Agent 专注于特定任务
# - Token 效率:子 Agent 返回压缩结果,节省主 Agent 上下文
✨ 子代理使用建议
  • 独立任务:适合可以独立完成的任务(研究、编码、测试)
  • 上下文隔离:子 Agent 不会污染主 Agent 的对话历史
  • 并行执行:多个子 Agent 可以同时运行,提升效率
  • 压缩返回:子 Agent 只返回关键结果,节省 Token

📝 对话历史摘要

当对话历史超过170,000 Token时,Harness 会 自动压缩旧消息,保留最近 6 条消息不变。

Python 🟢 基础
"""
历史摘要 - 自动压缩
"""
from deepagents import create_deep_agent

agent = create_deep_agent(
    model="gpt-4o",
    system_prompt="你是长期运行的助手"
)

# 长期运行的对话
for i in range(100):
    result = agent.invoke({
        "messages": [{
            "role": "user",
            "content": f"任务 {i}: 执行一些复杂的操作"
        }]
    })

# 执行过程:
# 1. 对话不断积累消息
# 2. 当达到 170,000 Token 时,Harness 触发摘要
# 3. 保留最近 6 条消息不变
# 4. 旧消息被压缩成摘要:"前 94 个任务的总结..."
# 5. 继续执行,上下文保持可控

# 配置(可选):
# - 摘要触发阈值:170,000 Token(默认)
# - 保留最近消息数:6 条(默认)
# - 摘要由模型生成,确保关键信息不丢失

🔧 悬空工具调用修复

Harness 会检测AIMessage 包含 tool_calls 但没有对应的 ToolMessage 的情况,并自动创建合成响应。

Python 🟡 中级
"""
工具调用修复 - 自动处理
"""
# 场景:Agent 中断或错误导致工具调用没有响应

# 错误的对话序列:
# 1. HumanMessage: "搜索 LangChain"
# 2. AIMessage: tool_calls=[search("LangChain")]
# 3. [中断,没有 ToolMessage]
# 4. HumanMessage: "继续"

# Harness 自动修复:
# 1. 检测到 AIMessage 有 tool_calls 但没有响应
# 2. 创建合成 ToolMessage: "工具调用被中断,请重试"
# 3. 对话序列变为完整:
#    - HumanMessage: "搜索 LangChain"
#    - AIMessage: tool_calls=[search("LangChain")]
#    - ToolMessage: "工具调用被中断,请重试" [合成]
#    - HumanMessage: "继续"
# 4. Agent 可以正常继续执行

# 优势:
# - 保证对话序列的完整性
# - 避免模型混淆
# - 自动恢复错误状态

✅ 待办列表追踪

Agent 可以使用write_todos 工具维护结构化的 任务列表,追踪复杂工作流的进度。

Python 🟡 中级
"""
待办列表 - write_todos 工具
"""
from deepagents import create_deep_agent

agent = create_deep_agent(
    model="gpt-4o",
    system_prompt="""你是项目管理助手。使用 write_todos 工具追踪任务进度。

任务状态:
- pending: 待处理
- in_progress: 进行中
- completed: 已完成

工作流程:
1. 收到任务后,使用 write_todos 创建任务列表
2. 开始任务时,更新状态为 in_progress
3. 完成任务后,更新状态为 completed
"""
)

result = agent.invoke({
    "messages": [{
        "role": "user",
        "content": "创建一个完整的 Web 应用:前端、后端、数据库、部署"
    }]
})

# Agent 执行过程:
# 1. 调用 write_todos:
#    [
#        {"task": "设计数据库 schema", "status": "pending"},
#        {"task": "实现后端 API", "status": "pending"},
#        {"task": "开发前端界面", "status": "pending"},
#        {"task": "配置部署", "status": "pending"}
#    ]
#
# 2. 开始第一个任务,更新:
#    [
#        {"task": "设计数据库 schema", "status": "in_progress"},
#        ...
#    ]
#
# 3. 完成第一个任务,更新:
#    [
#        {"task": "设计数据库 schema", "status": "completed"},
#        {"task": "实现后端 API", "status": "in_progress"},
#        ...
#    ]
#
# 4. 循环执行,直到所有任务完成

# 优势:
# - 结构化追踪复杂工作流
# - 用户可见任务进度
# - Agent 可以根据任务状态决策

👤 人工介入(HITL)

配置 Harness 在特定工具调用前暂停并等待人工审批, 实现安全门控和成本控制。

Python 🔴 高级
"""
人工介入 - HITL 配置
"""
from deepagents import create_deep_agent

# 定义需要审批的工具
def delete_file(path: str) -> str:
    """删除文件(危险操作)"""
    import os
    os.remove(path)
    return f"已删除文件:{path}"

def expensive_api_call(query: str) -> str:
    """调用昂贵的 API"""
    # 假设这是一个每次调用花费 $10 的 API
    return external_api.query(query)

agent = create_deep_agent(
    model="gpt-4o",
    tools=[delete_file, expensive_api_call],
    # 配置人工介入
    interrupt_before=["delete_file", "expensive_api_call"],
    system_prompt="你是文件管理和数据查询助手"
)

# 使用 Agent
result = agent.invoke({
    "messages": [{
        "role": "user",
        "content": "清理临时文件,并查询最新数据"
    }]
})

# 执行流程:
# 1. Agent 决定调用 delete_file("/tmp/cache")
# 2. Harness 检测到 interrupt_before 配置
# 3. 暂停执行,返回中断信号
# 4. 用户审批或拒绝:
#    - 审批:agent.resume() 继续执行
#    - 拒绝:agent.cancel() 取消操作
# 5. 继续执行后续任务

# 审批示例:
if result.get("interrupt"):
    print(f"Agent 请求执行:{result['next_tool_call']}")
    approval = input("是否批准?(y/n): ")

    if approval.lower() == "y":
        result = agent.resume()
    else:
        result = agent.cancel("用户拒绝操作")

# 应用场景:
# - 危险操作(删除、修改生产数据)
# - 昂贵的 API 调用
# - 需要人工判断的决策

⚡ 提示词缓存(Anthropic)

对于 Anthropic 模型,Harness 会自动缓存系统提示词, 实现10 倍加速和成本降低

Python 🟢 基础
"""
提示词缓存 - 自动启用(Anthropic)
"""
from deepagents import create_deep_agent

# 使用 Anthropic 模型时自动启用缓存
agent = create_deep_agent(
    model="claude-sonnet-4-5-20250929",  # Anthropic 模型
    system_prompt="""你是专业的代码审查助手...

    [非常长的系统提示词,包含详细的审查标准、代码规范、输出格式等]

    总共 5000+ Token 的系统提示词
    """
)

# 第一次调用:系统提示词被缓存
result1 = agent.invoke({
    "messages": [{"role": "user", "content": "审查这段代码..."}]
})

# 第二次调用:直接使用缓存,10 倍加速
result2 = agent.invoke({
    "messages": [{"role": "user", "content": "审查另一段代码..."}]
})

# 效果:
# - 第一次调用:正常速度和成本
# - 后续调用:
#   - 延迟降低 ~90%(10 倍加速)
#   - 成本降低 ~90%(系统提示词不重复计费)

# 注意:
# - 仅适用于 Anthropic Claude 模型
# - 缓存有效期:5 分钟(Anthropic 限制)
# - 系统提示词必须保持不变才能使用缓存

✨ Harness 最佳实践

1. 存储策略选择

  • 推荐使用 CompositeBackend:灵活路由不同类型的数据
  • 临时数据 → StateBackend(内存)
  • 知识库 → StoreBackend(持久化)
  • 真实文件操作 → FilesystemBackend(磁盘)

2. Token 管理

  • 信任大结果驱逐:让 Harness 自动管理超大输出
  • 使用子代理:隔离上下文,避免主 Agent 污染
  • 历史摘要:对长期运行的 Agent 自动生效

3. 安全和成本控制

  • 配置 interrupt_before:为危险/昂贵操作添加人工审批
  • FilesystemBackend 安全:设置 max_file_size、禁用 symlinks
  • 监控 Token 使用:配合 LangSmith 追踪

4. 性能优化

  • Anthropic 模型:启用提示词缓存,10 倍加速
  • 并行子代理:使用 task 工具并行执行独立任务
  • 适时使用文件工具:避免重复传输大量数据

❓ 常见问题

Q1: Harness 和普通 Agent 有什么区别?

特性 普通 Agent Harness(DeepAgent)
文件操作 需要手动定义工具 6 个内置工具
大结果处理 上下文溢出风险 自动驱逐到存储
子代理 不支持 内置 task 工具
历史管理 手动处理 自动摘要压缩
错误恢复 需要手动处理 自动修复悬空调用

Q2: 如何选择存储后端?

推荐使用 CompositeBackend,根据数据类型路由:

Python
# 推荐配置
composite = CompositeBackend({
    "/tmp": StateBackend(),          # 临时数据
    "/knowledge": StoreBackend(),    # 永久知识库
    "/workspace": FilesystemBackend()  # 真实文件
})

Q3: 大结果驱逐的阈值可以调整吗?

当前为固定值 20,000 Token。如需调整, 需要自定义 Harness 配置(高级用法)。

Q4: 子代理会消耗更多成本吗?

,每个子代理都是独立的模型调用。但由于:

  • 子代理上下文隔离,避免主 Agent 上下文膨胀
  • 子代理返回压缩结果,节省 Token
  • 可以并行执行,提升效率

总体上成本效益更高

Q5: 人工介入会阻塞 Agent 执行吗?

是的。配置 interrupt_before 的工具调用会暂停执行, 需要调用 agent.resume()agent.cancel() 才能继续。 这是设计行为,用于安全门控。

📖 参考资源