Heath Kang

从 Prompt 到 Harness:Agent 到底是什么,以及它如何真正做事

把 Agent 相关的概念梳理总结一下:Prompt、Context、Tool、Skill、MCP、Harness、Sub-agent、Workflow、Loop。这些词已经出现很久了,经常一起出现,却不在同一个层次上,结果是大家讨论 Agent 时,容易把“模型会不会思考”“产品给了哪些工具”“系统怎样运行”混成一件事。

我更喜欢从一个具体问题开始:

如果我只对一个 LLM 说“帮我修好这个 bug”,它为什么只能给建议;而 Claude Code、Codex 或 Pi 却能读代码、改文件、运行测试,最后把一个可工作的结果交给我?

答案不是多写几句 Prompt,而是给模型接上了一套可以观察、行动、获得反馈并继续行动的运行环境。

Prompt:这次想完成什么?
Context:模型现在知道什么?
Harness:模型能看见什么、能做什么、边界在哪里?
Loop:做完一步后,谁把结果送回来并决定是否继续?

这篇文章不试图给 Agent 下一个唯一的学术定义,而是从工程实现出发,建立一套足以阅读和设计 Agent 的心智模型。先给出一个足够实用的工程定义:

Agent = Model + Context + Actions + Execution Loop

Agent 从 Prompt、Context 经过 LLM 与 Harness,调用工具改变环境,再通过 Observation 进入 Loop 的综述图

1. 先把四个词放回各自的位置

Prompt:告诉模型目标和约束

Prompt 是发送给模型的指令与输入。它可以包含:

  • 用户的目标:修复一个 bug、实现一个 API、分析一份数据;
  • 约束:不要修改接口、遵守项目风格、不能访问生产环境;
  • 输出格式:给出计划、返回 JSON、修改代码并报告测试结果;
  • 当前对话:用户和模型之前说过的话。

如果只使用一次模型调用,Prompt 往往就是整个交互的中心:模型读完输入,生成一段文本,任务结束。

但 Agent 任务通常不是一次回答就能完成的。模型不知道仓库当前有哪些文件,不知道测试命令是否成功,也不能凭空修改电脑。Prompt 只表达“想要什么”,并不自动提供“做什么”的能力。

Context:模型这一次究竟看到了什么

Context 是某一次模型调用真正收到的上下文。它不等于用户输入,而是由多种信息拼出来的:

Context
├── system prompt:身份、基本规则、工具协议
├── developer / project instructions:仓库规范、团队约定
├── user prompt:这次任务
├── conversation history:之前的对话和工具结果
├── tool schemas:可以调用哪些工具、参数是什么
└── retrieved state:文件内容、测试输出、数据库结果、网页片段

同一个 Prompt,放在不同 Context 里,结果可能完全不同。让模型知道“这是一个 Go 项目,测试命令是 go test ./...”,和只告诉它“修好 bug”,不是同一个任务。

Context 也不是越多越好。无关的 README、过期规则和重复的工具描述会挤占窗口,稀释真正重要的约束。一个好的 Agent 会把信息分层:稳定规则常驻,任务相关知识按需加载,工具结果只保留对下一步有用的部分。

Harness:包住模型的运行时

Harness 可以直译成“马具”,在这里更接近 Agent 的运行时或控制层。它连接四样东西:

用户 / 上层应用
Harness ─── 模型 API
  │  │  │
  │  │  └── 状态:会话、文件、任务、权限、成本
  │  └───── 工具:read / edit / bash / browser / MCP
  └──────── 控制:循环、压缩、重试、审批、停止条件
真实环境:文件系统、shell、网络、数据库、CI

Harness 决定模型看到哪些信息、可以调用哪些工具、工具在哪里执行、结果如何返回、什么时候需要人批准,以及任务什么时候算完成。Claude Code、Codex CLI 和 Pi 都不只是“给模型发 Prompt 的脚本”,而是不同取舍的 Harness。

Loop:让一次回答变成持续行动

最小的 Agent Loop 大致是:

用户目标
组装 Context
调用模型
模型返回文本,或一个 Tool Call
执行工具,获得 Observation
把 Observation 放回 Context
继续调用模型,直到完成、失败或被停止

模型并没有在一次调用里“偷偷操作电脑”。它每次提出一个动作,Harness 执行动作,再把真实结果交还给模型。所谓 Agent 的自主性,主要来自这个循环能够持续运行,而不是模型突然获得了人类意义上的意志。

