返回专栏
Agent SDK/02 · OpenAI/2.2

OpenAI 客户端 SDK 与 Responses API

openai 包是 OpenAI REST API 的类型化封装,根据 OpenAPI 规范自动生成,提供同步和异步两种客户端。

预计阅读
19分钟
全文字数
2,088字
资料截至
2026-10-09
Agent SDK · OpenAI2.2
版本与时效声明
  • 本文基于 openai(Python)3.26.1(commit 9301e31,2026-10-08 发布)。文中代码已用 pyright 对照该版本做过类型检查;没有 API Key,因此没有实际运行。
  • 示例模型名 gpt-6-astra 取自 2026-10 的官方文档,使用时请以 Models 页面 为准。
  • 资料截至 2026-10-09。本文不随官方更新而同步,请对照 Responses API 参考 和 openai-python CHANGELOG 使用。
本文要点
  1. openai 包是 OpenAI REST API 的类型化封装,根据 OpenAPI 规范自动生成,提供同步和异步两种客户端1。
  2. Responses API 的核心模型是“输入一组 item,输出一组 item”。消息、推理、函数调用、工具结果都是 item2。
  3. 多轮对话有三种方式:手动回放、previous_response_id、Conversations API。
  4. 能力清单:函数调用、内置工具(web search、file search、远程 MCP 等)、结构化输出(responses.parse)、流式事件、错误处理与重试。

1. 定位:它在哪一层#

分层模型里,openai 包属于 L1 客户端 SDK,Responses API 属于 L0/L2。它已经能做的事:

  • 一次请求内,由 OpenAI 服务端执行内置工具(web search、code interpreter 等)2;
  • 在服务端保存对话状态(store、previous_response_id、Conversations)3。

它还不负责的事:本地函数工具的执行循环。这件事要你自己写(见 1.2 Tool Calling 与 Agent Loop 原理),或者交给 Agents SDK。


2. 安装与客户端配置#

Terminal window
pip install openai
export OPENAI_API_KEY=sk-...
from openai import OpenAI
# 默认值:从环境变量 OPENAI_API_KEY 读取密钥;超时 10 分钟;自动重试 2 次
client = OpenAI(timeout=60.0, max_retries=3)
response = client.responses.create(
model="gpt-6-astra",
instructions="你是一个资深后端工程师,回答要简洁。", # 相当于系统提示词
input="用一句话解释什么是幂等性。",
)
print(response.output_text) # SDK 提供的便捷属性:把所有输出文本拼接起来
print(response.id) # resp_...,可用于 previous_response_id
print(response.usage) # token 用量
配置项默认值说明
api_key环境变量 OPENAI_API_KEY官方建议不要把 key 写死在代码里1
timeout10 分钟可以传一个浮点数,或者 httpx2.Timeout。超时会抛出 APITimeoutError,并且默认会重试1
max_retries2会自动重试的错误:连接错误、408、409、429、5xx。只有请求体可以安全重发时才会重试1
单次请求覆盖—client.with_options(timeout=5.0).responses.create(...)
HTTP 底层HTTPX23.x 默认使用 HTTPX2;如果自定义了 HTTP 客户端,需要看迁移指南1

异步版本只需要把 OpenAI 换成 AsyncOpenAI,再加上 await1:

import asyncio
from openai import AsyncOpenAI
client = AsyncOpenAI()
async def main() -> None:
response = await client.responses.create(model="gpt-6-astra", input="你好")
print(response.output_text)
asyncio.run(main())

3. Responses 与 Chat Completions 的对比#

from openai import OpenAI
client = OpenAI()
# Chat Completions(上一代接口,仍然可用)
completion = client.chat.completions.create(
model="gpt-6-astra",
messages=[{"role": "user", "content": "写一句关于独角兽的睡前故事。"}],
)
print(completion.choices[0].message.content)
# Responses(新项目推荐使用)
response = client.responses.create(
model="gpt-6-astra",
input="写一句关于独角兽的睡前故事。",
)
print(response.output_text)
维度Chat CompletionsResponses
返回结构choices[].messageoutput[],即一组 item
一次生成多个候选(n)支持不支持,只返回一个2
状态需要手动管理默认存储,可以用 previous_response_id 或 Conversations2
结构化输出参数response_formattext.format2
内置工具(web/file search、MCP 等)—支持2
推理模型下的工具调用GPT-5.4 起,reasoning_effort 不为 none 时不支持2支持;GPT-6 Astra 和 6.1 Sol 必须用 Responses 做工具调用4

