Mindket

OpenAI API 教程:用 Python 和 JavaScript 调用 Responses API

黑色横幅,标题是“OpenAI API 实战”,下面是“Responses、工具调用、结构化输出与智能体”。

Responses API 是 OpenAI 文档推荐新项目使用的接口。你发送模型 id 和输入,也可以附上 instructions,返回的是一组输出项,外加一个 output_text 快捷属性。这篇教程会创建密钥,安装官方 Python 和 JavaScript SDK,发出第一次调用,把回复做成流式输出,再让对话跨回合延续下去。

本节内容

  • 把密钥放在环境变量里,别让访客能打开的页面碰到它。
  • 请求里一旦有工具或推理,就按输出项的类型逐个处理。
  • 每个串联的回合都要重新发送行为规则。
  • 每段对话只选一个地方保存历史,并且一直用它。
  • 迁移旧的聊天代码时小步推进,先迁纯文本。
全部课程
本页目录
  1. 开始之前
  2. 发出第一次调用,再看看返回了什么
  3. 用 instructions 引导模型,再把回复做成流式
  4. 让对话跨回合延续
  5. Responses 和 Chat Completions 是什么关系
  6. Atty Eleti 和 OpenAI Developers 谈 Responses API
  7. 常见错误
  8. 自己试一试
  9. 接下来
  10. 自测一下
  11. 常见问题
  12. 资料来源

开始之前

你需要一个 OpenAI 平台账号和一个 API 密钥,密钥在控制台的 API keys 页面创建。每个官方 SDK 都会从环境变量 OPENAI_API_KEY 读取密钥,所以代码里不用出现它。macOS 或 Linux 上运行 export OPENAI_API_KEY="your_api_key_here",PowerShell 里运行 setx OPENAI_API_KEY "your_api_key_here"。

你为自己创建的密钥,带的是你本人的权限。部署好的应用、定时任务或 CI,API 密钥指南建议改用项目服务账号。服务账号是一个非人类身份,自己持有密钥,这样工作负载就不会因为某位开发者离开团队而失效。服务账号的密钥只在创建那一刻完整显示一次,所以要直接存进密钥管理器。

密钥上的权限范围可以收窄它能做的事,但永远不会给出它的主人本来没有的权限。轮换密钥有固定的顺序:先签发新密钥,更新工作负载,确认能用,再吊销旧密钥。密钥换了,服务账号的身份不变。不同的项目可以把不同应用或环境的资源、成员和用量隔离开。如果工作负载运行在 OpenAI 支持的身份提供方上,可以用工作负载身份联合,完全不必保存长期有效的密钥。

Python SDK 需要 Python 3.10 或更高版本。JavaScript SDK 支持 Node.js 22 和 24 LTS,也支持 Deno、Bun 和 Cloudflare Workers。Node.js 20 已在 2026 年 4 月底结束生命周期,不再受支持。浏览器默认被禁止,打开 dangerouslyAllowBrowser 选项才能用,而那样一来,任何打开页面的人都能读到你的密钥。

发出第一次调用,再看看返回了什么

快速入门里的第一个请求只有三步:创建客户端,用模型和输入调用 responses.create,打印 output_text。下面是开发者快速入门里的 Python 版本。JavaScript 版本的调用写法是 await client.responses.create({ model, input }),文件存成 example.mjs,最后用 console.log(response.output_text) 输出。

返回的是一个带自己 id 的 response 对象,不是字符串。它的 output 属性是一组输出项。文本生成指南针对这个提示词给出的示例里,列表只有一项:id 以 msg_ 开头,类型是 message,角色是 assistant。里面有一个 content 列表,装着一个 output_text 部分,也就是那个独角兽故事,旁边是一个空的 annotations 列表,工具提供引用时,引用就放在这里。

迁移指南打印了同一个请求在 gpt-5.5 上的结果,那里的列表以一个 id 以 rs_ 开头的 reasoning 项开头,消息排在第二。output_text 是 SDK 提供的辅助属性,把所有文本部分拼成一个字符串,正好把这个差别藏了起来。写个小脚本时它很方便。代码一旦加了工具或要保存历史,就该逐项遍历这个列表,因为文本生成指南明确提醒,回复不一定在 output[0].content[0].text。

from openai import OpenAI

client = OpenAI()

response = client.responses.create(
    model="gpt-6-astra",
    input="Write a one-sentence bedtime story about a unicorn.",
)