2. 一个修 bug 的请求,实际经过了什么

假设用户说:

修复登录接口偶发返回 500 的问题,并补上测试。

一个简单的聊天模型可能直接猜测原因,给出一段代码。一个 coding agent 则更可能经历下面的过程:

1. 读取项目说明和目录
2. 搜索登录接口、错误日志和相关测试
3. 打开关键文件
4. 推断可能的失败路径
5. 修改实现
6. 运行针对性测试
7. 看到失败输出后继续修改
8. 运行完整测试或 lint
9. 检查 diff,向用户报告事实

这里每一步都需要不同的能力:

行为所需能力
读取目录和文件文件系统工具、当前工作目录
搜索代码shell 或专门的搜索工具
修改实现精确编辑/写文件工具
运行测试shell 执行器、超时与输出截断
根据失败继续Loop、状态持久化、错误作为反馈
安全执行沙箱、权限、审批、网络策略
最终报告读取真实 diff 和测试结果

这张表很重要:模型负责提出下一步,Harness 负责让下一步真的发生,并把结果带回来。模型再聪明,如果工具不可用、结果没有回到 Context,或者 Harness 在第一次回答后就退出,系统仍然不是一个能完成任务的 Agent。

3. Agent 不只是“更好的 Prompt”

Prompt engineering 关注的是:怎样描述任务,模型更容易给出正确答案。Agent engineering 还要问:

  • 模型如何看到环境事实?
  • 它如何改变环境?
  • 改变之后如何验证?
  • 失败时如何恢复?
  • 哪些动作需要人批准?
  • 运行多久、花多少钱、何时停止?

可以把一次 Agent 任务的质量粗略写成:

结果质量
≈ 模型推理能力
  × Context 质量
  × 工具可用性
  × Loop 的反馈质量
  × 验证与安全边界

这不是数学公式,而是一个提醒:任意一项接近零,整体效果都会很差。一个强模型拿不到代码,无法修 bug;一个工具很多但没有测试反馈的 Agent,可能会自信地宣布“已经修好”;一个循环没有停止条件的 Agent,则可能不断重复同一件事。

4. Boris 的观点:Agent 更像给 LLM 做事的能力

你提到的 Boris Cherny 的那种说法,我认为可以归纳为:Prompt 更像是在告诉模型做什么,Harness 则是在给模型做事的能力。

这句话的重点不在于 Prompt 不重要,而在于两者解决的是不同问题。

“把这个函数改成异步”
        ├── Prompt:目标、约束、验收标准
        └── Harness:读文件、搜引用、编辑、编译、测试、查看 diff

如果只有 Prompt,模型最多能描述修改方案;有了工具和循环,它才有机会验证方案、面对错误,并把修改落到真实文件中。

这也解释了一个常见现象:同一个模型放进不同 Agent 产品,体验差异可能非常大。差异未必来自模型权重,可能来自:

  • 一个产品默认把哪些项目文件放进 Context;
  • 工具返回的是完整输出还是经过整理的摘要;
  • 是否自动读取测试失败日志;
  • 是否有权限审批和沙箱;
  • 是否会在上下文过长时压缩历史;
  • 是否有停止钩子、后台任务和验证阶段。

不过,“给能力”不等于“把所有能力都打开”。能力必须和边界一起设计:可以读整个仓库,不代表可以删除整个磁盘;可以运行测试,不代表可以把生产凭据放进环境变量;可以访问网络,不代表应该允许任意外发数据。

我更愿意把 Boris 的观点理解成一种工程重心的变化,而不是一句“Prompt 已经不重要”:当模型已经能够理解自然语言和代码时,瓶颈会越来越多地转移到环境、工具、反馈、权限和验证上。

5. 从 Pi 出发:一个 Agent 最小需要什么

Pi 很适合用来讨论“Agent 的最小能力”。它的设计方向不是预装尽可能多的产品功能,而是提供一个很小的核心:模型、上下文、工具调用和循环,再通过扩展增加能力。Pi 的 coding agent 默认提供 readwriteeditbash 四类基本工具,并支持通过 extensions、skills、prompt templates 和 packages 扩展。

把最小 coding agent 抽象成伪代码,大概是:

const tools = [read, write, edit, bash];
const messages = [systemPrompt, userPrompt];