官方给出的迁移收益有三点2:

  • 使用推理模型时智能更好,内部 SWE-bench 测试提升约 3%;
  • 缓存利用率更高,内部测试中成本降低 40% 到 80%;
  • 默认就是 agentic loop:一次请求里可以调用多个内置工具。

4. Response 对象长什么样#

官方迁移指南中的一个返回示例(已节选)2:

{
"id": "resp_68af4030592c81938ec0a5fbab4a3e9f05438e46b5f69a3b",
"object": "response",
"model": "gpt-5.5",
"output": [
{ "id": "rs_...", "type": "reasoning", "content": [], "summary": [] },
{
"id": "msg_...",
"type": "message",
"status": "completed",
"role": "assistant",
"content": [{ "type": "output_text", "annotations": [], "text": "Under a quilt of moonlight, ..." }]
}
]
}

output

1

*

Response

+id

+model

+output

+output_text

+usage

«union»

OutputItem

+type

ResponseOutputMessage

+type = message

+content

ResponseReasoningItem

+type = reasoning

+summary

+encrypted_content

ResponseFunctionToolCall

+type = function_call

+call_id

+name

+arguments

WebSearchCall

+type = web_search_call

McpListTools

+type = mcp_list_tools

output

1

*

Response

+id

+model

+output

+output_text

+usage

«union»

OutputItem

+type

ResponseOutputMessage

+type = message

+content

ResponseReasoningItem

+type = reasoning

+summary

+encrypted_content

ResponseFunctionToolCall

+type = function_call

+call_id

+name

+arguments

WebSearchCall

+type = web_search_call

McpListTools

+type = mcp_list_tools

读图说明
  • output_text 是 SDK 提供的便捷属性,不是 API 原始字段。
  • ResponseOutputMessage.content 里装的是 output_text 或 refusal。
  • ResponseFunctionToolCall.arguments 是一个 JSON 字符串,用之前要自己 json.loads。

遍历 output 的典型写法:

from openai import OpenAI
client = OpenAI()
response = client.responses.create(model="gpt-6-astra", input="1+1 等于几?")
for item in response.output:
if item.type == "reasoning":
print("[推理 item]", item.id)
elif item.type == "message":
for part in item.content:
if part.type == "output_text":
print("[文本]", part.text)
elif part.type == "refusal":
print("[拒绝]", part.refusal)

5. 多轮对话的三种方式#

方式 3:会话对象

conversation=conv.id

持久对话资源

方式 2:链式

previous_response_id=r1.id

只发送新输入

方式 1:手动回放

history += response.output

每次发送完整历史

方式 3:会话对象

conversation=conv.id

持久对话资源

方式 2:链式

previous_response_id=r1.id

只发送新输入

方式 1:手动回放

history += response.output

每次发送完整历史

from typing import Any
from openai import OpenAI
client = OpenAI()
MODEL = "gpt-6-astra"
# 方式 1:手动管理历史。配合 store=False 时,OpenAI 不保存这次 response
history: list[Any] = [{"role": "user", "content": "讲个笑话"}]
r1 = client.responses.create(model=MODEL, input=history, store=False)
history += r1.output # 包括加密的 reasoning item,必须原样保留
history.append({"role": "user", "content": "再来一个"})
r2 = client.responses.create(model=MODEL, input=history, store=False)
# 方式 2:previous_response_id 链式接续
r1 = client.responses.create(model=MODEL, input="讲个笑话")
r2 = client.responses.create(
model=MODEL,
previous_response_id=r1.id,
input=[{"role": "user", "content": "解释一下笑点"}],
)
# 方式 3:Conversations API,得到一个持久的会话 ID
conv = client.conversations.create()
r3 = client.responses.create(
model=MODEL,
conversation=conv.id,
input=[{"role": "user", "content": "躲避球的 5 个 D 是什么?"}],
)
print(r2.output_text, r3.output_text)
关键事实出处
Response 对象默认保存 30 天,store: false 可以关闭3
Conversation 对象及其中的 item 不受 30 天 TTL 限制3
使用 previous_response_id 时,链上所有历史输入仍然按输入 token 计费3
无状态地调用推理模型时,必须保留 output 中的每一个 item;API 默认返回加密的 reasoning item3
previous_response_id 和 conversation 互斥Agents SDK 文档5

6. 函数调用(Function Calling)#

完整的手写循环见 1.2 Tool Calling 与 Agent Loop 原理 › 3. 手写一个最小 Agent Loop:OpenAI 版。这里补充几个常用参数:

