引言
2025年3月,OpenAI 正式推出 Responses API。一年后的今天,它已成为构建 AI Agent 的首选接口。2026年3月,OpenAI 进一步扩展了 Responses API,加入了 Shell 工具和托管容器工作空间。与此同时,Assistants API 将于 2026 年 8 月 26 日正式下线。
这些变化看似只是接口升级,实则揭示了一个更深层的趋势:大模型 API 正在从"让模型说话"的聊天接口,变成"让模型干活"的 Agent 运行时。
本文将从 API 演进、核心差异、工具系统到本地代理实现,为你系统梳理这一范式转移的全貌。
一、三条接口线,一次统一
要理解 Responses API,得先看清 OpenAI 走过的三条路。
Chat Completions API (2023 年)是无状态的对话补全接口。你发 messages,模型返回 completion。它简单、稳定,是整个行业的事实标准。但它的局限同样明显:每次请求都要重传完整历史,工具调用需要自己写循环,多轮对话的成本随长度线性增长。
Assistants API(2023 年)试图解决状态管理问题,引入了 Thread、Run 和内置工具。但它接口复杂、延迟偏高、灵活性不足,始终未能广泛普及。
Responses API (2025 年)正是为了统一前两者的优势而设计:像 Chat Completions 一样简洁,像 Assistants 一样强大,并专为推理模型和 Agent 工作流优化。
用 Java 生态来类比:Chat Completions 像是原始的 JDBC------你自己管连接、写 SQL、处理结果集;Responses API 像是 Spring Data JPA------平台帮你管理了大量样板逻辑,你只需要声明意图。
二、核心差异:不只是"新版本",而是不同的世界观
2.1 无状态 vs 有状态
这是两代 API 最本质的分水岭。
Chat Completions 是无状态的。 每次请求都是独立的。要实现多轮对话,你必须自己拼接完整的 messages 数组,每次都重传全部历史。对话越长,成本越高。
Responses API 是有状态的。 通过 previous_response_id 参数,服务端自动管理对话历史。推理状态在轮次之间保留------模型"带着笔记本"进入下一轮对话,而不是每次从头开始。
2.2 请求格式对比
| 维度 | Chat Completions | Responses API |
|---|---|---|
| 端点 | POST /v1/chat/completions | POST /v1/responses |
| 输入格式 | messages 数组(完整历史) |
input + previous_response_id |
| 系统提示 | messages 中的 role: system |
独立的 instructions 字段 |
| 状态管理 | 无状态,客户端维护历史 | 有状态,服务端存储历史 |
| 工具类型 | 仅 function(自定义函数) |
function + 多种内置工具 |
| 工具执行 | 客户端自己写循环 | 平台自动编排 Agent Loop |
| 响应结构 | choices[0].message.content |
output[0].content[0].text |
2.3 状态管理示例
python
# 第一轮
response = client.responses.create(
model="gpt-4.1",
input="你好,我叫小明",
store=True
)
response_id = response.id
# 第二轮 - 只需传入 previous_response_id
response = client.responses.create(
model="gpt-4.1",
input="我叫什么名字?",
previous_response_id=response_id
)
三、内置工具:它们在哪运行?
这是开发者最容易产生困惑的地方。Responses API 的内置工具并非全部运行在 OpenAI 服务器上,而是采用混合部署模式。
3.1 完全托管型(运行在 OpenAI 云端)
以下工具完全运行在 OpenAI 的服务器上,无需你安装任何东西,只需在请求中声明即可使用:
| 工具 | 功能 |
|---|---|
| Web Search | 联网搜索,让模型基于最新数据回答问题 |
| File Search | 从上传的文件中检索上下文 |
| Code Interpreter | 在沙箱中执行 Python 代码 |
| Image Generation | 生成图像 |
这类工具的特点是"即用即走"------你不需要考虑运行环境、依赖安装、算力资源,OpenAI 的后台全部替你处理。
3.2 本地执行型(运行在你的环境)
以下工具虽然由模型发起调用请求,但实际执行发生在你的本地环境:
| 工具 | 功能 |
|---|---|
| Computer Use | 操作虚拟计算机 |
| Shell | 执行 Shell 命令 |
Shell 工具采用常见的 Unix 工具集打造,提供 grep、curl 和 awk 等无需额外设置即可使用的工具。
3.3 远程连接型(运行在外部服务器)
Remote MCPs (Model Context Protocol)既不运行在 OpenAI 云端,也不直接在你的本地执行。你需要将 MCP 服务器部署到一个公网可访问的地址,Responses API 调用时,OpenAI 的服务器会直接向该地址发起请求。
3.4 一个简单的分类记忆法
Web Search / File Search / Code Interpreter / Image Generation = OpenAI 开的"官方旗舰店",直接为你服务。
Computer Use / Shell = "DIY 工具包",模型给你指令,你动手执行。
Remote MCPs = "第三方合作商",你自己开店,OpenAI 上门访问。
四、文件操作:内置工具能访问你的本地文件吗?
答案是不能,除非你主动上传。
内置工具运行在 OpenAI 服务器上,它们无法直接读取你电脑硬盘上的任何文件。
操作流程是这样的:
- 上传 :通过 OpenAI 的 Files API 将本地文件上传到云端,获得一个
file_id。 - 引用 :在调用 Responses API 时,通过
file_ids参数引用这个file_id。 - 处理 :内置工具在 OpenAI 的沙箱环境中处理这份云端副本。
python
# 1. 上传本地文件到 OpenAI 云端
file = client.files.create(
file=open("本地财报.pdf", "rb"),
purpose="user_data"
)
# 2. 引用 file_id,而不是本地路径
response = client.responses.create(
model="gpt-4.1",
input="总结这份财报的核心数据",
tools=[{"type": "file_search"}],
tool_resources={
"file_search": {
"vector_stores": [{
"file_ids": [file.id]
}]
}
}
)
Code Interpreter 同理。它执行 Python 代码时读取的是 OpenAI 沙箱环境里的临时文件夹,里面的文件要么是你通过 API 上传的,要么是之前工具调用生成的。
💡 你的本地文件是绝对安全的。 内置工具只认
file_id,不认文件路径。
五、从 API 到 Agent:Codex 与 Claude Code 的本地执行模式
理解了大模型 API 的演进,我们再来看一个更贴近开发者日常的场景:Codex 和 Claude Code 这类编程助手,是怎么读取和操作你本地文件的?
答案是一个统一的模式:本地代理程序 + 工具调用 + 权限控制。
5.1 代理模式:本地的"桥梁"
无论是 Codex CLI 还是 Claude Code,它们首先都是一个运行在你电脑上的本地客户端程序。
- Codex 是 OpenAI 的编程智能体,通过 CLI、IDE 扩展或桌面应用在开发者的笔记本电脑上运行。
- Claude Code 是 Anthropic 推出的本地化 AI 执行代理,可驻留项目、读写文件、调用工具。
这个客户端程序以你(用户)的权限运行,拥有访问和操作你电脑上文件的完整能力。
5.2 工具调用:赋予模型"双手"
本地代理程序会为大模型准备好一系列可以调用的"工具":
| 工具类别 | 具体功能 |
|---|---|
| 文件操作 | 读取文件、编辑代码、创建新文件、重命名、重组 |
| 搜索 | 按模式查找文件、使用正则表达式搜索内容、探索代码库 |
| 执行 | 执行 Shell 命令、启动服务器、运行测试、使用 Git |
| 网络 | 搜索网络、与外部服务交互 |
Claude Code 的所有能力------文件读写、Shell 命令、代码搜索------都通过统一的工具系统暴露给模型。模型不直接操作文件系统,而是通过调用工具来完成一切副作用操作。
5.3 权限与安全:在便利与风险间平衡
强大的能力也伴随着风险,因此这些工具内置了多层安全机制:
工作区(Workspace)限制 :默认情况下,AI 的操作范围被限定在当前项目目录内。Codex 可以读取几乎任何位置的文件,但在你的工作区(即运行 Codex 的目录)内写入文件。
沙箱(Sandbox)隔离 :操作系统会为 AI 的命令提供一个受限的执行环境。Codex 默认禁止访问互联网,除非你明确允许。不同操作系统使用不同的沙箱机制------macOS 的 Seatbelt、Linux 的 seccomp 与 bubblewrap。为了在 Windows 上实现同等效果,OpenAI 甚至专门构建了自定义沙箱方案。
用户审批(User Approval) :对于写入、修改文件或执行 Shell 命令等高风险操作,AI 通常会请求你的明确批准后才执行。
读取去重:为防止重复读取相同文件浪费资源,Claude Code 还内置了去重机制,如果文件未被修改,会直接使用缓存。
5.4 数据隐私:代码不上云
这类工具通常是本地优先 的。你的源代码文件本身不会被上传 到云端。发送给大模型的,通常只是部分相关代码片段 或经过处理的请求摘要。
六、Responses API 的独特优势
这是一个非常经典的场景。为了让你直观感受 Agentic Loop(智能体循环) 的区别,我用"联网搜索天气"这个最常见的任务来举例。
在旧版(Chat Completions)中,"循环"由你(开发者)在客户端编写 ;在新版(Responses API)中,"循环"被内置到了平台服务端。
场景设定
用户提问:"今天北京天气怎么样?适合户外运动吗?"
模型需要先联网搜索获取天气,再根据天气数据给出运动建议。
1. 旧模式:Chat Completions API(手动循环)
在 Chat Completions 中,没有内置的联网搜索工具 。你必须自己定义 search_web 函数,并且手动实现完整的"请求-判断-执行-再请求"循环。
python
import json
# 1. 定义模拟的联网搜索函数(需要你自己实现)
def mock_web_search(query):
# 在实际开发中,这里会是调用 Bing/Google API 的代码
if "北京" in query and "天气" in query:
return '{"city": "北京", "temperature": "25°C", "weather": "晴"}'
return ""
# 2. 定义工具结构
tools = [{
"type": "function",
"function": {
"name": "search_web",
"description": "获取实时信息",
"parameters": {
"type": "object",
"properties": {"query": {"type": "string"}},
"required": ["query"]
}
}
}]
# 3. 初始化消息列表(每次都要传全部历史)
messages = [{"role": "user", "content": "今天北京天气怎么样?适合户外运动吗?"}]
# 4. 【第一轮】调用模型,判断是否需要调用工具
response = client.chat.completions.create(
model="gpt-4",
messages=messages,
tools=tools
)
# 5. 提取模型返回的消息
assistant_message = response.choices[0].message
messages.append(assistant_message) # 手动将助手消息加入历史
# 6. 【手动判断】如果模型要求调用工具,则进入"执行-反馈"循环
if assistant_message.tool_calls:
for tool_call in assistant_message.tool_calls:
if tool_call.function.name == "search_web":
# 解析参数,手动执行函数(调用本地或第三方API)
args = json.loads(tool_call.function.arguments)
search_result = mock_web_search(args.get("query"))
# 7. 【手动拼接】将工具执行结果塞回 messages 数组
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": search_result
})
# 8. 【第二轮】再次调用模型,让它基于搜索结果生成最终回答
final_response = client.chat.completions.create(
model="gpt-4",
messages=messages
)
print(final_response.choices[0].message.content)
else:
print(assistant_message.content)
痛点分析:
- 代码臃肿 :需要手写
if判断和for循环来解析tool_calls。 - 状态维护 :每一次交互都要手动把
assistant消息和tool结果追加到messages数组,极其繁琐且容易出错。 - 高成本 :第二轮请求时,必须重传包含历史记录在内的整个
messages数组,历史越长,Token 消耗越大。
2. 新模式:Responses API(内置自动循环)
在 Responses API 中,联网搜索是内置工具(Web Search) 。平台服务端内部处理了"调用搜索-获取结果-继续生成"的完整循环。你只需要一次请求,代码简洁至极。
python
# 只需要一次调用,无需手写任何循环!
response = client.responses.create(
model="gpt-4.1",
input="今天北京天气怎么样?适合户外运动吗?",
tools=[{"type": "web_search"}] # 平台原生支持,服务端自动执行
)
# 直接拿到最终整合后的回答
print(response.output[0].content[0].text)
# 你甚至不用关心"搜索"这个中间步骤是怎么发生的。
平台内部发生了啥(自动 Agentic Loop):
- 模型决定调用
web_search。 - OpenAI 服务端自动执行搜索 API(无需你操心)。
- 服务端自动将搜索结果注入当前上下文。
- 模型基于搜索结果生成最终的运动建议。
- 一次性返回最终结果。
3. 如果非要对比"自定义工具"呢?
你可能会说:"我不用内置工具,还是想用自己的数据库查询函数,Responses 怎么处理?"
在 Responses API 中,即使是自定义函数调用,虽然执行动作(查你的数据库)依然必须由你的后端代码执行 ,但状态管理(循环)被极大地简化 了。你不再需要手动维护庞大的 messages 数组,而是通过 previous_response_id 优雅地衔接:
python
# 第一次调用:模型返回 function_call 请求
response1 = client.responses.create(
model="gpt-4.1",
input="查一下订单12345的状态",
tools=[{"type": "function", "name": "query_order", ...}],
store=True # 开启状态存储
)
# ---- 你的后端代码去执行 query_order 函数,拿到结果 ----
order_status = "已发货"
# 第二次调用:利用 previous_response_id 延续上下文,无需重传历史!
response2 = client.responses.create(
model="gpt-4.1",
previous_response_id=response1.id, # 神奇!状态在服务端自动继承
input=[{
"type": "function_call_output",
"call_id": response1.output[0].call_id,
"output": order_status
}]
)
print(response2.output[0].content[0].text)
💎 总结:Agentic Loop 的核心差异
| 维度 | Chat Completions(旧) | Responses API(新) |
|---|---|---|
| 循环控制权 | 在客户端 (你写 while 或 if) |
在服务端(平台内部自动编排) |
| 历史管理 | 手动维护 messages 数组(重传全部) |
自动缓存(previous_response_id 引用) |
| 内置工具 | 不支持(需自实现搜索/文件等) | 原生支持,开箱即自动执行 |
| 代码量 | 冗长(约 30-40 行) | 极简(约 5-10 行) |
| Token 成本 | 随对话轮次线性暴涨 | 利用缓存,节省 40%-80% |
一句话总结:
在旧 API 里,你像一个"手动挡司机",需要自己踩离合(手动拼接历史)、换挡(手动判断工具调用)。而在新 API 里,车变成了"自动驾驶"(平台自动处理 Agentic Loop),你只需要告诉它目的地(input 和 tools)即可。
6.2 更低的成本
得益于服务端状态管理,缓存利用率提升 40%--80% 。推理摘要可以加密保留,且不额外收费。
6.3 更清晰的响应结构
Responses API 的响应不仅包含模型说了什么,还包含模型做了什么------工具调用、结构化输出、中间步骤。
七、迁移路径与时间节点
7.1 映射关系速查表
| Chat Completions | Responses API |
|---|---|
messages 数组 |
input + previous_response_id |
role: "system" |
独立的 instructions 字段 |
response_format |
text.format |
choices[0].message.content |
output[0].content[0].text |
7.2 重要时间节点
| 事件 | 时间 |
|---|---|
| Assistants API 正式下线 | 2026 年 8 月 26 日 |
| GPT-5 及更新模型 | 必须使用 Responses API |
| Chat Completions 状态 | 进入维护模式,新功能只迭代在 Responses API 上 |
OpenAI 官方提供了迁移工具包 completions-responses-migration-pack,由 Codex CLI 引导完成迁移。
八、选型建议
| 场景 | 推荐方案 |
|---|---|
| 新项目(Agent / 工作流) | ✅ 直接使用 Responses API |
| 纯文本生成、简单问答 | ⚠️ 可暂用 Chat Completions,建议规划迁移 |
| 依赖 Assistants API 的项目 | 🚨 必须在 2026 年 8 月 26 日前完成迁移 |
| 使用 GPT-5 及更新模型 | ✅ 必须使用 Responses API |
结语:一次接口升级,一次思维转型
回顾全文,我们可以看到一条清晰的脉络:
第一层是 API 本身的演进------从无状态的 Chat Completions 到有状态的 Responses API,大模型接口从"对话补全"变成了"Agent 运行时"。
第二层是工具系统的扩展------从仅支持自定义函数,到内置 Web Search、File Search、Code Interpreter、Shell、Computer Use 等多种工具,大模型获得了操作真实世界的能力。
第三层是本地代理的实现------Codex、Claude Code 等工具通过"本地代理 + 工具调用 + 权限控制"的模式,将大模型的能力安全地延伸到你的文件系统和开发环境中。
这三层环环相扣:Responses API 提供了服务端的能力底座,内置工具提供了标准化的操作接口,而本地代理则把这些能力安全地交付到开发者手中。
正如 OpenAI 官方所说:"Chat Completions 会继续支持,但 Responses 是推荐所有新项目使用的接口。这不是营销话术,而是能力分叉的现实。"
如果你正在规划新的 AI 应用,现在就是认真了解并开始使用 Responses API 的最佳时机。未来已来,只是分布不均------而 Responses API,正在让它变得更均匀一些。