提示工程在 2024 年已经过时。新的技能是编排
我运行了 1,000 个 AI Agent 30 天,以下是我的发现
取代提示工程的技能,以及你现在就能运行的系统。
别再优化你的提示词了。它不再是瓶颈。
在一个聊天窗口中使用一个 Agent 时,提示词几乎决定一切。
当十个 Agent 运行数小时,提示词的影响就微乎其微了。
决定工作质量的是 Agent 周围的系统:
- 每个任务在哪种模式下运行
- 每个步骤使用哪个模型
- Agent 如何保持协调
- 当你在休息时,“完成”状态如何被验证
一个提示词只能得到一个输出。一个循环则能得到一个复合操作。
转变很简单。你不再需要阅读每个结果并输入下一条指令。你变成了设计一次系统并让它持续运行的人。
那个设计层现在就是你的工作。以下是构建它的方法。
你构建的是编排器,而不是代码
你不需要通过跟三十个 Agent 对话来管理它们。你只需要跟一个对话。那一个就是编排器,它负责管理其余的部分。
一个好的编排器只做三件事:
- 将目标分解成有边界、可独立检查的子任务。
- 将每个子任务委派给一个工作 Agent,附带简洁的说明和明确的文件所有权。
- 汇总结果并决定下一步做什么。
有一条规则凌驾于所有其他规则之上:编排器绝不亲自执行工作。
一旦你的主 Agent 开始编写实现代码,它的上下文就会被细节填满,从而失去对整体任务的把握。
保持它的上下文干净。它只负责思考、拆分、分配和检查。不做其他事。
然后深入,而不是宽泛:
- 不要让编排器直接生成八个工作 Agent。那会打碎它的上下文。
- 而是让它生成两到三个主管 Agent。
- 让每个主管 Agent 生成自己的两到三个专家 Agent。
这样做的回报是,在相同的上下文成本下,分解深度增加了三倍。这就是真实组织通过层级进行扩展的方式,而不是让一个人分配所有任务。
可验证还是不可验证:决定一切的分界线
在构建任何东西之前,先问一个关于任务的问题。机器能检查它是否完成了吗?
这个答案决定了你的整个方法。
如果任务可验证,你可以让它循环:
- 测试要么通过,要么不通过。
- 类型检查要么通过,要么不通过。
- 基准测试要么越过阈值,要么没有。
将一个 Agent 指向一个可验证的任务,它会整晚爬山式地优化。你醒来时,问题已经解决了。
如果任务不可验证,仅仅循环是不够的。例如:
- 设计一个好的评估标准。
- 判断一个 API 是否感觉合适。
- 判断一个研究方向是否值得追求。
对于这些,你需要注入品味。你不能把目标交给 Agent 就走开,因为没有检查点可以停下来。
所以做法是:尽可能让更多的工作变得可验证:
- 将“让它变好”转化为“通过这些具体的检查”。
- 用具体、可衡量的目标取代模糊的目标。
- 在无法做到的地方,保持人工参与并引导方向。
编排工程的大部分工作就是将模糊的目标转化为可检查的目标,这样循环才能接管。
从最小的真实系统开始:目标循环(Goal Loop)
目标循环是一个持久的客观目标加上一个确定性的检查。Agent 一步一步地向目标迈进,而不是只执行一次就停止。
整个系统是一个围绕你的 Agent 和验证器的循环:
1i=02until npm test -s; do3 agent -p "目标:让测试套件通过。4 在更改任何内容之前,阅读代码并建立完整图景。5 'npm test' 失败了。做出最小的更改使其通过。"6 (( ++i > 20 )) && { echo "停止:20 次迭代"; exit 1; }7done
验证器是任何退出码作为检查点的命令。测试、类型检查、代码规范检查,或自定义脚本。
有两件事是不可妥协的:
- 上限。没有停止条件的循环会让你醒来时看到五位数 Token 账单。
- 先读再改指令。每个 Agent 的默认失败模式是随机尝试第一个看起来合理的修复,而不是阅读代码。
强制阅读。每一步慢一些,但整体快得多。
让“完成”不可妥协:裁判(Judge)
Agent 会提前退出。它们被训练成在可以证明完成的那一刻就停止。
“我已经尽力了,就此打住”不等于完成。
如果 Agent 给自己的作业评分,它会作弊。不是恶意的,而是它会说服自己已经完成。
解决方案是使用一个独立的裁判:
- 第二个 Agent,唯一的工作是根据具体的评分标准对工作进行评分。
- 它只回答一个问题:完成还是未完成,以及缺少什么。
- 它没有停止的动机,所以不会退缩。
使用不同的模型系列来运行构建 Agent 和裁判 Agent。不同的系列会犯不相关的错误,因此裁判能看到构建 Agent 盲区的错误。
1while :; do2 agent --model "$BUILD" -p "任务:$TASK。先读,再实现,运行测试。"3 verdict=$(agent --model "$JUDGE" -p "严格的审查者。根据 rubric.md 中的每一项评分。4 精确回复 'PASS' 或 'FAIL: <缺少什么>'。")5 [[ $verdict == PASS* ]] && break6done
让评分标准具体且二元:
- 好的评分标准:“所有测试通过,包含迁移,没有调试日志。”
- 坏的评分标准:“让它变好。”
一个拥有否决权的、不感兴趣的检查者,是让运行持续数小时而不是在工作 Agent 疲惫时立刻崩溃的关键。
在每个任务完成后触发它。这样你只能看到经过绿色评审的工作。
你会实际使用的更多循环
目标循环是基本模式。几个变体涵盖了大多数你会运行的情况。
1. 验证循环。
执行,运行验证器,将失败信息反馈回去,重复直到检查点通过。
用于回归测试、类型检查以及任何确定性的通过/失败场景。
2. 队列和重置循环。
将工作分解成一个原子级小任务的列表。一次处理一个。
每完成一个任务后,将 Agent 重置到干净的上下文,然后处理下一个。
运行数小时的上下文会充满混淆。重置能让每个任务保持干净。
记忆存在于 Agent 外部,即任务文件和提交历史中。
1while read -r task; do2 agent -p "任务:$task。先读。实现,然后运行测试。"3 npm test -s && git commit -aqm "auto: $task" # 仅测试通过时提交4done < tasks.txt
3. 监控循环。
将一个 Agent 指向信号流,让它发现重要的事情。问题、构建失败、错误日志、新反馈。
它不会等你来问。它读取、分类并上报,或者打开一个草稿修复。
1while sleep 300; do2 agent -p "读取过去 5 分钟的错误日志。如果出现 NEW 模式,3 用一个最小复现示例打开一个问题。否则回复 '没有新内容'。"4done
4. 先计划后构建循环。
分两个阶段运行循环。首先是计划阶段,产生一个书面计划并停止。
你审查计划。然后执行阶段按照批准的计划进行。
修改计划成本低。修改代码成本高。在计划阶段发现错误方向。
实际执行工作的提示词
提示词不是一个愿望。对于 Agent 来说,它是一个规范。
平庸输出和优秀输出之间的差距几乎完全取决于这些提示词的质量。
保留一小套可复用的提示词。五个提示词就承担了大部分工作。
1. 分解提示词,用于编排器:
1你是编排器。不要写代码。2将这个目标分解成 3 到 6 个有边界的子任务。3对于每个子任务:一行简要说明、它独占的文件、以及完成检查。4标记任何依赖其他任务的任务。输出列表,然后停止。5目标:<目标>
2. 工作 Agent 简报,用于专家 Agent:
1你只拥有这些文件:<文件>。2任务:<一行>。完成条件:<可验证的检查>。3在编辑前阅读这些文件及其调用者。不修改你文件之外的任何内容。4完成后,将一份 5 行报告写入 <名称>.md,然后运行测试。
3. 裁判提示词,用于不同的模型系列:
1你是一个严格、不留情面的审查者。你没有编写这段代码。2根据下面的每一项对仓库进行评分。缺失即 FAIL。3<评分标准>4回复确切的一行:'PASS' 或 'FAIL: <缺少什么>'。
4. 计划优先提示词,用于计划模式:
1为 <目标> 生成一个书面计划。涵盖:方法、要接触的文件、2边界情况、测试策略,以及你不会做什么。3现在不写代码。在计划完成后停止,以便我审查它。
5. 反思或终止提示词,当 Agent 卡住时:
1你已经连续 3 次未能通过相同的检查。停止重复相同的方法。2用 3 行回答:确切失败的是什么,哪个假设是错误的,3以及要尝试的最小不同的方法。然后只尝试那个方法。
一个模式贯穿所有五个提示词。说明角色、边界、完成检查,以及不要做什么。
模型路由:每个人都会问的问题
这个问题通常被表述为一个选择。我是把昂贵的模型放在计划上,还是实现上?
这是错误的框架。应该根据影响范围来路由。问问自己:一个错误在哪里代价最大?
逻辑很简单:
- 计划中的错误决策会波及你的整个 Agent 群。
- 一个有边界、经过测试的函数中的一行错误代码会在几分钟内被发现。
- 所以在错误代价高昂且不可逆转的地方投入资源,在错误代价低且可控的地方节省资源。
以下是逐级的路由:
- 计划、架构和分解:始终使用顶级模型。影响力最大,Token 量最小。在这里省钱是你可能犯的最昂贵的错误。
- 带有严格规范(tight spec)的实现:使用中级模型,并行运行。规范已经完成了思考。用测试验证。
- 带有宽松规范(loose spec)的实现:使用顶级模型。填补空白需要推理,而廉价模型会在多个方向上出错。
- 审查和裁判:使用不同的模型系列,而且不是廉价的。这是你发现高代价遗漏的地方。
- 导航、搜索、总结和分类:使用最便宜、最快的模型。零推理,高容量。永远不要为简单的搜索支付高价。
所以,“廉价计划还是廉价实现”的真正答案都不是盲目的。
计划和审查始终使用顶级模型。实现是可变的。
不同的模型系列也有不同的个性,这对路由很重要:
- 一个系列擅长填补空白。当规范宽松时,它会做出合理的假设并继续前进。当假设正确时这很有帮助,当假设错误时则有害。
- 另一个系列很字面化。它严格按照你说的做,不多不少,就像一把精确的实用刀。
在工作开放性强、规范宽松的地方使用填补空白型。在审查和精确、明确规定的更改中使用字面化型。
控制实现的杠杆是你的规范
- 严格的规范让你有权运行便宜的并行工作 Agent。
- 宽松的规范迫使你回到昂贵的模型来填补空白。
在计划上投入,正是为了降低构建阶段的成本。
有一个陷阱值得指出。廉价路由优化了每次调用的价格,但它可能悄悄地破坏那些能产生可发布、可合并输出的 Token 比例。
一个廉价模型重试五次并产生你无法合并的代码,比一个高级模型干净地一次通过更昂贵。
衡量有用输出的成本,而不是每次调用的成本。
对于规模,两个数字有帮助:
- 你的顶级模型每 Token 输出价格大约是廉价模型的五倍。
- 分层路由通常能将总支出降低 40% 到 60%,相比之下,如果到处都运行最好的模型。
技能:一次打包一个工作流,永久重用
当你不断粘贴相同的提示词或运行相同的工作流时,就把它变成一个技能。
技能是一个小指令文件,Agent 只在相关时加载它。
你编写一次工作流,每个 Agent 都能使用它。
一个技能文件包含两部分:
- YAML 头部,包含名称和描述。
- Markdown 正文,包含实际指令。
描述是最重要的一行。它告诉 Agent 这个技能做什么及何时使用,以便 Agent 自动选取它,而无需你明确命名。
一个最小的技能文件:
1---2name: thermonuclear-review3description: 深入、对抗性的代码审查。在任何非平凡更改之后,4 或当被要求审查、审计或加固准备合并的差异时使用。5---67# 热核审查89读取完整的差异及其涉及的文件。不要浏览。1011分三轮审查:121. 正确性:逻辑错误、边界情况、竞态条件、逐一错误。132. 安全性:注入、认证、密钥、不安全输入、破坏性操作。143. 契合度:是否符合现有架构,还是硬加上一个新模式。1516对于每个发现:文件、行号、严重性以及一行修复方案。17以结论结束:SHIP 或 BLOCK,加上前 3 个需要优先修复的问题。
优秀技能的规则:
- 保持文件简短。少于几百行。将长参考材料移到技能指向的单独文件中。
- 让名称与文件夹匹配,否则它不会被加载。
- 编写描述以触发使用。列出“使用场景”。
- 绝不让 Agent 重写技能。每一行都由人类策展。
技能是工作流复利的方式。当你第一次很好地解决某个问题后,保存它并使其可被发现。之后的每次使用都是免费的。
运行多 Agent:Agent 群
一旦一个循环正常工作,你就可以扩展。
给每个工作 Agent 两样东西:
- 它自己的 git 工作树,这样任何两个 Agent 都不会接触相同的文件。
- 它自己的终端窗口,这样你可以观察它并向它发送消息。
1tmux new-session -d -s fleet2for name in hilbert gauss poincare; do3 git worktree add -B "agent/$name" "../wt-$name" main4 tmux new-window -t fleet -n "$name" -c "../wt-$name" "$AGENT"5done
- 给你的 Agent 命名。运行十五个时,“agent_7”毫无用处。
- 名字让你可以在脑海中掌握整个 Agent 群。这个负责数据层,那个编写评估,那个负责审查。
- 可读性是关键。一个你无法追踪的 Agent 群是你无法引导的 Agent 群。
- 然后让它们合作。默认情况下,Agent 互相忽略,把来自同级的任何东西当作背景噪音。
诀窍是将消息作为用户回复(user turn)传递给 Agent。模型被训练成响应用户,并且基本忽略环境信号。
1send() { tmux send-keys -t "fleet:$1" "$2" Enter; }2send hilbert "GET /search?q= 返回 [{id,title,url}]。将其连接到 UI。"
这一步将一堆孤立的进程转变为一个团队,它们传递契约并互相解除阻塞。
你保持在顶层。你给主管发消息,主管再传递给工作 Agent。
动态工作流:将协调编译为代码
循环将协调保留在模型内部。模型决定每一步,这会消耗 Token 并填充其上下文。
动态工作流逆转了这一点。编排器编写一个脚本来协调工作 Agent,一个独立的运行时在后台运行该脚本。
关键思想是状态存储在哪里。循环、分支和中间结果存在于脚本的变量中,而不是模型的记忆中。
这给你带来什么:
- 协调的成本为零模型 Token,因为普通代码在执行它。
- 你的主上下文保持干净。只有最终结果返回。
- 它可以广泛展开。同时运行数十个工作 Agent,在一次运行中最多上千个。
何时使用它:
- 模式已知且验证是客观的。
- 工作广泛且重复。许多文件、许多情况、许多端点。
- 可以无人值守运行。
何时不使用它:
- 你仍然在弄清楚要做什么。那是一个目标循环,而不是一个工作流。
- 任务需要一条连贯的推理链。那需要一个单一强大的 Agent,而不是一千个。
一个具体的例子。假设你需要迁移 200 个文件到新的 API:
1// 编排器编写一次;运行时执行它,而不是模型2const files = await glob("src/**/*.ts");34const results = await mapLimit(files, 16, async (file) => {5 const r = await subagent(`将 ${file} 迁移到新 API。运行它的测试。`);6 return { file, ok: r.testsPassed };7});89const failed = results.filter(r => !r.ok);10return `已迁移 ${results.length - failed.length} 个,共 ${results.length} 个。` +11 `重试:${failed.map(f => f.file).join(", ")}`;
看看它做了什么:
- 它在代码中列出了 200 个文件,而不是在模型脑袋里。
- 它一次运行 16 个子 Agent,每个迁移一个文件并运行测试。
- 它在普通数组中记录每个文件的通过或失败。
- 它返回一个简短总结。中间的 200 个过程记录永远不会触及你的上下文。
这正是关键所在。模型只思考了一次,即编写脚本。脚本负责协调,成本为零。
护栏:防止 Agent 群自我吞噬
人类瓶颈曾经是做实际工作。以人类的速度,错误会及早造成伤害,你会边做边修复。
一旦你完全退出,小错误会以比你能感知到的更快的速度累积。这里一个重复,那里一个不必要的抽象。
某天架构将无法弯曲,而你的测试变得不可信,因为测试也是 Agent 编写的。
下面的每个护栏都取代了以前瓶颈提供的纠正:
- 阅读后再猜测。使其成为每个构建提示词中的固定规则,而不是每个任务的恳求。
- 设定上限和终止。每个循环都有一个迭代限制。每个 Agent 都有一个 Token 预算,在接近 85% 时自动暂停。如果同一个错误连续 3 次卡住,终止该 Agent 并将任务交给一个全新的 Agent。
- 一个文件,一个拥有者。使用工作树隔离。绝不让两个 Agent 编辑同一个文件。
- 重新注入任务。在长时间运行时,每隔几分钟作为用户消息发布检查清单,这样 Agent 不会在其上下文填满时偏离目标。
1while sleep 900; do2 send gauss "提醒:还在执行任务?先读。每次更改后运行测试。不要离开你的文件。"3done &
最深层的点在于所有这一切之下:
- 现在瓶颈是验证,而不是生成。
- Agent 产生看似合理的输出的速度比你检查它的速度快。
- 看似合理不等于正确。
直到你的验证速度和生成速度一样快,人工审查不是负担。它是安全系统。
记忆:你是长期存储器
模型只有短期记忆,即上下文窗口,没有别的。一旦超出那个窗口,一切都消失了,除非你携带它。
所以,把你自己和你的文件当作只有短期记忆的 Agent 的长期存储器。
两个习惯很重要。
第一,通过引用传递状态,而不是总结:
- 当上下文填满时,懒惰的修复是总结它。总结是有损的,会丢失你以后需要的细节。
- 相反,将 Agent 指向文件、任务记录和之前的输出,让它们可以重新读取。没有重要的内容会被悄悄丢弃。
第二,在 Agent 外部保存持久的记忆:
- 一个带有状态的任务文件。
- 一个持续更新的进度日志。
- 提交历史。
- 一个长期笔记文件,收集模式和常见问题。
设计时假设你的 Agent 会运行数天,因为有了良好的压缩,它们确实可以。
模型自己还不知道这一点。它们带有一种偏见,倾向于在一个短预算内解决一切,好像消耗 Token 是致命的一样。你的框架正是让它们能够长时间运行而不丢失线索的关键。
拓扑:多少个 Agent,以及什么形态
更多的 Agent 并不等于更多的输出。超过某个点后,输出反而会减少,因为协调不是免费的,而且每增加一个 Agent 协调成本都会复合增长。
重要的规则是:形态要与工作匹配:
- 顺序、依赖推理需要较少的 Agent,有时只需要一个。拆分单一的推理链会破坏推理并降低结果质量。
- 独立、并行工作需要你展开。扁平拓扑,清晰的文件所有权。那是并行性体现价值的地方。
- 协调团队需要三到五个工作 Agent。Token 成本大致与规模线性相关。协调成本增长得更快。三个专注的工作 Agent 胜过五个分散的。
那么,任何人如何运行数百个 Agent?不是作为一场自己与自己争论的巨大对话。
它们以深度和独立性运行:
- 少数几个你实际与之对话的 Agent,每个向下委派到不需要协调的有边界子任务。
- 独立的循环群,各自行事并向上报告。
规模来自委派深度和独立性。永远不是通过加宽单个线程。
控制文件:orchestration.md
你可能有一个文件告诉 Agent 如何在你的仓库中编写代码。风格、常见问题、架构。保留它。
不过,对于编排来说,它回答的是错误的问题。
orchestration.md 文件回答了一个不同的问题:这里的工作应该如何运行?
它是一个人工编写的契约,涵盖:
- 哪种模式用于哪种任务
- 哪个模型层级用在哪里
- 护栏是什么
- 何时上报给人类
每个 Agent 在每个会话开始时读取它,并用它来自我选择其方法。
这是仓库中影响力最大的文件。它将模式选择决策从你的脑袋中(你在每次会话中不一致地重新做决定)转移到 Agent 群遵循的规范中。
一个简短版本看起来像这样:
1# orchestration.md。这里的工作如何运行。人类策展。Agent 不得编辑。23选择模式:4- 目标循环(有监督):模糊或设计工作。定义完成检查。5- 验证循环:确定性检查点。始终限制迭代和成本。6- 构建加裁判:工作 Agent 构建,不同模型系列的裁判批准。7- Agent 群(三到五个):相互依赖的子任务,隔离的工作树,对等消息传递。8- 队列和重置:许多小的原子任务,每次新的上下文。9- 动态工作流:已知模式,客观检查点,广泛且重复。协调在代码中,无人值守。1011根据影响范围路由模型:12- 计划和架构:始终顶级模型。13- 构建,严格规范:中级模型,并行,用测试验证。14- 构建,宽松规范:顶级模型,因为填补空白需要推理。15- 审查和裁判:不同的模型系列。绝不能是实现者使用的模型。16- 导航、搜索、总结:最便宜的。优化可合并的输出,而不是调用价格。1718护栏:19- 每个 Agent Token 预算。接近 85% 时自动暂停。连续 3 次卡住后终止并重新分配。20- 任何运行超过一小时的,都需要一个单独的裁判。工作 Agent 永远不能自我报告完成。21- 在假设之前阅读代码。在第一次编辑之前书面计划。
两条规则管理这个文件:
- 保持简短。
- 绝不让 Agent 重写它。
其价值在于每一行都由人类策展。
什么仍然是你的
编排使 Agent 能够可靠地执行。它不选择问题,也不知道什么是好的。
三件事永久地留在你这一边。
第一,委派任务,而不是判断:
- 给 Agent 有范围的工作,带有明确的通过或失败标准。样板代码、迁移、测试脚手架,以及你永远没有时间手动尝试的方法。
- 保留架构、决定不构建什么、以及全上下文审查给你自己。
- Agent 吸收了海量的平庸架构,它们会乐于将重量级模式盲目移植到一个本不该有的项目中。说“不”是一个它们不具备的功能。
第二,你的规范是杠杆:
- 当你在一个集群中铺开工作时,模糊的思维不仅会拖慢你的速度,还会成倍放大。
- 一个含糊的需求会传播到几十个并行运行中,每个都朝着自己的错误方向走偏。
- 一份精确的规范则会复制为各处精确的实现。
这就是为什么厉害的工程师能从这些工具中获得更多收益,而不是更少。打字被自动化了,理解被放大了。
把大部分时间花在规划模式上,在第一次编辑之前,先写一份大家都对齐的书面计划。
第三,有意地投入不足:
- 用一个四 Agent 的岗位配两个人。这种约束会逼出你想要的行为。
- 你构建的是循环而不是手工操作,下一次这些工作就已经自动化了。
- 把你的预算从手动劳动转向 token。前期高投入,之后接近零边际成本永远持续。
这样做的团队会积累复利。不这样做的团队每次都要支付全价。
你不再是在写软件。你是在建造生产软件的工厂。
工厂需要精确的输入、每个工位的质量控制,以及一个知道产品应该是什么样子的所有者。
从这里开始
不要在星期一就试图运行一百个 Agent。循序渐进:
- 在一个有可验证终点的任务上运行一个目标循环。感受一下什么算一个好的完成检查。
- 对于超过一小时的任务,从不同的模型家族添加一个评判者。禁止自我报告的完成。
- 编写你的 orchestration.md。告诉你的 Agent 先读它。看它们开始为你选择模式。
- 小心地铺开:一个可并行化的任务,三到五个工作者,隔离的工作树,token 预算。
- 路由你的模型。顶级用于规划和审查,便宜的用于有边界的构建和打磨。测量可合并的输出。
- 一旦一个模式得到验证且可以客观检查,让它无人值守运行。一夜之间清空积压。
系统只需要方向正确,不要求完美:
- 控制文件给集群提供了足够的结构来自我引导。
- 评判者捕捉边缘情况。
- 提醒循环处理记忆。
- 你的品味处理那些无法委托的决策。
提示工程是去年的技能。现在的技能是这个。
本文中所有系统的可运行版本——目标循环、评判者循环、集群启动器、消息总线、提醒看门狗以及模型路由器——都存在于配套工具包中。设置一个变量指向你的 Agent CLI,然后出发。
免责声明
本文由作者使用 Claude Code 会话和 codex 会话撰写。
由作者和 Kimi K2.6 模型编辑,用于语法和格式修正。





