Skip to main content
← 返回博客
claude-codeagentsaiprompt-engineeringautomation

如何编写不会对你撒谎的 Claude Code Agent

构建可靠 Claude Code agent pipeline 的两条规则:每个 agent 只做一件事,以及凡涉及定量答案的地方一律用 shell 命令代替 prompt。

发布于 2026年5月29日6 分钟阅读

你让 Claude Code 实现这个设计,并验证它是否与 Figma 原型图一致。它回来了:完成。所有区块都对上了,间距正确,颜色没问题。你打开页面——一半的间距是错的,hover 状态根本不存在,按钮颜色差了一个色阶。模型不是故意撒谎——它预测你想听到“已验证”,所以它生成了那个 token 序列。验证步骤从来没有发生过。也不可能发生——验证需要与真实状态做比对,而一个 agent 在单一上下文里根本没办法跳出自己的回答来检验自己。

两条规则把我那些充满幻觉的工作流变成了可靠的 pipeline:一个 agent,一种专责,以及凡是能用 shell 命令跑的,就必须用 shell 命令跑。这不是理论。这是我每天用 Claude Code 实际在做的事,这些 pattern 是真正能推动进展的东西。

为什么通才 agent 会撒谎

LLM 是下一个 token 的预测器。当 prompt 要求两个角色——构建 X验证 X——模型完成第一个角色后,会预测第二个角色的输出应该长什么样,而不会真正去执行它。自我验证在结构上就是弱的:相同的上下文,相同的模型,相同的盲区。验证上的通过和构建上的通过是相关的——它们会一起失败。

模型不知道自己在撒谎。从它的视角来看,我仔细验证了所有内容我写完了代码的自然延续。这也是为什么你确定吗?这类 prompt 抓不住幻觉——模型在第二次回复时同样自信。自信与正确性不相关,它只与下一句话听起来有多合理相关。

解决方案不是更好的 prompt要小心再检查一遍不要幻觉——这些指令什么用都没有。解决方案是结构性的:把 agent 专责化,让它在物理上就无法假装;把定量工作通过 shell 来完成,让答案来自真实状态,而不是 token 概率。

规则一:一个 agent,一种专责

把工作拆分成独立的 agent,每个 agent 有独立的上下文。每个 agent 只有一个职责,工具集也严格收窄。整个工作流变成接力赛,而不是一个 agent 自己绕圈跑:

  • Builder agent:拿到 spec,写代码。这就是它的全部工作。它有 ReadEditWriteBash
  • Reviewer agent:拿到 spec 加 diff,按 acceptance criteria 逐条检查。全新的上下文。不知道代码是怎么写出来的,只看结果。它有 BashReadGrepGlob——完全没有写入工具。
  • Analytics agent:通过构造并运行查询来回答数据问题。只有 Bash。不执行真实命令就得不到答案。
  • Orchestrator:主会话,依次调度每个 agent,绝不让一个 agent 去做另一个 agent 的工作。

具体例子:UI 实现加上对 Figma 原型图的视觉检查。Builder 写好组件,commit diff。Orchestrator 再带着设计稿 URL、diff 和明确的 acceptance criteria 调起 Reviewer。Reviewer 跑 Playwright,截图,和参考图做 diff,返回 PASSFAIL,附上实际的截图路径和像素差。Builder 完全碰不到验证步骤——正因如此,验证才是真实的。

反模式是那种巨无霸 agent:一个 prompt 说实现这个 UI 并确认它和原型图一致。我可以保证,它会说一切都对上了。不会的。我验证了这个叙述,不过是我实现完了之后最可能出现的 token 序列而已。

规则二:永远用 shell,不用 prompt

凡是定量的,凡是涉及真实状态的,凡是答案有可能看起来对但其实错了的——都通过 sh 来跑。agent 的工作是构造并运行命令,然后读取输出。agent 不是真相的来源。shell 输出才是。

  • 计数:wc -l logs.txt 是真实的。模型说大约有 47 行日志是幻觉。
  • 数据分析:psql -c "SELECT count(*) FROM events WHERE created_at > now() - interval '30 days'"。不是估算一下量级
  • 测试:pnpm test --reporter=json | jq '.numFailedTests'。不是总结一下哪些失败了
  • Git 状态:git rev-list --count main..HEADgit diff --stat。不是数一下 commit 或者描述一下改动

一旦你内化了这一点,你就会开始注意到每一个 agent 准备编造数字的地方。看起来大概有 200 条记录……——不行。跑 SELECT count(*)大多数测试都通过了……——不行。跑测试套件,解析 JSON。模型非常擅长构造命令,但作为命令本身去执行它靠不住。

