让智能体听话的不是提示词,是闸门

作者:程序员白大力 · 2026-09-28 09:13
让智能体听话的不是提示词,是闸门

封面

有一条流水线:先写文章,写完再配封面。规则白纸黑字写进技能文档——"必须先写完文章并保存,再生成封面,严禁先出图后写文或图文并行"。

结果这条规则失效了不止一次:模型在动笔前就调了出图工具,或者文章写到一半就并行去配图。出来的图跟成稿对不上,白烧一遍资源,还得重来。

顺着同一个思路复盘,另外还有两处:

■
"别把中间产物留在交付目录" → 十几个原始文件被提交进仓库
■
"这批内容发到 A 账号" → 推到了 B 账号

三件事看起来不一样,其实是同一个病:都是写在提示词里的纪律,都没有失败反馈。

一、为什么提示词里的纪律会失效

不是模型不听话,是机制不成立。三个原因:

第一,长任务会稀释注意力。 写一篇两千字的文章,上下文越滚越长,开头那句"顺序要求"的权重越来越低。它没忘,只是不再是最响的那个声音。

第二,工具就在手边。 出图工具随时可调用,没有任何东西阻止它在第 3 步调用而不是第 30 步。

第三,也是最关键的——违反了也不会报错。 顺序错了,流程照样一路走到终点,错误被"完成"这件事掩盖掉。没有红灯,就没有约束。

想明白这三点,解法也就清楚了:要么让规则形成回路(违反就报错),要么让违反在物理上不可能。

二、解法一:硬闸门,用退出码说话

把"文章写完没有"这个主观判断,改成脚本的五条客观检查:文件存在、首行是标题、字数达下限、文末有收尾标记、没有占位链接。任一不过就非零退出。

那段脚本其实就是一句话:把"该不该往下走"变成一个只有 0 和 1 两种答案的问题。 剥掉细节,核心长这样:

# gate.py 的本质:条件不满足就退出 1,后面全部停下
checks = [
    (文件存在,        "文章还没落盘"),
    (首行是标题,      "缺少标题"),
    (字数 >= 下限,    f"只写了 {n} 字,没写完"),
    (文末有收尾标记,  "没收尾"),
    (没有占位内容,    "还有占位符没清理"),
]
for 通过, 原因 in checks:
    if not 通过:
        print(f"[FAIL] {原因}")   # 说清楚缺什么,模型才知道补什么
        sys.exit(1)               # 非零退出 = 闸门关上
print("[OK] 条件满足")

就这么点东西:一份检查清单、挨个过、不过就带着原因退出。不需要复杂的框架,需要的只是"让它能失败"。

设计上有三个细节值得抄:

检查项必须可判定。 不要写"内容质量是否达标"这种模型都判不准的东西;写"字数够不够""标题在不在""有没有占位符"。

失败信息要能当下一步的输入。 输出"只写了 312 字,没写完",模型就知道该去补内容;只输出"校验失败",它只能瞎猜。

脚本不在时要有降级。 定义清楚:脚本缺失就手工完成同样几项检查,并在结果里写明检查结论。否则脚本一丢,闸门就整个消失。

一句话概括:一个模型可以忽略一段文字,但它无法忽略非零退出码。

三、解法二:解耦,让违反在物理上不可能

闸门治的是"顺序",解耦治的是"结构"。

还是那个例子:如果出图逻辑本来就写在写作技能里,那它随时可以被触发;但如果把出图拆成独立技能,而这个技能的唯一输入是"已经落盘的 md 文件"——那么在文件还不存在的时候,这个技能根本没有入口。

写作技能 ──▶ .md ──▶(可选)配图技能 ──▶(可选)发布技能

拆的时候有个验收标准很实用:删掉下游技能,上游还能不能完整工作? 能,才是真解耦。如果写作技能里还留着一句"封面由某某技能负责",那就不算——它仍然知道下游的存在,仍然可能在错误时机去触发它。

拆开之后还有个副作用是好的:同一份配图逻辑不用在四五个写作技能里各写一遍,改一处就够了。

四、解法三:自检命令,治"事后清理"型纪律

有一类纪律是事后才有意义的:不要留中间产物、不要留废弃版本、提交前检查范围。这类靠"记得清理"同样没用,要变成收尾必跑的自检命令。

比如"有没有孤儿文件(有图但没有对应文章)":

for d in */; do d=${d%/}; [ -d "$d" ] || continue
  orphan=$(ls "$d" | grep '\.png$' | sed 's/\.png$//' | while read n; do
    [ -f "$d/$n.md" ] || echo "$n.png"; done)
  [ -n "$orphan" ] && echo "[$d]" && echo "$orphan"
done

把它写进技能的收尾步骤,每次跑完自动暴露问题,而不是等到仓库涨到几百 MB 才被发现。

正是靠这条命令,才暴露了之前没注意到的状况:十几个原始文件早就被提交进去了,靠肉眼在几十个文件里根本看不出来。

五、解法四:不可逆操作,把选择变成必填参数

推错账号这类事,事后很难挽回。正确的做法是把"选哪个"从一个藏在上下文里的信息,变成一个必须显式给出的参数:

publish draft-multi manifest.json --account <必须指定>

不填就用默认,填了就按填的来——关键是这一步必须被显式说出来,而不是靠模型从对话里回忆。同类做法还有:删除前先列出完整清单、发布前回显目标、迁移前要求确认环境名。

六、什么时候该上机制

判断标准三问,命中任意一条就别再写提示词了:

问题 说明
违反之后不可逆吗? 推错账号、删文件、上线发布 → 必须上机制
违反之后浪费资源吗? 出图、长任务重跑 → 必须上机制
违反之后不报错吗? 静默失败最危险 → 必须上机制

反面例子:文章风格"要专业严谨"——主观、无法判定,这种就留在提示词里,靠示例反复校准。

七、这不是独门偏方

回头看,这套思路在社区里是有人验证过的。

一是"文档会被忽略"这件事,已经有人用更硬的方式解决了。 有工程师在社区里分享,他们干脆不用说明文件了——改用 TypeScript 的 AST 校验、pre-commit 钩子、确定性 linter 来强制规范。理由很直白:正如有人说的,"即使写得很明确的指令,也经常被忽略"——既然 markdown 靠不住,就换成会报错的东西。这正是"硬闸门"的同一个思路。

二是"顺序错了不会有人拦你"这件事,成本是可测的。 有研究显示,给智能体加说明文件会明显增加步骤与推理成本,而任务成功率并没有相应提升——这反过来说明:能用闸门表达的规则,就别写成文档;文档适合传达意图,不适合承担强制。

八、结尾

这一整套做法,说到底是把纪律从提示词层下沉到机制层。

模型能力越强,越容易给人一种"它应该懂"的错觉。但它懂不懂是一回事,环境让不让它做错是另一回事。与其反复叮嘱"记得先写文再配图",不如给它装一道门——走错了,门会响。

参考文章
■
Anthropic 官方文档《Agent Skills》:脚本作为技能中的确定性操作
■
Anthropic Engineering《Equipping agents for the real world with Agent Skills》
■
ETH Zurich SRI Lab《Evaluating AGENTS.md: Are Repository-Level Context Files Helpful for Coding Agents?》(2026 年预印本):说明文件使步骤数增加 2.45–3.92、成本上升 20%+
■
社区实践:以 AST 校验与 pre-commit 钩子替代说明文件的做法(Hacker News 讨论)

#智能体 #AI工程 #提示词工程 #自动化 #技术实践

本文由 AI 辅助生成并经人工审核发布,内容仅供参考,不构成法律意见。