Advanced (更新于: 2026/5/19)

Claude Code/Codex 安全 Agent Harness 实战:权限、验证与回滚

用权限策略、执行计划、验证脚本和回滚日志,为 Claude Code 与 Codex 搭建更安全的 AI Agent 工作流。

Claude Code/Codex 安全 Agent Harness 实战:权限、验证与回滚

Agent 越强,外部约束越重要

刚开始使用 Claude Code 或 Codex 时,很多人会把重点放在提示词上。小修小改时,这确实有效。但一旦你开始让 Agent 处理部署、SaaS API、文件编辑、文章发布、邮件发送,问题就不再只是提示词了。

真正重要的是 Agent 外面的足场,也就是 Agent Harness。

本文把 Agent Harness 定义为:让 AI Agent 安全工作的外部结构,包括权限规则、执行计划、验证脚本、运行日志和回滚路径。Agent 仍然负责理解任务、生成代码和提出改动,但它不能无条件执行所有命令。

如果想先理解概念,可以从 harness engineering 指南 开始。想看具体事故,可以阅读 Claude Code 安全失败案例。如果需要长期上下文管理,也可以结合 Claude Code 与 Obsidian 集成

这个思路适用于 Claude Code,也适用于 Codex。工具不同,安全结构是相同的。

User request
  |
  v
Agent
  |
  v
[1] Policy layer       哪些可以执行,哪些要询问,哪些必须禁止
[2] Plan layer         先做什么,后做什么
[3] Verification layer 如何确认真的成功
[4] Recovery layer     失败后如何恢复
  |
  v
Files / shell / SaaS APIs / deploy

Claude Code 官方文档中也把 settings、permissions、hooks、MCP 等能力拆开说明。可以参考 Claude Code settingsHooks referenceMCP 文档

实例1:内容发布 Agent Harness

“发布一篇文章”听起来像一个动作,但实际上是一条工作流。

1. 读取最近7天的访问数据
2. 从高流量主题周边选择新题目
3. 检查是否和旧文章重复
4. 写日文或英文源稿
5. 生成所有语言版本
6. 检查 frontmatter、slug、内部链接
7. 构建网站
8. 检查公开 URL
9. commit 并 push

如果这些步骤只存在于人的记忆中,Agent 很容易只完成“看得见”的部分,比如写正文,却忘记翻译、构建或线上确认。Plan layer 的价值,就是把这些步骤变成固定流程。

实例2:SaaS 连接 Agent Harness

SaaS 连接更需要边界。比如让 Agent 搜集公司信息、生成样例网站、起草销售邮件。

1. 读取公开网页
2. 保存公司名、网站和邮箱
3. 生成样例 landing page
4. 起草邮件
5. 发送邮件

前四步可以自动化,第五步必须要人确认。因为邮件一旦发出,就会影响真实的人,不能简单撤回。

操作是否自动原因
读取公开网页可以风险较低
保存本地CSV可以可审查
生成样例页面可以发布前可检查
起草邮件可以尚未发送
发送邮件需要确认外部影响,难以撤回

这就是 Agent Harness 的核心:读取、生成、发布、发送要分开。

Policy layer:从 allow、ask、deny 开始

最小的策略文件可以这样写。

{
  "allowCommands": [
    "npm run build",
    "npm run test",
    "node scripts/analytics-report.mjs",
    "node scripts/content-trend-report.mjs"
  ],
  "askCommands": [
    "git push",
    "wrangler pages deploy",
    "node scripts/outreach-send-mails.mjs --send"
  ],
  "denyCommands": [
    "rm -rf",
    "git reset --hard",
    "curl * | sh",
    "npm publish"
  ],
  "protectedPaths": [
    ".env",
    ".env.local",
    "claudecode-lab-sheets-f54fc47c68f0.json"
  ]
}

Claude Code 项目设置也可以表达类似边界。

{
  "$schema": "https://json.schemastore.org/claude-code-settings.json",
  "permissions": {
    "allow": [
      "Bash(npm run build)",
      "Bash(npm run test *)",
      "Bash(node scripts/content-trend-report.mjs *)"
    ],
    "ask": [
      "Bash(git push *)",
      "Bash(wrangler pages deploy *)"
    ],
    "deny": [
      "Bash(rm -rf *)",
      "Bash(git reset --hard *)",
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(./claudecode-lab-sheets-f54fc47c68f0.json)"
    ]
  }
}

不要只写“请小心处理密钥”。应该把秘密文件、破坏性命令、生产部署、外部发送操作写成明确规则。

