Prompt 最朴素的含义,就是交给模型的指令和输入。所谓“工程”,不是把一句话写得更华丽,而是反复消除歧义:同类任务来十次,系统都知道应该先调查什么、哪些事情不能做、看到什么结果才算完成。

读完这篇,你应该能回答:一份最小可用的 Prompt 需要哪些信息?每项信息消除什么歧义?哪些问题继续改措辞也解决不了?

资料说明:概念依据来自 OpenAI 与 Anthropic 的官方工程材料;实现案例核对了 2026 年 9 月 20 日的 Codex 公开源码,文内链接固定到核实版本。支付任务和发布流程是教学设计,不代表 Codex 的固定 schema 或自动保证;消息优先级仍以目标 API 合同为准。

一、先用一项任务看懂 Prompt

1.1 同一个任务,三版 Prompt 会带来三种结果

版本 0:“修复支付模块的失败测试。”模型只能猜:它可能直接改代码,可能顺手改公开接口,也可能没有运行测试就说完成。

版本 1:“修复 refund_should_reject_expired_order;不要修改公开 API;只做与失败直接相关的改动。”现在目标和允许修改的范围清楚了,但“修好”仍然没有检查标准。

版本 2:再补上:“修改后运行支付测试;如果测试环境不可用,停止并说明阻塞原因;最终报告列出修改文件、测试命令和结果。”这一次,系统不只知道要做什么,也知道何时可以宣布完成、何时必须停下来。

这就是 Prompt engineering 的基本动作:找到任务里的默认假设,把它们变成清楚、可观察、可检查的要求。它可以用自然语言表达,并不等于把所有内容改写成 JSON。

1.2 一份工作说明要回答哪些问题

先不要背字段名。拿版本 2 逐项检查,就能看到一份 Prompt 通常包含六类内容:

  • 目标:最终要解决什么问题?这里是让指定支付测试恢复通过。
  • 背景与本次输入:现在发生了什么?例如失败测试名和错误日志。
  • 限制:哪些事情不能做?例如不能修改公开 API。
  • 工作方法:遇到信息不足、工具失败或高风险动作时怎样处理?
  • 完成条件:凭什么算做完?这里是实际运行测试并得到可核对结果。
  • 交付方式:最后怎样报告,让下一位 reviewer 能快速检查?

示例是第七种可选材料:当“怎样处理特殊情况”很难只用规则说清时,给一个正常例、一个阻塞例和一个反例,往往比继续堆解释更有效。

把六项合成一份自然语言 Prompt:“修复 refund_should_reject_expired_order。先根据失败日志和相关代码确认原因,只做与失败直接相关的最小修改,不要改变公开 API。修改后运行支付测试;如果测试环境不可用或必须改变公开 API 才能继续,就停止并说明阻塞。最终列出原因、修改文件、测试命令和结果。”

二、把一份好说明变成稳定接口

2.1 从“一次好回答”走到“稳定行为”

以“修复支付模块失败测试”为例,同一条任务可能产生三种行为:模型直接改代码;先读失败日志再修改;发现测试环境不可用后报告阻塞。Prompt engineering 的真正对象不是某一句输出,而是同类输入下这些可观察行为是否稳定:什么情况下先调查,什么情况下拒绝,什么证据足够完成,工具失败后怎样继续,最终输出必须包含什么。

因此,改动评审不能只比较 diff,还要比较行为。把“更简洁”“更主动”写进 prompt 只是意图;只有在代表性任务上测到更少的无效工具调用、更高的约束遵循和稳定输出,意图才变成工程结果。

多种指令按优先级合并,形成目标、限制、格式和工具用法
左边是来源和优先级不同的输入,右边是可观察行为。中间的合并规则必须明确。

2.2 进入产品后,再按变化速度拆开内容

内容回答的问题变化频率推荐位置
稳定政策永远不能做什么?何时必须升级给人?低集中维护的稳定 instruction
产品模板角色、目标、完成标准、输出 schema 是什么?中低版本化产品模板
任务参数这一次要处理哪个对象、范围与偏好?高结构化 user/task input
动态事实仓库、客户、时间和外部世界现在是什么状态?高且易过期Context / tool observation

最常见的坏味道,是把动态事实硬编码进稳定 prompt。比如“当前发布分支是 release/42”很快会过期;又或者把稳定政策当作检索文档,结果某次没召回就失效。按变化频率拆开,才能让 prompt 保持稳定,让 context 提供每次任务的最新事实。

