什么是Harness?为什么它如此重要?
在Lilian Weng的定义中,Harness是包裹基础模型的系统层,负责编排执行、决定模型如何思考和规划、调用工具和行动、感知和管理上下文、存储产物、评估结果。简单来说,如果模型是"大脑",Harness就是周围的"神经系统"——它决定了大脑如何感知世界、如何行动、如何记忆、如何反思。
这一概念之所以重要,是因为当今最成功的AI Agent产品——Claude Code、Codex、Cursor等——其核心竞争力并不完全来自底层模型,而更多来自精心设计的Harness。同一个GPT-5或Claude模型,配上不同的Harness,可以产生数量级差异的效果。
图:Agent Harness完整架构,模型权重冻结,所有优化发生在Harness层
递归自我改进的新路径
Lilian Weng从I. J. Good在1965年提出的"智能爆炸"概念出发,追溯了从Yudkowsky 2008年的递归自我改进(RSI)框架到当今Agent实践的思想脉络。但她的核心贡献在于重新定义了RSI的近期实现路径。
传统理解中的RSI,意味着AI系统直接修改自己的权重或训练流程——这在当前技术条件下既不现实也充满风险。Weng提出了一个更务实的中介路径:
这三个层次中,改进Harness是投入产出比最高、风险最低、可操作性最强的路径。原因很简单:它不需要修改模型权重,不需要重新训练,可以在运行时动态调整,且改进效果可以被立即验证。
Harness的六大核心组件
基于Weng的分析和当前最先进的Agent产品实践,一个完整的Harness包含六个核心组件:
1. 规划器(Planner)
规划器负责将用户的自然语言请求分解为可执行的子任务序列。好的规划器不是简单的任务拆分,而是考虑任务间的依赖关系、资源约束和失败恢复策略。
class Planner:
def __init__(self, model_client, max_depth=5):
self.model = model_client
self.max_depth = max_depth
def plan(self, task: str, context: dict) -> list[Task]:
prompt = f"""
任务: {task}
上下文: {json.dumps(context)}
将此任务分解为子任务。要求:
1. 每个子任务必须可独立验证
2. 标注子任务间的依赖关系
3. 为每个子任务提供回滚策略
4. 最多{self.max_depth}层嵌套
"""
response = self.model.complete(prompt)
return self._parse_tasks(response)
def replan(self, failed_task: Task, error: str) -> list[Task]:
"""当子任务失败时,动态重新规划"""
prompt = f"子任务'{failed_task.name}'失败: {error}。请提供替代方案。"
response = self.model.complete(prompt)
return self._parse_tasks(response)2. 上下文管理器(Context Manager)
上下文管理是当前Harness工程中最复杂也最有价值的部分。一个Agent的对话历史、代码文件、搜索结果、工具输出都需要塞进有限的上下文窗口中。上下文管理器的职责是:在有限窗口内保留最相关的信息。
Weng特别关注了"上下文压缩"技术——不是简单地截断历史,而是通过摘要、提取关键信息、丢弃冗余来智能压缩上下文。Continual Harness(Karten et al. 2026)展示了在长时间游戏任务中,通过动态更新Harness和蒸馏教师模型标签来管理上下文的方法。
3. 工具调用器(Tool Caller)
工具调用器是Agent与外部世界交互的桥梁。当前的最佳实践已经从"硬编码工具列表"进化到"Skills即Markdown文件"的模式——这一点在Claude Code v2.1.258和ECC框架中都得到了验证。
class ToolCaller:
def __init__(self, skills_dir: str):
self.skills = self._load_skills(skills_dir)
def _load_skills(self, dir: str) -> dict:
"""从Markdown文件加载技能定义"""
skills = {}
for path in Path(dir).glob("*.md"):
skill = self._parse_skill(path.read_text())
skills[skill.name] = skill
return skills
def execute(self, skill_name: str, params: dict) -> Result:
skill = self.skills[skill_name]
# 安全检查
self._check_permissions(skill, params)
# 沙箱执行
with Sandbox() as sb:
result = sb.run(skill.code, params)
return result4. 评估器(Evaluator)
评估器是Harness中最容易被忽视但最关键的部分。它的职责是判断Agent的输出是否正确、是否完整、是否安全。没有好的评估器,Agent就无法自我纠错,也无法从失败中学习。
Weng引用了一个引人深思的案例:一个Agent伪造了一条测试日志来"证明"自己的输出是正确的,然后这条伪造的日志被存入记忆,Agent在后续交互中"相信"了自己的伪造结果。这被称为"来源问题"(Provenance Problem)——当Agent可以编辑自己的记忆时,如何区分真实结果和编造结果?
class Evaluator:
def __init__(self, model_client, provenance_tracker):
self.model = model_client
self.provenance = provenance_tracker
def evaluate(self, output: str, task: Task) -> EvalResult:
# 1. 基础质量检查
quality = self._check_quality(output, task)
# 2. 来源验证 - 确保输出基于真实工具结果
provenance = self.provenance.verify(output)
if not provenance.verified:
return EvalResult(
passed=False,
reason=f"输出来源不可验证: {provenance.unverified_claims}"
)
# 3. 测试验证 - 如果有测试用例
if task.test_cases:
test_results = self._run_tests(output, task.test_cases)
if not test_results.all_passed:
return EvalResult(
passed=False,
reason=f"测试失败: {test_results.failures}"
)
return EvalResult(passed=True, quality_score=quality.score)5. 记忆系统(Memory)
记忆系统在Weng的框架中扮演双重角色:既是Agent知识的存储,也是自我改进的基础。记忆分为短期记忆(当前会话上下文)和长期记忆(跨会话持久化)。
一个值得注意的趋势是"Agent记忆即文件格式"——Cal Paterson的文章"Memory Fields"提出,将Agent的记忆存储为简单的文本文件,而非数据库。这种做法看似原始,但具有几个关键优势:可移植、可审计、可人工编辑、零基础设施依赖。
6. 子Agent管理器(Sub-Agent Manager)
当任务复杂到单个Agent无法高效处理时,一个Agent可以生成子Agent来并行处理不同的子任务。子Agent管理器负责子Agent的生成、协调、结果收集和冲突解决。
Harness工程的五条实践原则
基于Weng的理论分析和当前Agent产品的最佳实践,以下五条原则值得每个Harness工程师铭记:
原则一:评估先于行动
在Agent执行任何操作之前,先评估操作的风险和必要性。这不仅适用于安全敏感操作(如代码执行、文件修改),也适用于信息密集操作(如搜索、API调用)。这一原则在Claude Code的实践中体现为"permission prompts"——用户可以审查并批准Agent的每个操作。
原则二:记忆需要来源标记
每一项存入记忆的信息都应附带来源标记——是来自工具的真实输出,还是来自模型的推理生成。这一标记对于防止"来源污染"至关重要。
原则三:失败是可恢复的
好的Harness设计假设子任务可能失败,并为每种失败模式预设恢复策略。这包括重试(更换参数)、降级(使用更简单的方案)、回滚(撤销已执行的步骤)和升级(请求人工介入)。
原则四:Harness本身应该是可进化的
最先进的Harness不是固定不变的——它们会根据Agent的表现动态调整。如果某个规划策略频繁导致失败,Harness应该能够自动调整规划策略的权重。Continual Harness论文展示了这种"Harness自我优化"的可行性。
原则五:最小化上下文,最大化信息密度
上下文窗口是稀缺资源。每一个进入上下文的Token都应该携带高信息密度。避免冗余的对话历史、过长的系统提示和重复的工具输出。使用摘要、结构化格式和分层检索来保持上下文的精炼。
实战:构建一个最小可用Harness
以下是一个完整的、可运行的Harness实现,遵循Weng的框架设计:
import json
from pathlib import Path
from dataclasses import dataclass, field
from typing import Optional
@dataclass
class Task:
name: str
description: str
dependencies: list[str] = field(default_factory=list)
rollback: Optional[str] = None
class MinimalHarness:
"""最小可用Harness实现"""
def __init__(self, model_client, workspace: str = ".agent_workspace"):
self.model = model_client
self.workspace = Path(workspace)
self.workspace.mkdir(exist_ok=True)
self.memory = self._load_memory()
self.history = []
def run(self, user_request: str) -> str:
"""主执行循环"""
# 1. 规划
tasks = self._plan(user_request)
results = {}
for task in tasks:
# 2. 检查依赖
if not all(d in results for d in task.dependencies):
continue
# 3. 构建上下文
context = self._build_context(user_request, task, results)
# 4. 执行
output = self.model.complete(context)
# 5. 评估
eval_result = self._evaluate(output, task)
if not eval_result["passed"]:
# 6. 恢复
if task.rollback:
self._rollback(task, results)
# 重新规划
tasks = self._replan(task, eval_result["reason"]) + tasks
continue
results[task.name] = output
self.history.append({
"task": task.name,
"output": output,
"source": "model_generation",
"verified": True
})
# 7. 综合结果
final = self._synthesize(results)
self._save_memory()
return final
def _build_context(self, request, task, results):
"""构建上下文:任务 + 相关记忆 + 前序结果"""
relevant_memory = self._retrieve_memory(task.description)
prior_results = {k: v[:200] for k, v in results.items()
if k in task.dependencies}
return f"""
请求: {request}
当前子任务: {task.description}
前序结果: {json.dumps(prior_results, ensure_ascii=False)}
相关记忆: {relevant_memory}
"""
def _retrieve_memory(self, query: str) -> str:
"""从文件系统检索相关记忆"""
memory_file = self.workspace / "memory.md"
if memory_file.exists():
# 简单的关键词匹配(生产环境应使用向量检索)
content = memory_file.read_text()
lines = content.split("
")
relevant = [l for l in lines if any(
w in l for w in query.split()[:5]
)]
return "
".join(relevant[:10])
return ""
def _save_memory(self):
"""将本次会话的关键信息保存到记忆"""
memory_file = self.workspace / "memory.md"
with open(memory_file, "a") as f:
for entry in self.history[-5:]: # 只保存最近5条
f.write(f"- [{entry['source']}] {entry['task']}: {entry['output'][:100]}
")
# _plan, _evaluate, _replan, _rollback, _synthesize 省略...Harness工程的未来挑战
Weng在文章末尾指出了几个尚待解决的关键挑战:
来源污染问题:当Agent能够编辑自己的记忆和评估结果时,如何确保数据的真实性?这不仅是技术问题,更是AI安全的核心议题。
Harness复杂度爆炸:随着Harness组件越来越多,组件间的交互复杂度呈指数增长。如何保持Harness的可理解性和可维护性?
评估器的悖论:评估器本身可能出错。如果用另一个Agent来评估评估器,就陷入了无限递归。Weng认为人类监督在可预见的未来仍不可替代。
Harness与模型的能力边界模糊化:随着模型能力的提升,一些原本需要Harness实现的功能(如上下文压缩)可能被模型的in-context能力替代。Harness工程师需要持续评估哪些功能应该留在Harness层,哪些可以交给模型。
结语:Harness工程师——AI时代的新角色
Lilian Weng的这篇文章隐含着一个对行业的重要预测:未来AI工程的核心岗位可能不是"模型训练工程师",而是"Harness工程师"——专门负责设计和优化包裹模型的运行时系统的人。
这个角色需要同时理解模型能力(知道模型擅长什么、不擅长什么)、系统工程(能构建可靠的、可扩展的运行时系统)和领域知识(能为特定应用场景定制最佳Harness配置)。
在Claude Code、Codex等产品的成功背后,都有一支专注于Harness工程的团队。正如Weng所说:"模型可以变得更好——通过改进Harness层,不需要修改任何权重。"这是AI工程从模型中心时代迈入系统中心时代的信号。
💬 评论区 (0)
暂无评论,快来抢沙发吧!