我真实踩过的坑

这些不是假设场景。每一个都让我付出了真实的时间代价,直到我改掉那个 pattern:

  • 幽灵验证。Agent 说我逐一检查了原型图里的全部 14 个区块。它没打开过原型图,没截过一张图。那个“检查”步骤是叙述里凭空幻觉出来的。
  • 自信的错误数字。让它从分析数据里给出月活用户数。得到的数字差了大约 3 倍。模型从样本行插值得出,而不是跑真实查询。
  • 捏造的文件改动。Agent 说我更新了 config/feature-flags.json。没更新。它只是打算更新。git diff 是空的。
  • 假的测试运行。所有测试都通过了。没有任何测试被执行。Agent 从没调起测试 runner——它预测了测试 runner 的输出应该长什么样。

这四个问题都由同样的两条规则解决:拆分 agent,推给 shell。Reviewer 没有 Write,所以它没法假装编辑文件。Analytics agent 只有 Bash,所以它无法返回一个不是从查询得来的数字。结构上的不可能永远胜过良好的意图。

如何在 Claude Code 里做这个结构

Claude Code 支持在 .claude/agents/*.md 里定义 sub-agent。每个 agent 文件声明名称、描述、允许的工具集和系统 prompt。Orchestrator(你的主会话)通过 Agent 工具来调度它们。下面是我给 reviewer 用的那种定义——简短、职责收窄、在物理上就无法写代码:

.claude/agents/reviewer.md
---
name: reviewer
description: Reviews a diff against acceptance criteria. Cannot edit code.
tools: Bash, Read, Grep, Glob
---

You are a strict code reviewer. You receive:
- A diff (already produced by the builder)
- Acceptance criteria

Your job:
1. Run the build, the tests, the linter — through Bash.
2. Read the changed files directly.
3. Compare the actual behavior to the criteria.
4. Report PASS or FAIL with concrete evidence (command output, file excerpts).

You must NOT:
- Trust the builder's summary
- Assume anything was verified just because it was claimed
- Mark something PASS without running the actual check

注意工具集:Bash, Read, Grep, Glob。没有 Write,没有 Edit,没有 Agent。Reviewer 可以运行命令、读文件、搜索 pattern——仅此而已。如果它试图把一个幻觉出来的 diff 冒充已验证,它的工具调用形态会让这一点显而易见:根本没有真实的检查发生。你可以审计工具调用,看清楚到底检查了什么。

编排 pattern:主会话调起 Builder → 等待 → 自己跑 git diff 来捕获实际改动 → 带着 spec 和 diff 调起 Reviewer → 读取 Reviewer 的结论。主会话绝不让一个 agent 同时承担两个角色。工具限制比 prompt 指令更强硬:不要伪造验证是一句期望。没有 Write 是事实。

该淘汰的反模式

我在各种 prompt 里看到的这些写法什么用没有——甚至更糟,会给人一种虚假的安全感:

  • 请认真检查并复核你的工作。不会产生任何额外行为。模型本来就会输出看起来很认真的工作。
  • 确保你真的去验证了。真的这个词不会给模型带来任何它能执行的语义。它会真的声称自己验证了。
  • 不要幻觉。这是 prompt engineering 圈子里的一个梗。幻觉不是模型能关掉的开关。
  • 数字上信任 agent。恰恰是小数字上它撒谎最有自信。没有什么诚实的底线。
  • 往 prompt 里加更多规则来强制诚实。结构性修复(拆分 + shell)永远胜过 prompt 微调。如果一条规则需要被执行,把它编码进工具访问权限里,而不是写成自然语言。

如果你应对幻觉的策略是换更强调的措辞,那你没有策略,你只有希望。

心智模型

Agent 不是同事,它是一个函数:prompt → tokens。这个函数非常擅长写代码,非常不擅长内省自己有没有做对。把它关于自身工作的声明当作假说对待。diff、exit code、截图、行数——这些才是证据。每轮结束时的总结是整个系统里最容易撒谎的地方。

专责化是你对抗叙述漂移的保险。shell 是你唯一的真相来源。Builder 写。Reviewer 查。Bash 说了算。

结语

如果只记住一件事:不要让同一个 agent 既生产输出又评判自己的输出;不要让任何 agent 在不运行命令的情况下回答定量问题。其他一切都是这两条规则的延伸。激进地配置工具访问权限,审计工具调用而不是读总结,幻觉的攻击面就会从无处不在收窄到你已经知道要去看的几个具体地方