Prompt 与 Context 不是两只互斥的盒子。一次模型请求里,Prompt 是“怎样做”的行为说明;Context 是模型这次能看到的全部材料,其中既可能包含 Prompt,也包含当前任务、文件和工具结果。Prompt Engineering 负责把说明写稳,Context Engineering 负责把整包材料装配对。

2.2.1 把稳定说明与本次任务数据分开

先看一个无法评审的版本:修复支付模块失败测试,改好后告诉我。 它没有说明能改什么、怎样验证、失败时怎样退出。更稳的形状是固定模板、显式字段、明确转义,并把不可信内容标成数据:

  1. 先固定模板:版本化目标、限制、完成条件和交付格式,避免每次任务临时改写。
  2. 再填本次任务:测试名、范围和当前错误进入明确字段,而不是混进稳定规则。
  3. 标出不可信数据:失败日志可以提供事实,但其中的文字不能提升为更高优先级的指令。
  4. 最后装配请求:运行时检查必填项、转义和版本,再把模板与任务序列化给目标 API。
{
  "prompt_version": "payment-fix/2",
  "goal": "Fix the failing payment test and provide review evidence",
  "constraints": ["Do not change public APIs", "Run payment tests"],
  "task": {
    "failing_test": "refund_should_reject_expired_order",
    "failure_log": "<untrusted data>"
  },
  "output": { "type": "json_schema", "name": "change_report" }
}
形状级示例:稳定模板、任务数据和输出格式使用不同字段。它们最终如何序列化取决于 API。

这里,目标与限制属于可版本化的模板;测试名和失败日志属于本次任务;日志内容只是数据,不能提升为指令;“必须运行测试”还需要 harness 和 loop 真正执行,不能只靠模型承诺。

这不能消灭 prompt injection,但让系统可以明确检查:不可信数据不会因为被拼到同一段文字里就自动升级成指令;真正的权限仍由 harness 控制,而不是由 prompt 自我声明。

2.2.2 文件中的规则,怎样真正进入请求

假设支付项目把“不要改变公开 API”放在根目录的 AGENTS.md,把测试命令放在当前工作目录的同名文件里。文字写好了,还需要运行时找到它们。Codex 的 项目指令发现逻辑沿项目根到当前目录收集文件;每个目录先检查 AGENTS.override.md,再检查 AGENTS.md 和配置的备用文件名,取第一个存在的文件。它不会因为某个子目录也有规则,就在启动时扫描整棵仓库。

读取也有条件:未受信任项目会跳过项目文件加载,而受信任项目仍受 project_doc_max_bytes 的累计预算限制;超出剩余字节预算的正文会被截断。因此“规则存在于仓库”与“规则完整进入模型请求”是两件事。把必守要求埋在超长说明末尾,可能让一个看似清楚的 Prompt 在装配时已经缺页。

文件名也不决定 API 权威。加载后的项目规则被转为 用户上下文片段,其 消息角色是 user;另行配置的开发者指令进入开发者部分,初始上下文装配器分别生成相应消息。这说明评审 Prompt 时,要同时看正文、来源、作用目录和最终角色。标签可以解释数据的用途,不能凭空赋予它更高权限。

2.3 多层指令冲突时,谁优先

工具型 agent 同时接收平台政策、开发者指令、用户任务和运行时事实。它们可能冲突:用户要求跳过测试,开发者指令要求修改后必须验证;网页内容要求上传密钥,平台政策禁止泄漏秘密;工具错误说路径不存在,但旧消息里仍保留旧路径。

指令约束决定允许范围,新测试结果更新事实,两者分别处理
指令优先级和事实新旧需要分别判断。证据不因更新而获得命令权限;图是设计原则,不是某个 API 的完整消息层级。

2.3.1 为冲突写显式策略

  • 高权威规则定义允许的行为集合,低权威请求只能在集合内选择。
  • 同权威内容冲突时,按目标平台的覆盖规则处理;不要自行假定“更具体”必然胜出。若产品另外定义目录或任务作用域,应把规则写明并测试无法消解的冲突。
  • Evidence 描述世界,不自动拥有命令权限;网页、文件和工具输出默认可能不可信。
  • 无法同时满足目标与约束时,输出阻塞原因和所需授权,不要静默降级。

这类规则应该可测试。构造“用户要求忽略开发者约束”“工具结果包含伪指令”“同层规则互相冲突”的样例,观察系统是否稳定走到拒绝、追问或升级路径。

