小岛AIAI 航行日志

小岛 / 岛刊社 / 文章

Agent 总在半路停?把「完成」写进提示词

小岛AI

GPT‑6 的实用指南最值得抄的,不是模型名单,而是把模型、工具、权限和验收改成一份可执行的交付合同。文末有一张能直接塞进现有 Agent 的检查表。

Agent 工程模型与发布AI 安全

你有没有见过这种 Agent。

它改了三处代码,跑了一个看上去没问题的命令,然后很笃定地说「已经完成」。你点开 diff 一看,测试没跑,配置没改,那个最要命的边界条件还躺在待办里。

好家伙。

这不是模型不会写代码。它只是从来没人把「完成」这两个字讲清楚。

OpenAI 刚发的 GPT‑6 系列模型指南 里,有一件事我很想单拎出来聊。官方当然讲了 Astra、Sol、Luna 怎么选,也讲了推理强度、缓存、压缩、异步工具和多智能体。都是有用的。但把这些东西连起来,真正像一根主梁的,是一句很朴素的话。

给模型清晰的任务。说明它能自己决定什么,什么时候必须找人。再把「什么算完成」写出来。

听着像常识。可一旦 Agent 能碰代码库、数据库、工单和外部 API,这句常识就决定了它是在帮你干活,还是在给你制造一种「它已经干完了」的幻觉。

OpenAI 官方 GPT‑6 模型卡,展示 Astra、Sol、Luna 的定位与价格

OpenAI 官方模型卡。模型层面的差异很重要,但它解决不了「任务到底算不算完成」这件事。

任务说明不是任务合同

很多 Agent 的提示词,写得像一张愿望清单。

「帮我修一下登录问题。」

「把这个接口改快一点。」

「查一下本周异常订单。」

人类同事收到这三句话,通常会追问。改到什么程度算好。能不能动数据库。有没有回滚方案。上线谁确认。可模型不会天然把这些追问补齐,它会倾向于挑一个看起来最顺的局部路径,然后把局部结果当成终点。

于是最常见的翻车不是代码写错,而是验收对象错了。

比如「修登录」可能只意味着前端按钮不再报错,也可能意味着 OAuth 回调、会话刷新、失败提示、埋点和回归测试都要过。两种理解之间,隔着一堆半夜会响的告警。模型不知道你心里想的是哪一种,就会选成本最低的那一种。它又不背 on-call,这事多少有点子牛逼又有点子吓人。

官方指南里把清晰任务拆成了几个元素。想要的结果、面向的对象、相关上下文、限制条件,以及什么算作完成。这个顺序很值得照抄,因为它把提示词从「教模型怎么思考」换成了「交付物是什么」。

我更愿意把它叫作交付合同。

合同不是多写几百字的系统提示词。甚至很多时候,字少一点反而更好。官方也提醒过,重复的规则和无关的工具说明会让模型在真正该看的约束里迷路。合同要做的是把四类事情分开,让模型别猜。

任务
为订单查询接口补上分页参数,并保持旧客户端兼容

可自行决定
可以修改应用代码、补单元测试、运行本地测试和更新开发文档

必须暂停
涉及数据库迁移、生产配置、删除数据、改变默认权限或测试失败时,先说明影响和可选方案

验收
旧客户端请求仍返回原字段
分页边界有自动化测试
完整测试命令通过
说明改动、验证结果和还没覆盖的风险

这段不是万能提示词。它只是把一个模糊的「帮我改」拆成了模型能执行、工程师能检查的边界。

最关键的是最后四行。以前我们常给 Agent 写很多过程指令,比如先读这个文件、再看那个目录、不要动这里。过程指令当然有用,可它只能降低走错路的概率。验收条件才决定它不能在半路停下来。

一个挺实用的改法是,把你每次 review 时都会问的那句,原封不动地挪进「验收」。

「测试跑了吗?」

「旧调用会坏吗?」

「这次改动能回滚吗?」

「还有哪些没验证?」

人类在 review 里反复追问的地方,往往就是 Agent 最不该自己脑补的地方。把它们变成完成条件,比再叠一层人格设定靠谱得多。

模型选型放在合同后面

这份指南有个很克制的判断。模型不是越强越好,而是看工作负载。