while (true) {
  const response = await model.complete(messages, tools);
  messages.push(response);

  if (response.type === "text") {
    return response.text;
  }

  for (const call of response.toolCalls) {
    const observation = await execute(call);
    messages.push(observation);
  }
}

这段代码看起来很朴素,但已经包含 Agent 的核心闭环:

  1. 模型接口:能返回普通文本,也能返回结构化 Tool Call。
  2. 工具注册:模型知道有哪些工具、参数如何填写。
  3. 工具执行:Harness 把 Tool Call 变成真实环境中的动作。
  4. 结果回传:工具结果成为下一次推理的上下文。
  5. 状态保存:至少保存当前对话和工具结果,必要时支持恢复。
  6. 停止机制:模型完成、出错、超时或用户中止时退出。

缺少其中任何一项,系统都会退化:

没有工具       → 只能回答,不能行动
没有结果回传   → 只能盲猜,不能根据现实修正
没有状态       → 每一步都像失忆
没有停止机制   → 可能无限循环或失控
没有边界       → 能做事,但不敢让它做

为什么四个工具就能做很多事

read 让模型获得事实,writeedit 让它改变代码,bash 让它运行搜索、测试、编译和自定义脚本。工具数量不多,但组合空间很大:

read  → 理解现状
edit  → 改变实现
bash  → 观察反馈
loop  → 根据反馈继续

这是一种很有启发性的设计:工具不需要替模型预先实现每一种工作流。只要环境提供足够通用、可组合、反馈清晰的原语,模型就能在循环中临时组织出工作流。

Bash 为什么接近“万能 Primitive”

如果 Agent 拥有一个受控的 bash(command),它理论上就能调用 gitgrepfindpytestgopsqlkubectl 和各种项目脚本。甚至 readwriteedit 都可以用 cat、shell redirection、sed 或脚本间接完成。

LLM + bash + loop
搜索、读取、修改、编译、测试、部署脚本

但“理论上能做”不等于“适合直接暴露”。专用的 read(path, offset, limit) 比任意 shell 更容易限制路径、限制输出、记录行为和返回结构化结果;edit 也比让模型拼接复杂 sed 命令更容易验证失败原因。因此 Primitive 的目标不是追求数学意义上的最小,而是追求:

少量、正交、可组合、可观察、容易授权的基本能力。

这也是为什么一个只有几个工具的 Agent,反而可能比拥有几百个语义重叠 Tool 的 Agent 更稳定。searchfindlookupfetch 如果职责和描述差不多,模型先要解决 Tool Selection Ambiguity;而 readeditbash 的边界更清楚,复杂行为由组合产生。

当然,最小能力不等于生产能力。真正的产品还需要权限、沙箱、上下文压缩、并行任务、子 Agent、日志、恢复、成本控制和可观测性。Pi 的价值正在于把“核心闭环”和“产品层功能”分开,让使用者看得见两者的边界。

6. Skill 和 MCP:一个教方法,一个接能力

Skill:按需加载的做事方法

Skill 通常是一组可复用的任务知识:说明、规范、脚本、模板、示例和资源。它回答的是:

面对某类任务,应该采用什么流程、遵守什么规则、使用哪些辅助材料?

例如一个 PDF skill 可以告诉 Agent:先识别文档结构,再提取表格,最后用指定脚本检查输出;一个数据库迁移 skill 可以规定:先生成 migration,再运行测试,禁止直接修改生产库。

Skill 不一定提供新的底层能力。它更像操作手册或领域 playbook:模型本来就能调用 bash,Skill 告诉它什么时候运行哪个脚本、如何判断结果、失败后怎么办。

一个典型 Skill 可以这样组织:

pdf-processing/
├── SKILL.md       ← 入口:何时使用、流程和约束
├── references/    ← 需要时读取的详细说明
├── scripts/       ← 可执行的确定性工具
└── templates/     ← 输出模板

Skill 最重要的设计原则是按需加载。所有领域知识一开始都塞进 system prompt,会造成 Context 膨胀;先让 Agent 发现有哪些 Skill,再只加载当前任务需要的那一个,通常更经济,也更容易维护。

MCP:把外部能力接入统一协议

MCP(Model Context Protocol)解决的是另一个问题:

外部系统如何以统一方式向 Agent 暴露工具、资源和提示模板?

Agent Harness(MCP Client)
        │ MCP
        ├──────── 文件系统服务器
        ├──────── GitHub 服务器
        ├──────── 数据库服务器
        └──────── 浏览器 / SaaS / 内部系统服务器

