AI Agent Harness 的工程本质:从控制边界到协作基础设施

过去一年,”Agent” 这个词被用得极度滥泛。几乎所有能调用 LLM 的系统都开始自称 Agent,从一个简单的 prompt chain 到复杂的多智能体协作框架,混在一起难以区分。

真正值得关注的,是那些在生产环境里实际跑起来的系统,背后有一套东西把它们撑起来——不是模型本身,而是围绕模型构建的控制结构。这个控制结构,我习惯称之为 Harness

Harness 不是 Framework

先做一个区分。

Framework 解决的是生产力问题:提供抽象、减少重复、加快开发。LangChain、LlamaIndex 都属于这个范畴,它们让你更快地把 LLM 接入应用。

Harness 解决的是控制问题:在 Agent 自主行动的过程中,如何划定它能做什么、不能做什么,以及人在哪些节点介入。

这两件事在早期 demo 阶段往往混在一起,但到了生产场景就会迅速分裂。一个写代码的 Agent,你可以用 Framework 快速搭出来;但要让它在真实工程环境里安全地跑起来——能访问代码库、能执行命令、但不能随意 push 到主分支、不能删除生产数据库——这件事 Framework 管不了,需要的是 Harness。

Claude Code 是目前我见过工程化程度最完整的 Harness 之一。它不是一个普通的 coding assistant,它定义了一整套权限模型、工具脚手架、上下文管理机制和钩子系统,让 Agent 在受控边界内自主完成复杂任务。

一个 Harness 的四个核心层

1. 权限与边界模型

权限模型是 Harness 最核心的部分,也是最容易被忽视的部分。

Agent 的能力边界不是靠 prompt 里的”你不能做 X”维持的,这件事大家慢慢都意识到了。真正可靠的边界来自工具层面的硬限制:工具暴露什么能力,Agent 就只有什么能力。

一个设计良好的 Harness 会在以下层面定义权限:

  • 工具粒度:哪些工具对 Agent 可见。不可见的工具,Agent 无法调用,即使被诱导也无效。
  • 操作粒度:同一个工具内部,哪些操作可以免确认执行,哪些需要人工审批。例如,读文件可以自动放行,但写文件、执行命令需要用户确认。
  • 作用域限制:工具的操作范围被限制在特定上下文内。Agent 只能操作当前工作目录,无法逃逸到系统其他位置。

这里有一个工程上的核心权衡:边界越紧,Agent 越安全,但完成任务的自主性越低;边界越松,效率越高,但风险越大。

没有通用答案。不同任务场景需要不同的边界配置,Harness 的工程价值之一,就是让这个配置变得清晰、可审计、可演化。

2. 工具脚手架(Tool Scaffolding)

工具是 Agent 与外部世界交互的唯一通道。工具的设计质量直接决定 Agent 行为的质量。

一个常见的错误是把工具设计得太通用。比如提供一个 run_shell_command 工具,让 Agent 自由执行任意 shell 命令。这在 demo 里看起来很强大,在生产里是灾难——不仅安全风险高,Agent 的行为也变得不可预测,因为它能做的事情太多,反而找不到最直接的路径。

好的工具脚手架有几个特征:

  • 语义清晰:工具名和参数准确描述意图,不留歧义。read_file(path)file_operation(op="read", path=...) 更好。
  • 职责单一:一个工具只做一件事。复合操作应该由 Agent 组合多个工具完成,而不是塞进一个工具里。
  • 结果可预期:相同输入应该产生相同结果,副作用明确。Agent 需要根据工具返回值做决策,不可预期的结果会导致错误链式累积。
  • 粒度适当:既不要太粗(覆盖太多操作),也不要太细(需要 Agent 花太多步骤完成简单任务)。

工具脚手架的设计,本质上是在做接口设计,只是服务的调用方不是人类开发者,而是 LLM。

3. 上下文管理

这里的”上下文”不是 RAG 意义上的知识检索,而是 Agent 执行任务过程中的操作上下文:任务目标、已完成的步骤、中间状态、失败记录、待决策事项。

Agent 在执行长任务时,上下文窗口是有限资源。如何在有限窗口里保留最有价值的信息,是一个工程问题。

Harness 需要处理两类上下文压力:

深度压力:单个任务执行过程中,历史对话和工具调用记录不断增长。Harness 需要策略性地压缩历史,保留关键决策和当前状态,丢弃冗余的中间过程。

