yugasun
Published on

Agent Harness:AI Agent 可靠性的真正瓶颈在哪里?

Authors
  • avatar
    Name
    Yuga Sun
    Twitter

为什么写这篇文章

OpenAI Codex 团队有一句话在 AI 圈广泛流传:

"Agents aren't hard; the Harness is hard."

这句话在 2026 年被反复引用,原因是它准确命中了一个反直觉的现象:即使在模型推理能力持续飞速提升的今天,AI Agent 在生产环境中的可靠性问题依然普遍存在。大量 Agent 项目失败,不是因为模型不够聪明,而是因为包裹模型的执行环境不够稳健。

这篇文章想回答的问题是:Agent Harness 的核心支柱是什么,每个支柱解决了哪些真实的工程问题,以及主流系统是如何设计这些支柱的?

同一个模型,两种截然不同的结果

给同一个 GPT-4.5 模型完全相同的任务:"重构这个 10 万行的遗留 Python 项目,采用领域驱动设计。"

  • Agent A(无专业 harness):产出 40% 可用代码,陷入死循环 3 次,产生 23 个冲突修改,5 小时后任务失败
  • Agent B(专业 harness):产出 92% 可用代码,2 小时内完成,零冲突,全程没有人工干预

同一个模型,为什么结果天差地别?因为 Agent B 的 harness 提供了四件事:

  1. 结构化任务分解:把"重构 10 万行代码"拆解成可以逐步完成的子任务
  2. 上下文管理:避免 agent 在某个细节上花太多 context,忘记全局目标
  3. 增量验证:每个子任务完成后运行测试,确认进度方向正确
  4. 状态回滚:某个子任务失败时,恢复到上一个已知良好状态,而不是继续构建在错误上

核心结论:模型的推理能力不是瓶颈,支撑模型在长任务中可靠运行的基础设施才是。

什么是 Agent Harness?

如果把 AI 模型比作"大脑",Agent Harness 就是这个大脑的颅骨、神经系统和工作记忆的结合体。它不是模型本身,但它决定了模型如何感知世界、如何采取行动、如何保持跨轮次的一致性。

Agent Harness = 模型之外的一切
                = 意图捕捉 → 规范编译 → 工具执行 → 验证 → 状态持久化

Harness vs Prompt Engineering vs Context Engineering

这三个概念经常被混淆,但它们处于不同的抽象层次:

维度Prompt EngineeringContext EngineeringAgent Harness
关注点提示词措辞上下文内容选择整个执行系统
抽象层级微观(单次交互)中观(单次会话)宏观(系统架构)
核心问题怎么表达更清晰传什么进 context如何可靠运行
影响范围单次 LLM 调用单次会话质量长期可靠性

三者是包含关系:Prompt 和 Context Engineering 是 Harness 内部的两个子问题,Harness 是整体架构。Harness Engineering 正是 2026 年兴起的新学科,它不是要取代前两者,而是为它们提供系统性的运行环境。

五大支柱:每个设计决策背后的原因

支柱一:工具调用系统 — Agent 与外部世界的唯一通道

工具调用是 Agent 能力的边界。没有工具,Agent 只能聊天;有了工具,Agent 才能真正执行操作。

工具系统设计的核心决策是:声明式规范 vs 动态发现

声明式(主流选择):预先定义所有工具的名称、参数、权限需求、描述。模型调用时行为确定可预测。

ToolSpec(
    name="bash",
    description="在 shell 中执行命令,支持 timeout",
    input_schema={
        "command": "string",
        "timeout": "integer (optional, default: 30s)"
    },
    required_permission="DangerFullAccess"
)

ToolSpec(
    name="read_file",
    description="读取文件内容,支持行范围",
    input_schema={
        "path": "string",
        "offset": "integer (optional)",
        "limit": "integer (optional)"
    },
    required_permission="ReadOnly"
)

动态发现:运行时发现可用工具,看似灵活。实际问题:不可预测性、安全风险、难以测试。

工具规范采用声明式的收益是:工具列表可版本化、可 code review、可测试,模型的行为空间有明确边界

Claude Code 的 Deferred Loading:减少 context 开销

声明式工具规范有一个潜在问题:复杂 Agent 可能定义几十个工具,全量传入 schema 会大量消耗 context token,而单次任务实际只会用到其中几个。

