大模型本身只能推理与生成,真正让智能体在现实环境中稳定执行任务的,是模型之外的工程基础设施——Harness。本文围绕 Harness 的五大支柱(工具、知识、观测、执行接口、权限)展开分析,结合 Python 原型代码实现一个最小可运行 Agent Loop,并解释其执行流程。报告结论是:模型决定智能上限,Harness 决定工程下限;在固定模型条件下,仅优化 Harness 即可显著提升任务成功率。
一、引言:为什么 Harness 正在成为 Agent 工程的核心
过去两年,AI 工程经历了从提示词工程、上下文工程到 Harness 工程的演进。大模型虽然具备强大的语言理解与推理能力,但它本质上仍然是概率性生成系统:它不能直接读写文件,不能执行命令,不能访问实时环境,也不能保证每次输出都符合工程约束。
Harness 正是为了解决这些问题而出现的。Anthropic 将其定义为“模型之外的操作系统级基础设施”,负责管理上下文与记忆、调度工具、回收执行结果、维护权限边界。 OpenAI、LangChain 等团队也给出了相近定义:Agent = Model + Harness。
一个关键事实是,Harness 对智能体能力的影响并非理论推测。LangChain 团队在 TerminalBench 2.0 上的实验显示,固定使用 gpt-5.2-codex 模型,仅通过优化 Harness,任务准确率从 52.8% 提升到 66.5%,排名从 Top 30 以外进入 Top 5。 另有研究指出,在更完善的自动化验证闭环下,同一模型的通过率可进一步提升至 76.4%。 这说明,评估一个 Agent 的真实能力,不能只看模型本身,而必须评估“模型 + Harness”的组合。
二、Harness 五大支柱
2.1 工具:Agent 的“双手”
工具层提供 Agent 与外部世界交互的原子能力,包括文件读写、Shell 执行、API 调用、数据库查询、浏览器操控等。 工具设计需要遵循几个原则:
- 原子性:每个工具只做一件事,便于组合与审计;
- 可描述性:工具必须有清晰的参数 Schema,便于模型正确调用;
- 可观测性:工具执行结果必须结构化返回,供模型继续推理;
- 最小集优先:工具并非越多越好,过多工具会增加模型选择成本。
Claude Code 内置约 40 个基础工具,包括 Bash、Read、Write、Edit、Grep、Glob 等,其中只读工具可并行执行,修改状态的工具则串行执行,避免冲突。
2.2 知识:Agent 的领域专长
知识层解决模型专业知识不足和上下文浪费问题。典型做法包括:
- 项目根目录放置
CLAUDE.md、AGENTS.md等规范文件,启动时自动注入; - 通过 RAG 检索增强,按需加载产品文档、API 规范、风格指南;
- 使用 Skills 机制渐进式披露能力,避免一次性塞满上下文;
- 通过指针索引式记忆管理长期知识,而非直接存储完整内容。
知识层的价值在于:把“每次对话都要重复说明的项目约定”,变成“启动时自动加载的运行环境”。
2.3 观测:Agent 的“眼睛”
观测层让 Agent 感知行动结果,形成“感知—推理—行动”闭环。常见观测信号包括:
- Shell 命令的 stdout/stderr 与退出码;
- Git diff 与文件变更状态;
- 测试用例通过/失败结果;
- 浏览器截图或 DOM 状态;
- 系统资源、日志、监控指标。
没有观测层,Agent 就像闭着眼睛干活:它可能发出指令,但无法确认指令是否真正生效。观测层也是验证循环的基础,只有看到结果,Agent 才能判断是否需要重试、修正或终止。
2.4 执行接口:把决策变成动作
执行接口层负责把模型的决策转化为实际动作,包括 CLI 命令、API 调用、UI 交互、跨应用编排等。 它通常包含:
- 工具调用解析器:识别模型输出的工具调用;
- 执行调度器:决定哪些工具可以并行,哪些必须串行;
- 结果回填机制:把执行结果重新注入对话上下文;
- 多智能体协作接口:支持主 Agent 向子 Agent 派发任务。
执行接口是 Harness 的“传动系统”。模型只负责决定下一步做什么,Harness 负责真正执行,并把结果带回循环。
2.5 权限:Agent 的安全边界
权限层是安全工程与 Harness 工程的交汇点。它通过沙箱隔离、审批流、信任边界分级,防止 Agent 执行危险操作。 Claude Code 的权限体系通常分为三级:
- Allow:自动执行,如只读文件、Git 状态查询;
- Ask:执行前需要用户确认,如修改文件、运行构建命令;
- Deny:完全禁止,如删除生产数据、强制推送远端分支。
更成熟的 Harness 还会引入 Hooks 机制,在工具调用前、调用后插入确定性校验逻辑,用代码约束概率性模型。
三、Python 原型实现:最小可运行 Agent Loop
下面给出一个简化版 Python Agent Loop,展示五大支柱如何协同工作。
importjsonimportsubprocessfrompathlibimportPathfromtypingimportCallable# ===================== 支柱一:Tools 工具层 =====================deftool_read(path:str)->str:"""读取文件内容(只读工具,低风险)。"""returnPath(path).read_text(encoding="utf-8")deftool_write(path:str,content:str)->str:"""写入文件(写操作,需权限校验)。"""Path(path).write_text(content,encoding="utf-8")returnf"Written to{path}"deftool_bash(command:str)->str:"""执行 Shell 命令,返回 stdout/stderr。"""result=subprocess.run(command,shell=True,capture_output=True,text=True,timeout=30)output=result.stdoutor""ifresult.stderr:output+=f"\n[stderr]{result.stderr}"ifresult.returncode!=0:output+=f"\n[exit_code]{result.returncode}"returnoutput.strip()# 工具注册表:名称 -> (函数, 描述)TOOLS={"read":(tool_read,"Read file content. Args: path"),"write":(tool_write,"Write content to file. Args: path, content"),"bash":(tool_bash,"Run a shell command. Args: command"),}# ===================== 支柱二:Knowledge 知识层 =====================defload_knowledge(project_root:str=".")->str:""" 按需加载项目知识。 生产系统中可替换为 RAG 检索、Skills 目录加载等。 """knowledge=[]fornamein["CLAUDE.md","AGENTS.md","README.md"]:file_path=Path(project_root)/nameiffile_path.exists():knowledge.append(f"---{name}---\n{file_path.read_text(encoding='utf-8')}")return"\n\n".join(knowledge)ifknowledgeelse"No project knowledge files found."# ===================== 支柱三:Observation 观测层 =====================defobserve(result:str,max_chars:int=2000)->str:""" 对工具执行结果做观测与裁剪。 生产系统中可增加日志采集、git diff 对比、测试状态解析等。 """iflen(result)>max_chars:returnresult[:max_chars]+f"\n... (truncated, total{len(result)}chars)"returnresult# ===================== 支柱四:Action Interfaces 执行接口层 =====================defexecute_action(action_name:str,args:dict)->str:""" 执行接口层:根据模型决策调度具体工具。 这里是简化版,生产系统可支持并行执行、超时控制、重试策略。 """ifaction_namenotinTOOLS:returnf"Error: unknown tool '{action_name}'"func,_=TOOLS[action_name]try:returnfunc(**args)exceptExceptionase:returnf"Error executing{action_name}:{e}"# ===================== 支柱五:Permissions 权限层 =====================PERMISSION_RULES={"read":"allow",# 只读自动放行"write":"ask",# 写文件需确认"bash":"ask",# Shell 执行需确认}defcheck_permission(action_name:str)->bool:""" 权限检查。 简化为交互式确认;生产系统可使用 settings.json、 白名单、沙箱策略或 Hooks 校验。 """rule=PERMISSION_RULES.get(action_name,"ask")ifrule=="allow":returnTrueifrule=="deny":print(f"[Permission] Denied action:{action_name}")returnFalse# ask 模式:交互式确认confirm=input(f"[Permission] Allow '{action_name}'? [y/N]: ").strip().lower()returnconfirmin("y","yes")# ===================== Agent Loop 主循环 =====================defmock_llm_decision(messages:list,knowledge:str)->dict:""" 模拟 LLM 决策函数。 生产系统中应替换为真实模型调用,例如 Anthropic / OpenAI SDK。 这里仅演示循环结构。 """# 简单演示:假设用户要求创建一个 hello.txtlast_user_msg=messages[-1]["content"]ifmessageselse""if"create hello"inlast_user_msg.lower():return{"tool":"write","args":{"path":"hello.txt","content":"Hello from Harness Agent!"},"done":False,}if"run ls"inlast_user_msg.lower():return{"tool":"bash","args":{"command":"ls -la"},"done":False,}# 默认结束return{"tool":None,"args":{},"done":True,"reply":"Task completed."}defagent_loop(user_query:str,max_steps:int=10)->str:""" 最小 Agent 循环: 感知 -> 决策 -> 权限检查 -> 执行 -> 观测 -> 回填 -> 再决策 """messages=[{"role":"user","content":user_query}]knowledge=load_knowledge()messages.insert(0,{"role":"system","content":f"Project knowledge:\n{knowledge}"})forstepinrange(1,max_steps+1):print(f"\n[Step{step}] Deciding next action...")decision=mock_llm_decision(messages,knowledge)ifdecision.get("done"):returndecision.get("reply","Done.")tool_name=decision["tool"]tool_args=decision["args"]# 支柱五:权限检查ifnotcheck_permission(tool_name):messages.append({"role":"system","content":f"Permission denied for tool:{tool_name}",})continue# 支柱四:执行接口raw_result=execute_action(tool_name,tool_args)# 支柱三:观测与裁剪observation=observe(raw_result)print(f"[Observation]{observation[:200]}")# 回填上下文,供下一轮决策使用messages.append({"role":"assistant","content":f"Called tool:{tool_name}with args:{json.dumps(tool_args)}",})messages.append({"role":"system","content":f"Tool result:\n{observation}",})return"Reached max steps without completing the task."# ===================== 运行示例 =====================if__name__=="__main__":result=agent_loop("Please create hello.txt with a greeting message.")print("\n[Final]",result)四、代码解析
4.1 工具层实现
tool_read、tool_write、tool_bash对应 Agent 最基础的三类能力:读取环境、修改环境、执行命令。生产系统中,工具层通常会扩展为 MCP 服务器、Docker 沙箱、浏览器自动化、数据库连接器等。
4.2 知识层实现
load_knowledge从项目根目录加载规范文件。这与 Claude Code 的CLAUDE.md、Codex 的AGENTS.md思路一致:把项目约定、编码风格、常用命令固化为可加载知识,避免每次对话重复说明。
4.3 观测层实现
observe对工具输出进行裁剪和结构化。真实系统中,观测层还会解析测试输出、提取 git diff、判断命令是否真正成功,而不仅仅是捕获文本。
4.4 执行接口层实现
execute_action是工具调度中心。它将模型决策映射到具体函数,并统一处理异常。生产系统会在此基础上增加并行执行、超时控制、重试、子 Agent 派发等能力。
4.5 权限层实现
check_permission实现了 Allow / Ask / Deny 三级权限。Claude Code 也采用类似机制:只读操作自动放行,修改文件和 Shell 执行通常需要确认,高危命令可直接拒绝。 更高级的实现还会在PreToolUse、PostToolUse等节点插入 Hooks,实现确定性校验。
4.6 Agent Loop 结构
主循环体现了 Harness 的核心模式:
- 模型接收消息与知识;
- 决定下一步工具调用;
- Harness 进行权限检查;
- 执行工具并回收结果;
- 观测层处理反馈;
- 结果回填上下文,进入下一轮决策。
这正是 TAOR(Think-Act-Observe-Repeat)或 ReAct 循环的工程化表达。
五、技术亮点
亮点一:明确区分“智能”与“载体”
模型负责推理,Harness 负责执行。这个分工避免了把工程可靠性寄托在模型输出稳定性上。模型可能偶尔幻觉,但 Harness 可以通过权限、沙箱、测试验证和 Hooks 兜底。
亮点二:用确定性代码约束概率性模型
权限检查、工具 Schema、观测裁剪、执行超时都是确定性逻辑。它们不一定让模型更聪明,但能让系统更可靠。这也是 Harness 工程的核心价值。
亮点三:观测闭环支撑自我修正
Agent 之所以能纠错,不是因为它“知道自己错了”,而是 Harness 把错误日志、测试失败、退出码等信息重新送回上下文,迫使模型基于真实反馈调整下一步。
亮点四:知识层降低 Token 成本
通过按需加载项目文档、风格指南和 API 规范,Agent 不必在每次请求中重复携带大量背景信息。长期记忆、会话检查点和跨会话持久化进一步缓解上下文腐烂问题。
亮点五:权限层是工业落地的前置条件
没有权限控制,Agent 无法进入企业环境。沙箱隔离、命令白名单、审批流和操作审计,是 Agent 从演示走向生产的关键门槛。
六、局限与改进方向
本文原型仅用于演示五大支柱的协作关系,距离生产级 Harness 仍有明显差距。主要改进方向包括:
- 替换模拟 LLM:接入真实模型 SDK,支持流式输出与工具调用解析;
- 增强沙箱:使用 Docker 或容器隔离执行环境,防止危险命令影响宿主机;
- 完善权限系统:支持配置文件持久化、项目级策略、细粒度命令匹配;
- 引入验证 Hooks:在工具调用前后插入自动化测试、Lint、CI 校验;
- 增加状态持久化:保存会话检查点,支持断点续跑和跨会话记忆;
- 支持多智能体:将复杂任务拆分为规划、执行、验证等子 Agent。
七、结论
Harness 不是简单的模型包装,而是让大模型从“能说话”走向“能干活”的工程基础设施。五大支柱分别解决不同问题:工具提供执行能力,知识提供领域专长,观测提供环境反馈,执行接口提供调度能力,权限提供安全边界。
在模型能力趋同的背景下,Harness 正在成为 Agent 系统差异化的关键来源。未来评估一个智能体,不能只问“它用了什么模型”,更要问“它的 Harness 是否形成了完整的感知—决策—执行—验证—安全闭环”。