参数 / 概念作用出处
strict: true保证模型生成的参数严格符合 JSON Schema。要求所有字段都是 required,并且 additionalProperties: false4
tool_choiceauto(默认)/ required / none / 指定某个函数4
parallel_tool_calls=false限制每次最多调用一个函数4
Custom tools输入和输出都是自由文本,可以用上下文无关文法约束4
defer_loading + tool_search函数太多时,按需加载工具定义(需要 gpt-5.4 及以上)46
async: true(GPT-6)异步工具调用:模型可以先去做别的事,等你稍后用原来的 call_id 回填结果7
怎么在“函数调用”和“结构化输出”之间选

官方给出的判断标准8:

  • 如果是把模型连接到你系统里的函数、数据或者 UI 操作,用函数调用;
  • 如果只是希望模型回复用户时输出固定结构,用 text.format,也就是 responses.parse。

7. 内置工具(Hosted Tools)#

内置工具在 OpenAI 服务端执行,你只需要在 tools 里声明:

from openai import OpenAI
client = OpenAI()
# 1) Web 搜索
r = client.responses.create(
model="gpt-6-astra",
tools=[{"type": "web_search"}],
input="今天有什么积极的科技新闻?",
)
print(r.output_text)
# 2) 远程 MCP 服务器:这里使用 OpenAI 官方的文档 MCP,只读,不需要鉴权
r = client.responses.create(
model="gpt-6-astra",
tools=[
{
"type": "mcp",
"server_label": "openai_docs",
"server_description": "Search and read the public OpenAI documentation.",
"server_url": "https://developers.openai.com/mcp",
"require_approval": "never",
}
],
input="在 OpenAI 文档中搜索 Responses API streaming,并返回相关链接。",
)
print(r.output_text)
内置工具type说明
Web 搜索web_search支持域名过滤、用户位置等参数6
文件搜索file_search在你的 Vector Store 里做检索6
代码解释器code_interpreter在沙箱中运行 Python2
远程 MCPmcp模型先列出 server 上的工具(产生 mcp_list_tools item),然后再调用9
图像生成image_generation10
Computer usecomputer驱动浏览器或桌面2
Shell(托管容器)+ Skillsshell在 OpenAI 托管容器中执行命令,可挂载 skills10
工具搜索tool_search按需加载延迟定义的工具6
MCP 的安全提醒

官方特别强调:只连接你信任的远程 MCP 服务器。恶意的 server 可以把进入模型上下文的敏感数据外泄出去9。


8. 结构化输出:responses.parse#

from pydantic import BaseModel
from openai import OpenAI
client = OpenAI()
class CalendarEvent(BaseModel):
name: str
date: str
participants: list[str]
response = client.responses.parse(
model="gpt-6-astra",
input=[
{"role": "system", "content": "抽取事件信息。"},
{"role": "user", "content": "Alice 和 Bob 周五去参加科学展。"},
],
text_format=CalendarEvent, # SDK 自动把 Pydantic 模型转成 JSON Schema
)
event = response.output_parsed # 已经校验过的 CalendarEvent 实例(可能为 None)
print(event)
  • responses.parse 和 responses.stream 都支持 text_format。output_parsed 返回第一个解析成功的结果11。
  • 模型拒绝作答时,不会把 commentary 当作结构化结果的兜底返回11。

9. 流式输出#

from openai import OpenAI
client = OpenAI()
stream = client.responses.create(
model="gpt-6-astra",
input="把 'double bubble bath' 快速说十遍。",
stream=True,
)
for event in stream:
if event.type == "response.output_text.delta":
print(event.delta, end="", flush=True)
elif event.type == "response.completed":
print("\n[完成]", event.response.usage)
  • Responses 使用语义事件,每种事件都有固定的 schema。常见的有 response.created、response.output_text.delta、response.completed、error12。
  • 函数调用的参数也会以流式到达,对应事件 response.function_call_arguments.delta 和 .done12。
  • 流式消费过程中出现的错误不会自动重试,因为重放可能导致已经输出的内容重复出现1。
  • 另有一种 WebSocket 模式:在一条持久连接上反复发送 response.create,可以降低多轮对话的延迟3。
Responses API客户端Responses API客户端loop[文本生成]POST /v1/responses (stream=true)response.createdresponse.output_item.added (message)response.output_text.deltaresponse.output_item.doneresponse.completed(包含完整的 response 和 usage)
Responses API客户端Responses API客户端loop[文本生成]POST /v1/responses (stream=true)response.createdresponse.output_item.added (message)response.output_text.deltaresponse.output_item.doneresponse.completed(包含完整的 response 和 usage)

