首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Harness Engineering:当AI编程的瓶颈从模型能力转向系统设计

Harness Engineering:当AI编程的瓶颈从模型能力转向系统设计

原创
作者头像
用户12502707
发布于 2026-09-26 18:00:28
发布于 2026-09-26 18:00:28
590
举报

一、一个被数据反复验证的事实

2026年,AI编程工具的能力已经毋庸置疑。但一个反直觉的数据正在改变行业对AI工程化的理解:在SWE-bench Lite基准测试上,同样使用GPT-4模型,一套Harness的解题率只有2.7%,另一套则达到28.3%,相差超过10倍-16。

模型没有变,改变的是包裹在模型外面的那层系统。

这个发现并非孤例。LangChain在2025年底的对比实验显示,只优化模型外层的Harness——规则、工具、检查流程——编码基准排名直接从30名开外冲到了前5-1。Anthropic和OpenAI的6个模型在两个基准上的12种对比中,最高成功率的Harness有9种并非来自模型的原厂-。

更值得关注的是OpenAI的内部实践。一个最初3人、后来扩展到7人的团队,从空Git仓库起步,完全禁止人工手写一行代码,用Codex Agent在约5个月内构建出一个供数百内部用户使用的Beta产品,生成近100万行代码,合并约1500个PR,人均日处理3.5个PR,整体效率提升约10倍-8。他们复盘时的一句话点破了核心:早期进展缓慢,不是因为Codex能力不足,而是因为环境定义不充分。Agent缺少工具、抽象和内部结构去推进高层目标-9。

这些数据共同指向一个判断:当模型能力逐渐商品化,围绕模型构建的工程系统——Harness——正在成为决定Agent可靠性与交付质量的分水岭。

二、三代工程范式的演进逻辑

要理解Harness Engineering,需要先理解它从哪来、解决了前两代范式的什么遗留问题。

2023年到2024年,主流关注的是Prompt Engineering——如何把话说对,让模型稳定地朝着预期内容和格式输出。它解决的是大模型无引导、乱说话的问题-29。Prompt Engineering的局限在于,它假设模型只面对单次交互。当AI开始承担多步骤任务时,单次提示词的精心设计无法保证系统级的一致性。

2025年前后,Context Engineering成为焦点。它关注的不再是提示词本身,而是模型在当前时刻“能看到什么信息”——历史对话、检索结果、工具返回、任务状态、工作记忆都被纳入进来,提示词只是上下文的一个组成部分-。Context Engineering引入了召回、压缩、组装三个步骤来动态管理有限的上下文窗口-29。

但Context Engineering也有其结构性失败模式。Context Poisoning(幻觉进入上下文并在后续步骤中反复复制)、Context Distraction(过多细节导致模型丢失焦点)、Context Confusion(无关信息降低响应质量)——这些失败模式在长链路任务中尤为致命-。更根本的问题是,Context Engineering只解决了“给模型看什么”,没有解决“模型能做什么、做错了怎么办”。

Harness Engineering正是在这个缺口上生长出来的。2026年2月,HashiCorp联合创始人Mitchell Hashimoto在个人博客写下定义:“每当发现Agent犯了一个错误,就花时间设计一个方案让它永远不再犯同样的错误”-9。同期,OpenAI工程师Ryan Lopopolo发布内部实验博客,将Harness推向主流工程讨论-9。

三者的关系是嵌套而非替代的。Prompt Engineering决定告诉模型什么,Context Engineering决定模型看到什么,Harness Engineering决定Agent能做什么以及做错了怎么办-9。Context Engineering之所以被Harness包含,是因为上下文本身就是Harness决定“该暴露什么、何时暴露”的产物-9。

三、Harness的三层架构:Control、Agency、Runtime

来自南洋理工大学和阿里巴巴联合实验室的论文《Harness Engineering for Language Agents》将Harness分解为三层结构,审计了63个Harness工作,并提出了HarnessCard作为轻量级报告工件,使Agent的收益能够与Harness效应分离。

Control层是持久存在的制约物。 它包括AGENTS.md、架构规则、linter、权限策略、验收标准。人类的判断在这里被翻译成机器可读的约束。OpenAI团队在百万行实验中使用的一个关键机制就是AGENTS.md文件——他们写了88个AGENTS.md文件来约束Agent行为-。这些文件不是普通的文档,而是Harness的Control层输入,定义了Agent在代码仓库中的行为边界。

