Harness 工程完全指南:用 Claude Code 构建 AI Agent
用 Claude Code 讲清 harness engineering:工具、上下文、权限、验证、Node.js 示例和真实 workflow。
只会写 prompt,已经不足以做好 AI Agent。2026 年真正重要的能力,是 harness engineering:为模型搭好可以工作的脚手架。这里的 harness 可以理解为“agent scaffold”,也可以类比软件测试里的 test harness:它负责把模型、工具、上下文、权限、验证和循环控制接在一起。
Claude Code 是学习这件事的好样本。它不是一个单纯聊天框,而是把文件读取、编辑、shell 命令、CLAUDE.md、hooks、权限模式、subagent 和记忆系统组合成一个工作环境。本文会从零解释为什么 harness engineering 变热,给出可复制运行的 Node.js mini harness 和 policy JSON,并用 content automation、code review、SaaS integration、cloud operations、security boundaries 五个 use case 说明如何落地。
为什么 harness engineering 正在变热
LLM 很擅长“决定下一步说什么”,但真实工作不止是生成文字。一个可靠的 agent 需要观察环境、选择输入、调用工具、处理失败、保留证据、限制危险操作,并把结果交付成文件、PR、报告或线上页面。模型本身只解决了其中一部分。
Claude Code 的趋势价值就在这里。Claude Agent SDK 官方文档说明,它可以读取 Claude Code 风格的项目指令、skills、hooks 和 permissions;权限文档解释了 allow、deny、permission mode 和运行时回调;prompt caching 文档说明如何复用长的固定上下文。这些都不是“更会写 prompt”,而是模型外层的工程系统。
用 OODA loop 看会更清楚:
| 阶段 | 内容 | 主要负责人 |
|---|---|---|
| Observe | 读取文件、日志、URL、ticket、API 状态 | Harness |
| Orient | 压缩信息、组织上下文、过滤噪声 | Harness |
| Decide | 判断下一步行动 | LLM |
| Act | 执行工具、写文件、调用 API、停止 | Harness |
四个阶段里有三个主要由 harness 负责。模型再强,如果脚手架薄弱,agent 也会不稳定。
一个 harness 应该包含什么
实用的 harness 会在任务开始前回答四个问题:允许读取什么?产物是什么?成功由什么验证?哪些动作自动执行,哪些必须 ask-first,哪些永远禁止?
以博客 workflow 为例,不能只写“生成文章”。更完整的 harness 是:读取已有 slug,选择不重复的主题,写 MDX,检查 frontmatter,验证 code fence,加入官方链接和内部链接,放入 /products/ 与 /training/ 的转化 CTA,运行构建,查看公开 URL。prompt 只是其中一个输入。
| 层 | 例子 | pitfall |
|---|---|---|
| 上下文 | 项目规则、写作风格、历史失败 | 旧前提长期残留 |
| 工具 | read、grep、write、test、API 调用 | 工具太多或职责太宽 |
| 策略 | allow、ask、deny、rate limit、sandbox | 破坏性操作无人值守 |
| 验证 | test、diff、截图、公开 URL | 产物看似合理但已损坏 |
| 记忆 | 可复用偏好和决策 | 临时备注变成永久规则 |
概念图
harness 是模型前后的控制层。prompt 很重要,但 policy、context、tools、permission gate 和 verification loop 才决定 workflow 是否可靠。
flowchart LR
A["Goal"] --> B["Harness policy"]
B --> C["Context"]
B --> D["Tools"]
B --> E["Permissions"]
C --> F["LLM decision"]
D --> F
E --> G["Safe action"]
F --> G
G --> H["Verification"]
H --> I["Artifact"]
H --> B
可运行的 Node.js mini harness
下面的最小例子包含模型、两个工具、policy、循环、路径边界和可读错误。先设置 ANTHROPIC_API_KEY,再在临时目录运行:
mkdir harness-demo
cd harness-demo
npm init -y
npm install @anthropic-ai/sdk
node -e "const fs=require('node:fs');fs.mkdirSync('sandbox',{recursive:true});fs.writeFileSync('sandbox/README.md','# Demo\nShip a safer agent workflow.\nKeep writes inside sandbox.\n');"
保存 policy.json:
{
"workspace": "./sandbox",
"maxSteps": 6,
"tools": {
"read_file": {
"allow": true,
"risk": "Read UTF-8 text only inside workspace"
},
"write_file": {
"allow": true,
"risk": "Write UTF-8 text only inside workspace"
}
}
}
保存 mini-harness.mjs:
import Anthropic from "@anthropic-ai/sdk";
import { mkdir, readFile, writeFile } from "node:fs/promises";
import path from "node:path";
const client = new Anthropic();
const policy = JSON.parse(await readFile(new URL("./policy.json", import.meta.url), "utf8"));
const model = process.env.ANTHROPIC_MODEL || "claude-sonnet-4-6";
const workspace = path.resolve(policy.workspace);
function safePath(requestedPath) {
const resolved = path.resolve(workspace, requestedPath);
const inside = resolved === workspace || resolved.startsWith(workspace + path.sep);
if (!inside) {
throw new Error(`Path escapes workspace: ${requestedPath}. Use a path under ${policy.workspace}.`);
}
return resolved;
}
function ensureAllowed(toolName) {
const rule = policy.tools?.[toolName];
if (!rule?.allow) {
throw new Error(`Tool '${toolName}' is not allowed by policy.json.`);
}
}
const tools = [
{
name: "read_file",
description: "Read a UTF-8 text file from the allowed workspace.",
input_schema: {
type: "object",
properties: { path: { type: "string" } },
required: ["path"],
additionalProperties: false
}
},
{
name: "write_file",
description: "Write a UTF-8 text file inside the allowed workspace.",
input_schema: {
type: "object",
properties: {
path: { type: "string" },
content: { type: "string" }
},
required: ["path", "content"],
additionalProperties: false
}
}
];
async function executeTool(name, input) {
ensureAllowed(name);
if (name === "read_file") {
return await readFile(safePath(input.path), "utf8");
}
if (name === "write_file") {
const target = safePath(input.path);
await mkdir(path.dirname(target), { recursive: true });
await writeFile(target, input.content, "utf8");
return `written ${input.path}`;
}
throw new Error(`Unknown tool: ${name}`);
}
async function run(goal) {
const messages = [{ role: "user", content: goal }];
for (let step = 0; step < policy.maxSteps; step++) {
const response = await client.messages.create({
model,
max_tokens: 1200,
tools,
system: "You are a careful file assistant. Use tools when needed. Keep writes under policy workspace.",
messages
});
messages.push({ role: "assistant", content: response.content });
const toolUses = response.content.filter((block) => block.type === "tool_use");
if (toolUses.length === 0) {
const text = response.content
.filter((block) => block.type === "text")
.map((block) => block.text)
.join("\n");
console.log(text);
return;
}
const results = [];
for (const toolUse of toolUses) {
try {
const output = await executeTool(toolUse.name, toolUse.input);
results.push({ type: "tool_result", tool_use_id: toolUse.id, content: String(output).slice(0, 8000) });
} catch (error) {
results.push({
type: "tool_result",
tool_use_id: toolUse.id,
is_error: true,
content: error instanceof Error ? error.message : String(error)
});
}
}
messages.push({ role: "user", content: results });
}
throw new Error(`Max steps reached: ${policy.maxSteps}`);
}
const goal = process.argv.slice(2).join(" ") || "Read README.md and write summary.md with three bullet points.";
await run(goal);
运行:
node mini-harness.mjs
这个例子很小,但已经具备核心结构:工具 schema、policy、sandbox 路径、最大步数、可读错误、具体产物。继续加入 grep、测试命令、approval UI、SaaS API 和 hooks,就会接近 Claude Code 的工作方式。
五个具体 use case
1. content automation
薄弱的 prompt 是“写一篇博客”。强 harness 会读取已有文章,避免重复主题,生成 MDX,检查 frontmatter、code fence、内部链接、官方链接、OGP 图像和 /products/、/training/ CTA,再构建并检查公开页面。pitfall 是为了发布速度牺牲原创视角,最后得到大量浅翻译。
2. code review
PR review harness 应读取 git diff、测试输出、变更文件和项目规范,并强制 findings-first:先列 bug、risk、回归和缺失测试,再给摘要。pitfall 是模型只复述改动,看起来礼貌却没有发现问题。
3. SaaS integration Notion、HubSpot、Stripe、CRM 这类场景必须拆成 read-only、dry-run、approved write。比如读取咨询线索、分类、生成 CRM 更新草稿,最后由人确认写入。risk 是误分类的客户、账单或备注被直接写进生产系统。
4. cloud operations 云操作不是一条 deploy 命令。harness 应检查环境变量、build、diff、目标环境、rollback 方案、health endpoint 和公开 URL。pitfall 是模型只看日志最后一行,改错根因。限制重试次数和日志压缩非常重要。
5. security boundaries
安全边界不是最后补丁。Read 可以相对宽,Write 必须限制在 workspace,shell 命令要 allow-list,rm、force push、生产 DB、账单设置、secret 读取要 deny 或 ask-first。harness 是为了避免过度信任模型。
从 Claude Code 借鉴什么
第一,分层上下文。稳定项目规则放进 CLAUDE.md 或等价配置;本次任务进 plan;长期偏好进 memory。这样不会让临时决策污染长期行为。
第二,把确定性检查交给 hooks。format、lint、test、链接检查、截图验证应该由命令完成,Claude 负责解释失败和提出修复。
第三,隔离噪声。长日志、广泛搜索、多语言翻译和大型重构可以交给 subagent 或独立阶段。主上下文应该保留决策,而不是堆满中间过程。
常见 pitfall
工具太多会让模型选择困难。先从 5 到 10 个清晰工具开始。
错误不可读会阻止自我修复。不要返回 Error: failed,要说明缺少什么、在哪里、下一步可以尝试什么。
忽略 prompt caching 会增加延迟和成本。固定长上下文要与动态上下文分开。
没有验证会让“看起来正确”的产物上线。文章要检查 frontmatter 和 code fence,代码要跑测试,云操作要查 health check,SaaS 写入要有审计日志。
权限会漂移。临时方便很容易变成永久风险,所以 allow、ask、deny 规则要定期复查。
下一步
如果你要先做安全边界,请读 Claude Code 权限指南。要整理项目知识,读 CLAUDE.md 最佳实践。需要拆分重任务,读 Claude Code subagent 模式。关注成本时,再看 Claude Code token 优化。
想快速查命令,可以保留免费的 Claude Code Quick Reference Cheatsheet。需要模板、工作流和产品化材料时,从 /products/ 开始。团队如果要一起设计权限、review gate、发布验证和收入转化路径,可以从 /training/ 发起咨询。
我实际验证到的结果
在 ClaudeCodeLab 的文章流程里,harness 最大的价值不是让 AI 写得更像人,而是让失败更可见。只靠 prompt 可以生成一篇文章;加入 harness 后,可以知道正文是否足够、code fence 是否闭合、frontmatter 是否正确、链接是否存在、CTA 是否完整、公开 URL 是否能打开。这样运营一个多语言内容站,风险会小很多。
总结
Harness engineering 是设计“模型能看什么、能做什么、在哪里停下、如何验证”的工程能力。Claude Code 之所以值得学习,不只是因为模型强,而是因为它把工具、上下文、权限和验证做成了可运行的脚手架。先运行上面的 mini harness,再为自己的 use case 加一个边界和一个检查点,就是最稳的开始。
参考链接
免费 PDF: Claude Code 速查表
输入邮箱即可获取一页 PDF,整理常用命令、审查习惯和安全工作流。
我们会妥善保护你的信息,不发送垃圾邮件。
把 Claude Code 变成真正能带来结果的工作流
先领取中文说明的免费 PDF,再进入英文商品页选择合适的教材。如果你需要团队落地、流程设计或内容变现支持,也可以直接咨询。
关于作者
Masa
专注 Claude Code 实务流程、团队导入和内容转化的工程师。
相关文章
Claude Code权限安全阶梯:逐步放开访问而不失控
从只读到有限编辑、验证命令和部署检查的 Claude Code 权限升级流程。
Claude Code 小PR证据包:让小改动真正可审查
用差异、验证命令、公开URL、CTA路径和回滚说明,把Claude Code的小PR变得可审查。
Claude Code 提交前 Review Gate:同时检查差异、测试、公开 URL 和 CTA
提交前用 Claude Code 审查差异范围、build、公开 URL、Gumroad 链接、咨询 CTA、缺少测试和无关文件。