10. 错误处理与排查#

import openai
from openai import OpenAI
client = OpenAI()
try:
response = client.responses.create(model="gpt-6-astra", input="hello")
print(response._request_id) # 例如 req_123;以 _ 开头,但这是一个公开属性
except openai.APIConnectionError as e:
print("连不上服务器:", e.__cause__)
except openai.RateLimitError:
print("429:触发限流,需要退避重试")
except openai.APIStatusError as e:
print("其他非 2xx 状态码:", e.status_code, e.request_id)
状态码异常类
400BadRequestError
401AuthenticationError
403PermissionDeniedError
404NotFoundError
422UnprocessableEntityError
429RateLimitError
≥500InternalServerError
网络问题APIConnectionError

所有异常都继承自 openai.APIError。表格来自 openai-python README1。


11. 迁移清单#

从 Chat Completions 迁移,官方的建议是看成三件相关的改动2:

  1. 端点从 /v1/chat/completions 改为 /v1/responses;
  2. 从 typed 的 output 数组里读取结果;
  3. 决定在轮次之间怎么保存状态。

另外,函数调用的请求和响应结构都变了(见 对照表),结构化输出参数从 response_format 改为 text.format。

从 Assistants 迁移:概念对应关系见 2.1 OpenAI 开发者生态全景 › 4.1 Assistants API 已下线。官方迁移指南明确说,没有现成的工具可以自动迁移已有的 Thread13。


小结#

  • Responses API 是 OpenAI 一切 agent 能力的底座。 Agents SDK 默认调用它,Agents API 也复用了它的工具体系。
  • 牢记三个概念:item(输入和输出的基本单元)、状态策略(手动回放、链式、会话三选一)、托管工具与本地函数的区别(谁来执行)。
  • 下一步:用 2.3 OpenAI Agents SDK 去掉手写循环;或者用 2.4 OpenAI Agents API 把整个运行过程交给 OpenAI 托管。

相关笔记#

参考资料#

注释与出处#

  1. openai/openai-python,README.md(Usage、Async usage、Streaming、Handling errors、Request IDs、Retries、Timeouts 等节),https://github.com/openai/openai-python/blob/9301e319ea33ef28fba380f39a289dedc14652c1/README.md ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8

  2. OpenAI,Migrate to the Responses API,https://developers.openai.com/api/docs/guides/migrate-to-responses ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10 ↩11 ↩12

  3. OpenAI,Conversation state,https://developers.openai.com/api/docs/guides/conversation-state ↩ ↩2 ↩3 ↩4 ↩5 ↩6

  4. OpenAI,Function calling,https://developers.openai.com/api/docs/guides/function-calling ↩ ↩2 ↩3 ↩4 ↩5 ↩6

  5. openai/openai-agents-python,docs/running_agents.md(“conversation_id and previous_response_id are mutually exclusive”),https://github.com/openai/openai-agents-python/blob/26345c1e45ebede8e2fc9b0bc7341dedab5e01fc/docs/running_agents.md ↩

  6. OpenAI,Using tools,https://developers.openai.com/api/docs/guides/tools ↩ ↩2 ↩3 ↩4

  7. OpenAI,Using GPT-6(What's new 一节:Async tool calling),https://developers.openai.com/api/docs/guides/latest-model ↩

  8. OpenAI,Structured model outputs,https://developers.openai.com/api/docs/guides/structured-outputs ↩

  9. OpenAI,MCP servers(Quickstart 与 Risks and Safety 两节),https://developers.openai.com/api/docs/guides/tools-connectors-mcp ↩ ↩2

  10. openai/openai-agents-python,docs/tools.md(Hosted tools、Hosted container shell + skills 两节),https://github.com/openai/openai-agents-python/blob/26345c1e45ebede8e2fc9b0bc7341dedab5e01fc/docs/tools.md ↩ ↩2

  11. openai/openai-python,helpers.md(Parsing Responses API output 一节),https://github.com/openai/openai-python/blob/9301e319ea33ef28fba380f39a289dedc14652c1/helpers.md ↩ ↩2

  12. OpenAI,Streaming API responses,https://developers.openai.com/api/docs/guides/streaming-responses ↩ ↩2

  13. OpenAI,Assistants migration guide,https://developers.openai.com/api/docs/assistants/migration ↩

输入关键词开始搜索。多个关键词用空格分隔。