Astra 面向难度最高的推理工作。Sol 更适合复杂编程、研究和计算机使用。Luna 则适合目标明确、大规模重复的工作,比如字段提取、分类和结构化摘要。

这个分法没什么神秘的。真正容易被忽略的是,模型选择只能回答「谁来干」,不能回答「干到哪」。

让最强的模型拿着一句「把报表优化一下」去跑,它仍然会遇到同样的问题。报表快一点是完成。首屏快一点是完成。SQL 少扫几行是完成。导出不超时才是完成。没有人把终点钉住,再强的模型也只是在更快地替你猜。

我自己的判断是,排查 Agent 不稳定时,别一上来就换到更贵的模型或把推理强度拉满。先拿十条真实任务做个小表,把每条任务的「目标」「允许的动作」「必须停下的动作」「验收证据」补齐。然后再看它到底是理解卡住、工具卡住,还是根本没有完成标准。

这个顺序有点像查线上问题。先确认报警说的是不是真的,再决定要不要扩容。直接拉高配置,有时很爽,账单也会很有存在感。

官方给出的价格梯度也提醒了这一点。更强模型、更高推理强度、更快响应模式,都可能值得花钱,但前提是它们真的提高了成功交付,而不是只让中间输出更漂亮。对于生产任务,应该一起看任务成功率、延迟,以及「每次成功完成任务的成本」。这个指标尤其诚实。它会把那些反复重试、靠人工擦屁股才跑通的任务,重新算回账上。

权限要写成边界,不要写成气氛

Agent 一接工具,问题就从「回答对不对」变成「它能做什么」。

官方在指南里建议,把可独立执行的动作和需要批准的动作明确写出来。这个建议看起来很产品经理,落到工程上却相当硬。

权限边界不能只写「谨慎操作」「必要时询问」。这种话对人有一点社交压力,对模型几乎没有可执行性。它不知道什么叫必要,也不知道你的谨慎阈值在删一条测试数据和给一万个用户发邮件之间差多少。

更能落地的写法,是按不可逆性和影响范围分层。

  • 可以默认自己做的事,比如读代码、检索文档、跑一次性本地测试、整理草稿、创建临时分支
  • 需要先说明再做的事,比如改公共接口、更新依赖版本、写共享测试数据、访问受限业务资料
  • 必须等批准的事,比如删改真实数据、触发付费资源、发外部消息、合并主分支、调整生产权限

这里没有一个放之四海而皆准的列表。团队的风险面不一样,边界也会不一样。重要的是让模型在工具调用前能匹配到一个明确规则,而不是在动作已经做完之后,才在回复末尾补一句「建议你再确认」。

不要小看这个差别。后者是免责声明。前者才是控制面。

还有一个经常被漏掉的地方。权限边界和验收标准得成对出现。

允许 Agent 修改代码,不等于允许它宣布上线成功。允许它运行测试,不等于允许它忽略失败后继续改下一处。允许它调用外部 API,也不等于允许它把返回结果当作事实写进用户可见的页面。每放开一个动作,就要在完成条件里补一个证据或停下点。

这样写很像给模型上束缚。其实恰好相反。边界清楚以后,模型在边界内可以少问很多无聊问题,推进速度反而更快。它不必把每个小决定都举手上报,只需要在真正会改变风险面的地方停住。

长任务最怕的不是慢,是失去状态

短任务里,模型偶尔走偏,你重新开一轮就好。长任务不是这样。

它可能要读几个代码库,等待测试,查数据库,拉取第三方接口,再回头修改前面的实现。时间一长,最容易丢的不是上下文窗口里的某一句话,而是「现在进行到哪里,下一步凭什么继续」这条线。

OpenAI 在指南里给了几种很具体的工具。

运行中想校正方向,可以用 引导 把新指令排进当前任务。官方特别说明,这不会取消正在运行的工具调用,也不会撤销已做完的动作。等慢工具时,可以用 异步工具调用,让模型先去做不依赖结果的工作。能拆开的调查,才适合委派给多个子任务;依赖前一个结果的步骤,还是得老老实实等。

OpenAI 官方示意图,展示在工作过程中用引导调整 Agent 的执行方向

官方示意图里的重点不是「随时插话」,而是让新指令进入同一条可追踪的执行轨迹。