Agency层是模型被允许做什么。 这包括代码执行、浏览器交互、文件读写、sub-agent调度。Claude Code暴露了大约19个受权限控制的工具,权限模型分为三个层级:自动批准(只读或本质上安全的操作)、需要确认(可能有副作用的操作)、需要显式授权(高风险操作)-。Agency层的设计质量直接决定了Agent的“可用动作空间”是否合理——空间太小,Agent寸步难行;空间太大,安全风险陡增。

Runtime层是工作展开过程中的动态机制。 包括上下文组装、记忆压缩、断点恢复、审批流程、预算管理、执行轨迹记录。这一层决定长时程任务的成败。一个持续数月、驱动63万行代码库的Claude Code会话记录显示,在长时间运行中,真正致命的不是推理失败,而是记忆失败——知识丢失、重复工作、上下文退化、静默记忆死亡-49。

三层的关系可以用一句话概括:Control定义“什么不能被违反”,Agency定义“什么可以做”,Runtime定义“做的过程中如何保持正确”。缺少任何一层,Agent要么被过度约束而无法推进,要么失控到产生不可逆的损害。

四、一个最小Harness的代码实现

理解了架构,再看一个具体实现。以下是一个Python Harness的核心循环,展示了Control、Agency、Runtime三层如何在代码中协同工作。

代码语言:javascript
复制
# harness.py — 一个最小化的Agent Harness实现
import subprocess
from dataclasses import dataclass, field
from typing import Callable

@dataclass
class HarnessConfig:
    """Control层:持久存在的约束,人类编辑,Agent不可修改"""
    system_prompt: str              # 角色与行为约定
    allowed_tools: list[str]        # 允许调用的工具白名单
    forbidden_patterns: list[str]   # 禁止操作的文件/命令模式
    max_steps: int = 50             # 最大执行步数
    max_budget_tokens: int = 100_000

@dataclass
class HarnessState:
    """Runtime层:跨步骤持久化的状态"""
    history: list[dict] = field(default_factory=list)
    todos: list[str] = field(default_factory=list)
    completed: list[str] = field(default_factory=list)
    error_log: list[str] = field(default_factory=list)

class Harness:
    def __init__(self, config: HarnessConfig, model_client):
        self.config = config
        self.model = model_client
        self.state = HarnessState()

    def run(self, user_input: str) -> str:
        """Agent Loop:规划→执行→观察→反思"""
        self.state.todos = self._plan(user_input)

        for step in range(self.config.max_steps):
            if not self.state.todos:
                break

            task = self.state.todos.pop(0)

            # Control层校验:是否在允许范围内
            if not self._check_constraints(task):
                self.state.error_log.append(
                    f"Blocked: {task} violates constraints"
                )
                continue

            # Agency层:调用模型和工具
            action = self.model.decide(
                system=self.config.system_prompt,
                context=self._build_context(),
                task=task,
                tools=self.config.allowed_tools,
            )

            # Runtime层:执行并记录
            result = self._execute(action)
            self.state.history.append({
                "task": task, "action": action,
                "result": result, "step": step,
            })
            self.state.completed.append(task)

        return self._summarize()

    def _check_constraints(self, task: str) -> bool:
        """Control层:硬约束检查,不可绕过"""
        for pattern in self.config.forbidden_patterns:
            if pattern in task:
                return False
        return True

    def _build_context(self) -> str:
        """Runtime层:上下文组装——只暴露当前步骤需要的信息"""
        recent = self.state.history[-5:]  # 滑动窗口,避免上下文膨胀
        return "\n".join(
            f"Step {h['step']}: {h['action']} → {h['result'][:200]}"
            for h in recent
        )

    def _execute(self, action: dict) -> str:
        """Agency层:在沙箱中执行工具调用"""
        if action["tool"] == "shell":
            result = subprocess.run(
                action["command"], shell=True,
                capture_output=True, timeout=30,
            )
            return result.stdout.decode()[:2000]
        return f"Unknown tool: {action['tool']}"

这段代码的关键设计不在实现细节,而在结构:Control层的约束是硬编码的,模型无法通过提示词绕过;Runtime层的上下文组装是滑动窗口的,防止上下文窗口被历史信息填满;Agency层的工具调用在子进程中执行,天然具备超时和隔离能力。

真实生产环境中的Harness远比这复杂,但结构逻辑一致。OpenAI的Codex Harness包含会话状态管理、流式输出处理、沙箱权限执行、跨回合任务持续性等更完整的机制。Google ADK 2.0的Harness则采用基于图的工作流——校验步骤本身就是图里的路由节点,执行失败会自动把控制流绕回生成节点,不需要在编排代码中手写重试逻辑-。