Claude Code 的 Deferred Loading 机制解决了这个问题:

实际工程意义:一个拥有 50 个工具的 Agent,如果全量 eager loading,初始 context 开销可能达 10,000+ tokens。Deferred Loading 把这个开销摊薄到首次使用时,大幅降低了工具丰富 Agent 的运行成本。

支柱二:上下文管理系统 — 有限 window 里的无限任务

上下文管理的失败是 Agent 系统最常见的故障模式。核心矛盾:context window 再大(当前主流 200K tokens),真实的长时间任务也可能持续数天、数百轮交互。

最常见的错误处理方式:等到 context 满了才截断。这会导致信息骤降,Agent 突然"忘记"之前的上下文,用户体验崩溃。

正确的做法:渐进式、主动压缩。 压缩应该在 context 还没满时就开始,且对用户完全透明。

压缩层级触发条件压缩策略关键目标
Micro-compact单条消息 > 2KB手术式删减:移除重复信息、verbose 日志保留完整语义
Auto-compact70% window 使用率生成结构化摘要 + 保留最近 N 条消息保留行动痕迹
Session-memory90% window 使用率生成持久化会话记忆文件跨会话连贯性
Reactive最后 10% 空间紧急压缩,可能降低质量防止崩溃

关键工程细节是 Instant Compaction:在 Auto-compact 阶段(70% 时)就启动后台线程提前生成摘要,当 Session-memory 阶段触发时,摘要已经就绪,压缩对用户完全无感:

def _background_compaction_worker(self):
    while True:
        if self.context_usage > 0.7 and self.session_memory is None:
            # 在用户无感知时提前生成摘要
            self.session_memory = self._generate_session_summary()

def _generate_session_summary(self) -> str:
    # 压缩时的优先级:
    # 必须保留:工具调用记录、错误记录、关键决策、用户明确意图
    # 可以删减:冗长中间讨论、已执行的计划草稿、重复确认信息
    return self.model.generate(SESSION_MEMORY_PROMPT)

压缩时保留什么的判断标准:Agent 做了什么比说了什么更重要。

支柱三:错误恢复系统 — 区分概念验证和生产系统的关键

错误处理是最容易被忽视、却最能区分生产级 Agent 和 demo 级 Agent 的组件。在 Agent 系统中,错误处理不只是 try-catch,而是整个执行流程的容错设计。

错误类型分类

错误类型示例处理策略
瞬时错误网络超时、API 限流指数退避重试(最多 3 次)
工具错误bash 命令失败、文件不存在向模型报告错误,让模型调整策略
语义错误模型误解了目标,方向错误回滚到最近检查点
权限错误操作超出当前权限级别拦截 + 提示升级权限或拒绝
不可恢复文件系统损坏、外部服务宕机保存状态,优雅退出

Checkpoint + Rollback 机制是错误恢复的核心。每完成一个有意义的工作单元,就保存一个检查点:

checkpoint = {
    "turn": 47,
    "context_summary": "已完成模块 A 的重构,测试通过",
    "verified_artifacts": [
        "src/auth/__init__.py",
        "tests/test_auth.py",
    ],
    "pending_operations": [],      # 回滚时丢弃
    "git_commit": "abc123",        # 可以 git reset 到这个状态
}

关键设计原则:Agent 应该"保守地前进,激进地回退"。当不确定当前操作是否正确时,宁可回到已知的良好状态,也不要在错误基础上继续叠加修改。这与人类工程师的直觉相反,这正是 Agent 系统需要显式设计回退机制的原因。

支柱四:状态持久化系统 — 让 Agent 具备跨会话连续性

真实任务跨会话是常态:用户周一开始的重构任务,周五还需要继续。如果每次启动 Agent 都是空白大脑,所有上下文都需要重新建立,生产效率大幅下降。

一个结构化的跨会话记忆模板(比原始对话摘要价值高得多):

## 跨会话记忆 — user-service 重构 — 2026-04-09

### 项目目标

重构 user-service,从单体迁移到 DDD 架构,目标完成日期:本周五

### 已完成工作

- [周一] auth 模块重构完成,12 个文件,所有测试通过
- [周二] user profile 模块重构,引入 Value Object 模式
- [周三] 集成测试发现 auth × profile 的依赖问题,已修复