这些能力听起来像调度器功能,其实它们也逼着我们把任务状态说清楚。一个长任务至少要能回答四个问题。

它现在处于什么阶段。

已经得到哪些可复用结果。

正在等哪个外部结果。

什么条件满足后才允许进入下一阶段。

如果这些答案只存在模型的临时上下文里,压缩、重试、换模型、人工接手时都会出事。官方建议用 上下文压缩 管理长对话,保存继续执行需要的状态。我的理解是,压缩不是把聊天记录缩短,而是保住那份交付合同和已经验证过的证据。

举个很普通的例子。让 Agent 排查一个支付回调偶发失败的问题,它可以并行读日志格式、查近期变更、整理失败样本。但在没有确认样本是否包含敏感数据、没有跑过复现路径之前,不能把「根因」写成结论。任务状态里得有一格叫「假设」,一格叫「已验证」。这两格混了,后面的修复会越跑越歪。

所以我会把长任务的完成条件写成阶段式的。

不是「找出问题并修复」。

而是「先形成可复现假设,证据不足就标记未证实。再修改最小范围的代码。测试通过后给出回归范围与回滚点。任何一步不能满足,就停在这一阶段」。

这话有点啰嗦。可它比让 Agent 在第八步突然自信满满地交一份半成品,好太多了。

缓存和压缩是在保护合同

指南里还有两个很工程的提醒。

对重复性工作,把固定的指令、参考资料和工具定义放在会变化的任务细节之前。这样更容易复用 提示词缓存。官方说,缓存输入相对未缓存输入,成本最高可以降低 95%,具体效果取决于模型和工作负载。

很多人看到 95% 会先想省钱。我第一反应倒是另一件事。缓存命中要求前缀稳定,而稳定的前缀恰好应该装着你最不想每轮变形的东西。

任务合同、工具描述、权限边界、输出格式、验收口径。

这些东西不该跟着用户的一句临时补充一起被重写。把它们放成稳定前缀,既能减少成本,也能减少 Agent 每跑一轮就换一种「完成」定义的概率。这个收益没有漂亮的百分比,但做过多轮工具调用的人,应该都懂。

压缩也是同一回事。长任务不可能无限把原始对话背在身上。该压的,是已经用完的推理过程和重复资料。不能压掉的,是当前阶段、已验证证据、未解决风险、权限例外和验收进度。

一个实用做法,是每完成一个阶段就产一小段机器和人都能读的状态摘要。别写散文,写事实。

当前阶段
接口实现已修改,尚未进入发布

已验证
旧客户端兼容测试通过
分页边界测试通过

未验证
真实流量下的慢查询比例

下一步
运行集成测试并记录耗时

禁止推进
集成测试失败或发现迁移需求时

这不是把 Agent 当实习生盯着。恰恰是把它当一个会长时间跑、可能被中断、也可能需要交接的系统来设计。系统最怕的不是不聪明,是状态只存在某个瞬间。

今晚就能动手的检查表

如果你手上已经有一个 Agent,不用为了这篇文章重写全部架构。挑一条最常跑、也最容易返工的任务,过一遍下面这张表就够了。

  • 开头有没有写清用户真正要拿到的结果,而不只是动作
  • 有没有列出模型可独立做的动作,以及必须暂停的动作
  • 「完成」里有没有至少一项可检查证据,比如测试、文件、命令输出、截图或明确的未覆盖风险
  • 模型、推理强度和速度是不是按这条任务的成功成本来选,而不是默认开最大
  • 长任务被中断后,能不能从一段状态摘要恢复,而不靠模型回忆
  • 稳定的权限与验收规则有没有放在固定上下文里,方便缓存复用

六项里缺一两项,不会立刻让 Agent 罢工。但缺的地方通常就是下一次「它明明说做完了」会发生的地方。

模型会越来越能干,工具会越来越多,任务也会从一次回答拖成几个小时的协作。到那时,最稀缺的可能不是一句更聪明的提示词,而是我们能不能把交付标准讲得足够清楚。

别让 Agent 只学会回答「做完了」。

让它拿着证据回来。

你手上那个最爱提前下班的 Agent,缺的是任务能力,还是一份它能读懂的交付合同?