print(response.output_text)
  1. 在要运行代码的终端里导出密钥。
  2. 安装 SDK:Python 用 pip install openai,JavaScript 用 npm install openai。
  3. 把代码存成 example.py,JavaScript 版本存成 example.mjs。
  4. 运行 python example.py 或 node example.mjs,调用返回后会打印出一个短故事。
  5. 把打印 output_text 换成打印 response.output,看看那个字符串背后有哪些输出项类型。
输出项类型出自迁移指南和各工具指南,2026 年 11 月 5 日阅读。
输出项类型什么时候出现你的代码要做什么
message模型给用户写了文字读取其中的文本部分,或者直接用 output_text
reasoning推理模型在回答前先做了推理保留它,自己回放历史时要原样传回
function_call模型想运行你的某个函数运行函数,再回一个带相同 call_id 的 function_call_output
web_search_call 或 file_search_call内置工具已在 OpenAI 那边运行过不用运行任何东西,读消息里的引用即可

用 instructions 引导模型,再把回复做成流式

instructions 是顶层参数,用来规定模型怎样表现,比如语气、目标、好回答的例子。它的优先级高于 input 里的提示词。传入它,大致相当于在输入列表最前面放一条 developer 角色的消息。developer 消息承载应用的规则,排在 user 消息之前,user 消息则是用户打出来的内容。模型自己的回合用 assistant 角色。

文本生成指南拿代码来比喻这两种角色。developer 消息像函数定义,装着规则和业务逻辑。user 消息像传给这个函数的参数。

它只对当前这一次请求生效。用 previous_response_id 串起来的回合,看不到你之前发过的 instructions,所以串联调用的代码每次都要重新发送。提示词本身应该写在代码里,这样它就有类型化的输入、代码审查和测试。OpenAI 正在淘汰一些旧教程存在平台上的可复用提示词对象,下面的时间线列出了日期。

默认情况下,API 要把整段回答写完,才通过一个 HTTP 响应发回来,回答一长,用户看到的就是这段等待。流式输出只多一个开关就解决了等待。把 stream 设为 true,SDK 交给你的就是带类型的服务器推送事件,也就是服务器单向持续写入的 HTTP 流。下面的示例把文本生成指南里的 instructions 示例和流式输出指南里的事件循环拼在了一起。

文档的示例还设置了 reasoning: { effort: "low" }。推理强度告诉推理模型回答前要想多少,强度越低,速度越快,token 越少。可用的取值因模型而异,推理指南写明 GPT-6.1 Sol 和 GPT-6 Luna 的默认值是 medium。Python 里传 stream=True,再用 for event in stream 遍历,检查的 event.type 名称完全相同。

import OpenAI from "openai";
const client = new OpenAI();

const stream = await client.responses.create({
  model: "gpt-6-astra",
  reasoning: { effort: "low" },
  instructions: "Talk like a pirate.",
  input: "Are semicolons optional in JavaScript?",
  stream: true,
});

for await (const event of stream) {
  if (event.type === "response.output_text.delta") {
    process.stdout.write(event.delta);
  } else if (event.type === "response.completed") {
    console.log("\nResponse completed.");
  } else if (event.type === "error") {
    console.error(event.message);
  }
}
  • response.created 只出现一次,在回复开始时。
  • response.output_text.delta 会出现很多次,每次的 delta 里是下一段文字。
  • response.completed 只出现一次,在生成结束时。
  • error 可能在流的中途出现,所以循环里要给它单独一个分支。
旧接口和它们的日期
  1. 弱化提示词对象的创建

    可复用提示词对象开始弃用,文本生成指南要求把提示词放在代码里。

    来源:OpenAI Docs: Text generation (2026年11月5日 查阅)

  2. Assistants API 停用

    它已经无法使用,迁移指南把它的用户引向 Responses API。

    来源:OpenAI Docs: Migrate to the Responses API (2026年11月5日 查阅)

  3. 提示词接口关闭

    文本生成指南给出的 v1/prompts 停止服务日期。

    来源:OpenAI Docs: Text generation (2026年11月5日 查阅)

一旦开始读取流,Python SDK 就不会再自动重试,因为重放可能把应用已经显示过的文字再输出一遍。流式输出也让内容审核更难,因为不完整的回答比完整的更难判断。如果你要求返回审核分数,它们要等完整输出生成后才会到达。

