OpenAI Responses API详解:system与developer迁移指南
解析OpenAI Responses API中system、developer、instructions区别,覆盖迁移方法、上下文继承和网关排错。

摘要
OpenAI 全新的 Responses API 带来了 system、developer、instructions 三套高层指令能力,很多开发者在接入、从旧 Completions 接口迁移历史会话时,很容易混淆三者定位,出现规则不生效、链路报错、多轮会话上下文丢失、网关转换异常等问题。三者并不是简单的三选一选项,分别归属请求顶层参数、消息队列 Item、历史消息角色三类不同位置,生命周期、持久化行为、网关‑适配器链路处理逻辑完全不一样。
本文梳理三者语义差异、适用场景、常见踩坑点,给出选型决策框架、完整可复现的迁移验证方案,同时说明网关、多层适配器链路下的隐蔽故障。搭建多模型兼容接口层的团队,可以借助 koalaapi 统一处理不同模型指令角色字段的格式转换。文中附带上线检查清单与FAQ,帮助开发者规避迁移过程中的隐性问题。
1 核心概念:三者不是平级可选参数
| 字段写法 | 存放位置 | 公开文档主要用途 | 高频踩坑点 |
|---|---|---|---|
system |
历史消息 Item,消息角色 | 用于历史 transcript 迁移、已经验证兼容的链路 | 把网关转换后的字段当成 Responses API 原生标准;链路拒绝 system 消息直接报错 |
developer |
input 数组内消息 Item | 应用业务逻辑、用户侧约束规则,优先级高于 user | 前端 UI 写的 system 提示词,序列化之后错误变成 developer |
instructions |
请求最顶层参数 | 单次请求生效,设置语气、目标、约束示例 | 误以为搭配 previous_response_id 之后可以自动继承延续 |
重要说明:OpenAI 迁移文档允许把旧的
system或者developer guidance映射到顶层instructions;也可以保留历史 transcript,把指令放到消息 Item。兼容性最终取决于目标模型、API 版本、中转链路(SDK、适配器、API网关),不是所有链路全部支持全部写法。 文本层面示例上,instructions和developer能力大体等价,但请求结构、会话状态持久化、链路兼容逻辑不一样,不能直接划等号。
1.1 developer:消息队列内的指令 Item
developer 属于 input 消息数组中的一员,和 user、assistant 消息并列。
- 生命周期:会跟随会话完整保存在消息序列,支持保存、重播、回放历史会话;
- 优先级:官方明确规定,
developer消息优先级高于普通user消息; - 适合场景:规则需要跟随对话一起持久化,多轮会话一直生效;业务代码自己维护消息列表。
示例 payload:
{
"model": "<已验证的模型ID>",
"input": [
{
"role":"developer",
"content":"回答前先核对用户提供的字段,不要编造缺失值。"
},
{
"role":"user",
"content":"帮我检查这份请求。"
}
]
}
优点:消息顺序直观,业务代码自主管理会话历史; 缺点:每一轮会话都需要维护消息数组,会占用上下文 token。
1.2 instructions:请求顶层单次生效指令
instructions 是请求根层级参数,不属于 input 消息数组。
- 生命周期:仅对当前这一次生成生效;使用
previous_response_id接续对话时,上一轮instructions不会自动带入下一轮请求,需要每次显式传入; - 优先级:优先级高于 input 内部用户消息;
- 适合场景:只想给本次请求附加全局约束,不需要把规则存入会话历史。
示例 payload:
{
"model":"<已验证的模型ID>",
"instructions":"回答前先核对用户提供的字段,不要编造缺失值。",
"input":"帮我检查这份请求。"
}
优点:写法简洁,不会污染消息队列; 缺点:多轮接续不会自动继承,遗忘传入就会丢失业务规则,这是最高频bug。
1.3 system:历史迁移专用角色
system 角色不再是 Responses API 原生推荐的新业务默认入口,主要用于旧会话 transcript 迁移。
- 部分中转网关、兼容链路会拒绝
system角色输入,抛出System messages are not allowed; - 出现报错不等于问题一定在模型本身,有可能是中间 SDK、适配器、网关层拦截;
- 修复方式不一定简单粗暴把
system改成developer,需要完整做两端验证。
开发常见误区:看到报错直接全局字符串替换角色字段,忽略多层链路转换,线上依旧异常。
2 为什么配置改完,接口依旧报错:多层链路陷阱
真实业务请求往往经过多层组件处理,不只是直接调用 OpenAI 原始端点:
业务代码 → SDK序列化 → 应用适配器转换 → 兼容网关二次改写 → OpenAI目标端点
UI界面、后台配置面板仅仅控制第一层入参。后续每一层适配器、网关都有可能改写消息角色、丢弃顶层字段。 只看“保存成功的配置”无法判断真实出参,必须抓最终抵达远端的真实请求体。
这一点在接入兼容网关的时候尤其关键,koalaapi 这类网关会做角色字段兼容转换,开发者必须校验经过网关转发之后的最终报文结构。
一套可落地、低误判的迁移验证流程
不要只靠单条请求做判断,完整验证分为4步:
-
固定环境基线 固定模型快照、SDK版本、网关版本,输入测试用例保持不变;只改变指令承载方式,排除模型版本、SDK版本波动带来的干扰,建议搭建 eval 测试环境。
-
两组最小用例对比测试 在同一个测试入口,分别发送两类测试请求:
- 测试A:
developer消息 + 普通user消息(消息队列模式) - 测试B:顶层
instructions+ 普通input(顶层参数模式) 目标不是选出哪个写法“更好”,而是确认目标链路两种模式都可以正常工作。
-
抓取最终出站请求 抓经过SDK、网关序列化之后的完整脱敏请求体:核对API路径、model名称、角色字段、参数位置,确认和预期一致。客户端看不到后端改写,这一步是定位问题的关键。
-
验证指令实际执行效果(不只看HTTP 200状态码) 选用一条可以客观校验的测试规则,例如:
缺失字段必须明确指出,禁止编造信息。覆盖下面全部场景:
- 首轮对话是否遵守规则;
- 使用
previous_response_id接续多轮,是否保留/丢失规则; - 网关、服务重启之后,指令行为是否稳定;
instructions与developer同时传入,冲突场景表现;- 原生OpenAI端点 和兼容网关,输出行为是否对齐;
- 不支持字段是否返回明确错误,而不是静默失效。
模型输出本身具备随机性,验收不能匹配固定文本,重点校验规则是否被执行、请求报文结构、错误分层是否符合预期。
3 选型决策表:怎么选 instructions / developer / system
| 决策问题 | 优先选 instructions | 优先选 developer | 遗留 system 历史数据怎么处理 |
|---|---|---|---|
| 是否需要 transcript 审计留痕 | 规则放在请求,单独审计 | 规则保存在消息序列,完整留存 | 边界层做明确字段转换,保留原始记录 |
| 是否是每次请求临时注入规则 | ✅适合,每次请求显式传入 | 可行,需要维护消息Item | 不建议新项目默认使用 |
| 是否要求跨轮次自动持续生效 | ❌不会自动继承,每轮手动重传 | ✅由应用保存消息,跟随会话重放 | 不要依赖链路自动兼容 |
| 是否使用缓存版本、transcript模板 | 适合,规则文本独立 | 可以跟随transcript做模板化 | 先转换为目标结构再送入链路 |
| 兼容网关完整支持该字段吗 | 核对顶层参数是否透传 | 核对角色会不会被改写 | 只有端点验证通过才保留,否则边界转换 |
核心判断:
- 规则只管控当前单次请求,不需要存入对话历史 → instructions
- 规则需要跟随对话多轮持久保存,业务自己维护会话列表 → developer
- 老项目迁移旧会话 transcript:在请求边界做转换,把历史
system映射为目标链路支持格式,新项目不要继续生成system消息。
4 权限边界:客户端看不到网关改写,排障提交材料规范
普通开发者拿不到网关转换之后的最终请求,遇到问题向技术支持提交材料,需要区分公开信息与私密敏感信息:
| 信息类别 | 可以公开对外提交 | 仅限私密受控环境提交 |
|---|---|---|
| 环境信息 | 客户端、SDK版本、操作系统;API类型、链路架构 | 完整Base‑URL、原始API Key(禁止公开) |
| 请求元信息 | 选用 instructions / developer;时间时区、HTTP状态码 | 脱敏完成的最终出站请求报文 |
| 复现场景 | 首轮、多轮、重启复现步骤 | 平台内部traceId,链路日志 |
严禁把 API Key、完整原始请求体直接粘贴到公开issue、论坛。
5 上线前检查清单
- 查阅目标API当前官方文档确认可用字段,不要记忆旧接口经验
- 明确客户端配置,序列化之后,字段最终会变成什么结构
- 使用固定模型快照,对比
developer和instructions两套行为 - 验证
instructions在previous_response_id多轮链路完整生命周期 - 验证网关重启之后,高层指令行为稳定
- eval覆盖高层指令互相冲突场景,不只测试正常流程
- 原生API链路、兼容网关链路分开记录测试结果
- 对外输出材料剔除密钥、内网地址、业务敏感标识
6 FAQ
Q:instructions 是第三种消息角色吗? A:不是。它属于请求顶层参数,不属于消息 Item 数组。文档描述它可以实现和 developer 相近的高层指令效果,但存储位置、多轮继承行为完全不同。
Q:developer 就是改个名字的 system prompt?
A:不完全等价。旧 system 还可能混杂平台元信息、客户端特殊语义。迁移不能直接简单字符串替换角色名,必须经过完整eval验证。
Q:报错 System messages are not allowed,直接全部替换为 developer 就能解决吗? A:不一定。报错代表链路拒绝 system 角色。修改角色之后,还需要完成首轮、多轮完整验证,确认网关、模型端点全部兼容 developer。
Q:instructions 和 developer 可以同时使用?
A:语法上允许同时传入顶层instructions和developer消息Item。但是官方没有给出通用冲突优先级规范。不同模型版本、网关的表现存在差异。生产环境尽量避免两套高层规则互相冲突;如果业务必须同时使用,纳入eval回归测试集。
7 总结
Responses API 的 instructions、developer、system,三者不是简单三选一替换关系:
instructions 作用单次请求,放置在请求顶层;developer 是消息数组内的指令角色,可以跟随会话持久回放;system 主要用于历史会话 transcript 迁移,不推荐新业务直接使用。
最大坑点来自多层链路:业务代码、SDK、应用适配器、API网关都会改写报文,只看入参配置不足以判断真实行为,必须拿到最终出站请求做验证。上线前搭建eval测试集合,覆盖首轮、多轮接续、网关重启、指令冲突等场景。迁移历史会话不要做简单字符串替换角色,需要完整验证链路兼容性。
Learn more:https://koalaapi.com