MCP Server 可以暴露:

  • Tools:模型可以调用的动作,例如查询 issue、创建文档、执行受限数据库操作;
  • Resources:客户端或模型可以读取的上下文,例如某个文档、schema 或配置;
  • Prompts:可复用的提示模板。

因此,Skill 和 MCP 的关系可以简单记为:

Skill:怎样完成一类任务?
MCP:怎样连接一个外部能力?

两者经常组合使用。比如“发布周报”这个 Skill 规定流程:读取数据、生成摘要、人工确认、发布;MCP 提供读取数据库、访问文档系统和发消息的工具。

MCP 不是 Agent Loop,也不是安全边界本身。它定义了能力如何被发现和调用,但真正的权限审批、凭据管理、超时、审计和沙箱,仍然需要 Harness 或 MCP Server 自己负责。

CLI-first 与 MCP-first

Pi 这类 Agent 很容易采用 CLI-first 的组合方式:

Agent → bash → gh / kubectl / psql / curl → 外部系统

它的优点是成熟、透明、容易让人和 Agent 共用,也方便在终端复现问题。MCP 则更偏 Protocol-first:

Agent → MCP Client → MCP Server → 外部系统

它带来工具发现、结构化 schema、统一调用格式和跨 Agent Host 复用。两者不是替代关系:一个内部服务和一个 Agent 可能直接用 Native Tool 最简单;当多个 Agent 都要连接 GitHub、数据库或内部系统时,MCP 的标准化价值才会明显。

无论使用 CLI 还是 MCP,都要遵守同一条边界:

LLM 提议动作
Schema 校验
权限与策略判断
确定性执行器执行

Tool description 是给模型看的 API 文档,但它不能替代 Authorization。Schema 可以把 environment 限制为 devstaging,却不能单独决定当前用户是否有权访问 staging;危险动作还需要 allowlist、dry-run、人工确认和审计。

7. Harness 应该承担哪些责任

当一个 Agent 从 demo 走向日常工作,Harness 的价值通常集中在下面几层。

Context 管理

Harness 要决定什么进入上下文、什么延迟加载、什么被压缩或丢弃:

常驻:身份、核心安全规则、项目入口
按需:Skill、参考文档、MCP 资源
即时:当前文件片段、命令输出、测试失败信息
可丢弃:已经解决的中间过程、重复日志、旧计划

上下文压缩不是简单截断字符串。好的压缩会保留目标、已完成修改、未解决问题、关键错误和下一步约束,否则模型可能在压缩后忘记自己为什么改某个文件。

工具执行与 Observation

工具执行结果是 Agent 的“感官”。一个好的 Observation 应该:

  • 真实:明确命令是否执行、退出码是什么;
  • 有用:突出错误位置和关键输出;
  • 可继续:让模型知道下一步能做什么;
  • 可控:限制输出大小、超时和敏感信息泄露。

如果测试失败只返回“command failed”,模型没有足够信息修复;如果把几万行日志原样塞进 Context,又会淹没真正错误。

权限与安全

Agent 的风险来自“模型能做什么”和“模型被什么输入影响”。除了工具权限,还要考虑 prompt injection:仓库里的 README、issue、网页内容都可能包含诱导模型执行危险操作的文本。

常见的边界包括:

  • 文件系统允许读写范围;
  • shell 命令审批和危险命令拦截;
  • 网络是否开放、允许哪些域名;
  • 是否能读取凭据和环境变量;
  • 修改是否必须经过人工确认;
  • 每步、每个任务和整个会话的预算。

“模型决定调用什么工具”和“系统允许它调用什么工具”应该是两层判断。MCP 暴露了一个工具,不等于当前任务就有权使用它。

Subagent:扩展并行性,不是最小能力

Subagent 不是最小 Agent 必需的 Primitive。一个 Model + Context + read/edit/bash + Loop 已经可以完成大量编码任务。Subagent 主要解决三件事:并行执行、专业化分工和 Context Isolation。

                 Parent Agent
              /       |        \
             ▼        ▼         ▼
        Security    Database   Performance
          Agent       Agent       Agent
             \        |        /
              └── summaries ──┘
                  Parent merge

子 Agent 不需要看到父 Agent 的全部历史,只需要收到目标、相关文件和约束,最后返回摘要、证据和待处理问题。这种隔离能降低上下文噪声;但一旦引入多 Agent,系统就开始面对调度、超时、重试、任务归属、共享文件冲突和结果合并等分布式系统问题。