### 当前状态

- 正在处理:payment 模块,已完成 50%
- 遇到问题:外键约束冲突,PostgreSQL 迁移脚本需要调整
- 下一步:修复迁移脚本,运行完整集成测试

### 关键技术决策

- 采用事件溯源模式处理用户状态变更
- PostgreSQL 替代 MongoDB(性能和事务需求)
- 服务间通信统一走 gRPC

### 已知风险

- payment 模块的外键约束问题可能影响数据迁移时间线

为什么结构化记忆比摘要更有价值:摘要记录的是"说了什么",而上面这个模板记录的是"做了什么、决策了什么、遇到了什么问题"。后者才是 Agent 恢复工作状态真正需要的信息。

支柱五:权限与安全系统 — 可用性与安全性的精确平衡

Agent 可以在真实环境执行操作这一事实,使其成为一个潜在的高风险系统。

两种错误设计

  • 过于严格:每一步都询问用户,效率低到无法接受
  • 过于宽松:Agent 可能执行灾难性操作,如 rm -rf / 或覆写生产配置

正确的设计是分级权限 + 默认拒绝

级别能力范围推荐场景为什么设计这一级
ReadOnly仅读取文件和目录生产环境、代码 review最安全的默认值
WorkspaceWrite读写指定工作区受控开发环境限制影响范围
DangerFullAccess完全访问含危险命令本地开发最高效率模式
Prompt每次危险操作前询问审计环境人在环路的安全阀

权限检查流程:

核心设计原则:"默认拒绝,显式允许"。DangerFullAccess 应该是用户主动选择的模式,而不是最省事的默认值。在安全系统设计中,永远不应该让高权限变成阻力最小的选项。

Hook 系统:Harness 的中间件层

Hook 系统是 Agent Harness 可扩展性的核心机制。它允许在不修改任何核心代码的情况下,在工具调用前后插入自定义逻辑。这是**控制反转(IoC)**思想在 Agent 系统中的应用。

Hook 的强大在于组合性:每个 Hook 专注单一职责,通过链式组合实现复杂治理逻辑。

场景 1:自动代码质量检查

每次修改 Python 文件后自动运行 ruff,无需 Agent 主动触发:

{
  "hooks": {
    "PostToolUse": [
      {
        "match": { "tool": "Write", "path": "**/*.py" },
        "type": "command",
        "command": "ruff check {path} --fix && ruff format {path}"
      }
    ]
  }
}

场景 2:危险命令安全拦截

#!/bin/bash
# pre_security_check.sh
DANGEROUS_PATTERNS=("rm -rf /" "curl.*\|.*sh" ":()\{:|:&\};")

for pattern in "${DANGEROUS_PATTERNS[@]}"; do
    if echo "$CLAW_TOOL_INPUT" | grep -qE "$pattern"; then
        echo "SECURITY: Dangerous pattern blocked" >&2
        exit 1  # 非零退出码 = 阻止执行
    fi
done
exit 0

场景 3:架构合规检查

每次修改领域层代码时,触发另一个 Agent 进行架构 review:

{
  "hooks": {
    "PostToolUse": [
      {
        "match": { "tool": "Edit", "path": "**/domain/*.py" },
        "type": "agent",
        "agent": "architect-reviewer",
        "prompt": "检查以下修改是否违反 DDD 分层原则:{diff}"
      }
    ]
  }
}

三个场景覆盖了三个不同的关切点:代码质量、安全防护、架构治理。它们相互独立,通过 Hook 组合而非硬编码实现,治理策略可以独立演化和测试。

Subagent:解决 Context 爆炸的关键策略

当主 Agent 的 context 接近饱和,同时需要并行探索多个子任务时,将子任务委托给 Subagent 是最优解。

假设要分析一个有 20 个模块的大型代码库。主 Agent 顺序探索,每个模块都会消耗 context,很快就会因 context 不足而无法继续。Subagent 的解法:

Subagent 配置的关键点是最小权限原则