让对话跨回合延续

先问“tell me a joke”,再在第二个请求里问“explain why this is funny”,第二个请求对第一个一无所知。每次调用都是独立的。要让模型拿到上下文,你有三种办法。

手动回放最直白。在应用里维护一个输出项列表,每次回复后把模型的 output 追加进去,再加上下一条用户消息,把整个列表作为 input 发出去。没有任何东西替你保存,也没有任何东西瞒着你。

最轻的是 previous_response_id:传入上一次响应的 id,只带新的用户输入,前面的回合由 OpenAI 补上。这能成立,是因为响应默认会被存储,存储的响应对象保留 30 天。下面的代码就是对话状态指南里的示例。

串联省掉的是重复发送文字,省不掉费用:链上所有先前的输入 token,在下一个回合仍按输入计费。如果你学过 Claude API 课程,这里的变化很大,因为 Anthropic 的 Messages API 是无状态的,历史总要由你的代码重新发送。

如果一段对话要跨会话保留,或者在不同设备之间接续,就用 client.conversations.create() 创建一个 conversation,并在每次请求里把它的 id 作为 conversation 传入。conversation 用自己的持久 id,把消息、工具调用和工具输出都存成输出项。

三种办法都会撞上同一个上限。上下文窗口是单次请求能用的最多 token 数,输入、输出和推理 token 都算在里面。长对话一个回合一个回合地逼近它,超出上限的输出可能被截断。对这种情况,指南指向压缩功能,在 /responses 上通过 context_management 和 compact_threshold 设置。发送之前,还可以用它提供的分词工具数一数一段文字有多少 token。

from openai import OpenAI

client = OpenAI()

response = client.responses.create(
    model="gpt-6-astra",
    input="tell me a joke",
)
print(response.output_text)

second_response = client.responses.create(
    model="gpt-6-astra",
    previous_response_id=response.id,
    input=[{"role": "user", "content": "explain why this is funny."}],
)
print(second_response.output_text)
出自对话状态指南,2026 年 11 月 5 日阅读。
方式历史存在哪里每个回合发送什么保留多久
手动回放你的应用之前的所有输出项,加上新消息你保留多久就多久,store 可以设为 false
previous_response_idOpenAI,按响应逐个保存上一次响应的 id 和新输入响应对象默认保留 30 天
Conversations API一个有自己 id 的 conversation 对象conversation id 和新输入其中的输出项不受 30 天期限限制

在 store 设为 false 的情况下手动回放?要保留 output 里的每一项,包括加密的推理项。Python 里就是在下一条用户消息之前执行 history += response.output。

Responses 和 Chat Completions 是什么关系

Chat Completions 是更早的接口,路径是 /v1/chat/completions,现在仍受支持。迁移指南建议所有新项目都用 Responses,而有些模型直接替你做了选择:GPT-6 Astra 和 GPT-6.1 Sol 只能通过 Responses 调用工具。从 GPT-5.4 起,只要推理强度不是 none,Chat Completions 也不再支持工具调用。

指南把迁移看成三处改动:请求发到 /v1/responses,从带类型的 output 列表读取输出,再决定应用怎样在回合之间保存状态。只有文本的消息列表可以原样迁移,同一个数组在一个接口里叫 messages,在另一个接口里叫 input。

其余部分的结构都变了,下表就是对照图。Chat Completions 把文本、工具调用和元数据黏在一个消息对象里,Responses 则把它们拆成各自独立的输出项。迁移指南给下表每一行都配了左右对照的示例。

存储方式也不同。Responses 默认会被存储,Chat Completions 只对新账号默认存储,两个接口都可以用 store: false 关闭存储。迁移旧代码时,有两个缺口最容易绊人。Responses 没有 n 参数,想要多个候选回答,就多请求几次。Assistants API 已经停用,还在调用它的代码只能在 Responses 上重写。

出自迁移指南,2026 年 11 月 5 日阅读。
Chat CompletionsResponses API
messages 数组input,一个字符串或一组输出项
system 或 developer 消息顶层的 instructions
choices[0].message.contentoutput_text,或者 output 里的 message 项
工具调用放在助手消息里独立的 function_call 项,靠 call_id 配对
用 response_format 指定 JSON schematext.format
带 delta 字段的流式片段带类型的事件,比如 response.output_text.delta
用 n 一次生成多个结果不支持,需要分开请求
函数默认是非严格模式省略 strict 时会先尝试严格模式