因此,Multi-Agent 不天然优于 Single-Agent。只有当并行性、专业化或上下文隔离确实带来收益时,才值得支付额外的协调成本。

验证与停止

Agent 不应把“模型说完成了”当成完成。完成最好由外部证据定义:测试通过、lint 通过、diff 符合预期、文件存在、API 返回正确结果。

模型:我认为已经修好了
Harness:运行测试、检查 diff、收集退出码
证据:测试通过 / 仍有失败
Loop:结束,或继续修复

停止条件同样重要:成功条件、最大步数、超时、预算、重复动作检测、用户中止和不可恢复错误都应该明确。

8. Claude Code、Codex、Pi 与 DeepSeek Harness 怎么比较

这里把 Harness 当作 Agent Runtime 来讨论。它有时也指评测脚手架、工作流编排器或产品中的 Agent 控制层,语境不同,不能把这些含义混在一起。DeepSeek Harness(DSH)则是 DeepSeek 推出的、以插件为核心的开源 Agent Harness:模型、工具、Skill、会话、沙箱、存储、循环、调度和 UI 都可以作为插件替换或重新组合,目前仍处于 developer preview 阶段。

更有意义的比较维度不是“谁的模型更聪明”,因为产品使用的模型、版本、权限和任务都可能不同,而是:谁负责循环,工具多大,默认上下文多少,安全边界在哪里,扩展成本如何。

维度Claude CodeCodexPiDeepSeek Harness
定位面向软件工程的完整 coding agent面向编码任务的 Agent 产品与运行时极简、可改造的 terminal coding harness插件优先、可组合的 Agent Harness
核心取舍开箱即用、工作流完整模型、沙箱、审批和多客户端能力结合小核心、低预设、强可塑性把 Harness 本身拆成可替换插件,换取组合能力与更高系统复杂度
工具与环境文件、shell、项目指令、扩展等文件和 shell 能力,并强调沙箱、审批、客户端集成默认 read/write/edit/bash由设计者决定
扩展方式Skills、hooks、plugins、MCP 等Skills、MCP、应用/协议层扩展TypeScript extensions、Skills、packages任意代码、协议和工作流
编排能力产品内置较多工作流能力支持线程、持久化和多种客户端形态核心保持简单,更多能力交给扩展Standard、Code Mode、Minimal、Creator 等预设,能力也可由插件重组
适合谁想直接在代码库中工作的人想要受控、可集成的编码 Agent 的团队想理解、改造和自定义 Agent 的工程师想研究 Harness、开发插件或用 DeepSeek 模型构建 Agent 的工程师
主要代价默认行为和上下文较复杂,需要理解其约定平台、权限和运行环境需要配置许多高级能力需要自己搭建生态和 API 仍在演进,插件组合、兼容性和安全需要自己判断

Claude Code:能力密度高的产品化 Agent

Claude Code 把项目指令、文件操作、shell、权限、hooks、skills、MCP 等组合成一个面向软件工程的完整体验。它的优势是把大量常见工作流预先产品化:用户可以直接在仓库中描述目标,让 Agent 自己搜索、编辑、运行验证。

它的代价是“默认世界”比较大:系统提示、工具协议、项目规则和扩展都可能参与一次调用。对于希望少操心基础设施的人,这种默认值很有价值;对于想精确控制 Token、上下文和循环的人,则需要理解并调整这些层。

Codex:把 Agent 作为可受控的运行时

Codex 可以从 CLI、应用和其他客户端使用。它的关键不只是“会写代码”,而是把 thread 生命周期、配置认证、工具执行、沙箱、MCP、Skills 和客户端集成放进一个可持续演进的运行时。这样,终端、IDE 和桌面应用可以共享同一类 Agent 核心,而不必各自重写循环。

它代表一种产品化方向:Agent 不再只是一个命令行 UI,而是一个可以被多个界面驱动、能够持久化和审计的服务/运行时。相应地,用户需要更多理解权限、沙箱、网络访问和线程状态。

Pi:把“Agent 是什么”缩到最小

Pi 的有趣之处在于它刻意不替用户预装所有复杂性。最小的四工具闭环已经能完成很多 coding task,其他能力可以通过扩展和 packages 逐步加入。