Verification layer:把成功条件写成脚本

“仔细检查”不是验证。更好的做法是把成功条件变成命令。

// scripts/verify-published-page.mjs
const url = process.argv[2];

if (!url) {
  throw new Error("Usage: node scripts/verify-published-page.mjs <url>");
}

const response = await fetch(url, { redirect: "follow" });
if (!response.ok) {
  throw new Error(`Page returned ${response.status}: ${url}`);
}

const html = await response.text();
const checks = [
  ["title", /<title>.+<\/title>/i],
  ["description", /<meta name="description"/i],
  ["adsense", /ca-pub-2125588229998303/i],
  ["analytics", /G-3YR0LE68MJ/i]
];

for (const [name, pattern] of checks) {
  if (!pattern.test(html)) {
    throw new Error(`Missing ${name} on ${url}`);
  }
}

console.log(`OK: ${url}`);

如果文章包含代码块,还应该用 Playwright 检查手机宽度下是否横向溢出。

import { chromium } from "playwright";

const url = process.argv[2];
const browser = await chromium.launch();
const page = await browser.newPage({ viewport: { width: 390, height: 844 } });

await page.goto(url, { waitUntil: "networkidle" });

const overflowing = await page.evaluate(() => {
  return [...document.querySelectorAll("pre, code, table")]
    .filter((el) => el.scrollWidth > el.clientWidth + 4)
    .map((el) => el.textContent?.slice(0, 80));
});

await browser.close();

if (overflowing.length > 0) {
  console.error(JSON.stringify(overflowing, null, 2));
  process.exit(1);
}

Recovery layer:先记录,再回滚

自动化真正危险的地方不是失败,而是失败后不知道改了什么。每次运行都应该留下日志。

{
  "runId": "2026-05-19-article-001",
  "topic": "agent harness security",
  "changedFiles": [
    "site/src/content/blog/claude-code-codex-agent-harness-security.mdx",
    "site/src/content/blog-zh/claude-code-codex-agent-harness-security.mdx"
  ],
  "commands": [
    "node scripts/content-trend-report.mjs --days 7",
    "npm run build",
    "wrangler pages deploy dist --project-name claudecode-lab"
  ],
  "status": "deployed"
}

Git 工作流中,优先使用有目标的恢复,而不是粗暴 reset。

git status --short
git diff -- site/src/content/blog/target-article.mdx
git revert <bad-commit>

不要让 Agent 随便执行 git reset --hard,尤其是在工作区可能有他人改动时。

最小 Node.js 命令 Harness

下面是一个很小的命令分类器。

const policy = {
  allow: [
    /^node scripts\/content-trend-report\.mjs( .*)?$/,
    /^npm run build$/,
    /^npm run test$/
  ],
  ask: [
    /^git push( .*)?$/,
    /^wrangler pages deploy( .*)?$/
  ],
  deny: [
    /rm -rf/,
    /git reset --hard/,
    /curl .* \| sh/,
    /npm publish/
  ]
};

export function classifyCommand(command) {
  if (policy.deny.some((rule) => rule.test(command))) return "deny";
  if (policy.allow.some((rule) => rule.test(command))) return "allow";
  if (policy.ask.some((rule) => rule.test(command))) return "ask";
  return "ask";
}

这个代码很普通,但这正是优点。好的 harness 应该稳定、可预测、容易审查。

总结

AI Agent 的质量不只取决于提示词。真正进入实务后,质量来自模型外面的结构。

  • Policy:什么可以做,什么必须问,什么禁止
  • Plan:执行前先明确步骤
  • Verification:用命令证明成功
  • Recovery:失败后知道如何恢复

当你让 Claude Code 或 Codex 接手更多工作时,不要只加长提示词。先搭建 Agent Harness。这样才能从“能修改文件的 AI”走向“可以安全承担一部分业务流程的 AI”。

#claude-code #codex #agent-harness #security #permissions #automation
免费

免费 PDF:5 分钟看懂 Claude Code 速查表

只需留下邮箱,我们就会立即把这份 A4 一页速查表 PDF 发送给你。

我们会严格保护你的个人信息,绝不发送垃圾邮件。

把 Claude Code 变成真正能带来结果的工作流

先领取中文说明的免费 PDF,再进入英文商品页选择合适的教材。如果你需要团队落地、流程设计或内容变现支持,也可以直接咨询。

Masa

本文作者

Masa

深度使用 Claude Code 的工程师。运营 claudecode-lab.com——一个涵盖 10 种语言、超过 2,000 页内容的科技媒体。