Atty Eleti 和 OpenAI Developers 谈 Responses API

Atty Eleti 在 OpenAI 工作,是这个接口的设计者之一。2025-03-11 Responses API 发布当天,他在 X 上介绍了它,称它是 OpenAI API 新的基础原语,凝结了两年的经验,也是构建智能体的基础。这条帖子是一串讲设计经过的帖子的开头。你第一次调用拿回的那个带类型的 item 列表,就是这个原语在工作,所以加工具之前,先认熟这些类型。

OpenAI Developers 在 2025-08-26 发帖说,Assistants API 的 beta 会在一年后停用,并附上迁移到 Responses 的指南。同一条帖子还说,Responses API 的 token 用量已经超过了 Chat Completions。时间线里的停用日期就是这一次。还在调用 Assistants 的代码现在得重写,而 Chat Completions 的代码可以一个流程一个流程地迁。

它是我们推荐的 OpenAI API 接入方式,现在如此,将来也是。

OpenAI Developers, OpenAI 面向开发者的官方账号,引文为译文 · X (2026年11月5日 查阅)
Atty Eleti(@athyuttamre)2025 年 3 月 11 日在 X 上发帖:推出 Responses API,OpenAI API 新的基础原语。它凝结了两年设计 OpenAI API 的经验,也是我们构建智能体下一阶段的基础。下面讲讲我们是怎样设计它的。
Atty Eleti 在 X 上,2025 年 3 月 11 日
OpenAI Developers(@OpenAIDevs)2025 年 8 月 26 日在 X 上发帖:我们正在逐步停用 Assistants API beta,它将在一年后,也就是 2026 年 8 月 26 日停用。我们准备了迁移到 Responses API 的指南。帖子还说,Responses API 的 token 用量已经超过 Chat Completions。
OpenAI Developers 在 X 上,2025 年 8 月 26 日
OpenAI 自己的 YouTube 频道上,Build Hour 系列讲 Responses API 的一期。

X 官方嵌入卡片的截图,拍摄于 2026-11-05,时间为 UTC。点击截图可到 X 上打开原帖。X 用 Show more 截断了 OpenAI Developers 的帖子。

常见错误

  • 出于习惯,从 Responses 对象里读取 choices[0].message.content。
  • 把 output[0] 当成回答,而它前面其实还有一个推理项。
  • 手动回放历史时,丢掉了推理项或工具项。
  • 串联的回合没带上 instructions,然后纳闷语气为什么变了。
  • 既传了 previous_response_id,又回放了完整对话,结果模型把同样的回合读了两遍。
  • 以为 previous_response_id 能让先前的回合免费,其实它们每次都按输入计费。
  • 把带类型的 Responses 事件交给旧的流处理代码,而它还在等 delta 片段。
  • 用 dangerouslyAllowBrowser 把密钥放进公开网页。

自己试一试

  • 问一个普通问题,打印 response.output 里每一项的类型。gpt-6-astra 返回了哪些类型?
  • 把 instructions 改成放在 input 最前面的一条 developer 消息,对比两次回复。
  • 用 previous_response_id 串起三个回合,第三个回合不带 instructions。语气还保持得住吗?
  • 用 store=False 发一次调用,再试着从它的 id 串联第二个回合。会发生什么?
  • 同一个问题,先把 reasoning 强度设为 low,再设为 high,记下第一个流式词出现要等多久。
  • 照着上面的对照表,迁移你自己代码里的一个 Chat Completions 调用,再把两边的输出并排比较。

接下来

第 2 课会给模型加上工具,包括你用 JSON Schema 描述的函数,以及由 OpenAI 替你运行的网页搜索和文件搜索。它就从第一张表里的 function_call 项讲起,还有把它和你的结果配对起来的 call_id。

本课里的每一个限额和每一笔费用都按 token 计算。文字在送到模型之前,会先被切分成 token,弄清这一点,串联的对话开始超出预算时,你就知道钱花在了哪里。