它更像一个可编程材料:你可以从一个小核心开始,自己决定是否需要 MCP、子 Agent、计划模式、主题、RPC 或 SDK。这个取舍让 Pi 特别适合研究 Agent 原理、适配不同模型、构建自己的工作流;但它也要求使用者承担更多设计工作。

DeepSeek Harness:把“Everything is a Plugin”贯彻到底

DeepSeek Harness 的核心取舍不是只提供一个更轻的 coding agent,而是把 Harness 的组成部分都放进插件模型:模型 provider、工具、Skill、session、sandbox、filesystem、loop、scheduler 甚至 UI 都可以被替换和组合。它更像一个可以装配 Agent 的运行时,而不是一个固定功能的客户端。

它还提供不同的运行预设:标准模式提供完整能力,Code Mode 让模型通过 SDK 把多步操作组合成程序,Minimal 模式只保留持久化 bash 和编辑器,Creator 模式则帮助开发者检查运行时、实验插件并创建自己的 preset。对想研究 Harness 的工程师来说,这种“把脚手架本身暴露出来”的设计很有意思;对只想马上完成任务的用户来说,插件和预设也意味着更多需要理解的配置。

自定义 Harness:当工作流本身就是产品

如果任务有强业务约束,例如处理生产事故、审批金融操作、运行长时间数据管道,通用 coding agent 可能不够。这时可以自己构建 Harness:

任务状态机
模型负责局部判断
确定性工具负责关键动作
策略引擎负责审批和权限
验证器负责验收
事件日志和可恢复状态

自定义 Harness 的优势是可以把不可违反的规则写成代码,把 Agent 放在适合它的模糊判断环节;缺点是你需要自己维护模型适配、上下文策略、错误恢复、观测、成本和安全。

9. 模型越强,Harness 是否应该越轻

你的这个感觉是成立的,但需要加一个限定:随着模型的工具使用、规划和自我修正能力增强,过重的 Harness 确实可能从“脚手架”变成“限制器”;但安全、验证和状态管理这些确定性能力不会因为模型变强而自动消失。

可以把 Harness 看成模型和环境之间的一层接口。如果模型还不擅长使用工具,Harness 需要提供更多流程引导;如果模型已经能自己决定先搜索、再修改、再测试,那么过多的固定步骤、重复提示和封闭工具会限制它的行动空间。

弱模型 + 重 Harness
  → 需要更多流程、示例、专用工具和强约束

强模型 + 轻 Harness
  → 只提供清晰的 Primitive、真实反馈和安全边界

强模型 + 过重 Harness
  → 可能被固定流程、提示噪声和工具选择限制

过重 Harness 常见的限制方式包括:

  • Prompt tax:每次调用都附带大量静态规则和工具描述,真正的任务反而被挤到 Context 边缘;
  • 流程锁定:强制模型先规划、再分解、再执行固定步骤,模型无法根据任务简单程度选择更短路径;
  • 工具替代判断:为每种场景制作一个高级工具,模型被迫在大量近似 Tool 中选择,而不是组合少量正交 Primitive;
  • 反馈失真:Harness 只返回摘要或预设状态,模型看不到足够的原始事实,无法自行诊断;
  • 能力封顶:系统只允许产品设计者预想过的动作,模型即使知道更好的 CLI 或脚本路径,也无法尝试。

这也是 Pi 的最小主义和 DeepSeek Harness 的插件化值得研究的原因:它们把更多控制权交还给模型或使用者,让 Harness 不必替模型预先写完所有工作流。对于能力很强的模型,一个清晰的 bash、文件工具、测试反馈和可控环境,可能比十个“智能助手”式的高级 API 更能发挥能力。

但轻并不等于裸奔。以下能力最好仍由 Harness 用确定性代码负责:

模型可以决定:下一步读哪个文件、运行哪个测试、是否需要继续
Harness 必须决定:能不能访问、是否需要批准、最多运行多久、结果如何验证

换句话说,应该减少的是替模型做认知决策的部分,而不是减少安全边界、验证器、状态持久化和故障恢复。理想状态不是“没有 Harness”,而是一个薄而透明、可替换、可观察、会随模型能力变化而收缩或扩展的 Harness

这会带来一个新的设计问题:Harness 不应该只有一个固定档位。简单任务可以走 Minimal Loop;复杂任务再按需启用 Skill、MCP、Subagent、Compaction 和审批。让能力渐进式出现,通常比一开始把整个系统的复杂性都暴露给模型更好。

10. 不要只比较 Agent,要比较 Model × Harness