AgentConfig(
    description="模块架构分析",
    prompt="分析指定模块的代码结构,输出:1)职责 2)依赖 3)重构建议",
    tools=["Read", "Grep", "Glob"],         # 只读工具
    disallowed_tools=["Bash", "Write"],      # 明确禁止修改
    permission_mode="ReadOnly",              # 权限最小化
    max_turns=30,                            # 避免无限循环
)

缓存优化:多个 Subagent 往往共享相同的 system prompt。这部分内容的 prompt cache 只计算一次,后续所有 Subagent 实例共享,大幅降低 token 成本。

这本质上是 map-reduce 模式:任务分解(map)→ 独立执行 → 结果聚合(reduce)。取舍标准:当主 Agent 的 context 成为瓶颈时,Subagent 协调成本是值得的。

MCP:工具发现的标准化协议

MCP(Model Context Protocol)解决了 AI 模型与工具之间缺乏标准化连接协议的问题。在 MCP 出现之前,每个 Agent 框架都需要为每个工具编写定制集成:

  • 连接 GitHub 需要 GitHub API SDK 的专用适配代码
  • 连接数据库需要数据库 SDK 的专用适配代码
  • 这些集成不可移植,切换 Agent 框架时需要全部重写

MCP 的架构实现了"一次编写,到处使用":

{
  "mcpServers": {
    "filesystem": {
      "type": "stdio",
      "command": "npx @modelcontextprotocol/server-filesystem",
      "args": ["/path/to/workspace"]
    },
    "enterprise-api": {
      "type": "sse",
      "url": "https://api.internal.company.com/mcp",
      "headers": { "Authorization": "Bearer ${TOKEN}" }
    }
  }
}

MCP 的核心价值是工具的可移植性:一个符合 MCP 规范的工具服务,可以被任何支持 MCP 的 Agent 框架使用,无需重写集成代码。

主流实现对比

特性Claude CodeCursorSWE-AgentDevin
工具加载Deferred LoadingEager LoadingEager Loading未知
上下文压缩四级自动渐进基础压缩简单截断未知
权限模型五级分权固定模式未知
Hook 系统完整 Pre/Post部分未知
Subagent原生支持通过 Composer支持未知
会话持久化Session MemoryProject Memory未知
MCP 支持原生插件未知
错误回滚Checkpoint 机制基础未知

Claude Code 在 Harness 层面目前设计最完整,特别是 Deferred Loading 和四级渐进压缩体系,是其他系统尚未充分解决的难题。这不是偶然的——它反映了对 Agent 系统可靠性更深的系统性理解。

核心设计模式总结

模式解决的问题
Deferred Tool Loading大量工具定义导致的 context 初始开销
Progressive Compactioncontext 满了才压缩导致的体验崩溃
Checkpoint + Rollback错误后无法恢复,在错误上继续构建
Permission Pipeline权限粒度粗,无法精细治理危险操作
Hook Chain治理逻辑硬编码进核心,难以扩展和测试
Subagent Fork主 Agent context 爆炸,无法并行处理子任务
Session Memory重启后需要重建所有上下文,降低效率
MCP Integration每个工具需要定制集成代码,不可移植

总结

Agent Harness 是五大支柱组成的执行环境。每个支柱的设计都有明确的工程动机:

  • 工具调用系统:决定 Agent 能干什么,以及能干到什么边界
  • 上下文管理:决定 Agent 能持续工作多久,不会因 context 耗尽崩溃
  • 错误恢复:决定 Agent 在真实环境中是否可靠,而不只是在 demo 里
  • 状态持久化:决定 Agent 是否有连续性记忆,而不是每次从零开始
  • 权限安全:决定 Agent 能否在非受控环境中安全部署

核心判断:Harness 工程是 AI Agent 系统最重要的工程学科,比模型选型更影响长期可靠性。

实践建议:

  1. 先设计 Harness 架构,再选模型。Harness 是基础设施,模型是可替换的组件
  2. 上下文压缩应该是渐进的,70% 时就要开始,不要等到满了
  3. 错误处理要分类:瞬时错误重试,语义错误回滚,权限错误拒绝
  4. 权限遵循"默认拒绝,显式允许",DangerFullAccess 不应是默认值
  5. 用 Hook 系统为治理逻辑预留扩展点,避免把安全和审计逻辑硬编码进核心
  6. 通过 MCP 标准化工具集成,避免重复造轮子,增强工具可移植性

参考资料