自测一下

  1. 你用 previous_response_id 串起第二个回合,第一个回合发过的 instructions 会怎样?

    查看答案

    B. 它们不在上下文里,所以要重新发送 instructions 只对当前请求生效,所以串联的回合要重新发送。

  2. 请求里有推理或工具时,哪种读取回复的方式靠得住?

    查看答案

    A. 遍历 response.output,逐项检查类型 输出列表可能以推理项或工具调用开头,所以代码要按每一项的类型分别处理。

  3. 哪个流式事件带着下一段文字?

    查看答案

    D. response.output_text.delta 每个 response.output_text.delta 事件的 delta 字段里,都是下一段文字。

  4. 你把一个使用 JSON schema 的 Chat Completions 请求迁到 Responses,schema 该放在哪里?

    查看答案

    C. text.format 在 Responses API 里,结构化输出从 response_format 移到了 text.format。

常见问题

OpenAI API 免费吗?

只有第一次测试是免费的。快速入门把你的第一个请求称为免费测试,之后会把你带到账单页面去充值额度,供正式使用。从那以后,用量按 token 计量,记在你的组织账上。价格经常变动,所以这一课不写具体数字。

刚开始该用哪个 OpenAI 模型?

2026 年 11 月 5 日的模型页面建议:复杂推理和编程用 GPT-6 Astra,兼顾能力和成本用 GPT-6.1 Sol,大批量任务用 GPT-6 Luna。三者标注的上下文窗口都是 1,050,000 个 token,最多输出 128,000 个 token。上线生产时,文本生成指南要求固定一个带日期的快照,比如 gpt-5.5-2026-04-23,这样不同版本发布之间行为不会变。

SDK 会自己重试哪些错误?

连接错误,以及 408、409、429 和 500 以上的状态码,默认各重试两次,采用较短的指数退避。请求超时时间是 10 分钟。Python 用 max_retries,JavaScript 用 maxRetries 来调整,失败的调用要记录 _request_id,这是 Python SDK README 给的建议。

现在就得重写我的 Chat Completions 代码吗?

不必一次全改。指南建议一次迁移一个用户流程,先从纯文本生成开始,比较延迟、token 用量和错误之后,再把更多流量切过去。需要在最新模型上调用函数的流程,要最先迁移。

资料来源

  1. OpenAI Docs: Developer quickstart (2026年11月5日 查阅)https://developers.openai.com/api/docs/quickstart
  2. OpenAI Docs: Text generation (2026年11月5日 查阅)https://developers.openai.com/api/docs/guides/text
  3. OpenAI Docs: Streaming API responses (2026年11月5日 查阅)https://developers.openai.com/api/docs/guides/streaming-responses
  4. OpenAI Docs: Conversation state (2026年11月5日 查阅)https://developers.openai.com/api/docs/guides/conversation-state
  5. OpenAI Docs: Migrate to the Responses API (2026年11月5日 查阅)https://developers.openai.com/api/docs/guides/migrate-to-responses
  6. OpenAI Docs: Reasoning models (2026年11月5日 查阅)https://developers.openai.com/api/docs/guides/reasoning
  7. OpenAI Docs: SDKs and CLI (2026年11月5日 查阅)https://developers.openai.com/api/docs/libraries
  8. OpenAI Docs: API keys and service accounts (2026年11月5日 查阅)https://developers.openai.com/api/docs/guides/api-keys
  9. OpenAI Docs: Models (2026年11月5日 查阅)https://developers.openai.com/api/docs/models
  10. OpenAI Docs: GPT-6 Astra (2026年11月5日 查阅)https://developers.openai.com/api/docs/models/gpt-6-astra
  11. openai/openai-python on GitHub (2026年11月5日 查阅)https://github.com/openai/openai-python
  12. openai/openai-node on GitHub (2026年11月5日 查阅)https://github.com/openai/openai-node
  13. X: Atty Eleti introduces the Responses API (2026年11月5日 查阅)https://x.com/athyuttamre/status/1899541471532867821
  14. X: OpenAI Developers on winding down the Assistants API beta (2026年11月5日 查阅)https://x.com/OpenAIDevs/status/1960409187122602172
  15. YouTube (OpenAI): Build Hour: Responses API (2026年11月5日 查阅)https://www.youtube.com/watch?v=hNr5EebepYs

分享本节课

看看基于这些 API 做成的智能体

在 Mindket 浏览其他开发者上架的 AI 智能体,读读它们的设置说明,再把你自己的也上架。

浏览 AI 智能体

本节课的 Markdown 版本 · OpenAI API 实战课:Responses、工具调用、结构化输出与智能体 · 全部课程