“哪个 Agent 最强”通常不是一个稳定问题。更合理的单位是:

一次真实结果 = Model × Harness × Context × Environment × Human policy

同一个模型在四个 Harness 中可能表现不同:

  • Harness A 自动读取正确的文件,并在每次修改后运行测试;
  • Harness B 把整个仓库塞进 Context,却不告诉模型测试结果;
  • Harness C 工具权限太少,模型只能输出建议;
  • Harness D 权限太大,但没有验证和停止条件。

如果要做公平比较,至少应该固定:模型版本、任务、仓库状态、工具权限、网络条件、上下文预算、是否允许人工干预、成功标准和总成本。否则比较出来的往往不是 Agent 能力,而是默认配置差异。

对日常使用者,可以用下面的问题选择:

你的问题更可能适合
我只想在仓库里直接完成开发任务Claude Code / Codex
我想把 Agent 接到 IDE、服务或自己的产品Codex 或自定义 Harness
我想理解 Agent 最小闭环并自己改造Pi
我有严格审批、审计、状态机和长任务需求自定义 Harness,必要时组合现成 Agent

11. Agent 最容易失败的地方

把计划当成进展

模型说“我会修改 A、运行 B、检查 C”,不代表这些事已经发生。Harness 应该把计划和实际 Tool Call、退出码、diff 分开记录。

把工具数量当成能力

工具越多,Context 和权限复杂度越高。一个清晰的 bash 加文件工具,可能比十几个边界模糊的工具更容易让模型正确使用。工具描述必须准确,错误的 schema 会直接变成模型的错误行动。

把上下文越长越好

上下文的价值取决于相关性和时效性。旧日志、重复文件和过期规则会降低信噪比。Context engineering 的目标不是装满窗口,而是让下一次决策拥有足够事实。

让 Agent 自己宣布成功

“看起来应该可以”不是证据。测试、lint、类型检查、diff、部署预检和业务查询,应该尽量由 Harness 自动运行。

在事务或高权限环境里无限循环

长任务一定会遇到超时、上下文耗尽、网络失败、工具异常和模型重复。没有预算、checkpoint、重试上限和人工接管,Agent 的自主性就会变成不可控性。

12. 一个 Agent System 的分层模型

把前面的概念放在一起,可以得到一个由下而上的分层:

Layer 4:Coordination
         Subagent / Delegation / Communication

Layer 3:Knowledge & Integration
         Skill / Memory / MCP

Layer 2:Runtime
         Context / Loop / Compaction / Permission / Verification

Layer 1:Action Primitives
         read / write / edit / bash

每一层回答的问题不同:

  • Layer 1:我如何观察和改变环境?
  • Layer 2:我如何持续、可靠、受控地运行?
  • Layer 3:我知道什么,以及如何连接外部能力?
  • Layer 4:我如何把工作拆分给其他 Agent,并合并结果?

设计时最好从下往上增加能力。一个简单任务先用 Primitive 和 Single-Agent Loop;遇到上下文过长,再加 Compaction 或 Subagent Isolation;遇到外部系统复用,再考虑 MCP;遇到严格业务流程,才引入更复杂的协调和状态机。

总结:Prompt 是意图,Harness 是能力,Loop 是行动

可以用下面这张图记住全文:

用户意图
   ↓ Prompt
模型当前知道什么
   ↓ Context
模型能够做什么
   ↓ Harness + Tools + Skills + MCP
做了一步后现实发生了什么
   ↓ Observation
是否继续、修正、请求批准或结束
   ↓ Loop + Verification + Policy
最终结果

Agent 的核心不在于给 LLM 换一个更神秘的名字,而在于把它从“一次性文本生成器”放进一个能够观察环境、采取行动、获得反馈、持续运行并接受约束的闭环里。

Pi 展示了这个闭环可以小到四个工具和一个循环;Claude Code 和 Codex 展示了它如何被做成面向真实工程的产品;DeepSeek Harness 则展示了如何把模型、工具、循环和 UI 都拆成可替换的插件;自定义 Harness 进一步展示了当工作流、权限和验收本身成为业务时,Agent 需要怎样嵌入更大的系统。

所以,与其问“应该给 LLM 写什么 Prompt”,不如同时问四个问题:

它应该知道什么?能够做什么?每一步如何获得真实反馈?什么证据能证明它完成了?

这四个问题,才是从 Prompt 走向 Agent 的起点。

References