五、约束层的设计哲学:建议和约束是两回事

Harness Engineering中最容易被忽视但最关键的设计原则,是建议与约束的区分。

“请在提交前运行测试”是一条建议。Agent可能在上下文压力下跳过它。“提交前必须通过make test,否则CI会拒绝合并”是一条约束。两者的区别不在于措辞强度,而在于是否有强制执行机制。

一个值得注意的实证发现来自对Agent指令遵循的研究:在所有模型中,遵循“与先前规则矛盾的指令”的准确率比遵循“全新指令”低3.6到7.4个百分点,平均低5.81个百分点-。这意味着,仅靠AGENTS.md中的文字描述来约束Agent行为是不够的——Agent在长会话中会逐渐偏离初始约束。可验证的约束必须被移到可执行的脚本中-。

这就是为什么Harness的约束层需要“分层落地”。软约束(命名规范、代码风格)可以写在AGENTS.md中,作为建议供Agent参考。硬约束(目录结构、接口契约、安全边界)必须实现为linter规则、CI检查或运行时校验。不可绕过的约束(禁止修改生产配置、禁止执行删除命令)必须在Harness的Agency层直接阻断,连模型看到的机会都不给。

OpenAI的百万行实验中,团队的主要工作就是“让Agent能做有用的事”,也就是不断设计和完善Harness。早期进展缓慢的原因不是模型不够强,而是环境定义不充分——Agent缺少工具、抽象和内部结构去推进高层目标-9。这提示了一个反直觉的结论:Harness Engineering的核心工作不是“限制Agent”,而是“给Agent创造能安全工作的条件”。

六、记忆基础设施:长时程任务中真正致命的失败

当Agent从“单次任务”进入“项目级持续开发”,失败的性质发生了根本变化。一项对633,000行代码库、持续数月使用Claude Code的研究记录了四种致命的记忆失败模式-49。

知识丢失是最隐蔽的一种。上下文压缩会“总结掉”长弧线的连接组织——计划幸存下来了,但“为什么做这个计划”丢失了。Agent恢复时语言流畅但微妙地失去了方向感。重复工作紧随其后:Agent反复提议已经构建完成的子系统,即使相关设计文档就在上下文中。第三种是上下文退化——对前两种问题的朴素补救是注入更多检索到的上下文,但这在反方向上同样失败:仅有时相关的注入块训练人类操作者(和Agent)快速略过它们,一旦通道被学习为噪音,它比不存在更糟。第四种是静默记忆死亡——记忆系统本身(索引、嵌入服务器、钩子管道)悄悄退化或死亡,而所有人都继续信任它。

这四种失败模式指向一个工程结论:长时程Agent的可靠性不取决于模型的推理能力,而取决于记忆子系统的工程化程度。需要的是带鉴别性失败模式的会话启动健康门、设计为“没有枚举的失败模式能不被记录地通过”的心跳遥测,以及借鉴SRE实践的告警疲劳预算-49。

七、Harness的工程边界与失败模式

任何方法论都有其边界,诚实面对边界比夸大适用范围更有价值。

Harness Engineering最根本的边界是:它不解决“做什么”的问题,只解决“怎么做才可靠”的问题。如果规范本身定义了一个错误的目标,Harness会忠实地、可靠地、持续地执行这个错误。Harness的价值在于让偏离更容易被发现——当Agent行为偏离Control层约束时你能立刻知道,当Runtime层检测到重复工作时你能干预。但它不替代人类对目标和方向的判断。

Harness也不总是“越多越好”。一项对Agent Harness敏感性的研究发现了“Harness复杂度悖论”:对于前沿聊天模型,增加Harness的冗长程度反而使任务成功率下降29到38个百分点-。随着模型能力增强,更简单、可预测的Harness设计可能让模型能力得到更充分的发挥-16。这提示了一个重要的设计原则:Harness的复杂度应当与任务复杂度和模型能力匹配,而非无差别地堆叠约束。

一个具体的失败模式来自记忆子系统的设计不当。在一项研究中,Harness的注入层在维护良好的情况下十天精度仪表显示零误

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 一、一个被数据反复验证的事实
  • 二、三代工程范式的演进逻辑
  • 三、Harness的三层架构:Control、Agency、Runtime
  • 四、一个最小Harness的代码实现
  • 五、约束层的设计哲学:建议和约束是两回事
  • 六、记忆基础设施:长时程任务中真正致命的失败
  • 七、Harness的工程边界与失败模式
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档