广度压力:多 Agent 协作场景下,不同 Agent 需要共享部分上下文,同时保持各自的执行隔离。如何设计共享上下文的边界和同步机制,是一个至今没有标准答案的问题。

我们在内部项目里尝试过几种方案,最终发现最简单的往往最有效:明确区分”任务规格”和”执行历史”。任务规格(目标、约束、当前状态摘要)始终保持精简并放在上下文前端;执行历史按需截断,只保留最近 N 轮和关键决策点。

4. 钩子系统(Hooks)

钩子是 Harness 里最被低估的设计。

一个 Agent 系统的核心矛盾是:你希望它自主完成任务,但又不能完全信任它的每一步决策。钩子解决的就是这个矛盾:在不打断主流程的前提下,在特定事件节点插入人或系统的干预逻辑。

典型的钩子点包括:

  • 工具调用前(pre-tool):审查 Agent 即将执行的操作,可以阻断或修改
  • 工具调用后(post-tool):处理工具返回值,可以注入额外上下文
  • 任务完成时(on-completion):验证结果,触发下游流程
  • 错误发生时(on-error):自定义错误处理,而不是直接中断

钩子的力量在于组合性。把日志记录、权限检查、人工审批、自动化测试分别实现为独立钩子,然后按场景组合,比把这些逻辑全部硬编码进主流程要灵活得多。

在开源项目治理场景里,我们用钩子实现了一套”软边界”机制:Agent 可以自由探索和执行,但每当它准备写入代码库或发布 issue 时,会触发一个钩子,把操作描述推送给维护者审批队列,异步等待批准再继续。这让 Agent 的自主性和人工监管可以同时存在,而不是非此即彼。

设计中的几个实际权衡

写到这里,我想说几个在工程实践中真正困难的地方。

权限配置的维护成本。 权限模型在初始设计时往往比较清晰,但随着任务场景扩展,权限配置会越来越复杂。谁有权修改配置?配置变更需要审计吗?如何避免权限蔓延?这些问题的复杂度和传统的 IAM 系统没有本质区别,只是换了一个语境。

工具版本兼容性。 Agent 对工具的调用方式是基于工具描述(通常是自然语言的 schema)推理出来的。当工具接口需要变更时,你不能像普通 API 那样简单地更新版本——因为 Agent 可能已经在上下文里”记住”了旧的调用方式。这要求工具变更必须向后兼容,或者在 Harness 层做显式的版本适配。

上下文压缩的信息损失。 任何压缩都会丢失信息,问题是丢失哪些。目前没有通用的最优策略,只有”对当前任务什么信息最重要”这个问题的具体答案。这意味着上下文管理策略需要和任务类型绑定,而不是 Harness 层的统一处理。

钩子的调试难度。 钩子增加了系统的行为维度。当 Agent 的行为出乎意料时,你需要判断问题出在 Agent 本身、工具、还是某个钩子。这对可观测性提出了更高要求——每个钩子的执行都应该有完整的日志和追踪。

从基础设施视角看 Harness 的演化

回到一个更大的问题:Harness 最终会演化成什么?

我的判断是,它会沿着两个方向分化:

一个方向是标准化。就像容器运行时从百花齐放到 OCI 标准收敛一样,Agent Harness 的核心接口——权限模型、工具协议、上下文格式——最终会有事实标准出现。MCP 协议是这个方向上的一个早期探索,但它解决的只是工具发现和调用的标准化,权限和上下文部分还远未成熟。

另一个方向是可组合基础设施。Harness 不会是一个单体系统,而是一组可以独立部署、按需组合的基础设施组件:权限服务、工具注册中心、上下文存储、事件总线。不同的 Agent 系统按需选用,而不是统一由一个 Harness 框架接管。

这和云原生基础设施的演化路径高度相似:从巨石应用到微服务,从 monolithic 监控到可观测性组件栈。Agent 基础设施大概率会走同一条路。


Harness 是一个工程概念,不是产品名词。它的价值不在于让 Agent 变得更智能,而在于让 Agent 的行为变得可预期、可审计、可控制

在 Agent 能力快速提升的当下,这件事比让 Agent 更聪明更重要。


AI Agent Harness 的工程本质:从控制边界到协作基础设施
https://www.krli.org/2026/04/15/AI-Agent-Harness工程实践/
作者
李科燃
发布于
2026年4月15日
许可协议