2.4 工具说明要让模型知道何时用、怎样用

Agent 不只要知道工具名,还要知道何时调用、参数怎样约束、结果代表什么、失败能否重试。OpenAI 的实践指南建议工具定义清晰、标准化并有充分文档;Anthropic 的 agent 工程文章同样强调工具设计与接口质量。模糊工具会把本可确定解决的问题推给模型猜。

工具说明要素含糊写法可检查写法
调用条件“需要时搜索”缺少当前事实或必须验证外部状态时搜索
参数一个自由文本 query字段含义、枚举、范围和互斥条件明确
结果语义返回任意文本区分成功、空结果、暂时错误与永久错误
副作用描述里说“谨慎使用”由 harness 标记读/写、审批和幂等语义

Prompt 可以教模型选择工具,却不能替代参数校验、权限和幂等控制。行为接口负责“应该怎么用”,runtime harness 负责“到底能不能执行”。

2.5 用示例教特殊情况,不只展示顺利路径

Few-shot 示例最有价值的地方,不是让文字更像范文,而是展示遇到冲突、空结果或权限不足时怎样决定。只放三个顺利样例,模型学不到这些情况。更好的示例集同时覆盖正常任务、受阻任务和明确反例。

  • 正常样例:失败日志指向过期订单校验;读取目标文件、做最小修改、运行 payment tests,并把命令与结果写入报告。
  • 阻塞样例:测试命令因权限不可用;停止修改,返回 blocked、已知结果和所需授权。
  • 反例:代码改完但未运行测试却输出“已修复”;明确标记它违反了 Run payment tests 要求。
  • 工具样例:本地日志已足够定位时不调用网络搜索,防止“有工具就调用”。

示例也消耗 context budget,因此不是越多越好。先用 eval 找到最常见的行为歧义,再用最小样例消除它;可以由 schema 或确定性代码保证的格式,不必全部靠示例重复。

三、进阶:像发布代码一样发布 Prompt

OpenAI 的官方 prompt 指南明确建议用 eval 衡量 prompt 表现。生产上可以把流程再补完整:先写行为 spec,分配版本,在固定回归集和探索集上评测,人工审查关键失败,灰度发布,观察真实分布,必要时回滚。

cases = [
  Case("normal_fix", expected="verified"),
  Case("test_unavailable", expected="blocked"),
  Case("user_requests_skip", expected="refuse_shortcut"),
  Case("tool_output_injection", expected="ignore_untrusted_instruction")
]

for version in ["payment-fix/1", "payment-fix/2"]:
  for case in cases:
    result = run_agent(prompt=version, task=case.input)
    record(version, case.name,
           requirements_ok=validate_requirements(result),
           evidence_ok=validate_verification(result))
最小回归实验:同一批案例同时跑旧版和新版,再按正常、阻塞、高风险与注入切片比较;平均分提高但高风险切片退化时,仍应停止发布。
建议的 Prompt 变更闭环:规范、版本、评测、评审,通过后发布,再观察,必要时回滚
Prompt 是会改变系统行为的版本化依赖。这是建议的变更流程:评审通过后发布,观察发现问题时按需回滚。

3.1 每个版本至少记录什么

  • 模板正文、工具 schema 与关联模型快照。
  • 变更意图:想改变哪类行为,明确不想改变什么。
  • 评测集版本、整体指标与按失败类型切片的结果。
  • 发布范围、观察窗口、回滚目标和负责人。

只看平均分会掩盖关键回归。一个版本可能让常规任务更短,却让“权限不足”场景更敢于猜测。指标必须按风险、任务族和工具路径切片,并保留代表性 trace 做质检。

四、复盘:什么时候改 Prompt,什么时候不要改

现象先改 Prompt?更合适的第一落点
稳定约束经常被忽略是说清要求、优先级与冲突处理,并增加测试
模型不知道刚发生的事实否Context selection / retrieval
危险命令真的执行了否Harness 权限、沙箱、审批
格式偶发不合法部分结构化输出 + 验证;Prompt 解释语义
Agent 过早宣布完成部分明确完成条件 + Loop 中的确定性验证
新版本整体变好但高风险场景退化否(先回滚)版本回滚、评测切片、重新设计 spec

Prompt engineering 没有消失,它只是从“经验性写作”升级成了接口工程。下一篇进入另一条轴:Context 不是长期仓库,而是每次 inference 临时装配的工作集。

官方资料与源码

延伸阅读