SpyBara
Go Premium

Documentation 2026-09-05 17:01 UTC to 2026-09-09 23:59 UTC

33 files changed +4,329 −597. View all changes and history on the product overview
2026
Tue 29 22:57 Mon 28 22:57 Sat 26 23:59 Fri 25 23:58 Thu 24 23:58 Wed 23 23:58 Tue 22 23:57 Mon 21 23:00 Sat 19 23:00 Fri 18 22:59 Thu 17 10:04 Wed 16 20:58 Tue 15 22:59 Mon 14 22:58 Sun 13 15:02 Fri 11 20:00 Thu 10 18:01 Wed 9 23:59 Sat 5 17:01 Fri 4 23:59 Thu 3 23:00 Wed 2 22:59
Details

190mu[j] = mu[j] - c[j] * alpha_frequency - float(c[j] > 0) * alpha_presence190mu[j] = mu[j] - c[j] * alpha_frequency - float(c[j] > 0) * alpha_presence

191```191```

192 192 

193```ruby

194mu[j] = mu[j] - c[j] * alpha_frequency - ((c[j] > 0) ? alpha_presence : 0.0)

195```

196 

193 197 

194Where:198Where:

195 199 

196- `mu[j]` is the logits of the j-th token200- `mu[j]` is the logits of the j-th token

197- `c[j]` is how often that token was sampled prior to the current position201- `c[j]` is how often that token was sampled prior to the current position

198- `float(c[j] > 0)` is 1 if `c[j] > 0` and 0 otherwise202- The presence penalty subtracts `alpha_presence` if `c[j] > 0` and 0 otherwise

199- `alpha_frequency` is the frequency penalty coefficient203- `alpha_frequency` is the frequency penalty coefficient

200- `alpha_presence` is the presence penalty coefficient204- `alpha_presence` is the presence penalty coefficient

201 205 

Details

34 34 

35 35 

36 <figure>36 <figure>

37

38 

39![Diagram showing an agent harness running inside sandbox compute with filesystem access and gateway-mediated access to data, APIs, and the web.](<https://developers.openai.com/images/api/agents/harness_with_compute.png>)

40 

41 

37 <figcaption className="mt-3 text-sm text-gray-600 dark:text-gray-400">42 <figcaption className="mt-3 text-sm text-gray-600 dark:text-gray-400">

38 Running the harness inside the sandbox can be convenient for prototypes,43 Running the harness inside the sandbox can be convenient for prototypes,

39 but it puts orchestration and model-directed execution in the same compute44 but it puts orchestration and model-directed execution in the same compute


42 </figure>47 </figure>

43 48 

44 <figure>49 <figure>

50

51 

52![Diagram showing an agent harness separate from sandbox compute, where the harness accesses trusted services and the sandbox executes commands against a filesystem.](<https://developers.openai.com/images/api/agents/harness_separate_from_compute.png>)

53 

54 

45 <figcaption className="mt-3 text-sm text-gray-600 dark:text-gray-400">55 <figcaption className="mt-3 text-sm text-gray-600 dark:text-gray-400">

46 The harness can run in your infrastructure while the sandbox handles56 The harness can run in your infrastructure while the sandbox handles

47 provider-specific, stateful execution.57 provider-specific, stateful execution.

Details

2 2 

3> For the complete documentation index, see [llms.txt](/llms.txt). Markdown versions of documentation pages are available by appending `.md` to the page URL.3> For the complete documentation index, see [llms.txt](/llms.txt). Markdown versions of documentation pages are available by appending `.md` to the page URL.

4 4 

5Amazon Bedrock makes supported OpenAI models available through AWS-managed5Amazon Bedrock runs supported OpenAI models on AWS-managed infrastructure.

6infrastructure. This deployment path is useful when your organization wants to6Use this guide to compare [OpenAI API feature support](#responses-api-feature-availability)

7keep procurement, identity, regional controls, and related cloud operations in7and connect with the OpenAI SDK. For deployment configuration, use the

8AWS.8[AWS documentation](#availability-and-operations) linked from this page.

9 9 

10Amazon Bedrock availability differs from the OpenAI API. Confirm the supported10Model capabilities and API compatibility determine what your application can

11 model, AWS Region, feature set, and pricing path for your workload before you11 do. AWS manages model access, regional availability, routing, billing, and

12 deploy.12 operational controls for your Bedrock deployment.

13 13 

14## How Bedrock availability works14## How Bedrock availability works

15 15 

16OpenAI models in Amazon Bedrock run through an AWS-managed deployment path with16OpenAI models are available through two Amazon Bedrock endpoints:

17Responses API compatibility for supported models and capabilities.17`bedrock-runtime` and `bedrock-mantle`. Both support the OpenAI-compatible

18Your application still uses OpenAI model behavior, but AWS owns the surrounding18Responses and Chat Completions APIs for supported models, but their feature

19cloud control plane, including account access, regional availability, and19coverage differs.

20billing.

21 20 

22Use Bedrock when you need:21Choose your endpoint based on the capabilities your application needs. For

22example, hosted web search currently requires Mantle. See the

23[endpoint differences](#endpoint-differences) on this page and the AWS [endpoint comparison](https://docs.aws.amazon.com/bedrock/latest/userguide/endpoints.html) for Bedrock-specific capabilities and endpoint selection.

23 24 

24- AWS-native procurement and billing.25GPT-6 Astra is available through Bedrock Runtime and through Mantle in

25- AWS-managed identity, access, and account controls.26 `us-west-2` (Oregon). The examples in this guide use GPT-5.6 Sol in

26- Deployment in supported AWS Regions for customers with cloud-location27 `us-east-2`; select Astra's supported Region before changing the model.

27 requirements.

28 28 

29Use the OpenAI API directly when you need the broadest feature coverage, the29For access and setup, see the AWS [GPT-6 Astra announcement](https://aws.amazon.com/blogs/machine-learning/take-on-your-most-ambitious-work-with-gpt-6-astra-on-amazon-bedrock/) and [Runtime endpoint instructions](https://docs.aws.amazon.com/bedrock/latest/userguide/bedrock-mantle.html).

30latest first-party platform capabilities, or functionality unavailable in

31Bedrock.

32 30 

33## Make Responses API requests31## Make Responses API requests

34 32 

35To send OpenAI SDK requests through Amazon Bedrock, configure your client for33These examples use the OpenAI SDK with the Mantle endpoint. Select the AWS

36the AWS Region and model ID for your deployment:34Region and model ID for your deployment:

37 35 

38- Client libraries with a Bedrock provider derive a regional Mantle base URL36- Client libraries with a Bedrock provider derive a regional Mantle base URL

39 from the AWS Region. The JavaScript, Python, Go, and Java providers use37 from the AWS Region. The JavaScript, Python, Go, and Java providers use

40 `https://bedrock-mantle.us-east-2.api.aws/openai/v1` for this guide's38 `https://bedrock-mantle.us-east-2.api.aws/openai/v1` for this guide's

41 `us-east-2` examples. The Ruby examples configure this `/openai/v1`39 `us-east-2` examples. The Ruby examples configure this `/openai/v1`

42 endpoint directly because the provider's default `/v1` route doesn't40 endpoint directly because the provider's default `/v1` route doesn't

43 support this model. The .NET SDK also configures the endpoint directly41 support this model.

44 because it doesn't include a Bedrock provider.

45- Use a Bedrock model ID with the `openai.` prefix, such as42- Use a Bedrock model ID with the `openai.` prefix, such as

46 `openai.gpt-5.6-sol`.43 `openai.gpt-5.6-sol`.

47 44 

48This example uses `openai.gpt-5.6-sol` in `us-east-2`. Use a supported model and45The examples use `openai.gpt-5.6-sol` in `us-east-2`. For Runtime, follow the AWS [Responses API endpoint instructions](https://docs.aws.amazon.com/bedrock/latest/userguide/bedrock-mantle.html) to select the base URL and inference profile. Do not reuse a Mantle model ID

49AWS Region combination for your Bedrock deployment.46without checking the Runtime requirements.

50 47 

51The following example uses a Bedrock API key stored as48The following example uses a Bedrock API key stored as

52`AWS_BEARER_TOKEN_BEDROCK`. See49`AWS_BEARER_TOKEN_BEDROCK`. See [Amazon Bedrock API keys](https://docs.aws.amazon.com/bedrock/latest/userguide/api-keys.html) for information about generating and using a Bedrock API key.

53[Amazon Bedrock API keys](https://docs.aws.amazon.com/bedrock/latest/userguide/api-keys.html)

54for information about generating and using a Bedrock API key. Each example

55passes the token from your environment to its language's Bedrock provider, or

56for .NET, to the regional OpenAI-compatible endpoint. The .NET SDK doesn't

57currently include a Bedrock provider.

58 50 

59Install the optional Java Bedrock provider before using either Java example:51Install the optional Java Bedrock provider before using either Java example:

60 52 


384```376```

385 377 

386 378 

387## Availability and operations

388 

389Availability depends on AWS Region and model. The initial launch scope is more

390limited than the OpenAI API, so check [model support by AWS

391Region](https://docs.aws.amazon.com/bedrock/latest/userguide/models-region-compatibility.html)

392before rollout.

393 

394Amazon Bedrock provides Responses API-compatible inference for supported OpenAI

395models in supported AWS Regions. AWS manages authentication, account access,

396procurement, and billing.

397 

398AWS Regions are physical deployment locations, which differ from OpenAI data

399residency jurisdictions. Teams with residency requirements should evaluate the

400Bedrock Region itself and the corresponding AWS terms.

401 

402## Data access and retention

403 

404Amazon Bedrock uses separate controls for operator access and data retention:

405 

406- **[Zero operator access (ZOA)](https://aws.amazon.com/blogs/machine-learning/exploring-the-zero-operator-access-design-of-mantle/)**

407 means AWS operators have no technical mechanism to sign in to Mantle's

408 underlying compute systems or access customer data, including inference

409 prompts and completions.

410- **[Zero data retention (ZDR)](https://docs.aws.amazon.com/bedrock/latest/userguide/data-retention.html)**

411 means AWS does not write model inputs or outputs to durable storage when the

412 effective retention mode is `none`.

413 

414For OpenAI models in Amazon Bedrock, AWS does not share request or response

415content with OpenAI when the effective retention mode is `default` or `none`.

416 

417[Configure Bedrock data

418retention](https://docs.aws.amazon.com/bedrock/latest/userguide/data-retention.html#data-retention-configuration)

419for your AWS account or project.

420 

421Under the `default` retention mode, retention depends on the model and request

422settings. For specific OpenAI GPT models, AWS retains classifier-flagged traffic

423for up to 30 days for automated offline abuse detection. Responses API requests

424use `store: true` by default. AWS retains the response, including its input and

425output, for 30 days so you can retrieve it or reference it in a later request.

426See [Amazon Bedrock abuse

427detection](https://docs.aws.amazon.com/bedrock/latest/userguide/abuse-detection.html)

428for the current model list and retention details.

429 

430If you need full ZDR for a model that requires retention, contact your AWS

431account manager to discuss eligibility. AWS evaluates ZDR access for each account

432and model. If AWS approves access, confirm that `none` appears in the model's

433`allowed_modes`, then set the account or project retention mode to `none`.

434Setting `store: false` does not guarantee ZDR. When the effective retention mode

435is `none`, AWS rejects `store: true`, and background mode is unavailable.

436 

437If AWS detects apparent CSAM in an image input, AWS may move the flagged input

438 or output outside the ZOA environment and store and review it only to

439 determine whether it is CSAM. AWS may also file a report with national

440 authorities.

441 

442## Responses API feature availability379## Responses API feature availability

443 380 

444Amazon Bedrock supports a subset of Responses API capabilities available381Use this matrix to identify differences from the OpenAI API. Availability is

445through the OpenAI API. This table describes feature availability as of the382specific to the model and endpoint; a supported API does not imply support for

446date below. It excludes transient availability and service status.383every tool or response mode.

447 

448The information below represents feature availability as of July 13, 2026.

449 Model and Region availability can also change. For the latest information, see

450 the [AWS documentation for OpenAI models in Amazon

451 Bedrock](https://docs.aws.amazon.com/bedrock/latest/userguide/model-cards-openai.html)

452 and [model support by AWS

453 Region](https://docs.aws.amazon.com/bedrock/latest/userguide/models-region-compatibility.html).

454 384 

455| Capability | OpenAI API | Amazon Bedrock |385| Capability | OpenAI API | Amazon Bedrock |

456| ------------------------- | ----------------------------- | ------------------------------------------------- |386| ------------------------- | ----------------------------- | ----------------------------- |

457| Text generation | Available | Available |387| Text generation | Available | Available |

458| Image input | Available | Available |388| Image input | Available | Available |

459| File input | Available | Available for supported file types |389| File input | Available | Available |

460| Structured outputs | Available | Available |390| Structured outputs | Available | Available |

461| Function calling | Available | Available |391| Function calling | Available | Available |

392| Asynchronous tool calling | Available on supported models | Not available |

462| Streaming responses | Available | Available |393| Streaming responses | Available | Available |

463| WebSocket connections | Available | Not available |394| WebSocket connections | Available | Not available |

464| Context window | Model-dependent | 272,000 tokens for GPT-5.4 and GPT-5.5 |395| Mid-turn steering | Available on supported models | Not available |

465| Context window | Model-dependent | 1,050,000 tokens for GPT-5.6 Sol, Terra, and Luna |396| Context window | Model-dependent | Model-dependent |

466| Reasoning effort | Available | Available, including `max` on supported models |397| Reasoning effort | Available | Available |

398| Reasoning updates | Available on supported models | Not available |

467| Pro mode | Available on supported models | Not available |399| Pro mode | Available on supported models | Not available |

468| Persisted reasoning | Available on supported models | Available on supported models |400| Persisted reasoning | Available on supported models | Available on supported models |

469| Prompt caching | Available | Implicit and explicit caching on supported models |401| Prompt caching | Available | Available |

470| Programmatic Tool Calling | Available on supported models | Not available |402| Programmatic Tool Calling | Available on supported models | Not available |

471| Multi-agent | Beta on supported models | Not available |403| Multi-agent | Beta on supported models | Not available |

472| Custom tools | Available | Available |404| Custom tools | Available | Available |

473| Client-side `tool_search` | Available | Available |405| Client-side `tool_search` | Available | Available |

474| Hosted web search | Available | Available |406| Hosted web search | Available | Mantle only |

475| Hosted file search | Available | Not available |407| Hosted file search | Available | Not available |

476| Computer use | Available | Not available |408| Computer use | Available | Available |

477| Shell tool | Available | Not available |409| Shell tool | Available | Not available |

478| Image generation tool | Available | Not available |410| Image generation tool | Available | Not available |

479| Remote MCP servers | Available | Not available |411| Remote MCP servers | Available | Not available |

480| Service tiers | Available where supported | On-demand inference only |412 

413Asynchronous tool calling (`async: true`) and reasoning updates

414(`configuration_update` input items) are not supported on Amazon Bedrock.

415Mid-turn steering requires WebSockets and is not available through either

416Bedrock endpoint.

481 417 

482Client-side `tool_search` is distinct from hosted tools and remote MCP server418Client-side `tool_search` is distinct from hosted tools and remote MCP server

483support. Hosted web search is available on Amazon Bedrock, but hosted file419support. Hosted web search is available through Mantle; hosted file search and

484search and remote MCP servers are unavailable.420remote MCP servers are unavailable.

485 421 

486GPT-5.4 and GPT-5.5 have a 272,000-token context window on Amazon Bedrock.422Computer use is available on Runtime and Mantle for supported models. Your

487GPT-5.6 Sol, Terra, and Luna have a 1,050,000-token context window. Amazon423application executes computer actions and returns results to the model; this

488Bedrock rejects requests that exceed the applicable model limit. See the AWS424capability does not require a Bedrock-hosted execution environment.

489model cards for current model-specific limits.

490 425 

491Treat feature parity as workload-specific. If your application depends on a426On Amazon Bedrock, GPT-5.4 and GPT-5.5 support a 1-million-token context window;

492specific tool, response mode, or service tier, test that behavior through427GPT-5.6 Sol, Terra, Luna, and GPT-6 Astra support 1,050,000 tokens. Check the AWS [OpenAI model cards](https://docs.aws.amazon.com/bedrock/latest/userguide/model-cards-openai.html) for model-specific limits.

493Bedrock before you commit to the deployment path.

494 428 

495## Authentication and operations429### Endpoint differences

496 430 

497Amazon Bedrock uses AWS-managed access controls. Your AWS administrator controls431These Responses API differences apply when choosing between Runtime and Mantle:

498which accounts, roles, or temporary credentials can reach the supported model

499deployment. The exact authentication flow depends on the Bedrock configuration

500your organization uses.

501 432 

502Plan for AWS-owned operational checks such as:433| Capability | Bedrock Runtime | Mantle |

434| -------------------------------------- | -------------------------------- | --------------------------------------------------------------------------- |

435| GPT-6 Astra | Available | Available in `us-west-2` (Oregon) |

436| Computer use | Available on supported models | Available on supported models |

437| Streaming responses | Available | Available |

438| Background mode (`background: true`) | Not available | Available, subject to [data retention settings](#data-access-and-retention) |

439| Hosted web search | Not available | Available on supported models |

440| Continuing with `previous_response_id` | Include `model` on every request | The model can be inherited from the previous response |

441 

442Runtime requires `model` even when you supply `previous_response_id`. Background

443mode is separate from streaming and does not describe asynchronous function

444calling. Use the AWS [Responses API documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/bedrock-mantle.html) for the complete endpoint contract. For web search permissions and

445configuration, see the AWS [web search guide](https://docs.aws.amazon.com/bedrock/latest/userguide/web-search.html).

446 

447## Availability and operations

448 

449AWS maintains the deployment options and availability for Amazon Bedrock. Use

450these references to select and configure your deployment:

451 

452| AWS-managed concern | AWS documentation |

453| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |

454| Model IDs and supported APIs | [OpenAI model cards](https://docs.aws.amazon.com/bedrock/latest/userguide/model-cards-openai.html) |

455| Model and endpoint availability by AWS Region | [Model availability](https://docs.aws.amazon.com/bedrock/latest/userguide/models-region-compatibility.html) and [endpoint availability](https://docs.aws.amazon.com/bedrock/latest/userguide/endpoints-region-availability.html) |

456| Geographic and global request routing | [Cross-Region inference](https://docs.aws.amazon.com/bedrock/latest/userguide/cross-region-inference.html) |

457| Account quotas and increase requests | [Amazon Bedrock quotas](https://docs.aws.amazon.com/bedrock/latest/userguide/quotas.html) |

458 

459An AWS Region is not an OpenAI data residency jurisdiction. If your workload has

460location requirements, review the destination Regions of your inference profile

461and the applicable AWS terms, not only the Region in your endpoint URL.

462 

463## Data access and retention

464 

465Amazon Bedrock uses separate controls for operator access and data retention:

466 

467- **Zero operator access (ZOA)** means AWS operators have no technical mechanism

468 to sign in to Mantle's underlying compute systems or access customer data

469 there. See the AWS [ZOA design](https://aws.amazon.com/blogs/machine-learning/exploring-the-zero-operator-access-design-of-mantle/).

470- **Zero data retention (ZDR)** means AWS does not write request or response data

471 to durable storage when the effective retention mode is `none`.

472 

473Setting `store: false` does not guarantee ZDR. For Responses API requests with an

474effective retention mode of `none`, AWS rejects `store: true`, and background

475mode is unavailable.

476 

477For OpenAI models in Amazon Bedrock, AWS does not share request or response

478content with OpenAI when the effective retention mode is `default` or `none`.

479Use the AWS [data retention documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/data-retention.html) for available modes, eligibility, and account or project configuration. See [Amazon Bedrock abuse detection](https://docs.aws.amazon.com/bedrock/latest/userguide/abuse-detection.html) for model-specific retention requirements and exceptions.

480 

481If AWS detects apparent CSAM in an image input, AWS may move the flagged input

482 or output outside the ZOA environment and store and review it only to

483 determine whether it is CSAM. AWS may also file a report with national

484 authorities.

485 

486## Authentication and operations

503 487 

504- Account and model access configuration.488Your AWS administrator controls account, model, and feature access. Use the AWS [API key documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/api-keys.html) for credential creation and lifecycle, and the [IAM documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/security-iam.html) for identities and permissions. The OpenAI SDK examples on this page show how to

505- Region-specific deployment approval.489supply those credentials; they do not configure AWS permissions.

506- Temporary credential or token validity.

507- AWS quota, logging, and support workflows.

508 490 

509## Pricing491## Pricing

510 492 

511AWS bills Amazon Bedrock usage. Bedrock-specific pricing can differ from direct493Amazon Bedrock usage is billed through AWS. Bedrock pricing in commercial regions

512OpenAI API pricing, including regional processing premiums or other AWS-specific494matches OpenAI direct pricing for equivalent services. Note that using a

513commercial terms.495region-specific service in Bedrock will be priced at the same rate as Regional

496processing in the OpenAI API. Amazon commercial terms apply to Bedrock usage.

514 497 

515See [API pricing](https://developers.openai.com/api/docs/pricing) for direct OpenAI API pricing. For Bedrock498See [API pricing](https://developers.openai.com/api/docs/pricing) for direct OpenAI API pricing. For Bedrock

516pricing, use the AWS pricing materials published for the Bedrock deployment you499rates, supported service tiers, and billing options, use [Amazon Bedrock pricing](https://aws.amazon.com/bedrock/pricing/) and the applicable model card.

517plan to use.

518 500 

519## Next steps501## Next steps

520 502 

521- Confirm your supported model and AWS Region in Amazon Bedrock.503For setup in ChatGPT Work and Codex, see

522- Verify the exact API features your workload needs.504[Use ChatGPT Work and Codex with Amazon Bedrock](https://developers.openai.com/codex/amazon-bedrock).

523- Compare Bedrock pricing and direct API pricing before launch.

524- For setup in ChatGPT Work and Codex, see

525 [Use ChatGPT Work and Codex with Amazon Bedrock](https://developers.openai.com/codex/amazon-bedrock).

Details

52 52 

531. On your server, generate a client token.531. On your server, generate a client token.

54 54 

55 This snippet spins up a FastAPI service whose sole job is to create a new ChatKit session through the OpenAI API and hand back the session's client secret:55 This example starts a service that creates a ChatKit session through the OpenAI API and returns the session's client secret:

56 

57 server.py

58 56 

59```python57```python

60import hmac58import hmac


118 return {"client_secret": session.client_secret}116 return {"client_secret": session.client_secret}

119```117```

120 118 

119```ruby

120require "json"

121require "net/http"

122require "openssl"

123require "webrick"

124 

125api_key = ENV.fetch("OPENAI_API_KEY")

126workflow_id = ENV.fetch("OPENAI_CHATKIT_WORKFLOW_ID")

127# Demo authentication mapping. Replace this with your application's session authentication.

128authenticated_users = JSON.parse(ENV.fetch("CHATKIT_AUTHENTICATED_USERS"))

129server = WEBrick::HTTPServer.new(

130 BindAddress: "127.0.0.1", Port: Integer(ENV.fetch("PORT", "8000")),

131 AccessLog: [], Logger: WEBrick::Log.new($stderr, WEBrick::BasicLog::WARN)

132)

133server.mount_proc("/api/chatkit/session") do |request, response|

134 response["Content-Type"] = "application/json"

135 response["Cache-Control"] = "no-store"

136 unless request.path == "/api/chatkit/session" && request.request_method == "POST"

137 response.status = 405

138 response.body = JSON.generate(error: "Use POST /api/chatkit/session")

139 next

140 end

141 token = request["Authorization"].to_s.delete_prefix("Bearer ")

142 user = authenticated_users.find do |credential, _id|

143 request["Authorization"].to_s.start_with?("Bearer ") &&

144 OpenSSL.secure_compare(credential, token)

145 end

146 unless user

147 response.status = 401

148 response.body = JSON.generate(error: "Invalid authentication token")

149 next

150 end

151 uri = URI("https://api.openai.com/v1/chatkit/sessions")

152 upstream = Net::HTTP::Post.new(uri)

153 upstream["Authorization"] = "Bearer #{api_key}"

154 upstream["Content-Type"] = "application/json"

155 upstream["OpenAI-Beta"] = "chatkit_beta=v1"

156 upstream.body = JSON.generate(workflow: {id: workflow_id}, user: user.fetch(1))

157 begin

158 result = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true, open_timeout: 10, read_timeout: 30) do |http|

159 http.request(upstream)

160 end

161 result.value

162 secret = JSON.parse(result.body).fetch("client_secret")

163 raise "Missing session secret" unless secret.is_a?(String) && !secret.empty?

164 response.body = JSON.generate(client_secret: secret)

165 rescue

166 response.status = 502

167 response.body = JSON.generate(error: "Unable to create a ChatKit session")

168 end

169end

170trap("INT") { server.shutdown }

171trap("TERM") { server.shutdown }

172puts("http://127.0.0.1:#{server.config[:Port]}/api/chatkit/session")

173$stdout.flush

174server.start

175```

176 

177 

178 For Ruby, install WEBrick with `gem install webrick`.

121 179 

122 Before starting the service, set `OPENAI_API_KEY`, `OPENAI_CHATKIT_WORKFLOW_ID`, and `CHATKIT_AUTHENTICATED_USERS`. The last value is a JSON map from your application's bearer tokens to stable user IDs. In production, replace this environment-backed map with your application's authentication or session lookup.180 Before starting the service, set `OPENAI_API_KEY`, `OPENAI_CHATKIT_WORKFLOW_ID`, and `CHATKIT_AUTHENTICATED_USERS`. The last value is a JSON map from your application's bearer tokens to stable user IDs. In production, replace this environment-backed map with your application's authentication or session lookup.

123 181 

Details

14| [Use Multi-agent for parallel work](#use-multi-agent-for-parallel-work) | Quality, cost, latency |14| [Use Multi-agent for parallel work](#use-multi-agent-for-parallel-work) | Quality, cost, latency |

15| [Leverage built-in tools](#leverage-built-in-tools) | Quality |15| [Leverage built-in tools](#leverage-built-in-tools) | Quality |

16| [Leverage compaction](#leverage-compaction) | Cost |16| [Leverage compaction](#leverage-compaction) | Cost |

17| [Use `prompt_cache_key`](#use-promptcachekey) | Latency, cost |17| [Optimize prompt caching](#optimize-prompt-caching) | Latency, cost |

18| [Use `reasoning.encrypted_content`](#use-reasoningencryptedcontent) | Quality, latency |18| [Use `reasoning.encrypted_content`](#use-reasoningencryptedcontent) | Quality, latency |

19| [Set image detail intentionally](#set-image-detail-intentionally) | Quality, cost, latency |19| [Set image detail intentionally](#set-image-detail-intentionally) | Quality, cost, latency |

20| [Send a safety identifier](#send-a-safety-identifier) | Safety, reliability |20| [Send a safety identifier](#send-a-safety-identifier) | Safety, reliability |


1034```1034```

1035 1035 

1036 1036 

1037## Use `prompt_cache_key`1037<a id="use-promptcachekey"></a>

1038 

1039<a id="separate-prompts-with-promptcachekey"></a>

1040 

1041## Optimize prompt caching

1038 1042 

1039[Prompt caching](https://developers.openai.com/api/docs/guides/prompt-caching) automatically reduces latency1043[Prompt caching](https://developers.openai.com/api/docs/guides/prompt-caching) automatically reduces latency

1040and cost when requests reuse the same long prefix. For high-volume workflows,1044and cost when requests reuse the same long prefix. Put stable instructions,

1041set1045examples, and reference material first, followed by dynamic user-specific

1042[`prompt_cache_key`](https://developers.openai.com/api/reference/resources/responses/methods/create#responses-create-prompt_cache_key)1046content. Keep tool definitions and ordering stable, and append new conversation

1043consistently for requests that share the same stable prefix. The service1047turns without rewriting earlier context.

1044combines the key with the prompt prefix hash to help route similar requests to

1045the same cache without changing the model input. Keep the key stable for

1046genuinely shared prefixes, choose a granularity that avoids sending too much

1047traffic to one key, and keep total traffic across the prefixes for each key to

1048about 15 requests per minute. Partition higher-volume traffic across more keys

1049with a stable mapping.

1050 1048 

1051GPT-5.6 introduced explicit prompt caching. Implicit caching remains the1049GPT-5.6 introduced explicit prompt caching. Implicit caching remains the

1052default, but GPT-5.6 models and later model families also support explicit1050default, but GPT-5.6 models and later model families also support explicit

1053cache breakpoints and request-wide cache policy. On those models, set1051cache breakpoints and request-wide cache policy. If a changing suffix comes

1054`prompt_cache_key` to use the more reliable matching for both implicit caching1052after a stable prefix, add an explicit `prompt_cache_breakpoint` at the reusable boundary. Set

1055and explicit breakpoints. If a changing suffix comes after a stable prefix, add

1056an explicit `prompt_cache_breakpoint` at the reusable boundary. Set

1057`prompt_cache_options.mode` to `explicit` only when the request should use only1053`prompt_cache_options.mode` to `explicit` only when the request should use only

1058the breakpoints you provide and no implicit breakpoint. Earlier models continue1054the breakpoints you provide and no implicit breakpoint. Earlier models continue

1059to use automatic prompt caching only.1055to use automatic prompt caching only.

1060 1056 

1061On GPT-5.6 models and later model families, cache writes cost 1.25× the1057On GPT-5.6 models and later model families, cache writes cost 1.25× the

1062uncached input token rate. Log `cached_tokens` and `cache_write_tokens`, then1058uncached input token rate. Log `cached_tokens` and `cache_write_tokens`, then

1063compare write volume with later cache reads to measure net cost and tune key1059compare write volume with later cache reads to measure net cost and tune

1064granularity and breakpoint placement.1060breakpoint placement.

1065 1061 

1066Route related requests to the same prompt cache1062Use an optional `prompt_cache_key` to maintain separate cache accounting for

1063customers, users, or workspaces. This can make cached token usage and billing

1064easier to explain for each group. Assign a distinct key to each customer and

1065keep it stable across that customer's related requests. Separate keys also help

1066prevent cache-hit probing across customers. See [Separate cache accounting with

1067keys](https://developers.openai.com/api/docs/guides/prompt-caching#separate-prompts-with-cache-keys).

1068 

1069Maintain separate cache accounting for a customer

1067 1070 

1068```javascript1071```javascript

1069import OpenAI from "openai";1072import OpenAI from "openai";


1698 1701 

1699The Python sample uses `pip install "openai[realtime]>=3.8.0"`.1702The Python sample uses `pip install "openai[realtime]>=3.8.0"`.

1700The JavaScript sample uses `npm install openai@^7.10.0 ws`.1703The JavaScript sample uses `npm install openai@^7.10.0 ws`.

1704The Ruby sample uses `gem install async-websocket`.

1701 1705 

1702Start a Responses API WebSocket session1706Start a Responses API WebSocket session

1703 1707 


1778 print(first_event.type)1782 print(first_event.type)

1779```1783```

1780 1784 

1785```ruby

1786require "async"

1787require "async/http/endpoint"

1788require "async/websocket/client"

1789require "json"

1790 

1791def wait_for_response(connection)

1792 while (message = connection.read)

1793 event = JSON.parse(message.to_str)

1794 case event.fetch("type")

1795 when "response.completed" then return event.fetch("response")

1796 when "response.failed", "response.incomplete", "error"

1797 raise "Response failed: #{JSON.generate(event)}"

1798 end

1799 end

1800 raise "Connection closed before the response finished"

1801end

1802 

1803test_log_tool = {

1804 type: "function", name: "search_test_logs", description: "Search test logs.",

1805 parameters: {type: "object", properties: {query: {type: "string"}}, required: ["query"], additionalProperties: false},

1806 strict: true

1807}

1808code_search_tool = {

1809 type: "function", name: "search_code", description: "Search source code.",

1810 parameters: {type: "object", properties: {query: {type: "string"}}, required: ["query"], additionalProperties: false},

1811 strict: true

1812}

1813 

1814endpoint = Async::HTTP::Endpoint.parse("wss://api.openai.com/v1/responses", timeout: 10, alpn_protocols: ["http/1.1"])

1815headers = {"Authorization" => "Bearer #{ENV.fetch("OPENAI_API_KEY")}"}

1816Sync do |task|

1817 task.with_timeout(120) do

1818 Async::WebSocket::Client.connect(endpoint, headers: headers) do |connection|

1819 connection.write(JSON.generate(

1820 type: "response.create", stream_id: "main", model: "gpt-6-astra", store: false,

1821 input: [{role: "user", content: "Find the flaky test in this run, call the tools you need, and keep going until you can explain the root cause."}],

1822 tools: [test_log_tool, code_search_tool]

1823 ))

1824 connection.flush

1825 puts(JSON.pretty_generate(wait_for_response(connection).fetch("output")))

1826 end

1827 end

1828end

1829```

1830 

1781 1831 

1782## Final takeaway1832## Final takeaway

1783 1833 

Details

235print("run response:", response.text)235print("run response:", response.text)

236```236```

237 237 

238```ruby

239require "openai"

240 

241client = OpenAI::Client.new

242grader = {

243 "type" => "score_model",

244 "name" => "my_score_model",

245 "input" => [{

246 "role" => "system",

247 "content" => "You are an expert grader. If the reference and model answer are exact matches, output a score of 1. If they are somewhat similar in meaning, output a score in 0.5. Otherwise, give a score of 0."

248 }, {

249 "role" => "user",

250 "content" => "Reference: {{ item.reference_answer }}. Model answer: {{ sample.output_text }}"

251 }],

252 "pass_threshold" => 0.5,

253 "model" => "o4-mini-2025-04-16",

254 "range" => [0, 1],

255 "sampling_params" => {

256 "max_completions_tokens" => 32768,

257 "top_p" => 1,

258 "reasoning_effort" => "medium"

259 }

260}

261item = {reference_answer: 1.0}

262model_sample = "0.9"

263 

264pp(client.fine_tuning.alpha.graders.validate(grader: grader))

265pp(client.fine_tuning.alpha.graders.run(grader: grader, item: item, model_sample: model_sample))

266```

267 

238 268 

239#### Score model grader outputs269#### Score model grader outputs

240 270 


344}374}

345```375```

346 376 

347Here's a working example:377Here's a working example. For Ruby, save the `grade` function shown above, including its import, as `grader.py`. Set `OPENAI_GRADER_SOURCE_PATH` to that file's path before running the example. The supplied function returns `1.0`; replace its body with your grading logic.

348 378 

349```python379```python

350import os380import os


391print("run response:", response.text)421print("run response:", response.text)

392```422```

393 423 

424```ruby

425require "openai"

426 

427client = OpenAI::Client.new

428# Set OPENAI_GRADER_SOURCE_PATH to the Python grader file to upload.

429grader = {type: :python, source: File.read(ENV.fetch("OPENAI_GRADER_SOURCE_PATH"))}

430item = {reference_answer: "fuzzy wuzzy had no hair"}

431model_sample = "fuzzy wuzzy was a bear"

432 

433pp(client.fine_tuning.alpha.graders.validate(grader: grader))

434pp(client.fine_tuning.alpha.graders.run(grader: grader, item: item, model_sample: model_sample))

435```

436 

394 437 

395**Tip:**438**Tip:**

396If you don't want to manually put your grading function in a string, you can also load it from a Python file using `importlib` and `inspect`. For example, if your grader function is in a file named `grader.py`, you can do:439If you don't want to manually put your grading function in a string, you can also load it from a Python file using `importlib` and `inspect`. For example, if your grader function is in a file named `grader.py`, you can do:

Details

4 4 

5## Overview5## Overview

6 6 

7The OpenAI API lets you generate and edit images from text prompts using GPT Image models, including our latest, `gpt-image-2`. You can access image generation capabilities through two APIs:7The API lets you generate and edit images from text prompts using `gpt-image-2.5-sunburst` and `gpt-image-2.5-flare`. Choose Sunburst for workflows where editing precision matters most, and Flare for fast, high-quality everyday image generation. You can access image generation capabilities through two APIs:

8 8 

9### Image API9### Image API

10 10 

11Starting with `gpt-image-1` and later models, the [Image API](https://developers.openai.com/api/reference/resources/images) provides two endpoints, each with distinct capabilities:11The [Image API](https://developers.openai.com/api/reference/resources/images) provides two endpoints, each with distinct capabilities:

12 12 

13- **Generations**: [Generate images](#generate-images) from scratch based on a text prompt13- **Generations**: [Generate images](#generate-images) from scratch based on a text prompt

14- **Edits**: [Modify existing images](#edit-images) using a new prompt, either partially or entirely14- **Edits**: [Modify existing images](#edit-images) using a new prompt, either partially or entirely


22- **Multi-turn editing**: Iteratively make high fidelity edits to images with prompting22- **Multi-turn editing**: Iteratively make high fidelity edits to images with prompting

23- **Flexible inputs**: Accept image [File](https://developers.openai.com/api/reference/resources/files) IDs as input images, not just bytes23- **Flexible inputs**: Accept image [File](https://developers.openai.com/api/reference/resources/files) IDs as input images, not just bytes

24 24 

25The Responses API image generation tool uses its own GPT Image model selection. For details on mainline models that support calling this tool, refer to the [supported models](#supported-models) below.25For mainline models that can call the image generation tool, refer to [supported models](#supported-models).

26 26 

27### Choosing the right API27### Choosing the right API

28 28 

29- If you only need to generate or edit a single image from one prompt, the Image API is your best choice.29- If you only need to generate or edit a single image from one prompt, the Image API is your best choice.

30- If you want to build conversational, editable image experiences with GPT Image, go with the Responses API.30- If you want to build conversational, editable image experiences with GPT Image, go with the Responses API.

31 31 

32With the Image API, you choose a GPT Image model directly. With the Responses API, you choose a mainline model that supports the image generation tool; the tool handles GPT Image model selection. Responses API requests include the mainline model's token usage in addition to image generation costs.32With the Image API, set `model` to `gpt-image-2.5-sunburst` or `gpt-image-2.5-flare` directly. With the Responses API, select a supported mainline model at the top level and specify `gpt-image-2.5-sunburst` or `gpt-image-2.5-flare` in the image generation tool's `model` field.

33 33 

34Both APIs let you [customize output](#customize-image-output) by adjusting quality, size, format, and compression. Transparent backgrounds depend on model support.34Both APIs let you [customize output](#customize-image-output) by adjusting quality, size, format, and compression.

35 

36This guide focuses on GPT Image.

37 35 

38To ensure these models are used responsibly, you may need to complete the [API36To ensure these models are used responsibly, you may need to complete the [API

39 Organization37 Organization

40 Verification](https://help.openai.com/en/articles/10910291-api-organization-verification)38 Verification](https://help.openai.com/en/articles/10910291-api-organization-verification)

41 from your [developer39 from your [developer

42 console](https://platform.openai.com/settings/organization/general) before40 console](https://platform.openai.com/settings/organization/general) before

43 using GPT Image models, including `gpt-image-2`, `gpt-image-1.5`,41 using GPT Image models.

44 `gpt-image-1`, and `gpt-image-1-mini`.

45 42 

46<div43<div

47 className="not-prose"44 className="not-prose"

48 style={{ float: "right", margin: "10px 0 10px 10px" }}45 style={{ float: "right", margin: "10px 0 10px 10px" }}

49>46>

50 <img src="https://cdn.openai.com/API/docs/images/mug.png"47 <img src="https://developers.openai.com/images/image-25-article/mug.png"

51 alt="A beige coffee mug on a wooden table"48 alt="A beige coffee mug on a wooden table"

52 style={{ height: "180px", width: "auto", borderRadius: "8px" }}49 style={{ height: "180px", width: "auto", borderRadius: "8px" }}

53 />50 />


79`;76`;

80 77 

81const result = await openai.images.generate({78const result = await openai.images.generate({

82 model: "gpt-image-2",79 model: "gpt-image-2.5-sunburst",

83 prompt,80 prompt,

84});81});

85 82 


100listen to the heartbeat of a baby otter.97listen to the heartbeat of a baby otter.

101"""98"""

102 99 

103result = client.images.generate(model="gpt-image-2", prompt=prompt)100result = client.images.generate(model="gpt-image-2.5-sunburst", prompt=prompt)

104 101 

105image_base64 = result.data[0].b64_json102image_base64 = result.data[0].b64_json

106image_bytes = base64.b64decode(image_base64)103image_bytes = base64.b64decode(image_base64)


124func main() {121func main() {

125 client := openai.NewClient()122 client := openai.NewClient()

126 result, err := client.Images.Generate(context.Background(), openai.ImageGenerateParams{123 result, err := client.Images.Generate(context.Background(), openai.ImageGenerateParams{

127 Model: openai.ImageModel("gpt-image-2"),124 Model: openai.ImageModel("gpt-image-2.5-sunburst"),

128 Prompt: "A children's book drawing of a veterinarian using a stethoscope to " +125 Prompt: "A children's book drawing of a veterinarian using a stethoscope to " +

129 "listen to the heartbeat of a baby otter.",126 "listen to the heartbeat of a baby otter.",

130 })127 })


155 .images()152 .images()

156 .generate(153 .generate(

157 ImageGenerateParams.builder()154 ImageGenerateParams.builder()

158 .model("gpt-image-2")155 .model("gpt-image-2.5-sunburst")

159 .prompt("A watercolor robot reading in a library")156 .prompt("A watercolor robot reading in a library")

160 .build());157 .build());

161 158 


168using OpenAI.Images;165using OpenAI.Images;

169 166 

170string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;167string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;

171string model = "gpt-image-2";168string model = "gpt-image-2.5-sunburst";

172ImageClient client = new(model, key);169ImageClient client = new(model, key);

173 170 

174GeneratedImage image = await client.GenerateImageAsync(171GeneratedImage image = await client.GenerateImageAsync(


185 182 

186client = OpenAI::Client.new183client = OpenAI::Client.new

187result = client.images.generate(184result = client.images.generate(

188 model: "gpt-image-2",185 model: "gpt-image-2.5-sunburst",

189 prompt: "A watercolor robot reading in a library"186 prompt: "A watercolor robot reading in a library"

190)187)

191generated_image = result.data&.first or raise "No image returned"188generated_image = result.data&.first or raise "No image returned"


200 -H "Authorization: Bearer $OPENAI_API_KEY" \197 -H "Authorization: Bearer $OPENAI_API_KEY" \

201 -H "Content-type: application/json" \198 -H "Content-type: application/json" \

202 -d '{199 -d '{

203 "model": "gpt-image-2",200 "model": "gpt-image-2.5-sunburst",

204 "prompt": "A children'\''s book drawing of a veterinarian using a stethoscope to listen to the heartbeat of a baby otter."201 "prompt": "A children'\''s book drawing of a veterinarian using a stethoscope to listen to the heartbeat of a baby otter."

205 }' | jq -r '.data[0].b64_json' | base64 --decode > otter.png202 }' | jq -r '.data[0].b64_json' | base64 --decode > otter.png

206```203```

207 204 

208```bash205```bash

209openai images generate \206openai images generate \

210 --model gpt-image-2 \207 --model gpt-image-2.5-sunburst \

211 --prompt "A children's book drawing of a veterinarian using a stethoscope to listen to the heartbeat of a baby otter." \208 --prompt "A children's book drawing of a veterinarian using a stethoscope to listen to the heartbeat of a baby otter." \

212 --raw-output \209 --raw-output \

213 --transform 'data.0.b64_json' | base64 --decode > otter.png210 --transform 'data.0.b64_json' | base64 --decode > otter.png


230 model: "gpt-6-astra",227 model: "gpt-6-astra",

231 input:228 input:

232 "Generate an image of gray tabby cat hugging an otter with an orange scarf",229 "Generate an image of gray tabby cat hugging an otter with an orange scarf",

233 tools: [{ type: "image_generation" }],230 tools: [{ type: "image_generation", model: "gpt-image-2.5-sunburst" }],

234});231});

235 232 

236// Save the image to a file233// Save the image to a file


254response = client.responses.create(251response = client.responses.create(

255 model="gpt-6-astra",252 model="gpt-6-astra",

256 input="Generate an image of gray tabby cat hugging an otter with an orange scarf",253 input="Generate an image of gray tabby cat hugging an otter with an orange scarf",

257 tools=[{"type": "image_generation"}],254 tools=[{"type": "image_generation", "model": "gpt-image-2.5-sunburst"}],

258)255)

259 256 

260# Save the image to a file257# Save the image to a file


289 Input: responses.ResponseNewParamsInputUnion{286 Input: responses.ResponseNewParamsInputUnion{

290 OfString: openai.String("Generate an image of gray tabby cat hugging an otter with an orange scarf"),287 OfString: openai.String("Generate an image of gray tabby cat hugging an otter with an orange scarf"),

291 },288 },

292 Tools: []responses.ToolUnionParam{{OfImageGeneration: &responses.ToolImageGenerationParam{}}},289 Tools: []responses.ToolUnionParam{{OfImageGeneration: &responses.ToolImageGenerationParam{Model: "gpt-image-2.5-sunburst"}}},

293 })290 })

294 if err != nil {291 if err != nil {

295 panic(err)292 panic(err)


354 "Generate an image of a gray tabby cat hugging an otter with an orange scarf."351 "Generate an image of a gray tabby cat hugging an otter with an orange scarf."

355 )352 )

356);353);

357options.Tools.Add(ResponseTool.CreateImageGenerationTool(model: "gpt-image-2"));354options.Tools.Add(ResponseTool.CreateImageGenerationTool(model: "gpt-image-2.5-sunburst"));

358 355 

359ResponseResult response = await client.CreateResponseAsync(options);356ResponseResult response = await client.CreateResponseAsync(options);

360ImageGenerationCallResponseItem image = response357ImageGenerationCallResponseItem image = response


372response = client.responses.create(369response = client.responses.create(

373 model: "gpt-6-astra",370 model: "gpt-6-astra",

374 input: "Generate an image of a gray tabby cat hugging an otter with an orange scarf.",371 input: "Generate an image of a gray tabby cat hugging an otter with an orange scarf.",

375 tools: [{type: :image_generation}]372 tools: [{type: :image_generation, model: "gpt-image-2.5-sunburst"}]

376)373)

377 374 

378image_call = response.output.find do |item|375image_call = response.output.find do |item|


405 model: "gpt-6-astra",402 model: "gpt-6-astra",

406 input:403 input:

407 "Generate an image of gray tabby cat hugging an otter with an orange scarf",404 "Generate an image of gray tabby cat hugging an otter with an orange scarf",

408 tools: [{ type: "image_generation", action: "generate" }],405 tools: [

406 { type: "image_generation", model: "gpt-image-2.5-sunburst", action: "generate" },

407 ],

409});408});

410 409 

411// Save the image to a file410// Save the image to a file


429response = client.responses.create(428response = client.responses.create(

430 model="gpt-6-astra",429 model="gpt-6-astra",

431 input="Generate an image of gray tabby cat hugging an otter with an orange scarf",430 input="Generate an image of gray tabby cat hugging an otter with an orange scarf",

432 tools=[{"type": "image_generation", "action": "generate"}],431 tools=[

432 {"type": "image_generation", "model": "gpt-image-2.5-sunburst", "action": "generate"}

433 ],

433)434)

434 435 

435# Save the image to a file436# Save the image to a file


464 Input: responses.ResponseNewParamsInputUnion{465 Input: responses.ResponseNewParamsInputUnion{

465 OfString: openai.String("Generate an image of gray tabby cat hugging an otter with an orange scarf"),466 OfString: openai.String("Generate an image of gray tabby cat hugging an otter with an orange scarf"),

466 },467 },

467 Tools: []responses.ToolUnionParam{{OfImageGeneration: &responses.ToolImageGenerationParam{Action: "generate"}}},468 Tools: []responses.ToolUnionParam{{OfImageGeneration: &responses.ToolImageGenerationParam{Model: "gpt-image-2.5-sunburst", Action: "generate"}}},

468 })469 })

469 if err != nil {470 if err != nil {

470 panic(err)471 panic(err)


530);531);

531options.Tools.Add(532options.Tools.Add(

532 ResponseTool.CreateImageGenerationTool(533 ResponseTool.CreateImageGenerationTool(

533 model: "gpt-image-2",534 model: "gpt-image-2.5-sunburst",

534 action: ImageGenerationToolAction.Generate535 action: ImageGenerationToolAction.Generate

535 )536 )

536);537);


551response = client.responses.create(552response = client.responses.create(

552 model: "gpt-6-astra",553 model: "gpt-6-astra",

553 input: "Generate an image of a gray tabby cat hugging an otter with an orange scarf.",554 input: "Generate an image of a gray tabby cat hugging an otter with an orange scarf.",

554 tools: [{type: :image_generation, action: :generate}]555 tools: [{type: :image_generation, model: "gpt-image-2.5-sunburst", action: :generate}]

555)556)

556 557 

557image_call = response.output.find do |item|558image_call = response.output.find do |item|


584 model: "gpt-6-astra",585 model: "gpt-6-astra",

585 input:586 input:

586 "Generate an image of gray tabby cat hugging an otter with an orange scarf",587 "Generate an image of gray tabby cat hugging an otter with an orange scarf",

587 tools: [{ type: "image_generation" }],588 tools: [{ type: "image_generation", model: "gpt-image-2.5-sunburst" }],

588});589});

589 590 

590const imageData = response.output591const imageData = response.output


603 model: "gpt-6-astra",604 model: "gpt-6-astra",

604 previous_response_id: response.id,605 previous_response_id: response.id,

605 input: "Now make it look realistic",606 input: "Now make it look realistic",

606 tools: [{ type: "image_generation" }],607 tools: [{ type: "image_generation", model: "gpt-image-2.5-sunburst" }],

607});608});

608 609 

609const imageData_fwup = response_fwup.output610const imageData_fwup = response_fwup.output


629response = client.responses.create(630response = client.responses.create(

630 model="gpt-6-astra",631 model="gpt-6-astra",

631 input="Generate an image of gray tabby cat hugging an otter with an orange scarf",632 input="Generate an image of gray tabby cat hugging an otter with an orange scarf",

632 tools=[{"type": "image_generation"}],633 tools=[{"type": "image_generation", "model": "gpt-image-2.5-sunburst"}],

633)634)

634 635 

635image_data = [636image_data = [


651 model="gpt-6-astra",652 model="gpt-6-astra",

652 previous_response_id=response.id,653 previous_response_id=response.id,

653 input="Now make it look realistic",654 input="Now make it look realistic",

654 tools=[{"type": "image_generation"}],655 tools=[{"type": "image_generation", "model": "gpt-image-2.5-sunburst"}],

655)656)

656 657 

657image_data_fwup = [658image_data_fwup = [


685 Input: responses.ResponseNewParamsInputUnion{686 Input: responses.ResponseNewParamsInputUnion{

686 OfString: openai.String("Generate an image of gray tabby cat hugging an otter with an orange scarf"),687 OfString: openai.String("Generate an image of gray tabby cat hugging an otter with an orange scarf"),

687 },688 },

688 Tools: []responses.ToolUnionParam{{OfImageGeneration: &responses.ToolImageGenerationParam{}}},689 Tools: []responses.ToolUnionParam{{OfImageGeneration: &responses.ToolImageGenerationParam{Model: "gpt-image-2.5-sunburst"}}},

689 })690 })

690 if err != nil {691 if err != nil {

691 panic(err)692 panic(err)


698 Input: responses.ResponseNewParamsInputUnion{699 Input: responses.ResponseNewParamsInputUnion{

699 OfString: openai.String("Now make it look realistic"),700 OfString: openai.String("Now make it look realistic"),

700 },701 },

701 Tools: []responses.ToolUnionParam{{OfImageGeneration: &responses.ToolImageGenerationParam{}}},702 Tools: []responses.ToolUnionParam{{OfImageGeneration: &responses.ToolImageGenerationParam{Model: "gpt-image-2.5-sunburst"}}},

702 })703 })

703 if err != nil {704 if err != nil {

704 panic(err)705 panic(err)


789ResponsesClient client = new(key);790ResponsesClient client = new(key);

790 791 

791CreateResponseOptions options = new() { Model = "gpt-6-astra" };792CreateResponseOptions options = new() { Model = "gpt-6-astra" };

792options.Tools.Add(ResponseTool.CreateImageGenerationTool(model: "gpt-image-2"));793options.Tools.Add(ResponseTool.CreateImageGenerationTool(model: "gpt-image-2.5-sunburst"));

793options.InputItems.Add(794options.InputItems.Add(

794 ResponseItem.CreateUserMessageItem(795 ResponseItem.CreateUserMessageItem(

795 "Generate an image of a gray tabby cat hugging an otter with an orange scarf."796 "Generate an image of a gray tabby cat hugging an otter with an orange scarf."


807 Model = "gpt-6-astra",808 Model = "gpt-6-astra",

808 PreviousResponseId = first.Id,809 PreviousResponseId = first.Id,

809};810};

810followUp.Tools.Add(ResponseTool.CreateImageGenerationTool(model: "gpt-image-2"));811followUp.Tools.Add(ResponseTool.CreateImageGenerationTool(model: "gpt-image-2.5-sunburst"));

811followUp.InputItems.Add(ResponseItem.CreateUserMessageItem("Now make it look realistic."));812followUp.InputItems.Add(ResponseItem.CreateUserMessageItem("Now make it look realistic."));

812 813 

813ResponseResult second = await client.CreateResponseAsync(followUp);814ResponseResult second = await client.CreateResponseAsync(followUp);


828first = client.responses.create(829first = client.responses.create(

829 model: "gpt-6-astra",830 model: "gpt-6-astra",

830 input: "Generate an image of a gray tabby cat hugging an otter with an orange scarf.",831 input: "Generate an image of a gray tabby cat hugging an otter with an orange scarf.",

831 tools: [{type: :image_generation}]832 tools: [{type: :image_generation, model: "gpt-image-2.5-sunburst"}]

832)833)

833 834 

834first_image = first.output.find do |item|835first_image = first.output.find do |item|


845 model: "gpt-6-astra",846 model: "gpt-6-astra",

846 input: "Now make it look realistic.",847 input: "Now make it look realistic.",

847 previous_response_id: first.id,848 previous_response_id: first.id,

848 tools: [{type: :image_generation}]849 tools: [{type: :image_generation, model: "gpt-image-2.5-sunburst"}]

849)850)

850 851 

851follow_up_image = follow_up.output.find do |item|852follow_up_image = follow_up.output.find do |item|


876 model: "gpt-6-astra",877 model: "gpt-6-astra",

877 input:878 input:

878 "Generate an image of gray tabby cat hugging an otter with an orange scarf",879 "Generate an image of gray tabby cat hugging an otter with an orange scarf",

879 tools: [{ type: "image_generation" }],880 tools: [{ type: "image_generation", model: "gpt-image-2.5-sunburst" }],

880});881});

881 882 

882const imageGenerationCalls = response.output.filter(883const imageGenerationCalls = response.output.filter(


905 id: imageGenerationCalls[0].id,906 id: imageGenerationCalls[0].id,

906 },907 },

907 ],908 ],

908 tools: [{ type: "image_generation" }],909 tools: [{ type: "image_generation", model: "gpt-image-2.5-sunburst" }],

909});910});

910 911 

911const imageData_fwup = response_fwup.output912const imageData_fwup = response_fwup.output


929response = openai.responses.create(930response = openai.responses.create(

930 model="gpt-6-astra",931 model="gpt-6-astra",

931 input="Generate an image of gray tabby cat hugging an otter with an orange scarf",932 input="Generate an image of gray tabby cat hugging an otter with an orange scarf",

932 tools=[{"type": "image_generation"}],933 tools=[{"type": "image_generation", "model": "gpt-image-2.5-sunburst"}],

933)934)

934 935 

935image_generation_calls = [936image_generation_calls = [


959 "id": image_generation_calls[0].id,960 "id": image_generation_calls[0].id,

960 },961 },

961 ],962 ],

962 tools=[{"type": "image_generation"}],963 tools=[{"type": "image_generation", "model": "gpt-image-2.5-sunburst"}],

963)964)

964 965 

965image_data_fwup = [966image_data_fwup = [


994 Input: responses.ResponseNewParamsInputUnion{995 Input: responses.ResponseNewParamsInputUnion{

995 OfString: openai.String("Generate an image of gray tabby cat hugging an otter with an orange scarf"),996 OfString: openai.String("Generate an image of gray tabby cat hugging an otter with an orange scarf"),

996 },997 },

997 Tools: []responses.ToolUnionParam{{OfImageGeneration: &responses.ToolImageGenerationParam{}}},998 Tools: []responses.ToolUnionParam{{OfImageGeneration: &responses.ToolImageGenerationParam{Model: "gpt-image-2.5-sunburst"}}},

998 })999 })

999 if err != nil {1000 if err != nil {

1000 panic(err)1001 panic(err)


1010 followUp, err := client.Responses.New(context.Background(), responses.ResponseNewParams{1011 followUp, err := client.Responses.New(context.Background(), responses.ResponseNewParams{

1011 Model: "gpt-6-astra",1012 Model: "gpt-6-astra",

1012 Input: responses.ResponseNewParamsInputUnion{OfInputItemList: input},1013 Input: responses.ResponseNewParamsInputUnion{OfInputItemList: input},

1013 Tools: []responses.ToolUnionParam{{OfImageGeneration: &responses.ToolImageGenerationParam{}}},1014 Tools: []responses.ToolUnionParam{{OfImageGeneration: &responses.ToolImageGenerationParam{Model: "gpt-image-2.5-sunburst"}}},

1014 })1015 })

1015 if err != nil {1016 if err != nil {

1016 panic(err)1017 panic(err)


1127ResponsesClient client = new(key);1128ResponsesClient client = new(key);

1128 1129 

1129CreateResponseOptions options = new() { Model = "gpt-6-astra" };1130CreateResponseOptions options = new() { Model = "gpt-6-astra" };

1130options.Tools.Add(ResponseTool.CreateImageGenerationTool(model: "gpt-image-2"));1131options.Tools.Add(ResponseTool.CreateImageGenerationTool(model: "gpt-image-2.5-sunburst"));

1131options.InputItems.Add(1132options.InputItems.Add(

1132 ResponseItem.CreateUserMessageItem(1133 ResponseItem.CreateUserMessageItem(

1133 "Generate an image of a gray tabby cat hugging an otter with an orange scarf."1134 "Generate an image of a gray tabby cat hugging an otter with an orange scarf."


1141await File.WriteAllBytesAsync("cat_and_otter.png", initialImage.ImageResultBytes.ToArray());1142await File.WriteAllBytesAsync("cat_and_otter.png", initialImage.ImageResultBytes.ToArray());

1142 1143 

1143CreateResponseOptions followUp = new() { Model = "gpt-6-astra" };1144CreateResponseOptions followUp = new() { Model = "gpt-6-astra" };

1144followUp.Tools.Add(ResponseTool.CreateImageGenerationTool(model: "gpt-image-2"));1145followUp.Tools.Add(ResponseTool.CreateImageGenerationTool(model: "gpt-image-2.5-sunburst"));

1145followUp.InputItems.Add(ResponseItem.CreateUserMessageItem("Now make it look realistic."));1146followUp.InputItems.Add(ResponseItem.CreateUserMessageItem("Now make it look realistic."));

1146followUp.InputItems.Add(ResponseItem.CreateReferenceItem(initialImage.Id));1147followUp.InputItems.Add(ResponseItem.CreateReferenceItem(initialImage.Id));

1147 1148 


1163first = client.responses.create(1164first = client.responses.create(

1164 model: "gpt-6-astra",1165 model: "gpt-6-astra",

1165 input: "Generate an image of a gray tabby cat hugging an otter with an orange scarf.",1166 input: "Generate an image of a gray tabby cat hugging an otter with an orange scarf.",

1166 tools: [{type: :image_generation}]1167 tools: [{type: :image_generation, model: "gpt-image-2.5-sunburst"}]

1167)1168)

1168 1169 

1169first_image = first.output.find do |item|1170first_image = first.output.find do |item|


1185 },1186 },

1186 {type: :image_generation_call, id: first_image.id}1187 {type: :image_generation_call, id: first_image.id}

1187 ],1188 ],

1188 tools: [{type: :image_generation}]1189 tools: [{type: :image_generation, model: "gpt-image-2.5-sunburst"}]

1189)1190)

1190 1191 

1191follow_up_image = follow_up.output.find do |item|1192follow_up_image = follow_up.output.find do |item|


1219 paddingBottom: "16px",1220 paddingBottom: "16px",

1220 }}1221 }}

1221 >1222 >

1222 <img src="https://cdn.openai.com/API/docs/images/cat_and_otter.png"1223 <img src="https://developers.openai.com/images/image-25-article/cat_and_otter.png"

1223 alt="A cat and an otter"1224 alt="A cat and an otter"

1224 style={{ width: "200px", borderRadius: "8px" }}1225 style={{ width: "200px", borderRadius: "8px" }}

1225 />1226 />


1230 "Now make it look realistic"1231 "Now make it look realistic"

1231 </td>1232 </td>

1232 <td style={{ textAlign: "right", verticalAlign: "top" }}>1233 <td style={{ textAlign: "right", verticalAlign: "top" }}>

1233 <img src="https://cdn.openai.com/API/docs/images/cat_and_otter_realistic.png"1234 <img src="https://developers.openai.com/images/image-25-article/cat_and_otter_realistic.png"

1234 alt="A cat and an otter"1235 alt="A cat and an otter"

1235 style={{ width: "200px", borderRadius: "8px" }}1236 style={{ width: "200px", borderRadius: "8px" }}

1236 />1237 />


1271 input:1272 input:

1272 "Draw a gorgeous image of a river made of white owl feathers, snaking its way through a serene winter landscape",1273 "Draw a gorgeous image of a river made of white owl feathers, snaking its way through a serene winter landscape",

1273 stream: true,1274 stream: true,

1274 tools: [{ type: "image_generation", partial_images: 2 }],1275 tools: [

1276 { type: "image_generation", model: "gpt-image-2.5-sunburst", partial_images: 2 },

1277 ],

1275});1278});

1276 1279 

1277for await (const event of stream) {1280for await (const event of stream) {


1307 model="gpt-6-astra",1310 model="gpt-6-astra",

1308 input="Draw a gorgeous image of a river made of white owl feathers, snaking its way through a serene winter landscape",1311 input="Draw a gorgeous image of a river made of white owl feathers, snaking its way through a serene winter landscape",

1309 stream=True,1312 stream=True,

1310 tools=[{"type": "image_generation", "partial_images": 2}],1313 tools=[

1314 {"type": "image_generation", "model": "gpt-image-2.5-sunburst", "partial_images": 2}

1315 ],

1311)1316)

1312 1317 

1313for event in stream:1318for event in stream:


1345 Input: responses.ResponseNewParamsInputUnion{1350 Input: responses.ResponseNewParamsInputUnion{

1346 OfString: openai.String("Draw a gorgeous image of a river made of white owl feathers, snaking its way through a serene winter landscape"),1351 OfString: openai.String("Draw a gorgeous image of a river made of white owl feathers, snaking its way through a serene winter landscape"),

1347 },1352 },

1348 Tools: []responses.ToolUnionParam{{OfImageGeneration: &responses.ToolImageGenerationParam{PartialImages: openai.Int(2)}}},1353 Tools: []responses.ToolUnionParam{{OfImageGeneration: &responses.ToolImageGenerationParam{Model: "gpt-image-2.5-sunburst", PartialImages: openai.Int(2)}}},

1349 })1354 })

1350 for stream.Next() {1355 for stream.Next() {

1351 event := stream.Current()1356 event := stream.Current()


1433stream = client.responses.stream(1438stream = client.responses.stream(

1434 model: "gpt-6-astra",1439 model: "gpt-6-astra",

1435 input: "Generate an image of a river made of white owl feathers.",1440 input: "Generate an image of a river made of white owl feathers.",

1436 tools: [{type: :image_generation, partial_images: 2}]1441 tools: [{type: :image_generation, model: "gpt-image-2.5-sunburst", partial_images: 2}]

1437)1442)

1438 1443 

1439stream.each do |event|1444stream.each do |event|


1474 "Draw a gorgeous image of a river made of white owl feathers, snaking its way through a serene winter landscape";1479 "Draw a gorgeous image of a river made of white owl feathers, snaking its way through a serene winter landscape";

1475const stream = await openai.images.generate({1480const stream = await openai.images.generate({

1476 prompt: prompt,1481 prompt: prompt,

1477 model: "gpt-image-2",1482 model: "gpt-image-2.5-sunburst",

1478 stream: true,1483 stream: true,

1479 partial_images: 2,1484 partial_images: 2,

1480});1485});


1497 1502 

1498stream = client.images.generate(1503stream = client.images.generate(

1499 prompt="Draw a gorgeous image of a river made of white owl feathers, snaking its way through a serene winter landscape",1504 prompt="Draw a gorgeous image of a river made of white owl feathers, snaking its way through a serene winter landscape",

1500 model="gpt-image-2",1505 model="gpt-image-2.5-sunburst",

1501 stream=True,1506 stream=True,

1502 partial_images=2,1507 partial_images=2,

1503)1508)


1526func main() {1531func main() {

1527 client := openai.NewClient()1532 client := openai.NewClient()

1528 stream := client.Images.GenerateStreaming(context.Background(), openai.ImageGenerateParams{1533 stream := client.Images.GenerateStreaming(context.Background(), openai.ImageGenerateParams{

1529 Model: openai.ImageModel("gpt-image-2"),1534 Model: openai.ImageModel("gpt-image-2.5-sunburst"),

1530 Prompt: "Draw a gorgeous image of a river made of white owl feathers, snaking its way through a serene winter landscape",1535 Prompt: "Draw a gorgeous image of a river made of white owl feathers, snaking its way through a serene winter landscape",

1531 PartialImages: openai.Int(2),1536 PartialImages: openai.Int(2),

1532 })1537 })


1560 1565 

1561client = OpenAI::Client.new1566client = OpenAI::Client.new

1562stream = client.images.generate_stream_raw(1567stream = client.images.generate_stream_raw(

1563 model: "gpt-image-2",1568 model: "gpt-image-2.5-sunburst",

1564 prompt: "A river made of white owl feathers in a winter landscape",1569 prompt: "A river made of white owl feathers in a winter landscape",

1565 partial_images: 21570 partial_images: 2

1566)1571)


1581 1586 

1582 1587 

1583| Partial 1 | Partial 2 | Final image |1588| Partial 1 | Partial 2 | Final image |

1584| ------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |1589| ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |

1585| <img className="images-example-image" src="https://cdn.openai.com/API/docs/images/imgen1p5-streaming1.png" alt="1st partial" /> | <img className="images-example-image" src="https://cdn.openai.com/API/docs/images/imgen1p5-streaming2.png" alt="2nd partial" /> | <img className="images-example-image" src="https://cdn.openai.com/API/docs/images/imgen1p5-streaming3.png" alt="3rd partial" /> |1590| <img className="images-example-image" src="https://developers.openai.com/images/image-25-article/river-partial-0.png" alt="1st partial" /> | <img className="images-example-image" src="https://developers.openai.com/images/image-25-article/river-partial-1.png" alt="2nd partial" /> | <img className="images-example-image" src="https://developers.openai.com/images/image-25-article/river-final.png" alt="Final image" /> |

1586 1591 

1587 1592 

1588 1593 


1842 ],1847 ],

1843 },1848 },

1844 ],1849 ],

1845 tools: [{ type: "image_generation" }],1850 tools: [{ type: "image_generation", model: "gpt-image-2.5-sunburst" }],

1846});1851});

1847 1852 

1848const imageData = response.output1853const imageData = response.output


1910 ],1915 ],

1911 }1916 }

1912 ],1917 ],

1913 tools=[{"type": "image_generation"}],1918 tools=[{"type": "image_generation", "model": "gpt-image-2.5-sunburst"}],

1914)1919)

1915 1920 

1916image_generation_calls = [1921image_generation_calls = [


1958 responses.EasyInputMessageRoleUser,1963 responses.EasyInputMessageRoleUser,

1959 ),1964 ),

1960 }},1965 }},

1961 Tools: []responses.ToolUnionParam{{OfImageGeneration: &responses.ToolImageGenerationParam{}}},1966 Tools: []responses.ToolUnionParam{{OfImageGeneration: &responses.ToolImageGenerationParam{Model: "gpt-image-2.5-sunburst"}}},

1962 })1967 })

1963 if err != nil {1968 if err != nil {

1964 panic(err)1969 panic(err)


2120 end2125 end

2121 ]2126 ]

2122 }],2127 }],

2123 tools: [{type: :image_generation}]2128 tools: [{type: :image_generation, model: "gpt-image-2.5-sunburst"}]

2124)2129)

2125 2130 

2126image_call = response.output.find do |item|2131image_call = response.output.find do |item|


2172);2177);

2173 2178 

2174const response = await client.images.edit({2179const response = await client.images.edit({

2175 model: "gpt-image-2",2180 model: "gpt-image-2.5-sunburst",

2176 image: images,2181 image: images,

2177 prompt,2182 prompt,

2178});2183});


2196"""2201"""

2197 2202 

2198result = client.images.edit(2203result = client.images.edit(

2199 model="gpt-image-2",2204 model="gpt-image-2.5-sunburst",

2200 image=[2205 image=[

2201 open("body-lotion.png", "rb"),2206 open("body-lotion.png", "rb"),

2202 open("bath-bomb.png", "rb"),2207 open("bath-bomb.png", "rb"),


2237 defer closeFiles()2242 defer closeFiles()

2238 2243 

2239 response, err := client.Images.Edit(context.Background(), openai.ImageEditParams{2244 response, err := client.Images.Edit(context.Background(), openai.ImageEditParams{

2240 Model: openai.ImageModel("gpt-image-2"),2245 Model: openai.ImageModel("gpt-image-2.5-sunburst"),

2241 Image: openai.ImageEditParamsImageUnion{OfFileArray: files},2246 Image: openai.ImageEditParamsImageUnion{OfFileArray: files},

2242 Prompt: "Generate a photorealistic image of a gift basket on a white background " +2247 Prompt: "Generate a photorealistic image of a gift basket on a white background " +

2243 "labeled 'Relax & Unwind' with a ribbon and handwriting-like font, containing all the items in the reference pictures.",2248 "labeled 'Relax & Unwind' with a ribbon and handwriting-like font, containing all the items in the reference pictures.",


2307 .images()2312 .images()

2308 .edit(2313 .edit(

2309 ImageEditParams.builder()2314 ImageEditParams.builder()

2310 .model("gpt-image-2")2315 .model("gpt-image-2.5-sunburst")

2311 .image(2316 .image(

2312 MultipartField.<ImageEditParams.Image>builder()2317 MultipartField.<ImageEditParams.Image>builder()

2313 .value(2318 .value(


2341end2346end

2342result = client.images.edit(2347result = client.images.edit(

2343 image: images,2348 image: images,

2344 model: "gpt-image-2",2349 model: "gpt-image-2.5-sunburst",

2345 prompt: <<~PROMPT2350 prompt: <<~PROMPT

2346 Generate a photorealistic image of a gift basket on a white background2351 Generate a photorealistic image of a gift basket on a white background

2347 labeled 'Relax & Unwind' with a ribbon and handwriting-like font,2352 labeled 'Relax & Unwind' with a ribbon and handwriting-like font,


2357 -o >(jq -r '.data[0].b64_json' | base64 --decode > gift-basket.png) \2362 -o >(jq -r '.data[0].b64_json' | base64 --decode > gift-basket.png) \

2358 -X POST "https://api.openai.com/v1/images/edits" \2363 -X POST "https://api.openai.com/v1/images/edits" \

2359 -H "Authorization: Bearer $OPENAI_API_KEY" \2364 -H "Authorization: Bearer $OPENAI_API_KEY" \

2360 -F "model=gpt-image-2" \2365 -F "model=gpt-image-2.5-sunburst" \

2361 -F "image[]=@body-lotion.png" \2366 -F "image[]=@body-lotion.png" \

2362 -F "image[]=@bath-bomb.png" \2367 -F "image[]=@bath-bomb.png" \

2363 -F "image[]=@incense-kit.png" \2368 -F "image[]=@incense-kit.png" \


2367 2372 

2368```bash2373```bash

2369openai images edit \2374openai images edit \

2370 --model gpt-image-2 \2375 --model gpt-image-2.5-sunburst \

2371 --image body-lotion.png \2376 --image body-lotion.png \

2372 --image bath-bomb.png \2377 --image bath-bomb.png \

2373 --image incense-kit.png \2378 --image incense-kit.png \


2434 tools: [2439 tools: [

2435 {2440 {

2436 type: "image_generation",2441 type: "image_generation",

2442 model: "gpt-image-2.5-sunburst",

2437 quality: "high",2443 quality: "high",

2438 input_image_mask: {2444 input_image_mask: {

2439 file_id: maskId,2445 file_id: maskId,


2488 tools=[2494 tools=[

2489 {2495 {

2490 "type": "image_generation",2496 "type": "image_generation",

2497 "model": "gpt-image-2.5-sunburst",

2491 "quality": "high",2498 "quality": "high",

2492 "input_image_mask": {2499 "input_image_mask": {

2493 "file_id": maskId,2500 "file_id": maskId,


2536 ),2543 ),

2537 }},2544 }},

2538 Tools: []responses.ToolUnionParam{{OfImageGeneration: &responses.ToolImageGenerationParam{2545 Tools: []responses.ToolUnionParam{{OfImageGeneration: &responses.ToolImageGenerationParam{

2546 Model: "gpt-image-2.5-sunburst",

2539 Quality: "high",2547 Quality: "high",

2540 InputImageMask: responses.ToolImageGenerationInputImageMaskParam{FileID: openai.String(maskID)},2548 InputImageMask: responses.ToolImageGenerationInputImageMaskParam{FileID: openai.String(maskID)},

2541 }}},2549 }}},


2664 ]2672 ]

2665 }],2673 }],

2666 tools: [{2674 tools: [{

2667 type: :image_generation,2675 type: :image_generation, model: "gpt-image-2.5-sunburst",

2668 input_image_mask: {file_id: mask.id}2676 input_image_mask: {file_id: mask.id}

2669 }]2677 }]

2670)2678)


2695const client = new OpenAI();2703const client = new OpenAI();

2696 2704 

2697const rsp = await client.images.edit({2705const rsp = await client.images.edit({

2698 model: "gpt-image-2",2706 model: "gpt-image-2.5-sunburst",

2699 image: await toFile(fs.createReadStream("fixtures/sunlit_lounge.png"), null, {2707 image: await toFile(fs.createReadStream("fixtures/sunlit_lounge.png"), null, {

2700 type: "image/png",2708 type: "image/png",

2701 }),2709 }),


2718client = OpenAI()2726client = OpenAI()

2719 2727 

2720result = client.images.edit(2728result = client.images.edit(

2721 model="gpt-image-2",2729 model="gpt-image-2.5-sunburst",

2722 image=open("sunlit_lounge.png", "rb"),2730 image=open("sunlit_lounge.png", "rb"),

2723 mask=open("mask.png", "rb"),2731 mask=open("mask.png", "rb"),

2724 prompt="A sunlit indoor lounge area with a pool containing a flamingo",2732 prompt="A sunlit indoor lounge area with a pool containing a flamingo",


2757 defer mask.Close()2765 defer mask.Close()

2758 2766 

2759 response, err := client.Images.Edit(context.Background(), openai.ImageEditParams{2767 response, err := client.Images.Edit(context.Background(), openai.ImageEditParams{

2760 Model: openai.ImageModel("gpt-image-2"),2768 Model: openai.ImageModel("gpt-image-2.5-sunburst"),

2761 Image: openai.ImageEditParamsImageUnion{OfFile: openai.File(image, "sunlit_lounge.png", "image/png")},2769 Image: openai.ImageEditParamsImageUnion{OfFile: openai.File(image, "sunlit_lounge.png", "image/png")},

2762 Mask: openai.File(mask, "mask.png", "image/png"),2770 Mask: openai.File(mask, "mask.png", "image/png"),

2763 Prompt: "A sunlit indoor lounge area with a pool containing a flamingo",2771 Prompt: "A sunlit indoor lounge area with a pool containing a flamingo",


2795 .images()2803 .images()

2796 .edit(2804 .edit(

2797 ImageEditParams.builder()2805 ImageEditParams.builder()

2798 .model("gpt-image-2")2806 .model("gpt-image-2.5-sunburst")

2799 .image(2807 .image(

2800 MultipartField.<ImageEditParams.Image>builder()2808 MultipartField.<ImageEditParams.Image>builder()

2801 .value(ImageEditParams.Image.ofInputStream(image))2809 .value(ImageEditParams.Image.ofInputStream(image))


2828result = client.images.edit(2836result = client.images.edit(

2829 image: image,2837 image: image,

2830 mask: mask,2838 mask: mask,

2831 model: "gpt-image-2",2839 model: "gpt-image-2.5-sunburst",

2832 prompt: "A sunlit indoor lounge area with a pool containing a flamingo"2840 prompt: "A sunlit indoor lounge area with a pool containing a flamingo"

2833)2841)

2834generated_image = result.data&.first or raise "No image returned"2842generated_image = result.data&.first or raise "No image returned"


2840 -o >(jq -r '.data[0].b64_json' | base64 --decode > lounge.png) \2848 -o >(jq -r '.data[0].b64_json' | base64 --decode > lounge.png) \

2841 -X POST "https://api.openai.com/v1/images/edits" \2849 -X POST "https://api.openai.com/v1/images/edits" \

2842 -H "Authorization: Bearer $OPENAI_API_KEY" \2850 -H "Authorization: Bearer $OPENAI_API_KEY" \

2843 -F "model=gpt-image-2" \2851 -F "model=gpt-image-2.5-sunburst" \

2844 -F "mask=@mask.png" \2852 -F "mask=@mask.png" \

2845 -F "image[]=@sunlit_lounge.png" \2853 -F "image[]=@sunlit_lounge.png" \

2846 -F 'prompt=A sunlit indoor lounge area with a pool containing a flamingo'2854 -F 'prompt=A sunlit indoor lounge area with a pool containing a flamingo'


2848 2856 

2849```bash2857```bash

2850openai images edit \2858openai images edit \

2851 --model gpt-image-2 \2859 --model gpt-image-2.5-sunburst \

2852 --image sunlit_lounge.png \2860 --image sunlit_lounge.png \

2853 --mask mask.png \2861 --mask mask.png \

2854 --prompt "A sunlit indoor lounge area with a pool containing a flamingo" \2862 --prompt "A sunlit indoor lounge area with a pool containing a flamingo" \


2862 2870 

2863 2871 

2864| Image | Mask | Output |2872| Image | Mask | Output |

2865| ------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |2873| ------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

2866| <img className="images-example-image" src="https://cdn.openai.com/API/docs/images/sunlit_lounge.png" alt="A pink room with a pool" /> | <img className="images-example-image" src="https://cdn.openai.com/API/docs/images/mask.png" alt="A mask in part of the pool" /> | <img className="images-example-image" src="https://cdn.openai.com/API/docs/images/sunlit_lounge_result.png" alt="The original pool with an inflatable flamingo replacing the mask" /> |2874| <img className="images-example-image" src="https://cdn.openai.com/API/docs/images/sunlit_lounge.png" alt="A pink room with a pool" /> | <img className="images-example-image" src="https://cdn.openai.com/API/docs/images/mask.png" alt="A mask in part of the pool" /> | <img className="images-example-image" src="https://developers.openai.com/images/image-25-article/sunlit_lounge_result.png" alt="The original pool with an inflatable flamingo replacing the mask" /> |

2867 2875 

2868 2876 

2869 2877 


2952```2960```

2953 2961 

2954 2962 

2955### Image input fidelity

2956 

2957The `input_fidelity` parameter controls how strongly a model preserves details from input images during edits and reference-image workflows. For `gpt-image-2`, omit this parameter; the API doesn't allow changing it because the model processes every image input at high fidelity automatically.

2958 

2959Because `gpt-image-2` always processes image inputs at high fidelity, image

2960 input tokens can be higher for edit requests that include reference images. To

2961 understand the cost implications, refer to the [vision

2962 costs](https://developers.openai.com/api/docs/guides/images-vision?api-mode=responses#calculating-costs)

2963 section.

2964 

2965## Customize Image Output2963## Customize Image Output

2966 2964 

2967You can configure the following output options:2965You can configure the following output options:


2974 2972 

2975`size`, `quality`, and `background` support the `auto` option, where the model will automatically select the best option based on the prompt.2973`size`, `quality`, and `background` support the `auto` option, where the model will automatically select the best option based on the prompt.

2976 2974 

2977Transparent backgrounds are available in preview for `gpt-image-2`. Set

2978 `background: "transparent"` to request one. Use `png` (the default) or `webp`;

2979 `jpeg` isn't supported with transparent backgrounds.

2980 

2981### Size and quality options2975### Size and quality options

2982 2976 

2983`gpt-image-2` accepts any resolution in the `size` parameter when it satisfies the constraints below. Square images are typically fastest to generate.2977`gpt-image-2.5-sunburst` and `gpt-image-2.5-flare` add `xhigh` and `max` quality settings. Both default to `auto`. Earlier GPT Image models support quality settings up to `high`.

2984 2978 

2985<table>2979| Setting | Options |

2986 <tbody>2980| ----------------- | --------------------------------------------------------------------- |

2987 <tr>2981| Recommended sizes | `1024x1024` (square), `1536x1024` (landscape), `1024x1536` (portrait) |

2988 <td>Popular sizes</td>2982| Quality | `low`, `medium`, `high`, `xhigh`, `max`, `auto` |

2989 <td>2983 

2990 <ul>2984Both models also support custom dimensions as `WIDTHxHEIGHT` strings, such as `1536x864`. Width and height must be multiples of 16, the aspect ratio must be between 1:3 and 3:1, and neither edge may exceed 3840 pixels. The total pixel count must be between 655,360 and 8,294,400 (4K). Resolutions above `2560x1440` are experimental.

2991 <li>

2992 `1024x1024` (square)

2993 </li>

2994 <li>

2995 `1536x1024` (landscape)

2996 </li>

2997 <li>

2998 `1024x1536` (portrait)

2999 </li>

3000 <li>

3001 `2048x2048` (2K square)

3002 </li>

3003 <li>

3004 `2048x1152` (2K landscape)

3005 </li>

3006 <li>

3007 `3840x2160` (4K landscape)

3008 </li>

3009 <li>

3010 `2160x3840` (4K portrait)

3011 </li>

3012 <li>

3013 `auto` (default)

3014 </li>

3015 </ul>

3016 </td>

3017 </tr>

3018 <tr>

3019 <td>Size constraints</td>

3020 <td>

3021 <ul>

3022 <li>

3023 Maximum edge length must be less than or equal to

3024 `3840px`

3025 </li>

3026 <li>

3027 Both edges must be multiples of `16px`

3028 </li>

3029 <li>

3030 Long edge to short edge ratio must not exceed `3:1`

3031 </li>

3032 <li>

3033 Total pixels must be at least `655,360` and no more than

3034 `8,294,400`

3035 </li>

3036 </ul>

3037 </td>

3038 </tr>

3039 <tr>

3040 <td>Quality options</td>

3041 <td>

3042 <ul>

3043 <li>

3044 `low`

3045 </li>

3046 <li>

3047 `medium`

3048 </li>

3049 <li>

3050 `high`

3051 </li>

3052 <li>

3053 `auto` (default)

3054 </li>

3055 </ul>

3056 </td>

3057 </tr>

3058 </tbody>

3059</table>

3060 2985 

3061Use `quality: "low"` for fast drafts, thumbnails, and quick iterations. It is2986For transparent backgrounds with either model, set `background: "transparent"` and use `output_format: "png"` or `"webp"`.

3062 the fastest option and works well for many common use cases before you move to

3063 `medium` or `high` for final assets.

3064 2987 

3065Outputs that contain more than `2560x1440` (`3,686,400`) total pixels,2988Use `quality: "low"` for quick drafts. For final assets, compare higher quality settings to find the right balance of detail, latency, and cost.

3066 typically referred to as 2K, are considered experimental.

3067 2989 

3068### Output format2990### Output format

3069 2991 


3077 2999 

3078## Limitations3000## Limitations

3079 3001 

3080GPT Image models (`gpt-image-2`, `gpt-image-1.5`, `gpt-image-1`, and `gpt-image-1-mini`) are powerful and versatile image generation models, but they still have some limitations to be aware of:3002GPT Image models are powerful and versatile image generation models, but they still have some limitations to be aware of:

3081 3003 

3082- **Latency:** Complex prompts may take up to 2 minutes to process.3004- **Latency:** Complex prompts may take up to 2 minutes to process.

3083- **Text Rendering:** Although significantly improved, the model can still struggle with precise text placement and clarity.3005- **Text Rendering:** Although significantly improved, the model can still struggle with precise text placement and clarity.


3088 3010 

3089All prompts and generated images are filtered in accordance with our [content policy](https://openai.com/policies/usage-policies/).3011All prompts and generated images are filtered in accordance with our [content policy](https://openai.com/policies/usage-policies/).

3090 3012 

3091For image generation using GPT Image models (`gpt-image-2`, `gpt-image-1.5`, `gpt-image-1`, and `gpt-image-1-mini`), you can control moderation strictness with the `moderation` parameter. This parameter supports two values:3013For image generation using GPT Image models, you can control moderation strictness with the `moderation` parameter. This parameter supports two values:

3092 3014 

3093- `auto` (default): Standard filtering that seeks to limit creating certain categories of potentially age-inappropriate content.3015- `auto` (default): Standard filtering that seeks to limit creating certain categories of potentially age-inappropriate content.

3094- `low`: Less restrictive filtering.3016- `low`: Less restrictive filtering.

3095 3017 

3096### Handling blocked requests and other errors3018### Handling blocked requests and other errors

3097 3019 

3098Handle image generation failures the same way you handle other API errors: check the HTTP status or SDK exception type, log the request ID, and refer to the [error codes guide](https://developers.openai.com/api/docs/guides/error-codes) for authentication, quota, rate-limit, and server failures. Retries are appropriate for transient failures like `429` and `5xx`, but not for image generation user errors that require changing the request.3020Handle image generation failures the same way you handle other API errors: check the HTTP status or SDK exception type, log the request ID, and refer to the [error codes guide](https://developers.openai.com/api/docs/guides/error-codes) for authentication, quota, rate-limit, and server failures. Retry transient rate-limit and server failures with backoff. Don't automatically retry quota errors or image generation user errors that require changing the request.

3099 3021 

3100Some image generation failures are user-correctable and may return `error.type = "image_generation_user_error"`. Don't automatically retry these errors without modifying the prompt or input images. For programmatic handling, use `error.code` as the stable discriminator.3022Some image generation failures are user-correctable and may return `error.type = "image_generation_user_error"`. Don't automatically retry these errors without modifying the prompt or input images. For programmatic handling, use `error.code` as the stable discriminator.

3101 3023 


3126 3048 

3127For most apps, keep the primary end-user message generic. Use `moderation_details` for developer logs, support workflows, analytics, and light remediation hints.3049For most apps, keep the primary end-user message generic. Use `moderation_details` for developer logs, support workflows, analytics, and light remediation hints.

3128 3050 

3129For example, if `harassment` appears, suggest removing abusive or targeting language. If the block happened at the `input` stage, guide the user to revise the prompt. If it happened at the `output` stage, treat it as a generated result safety block and distinguish it in your logs. Always branch on `error.code = "moderation_blocked"` first, and treat `moderation_details` as optional extra context.

3130 

3131Handle moderation-blocked image generation errors3051Handle moderation-blocked image generation errors

3132 3052 

3133```javascript3053```javascript


3139 // The same error handling pattern applies to image generation requests,3059 // The same error handling pattern applies to image generation requests,

3140 // image edits, and Responses API tool calls that generate images.3060 // image edits, and Responses API tool calls that generate images.

3141 await openai.images.generate({3061 await openai.images.generate({

3142 model: "gpt-image-2",3062 model: "gpt-image-2.5-sunburst",

3143 prompt: "Create a poster humiliating my coworker with insulting captions",3063 prompt: "Create a poster humiliating my coworker with insulting captions",

3144 });3064 });

3145} catch (error) {3065} catch (error) {


3185 # The same error handling pattern applies to image generation requests,3105 # The same error handling pattern applies to image generation requests,

3186 # image edits, and Responses API tool calls that generate images.3106 # image edits, and Responses API tool calls that generate images.

3187 client.images.generate(3107 client.images.generate(

3188 model="gpt-image-2",3108 model="gpt-image-2.5-sunburst",

3189 prompt="Create a poster humiliating my coworker with insulting captions",3109 prompt="Create a poster humiliating my coworker with insulting captions",

3190 )3110 )

3191except openai.BadRequestError as error:3111except openai.BadRequestError as error:


3234func main() {3154func main() {

3235 client := openai.NewClient()3155 client := openai.NewClient()

3236 _, err := client.Images.Generate(context.Background(), openai.ImageGenerateParams{3156 _, err := client.Images.Generate(context.Background(), openai.ImageGenerateParams{

3237 Model: openai.ImageModel("gpt-image-2"),3157 Model: openai.ImageModel("gpt-image-2.5-sunburst"),

3238 Prompt: "Create a poster humiliating my coworker with insulting captions",3158 Prompt: "Create a poster humiliating my coworker with insulting captions",

3239 })3159 })

3240 if err == nil {3160 if err == nil {


3283 .images()3203 .images()

3284 .generate(3204 .generate(

3285 ImageGenerateParams.builder()3205 ImageGenerateParams.builder()

3286 .model("gpt-image-2")3206 .model("gpt-image-2.5-sunburst")

3287 .prompt("Create a poster humiliating my coworker with insulting captions")3207 .prompt("Create a poster humiliating my coworker with insulting captions")

3288 .build());3208 .build());

3289 3209 


3316client = OpenAI::Client.new3236client = OpenAI::Client.new

3317begin3237begin

3318 client.images.generate(3238 client.images.generate(

3319 model: "gpt-image-2",3239 model: "gpt-image-2.5-sunburst",

3320 prompt: "Create a poster humiliating my coworker with insulting captions"3240 prompt: "Create a poster humiliating my coworker with insulting captions"

3321 )3241 )

3322rescue OpenAI::Errors::BadRequestError => error3242rescue OpenAI::Errors::BadRequestError => error


3347 3267 

3348## Cost and latency3268## Cost and latency

3349 3269 

3350### `gpt-image-2` output tokens3270### GPT Image 2.5 costs

3271 

3272Responses API requests include the mainline model's token usage in addition to image generation costs.

3273 

3274Both GPT Image 2.5 models use the same token rates: $8 per million image input tokens, $2 per million cached image input tokens, $30 per million image output tokens, $5 per million text input tokens, and $1.25 per million cached text input tokens. See [pricing](https://developers.openai.com/api/docs/pricing#image-generation).

3275 

3276Use the response's `usage` to measure token consumption for your prompts, sizes, and quality settings. Equal token rates don't mean equal cost per image: token consumption can differ by model and quality setting. For older-model pricing examples, see [Earlier GPT Image models](#earlier-gpt-image-models).

3277 

3278 

3351 3279 

3352For `gpt-image-2`, use the calculator to estimate output tokens from the requested `quality` and `size`:3280 

3281### GPT Image 2.5 and GPT Image 2 output tokens

3282 

3283Select a model, quality, and size to estimate output tokens and image output cost.

3284For `gpt-image-2.5-sunburst` and `gpt-image-2.5-flare`, the quality options are `low`, `medium`, `high`, `xhigh`, and `max`.

3285For `gpt-image-2`, the options are `low`, `medium`, and `high`.

3286The models can use different token counts for the same quality setting and share the same price per image output token.

3287Use explicit quality and size values for this estimate; `auto` depends on the generated image.

3288 

3289<GptImageTokenCalculator

3290 client:load

3291 outputPricePerMillion={Number(

3292 pricing.latest.subsections

3293 .find((section) => section.price_type === "Image tokens")

3294 ?.items.find((item) => item.name === "gpt-image-2")?.values.main.output

3295 )}

3296/>

3297 

3298### Partial images cost

3299 

3300If you want to [stream image generation](#streaming) using the `partial_images` parameter, each partial image will incur an additional 100 image output tokens.

3301 

3302## Earlier GPT Image models

3303 

3304The details below apply to earlier models, not Sunburst or Flare. For new integrations, use one of the GPT Image 2.5 models described above.

3305 

3306<details>

3307<summary>GPT Image 2 settings and input fidelity</summary>

3308 

3309`gpt-image-2` accepts any resolution in the `size` parameter when it satisfies the constraints below. Square images are typically fastest to generate.

3310 

3311<table>

3312 <tbody>

3313 <tr>

3314 <td>Popular sizes</td>

3315 <td>

3316 <ul>

3317 <li>

3318 `1024x1024` (square)

3319 </li>

3320 <li>

3321 `1536x1024` (landscape)

3322 </li>

3323 <li>

3324 `1024x1536` (portrait)

3325 </li>

3326 <li>

3327 `2048x2048` (2K square)

3328 </li>

3329 <li>

3330 `2048x1152` (2K landscape)

3331 </li>

3332 <li>

3333 `3840x2160` (4K landscape)

3334 </li>

3335 <li>

3336 `2160x3840` (4K portrait)

3337 </li>

3338 <li>

3339 `auto` (default)

3340 </li>

3341 </ul>

3342 </td>

3343 </tr>

3344 <tr>

3345 <td>Size constraints</td>

3346 <td>

3347 <ul>

3348 <li>

3349 Maximum edge length must be less than or equal to

3350 `3840px`

3351 </li>

3352 <li>

3353 Both edges must be multiples of `16px`

3354 </li>

3355 <li>

3356 Long edge to short edge ratio must not exceed `3:1`

3357 </li>

3358 <li>

3359 Total pixels must be at least `655,360` and no more than

3360 `8,294,400`

3361 </li>

3362 </ul>

3363 </td>

3364 </tr>

3365 <tr>

3366 <td>Quality options</td>

3367 <td>

3368 <ul>

3369 <li>

3370 `low`

3371 </li>

3372 <li>

3373 `medium`

3374 </li>

3375 <li>

3376 `high`

3377 </li>

3378 <li>

3379 `auto` (default)

3380 </li>

3381 </ul>

3382 </td>

3383 </tr>

3384 </tbody>

3385</table>

3386 

3387### Image input fidelity

3388 

3389The `input_fidelity` parameter controls how strongly a model preserves details from input images during edits and reference-image workflows. For `gpt-image-2`, omit this parameter; the API doesn't allow changing it because the model processes every image input at high fidelity automatically.

3390 

3391Because `gpt-image-2` always processes image inputs at high fidelity, image

3392 input tokens can be higher for edit requests that include reference images. To

3393 understand the cost implications, refer to the [vision

3394 costs](https://developers.openai.com/api/docs/guides/images-vision?api-mode=responses#calculating-costs)

3395 section.

3396 

3397</details>

3398 

3399<details>

3400<summary>Older-model pricing examples</summary>

3353 3401 

3354### Models prior to `gpt-image-2`3402### Models prior to `gpt-image-2`

3355 3403 


3499 </tbody>3547 </tbody>

3500</table>3548</table>

3501 3549 

3502### Partial images cost3550</details>

3503 

3504If you want to [stream image generation](#streaming) using the `partial_images` parameter, each partial image will incur an additional 100 image output tokens.

guides/image-prompting.md +1557 −0 created

Details

1# Image prompting

2 

3> For the complete documentation index, see [llms.txt](/llms.txt). Markdown versions of documentation pages are available by appending `.md` to the page URL.

4 

5<header className="not-prose mb-8">

6 <h2

7 id="gpt-image-2.5-guide"

8 className="m-0 text-3xl font-semibold text-default"

9 >

10 {"GPT Image 2.5 prompting guide"}

11 </h2>

12

13 

14 Choose a model, write effective prompts, and preserve details across

15 edits.

16

17 

18 </header>

19

20 

21## Overview

22 

23Start with the image you need, then describe the subject, composition, style, and constraints. For edits, identify what should change and what must stay the same. Refine one thing at a time and inspect the result.

24 

25GPT Image 2.5 includes two model choices. GPT Image 2.5 Flare is the small model, optimized for speed, with image quality comparable to GPT Image 2. GPT Image 2.5 Sunburst is the base model, optimized for quality, with higher image quality than GPT Image 2. Both models offer improvements in precise editing and subject preservation.

26 

27For API setup and request examples, see the [image generation guide](https://developers.openai.com/api/docs/guides/image-generation).

28 

29## Choose a model

30 

31For a new workflow, start with GPT Image 2.5 Flare when speed is the priority, or GPT Image 2.5 Sunburst when demanding quality requirements are the priority. Once the output meets your requirements, look for opportunities to reduce latency.

32 

33For migrating from a current image model, use your current image quality as the starting point. Both models support image generation, editing, and transparent backgrounds.

34 

35| Your current workflow | Start by testing |

36| ----------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |

37| An existing, validated GPT Image 2 workflow already meets your quality requirements | GPT Image 2.5 Flare. Check whether you can retain acceptable quality while reducing latency. |

38| A complex use case where GPT Image 2 does not meet your quality requirements | GPT Image 2.5 Sunburst. First establish that it delivers the quality you need. |

39 

40If GPT Image 2.5 Sunburst meets your quality requirements, then test GPT Image 2.5 Flare with the same prompts and inputs. Switch to GPT Image 2.5 Flare if it also meets those requirements and improves latency. Keep GPT Image 2.5 Sunburst when its quality advantage is necessary for your workflow.

41 

42Measure response time and quality on your own workload. Results depend on your prompts, reference images, output dimensions, and quality settings; a speed improvement on one workload doesn't establish a fixed improvement on another.

43 

44## Model parameters

45 

46Set API parameters separately from the prompt.

47 

48| Parameter | GPT Image 2.5 settings |

49| ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

50| `model` | `gpt-image-2.5-flare` (small model) or `gpt-image-2.5-sunburst` (base model) |

51| `quality` | `auto` (default), `low`, `medium`, `high`, `xhigh`, or `max` |

52| `size` | `auto` or a custom resolution. Common sizes: `1024x1024` (square), `1536x1024` (landscape), `1024x1536` (portrait), `2048x2048` (2K square), `2048x1152` (2K landscape), `3840x2160` (4K landscape), and `2160x3840` (4K portrait). |

53| `background` | `auto`, `opaque`, or `transparent` |

54 

55For a custom resolution, use `WIDTHxHEIGHT` and follow these constraints:

56 

57- Each edge must be no more than 3,840 pixels.

58- Both edges must be multiples of 16 pixels.

59- The ratio of the longer edge to the shorter edge must not exceed 3:1.

60- The total pixel count must be between 655,360 and 8,294,400.

61 

62Outputs with more than 3,686,400 total pixels (`2560x1440`) are experimental.

63 

64Choose the model using the workflow above before tuning `quality`. For the first comparison, keep an explicitly selected quality setting unchanged when both models support it, along with the prompt, reference images, and output dimensions. The same quality label does not imply the same image quality or response time across models.

65 

66If the output falls short, test a higher quality setting. Once it meets your requirements, test lower settings to see whether they preserve acceptable quality while reducing latency. Use `xhigh` or `max` only when they improve an unmet quality requirement within your latency budget. A higher setting doesn't guarantee a better result for every prompt.

67 

68For transparent assets, explicitly request `background="transparent"` and use PNG or WebP. Check the decoded image's alpha channel, including hair, glass, shadows, and object edges. Use `output_compression` only for JPEG or WebP output, not PNG.

69 

70## Migrate an existing workflow

71 

721. **Save a baseline.** Collect representative production prompts and reference images, including difficult edits, exact text, faces, product geometry, and transparent assets. Record the current model, request settings, and results.

732. **Choose the first candidate.** If GPT Image 2 already meets your quality requirements, start with GPT Image 2.5 Flare and test for a latency improvement. If GPT Image 2 falls short on a complex use case, start with GPT Image 2.5 Sunburst and first establish that it meets your quality requirements. Keep the prompt, references, dimensions, and output format unchanged for the first comparison.

743. **Check the complete result.** Compare instruction following, identity and product preservation, text accuracy, unwanted changes, and transparency. Repeat requests to measure consistency. For editing workflows, test the complete sequence of edits as well as individual steps.

754. **Test for a latency gain after quality passes.** If you started with GPT Image 2.5 Sunburst and it meets your quality requirements, evaluate GPT Image 2.5 Flare against the same requirements. Switch only if the quality remains acceptable and latency improves; otherwise, keep GPT Image 2.5 Sunburst.

765. **Tune one setting at a time.** Compare quality levels before rewriting the prompt. Measure typical and slow responses, failures, retries, and cost per accepted image. Confirm current pricing rather than assuming the faster model costs less.

776. **Roll out by workflow.** Once the released model passes your acceptance criteria, move a small share of traffic, monitor the same measures, and expand gradually. Keep the previous model available for rollback while it remains supported.

78 

79When migrating from GPT Image 1 or 1.5, use the reference tabs to check parameter differences and shutdown dates. Test the candidate model's supported request settings rather than copying older settings unchanged. For GPT Image 2, keep your existing resolution and transparency requirements in the comparison.

80 

81Repeated edits can still change details you intended to preserve. Restate those constraints and inspect each result. If a region must remain pixel-identical, composite the approved edit into the original image instead of relying on prompting alone.

82 

83## Prompting fundamentals

84 

851. **Define the result.** Name the subject and intended use, such as a product photograph, advertisement, or diagram. Specify the composition, aspect ratio, and important placement constraints. For complex requests, organize the prompt as scene, subject, details, and constraints, using labeled sections.

862. **Choose a maintainable format.** Short prompts, descriptive paragraphs, JSON-like structures, instructions, and tags can all express the same intent. Choose the format that makes the requirements easiest to read and update rather than relying on special syntax.

873. **Describe visible details.** Name materials, lighting, colors, and the visual medium. Request “photorealistic” or “real photograph” explicitly when that is the goal, and describe framing and texture. Treat camera specifications as cues for appearance, not a guarantee of exact physical simulation. For wide, cinematic, low-light, rainy, or neon scenes, specify scale, atmosphere, and color instead of relying on mood words alone.

884. **Specify people and actions.** Describe body framing, relative scale, gaze, and interaction with objects. Instructions such as “full body visible, feet included,” “looking down at the open book,” or “hands naturally gripping the handlebars” make the intended pose and action clearer.

895. **Specify exact text.** Put required wording in quotes and describe its position and typography. Spell unusual words or brand names letter by letter when needed. Ask for no extra text, then check spelling and legibility in the output. Compare medium or high quality for small text, dense information, or multiple fonts.

906. **Separate changes from constraints.** For edits, say “change only X” and list the details to preserve, such as identity, geometry, layout, lighting, or labels. State exclusions such as unwanted text, logos, or watermarks. For precise local edits, also identify saturation, contrast, arrows, camera angle, and surrounding objects that must remain unchanged.

917. **Assign roles to references.** Identify each input by number and purpose: subject, style, clothing, or background. Explain how the inputs should combine and which elements should move where.

928. **Iterate deliberately.** Pass the previous output as the next edit input, request one change, and repeat the details to preserve. References such as “same style as before” can carry context, but restate critical constraints if the result drifts. Compare results before adding more instructions.

93 

94The examples below each demonstrate a different technique. Keep their prompts as starting points and adapt them to your own images and requirements.

95 

96## Generate images

97 

98### Control style and lighting

99 

100Describe a photograph through its subject, framing, light, and texture. This example specifies a candid composition and explicitly excludes heavy retouching.

101 

102Generation settings: `size="1024x1536"`, `quality="medium"`.

103 

104```text

105Create a photorealistic candid photograph of an elderly sailor standing on a small fishing boat.

106He has weathered skin with visible wrinkles, pores, and sun texture, and a few faded traditional sailor tattoos on his arms.

107He is calmly adjusting a net while his dog sits nearby on the deck. Shot like a 35mm film photograph, medium close-up at eye level, using a 50mm lens.

108Soft coastal daylight, shallow depth of field, subtle film grain, natural color balance.

109The image should feel honest and unposed, with real skin texture, worn materials, and everyday detail. No glamorization, no heavy retouching.

110```

111 

112Example outputs:

113 

114 

115 

116 <figure className="m-0 min-w-0">

117 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

118 GPT Image 2.5 Flare

119 </figcaption>

120

121 

122![Photorealistic portrait of a sailor repairing a net — GPT Image 2.5 Flare](<https://developers.openai.com/images/platform/guides/image-prompting/photorealism-gpt-image-2-5-flare.webp>)

123 

124 

125 </figure>

126 <figure className="m-0 min-w-0">

127 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

128 GPT Image 2.5 Sunburst

129 </figcaption>

130

131 

132![Photorealistic portrait of a sailor repairing a net — GPT Image 2.5 Sunburst](<https://developers.openai.com/images/platform/guides/image-prompting/photorealism-gpt-image-2-5-sunburst.webp>)

133 

134 

135 </figure>

136 

137 

138 

139### Explain a process visually

140 

141Name the process, audience, and information the image should communicate. For diagrams and information graphics, verify labels and factual relationships as well as appearance.

142 

143Generation settings: `size="1024x1536"`, `quality="medium"`.

144 

145```text

146Create a detailed Infographic of the functioning and flow of an automatic coffee machine like a Jura.

147From bean basket, to grinding, to scale, water tank, boiler, etc.

148I'd like to understand technically and visually the flow.

149```

150 

151Example outputs:

152 

153 

154 

155 <figure className="m-0 min-w-0">

156 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

157 GPT Image 2.5 Flare

158 </figcaption>

159

160 

161![Diagram explaining an automatic coffee machine — GPT Image 2.5 Flare](<https://developers.openai.com/images/platform/guides/image-prompting/infographic-coffee-machine-gpt-image-2-5-flare.webp>)

162 

163 

164 </figure>

165 <figure className="m-0 min-w-0">

166 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

167 GPT Image 2.5 Sunburst

168 </figcaption>

169

170 

171![Diagram explaining an automatic coffee machine — GPT Image 2.5 Sunburst](<https://developers.openai.com/images/platform/guides/image-prompting/infographic-coffee-machine-gpt-image-2-5-sunburst.webp>)

172 

173 

174 </figure>

175 

176 

177 

178### Render exact text

179 

180Quote the required copy and tell the model how many times it should appear. Specify the audience and visual treatment without adding unrelated instructions.

181 

182Generation settings: `size="1024x1536"`, `quality="medium"`.

183 

184```text

185Give me a cool in culture ad / fashion shot for a brand called Thread.

186It's a hip young street brand. The ad shows a group of friends hanging out together with the tagline "Yours to Create."

187Make it feel like a polished campaign image for a youth streetwear audience: stylish, contemporary, energetic, and tasteful.

188Use clean composition, strong color direction, natural poses, and premium fashion photography cues.

189Render the tagline exactly once, clearly and legibly, integrated into the ad layout.

190No extra text, no watermarks, no unrelated logos.

191```

192 

193Example outputs:

194 

195 

196 

197 <figure className="m-0 min-w-0">

198 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

199 GPT Image 2.5 Flare

200 </figcaption>

201

202 

203![Thread streetwear campaign with the requested tagline — GPT Image 2.5 Flare](<https://developers.openai.com/images/platform/guides/image-prompting/thread-ad-gpt-image-2-5-flare.webp>)

204 

205 

206 </figure>

207 <figure className="m-0 min-w-0">

208 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

209 GPT Image 2.5 Sunburst

210 </figcaption>

211

212 

213![Thread streetwear campaign with the requested tagline — GPT Image 2.5 Sunburst](<https://developers.openai.com/images/platform/guides/image-prompting/thread-ad-gpt-image-2-5-sunburst.webp>)

214 

215 

216 </figure>

217 

218 

219 

220### Design a reusable logo

221 

222Describe the brand and the shapes that should define the mark. Specify a clear composition that remains legible at different sizes. Use `n` to request multiple variations.

223 

224Generation settings: `size="1024x1536"`, `quality="medium"`, `background="transparent"`, `output_format="png"`, `n=1`.

225 

226```text

227Create an original, non-infringing logo for a company called Field & Flour, a local bakery.

228The logo should feel warm, simple, and timeless. Use clean, vector-like shapes, a strong silhouette, and balanced negative space.

229Favor simplicity over detail so it reads clearly at small and large sizes. Flat design, minimal strokes, no gradients unless essential.

230Fully transparent background. Deliver a single centered logo with generous padding, clean alpha edges, and no solid backdrop, scenery, checkerboard, or watermark.

231```

232 

233Each row compares one variation from each model.

234 

235Example outputs:

236 

237 

238 

239 <figure className="m-0 min-w-0">

240 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

241 GPT Image 2.5 Flare

242 </figcaption>

243

244 

245![Field and Flour bakery logo, first variation — GPT Image 2.5 Flare](<https://developers.openai.com/images/platform/guides/image-prompting/logo-generation-1-gpt-image-2-5-flare.webp>)

246 

247 

248 </figure>

249 <figure className="m-0 min-w-0">

250 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

251 GPT Image 2.5 Sunburst

252 </figcaption>

253

254 

255![Field and Flour bakery logo, first variation — GPT Image 2.5 Sunburst](<https://developers.openai.com/images/platform/guides/image-prompting/logo-generation-1-gpt-image-2-5-sunburst.webp>)

256 

257 

258 </figure>

259 

260 

261 

262 

263 

264 <figure className="m-0 min-w-0">

265 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

266 GPT Image 2.5 Flare

267 </figcaption>

268

269 

270![Field and Flour bakery logo, second variation — GPT Image 2.5 Flare](<https://developers.openai.com/images/platform/guides/image-prompting/logo-generation-2-gpt-image-2-5-flare.webp>)

271 

272 

273 </figure>

274 <figure className="m-0 min-w-0">

275 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

276 GPT Image 2.5 Sunburst

277 </figcaption>

278

279 

280![Field and Flour bakery logo, second variation — GPT Image 2.5 Sunburst](<https://developers.openai.com/images/platform/guides/image-prompting/logo-generation-2-gpt-image-2-5-sunburst.webp>)

281 

282 

283 </figure>

284 

285 

286 

287 

288 

289 <figure className="m-0 min-w-0">

290 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

291 GPT Image 2.5 Flare

292 </figcaption>

293

294 

295![Field and Flour bakery logo, third variation — GPT Image 2.5 Flare](<https://developers.openai.com/images/platform/guides/image-prompting/logo-generation-3-gpt-image-2-5-flare.webp>)

296 

297 

298 </figure>

299 <figure className="m-0 min-w-0">

300 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

301 GPT Image 2.5 Sunburst

302 </figcaption>

303

304 

305![Field and Flour bakery logo, third variation — GPT Image 2.5 Sunburst](<https://developers.openai.com/images/platform/guides/image-prompting/logo-generation-3-gpt-image-2-5-sunburst.webp>)

306 

307 

308 </figure>

309 

310 

311 

312 

313 

314 <figure className="m-0 min-w-0">

315 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

316 GPT Image 2.5 Flare

317 </figcaption>

318

319 

320![Field and Flour bakery logo, fourth variation — GPT Image 2.5 Flare](<https://developers.openai.com/images/platform/guides/image-prompting/logo-generation-4-gpt-image-2-5-flare.webp>)

321 

322 

323 </figure>

324 <figure className="m-0 min-w-0">

325 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

326 GPT Image 2.5 Sunburst

327 </figcaption>

328

329 

330![Field and Flour bakery logo, fourth variation — GPT Image 2.5 Sunburst](<https://developers.openai.com/images/platform/guides/image-prompting/logo-generation-4-gpt-image-2-5-sunburst.webp>)

331 

332 

333 </figure>

334 

335 

336 

337### Use historical and real-world context

338 

339Name the place and date to establish a historical setting. The model can infer contextual details, but inspect clothing, staging, and surroundings for historical accuracy.

340 

341Generation settings: `size="1024x1536"`, `quality="medium"`.

342 

343```text

344Create a realistic outdoor crowd scene in Bethel, New York on August 16, 1969.

345Photorealistic, period-accurate clothing, staging, and environment.

346```

347 

348Example outputs:

349 

350 

351 

352 <figure className="m-0 min-w-0">

353 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

354 GPT Image 2.5 Flare

355 </figcaption>

356

357 

358![Crowd scene in Bethel, New York, in August 1969 — GPT Image 2.5 Flare](<https://developers.openai.com/images/platform/guides/image-prompting/world-knowledge-gpt-image-2-5-flare.webp>)

359 

360 

361 </figure>

362 <figure className="m-0 min-w-0">

363 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

364 GPT Image 2.5 Sunburst

365 </figcaption>

366

367 

368![Crowd scene in Bethel, New York, in August 1969 — GPT Image 2.5 Sunburst](<https://developers.openai.com/images/platform/guides/image-prompting/world-knowledge-gpt-image-2-5-sunburst.webp>)

369 

370 

371 </figure>

372 

373 

374 

375### Turn a story into a comic strip

376 

377For story-to-comic generation, define the narrative as a sequence of clear visual beats, one per panel. Keep descriptions concrete and action-focused so the model can translate the story into readable, well-paced panels.

378 

379Generation settings: `size="1024x1536"`, `quality="medium"`.

380 

381```text

382Create a short vertical comic-style reel with 4 panels.

383Panel 1: The owner leaves through the front door. The pet is framed in the window behind them, small against the glass, eyes wide, paws pressed high, the house suddenly quiet.

384Panel 2: The door clicks shut. Silence breaks. The pet slowly turns toward the empty house, posture shifting, eyes sharp with possibility.

385Panel 3: The house transformed. The pet sprawls across the couch like it owns the place, crumbs nearby, sunlight cutting across the room like a spotlight.

386Panel 4: The door opens. The pet is seated perfectly by the entrance, alert and composed, as if nothing happened.

387```

388 

389Example outputs:

390 

391 

392 

393 <figure className="m-0 min-w-0">

394 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

395 GPT Image 2.5 Flare

396 </figcaption>

397

398 

399![Four-panel comic about a pet at home — GPT Image 2.5 Flare](<https://developers.openai.com/images/platform/guides/image-prompting/comic-reel-gpt-image-2-5-flare.webp>)

400 

401 

402 </figure>

403 <figure className="m-0 min-w-0">

404 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

405 GPT Image 2.5 Sunburst

406 </figcaption>

407

408 

409![Four-panel comic about a pet at home — GPT Image 2.5 Sunburst](<https://developers.openai.com/images/platform/guides/image-prompting/comic-reel-gpt-image-2-5-sunburst.webp>)

410 

411 

412 </figure>

413 

414 

415 

416### Create an interface preview

417 

418Interface previews work best when you describe the product as if it already exists. Focus on layout, hierarchy, spacing, and real interface elements, and avoid concept art language so the result looks like a usable, shipped interface rather than a design sketch.

419 

420Generation settings: `size="1024x1536"`, `quality="medium"`.

421 

422```text

423Create a realistic mobile app UI mockup for a local farmers market.

424Show today’s market with a simple header, a short list of vendors with small photos and categories, a small “Today’s specials” section, and basic information for location and hours.

425Design it to be practical, and easy to use. White background, subtle natural accent colors, clear typography, and minimal decoration.

426It should look like a real, well-designed, beautiful app for a small local market.

427Place the UI mockup in an iPhone frame.

428```

429 

430Example outputs:

431 

432 

433 

434 <figure className="m-0 min-w-0">

435 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

436 GPT Image 2.5 Flare

437 </figcaption>

438

439 

440![Farmers market mobile app mockup — GPT Image 2.5 Flare](<https://developers.openai.com/images/platform/guides/image-prompting/ui-farmers-market-gpt-image-2-5-flare.webp>)

441 

442 

443 </figure>

444 <figure className="m-0 min-w-0">

445 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

446 GPT Image 2.5 Sunburst

447 </figcaption>

448

449 

450![Farmers market mobile app mockup — GPT Image 2.5 Sunburst](<https://developers.openai.com/images/platform/guides/image-prompting/ui-farmers-market-gpt-image-2-5-sunburst.webp>)

451 

452 

453 </figure>

454 

455 

456 

457### Create scientific and educational visuals

458 

459Scientific and educational visuals are strong fits for biology, chemistry, classroom explanations, flat scientific icon systems, diagrams, and learning assets. Prompt them like an instructional design brief: define the audience, lesson objective, visual format, required labels, and scientific constraints. For best results, ask for a clean, flat visual system with consistent icon style, clear arrows, readable labels, and enough white space for students to scan the concept quickly.

460 

461When accuracy matters, list the required components explicitly and say what should not be included. Use `quality="high"` for dense labels, diagrams, or assets that will be used in slides or course materials.

462 

463Generation settings: `size="1536x1024"`, `quality="high"`.

464 

465```text

466Create a simple biology diagram titled "Cellular Respiration at a Glance" for high school students.

467 

468Show how glucose turns into energy inside a cell. Include glycolysis, the Krebs cycle, and the electron transport chain.

469Use arrows to connect the steps, and label the main molecules: glucose, pyruvate, ATP, NADH, FADH2, CO2, O2, and H2O.

470Make it look like a clean classroom handout or slide, with a white background, simple icons, clear labels, and easy-to-read text.

471 

472Avoid tiny text, extra decoration, or anything that makes the diagram hard to understand.

473```

474 

475Example outputs:

476 

477 

478 

479 <figure className="m-0 min-w-0">

480 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

481 GPT Image 2.5 Flare

482 </figcaption>

483

484 

485![Classroom diagram of cellular respiration — GPT Image 2.5 Flare](<https://developers.openai.com/images/platform/guides/image-prompting/scientific-educational-cellular-respiration-gpt-image-2-5-flare.webp>)

486 

487 

488 </figure>

489 <figure className="m-0 min-w-0">

490 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

491 GPT Image 2.5 Sunburst

492 </figcaption>

493

494 

495![Classroom diagram of cellular respiration — GPT Image 2.5 Sunburst](<https://developers.openai.com/images/platform/guides/image-prompting/scientific-educational-cellular-respiration-gpt-image-2-5-sunburst.webp>)

496 

497 

498 </figure>

499 

500 

501 

502### Build slides, diagrams, and charts

503 

504Productivity visuals work best when the prompt is written like an artifact spec rather than an illustration request. Name the exact deliverable (slide, workflow diagram, chart, page image), define the canvas and hierarchy, provide the real text or data, and describe the visual language. These prompts should include practical constraints: readable typography, polished spacing, no decorative clutter, and no generic stock-photo treatment.

505 

506For slides, charts, and diagram-heavy assets, include the numbers and labels directly in the prompt. Use a landscape size for deck-style outputs and `quality="high"` when the image contains small text, legends, axes, or footnotes.

507 

508The sample market figures and citations below are fictional design inputs. Replace them with verified data before using the slide.

509 

510Generation settings: `size="1536x864"`, `quality="high"`.

511 

512```text

513Create one pitch-deck slide titled **"Market Opportunity"** that feels like a real Series A fundraising slide from a YC-backed startup.

514 

515Use a clean white background, modern sans-serif typography like Inter, and a crisp, minimal layout. The slide should include:

516 

517* A TAM/SAM/SOM concentric-circle diagram in muted blues and grays

518* Specific, believable market sizing numbers:

519 

520 * **TAM:** $42B

521 * **SAM:** $8.7B

522 * **SOM:** $340M

523* A clean bar chart below showing market growth from **2021 to 2026**, with a subtle upward trend

524* Small footnotes: **"AGI Research, 2024"** and **"Internal analysis"**

525* A company logo placeholder in the bottom-right corner

526 

527The design should look like it belongs in a deck that actually raised money: highly readable text, clear data hierarchy, polished spacing, and professional startup-style visual language.

528 

529Avoid clip art, stock photography, gradients, shadows, decorative elements, or anything that feels generic or overdesigned.

530```

531 

532Example outputs:

533 

534 

535 

536 <figure className="m-0 min-w-0">

537 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

538 GPT Image 2.5 Flare

539 </figcaption>

540

541 

542![Market opportunity slide with sample market sizing figures — GPT Image 2.5 Flare](<https://developers.openai.com/images/platform/guides/image-prompting/market-opportunity-slide-gpt-image-2-5-flare.webp>)

543 

544 

545 </figure>

546 <figure className="m-0 min-w-0">

547 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

548 GPT Image 2.5 Sunburst

549 </figcaption>

550

551 

552![Market opportunity slide with sample market sizing figures — GPT Image 2.5 Sunburst](<https://developers.openai.com/images/platform/guides/image-prompting/market-opportunity-slide-gpt-image-2-5-sunburst.webp>)

553 

554 

555 </figure>

556 

557 

558 

559## Edit images

560 

561Use `client.images.edit` with the referenced input images. For local edits that require a mask, see [editing with a mask](https://developers.openai.com/api/docs/guides/image-generation#edit-an-image-using-a-mask).

562 

563### Translate while preserving layout

564 

565Use each model's coffee-machine diagram from [Explain a process visually](#explain-a-process-visually) as the input. Ask to replace its text while keeping the design unchanged, then check the translation and any words left in the original language.

566 

567Edit settings: `size="1024x1536"`, `quality="high"`.

568 

569```text

570Translate the text in the infographic to Spanish. Do not change any other aspect of the image.

571```

572 

573Example outputs:

574 

575 

576 

577 <figure className="m-0 min-w-0">

578 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

579 GPT Image 2.5 Flare

580 </figcaption>

581

582 

583![Coffee machine diagram translated into Spanish — GPT Image 2.5 Flare](<https://developers.openai.com/images/platform/guides/image-prompting/infographic-coffee-machine-sp-gpt-image-2-5-flare.webp>)

584 

585 

586 </figure>

587 <figure className="m-0 min-w-0">

588 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

589 GPT Image 2.5 Sunburst

590 </figcaption>

591

592 

593![Coffee machine diagram translated into Spanish — GPT Image 2.5 Sunburst](<https://developers.openai.com/images/platform/guides/image-prompting/infographic-coffee-machine-sp-gpt-image-2-5-sunburst.webp>)

594 

595 

596 </figure>

597 

598 

599 

600### Transfer a visual style

601 

602Assign the reference image a specific role: its palette, texture, or visual medium. Describe the new subject separately. Use the pixel-art image below as the input.

603 

604Edit settings: `size="1024x1536"`, `quality="medium"`.

605 

606```text

607Use the same style from the input image and generate a man riding a motorcycle on a white background.

608```

609 

610Input image:

611 

612 

613 

614![Pixel-art game screen used as a style reference](<https://developers.openai.com/images/platform/guides/image-prompting/pixels.webp>)

615 

616 

617 

618Example outputs:

619 

620 

621 

622 <figure className="m-0 min-w-0">

623 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

624 GPT Image 2.5 Flare

625 </figcaption>

626

627 

628![Pixel-art motorcycle rider using the reference style — GPT Image 2.5 Flare](<https://developers.openai.com/images/platform/guides/image-prompting/motorcycle-gpt-image-2-5-flare.webp>)

629 

630 

631 </figure>

632 <figure className="m-0 min-w-0">

633 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

634 GPT Image 2.5 Sunburst

635 </figcaption>

636

637 

638![Pixel-art motorcycle rider using the reference style — GPT Image 2.5 Sunburst](<https://developers.openai.com/images/platform/guides/image-prompting/motorcycle-gpt-image-2-5-sunburst.webp>)

639 

640 

641 </figure>

642 

643 

644 

645### Preserve identity and change clothing

646 

647Use the person photograph and three clothing references below as inputs. State which aspects of the person must remain fixed, and allow only the clothing to change. This pattern also applies to edits where a product or object must remain recognizable.

648 

649Edit settings: `size="1024x1536"`, `quality="medium"`.

650 

651```text

652Edit the image to dress the woman using the provided clothing images. Do not change her face, facial features, skin tone, body shape, pose, or identity in any way. Preserve her exact likeness, expression, hairstyle, and proportions. Replace only the clothing, fitting the garments naturally to her existing pose and body geometry with realistic fabric behavior. Match lighting, shadows, and color temperature to the original photo so the outfit integrates photorealistically, without looking pasted on. Do not change the background, camera angle, framing, or image quality, and do not add accessories, text, logos, or watermarks.

653```

654 

655Input images:

656 

657 

658 

659

660 

661![Woman in a museum used as the identity reference](<https://developers.openai.com/images/platform/guides/image-prompting/woman-in-museum.webp>)

662 

663 

664

665 

666![Beige jacket used as a clothing reference](<https://developers.openai.com/images/platform/guides/image-prompting/jacket.webp>)

667 

668 

669

670 

671![White tank top used as a clothing reference](<https://developers.openai.com/images/platform/guides/image-prompting/tank-top.webp>)

672 

673 

674

675 

676![Gray boots used as a clothing reference](<https://developers.openai.com/images/platform/guides/image-prompting/boots.webp>)

677 

678 

679 

680 

681 

682Example outputs:

683 

684 

685 

686 <figure className="m-0 min-w-0">

687 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

688 GPT Image 2.5 Flare

689 </figcaption>

690

691 

692![Woman wearing the supplied clothing items — GPT Image 2.5 Flare](<https://developers.openai.com/images/platform/guides/image-prompting/outfit-gpt-image-2-5-flare.webp>)

693 

694 

695 </figure>

696 <figure className="m-0 min-w-0">

697 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

698 GPT Image 2.5 Sunburst

699 </figcaption>

700

701 

702![Woman wearing the supplied clothing items — GPT Image 2.5 Sunburst](<https://developers.openai.com/images/platform/guides/image-prompting/outfit-gpt-image-2-5-sunburst.webp>)

703 

704 

705 </figure>

706 

707 

708 

709### Combine references

710 

711Pass the scene photograph as image 1 and the dog photograph as image 2. Specify which element to move, its destination, and what must remain unchanged.

712 

713Edit settings: `size="1024x1536"`, `quality="medium"`.

714 

715```text

716Place the dog from the second image into the setting of image 1, right next to the woman, use the same style of lighting, composition and background. Do not change anything else.

717```

718 

719Input images:

720 

721 

722 

723

724 

725![Woman in a street scene, the first compositing input](<https://developers.openai.com/images/platform/guides/image-prompting/test-woman.webp>)

726 

727 

728

729 

730![Woman with a dog, the second compositing input](<https://developers.openai.com/images/platform/guides/image-prompting/test-woman-2.webp>)

731 

732 

733 

734 

735 

736Example outputs:

737 

738 

739 

740 <figure className="m-0 min-w-0">

741 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

742 GPT Image 2.5 Flare

743 </figcaption>

744

745 

746![Dog placed beside the woman in the street scene — GPT Image 2.5 Flare](<https://developers.openai.com/images/platform/guides/image-prompting/test-woman-with-dog-gpt-image-2-5-flare.webp>)

747 

748 

749 </figure>

750 <figure className="m-0 min-w-0">

751 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

752 GPT Image 2.5 Sunburst

753 </figcaption>

754

755 

756![Dog placed beside the woman in the street scene — GPT Image 2.5 Sunburst](<https://developers.openai.com/images/platform/guides/image-prompting/test-woman-with-dog-gpt-image-2-5-sunburst.webp>)

757 

758 

759 </figure>

760 

761 

762 

763 

764 

765 

766### Create a transparent product cutout

767 

768Request both an isolated subject in the prompt and `background="transparent"` in the API. Use PNG or WebP, preserve the returned alpha channel, and omit `output_compression` for PNG. A drawn checkerboard is not transparency. For subsequent edits, repeat the requirement to preserve the transparent background. Use the product photograph below as the input.

769 

770Edit settings: `size="1024x1536"`, `quality="medium"`, `background="transparent"`, `output_format="png"`.

771 

772```text

773Extract the product from the input image and isolate it on a fully transparent background.

774Output: centered product, crisp silhouette, no halos/fringing.

775Preserve product geometry and label legibility exactly.

776Add only light polishing. Do not add a solid backdrop, checkerboard, scenery, or shadow.

777Do not restyle the product; remove the background and preserve clean alpha transparency.

778```

779 

780Input image:

781 

782 

783 

784![Original shampoo product photograph](<https://developers.openai.com/images/platform/guides/image-prompting/shampoo.webp>)

785 

786 

787 

788Example outputs:

789 

790 

791 

792 <figure className="m-0 min-w-0">

793 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

794 GPT Image 2.5 Flare

795 </figcaption>

796

797 

798![Isolated shampoo bottle from the original example — GPT Image 2.5 Flare](<https://developers.openai.com/images/platform/guides/image-prompting/extract-product-gpt-image-2-5-flare.webp>)

799 

800 

801 </figure>

802 <figure className="m-0 min-w-0">

803 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

804 GPT Image 2.5 Sunburst

805 </figcaption>

806

807 

808![Isolated shampoo bottle from the original example — GPT Image 2.5 Sunburst](<https://developers.openai.com/images/platform/guides/image-prompting/extract-product-gpt-image-2-5-sunburst.webp>)

809 

810 

811 </figure>

812 

813 

814 

815### Turn a drawing into a realistic image

816 

817Sketch-to-render workflows are great for turning rough drawings into photorealistic concepts while keeping the original intent. Treat the prompt like a spec: preserve layout and perspective, then _add realism_ by specifying plausible materials, lighting, and environment. Include "do not add new elements/text" to avoid creative reinterpretations.

818 

819Edit settings: `size="1024x1536"`, `quality="medium"`.

820 

821```text

822Turn this drawing into a photorealistic image.

823Preserve the exact layout, proportions, and perspective.

824Choose realistic materials and lighting consistent with the sketch intent.

825Do not add new elements or text.

826```

827 

828Input image:

829 

830 

831 

832![Line drawing of a river valley](<https://developers.openai.com/images/platform/guides/image-prompting/drawings.webp>)

833 

834 

835 

836Example outputs:

837 

838 

839 

840 <figure className="m-0 min-w-0">

841 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

842 GPT Image 2.5 Flare

843 </figcaption>

844

845 

846![Photorealistic river valley rendered from the drawing — GPT Image 2.5 Flare](<https://developers.openai.com/images/platform/guides/image-prompting/realistic-valley-gpt-image-2-5-flare.webp>)

847 

848 

849 </figure>

850 <figure className="m-0 min-w-0">

851 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

852 GPT Image 2.5 Sunburst

853 </figcaption>

854

855 

856![Photorealistic river valley rendered from the drawing — GPT Image 2.5 Sunburst](<https://developers.openai.com/images/platform/guides/image-prompting/realistic-valley-gpt-image-2-5-sunburst.webp>)

857 

858 

859 </figure>

860 

861 

862 

863### Remove an object

864 

865Remove one object by naming it explicitly and preserving everything around it. Keep the person, pose, lighting, and composition unchanged so the edit stays local.

866 

867Edit settings: `size="1024x1536"`, `quality="medium"`.

868 

869```text

870Remove the flower from man's hand. Do not change anything else.

871```

872 

873Input image:

874 

875 

876 

877![Man holding a flower and wearing a blue cap](<https://developers.openai.com/images/platform/guides/image-prompting/man-with-blue-hat.webp>)

878 

879 

880 

881Example outputs:

882 

883 

884 

885 <figure className="m-0 min-w-0">

886 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

887 GPT Image 2.5 Flare

888 </figcaption>

889

890 

891![Same man after the flower has been removed — GPT Image 2.5 Flare](<https://developers.openai.com/images/platform/guides/image-prompting/man-with-no-flower-gpt-image-2-5-flare.webp>)

892 

893 

894 </figure>

895 <figure className="m-0 min-w-0">

896 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

897 GPT Image 2.5 Sunburst

898 </figcaption>

899

900 

901![Same man after the flower has been removed — GPT Image 2.5 Sunburst](<https://developers.openai.com/images/platform/guides/image-prompting/man-with-no-flower-gpt-image-2-5-sunburst.webp>)

902 

903 

904 </figure>

905 

906 

907 

908### Insert a person into a scene

909 

910Insert a person into a new scene while preserving their identity. Specify natural lighting, believable detail, body framing, gaze, and interaction with the scene. State which facial features and proportions must remain unchanged. For `gpt-image-2`, omit `input_fidelity`; image inputs are always processed at high fidelity.

911 

912Use the [woman in the museum](https://developers.openai.com/images/platform/guides/image-prompting/woman-in-museum.webp) as the input image.

913 

914Edit settings: `size="1024x1536"`, `quality="medium"`.

915 

916```text

917Generate a highly realistic action scene where this person is running away from a large, realistic brown bear attacking a campsite. The image should look like a real photograph someone could have taken, not an overly enhanced or cinematic movie-poster image.

918She is centered in the image but looking away from the camera, wearing outdoorsy camping attire, with dirt on her face and tears in her clothing. She is clearly afraid but focused on escaping, running away from the bear as it destroys the campsite behind her.

919The campsite is in Yosemite National Park, with believable natural details. The time of day is dusk, with natural lighting and realistic colors. Everything should feel grounded, authentic, and unstyled, as if captured in a real moment. Avoid cinematic lighting, dramatic color grading, or stylized composition.

920```

921 

922Example outputs:

923 

924 

925 

926 <figure className="m-0 min-w-0">

927 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

928 GPT Image 2.5 Flare

929 </figcaption>

930

931 

932![Woman running from a bear in a campsite scene — GPT Image 2.5 Flare](<https://developers.openai.com/images/platform/guides/image-prompting/scene-gpt-image-2-5-flare.webp>)

933 

934 

935 </figure>

936 <figure className="m-0 min-w-0">

937 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

938 GPT Image 2.5 Sunburst

939 </figcaption>

940

941 

942![Woman running from a bear in a campsite scene — GPT Image 2.5 Sunburst](<https://developers.openai.com/images/platform/guides/image-prompting/scene-gpt-image-2-5-sunburst.webp>)

943 

944 

945 </figure>

946 

947 

948 

949## Refine an image across turns

950 

951Start with one output, inspect it, and use it as the next input. Keep each follow-up narrow so you can see which change helped.

952 

953### Create the starting image

954 

955Use the shampoo photograph from [Create a transparent product cutout](#create-a-transparent-product-cutout) as the input for this billboard scene. Quote the label text exactly.

956 

957Edit settings: `size="1024x1536"`, `quality="medium"`.

958 

959```text

960Create a realistic billboard mockup of the shampoo on a highway scene during sunset.

961Billboard text (EXACT, verbatim, no extra characters):

962"Fresh and clean"

963Typography: bold sans-serif, high contrast, centered, clean kerning.

964Ensure text appears once and is perfectly legible.

965No watermarks, no logos.

966```

967 

968Input image:

969 

970 

971 

972![Original shampoo product photograph](<https://developers.openai.com/images/platform/guides/image-prompting/shampoo.webp>)

973 

974 

975 

976Example outputs:

977 

978 

979 

980 <figure className="m-0 min-w-0">

981 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

982 GPT Image 2.5 Flare

983 </figcaption>

984

985 

986![Shampoo billboard at sunset — GPT Image 2.5 Flare](<https://developers.openai.com/images/platform/guides/image-prompting/billboard-gpt-image-2-5-flare.webp>)

987 

988 

989 </figure>

990 <figure className="m-0 min-w-0">

991 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

992 GPT Image 2.5 Sunburst

993 </figcaption>

994

995 

996![Shampoo billboard at sunset — GPT Image 2.5 Sunburst](<https://developers.openai.com/images/platform/guides/image-prompting/billboard-gpt-image-2-5-sunburst.webp>)

997 

998 

999 </figure>

1000 

1001 

1002 

1003### Change one condition

1004 

1005Pass each model's billboard output from the previous step into its next edit request. This short follow-up changes the weather while retaining the existing scene.

1006 

1007Edit settings: `size="1024x1536"`, `quality="medium"`.

1008 

1009```text

1010Make it look like a winter evening with snowfall.

1011```

1012 

1013Example outputs:

1014 

1015 

1016 

1017 <figure className="m-0 min-w-0">

1018 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

1019 GPT Image 2.5 Flare

1020 </figcaption>

1021

1022 

1023![Shampoo billboard in a snowy evening scene — GPT Image 2.5 Flare](<https://developers.openai.com/images/platform/guides/image-prompting/billboard-winter-gpt-image-2-5-flare.webp>)

1024 

1025 

1026 </figure>

1027 <figure className="m-0 min-w-0">

1028 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

1029 GPT Image 2.5 Sunburst

1030 </figcaption>

1031

1032 

1033![Shampoo billboard in a snowy evening scene — GPT Image 2.5 Sunburst](<https://developers.openai.com/images/platform/guides/image-prompting/billboard-winter-gpt-image-2-5-sunburst.webp>)

1034 

1035 

1036 </figure>

1037 

1038 

1039 

1040### Keep a character consistent

1041 

1042For a book with multiple illustrations, create a reusable character reference to help preserve appearance across scenes, poses, and pages. Change the environment and story while repeating the character’s defining details.

1043 

1044#### Establish the character

1045 

1046Define the character’s appearance, proportions, outfit, and tone.

1047 

1048Generation settings: `size="1024x1536"`, `quality="medium"`.

1049 

1050```text

1051Create a children’s book illustration introducing a main character.

1052 

1053Character:

1054A young, storybook-style hero inspired by a little forest outlaw,

1055wearing a simple green hooded tunic, soft brown boots, and a small belt pouch.

1056The character has a kind expression, gentle eyes, and a brave but warm demeanor.

1057Carries a small wooden bow used only for helping, never harming.

1058 

1059Theme:

1060The character protects and rescues small forest animals like squirrels, birds, and rabbits.

1061 

1062Style:

1063Children’s book illustration, hand-painted watercolor look,

1064soft outlines, warm earthy colors, whimsical and friendly.

1065Proportions suitable for picture books (slightly oversized head, expressive face).

1066 

1067Constraints:

1068- Original character (no copyrighted characters)

1069- No text

1070- No watermarks

1071- Plain forest background to clearly showcase the character

1072```

1073 

1074Example outputs:

1075 

1076 

1077 

1078 <figure className="m-0 min-w-0">

1079 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

1080 GPT Image 2.5 Flare

1081 </figcaption>

1082

1083 

1084![Forest hero introducing a children&#x27;s book character — GPT Image 2.5 Flare](<https://developers.openai.com/images/platform/guides/image-prompting/childrens-book-illustration-1-gpt-image-2-5-flare.webp>)

1085 

1086 

1087 </figure>

1088 <figure className="m-0 min-w-0">

1089 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

1090 GPT Image 2.5 Sunburst

1091 </figcaption>

1092

1093 

1094![Forest hero introducing a children&#x27;s book character — GPT Image 2.5 Sunburst](<https://developers.openai.com/images/platform/guides/image-prompting/childrens-book-illustration-1-gpt-image-2-5-sunburst.webp>)

1095 

1096 

1097 </figure>

1098 

1099 

1100 

1101#### Continue the story

1102 

1103Reuse each model's generated character image and describe a new scene. Repeat the appearance constraints so the character stays consistent.

1104 

1105Edit settings: `size="1024x1536"`, `quality="medium"`.

1106 

1107```text

1108Continue the children’s book story using the same character.

1109 

1110Scene:

1111The same young forest hero is gently helping a frightened squirrel

1112out of a fallen tree after a winter storm.

1113The character kneels beside the squirrel, offering reassurance.

1114 

1115Character Consistency:

1116- Same green hooded tunic

1117- Same facial features, proportions, and color palette

1118- Same gentle, heroic personality

1119 

1120Style:

1121Children’s book watercolor illustration,

1122soft lighting, snowy forest environment,

1123warm and comforting mood.

1124 

1125Constraints:

1126- Do not redesign the character

1127- No text

1128- No watermarks

1129```

1130 

1131Example outputs:

1132 

1133 

1134 

1135 <figure className="m-0 min-w-0">

1136 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

1137 GPT Image 2.5 Flare

1138 </figcaption>

1139

1140 

1141![Same forest hero helping a squirrel in a winter scene — GPT Image 2.5 Flare](<https://developers.openai.com/images/platform/guides/image-prompting/childrens-book-illustration-2-gpt-image-2-5-flare.webp>)

1142 

1143 

1144 </figure>

1145 <figure className="m-0 min-w-0">

1146 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

1147 GPT Image 2.5 Sunburst

1148 </figcaption>

1149

1150 

1151![Same forest hero helping a squirrel in a winter scene — GPT Image 2.5 Sunburst](<https://developers.openai.com/images/platform/guides/image-prompting/childrens-book-illustration-2-gpt-image-2-5-sunburst.webp>)

1152 

1153 

1154 </figure>

1155 

1156 

1157 

1158## More workflows

1159 

1160### Change furniture in a room

1161 

1162Visualize furniture or décor changes in real spaces without recreating the entire scene. The goal is surgical realism: swap a single object while preserving camera angle, lighting, shadows, and surrounding context so the edit looks like a real photograph, not a redesign.

1163 

1164Edit settings: `size="1536x1024"`, `quality="medium"`.

1165 

1166```text

1167In this room photo, replace ONLY the white chairs with chairs made of wood.

1168Preserve camera angle, room lighting, floor shadows, and surrounding objects.

1169Keep all other aspects of the image unchanged.

1170Photorealistic contact shadows and fabric texture.

1171```

1172 

1173Input image:

1174 

1175 

1176 

1177![Original kitchen with white chairs](<https://developers.openai.com/images/platform/guides/image-prompting/kitchen.webp>)

1178 

1179 

1180 

1181Example outputs:

1182 

1183 

1184 

1185 <figure className="m-0 min-w-0">

1186 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

1187 GPT Image 2.5 Flare

1188 </figcaption>

1189

1190 

1191![Kitchen with replacement wooden chairs — GPT Image 2.5 Flare](<https://developers.openai.com/images/platform/guides/image-prompting/kitchen-chairs-gpt-image-2-5-flare.webp>)

1192 

1193 

1194 </figure>

1195 <figure className="m-0 min-w-0">

1196 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

1197 GPT Image 2.5 Sunburst

1198 </figcaption>

1199

1200 

1201![Kitchen with replacement wooden chairs — GPT Image 2.5 Sunburst](<https://developers.openai.com/images/platform/guides/image-prompting/kitchen-chairs-gpt-image-2-5-sunburst.webp>)

1202 

1203 

1204 </figure>

1205 

1206 

1207 

1208### Design a holiday card

1209 

1210For seasonal card concepts, describe the scene, emotional tone, materials, lighting, and exact copy. For a 3D pop-up or photographed-card treatment, specify paper layers, fibers, folds, and soft studio lighting. The example below uses a nostalgic teddy-bear scene.

1211 

1212Generation settings: `size="1024x1536"`, `quality="medium"`.

1213 

1214```text

1215Create a Christmas holiday card illustration.

1216 

1217Scene:

1218a cozy Christmas scene with an old teddy bear sitting inside a keepsake box, slightly worn fur, soft stitching repairs, placed near a window with falling snow outside. The scene suggests the child has grown up, but the memories remain.

1219 

1220Mood:

1221Warm, nostalgic, gentle, emotional.

1222 

1223Style:

1224Premium holiday card photography, soft cinematic lighting,

1225realistic textures, shallow depth of field,

1226tasteful bokeh lights, high print-quality composition.

1227 

1228Constraints:

1229- Original artwork only

1230- No trademarks

1231- No watermarks

1232- No logos

1233 

1234Include ONLY this card text (verbatim):

1235"Merry Christmas — some memories never fade."

1236```

1237 

1238Example outputs:

1239 

1240 

1241 

1242 <figure className="m-0 min-w-0">

1243 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

1244 GPT Image 2.5 Flare

1245 </figcaption>

1246

1247 

1248![Holiday card showing a teddy bear by a window — GPT Image 2.5 Flare](<https://developers.openai.com/images/platform/guides/image-prompting/christmas-holiday-card-teddy-gpt-image-2-5-flare.webp>)

1249 

1250 

1251 </figure>

1252 <figure className="m-0 min-w-0">

1253 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

1254 GPT Image 2.5 Sunburst

1255 </figcaption>

1256

1257 

1258![Holiday card showing a teddy bear by a window — GPT Image 2.5 Sunburst](<https://developers.openai.com/images/platform/guides/image-prompting/christmas-holiday-card-teddy-gpt-image-2-5-sunburst.webp>)

1259 

1260 

1261 </figure>

1262 

1263 

1264 

1265### Design collectible merchandise

1266 

1267Explore merchandise and packaging concepts using product photography cues: materials, packaging, and print clarity. Keep designs original and non-infringing, and compare multiple character or packaging variants.

1268 

1269Generation settings: `size="1024x1536"`, `quality="medium"`.

1270 

1271```text

1272Create a collectible action figure of a vintage-style toy propeller airplane with rounded wings, a front-mounted spinning propeller, slightly worn paint edges, classic childhood proportions, designed as a nostalgic holiday collectible, in blister packaging.

1273 

1274Concept:

1275A nostalgic holiday collectible inspired by the simple toy airplanes

1276children used to play with during winter holidays.

1277Evokes warmth, imagination, and childhood wonder.

1278 

1279Style:

1280Premium toy photography, realistic plastic and painted metal textures,

1281studio lighting, shallow depth of field,

1282sharp label printing, high-end retail presentation.

1283 

1284Constraints:

1285- Original design only

1286- No trademarks

1287- No watermarks

1288- No logos

1289 

1290Include ONLY this packaging text (verbatim):

1291"Christmas Memories Edition"

1292```

1293 

1294Example outputs:

1295 

1296 

1297 

1298 <figure className="m-0 min-w-0">

1299 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

1300 GPT Image 2.5 Flare

1301 </figcaption>

1302

1303 

1304![Collectible toy airplane in holiday packaging — GPT Image 2.5 Flare](<https://developers.openai.com/images/platform/guides/image-prompting/christmas-collectible-toy-airplane-gpt-image-2-5-flare.webp>)

1305 

1306 

1307 </figure>

1308 <figure className="m-0 min-w-0">

1309 <figcaption className="mb-2 min-h-10 text-sm font-semibold">

1310 GPT Image 2.5 Sunburst

1311 </figcaption>

1312

1313 

1314![Collectible toy airplane in holiday packaging — GPT Image 2.5 Sunburst](<https://developers.openai.com/images/platform/guides/image-prompting/christmas-collectible-toy-airplane-gpt-image-2-5-sunburst.webp>)

1315 

1316 

1317 </figure>

1318 

1319 

1320 

1321## Run a complete example

1322 

1323This runnable example remains pinned to `gpt-image-2`. Use it as a baseline, then choose an available model and its supported request settings for your evaluation.

1324 

1325The examples below generate four logo variations and extract a product onto a transparent background. Install the [OpenAI SDK](https://developers.openai.com/api/docs/libraries#install-an-official-sdk) with `pip install openai` for Python or `gem install openai` for Ruby. Set `OPENAI_API_KEY` and save the [product photograph](https://developers.openai.com/images/platform/guides/image-prompting/shampoo.webp) as `input_images/shampoo.webp`. Live requests incur API usage charges.

1326 

1327 

1328 

1329### View the complete example

1330 

1331 

1332 Generate and edit transparent assets

1333 

1334```python

1335import base64

1336from pathlib import Path

1337 

1338from openai import OpenAI

1339 

1340client = OpenAI()

1341 

1342 

1343prompt = """

1344Create an original, non-infringing logo for a company called Field & Flour, a local bakery.

1345The logo should feel warm, simple, and timeless. Use clean, vector-like shapes, a strong silhouette, and balanced negative space.

1346Favor simplicity over detail so it reads clearly at small and large sizes. Flat design, minimal strokes, no gradients unless essential.

1347Fully transparent background. Deliver a single centered logo with generous padding, clean alpha edges, and no solid backdrop, scenery, checkerboard, or watermark.

1348"""

1349 

1350result = client.images.generate(

1351 model="gpt-image-2",

1352 prompt=prompt,

1353 size="1024x1536",

1354 quality="medium",

1355 background="transparent",

1356 output_format="png",

1357 n=4, # Generate 4 versions of the logo

1358)

1359 

1360# Preserve the returned PNG bytes, including the alpha channel.

1361for index, item in enumerate(result.data, start=1):

1362 Path(f"logo-generation-{index}-gpt-image-2.png").write_bytes(

1363 base64.b64decode(item.b64_json)

1364 )

1365 

1366# Extract a product from a reference image.

1367prompt = """

1368Extract the product from the input image and isolate it on a fully transparent background.

1369Output: centered product, crisp silhouette, no halos/fringing.

1370Preserve product geometry and label legibility exactly.

1371Add only light polishing. Do not add a solid backdrop, checkerboard, scenery, or shadow.

1372Do not restyle the product; remove the background and preserve clean alpha transparency.

1373"""

1374 

1375result = client.images.edit(

1376 model="gpt-image-2",

1377 image=[

1378 Path("input_images/shampoo.webp"),

1379 ],

1380 prompt=prompt,

1381 size="1024x1536",

1382 quality="medium",

1383 background="transparent",

1384 output_format="png",

1385)

1386 

1387Path("extract-product-gpt-image-2.png").write_bytes(

1388 base64.b64decode(result.data[0].b64_json)

1389)

1390```

1391 

1392```ruby

1393require "base64"

1394require "openai"

1395require "pathname"

1396 

1397client = OpenAI::Client.new

1398result = client.images.generate(

1399 model: "gpt-image-2",

1400 prompt: "Create an original logo for Field & Flour, a local bakery. Use warm, simple shapes on a fully transparent background, with clean alpha edges and no shadow or checkerboard.",

1401 size: "1024x1536", quality: :medium, background: :transparent, output_format: :png, n: 4

1402)

1403Array(result.data).each_with_index do |item, index|

1404 File.binwrite("logo-generation-#{index + 1}-gpt-image-2.png", Base64.strict_decode64(item.b64_json || raise("No PNG returned")))

1405end

1406result = client.images.edit(

1407 model: "gpt-image-2", image: OpenAI::FilePart.new(Pathname("input_images/shampoo.webp"), content_type: "image/webp"),

1408 prompt: "Extract the product onto a fully transparent background. Preserve its geometry and label, with clean edges and no shadow or restyling.",

1409 size: "1024x1536", quality: :medium, background: :transparent, output_format: :png

1410)

1411File.binwrite("extract-product-gpt-image-2.png", Base64.strict_decode64(Array(result.data).fetch(0).b64_json || raise("No PNG returned")))

1412```

1413 

1414 

1415 

1416 

1417 

1418For additional prompts and complete workflows, see the [original notebook](https://github.com/openai/openai-cookbook/blob/d310dfa05d20fb653caa9c1c4b89ac1a4aeeeae4/examples/multimodal/image-gen-models-prompting-guide.ipynb).

1419 

1420## Check the result

1421 

1422Check the output against the requirements before using it:

1423 

1424- Is required text accurate and legible? Are diagram labels and relationships correct?

1425- Do identities, product shapes, labels, and reference details remain intact?

1426- Did the edit change only what you requested?

1427- If transparency is required, does the file contain an alpha channel rather than a painted background?

1428 

1429Compare quality, latency, and cost on representative inputs when changing prompts or models. See [image generation pricing](https://developers.openai.com/api/docs/pricing#image-generation) for current costs.

1430 

1431 

1432

1433 

1434

1435 

1436 <header className="not-prose mb-8">

1437 <h2

1438 id="gpt-image-2-guide"

1439 className="m-0 text-3xl font-semibold text-default"

1440 >

1441 {"GPT Image 2 reference"}

1442 </h2>

1443

1444 

1445 Overview and request settings for existing GPT Image 2 workflows.

1446

1447 

1448 </header>

1449

1450 

1451## Overview

1452 

1453GPT Image 2 supports image generation and editing, including text rendering, reference-based edits, and flexible output sizes. Use this reference to maintain existing integrations. The [prompting guide](https://developers.openai.com/api/docs/guides/image-prompting?model=gpt-image-2.5) covers shared techniques for composition, text, reference images, and preserving details during edits. Its illustrated examples use GPT Image 2.5 Flare and GPT Image 2.5 Sunburst; outputs can differ across models. For migration, use the guide's [model selection](https://developers.openai.com/api/docs/guides/image-prompting?model=gpt-image-2.5#choose-a-model) and [evaluation workflow](https://developers.openai.com/api/docs/guides/image-prompting?model=gpt-image-2.5#migrate-an-existing-workflow).

1454 

1455## Model parameters

1456 

1457Use `client.images.generate` for generation and `client.images.edit` for edits. See the [image generation guide](https://developers.openai.com/api/docs/guides/image-generation) for API setup and request examples.

1458 

1459| Parameter | GPT Image 2 |

1460| -------------------- | -------------------------------------------------------------------------------------------------------------------- |

1461| `model` | `gpt-image-2` |

1462| `quality` | `low`, `medium`, `high`, or `auto` |

1463| `size` | `auto` or a supported resolution; see [size constraints](https://developers.openai.com/api/docs/guides/image-generation#size-and-quality-options) |

1464| `input_fidelity` | Omit it. Image inputs are always processed at high fidelity. |

1465| `output_format` | `png`, `jpeg`, or `webp` |

1466| `background` | For transparent output, explicitly set `transparent` and use PNG or WebP. |

1467| `output_compression` | Use only for JPEG or WebP output, not PNG. |

1468 

1469Transparent backgrounds are available in preview for `gpt-image-2`.

1470 

1471For the original prompts, inputs, and runnable workflows, see the pinned [GPT Image 2 notebook](https://github.com/openai/openai-cookbook/blob/d310dfa05d20fb653caa9c1c4b89ac1a4aeeeae4/examples/multimodal/image-gen-models-prompting-guide.ipynb).

1472 

1473 

1474

1475 

1476

1477 

1478 <header className="not-prose mb-8">

1479 <h2

1480 id="gpt-image-1.5-guide"

1481 className="m-0 text-3xl font-semibold text-default"

1482 >

1483 {"GPT Image 1.5 reference"}

1484 </h2>

1485

1486 

1487 Overview and request settings for existing GPT Image 1.5 workflows.

1488

1489 

1490 </header>

1491

1492 

1493## Overview

1494 

1495**Deprecated model.** `gpt-image-1.5` is scheduled to shut down on December 1,

1496 2026. See the [deprecation

1497 notice](https://developers.openai.com/api/docs/deprecations#2026-06-02-gpt-image-model-deprecations) and

1498 validate existing workflows with `gpt-image-2` before migrating.

1499 

1500GPT Image 1.5 supports image generation and editing, including text rendering, photorealistic images, and reference-based edits. Use this reference to maintain existing integrations. The [prompting guide](https://developers.openai.com/api/docs/guides/image-prompting?model=gpt-image-2.5) covers shared techniques for composition, text, reference images, and preserving details during edits. Test those techniques with your model and inputs; outputs can differ across models.

1501 

1502## Model parameters

1503 

1504Use `client.images.generate` for generation and `client.images.edit` for edits. See the [image generation guide](https://developers.openai.com/api/docs/guides/image-generation) for API setup and request examples.

1505 

1506| Parameter | GPT Image 1.5 |

1507| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

1508| `model` | `gpt-image-1.5` |

1509| `quality` | `low`, `medium`, `high`, or `auto` |

1510| `size` | `1024x1024`, `1024x1536`, `1536x1024`, or `auto` |

1511| `output_format` | `png`, `jpeg`, or `webp` |

1512| `output_compression` | 0 to 100, for JPEG or WebP output only |

1513| `background` | Set `transparent` explicitly for transparent output; use PNG or WebP |

1514| `input_fidelity` | `low` or `high`; `high` preserves input details, while `quality` controls output generation. Omit this parameter when migrating to GPT Image 2, which always uses high input fidelity. |

1515 

1516 

1517

1518 

1519

1520 

1521 <header className="not-prose mb-8">

1522 <h2

1523 id="gpt-image-1-guide"

1524 className="m-0 text-3xl font-semibold text-default"

1525 >

1526 {"GPT Image 1 reference"}

1527 </h2>

1528

1529 

1530 Overview and request settings for existing GPT Image 1 workflows.

1531

1532 

1533 </header>

1534

1535 

1536## Overview

1537 

1538**Deprecated model.** `gpt-image-1` is scheduled to shut down on October 23,

1539 2026. See the [deprecation

1540 notice](https://developers.openai.com/api/docs/deprecations#2026-04-22-legacy-gpt-model-snapshots) and

1541 validate existing workflows with `gpt-image-2` before migrating.

1542 

1543GPT Image 1 supports image generation and editing with reference images and masks. Use this reference to maintain existing integrations. For shared techniques such as describing a scene, preserving details, and refining an edit, see the [prompting guide](https://developers.openai.com/api/docs/guides/image-prompting?model=gpt-image-2.5).

1544 

1545## Model parameters

1546 

1547Use `client.images.generate` for generation and `client.images.edit` for edits. See the [image generation guide](https://developers.openai.com/api/docs/guides/image-generation) for API setup and request examples.

1548 

1549| Parameter | GPT Image 1 |

1550| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

1551| `model` | `gpt-image-1` |

1552| `quality` | `low`, `medium`, `high`, or `auto` |

1553| `size` | `1024x1024`, `1024x1536`, `1536x1024`, or `auto` |

1554| `output_format` | `png`, `jpeg`, or `webp` |

1555| `output_compression` | 0 to 100, for JPEG or WebP output only |

1556| `background` | Set `transparent` explicitly for transparent output; use PNG or WebP |

1557| `input_fidelity` | `low` or `high`; `high` preserves input details, while `quality` controls output generation. High input fidelity uses more image input tokens. Omit this parameter when migrating to GPT Image 2, which always uses high input fidelity. |

Details

27 27 

28## Generate or edit images28## Generate or edit images

29 29 

30With the Images API, choose `gpt-image-2` to generate images from text or edit existing images. With the Responses API, choose a mainline model that supports the image generation tool; the tool handles GPT Image model selection.30With the Images API, choose `gpt-image-2.5-sunburst` to generate images from text or edit existing images. With the Responses API, choose a mainline model that supports the image generation tool; the tool handles GPT Image model selection.

31 31 

32 32 

33 33 

Details

950}950}

951```951```

952 952 

953```ruby

954require "json"

955 

956APPLY_PATCH_TOOL_DESC = <<~PROMPT

957 This is a custom utility that makes it more convenient to add, remove, move, or edit code files. `apply_patch` effectively allows you to execute a diff/patch against a file, but the format of the diff specification is unique to this task, so pay careful attention to these instructions. To use the `apply_patch` command, you should pass a message of the following structure as "input":

958 

959 %%bash

960 apply_patch <<"EOF"

961 *** Begin Patch

962 [YOUR_PATCH]

963 *** End Patch

964 EOF

965 

966 Where [YOUR_PATCH] is the actual content of your patch, specified in the following V4A diff format.

967 

968 *** [ACTION] File: [path/to/file] -> ACTION can be one of Add, Update, or Delete.

969 For each snippet of code that needs to be changed, repeat the following:

970 [context_before] -> See below for further instructions on context.

971 - [old_code] -> Precede the old code with a minus sign.

972 + [new_code] -> Precede the new, replacement code with a plus sign.

973 [context_after] -> See below for further instructions on context.

974 

975 For instructions on [context_before] and [context_after]:

976 - By default, show 3 lines of code immediately above and 3 lines immediately below each change. If a change is within 3 lines of a previous change, do NOT duplicate the first change’s [context_after] lines in the second change’s [context_before] lines.

977 - If 3 lines of context is insufficient to uniquely identify the snippet of code within the file, use the @@ operator to indicate the class or function to which the snippet belongs. For instance, we might have:

978 @@ class BaseClass

979 [3 lines of pre-context]

980 - [old_code]

981 + [new_code]

982 [3 lines of post-context]

983 

984 - If a code block is repeated so many times in a class or function such that even a single @@ statement and 3 lines of context cannot uniquely identify the snippet of code, you can use multiple `@@` statements to jump to the right context. For instance:

985 

986 @@ class BaseClass

987 @@ def method():

988 [3 lines of pre-context]

989 - [old_code]

990 + [new_code]

991 [3 lines of post-context]

992 

993 Note, then, that we do not use line numbers in this diff format, as the context is enough to uniquely identify code. An example of a message that you might pass as "input" to this function, in order to apply a patch, is shown below.

994 

995 %%bash

996 apply_patch <<"EOF"

997 *** Begin Patch

998 *** Update File: pygorithm/searching/binary_search.py

999 @@ class BaseClass

1000 @@ def search():

1001 - pass

1002 + raise NotImplementedError()

1003 

1004 @@ class Subclass

1005 @@ def search():

1006 - pass

1007 + raise NotImplementedError()

1008 

1009 *** End Patch

1010 EOF

1011 

1012PROMPT

1013 

1014tool = {

1015 name: "apply_patch",

1016 description: APPLY_PATCH_TOOL_DESC,

1017 parameters: {

1018 type: "object",

1019 properties: {input: {type: "string", description: "The apply_patch command to execute."}},

1020 required: ["input"]

1021 }

1022}

1023puts(JSON.generate(tool))

1024```

1025 

953 1026 

954### Reference Implementation: apply_patch.py1027### Reference Implementation: apply_patch.py

955 1028 

Details

340 .forEach(text -> System.out.println(text.text()));340 .forEach(text -> System.out.println(text.text()));

341```341```

342 342 

343```ruby

344response = client.responses.create(

345 model: "gpt-5.1", input: response_input, tools: [{type: :apply_patch}]

346)

347```

348 

343 349 

344When the model decides to execute an apply_patch tool, you will receive an apply_patch_call function type within the response stream. Within the operation object, you’ll receive a type field (with one of `create_file`, `update_file`, or `delete_file`) and the diff to implement.350When the model decides to execute an apply_patch tool, you will receive an apply_patch_call function type within the response stream. Within the operation object, you’ll receive a type field (with one of `create_file`, `update_file`, or `delete_file`) and the diff to implement.

345 351 


376}382}

377```383```

378 384 

385```ruby

386output = {

387 type: :apply_patch_call_output,

388 call_id: call_id,

389 status: success ? :completed : :failed,

390 output: log_output

391}

392```

393 

379 394 

380#### Using the shell tool395#### Using the shell tool

381 396 


387tools = [{"type": "shell"}]402tools = [{"type": "shell"}]

388```403```

389 404 

405```ruby

406tools = [{type: :shell}]

407```

408 

390 409 

391When a shell tool call is returned, the Responses API includes a `shell_call` object with a timeout, a maximum output length, and the command to run.410When a shell tool call is returned, the Responses API includes a `shell_call` object with a timeout, a maximum output length, and the command to run.

392 411 

Details

392 # *** End Patch392 # *** End Patch

393```393```

394 394 

395```ruby

396require "openai"

397 

398client = OpenAI::Client.new

399 

400input = <<~PROMPT

401 Add a cancel button next to the save button in app/page.tsx.

402 Current file contents:

403 export default function Page() { return <button>Save</button>; }

404PROMPT

405response = client.responses.create(

406 model: "gpt-5.3-codex", input: input,

407 tools: [{type: :apply_patch}], parallel_tool_calls: false

408)

409response.output.each do |item|

410 pp(item.operation) if item.is_a?(OpenAI::Responses::ResponseApplyPatchToolCall)

411end

412 

413APPLY_PATCH_GRAMMAR = <<~GRAMMAR

414 

415 start: begin_patch hunk+ end_patch

416 begin_patch: "*** Begin Patch" LF

417 end_patch: "*** End Patch" LF?

418 

419 hunk: add_hunk | delete_hunk | update_hunk

420 add_hunk: "*** Add File: " filename LF add_line+

421 delete_hunk: "*** Delete File: " filename LF

422 update_hunk: "*** Update File: " filename LF change_move? change?

423 

424 filename: /(.+)/

425 add_line: "+" /(.*)/ LF -> line

426 

427 change_move: "*** Move to: " filename LF

428 change: (change_context | change_line)+ eof_line?

429 change_context: ("@@" | "@@ " /(.+)/) LF

430 change_line: ("+" | "-" | " ") /(.*)/ LF

431 eof_line: "*** End of File" LF

432 

433 %import common.LF

434 

435GRAMMAR

436 

437response = client.responses.create(

438 model: "gpt-5.3-codex", input: input,

439 tools: [{

440 type: :custom, name: "apply_patch",

441 description: "Apply a patch to update files.",

442 format: {type: :grammar, syntax: :lark, definition: APPLY_PATCH_GRAMMAR}

443 }],

444 parallel_tool_calls: false

445)

446response.output.each do |item|

447 puts(item.input) if item.is_a?(OpenAI::Responses::ResponseCustomToolCall)

448end

449```

450 

395 451 

396Patches objects the Responses API tool can be implemented by following this [example](https://github.com/openai/openai-agents-python/blob/main/examples/tools/apply_patch.py) and patches from the freeform tool can be applied with the logic in our canonical GPT-5 [apply_patch.py](https://github.com/openai/openai-cookbook/blob/main/examples/gpt-5/apply_patch.py%20) implementation.452Patches objects the Responses API tool can be implemented by following this [example](https://github.com/openai/openai-agents-python/blob/main/examples/tools/apply_patch.py) and patches from the freeform tool can be applied with the logic in our canonical GPT-5 [apply_patch.py](https://github.com/openai/openai-cookbook/blob/main/examples/gpt-5/apply_patch.py%20) implementation.

397 453 


557)613)

558```614```

559 615 

616```ruby

617require "json"

618 

619GIT_TOOL = {

620 "type" => "function",

621 "name" => "git",

622 "description" => "Execute a git command in the repository root. Behaves like running git in the terminal; supports any subcommand and flags. The command can be provided as a full git invocation (e.g., `git status -sb`) or just the arguments after git (e.g., `status -sb`).",

623 "parameters" => {

624 "type" => "object",

625 "properties" => {

626 "command" => {

627 "type" => "string",

628 "description" => "The git command to execute. Accepts either a full git invocation or only the subcommand/args."

629 },

630 "timeout_sec" => {

631 "type" => "integer",

632 "minimum" => 1,

633 "maximum" => 1800,

634 "description" => "Optional timeout in seconds for the git command."

635 }

636 },

637 "required" => ["command"]

638 }

639}

640 

641TOOLS = [GIT_TOOL]

642PROMPT_TOOL_USE_DIRECTIVE = "- Strictly avoid raw `cmd`/terminal for Git operations. Use the dedicated `git` tool instead."

643puts(JSON.generate(TOOLS))

644puts(PROMPT_TOOL_USE_DIRECTIVE)

645```

646 

560 647 

561### Other Custom Tools (web search, semantic search, memory, etc.)648### Other Custom Tools (web search, semantic search, memory, etc.)

562 649 

Details

73- **Reasoning effort:** Use `reasoning.effort` to choose between `low`, `medium`, `high`, or `xhigh`. The default is `medium`, but many workloads will perform well with `low`. Reserve `none` for use cases where low latency is more important than intelligence. See [Reasoning Models](https://developers.openai.com/api/docs/guides/reasoning) for detailed recommendations.73- **Reasoning effort:** Use `reasoning.effort` to choose between `low`, `medium`, `high`, or `xhigh`. The default is `medium`, but many workloads will perform well with `low`. Reserve `none` for use cases where low latency is more important than intelligence. See [Reasoning Models](https://developers.openai.com/api/docs/guides/reasoning) for detailed recommendations.

74- **Verbosity:** Use `text.verbosity` to control output length. Treat final answer length as separate from reasoning quality; specify word budgets, section counts, table widths, or JSON-only output where needed.74- **Verbosity:** Use `text.verbosity` to control output length. Treat final answer length as separate from reasoning quality; specify word budgets, section counts, table widths, or JSON-only output where needed.

75- **Structured Outputs:** Avoid describing the expected output schema in the prompt. Use [Structured Outputs](https://developers.openai.com/api/docs/guides/structured-outputs) for automatic validation and increased accuracy.75- **Structured Outputs:** Avoid describing the expected output schema in the prompt. Use [Structured Outputs](https://developers.openai.com/api/docs/guides/structured-outputs) for automatic validation and increased accuracy.

76- **Prompt caching:** [Prompt caching](https://developers.openai.com/api/docs/guides/prompt-caching) works automatically for eligible long prompts and can reduce latency and input-token cost. To maximize cache hits, keep stable content at the beginning of the request. Put dynamic user-specific context near the end. For repeated traffic with common prefixes, use `prompt_cache_key` consistently and track `usage.prompt_tokens_details.cached_tokens`.76- **Prompt caching:** [Prompt caching](https://developers.openai.com/api/docs/guides/prompt-caching) works automatically for eligible long prompts and can reduce latency and input-token cost. To maximize cache hits, keep stable content at the beginning of the request. Put dynamic user-specific context near the end. Track `usage.prompt_tokens_details.cached_tokens` to measure reuse. Use an optional [`prompt_cache_key`](https://developers.openai.com/api/docs/guides/prompt-caching#separate-prompts-with-cache-keys) to maintain separate cache accounting for customers or users, making cached token usage and billing easier to explain for each group. This also helps prevent cache-hit probing across users.

77- **Tool calling:** GPT-5.5 supports the same tool-calling patterns as GPT-5.4, including function tools and tool-heavy agent workflows. Put most tool-specific guidance in the tool descriptions themselves: what the tool does, when to use it, required inputs, side effects, retry safety, and common error modes. Add tool-specific context to system instructions only when it applies across tools or materially changes the agent's operating policy.77- **Tool calling:** GPT-5.5 supports the same tool-calling patterns as GPT-5.4, including function tools and tool-heavy agent workflows. Put most tool-specific guidance in the tool descriptions themselves: what the tool does, when to use it, required inputs, side effects, retry safety, and common error modes. Add tool-specific context to system instructions only when it applies across tools or materially changes the agent's operating policy.

78- **Hosted tools and tool search:** Prefer [OpenAI-hosted tools](https://developers.openai.com/api/docs/guides/tools) where they fit the workflow, such as web search, file search, code interpreter, image generation, and computer use. Hosted tools reduce custom orchestration burden and keep common tool patterns aligned with the Responses API and Agents SDK. Use custom function tools when you need to call your own systems, enforce domain-specific side effects, or expose internal business workflows. For large tool catalogs, consider using [tool search](https://developers.openai.com/api/docs/guides/tools-tool-search) to defer tool definitions and load only the relevant subset.78- **Hosted tools and tool search:** Prefer [OpenAI-hosted tools](https://developers.openai.com/api/docs/guides/tools) where they fit the workflow, such as web search, file search, code interpreter, image generation, and computer use. Hosted tools reduce custom orchestration burden and keep common tool patterns aligned with the Responses API and Agents SDK. Use custom function tools when you need to call your own systems, enforce domain-specific side effects, or expose internal business workflows. For large tool catalogs, consider using [tool search](https://developers.openai.com/api/docs/guides/tools-tool-search) to defer tool definitions and load only the relevant subset.

79- **Tool preambles:** Preambles can improve chat UX because the user sees an initial, useful status update before the model generates the final response. They also make tool use easier to follow: the model can state what it's about to check or do, then continue from that same assistant state after tool results arrive.79- **Tool preambles:** Preambles can improve chat UX because the user sees an initial, useful status update before the model generates the final response. They also make tool use easier to follow: the model can state what it's about to check or do, then continue from that same assistant state after tool results arrive.

Details

60 60 

61Additionally, Chat Completions can return multiple parallel generations as `choices`, using the `n` param. In Responses, we've removed this param, leaving only one generation.61Additionally, Chat Completions can return multiple parallel generations as `choices`, using the `n` param. In Responses, we've removed this param, leaving only one generation.

62 62 

63 

64 

65 Chat Completions API

66 

67```python

68from openai import OpenAI

69 

70client = OpenAI()

71 

72completion = client.chat.completions.create(

73 model="gpt-6-astra",

74 messages=[

75 {

76 "role": "user",

77 "content": "Write a one-sentence bedtime story about a unicorn.",

78 }

79 ],

80)

81 

82print(completion.choices[0].message.content)

83```

84 

85```ruby

86require "openai"

87 

88client = OpenAI::Client.new

89completion = client.chat.completions.create(

90 model: "gpt-6-astra",

91 messages: [{role: :user, content: "Write a one-sentence bedtime story about a unicorn."}]

92)

93puts(completion.choices.fetch(0).message.content)

94```

95 

96 Responses API

97 

98```python

99from openai import OpenAI

100 

101client = OpenAI()

102 

103response = client.responses.create(

104 model="gpt-6-astra",

105 input="Write a one-sentence bedtime story about a unicorn.",

106)

107 

108print(response.output_text)

109```

110 

111```ruby

112require "openai"

113 

114client = OpenAI::Client.new

115response = client.responses.create(

116 model: "gpt-6-astra",

117 input: "Write a one-sentence bedtime story about a unicorn."

118)

119puts(response.output_text)

120```

121 

122 

123 

124 

63When you get a response back from the Responses API, the fields differ slightly.125When you get a response back from the Responses API, the fields differ slightly.

64Instead of a `message`, you receive a typed `response` object with its own `id`.126Instead of a `message`, you receive a typed `response` object with its own `id`.

65Responses are stored by default. Chat completions are stored by default for new accounts.127Responses are stored by default. Chat completions are stored by default for new accounts.

Details

10- **Cheaper input tokens:** Pay the model's reduced cached-input rate for reused tokens, discounted up to 90%.10- **Cheaper input tokens:** Pay the model's reduced cached-input rate for reused tokens, discounted up to 90%.

11- **Faster:** Reduce the time spent processing input before the response starts.11- **Faster:** Reduce the time spent processing input before the response starts.

12 12 

13Prompt caching is enabled by default for supported OpenAI models. Use the [Prompt Caching Dashboard](https://platform.openai.com/usage?usage_section=prompt-caching) to monitor cache read hit rates.13Prompt caching is enabled by default for supported OpenAI models. Use the [Prompt Caching Dashboard](https://platform.openai.com/usage?usage_section=prompt-caching) to monitor cache read hit rates and use the [Prompt Cache Diagnostics tool](https://developers.openai.com/api/docs/guides/prompt-caching/diagnostics) to diagnose cache misses and improve cache reuse.

14 14 

15## What is the prompt cache?15## What is the prompt cache?

16 16 

17As the model processes input tokens, it calculates intermediate key-value (KV) states. These states let the model refer back to earlier tokens while processing new input and generating a response.17When the model processes input tokens, it must calculate intermediate states, known as key-value (KV) states. These states let the model refer back to earlier tokens while processing new input and generating output tokens.

18 18 

19Prompt caching preserves that state for a reusable prefix. When a later request has the same prefix and finds a matching cache entry, the model can reuse the saved state instead of processing those tokens again. It still needs to process any new input to generate a new response.19Prompt caching preserves that state for a reusable **prefix**: the unchanged tokens at the beginning of a prompt. When a later request has the same prefix and finds a matching cache entry, the model can reuse the saved state instead of processing those tokens again. It still needs to process any new input to generate a new response.

20 20 

21The prompt cache stores key-value (KV) tensors, not the tokens themselves.21The prompt cache stores key-value (KV) tensors, not the tokens themselves.

22 22 


30 30 

31Cache reuse requires the entire rendered prefix to match. If content or a relevant setting changes before a breakpoint, the prefix after that change cannot match the existing cache entry.31Cache reuse requires the entire rendered prefix to match. If content or a relevant setting changes before a breakpoint, the prefix after that change cannot match the existing cache entry.

32 32 

33<a id="which-settings-affect-the-cached-prefix"></a>

34 

35 

36 

33### Which settings affect the cached prefix?37### Which settings affect the cached prefix?

34 38 

35 39 


37Changing a request does not necessarily discard an existing cache entry. What matters is whether a subsequent request has the same prefix and can find an eligible matching breakpoint. The main settings to check are:41Changing a request does not necessarily discard an existing cache entry. What matters is whether a subsequent request has the same prefix and can find an eligible matching breakpoint. The main settings to check are:

38 42 

39| Setting | Impact |43| Setting | Impact |

40| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |44| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |

41| [`model`](https://developers.openai.com/api/reference/resources/responses/methods/create#%28resource%29%20responses%20%3E%20%28method%29%20create%20%3E%20%28params%29%200.non_streaming%20%3E%20%28param%29%20model%20%3E%20%28schema%29) | A different model can use different weights and caching behavior. |45| [`model`](https://developers.openai.com/api/reference/resources/responses/methods/create#%28resource%29%20responses%20%3E%20%28method%29%20create%20%3E%20%28params%29%200.non_streaming%20%3E%20%28param%29%20model%20%3E%20%28schema%29) | A different model can use different weights and caching behavior. |

42| [`tools`](https://developers.openai.com/api/reference/resources/responses/methods/create#%28resource%29%20responses%20%3E%20%28method%29%20create%20%3E%20%28params%29%200.non_streaming%20%3E%20%28param%29%20tools%20%3E%20%28schema%29) | Changes tool names, descriptions, schemas, ordering, or tool-specific instructions. |46| [`tools`](https://developers.openai.com/api/reference/resources/responses/methods/create#%28resource%29%20responses%20%3E%20%28method%29%20create%20%3E%20%28params%29%200.non_streaming%20%3E%20%28param%29%20tools%20%3E%20%28schema%29) | Changes tool names, descriptions, schemas, ordering, or tool-specific instructions. |

43| [`parallel_tool_calls`](https://developers.openai.com/api/reference/resources/responses/methods/create#%28resource%29%20responses%20%3E%20%28method%29%20create%20%3E%20%28params%29%200.non_streaming%20%3E%20%28param%29%20parallel_tool_calls%20%3E%20%28schema%29) | Can change instructions about calling multiple tools in one turn. |47| [`parallel_tool_calls`](https://developers.openai.com/api/reference/resources/responses/methods/create#%28resource%29%20responses%20%3E%20%28method%29%20create%20%3E%20%28params%29%200.non_streaming%20%3E%20%28param%29%20parallel_tool_calls%20%3E%20%28schema%29) | Can change instructions about calling multiple tools in one turn. |

44| [`text.format`](https://developers.openai.com/api/reference/resources/responses/methods/create#%28resource%29%20responses%20%3E%20%28method%29%20create%20%3E%20%28params%29%200.non_streaming%20%3E%20%28param%29%20text%20%3E%20%28schema%29) ([Structured Outputs](https://developers.openai.com/api/docs/guides/structured-outputs)) | Adds output-format instructions and the requested schema. |48| [`text.format`](https://developers.openai.com/api/reference/resources/responses/methods/create#%28resource%29%20responses%20%3E%20%28method%29%20create%20%3E%20%28params%29%200.non_streaming%20%3E%20%28param%29%20text%20%3E%20%28schema%29) ([Structured Outputs](https://developers.openai.com/api/docs/guides/structured-outputs)) | Adds output-format instructions and the requested schema. |

45| [`reasoning.effort`](https://developers.openai.com/api/reference/resources/responses/methods/create#%28resource%29%20responses%20%3E%20%28method%29%20create%20%3E%20%28params%29%200.non_streaming%20%3E%20%28param%29%20reasoning%20%3E%20%28schema%29) | Request-level changes can alter reasoning instructions. See [configuration updates](https://developers.openai.com/api/docs/guides/reasoning#change-reasoning-mid-conversation). |49| [`reasoning.effort`](https://developers.openai.com/api/reference/resources/responses/methods/create#%28resource%29%20responses%20%3E%20%28method%29%20create%20%3E%20%28params%29%200.non_streaming%20%3E%20%28param%29%20reasoning%20%3E%20%28schema%29) | Can change model-side reasoning instructions. On supported models, use a [configuration update](#change-reasoning-effort-without-rewriting-the-prefix) to change effort while preserving the earlier prefix. |

46| [`text.verbosity`](https://developers.openai.com/api/reference/resources/responses/methods/create#%28resource%29%20responses%20%3E%20%28method%29%20create%20%3E%20%28params%29%200.non_streaming%20%3E%20%28param%29%20text%20%3E%20%28schema%29) | Can change instructions about response detail. |50| [`text.verbosity`](https://developers.openai.com/api/reference/resources/responses/methods/create#%28resource%29%20responses%20%3E%20%28method%29%20create%20%3E%20%28params%29%200.non_streaming%20%3E%20%28param%29%20text%20%3E%20%28schema%29) | Can change instructions about response detail. |

47| [`context_management`](https://developers.openai.com/api/reference/resources/responses/methods/create#%28resource%29%20responses%20%3E%20%28method%29%20create%20%3E%20%28params%29%200.non_streaming%20%3E%20%28param%29%20context_management%20%3E%20%28schema%29) ([Compaction](https://developers.openai.com/api/docs/guides/compaction)) | Replaces earlier conversation content with a compacted context that can prevent reuse from the first changed token onward. |51| [`context_management`](https://developers.openai.com/api/reference/resources/responses/methods/create#%28resource%29%20responses%20%3E%20%28method%29%20create%20%3E%20%28params%29%200.non_streaming%20%3E%20%28param%29%20context_management%20%3E%20%28schema%29) ([Compaction](https://developers.openai.com/api/docs/guides/compaction)) | Replaces earlier conversation content with a compacted context that can prevent reuse from the first changed token onward. |

48 52 


52 56 

53## How caching works57## How caching works

54 58 

55A **cache breakpoint** marks the end of a prompt prefix that OpenAI can save to the cache and reuse in later requests. The first request writes an eligible prefix to the cache and a later request looks for the longest matching cached prefix available, working backward through eligible breakpoints until it finds a match.59A **cache breakpoint** marks the end of a prompt prefix that OpenAI can save to the cache and reuse in later requests. The first request writes an eligible prefix to the cache and subsequent requests look for the longest matching cached prefix available, working backward through eligible breakpoints until they find a match.

56 60 

57A prompt prefix must meet the model's **minimum cacheable token length** before it can be cached. Tokens in the OpenAI-provided hidden system content do not count toward this minimum. The minimum cacheable prompt length is 1,024 tokens for GPT-5.6 and later and 2,048 tokens for models older than GPT-5.6. You may occasionally get cache hits below 2,048 tokens for some earlier models. See the [model comparison](#summary-of-model-differences) for other differences.61A prompt prefix must meet the model's **minimum cacheable token length** before it can be cached. Tokens in the OpenAI-provided hidden system content do not count toward this minimum. The minimum cacheable prompt length is 1,024 tokens for GPT-5.6 and later and varies by request settings for earlier models. See the [model comparison](#summary-of-model-differences) for details.

58 62 

59After the minimum cacheable token length, you can choose where to place cache breakpoints explicitly, or let OpenAI choose their locations implicitly. The available options depend on the model.63After the minimum cacheable token length, you can choose where to place cache breakpoints explicitly, or let OpenAI choose their locations implicitly. The available options depend on the model.

60 64 

61 65 

62 66 

67<a id="how-caching-works-gpt-5-6-and-later"></a>

68 

69 

70 

63### GPT-5.6 and later71### GPT-5.6 and later

64 72 

65 73 

66 74 

67For GPT-5.6 and later, cache writes cost 1.25× the standard, uncached input-token rate. It is worth incurring this charge when a prefix will be reused, because subsequent reads cost only 0.1× that rate. Writing a prefix once and fully reusing it once costs 1.35× its ordinary input cost, compared with 2× for processing it twice without caching. The savings grow with each additional cache read: across ten requests, one write and nine full reads cost 2.15×, compared with 10× without caching.75For GPT-5.6 and later, cache writes cost 1.25× the standard, uncached input-token rate. It is worth incurring this charge when you know a prefix will be reused, because subsequent reads cost only 0.1× that rate. Writing a prefix once and fully reusing it once costs 1.35× its ordinary input cost, compared with 2× for processing it twice without caching. The savings grow with each additional cache read: across ten requests, one write and nine full reads cost 2.15×, compared with 10× without caching.

68 76 

69Both implicit and explicit caching are supported, where explicit caching gives you more control over which context is written to cache.77Both implicit and explicit caching are supported, where explicit caching gives you more control over which context is written to cache.

70 78 


74- When no explicit breakpoints are placed, the request does not use prompt caching or create cache writes.82- When no explicit breakpoints are placed, the request does not use prompt caching or create cache writes.

75- Explicit-only mode lets you choose where cache writes end. Content after the last selected breakpoint is processed at the uncached input-token rate without a cache-write charge, so you can avoid writing changing content that is unlikely to be reused.83- Explicit-only mode lets you choose where cache writes end. Content after the last selected breakpoint is processed at the uncached input-token rate without a cache-write charge, so you can avoid writing changing content that is unlikely to be reused.

76- Multiple explicit breakpoints can preserve prefixes that change at different rates. Each request can create up to four cache writes.84- Multiple explicit breakpoints can preserve prefixes that change at different rates. Each request can create up to four cache writes.

77- For cache reads, OpenAI considers up to the latest 50 breakpoints in the conversation and reuses the longest matching cached prefix.85- `additional_tools` input items do not currently accept `prompt_cache_breakpoint`.

78 86 

79Top-level `instructions` cannot contain an explicit breakpoint. To mark reusable developer instructions, place them in an `input_text` block inside a developer message.87Top-level `instructions` cannot contain an explicit breakpoint. To mark reusable developer instructions, place them in an `input_text` block inside a developer message.

80 88 

81**Implicit mode:** OpenAI chooses breakpoint locations out of the box that work well for most use cases.89**Implicit mode:** OpenAI chooses breakpoint locations out of the box that work well for most use cases.

82 90 

83- When `prompt_cache_options.mode` is `implicit`, OpenAI places a breakpoint at the end of the latest eligible message.91- When `prompt_cache_options.mode` is `implicit`, OpenAI places a breakpoint at the end of the latest eligible message. Eligible messages are:

92 - user messages

93 - the last tool response in a consecutive group of tool responses

94 - the last developer message in the initial consecutive group of developer messages.

84- You can add explicit breakpoints without turning off the implicit breakpoint; an implicit breakpoint uses one of the four cache write slots to leave three usable explicit cache write slots.95- You can add explicit breakpoints without turning off the implicit breakpoint; an implicit breakpoint uses one of the four cache write slots to leave three usable explicit cache write slots.

85- The implicit breakpoint creates a cache write through the latest eligible message.

86 96 

87 97 

88 98 


90 100 

91 101 

92 102 

103<a id="how-caching-works-earlier-models"></a>

104 

105 

106 

93### Earlier models107### Earlier models

94 108 

95 109 


102 116 

103 117 

104 118 

119### How prefix matching works

120 

121OpenAI walks through only the **cache lookup boundaries** (explained below) in the incoming request, from longest prefix to shortest, looking for an available matching prefix already cached on the machine.

122 

123For GPT-5.6 and later, the cache lookup boundaries in the incoming request are:

124 

125- **Explicit-only mode:** The first 2 and latest 50 explicit breakpoints.

126- **Implicit mode:** The first 2 and latest 50 explicit breakpoints, the implicit breakpoint, up to 20 earlier eligible message endings, and the endpoint of the initial consecutive block of developer messages. This lets implicit mode reuse a prefix ending at an earlier message without explicit breakpoints there.

127 

105## Cache lifetime128## Cache lifetime

106 129 

107Cache entries are not stored indefinitely. A later request can reuse a cached prefix only while its entry remains available, and reusing the prefix refreshes its lifetime without another cache-write charge. The lifetime and retention settings [depend on the model](#summary-of-model-differences).130Cache entries are not stored indefinitely. A later request can reuse a cached prefix only while its entry remains available, and reusing the prefix refreshes its lifetime without another cache-write charge. The lifetime and retention settings [depend on the model](#summary-of-model-differences).


110 133 

111 134 

112 135 

136<a id="cache-lifetime-gpt-5-6-and-later"></a>

137 

138 

139 

113### GPT-5.6 and later140### GPT-5.6 and later

114 141 

115 142 


124 151 

125 152 

126 153 

154<a id="cache-lifetime-earlier-models"></a>

155 

156 

157 

127### Earlier models158### Earlier models

128 159 

129 160 


162 193 

163- Current machine load and available capacity.194- Current machine load and available capacity.

164- A hash of the initial tokens after the hidden OpenAI content, including tool definitions when present. The number of tokens hashed varies by model.195- A hash of the initial tokens after the hidden OpenAI content, including tool definitions when present. The number of tokens hashed varies by model.

165- The optionally supplied [`prompt_cache_key`](#prompt-cache-keys) that controls grouping and distribution during higher-volume traffic, to mitigate request overflow to other machines and, therefore, cache misses.196- An optional [`prompt_cache_key`](#prompt-cache-keys), which separates cache reuse between groups of requests.

197 

198 

166 199 

167<a id="prompt-cache-keys"></a>200<a id="prompt-cache-keys"></a>

168 201 


172 205 

173 206 

174 207 

175When traffic exceeds a machine's available capacity, requests may overflow to another machine. If that machine does not have a matching cache entry, the initial overflow request incurs a cache miss.208[`prompt_cache_key`](https://developers.openai.com/api/reference/resources/responses/methods/create#%28resource%29%20responses%20%3E%20%28method%29%20create%20%3E%20%28params%29%200.non_streaming%20%3E%20%28param%29%20prompt_cache_key%20%3E%20%28schema%29) is an optional control for maintaining separate cache accounting for customers or users within your application. OpenAI handles cache routing automatically; you can omit the key for normal caching.

176 209 

177Set [`prompt_cache_key`](https://developers.openai.com/api/reference/resources/responses/methods/create#%28resource%29%20responses%20%3E%20%28method%29%20create%20%3E%20%28params%29%200.non_streaming%20%3E%20%28param%29%20prompt_cache_key%20%3E%20%28schema%29) to help requests with the same prefix reach the same cache. Keys influence routing; they do not pin requests to a machine or guarantee a cache read hit. See [how to tune prompt cache keys](#prompt-cache-key-best-practices).210Using separate keys can make cached token usage and billing easier to explain for each customer or user. For example, separate keys help prevent cache-hit probing across users: submitting candidate prompts and observing cache hits to learn whether matching content was previously cached. See [Separate cache accounting with keys](#separate-prompts-with-cache-keys).

178 211 

179 212 

180 213 


185## Summary of model differences218## Summary of model differences

186 219 

187| Behavior | GPT-5.6 and later | GPT-5.5 and GPT-5.5 Pro | Other earlier models |220| Behavior | GPT-5.6 and later | GPT-5.5 and GPT-5.5 Pro | Other earlier models |

188| -------------------------- | ------------------------------------------------------- | ------------------------------------------------------------------ | ------------------------------------------------------------------------------- |221| -------------------------- | --------------------------------------------------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------- |

189| Implicit breakpoints | At the end of the latest eligible user or tool message. | Spaced at regular 2,048-token intervals. | Spaced at regular, model-dependent intervals. |222| Implicit breakpoints | At the end of the latest eligible message. | Spaced at regular 2,048-token intervals. | Spaced at regular, model-dependent intervals. |

190| Explicit breakpoints | Supported | Not supported | Not supported |223| Explicit breakpoints | Supported | Not supported | Not supported |

191| Minimum cacheable prefix | 1,024 visible input tokens | 2,048 visible input tokens; some models may cache shorter prefixes | 2,048 visible input tokens; some models may cache shorter prefixes |224| Minimum cacheable prefix | 1,024 visible input tokens | Varies by request settings | Varies by request settings |

192| Cached-token reporting | Exact eligible boundary, excluding hidden tokens | Excludes hidden tokens and rounds down to a multiple of 128 | Excludes hidden tokens and rounds down to a multiple of 128 |225| Cached-token reporting | Exact eligible boundary, excluding hidden tokens | Excludes hidden tokens and rounds down to a multiple of 128 | Excludes hidden tokens and rounds down to a multiple of 128 |

193| Cache read charge | 0.1× the uncached input-token rate | Model-dependent cached-input rate | Model-dependent cached-input rate |226| Cache read charge | 0.1× the uncached input-token rate | Model-dependent cached-input rate | Model-dependent cached-input rate |

194| Cache write charge | 1.25× the uncached input-token rate | No additional cache-write charge | No additional cache-write charge |227| Cache write charge | 1.25× the uncached input-token rate | No additional cache-write charge | No additional cache-write charge |


206 239 

207 240 

208 241 

242For models before GPT-5.6, the minimum cacheable input length varies with request settings, including tools, images, output schemas, reasoning effort, and verbosity.

243 

209<a id="best-practices"></a>244<a id="best-practices"></a>

210 245 

211## How to optimize prompt caching246## How to optimize prompt caching

212 247 

213Focus on [preserving conversation history](#preserve-conversation-history), [keeping tool definitions stable](#tools), and understanding the three main cache controls. Use [`prompt_cache_options.mode` and `prompt_cache_breakpoint`](#choose-a-caching-mode) to choose where caching occurs, and [`prompt_cache_key`](#prompt-cache-key-best-practices) to help related requests reach the same cache.248Focus on [preserving conversation history](#preserve-conversation-history), [keeping tool definitions stable](#manage-tools-with-append-only-updates), and choosing where caching occurs. Use [`prompt_cache_options.mode` and `prompt_cache_breakpoint`](#choose-a-caching-mode) to control cache breakpoints. If your application needs separate cache accounting for customers, you can also use an optional [`prompt_cache_key`](#separate-prompts-with-cache-keys).

214 249 

215 250 

216 251 


229In multi-turn applications, reusing the growing conversation history can save more input tokens than caching only the initial instructions. Preserve earlier messages and tool results so later turns can reuse the full shared prefix.266In multi-turn applications, reusing the growing conversation history can save more input tokens than caching only the initial instructions. Preserve earlier messages and tool results so later turns can reuse the full shared prefix.

230 267 

231- **Keep the prefix stable.** Put stable developer instructions and shared reference material first. If developer instructions or shared material contain timestamps, user-specific content, or other dynamic content, place those at the end rather than the beginning, or move them into later conversation messages.268- **Keep the prefix stable.** Put stable developer instructions and shared reference material first. If developer instructions or shared material contain timestamps, user-specific content, or other dynamic content, place those at the end rather than the beginning, or move them into later conversation messages.

232- **Preserve conversation history.** Append new messages rather than rewriting earlier turns. Summarization, compaction, or context truncation can change the prefix and reset cache reuse.269- **Preserve conversation history.** Append new messages rather than rewriting earlier turns. Summarization, [compaction](#compaction-can-reduce-cache-reuse), or context truncation can change the prefix and reset cache reuse.

233- **Change reasoning effort without rewriting the prefix.** On GPT-6 Astra, append a `configuration_update` input item to change reasoning effort between responses while keeping request-level `reasoning.effort` unchanged. This preserves the original prefix for cache reuse. See [Change reasoning mid-conversation](https://developers.openai.com/api/docs/guides/reasoning#change-reasoning-mid-conversation) for examples and compatibility limits.270- **Change reasoning effort without rewriting the prefix.** On GPT-6 Astra, append a `configuration_update` input item to change reasoning effort between responses while keeping request-level `reasoning.effort` unchanged. This preserves the original prefix for cache reuse. See [Change reasoning mid-conversation](https://developers.openai.com/api/docs/guides/reasoning#change-reasoning-mid-conversation) for examples and compatibility limits.

234 271 

235Keep changing content after the breakpoint272Keep changing content after the breakpoint


268 305 

269 306 

270 307 

271<a id="tools"></a>308 

309 

310<a id="change-reasoning-effort-without-rewriting-the-prefix"></a>

311 

312 

313 

314### Change reasoning effort without rewriting the prefix

315 

316 

317 

318On supported GPT-6 and later models, append a `configuration_update` input item to [change reasoning effort during a conversation](https://developers.openai.com/api/docs/guides/reasoning?api-mode=responses#change-reasoning-mid-conversation) while preserving the earlier cached prefix. Keep the top-level `reasoning.effort` at its original value as changing that setting can rewrite instructions in the hidden system instructions.

319 

320The latest configuration update controls the reasoning effort for subsequent responses. For example, append this item to the existing `input` array to switch to `high` reasoning for the subsequent requests:

321 

322Item to append to the input array

323 

324```json

325{

326 "type": "configuration_update",

327 "reasoning": { "effort": "high" }

328}

329```

330 

331 

332 

333 

334 

335 

336 

337 

338<a id="manage-tools-with-append-only-updates"></a>

272 339 

273 340 

274 341 


313 382 

314<a id="prompt-cache-key-best-practices"></a>383<a id="prompt-cache-key-best-practices"></a>

315 384 

385<a id="tune-prompt-cache-keys"></a>

316 386 

387<a id="separate-prompts-with-cache-keys"></a>

317 388 

318### Tune prompt cache keys

319 389 

320 390 

391<a id="separate-cache-accounting-with-keys"></a>

321 392 

322- **Group related requests.** Combine a prompt version with a stable user, workspace, session, or thread ID that matches how your application reuses context. For example:

323 - `prompt_name_v1:user_123` groups a user's related requests that share a prompt version.

324 - `prompt_name_v1:session_456` groups requests within one session.

325 - `prompt_name_v1:workspace_acme:shard_3` groups requests within a stable shard of a workspace.

326- **Keep keys stable.** Reuse the key while its prefix remains useful; do not generate a new key for every request.

327- **Split busy groups.** If a group receives high traffic and cache read hits decline, distribute it across more keys with a stable, deterministic mapping. Keep related requests on the same shard so they can reuse its cache.

328 393 

329Create stable cache keys

330 394 

331```javascript395### Separate cache accounting with keys

332import { createHash } from "node:crypto";

333 

334const tenantId = "acme";

335const sessionId = "session-42";

336const promptVersion = "support-v3";

337// Tune for peak traffic per tenant and reusable prompt group; monitor cache hits.

338const shardCount = 16;

339 

340const digest = createHash("sha256")

341 .update(`${tenantId}:${sessionId}`)

342 .digest("hex");

343const shard = Number.parseInt(digest.slice(0, 8), 16) % shardCount;

344const promptCacheKey = `${promptVersion}:${tenantId}:shard-${shard}`;

345```

346 396 

347```python

348import hashlib

349 397 

350tenant_id = "acme"

351session_id = "session-42"

352prompt_version = "support-v3"

353# Tune for peak traffic per tenant and reusable prompt group; monitor cache hits.

354shard_count = 16

355 398 

356digest = hashlib.sha256(f"{tenant_id}:{session_id}".encode()).hexdigest()399Use `prompt_cache_key` when you want to maintain separate cache accounting for customers, users, or workspaces within your application. This can make cached token usage and billing easier to explain within each group. The key is optional and is not needed to optimize caching.

357shard = int(digest[:8], 16) % shard_count

358prompt_cache_key = f"{prompt_version}:{tenant_id}:shard-{shard}"

359```

360 400 

361```java401- **Choose how to separate cache accounting.** Assign a distinct key to each customer or user whose cache accounting should remain separate. For example, `support:customer_123` and `support:customer_456` maintain separate cache accounting for two customers, even when their requests contain the same prefix.

362import java.nio.charset.StandardCharsets;402- **Keep keys stable within each group.** Reuse the same key for a customer's related requests. Generate a separate key for a session or thread only when it needs its own cache accounting.

363import java.security.MessageDigest;403- **Apply keys consistently.** Use the customer's key across their requests to maintain separate cache accounting. This also helps prevent cache-hit probing across customers.

364import java.util.HexFormat;

365 

366String tenantId = "acme";

367String sessionId = "session-42";

368String promptVersion = "support-v3";

369int shardCount = 16;

370 

371String digest =

372 HexFormat.of()

373 .formatHex(

374 MessageDigest.getInstance("SHA-256")

375 .digest((tenantId + ":" + sessionId).getBytes(StandardCharsets.UTF_8)));

376long shard = Long.parseLong(digest.substring(0, 8), 16) % shardCount;

377String promptCacheKey = promptVersion + ":" + tenantId + ":shard-" + shard;

378```

379 404 

380```ruby

381require "digest"

382 

383tenant_id = "acme"

384session_id = "session-42"

385prompt_version = "support-v3"

386# Tune for peak traffic per tenant and reusable prompt group; monitor cache hits.

387shard_count = 16

388 405 

389digest = Digest::SHA256.hexdigest("#{tenant_id}:#{session_id}")

390shard = digest.slice(0, 8).to_s.to_i(16) % shard_count

391prompt_cache_key = "#{prompt_version}:#{tenant_id}:shard-#{shard}"

392```

393 406 

394 407 

395 408 

409<a id="choose-a-cache-lifetime"></a>

396 410 

397 411 

398 412 

399<a id="choose-a-cache-lifetime"></a>413<a id="configure-cache-retention"></a>

400 414 

401 415 

402 416 


414 428 

415 429 

416 430 

431<a id="escape-the-minimum-cacheable-length-cost-trap"></a>

432 

433 

434 

417### Escape the minimum cacheable length cost trap435### Escape the minimum cacheable length cost trap

418 436 

419 437 


422 440 

423The chart highlights the minimum cacheable length cost trap where short prefix lengths can cost more uncached than expanding to the minimum cacheable token length.441The chart highlights the minimum cacheable length cost trap where short prefix lengths can cost more uncached than expanding to the minimum cacheable token length.

424 442 

443<a id="mathematical-details"></a>

444 

445 

446 

425#### Mathematical details447#### Mathematical details

426 448 

427 449 


531 555 

532 556 

533 557 

558<a id="migrate-prompt-caching-from-an-earlier-model-to-gpt-5-6-and-later"></a>

559 

560 

561 

534### Migrate prompt caching from an earlier model to GPT-5.6 and later562### Migrate prompt caching from an earlier model to GPT-5.6 and later

535 563 

536 564 

537 565 

538- Keep existing stable prefixes.566- Keep existing stable prefixes.

539- Keep existing `prompt_cache_key` values.567- If you use `prompt_cache_key`, keep existing values to preserve separate cache accounting for customers or users.

540- Replace `prompt_cache_retention` with `prompt_cache_options.ttl`.568- Replace `prompt_cache_retention` with `prompt_cache_options.ttl`.

541- Confirm that reusable prefixes meet the model's [minimum cacheable length](#summary-of-model-differences).569- Confirm that reusable prefixes meet the model's [minimum cacheable length](#summary-of-model-differences).

542- If the default breakpoint includes content that changes between requests, add an explicit breakpoint after the stable prefix.570- If the default breakpoint includes content that changes between requests, add an explicit breakpoint after the stable prefix.

543- Use `prompt_cache_options.mode: "explicit"` when later content is not worth writing.571- Use `prompt_cache_options.mode: "explicit"` when later content is not worth writing.

544- Compare `cached_tokens`, `cache_write_tokens`, latency, and total cost before and after migration.572- [Compare `cached_tokens`, `cache_write_tokens`, latency, and total cost](#monitor-cache-performance) before and after migration.

545 573 

546 574 

547 575 


560Consider a single-turn LLM judge that determines whether a completed interaction shows evidence that the user is satisfied after an interaction with a chatbot. Each request uses the same grading rubric and labeled few-shot examples to evaluate a different interaction.590Consider a single-turn LLM judge that determines whether a completed interaction shows evidence that the user is satisfied after an interaction with a chatbot. Each request uses the same grading rubric and labeled few-shot examples to evaluate a different interaction.

561 591 

562- **Preserving the prefix:** The fixed rubric and examples come first. Their combined length is deliberately kept just above the model's [minimum cacheable length](#summary-of-model-differences), using material that helps calibrate the judge. The interaction being evaluated comes last.592- **Preserving the prefix:** The fixed rubric and examples come first. Their combined length is deliberately kept just above the model's [minimum cacheable length](#summary-of-model-differences), using material that helps calibrate the judge. The interaction being evaluated comes last.

563- **Prompt cache key:** A stable `prompt_cache_key`, such as `satisfaction_judge_v1`, groups requests using the same rubric version.

564- **Caching mode and breakpoint:** Explicit-only caching is enabled, with a breakpoint after the fixed rubric and examples. The user–chatbot conversation being evaluated comes after that breakpoint and is not written to the cache, avoiding a cache-write charge for content that is unlikely to be reused.593- **Caching mode and breakpoint:** Explicit-only caching is enabled, with a breakpoint after the fixed rubric and examples. The user–chatbot conversation being evaluated comes after that breakpoint and is not written to the cache, avoiding a cache-write charge for content that is unlikely to be reused.

565 594 

566For illustration, a deployment using these principles might achieve a **token cache-hit rate of around 70%**. This is a hypothetical figure, not a measured deployment result. Actual cache-hit rates depend on your context and application usage.595An example deployment using these principles reported a **token cache-hit rate of ~70%**. This figure illustrates a possible outcome. Actual cache-hit rate ceilings will depend upon your context and application usage.

567 596 

568Responses API request for a single-turn judge597Responses API request for a single-turn judge

569 598 


572 "model": "gpt-5.6-sol",601 "model": "gpt-5.6-sol",

573 "reasoning": { "effort": "medium", "context": "all_turns" },602 "reasoning": { "effort": "medium", "context": "all_turns" },

574 "text": { "verbosity": "low" },603 "text": { "verbosity": "low" },

575 "prompt_cache_key": "satisfaction_judge_v1",

576 "prompt_cache_options": { "mode": "explicit" },604 "prompt_cache_options": { "mode": "explicit" },

577 "input": [605 "input": [

578 {606 {


598 626 

599 627 

600 628 

601<a id="customer-support-agent"></a>629 

630 

631<a id="multi-turn-agent"></a>

602 632 

603 633 

604 634 


609Consider a multi-turn agent with long, shared developer instructions and frequent tool calls. Typical usage sees users running multiple sessions with the agent at once, and often forking the threads.639Consider a multi-turn agent with long, shared developer instructions and frequent tool calls. Typical usage sees users running multiple sessions with the agent at once, and often forking the threads.

610 640 

611- **Preserving the prefix**: Each turn appends new messages, tool calls, and results without rewriting earlier context, so the reusable prefix grows over time.641- **Preserving the prefix**: Each turn appends new messages, tool calls, and results without rewriting earlier context, so the reusable prefix grows over time.

612- **Prompt cache key:** The `prompt_cache_key` is defined for each user-agent pair, shared across that user's sessions with the agent. For example, `agent_123_v1:user_456` groups user 456's sessions and forks with agent 123. The session and thread IDs are kept out of the key when those sessions should share the same reusable prefix.642- **Optional prompt cache key:** This example uses `agent_123_v1:user_456` to maintain separate cache accounting for user 456, making their cached token usage and billing easier to explain. This also helps prevent cache-hit probing across users. The key stays the same across that user's sessions and forks with the agent. Omit it if your application does not need this separation.

613- **Implicit caching mode:** Implicit caching is enabled so the latest eligible user or tool message provides a breakpoint.643- **Implicit caching mode:** Implicit caching is enabled so the latest eligible user or tool message provides a breakpoint.

614- **Explicit breakpoints:** A breakpoint is added after each tool result to preserve earlier reusable prefixes and improve cache efficiency of forking.644- **Explicit breakpoints:** A breakpoint is added after each tool result to preserve earlier reusable prefixes and improve cache efficiency of forking.

615 645 

616An example deployment using these principles reported a **token cache-hit rate >90%**. This figure illustrates a possible outcome. Actual cache-hit rate ceilings will depend upon your own context and application usage.646An example deployment using these principles reported a **token cache-hit rate >90%**. This figure illustrates a possible outcome. Actual cache-hit rate ceilings will depend upon your context and application usage.

617 647 

618Responses API request for a multi-turn agent648Responses API request for a multi-turn agent

619 649 


672 702 

673 703 

674 704 

705<a id="a-shared-prefix-is-not-always-a-cached-prefix"></a>

706 

707 

708 

675### A shared prefix is not always a cached prefix709### A shared prefix is not always a cached prefix

676 710 

677 711 

678 712 

679This is particularly prevalent when migrating from earlier models to GPT-5.6 or later due to the change in implicit caching behaviour. If requests share a long prefix but have different suffixes, caching the first complete request implicitly-only does not make the shorter shared prefix reusable.713This is particularly prevalent when [migrating from earlier models to GPT-5.6 or later](#migrate-prompt-caching-from-an-earlier-model-to-gpt-5-6-and-later) due to the change in implicit caching behaviour. If requests share a long prefix but have different suffixes, caching the first complete request implicitly-only does not make the shorter shared prefix reusable.

680 714 

681Consider a static developer message followed by a dynamic user message in each request. This request writes through the dynamic content. Changing that content in the next request does not match the longer cached prefix, and there is no separate breakpoint after the static content.715Consider a static developer message followed by a dynamic user message in each request. This request writes through the dynamic content. Changing that content in the next request does not match the longer cached prefix, and there is no separate breakpoint after the static content.

682 716 


687 "model": "gpt-5.6-sol",721 "model": "gpt-5.6-sol",

688 "reasoning": { "effort": "medium", "context": "all_turns" },722 "reasoning": { "effort": "medium", "context": "all_turns" },

689 "text": { "verbosity": "low" },723 "text": { "verbosity": "low" },

690 "prompt_cache_key": "prompt_name_v1",

691 "prompt_cache_options": { "mode": "implicit" },724 "prompt_cache_options": { "mode": "implicit" },

692 "input": [725 "input": [

693 { "role": "developer", "content": "Static content..." },726 { "role": "developer", "content": "Static content..." },


706 "model": "gpt-5.6-sol",739 "model": "gpt-5.6-sol",

707 "reasoning": { "effort": "medium", "context": "all_turns" },740 "reasoning": { "effort": "medium", "context": "all_turns" },

708 "text": { "verbosity": "low" },741 "text": { "verbosity": "low" },

709 "prompt_cache_key": "prompt_name_v1",

710 "prompt_cache_options": { "mode": "explicit" },742 "prompt_cache_options": { "mode": "explicit" },

711 "input": [743 "input": [

712 {744 {


729 761 

730 762 

731 763 

764<a id="switching-to-explicit-only-mode-can-miss-an-implicit-cache-write"></a>

765 

766 

767 

768### Switching to explicit-only mode can miss an implicit cache write

769 

770 

771 

772Suppose request 1 uses implicit mode and caches a prefix through the end of a user message, then follow-up request 2 preserves that prefix but switches to `prompt_cache_options.mode: "explicit"`. As explained in [How prefix matching works](#how-prefix-matching-works), request 2 checks only the explicit breakpoints in its own input, so it will not reuse that saved implicit prefix from request 1 (unless one of the explicit breakpoints in request 2 matches the cached endpoint from request 1).

773 

774```text

775▼ = breakpoint

776 

777- Request 1: implicit mode

778 [Developer message][User message] ▼

779 

780- Request 2: explicit-only mode. Does not hit cache.

781 [Developer message][User message][Follow-up] ▼

782```

783 

784To reuse the implicit prefix from request 1, place an explicit breakpoint at the matching content-block boundary in request 2, or keep implicit mode enabled so the earlier eligible message ending remains a lookup candidate.

785 

786 

787 

788 

789 

790 

791 

792<a id="extending-a-message-can-prevent-reuse-of-its-cached-prefix"></a>

793 

794 

795 

796### Extending a message can prevent reuse of its cached prefix

797 

798 

799 

800Even when both requests use implicit mode, preserving the same initial tokens is not always enough. Suppose request 1 ends with a user message containing `Content A`, then follow-up request 2 extends that same message to `Content A + Content B`. The old endpoint after `Content A` is now inside a message, rather than at its end. As explained in [How prefix matching works](#how-prefix-matching-works), without an explicit breakpoint at that boundary, request 2 does not reuse the prefix saved there.

801 

802```text

803▼ = breakpoint

804 

805- Request 1: implicit mode

806 [Developer message][User message: Content A] ▼

807 

808- Request 2: implicit mode. Cannot reuse the prefix through Content A.

809 [Developer message][User message: Content A + Content B] ▼

810```

811 

812When the conversation structure permits, preserve the original message and append a new message instead. Otherwise, keep the reusable text in a separate content block and place an explicit breakpoint after it in both requests.

813 

814 

815 

816 

817 

818 

819 

820<a id="not-all-developer-messages-are-automatic-implicit-mode-cache-lookup-boundaries"></a>

821 

822 

823 

824### Not all developer messages are automatic implicit mode cache lookup boundaries

825 

826 

827 

828In implicit mode, developer messages after the initial consecutive block of developer messages are not automatic cache lookup boundaries. Add an explicit breakpoint at the end of the reusable developer message to preserve that breakpoint in subsequent requests so OpenAI can check for a matching cached prefix.

829 

830 

831 

832 

833 

834 

835 

836<a id="minimum-cacheable-length-varies-by-model"></a>

837 

838 

839 

732### Minimum cacheable length varies by model840### Minimum cacheable length varies by model

733 841 

734 842 


741 849 

742 850 

743 851 

852<a id="compaction-can-reduce-cache-reuse"></a>

853 

854 

855 

744### Compaction can reduce cache reuse856### Compaction can reduce cache reuse

745 857 

746 858 


757 869 

758 870 

759 871 

872<a id="does-prompt-caching-affect-output-generation"></a>

873 

874 

875 

760### Does prompt caching affect output generation?876### Does prompt caching affect output generation?

761 877 

762 878 


769 885 

770 886 

771 887 

888<a id="can-i-manually-clear-the-cache"></a>

889 

890 

891 

772### Can I manually clear the cache?892### Can I manually clear the cache?

773 893 

774 894 


781 901 

782 902 

783 903 

904<a id="do-cached-prompts-count-toward-rate-limits"></a>

905 

906 

907 

784### Do cached prompts count toward rate limits?908### Do cached prompts count toward rate limits?

785 909 

786 910 

Details

1# Prompt cache diagnostics

2 

3> For the complete documentation index, see [llms.txt](/llms.txt). Markdown versions of documentation pages are available by appending `.md` to the page URL.

4 

5Prompt cache diagnostics help explain why a request reused fewer tokens than expected. Compare a request with an earlier response to identify changes to the model, tools, settings, or input that prevented reuse.

6 

7Diagnostics are available in the Responses API for GPT-5.6 and later supported models. Use them to investigate individual requests, and use the [Prompt Caching Dashboard](https://platform.openai.com/usage?usage_section=prompt-caching) to monitor cache performance across your application.

8 

9<a id="compare-with-an-earlier-response"></a>

10 

11## How it works

12 

13Prompt cache diagnostics compare your current request with an earlier response to help explain why an expected prompt prefix wasn’t reused. A prefix is the content at the beginning of a prompt. Reuse requires an exact prefix match and compatible request settings, including the model, service tier, and tools.

14 

151. **Choose a baseline response.** Use a recent completed response from the same organization whose prefix you expect the current request to reuse, such as the preceding conversation turn.

162. **Request a comparison.** Set `prompt_cache_options.comparison_response_id` to the baseline response’s `id`.

173. **Read the result.** Check `prompt_cache_diagnostics` on the current response. If diagnostics identify a cache miss, the result includes a reason to help you investigate. Use `usage.input_tokens_details.cached_tokens` to measure actual cache reuse.

18 

19Setting `comparison_response_id` only requests diagnostics. It does not load the earlier conversation or change caching behavior. The current request can still reuse matching cache entries from other requests.

20 

21### Example usage

22 

23The following example sends two requests with the same model, instructions, and input, but changes a function tool's name from `get_time` to `get_date`. The second request compares cache reuse against the first.

24 

25Use your own policy document in `support-policy.txt`. The reusable prefix must meet the model's [minimum cacheable length](https://developers.openai.com/api/docs/guides/prompt-caching#summary-of-model-differences), which is 1,024 tokens for GPT-5.6 and later.

26 

27Compare prompt cache reuse between responses

28 

29```python

30from pathlib import Path

31 

32from openai import OpenAI

33 

34client = OpenAI()

35policy = Path("support-policy.txt").read_text() # At least 1,024 tokens.

36 

37first = client.responses.create(

38 model="gpt-6-astra",

39 instructions=policy,

40 input="Reply with exactly OK.",

41 tools=[{"type": "function", "name": "get_time"}],

42)

43 

44second = client.responses.create(

45 model="gpt-6-astra",

46 instructions=policy,

47 input="Reply with exactly OK.",

48 tools=[{"type": "function", "name": "get_date"}],

49 prompt_cache_options={"comparison_response_id": first.id},

50)

51 

52diagnostics = second.prompt_cache_diagnostics

53if diagnostics is not None and diagnostics.type == "cache_miss":

54 print(diagnostics.reason)

55 print(diagnostics.comparison_reusable_tokens)

56 print(diagnostics.cache_missed_tokens)

57```

58 

59 

60If the tool change causes a miss, the result may look like this. Token counts vary with the input.

61 

62```json

63{

64 "prompt_cache_diagnostics": {

65 "type": "cache_miss",

66 "reason": "tools_changed",

67 "comparison_reusable_tokens": 5629,

68 "cache_missed_tokens": 5629

69 }

70}

71```

72 

73To preserve reuse, keep tool definitions and ordering unchanged between requests. See [Manage tools with append-only updates](https://developers.openai.com/api/docs/guides/prompt-caching#manage-tools-with-append-only-updates).

74 

75### Multi-turn conversations

76 

77To compare consecutive turns, save each completed response's `id` and pass it as `comparison_response_id` in `prompt_cache_options` on the next request. Omit the comparison ID on the first turn.

78 

79When testing a fix, keep the comparison ID set to the baseline response.

80 

81### Streaming

82 

83When `stream=True`, read `prompt_cache_diagnostics` from `event.response` in the [`response.completed` event](https://developers.openai.com/api/reference/resources/responses/streaming-events#response.completed).

84 

85## Understand the response

86 

87Read `prompt_cache_diagnostics.type` to determine the comparison outcome.

88 

89 

90 

91 

92| Type | Meaning | What to do |

93| ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |

94| `cache_hit` | No cache miss was detected for the comparison. | Check `usage.input_tokens_details.cached_tokens` to measure actual reuse. |

95| `cache_miss` | A difference prevented reuse of the expected prefix. The result includes `reason` and `cache_missed_tokens`. It may also include `comparison_reusable_tokens`. | Find the reason and suggested fix in [Fix a cache miss](#fix-a-cache-miss). |

96| `comparison_response_not_found` | No usable diagnostic record is available for the comparison response. It may be missing or expired. | Select another recent completed response from the same organization. |

97| `unavailable` | The comparison could not produce a conclusive result, or the model does not support diagnostics. | Confirm model support and try another recent comparison. You can still use the response normally. |

98 

99 

100 

101 

102### Interpret token counts

103 

104A `cache_hit` means no cache miss was detected for the comparison. New input can still require processing. For example, a request with 2,500 input tokens can report `cache_hit` when it reuses the comparison response’s 2,000-token prefix and processes 500 new tokens.

105 

106For a `cache_miss`:

107 

108- `comparison_reusable_tokens`, when present, is the raw token count of the comparison response’s reusable prefix.

109- `cache_missed_tokens` estimates how many of those tokens were not reused.

110 

111These diagnostic counts can differ from usage counts. Use the current response’s usage fields to measure reported cache reuse and billing.

112 

113## Fix a cache miss

114 

115Use `prompt_cache_diagnostics.reason` to find the cause of a cache miss and a suggested fix in the following table.

116 

117Some changes, such as switching models or compacting a conversation, are intentional. You may choose to keep them even if they reduce cache reuse.

118 

119 

120 

121 

122| Reason | What changed | How to improve reuse |

123| -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

124| `model_changed` | A different model processed the request, for example because routing, an A/B test, or a fallback selected another model. | Check model selection for unintended switches. Use the same model for requests intended to share a cached prefix. See [cache-affecting settings](https://developers.openai.com/api/docs/guides/prompt-caching#which-settings-affect-the-cached-prefix). |

125| `prompt_cache_key_changed` | The supplied key changed between requests. This can be reported as a cache miss in response `usage` without a physical cache miss. | Omit `prompt_cache_key` unless your application needs separate cache accounting for customers or users. If you use keys, keep a stable key within each group. See [Separate cache accounting with keys](https://developers.openai.com/api/docs/guides/prompt-caching#separate-prompts-with-cache-keys). |

126| `service_tier_changed` | The service tier used to process the request changed. | Keep the service tier consistent for requests expected to share a prefix. Check the returned `service_tier`, which can differ from the requested value. See [`service_tier`](https://developers.openai.com/api/reference/resources/responses/methods/create#%28resource%29%20responses%20%3E%20%28method%29%20create%20%3E%20%28params%29%200.non_streaming%20%3E%20%28param%29%20service_tier%20%3E%20%28schema%29) for supported values and behavior. |

127| `tools_changed` | Tools were added, removed, or reordered, or their descriptions, schemas, or configuration changed. | Keep tool definitions and ordering stable. Use `tool_choice: "none"` to disable tools or `allowed_tools` to restrict which tools can run without changing the supplied tool list. See [Manage tools with append-only updates](https://developers.openai.com/api/docs/guides/prompt-caching#manage-tools-with-append-only-updates). |

128| `text_format_changed` | The output format or its schema changed. | Keep `text.format` and the schema consistent when the required output structure is unchanged. See [Structured Outputs](https://developers.openai.com/api/docs/guides/structured-outputs). |

129| `reasoning_effort_changed` | The reasoning effort changed. | Keep `reasoning.effort` consistent across requests intended to share a prefix. See [cache-affecting settings](https://developers.openai.com/api/docs/guides/prompt-caching#which-settings-affect-the-cached-prefix). |

130| `verbosity_changed` | The response verbosity changed. | Keep `text.verbosity` consistent across requests intended to share a prefix. See [cache-affecting settings](https://developers.openai.com/api/docs/guides/prompt-caching#which-settings-affect-the-cached-prefix). |

131| `context_compacted` | Compaction replaced earlier conversation content. | Preserve stable instructions and let later turns build on the compacted context. Compare total input cost: fewer input tokens can still save money despite lower cache reuse. See [Compaction](https://developers.openai.com/api/docs/guides/compaction). |

132| `input_changed` | Earlier input changed, for example because instructions contain a timestamp or request ID, or previous messages were edited, reordered, or removed. | Move changing content after the reusable prefix and its cache breakpoint. Preserve earlier messages and tool results, and append new turns. See [Preserve conversation history](https://developers.openai.com/api/docs/guides/prompt-caching#preserve-conversation-history). |

133 

134 

135 

136 

137## Confirm the improvement

138 

139After making a change:

140 

1411. Send another representative request and compare it with the intended baseline.

1422. Check the diagnostic result for any remaining difference.

1433. Compare `cached_tokens`, `cache_write_tokens`, and total cost across several requests.

144 

145See [Monitor cache performance](https://developers.openai.com/api/docs/guides/prompt-caching#monitor-cache-performance) for usage metrics and cost calculations.

146 

147## Pricing and rate limits

148 

149Prompt cache diagnostics have no additional cost and do not count separately toward rate limits. Any extra baseline or retry requests to the Responses API are billed normally and count toward rate limits.

150 

151## Zero Data Retention

152 

153Prompt cache diagnostics are compatible with Zero Data Retention. OpenAI does not store raw prompts or model outputs for this feature. Diagnostic records contain configuration metadata, token-count estimates, and hashes used to compare cache-sensitive content. These records are scoped to the organization, expire after a short period, and are used only to explain prompt-cache hits or misses.

154 

155Setting `comparison_response_id` does not retrieve or persist the earlier response's content. See [Your data](https://developers.openai.com/api/docs/guides/your-data) for OpenAI's data controls.

156 

157## Limitations

158 

159- Diagnostics are available in the Responses API for GPT-5.6 and later supported models.

160- Diagnostic records expire after a short period. An expired record returns `comparison_response_not_found`, even if the response is still available through the API.

161- Diagnostics report the first classified reason. Address it, then repeat the comparison to check for other causes.

162- Diagnostics are best effort and may not classify every miss. An `unavailable` result does not indicate a hit or miss and is returned if the comparison is not ready.

163- Diagnostics never block or fail your request or change how the model generates output.

Details

2181 .forEach(System.out::println);2181 .forEach(System.out::println);

2182```2182```

2183 2183 

2184```ruby

2185require "openai"

2186require "json"

2187 

2188META_SCHEMA = {

2189 "name" => "metaschema",

2190 "schema" => {

2191 "type" => "object",

2192 "properties" => {

2193 "name" => {

2194 "type" => "string",

2195 "description" => "The name of the schema"

2196 },

2197 "type" => {

2198 "type" => "string",

2199 "enum" => ["object", "array", "string", "number", "boolean", "null"]

2200 },

2201 "properties" => {

2202 "type" => "object",

2203 "additionalProperties" => {

2204 "$ref" => "#/$defs/schema_definition"

2205 }

2206 },

2207 "items" => {

2208 "anyOf" => [{

2209 "$ref" => "#/$defs/schema_definition"

2210 }, {

2211 "type" => "array",

2212 "items" => {

2213 "$ref" => "#/$defs/schema_definition"

2214 }

2215 }]

2216 },

2217 "required" => {

2218 "type" => "array",

2219 "items" => {

2220 "type" => "string"

2221 }

2222 },

2223 "additionalProperties" => {

2224 "type" => "boolean"

2225 }

2226 },

2227 "required" => ["type"],

2228 "additionalProperties" => false,

2229 "if" => {

2230 "properties" => {

2231 "type" => {

2232 "const" => "object"

2233 }

2234 }

2235 },

2236 "then" => {

2237 "required" => ["properties"]

2238 },

2239 "$defs" => {

2240 "schema_definition" => {

2241 "type" => "object",

2242 "properties" => {

2243 "type" => {

2244 "type" => "string",

2245 "enum" => ["object", "array", "string", "number", "boolean", "null"]

2246 },

2247 "properties" => {

2248 "type" => "object",

2249 "additionalProperties" => {

2250 "$ref" => "#/$defs/schema_definition"

2251 }

2252 },

2253 "items" => {

2254 "anyOf" => [{

2255 "$ref" => "#/$defs/schema_definition"

2256 }, {

2257 "type" => "array",

2258 "items" => {

2259 "$ref" => "#/$defs/schema_definition"

2260 }

2261 }]

2262 },

2263 "required" => {

2264 "type" => "array",

2265 "items" => {

2266 "type" => "string"

2267 }

2268 },

2269 "additionalProperties" => {

2270 "type" => "boolean"

2271 }

2272 },

2273 "required" => ["type"],

2274 "additionalProperties" => false,

2275 "if" => {

2276 "properties" => {

2277 "type" => {

2278 "const" => "object"

2279 }

2280 }

2281 },

2282 "then" => {

2283 "required" => ["properties"]

2284 }

2285 }

2286 }

2287 }

2288}

2289 

2290META_PROMPT = <<~PROMPT.strip

2291 # Instructions

2292 Return a valid schema for the described JSON.

2293 

2294 You must also make sure:

2295 - all fields in an object are set as required

2296 - I REPEAT, ALL FIELDS MUST BE MARKED AS REQUIRED

2297 - all objects must have additionalProperties set to false

2298 - because of this, some cases like "attributes" or "metadata" properties that would normally allow additional properties should instead have a fixed set of properties

2299 - all objects must have properties defined

2300 - field order matters. any form of "thinking" or "explanation" should come before the conclusion

2301 - $defs must be defined under the schema param

2302 

2303 Notable keywords NOT supported include:

2304 - For objects: unevaluatedProperties, propertyNames, minProperties, maxProperties

2305 - For arrays: unevaluatedItems, contains, minContains, maxContains, uniqueItems

2306 

2307 Other notes:

2308 - definitions and recursion are supported

2309 - only if necessary to include references e.g. "$defs", it must be inside the "schema" object

2310 

2311 # Examples

2312 Input: Generate a math reasoning schema with steps and a final answer.

2313 Output: {

2314 "name": "math_reasoning",

2315 "type": "object",

2316 "properties": {

2317 "steps": {

2318 "type": "array",

2319 "description": "A sequence of steps involved in solving the math problem.",

2320 "items": {

2321 "type": "object",

2322 "properties": {

2323 "explanation": {

2324 "type": "string",

2325 "description": "Description of the reasoning or method used in this step."

2326 },

2327 "output": {

2328 "type": "string",

2329 "description": "Result or outcome of this specific step."

2330 }

2331 },

2332 "required": [

2333 "explanation",

2334 "output"

2335 ],

2336 "additionalProperties": false

2337 }

2338 },

2339 "final_answer": {

2340 "type": "string",

2341 "description": "The final solution or answer to the math problem."

2342 }

2343 },

2344 "required": [

2345 "steps",

2346 "final_answer"

2347 ],

2348 "additionalProperties": false

2349 }

2350 

2351 Input: Give me a linked list

2352 Output: {

2353 "name": "linked_list",

2354 "type": "object",

2355 "properties": {

2356 "linked_list": {

2357 "$ref": "#/$defs/linked_list_node",

2358 "description": "The head node of the linked list."

2359 }

2360 },

2361 "$defs": {

2362 "linked_list_node": {

2363 "type": "object",

2364 "description": "Defines a node in a singly linked list.",

2365 "properties": {

2366 "value": {

2367 "type": "number",

2368 "description": "The value stored in this node."

2369 },

2370 "next": {

2371 "anyOf": [

2372 {

2373 "$ref": "#/$defs/linked_list_node"

2374 },

2375 {

2376 "type": "null"

2377 }

2378 ],

2379 "description": "Reference to the next node; null if it is the last node."

2380 }

2381 },

2382 "required": [

2383 "value",

2384 "next"

2385 ],

2386 "additionalProperties": false

2387 }

2388 },

2389 "required": [

2390 "linked_list"

2391 ],

2392 "additionalProperties": false

2393 }

2394 

2395 Input: Dynamically generated UI

2396 Output: {

2397 "name": "ui",

2398 "type": "object",

2399 "properties": {

2400 "type": {

2401 "type": "string",

2402 "description": "The type of the UI component",

2403 "enum": [

2404 "div",

2405 "button",

2406 "header",

2407 "section",

2408 "field",

2409 "form"

2410 ]

2411 },

2412 "label": {

2413 "type": "string",

2414 "description": "The label of the UI component, used for buttons or form fields"

2415 },

2416 "children": {

2417 "type": "array",

2418 "description": "Nested UI components",

2419 "items": {

2420 "$ref": "#"

2421 }

2422 },

2423 "attributes": {

2424 "type": "array",

2425 "description": "Arbitrary attributes for the UI component, suitable for any element",

2426 "items": {

2427 "type": "object",

2428 "properties": {

2429 "name": {

2430 "type": "string",

2431 "description": "The name of the attribute, for example onClick or className"

2432 },

2433 "value": {

2434 "type": "string",

2435 "description": "The value of the attribute"

2436 }

2437 },

2438 "required": [

2439 "name",

2440 "value"

2441 ],

2442 "additionalProperties": false

2443 }

2444 }

2445 },

2446 "required": [

2447 "type",

2448 "label",

2449 "children",

2450 "attributes"

2451 ],

2452 "additionalProperties": false

2453 }

2454PROMPT

2455 

2456client = OpenAI::Client.new

2457completion = client.chat.completions.create(

2458 model: "gpt-5.6-terra",

2459 response_format: {type: :json_schema, json_schema: META_SCHEMA},

2460 messages: [

2461 {role: :system, content: META_PROMPT},

2462 {role: :user, content: "Description: Schedule a meeting with a title and start time."}

2463 ]

2464)

2465message = completion.choices.fetch(0).message

2466raise "Schema generation refused: #{message.refusal}" if message.refusal

2467puts(JSON.pretty_generate(JSON.parse(message.content || raise("No schema returned"))))

2468```

2469 

2184 2470

2185 2471 

2186 2472


2840 .flatMap(choice -> choice.message().content().stream())3126 .flatMap(choice -> choice.message().content().stream())

2841 .forEach(System.out::println);3127 .forEach(System.out::println);

2842```3128```

3129 

3130```ruby

3131require "openai"

3132require "json"

3133 

3134META_SCHEMA = {

3135 "name" => "function-metaschema",

3136 "schema" => {

3137 "type" => "object",

3138 "properties" => {

3139 "name" => {

3140 "type" => "string",

3141 "description" => "The name of the function"

3142 },

3143 "description" => {

3144 "type" => "string",

3145 "description" => "A description of what the function does"

3146 },

3147 "parameters" => {

3148 "$ref" => "#/$defs/schema_definition",

3149 "description" => "A JSON schema that defines the function's parameters"

3150 }

3151 },

3152 "required" => ["name", "description", "parameters"],

3153 "additionalProperties" => false,

3154 "$defs" => {

3155 "schema_definition" => {

3156 "type" => "object",

3157 "properties" => {

3158 "type" => {

3159 "type" => "string",

3160 "enum" => ["object", "array", "string", "number", "boolean", "null"]

3161 },

3162 "properties" => {

3163 "type" => "object",

3164 "additionalProperties" => {

3165 "$ref" => "#/$defs/schema_definition"

3166 }

3167 },

3168 "items" => {

3169 "anyOf" => [{

3170 "$ref" => "#/$defs/schema_definition"

3171 }, {

3172 "type" => "array",

3173 "items" => {

3174 "$ref" => "#/$defs/schema_definition"

3175 }

3176 }]

3177 },

3178 "required" => {

3179 "type" => "array",

3180 "items" => {

3181 "type" => "string"

3182 }

3183 },

3184 "additionalProperties" => {

3185 "type" => "boolean"

3186 }

3187 },

3188 "required" => ["type"],

3189 "additionalProperties" => false,

3190 "if" => {

3191 "properties" => {

3192 "type" => {

3193 "const" => "object"

3194 }

3195 }

3196 },

3197 "then" => {

3198 "required" => ["properties"]

3199 }

3200 }

3201 }

3202 }

3203}

3204 

3205META_PROMPT = <<~PROMPT.strip

3206 # Instructions

3207 Return a valid schema for the described function.

3208 

3209 Pay special attention to making sure that "required" and "type" are always at the correct level of nesting. For example, "required" should be at the same level as "properties", not inside it.

3210 Make sure that every property, no matter how short, has a type and description correctly nested inside it.

3211 

3212 # Examples

3213 Input: Assign values to NN hyperparameters

3214 Output: {

3215 "name": "set_hyperparameters",

3216 "description": "Assign values to NN hyperparameters",

3217 "parameters": {

3218 "type": "object",

3219 "required": [

3220 "learning_rate",

3221 "epochs"

3222 ],

3223 "properties": {

3224 "epochs": {

3225 "type": "number",

3226 "description": "Number of complete passes through dataset"

3227 },

3228 "learning_rate": {

3229 "type": "number",

3230 "description": "Speed of model learning"

3231 }

3232 }

3233 }

3234 }

3235 

3236 Input: Plans a motion path for the robot

3237 Output: {

3238 "name": "plan_motion",

3239 "description": "Plans a motion path for the robot",

3240 "parameters": {

3241 "type": "object",

3242 "required": [

3243 "start_position",

3244 "end_position"

3245 ],

3246 "properties": {

3247 "end_position": {

3248 "type": "object",

3249 "properties": {

3250 "x": {

3251 "type": "number",

3252 "description": "End X coordinate"

3253 },

3254 "y": {

3255 "type": "number",

3256 "description": "End Y coordinate"

3257 }

3258 }

3259 },

3260 "obstacles": {

3261 "type": "array",

3262 "description": "Array of obstacle coordinates",

3263 "items": {

3264 "type": "object",

3265 "properties": {

3266 "x": {

3267 "type": "number",

3268 "description": "Obstacle X coordinate"

3269 },

3270 "y": {

3271 "type": "number",

3272 "description": "Obstacle Y coordinate"

3273 }

3274 }

3275 }

3276 },

3277 "start_position": {

3278 "type": "object",

3279 "properties": {

3280 "x": {

3281 "type": "number",

3282 "description": "Start X coordinate"

3283 },

3284 "y": {

3285 "type": "number",

3286 "description": "Start Y coordinate"

3287 }

3288 }

3289 }

3290 }

3291 }

3292 }

3293 

3294 Input: Calculates various technical indicators

3295 Output: {

3296 "name": "technical_indicator",

3297 "description": "Calculates various technical indicators",

3298 "parameters": {

3299 "type": "object",

3300 "required": [

3301 "ticker",

3302 "indicators"

3303 ],

3304 "properties": {

3305 "indicators": {

3306 "type": "array",

3307 "description": "List of technical indicators to calculate",

3308 "items": {

3309 "type": "string",

3310 "description": "Technical indicator",

3311 "enum": [

3312 "RSI",

3313 "MACD",

3314 "Bollinger_Bands",

3315 "Stochastic_Oscillator"

3316 ]

3317 }

3318 },

3319 "period": {

3320 "type": "number",

3321 "description": "Time period for the analysis"

3322 },

3323 "ticker": {

3324 "type": "string",

3325 "description": "Stock ticker symbol"

3326 }

3327 }

3328 }

3329 }

3330PROMPT

3331 

3332client = OpenAI::Client.new

3333completion = client.chat.completions.create(

3334 model: "gpt-5.6-terra",

3335 response_format: {type: :json_schema, json_schema: META_SCHEMA},

3336 messages: [

3337 {role: :system, content: META_PROMPT},

3338 {role: :user, content: "Description: Schedule a meeting with a title and start time."}

3339 ]

3340)

3341message = completion.choices.fetch(0).message

3342raise "Schema generation refused: #{message.refusal}" if message.refusal

3343puts(JSON.pretty_generate(JSON.parse(message.content || raise("No schema returned"))))

3344```

Details

123 123 

124Connect to the dedicated translation endpoint and select the model in the URL:124Connect to the dedicated translation endpoint and select the model in the URL:

125 125 

126Install the `ws` package for Node.js or the `websocket-client` package for Python before running this example.126Before running this example, install `ws` for Node.js, `websocket-client` for Python, or `async-websocket` for Ruby (`gem install async-websocket`).

127 127 

128Connect to a translation session128Connect to a translation session

129 129 


155)155)

156```156```

157 157 

158```ruby

159require "async"

160require "async/http/endpoint"

161require "async/websocket/client"

162require "json"

163 

164endpoint = Async::HTTP::Endpoint.parse("wss://api.openai.com/v1/realtime/translations?model=gpt-realtime-translate", timeout: 10, alpn_protocols: ["http/1.1"])

165headers = {"Authorization" => "Bearer #{ENV.fetch("OPENAI_API_KEY")}", "OpenAI-Safety-Identifier" => "hashed-user-id"}

166Sync do |task|

167 task.with_timeout(120) do

168 Async::WebSocket::Client.connect(endpoint, headers: headers) do |connection|

169 message = connection.read or raise "Connection closed before session creation"

170 event = JSON.parse(message.to_str)

171 raise "Expected session.created: #{event}" unless event["type"] == "session.created"

172 puts(event.fetch("type"))

173 end

174 end

175end

176```

177 

178 

179For Ruby, insert the following configuration and audio-append snippets inside the `Async::WebSocket::Client.connect` block, after the session-created check and before the block ends. Keep the connection open while sending audio and receiving translation events.

158 180 

159Configure the target language after the socket opens:181Configure the target language after the socket opens:

160 182 


196)218)

197```219```

198 220 

221```ruby

222connection.write(JSON.generate(type: "session.update", session: {audio: {output: {language: "es"}}}))

223connection.flush

224```

225 

199 226 

200Then append audio continuously:227Then append audio continuously:

201 228 


221)248)

222```249```

223 250 

251```ruby

252require "base64"

253 

254File.open("speech.pcm", "rb") do |audio|

255 while (chunk = audio.read(4_800))

256 connection.write(JSON.generate(type: "session.input_audio_buffer.append", audio: Base64.strict_encode64(chunk)))

257 connection.flush

258 end

259end

260```

261 

224 262 

225Listen for translated audio and transcripts:263Listen for translated audio and transcripts:

226 264 

Details

35The private MCP server does not need a public listener. The OpenAI-hosted endpoint gives supported products a normal MCP request path, while the network initiation point stays inside your boundary. When a connector asks for streamed results, the tunnel path can forward intermediate server-sent events.35The private MCP server does not need a public listener. The OpenAI-hosted endpoint gives supported products a normal MCP request path, while the network initiation point stays inside your boundary. When a connector asks for streamed results, the tunnel path can forward intermediate server-sent events.

36 36 

37<figure className="not-prose my-8">37<figure className="not-prose my-8">

38

39 

40![Diagram showing an OpenAI product sending MCP JSON-RPC through the OpenAI tunnel service to tunnel-client, which forwards the request to a private MCP server and returns the response through the same tunnel.](<https://developers.openai.com/images/platform/guides/secure-mcp-tunnels/request-flow-diagram.png>)

41 

42 

38 <figcaption className="mt-3 text-sm text-gray-600 dark:text-gray-400">43 <figcaption className="mt-3 text-sm text-gray-600 dark:text-gray-400">

39 OpenAI products call the OpenAI-hosted tunnel endpoint; `tunnel-client`44 OpenAI products call the OpenAI-hosted tunnel endpoint; `tunnel-client`

40 long-polls for queued work and returns the MCP response through the same45 long-polls for queued work and returns the MCP response through the same


108Keep `tunnel-client run ...` healthy while you create or test the app. App discovery and MCP tool calls depend on the running client.113Keep `tunnel-client run ...` healthy while you create or test the app. App discovery and MCP tool calls depend on the running client.

109 114 

110<figure className="not-prose my-8">115<figure className="not-prose my-8">

116

117 

118![Live local tunnel-client admin UI showing health, readiness, tunnel metadata, and channel status.](<https://developers.openai.com/images/platform/guides/secure-mcp-tunnels/tunnel-client-admin-ui.png>)

119 

120 

111 <figcaption className="mt-3 text-sm text-gray-600 dark:text-gray-400">121 <figcaption className="mt-3 text-sm text-gray-600 dark:text-gray-400">

112 The local admin UI at `/ui` shows whether the running client is122 The local admin UI at `/ui` shows whether the running client is

113 healthy, ready, and connected before you test from ChatGPT, Codex, or an API123 healthy, ready, and connected before you test from ChatGPT, Codex, or an API


129 139 

130If the tunnel does not appear in ChatGPT, verify that the tunnel is associated with the target ChatGPT workspace, not only with a Platform organization, and that the app creator has Tunnels **Read** + **Use**.140If the tunnel does not appear in ChatGPT, verify that the tunnel is associated with the target ChatGPT workspace, not only with a Platform organization, and that the app creator has Tunnels **Read** + **Use**.

131 141 

142## Connect from the Responses API

143 

144Pass the tunnel identifier as `tunnel_id` in the MCP tool definition. Do not pass the OpenAI-hosted tunnel endpoint as `server_url`; use `server_url` only for an MCP server that the Responses API can reach directly.

145 

146Use Secure MCP Tunnel with the Responses API

147 

148```bash

149curl https://api.openai.com/v1/responses \

150 -H "Content-Type: application/json" \

151 -H "Authorization: Bearer $OPENAI_API_KEY" \

152 -d '{

153 "model": "gpt-6-astra",

154 "input": "Use the private MCP server to answer my request.",

155 "tools": [

156 {

157 "type": "mcp",

158 "server_label": "private_mcp",

159 "tunnel_id": "tunnel_0123456789abcdef0123456789abcdef"

160 }

161 ]

162 }'

163```

164 

165 

132## Security and networking166## Security and networking

133 167 

134<figure className="not-prose my-8">168<figure className="not-prose my-8">

169

170 

171![Diagram showing tunnel-client inside the customer-controlled environment connecting outbound to the OpenAI-managed tunnel control plane while the private MCP server remains inside the customer network.](<https://developers.openai.com/images/platform/guides/secure-mcp-tunnels/trust-boundaries-diagram.png>)

172 

173 

135 <figcaption className="mt-3 text-sm text-gray-600 dark:text-gray-400">174 <figcaption className="mt-3 text-sm text-gray-600 dark:text-gray-400">

136 The private MCP server stays inside the customer-controlled environment.175 The private MCP server stays inside the customer-controlled environment.

137 `tunnel-client` reaches OpenAI over outbound HTTPS using the runtime API key176 `tunnel-client` reaches OpenAI over outbound HTTPS using the runtime API key

Details

298}298}

299```299```

300 300 

301```ruby

302require "async"

303require "async/http/endpoint"

304require "async/websocket/client"

305require "json"

306 

307endpoint = Async::HTTP::Endpoint.parse("wss://api.openai.com/v1/responses", timeout: 10, alpn_protocols: ["http/1.1"])

308headers = {"Authorization" => "Bearer #{ENV.fetch("OPENAI_API_KEY")}"}

309Sync do |task|

310 task.with_timeout(120) do

311 Async::WebSocket::Client.connect(endpoint, headers: headers) do |connection|

312 connection.write(JSON.generate(

313 type: "response.create", model: "gpt-6-astra", reasoning: {effort: "medium"},

314 input: "Draft a project plan for building a task-tracking app."

315 ))

316 connection.flush

317 state = {}

318 while (message = connection.read)

319 event = JSON.parse(message.to_str)

320 response = event["response"]

321 case event.fetch("type")

322 when "response.created"

323 if !state[:initial_id]

324 state[:initial_id] = response.fetch("id")

325 connection.write(JSON.generate(

326 type: "response.steer", previous_response_id: state[:initial_id],

327 input: "Keep the scope small enough for one developer to finish in two weeks."

328 ))

329 connection.flush

330 else

331 state[:successor_id] = response.fetch("id")

332 end

333 when "response.steer.failed", "response.failed", "error"

334 raise "Steering failed: #{JSON.generate(event)}"

335 when "response.incomplete"

336 unless response.fetch("id") == state[:initial_id] && response.dig("incomplete_details", "reason") == "steered"

337 raise "Response incomplete: #{JSON.generate(event)}"

338 end

339 when "response.completed"

340 next unless state[:successor_id] && response.fetch("id") == state[:successor_id]

341 response.fetch("output").each do |item|

342 next unless item["type"] == "message"

343 item.fetch("content").each { |part| puts(part.fetch("text")) if part["type"] == "output_text" }

344 end

345 state[:completed] = true

346 break

347 end

348 end

349 raise "Connection closed before the steered response finished" unless state[:completed]

350 end

351 end

352end

353```

354 

301 355 

302The example sends the update after the first `response.created` event. In your application, send it when a user supplies an update. Use the continuation's ID for new steering once its `response.created` event arrives.356The example sends the update after the first `response.created` event. In your application, send it when a user supplies an update. Use the continuation's ID for new steering once its `response.created` event arrives.

303 357 

Details

511 511 

512**Realtime API example**512**Realtime API example**

513 513 

514For Ruby, set `OPENAI_VOICE_ID` to your custom voice ID before running the example.

515 

514```javascript516```javascript

515const sessionConfig = JSON.stringify({517const sessionConfig = JSON.stringify({

516 session: {518 session: {


525});527});

526```528```

527 529 

530```ruby

531require "json"

532 

533session_config = JSON.generate(

534 session: {

535 type: "realtime",

536 model: "gpt-realtime-2",

537 audio: {output: {voice: {id: ENV.fetch("OPENAI_VOICE_ID")}}}

538 }

539)

540puts(session_config)

541```

542 

528 543 

529## Related guides544## Related guides

530 545 

Details

43 43 

44### Connect your own runtime44### Connect your own runtime

45 45 

46The following example shows the API loop for a runtime you provide. Python uses PyAutoGUI to operate a desktop; JavaScript uses Playwright to operate a browser. Both expose an ordinary function tool and return text or images with the original `call_id`.46The following example shows the API loop for a runtime you provide. Python and Ruby send Python code to a desktop runtime that uses PyAutoGUI; JavaScript uses Playwright to operate a browser. Each client exposes an ordinary function tool and returns text or images with the original `call_id`.

47 47 

48The `execute_in_sandbox` or `executeInSandbox` helper sends code to your execution environment and returns its observations. It must preserve the browser or desktop session, enforce execution limits, and apply your permission rules. These are integration examples, separate from running the sample app.48The `execute_in_sandbox` or `executeInSandbox` helper sends code to your execution environment and returns its observations. It must preserve the browser or desktop session, enforce execution limits, and apply your permission rules. These are integration examples, separate from running the sample app.

49 49 


216 216 

217 217

218 218 

219

220 

221

222Ruby

223 

224 Run computer use with code execution

225 

226```ruby

227require "json"

228require "openai"

229require "securerandom"

230 

231def run_computer_use(endpoint, prompt)

232 client = OpenAI::Client.new

233 session_id = SecureRandom.uuid

234 tools = [{

235 type: :function, name: "exec_py",

236 description: "Run Python in a persistent desktop. Variables persist across calls. PyAutoGUI operations are synchronous. Available: pyautogui, time, log(value), and display(PIL_image). Inspect the screen with display(pyautogui.screenshot()) before acting. Use screenshot coordinates and check the screen after a short group of actions. Keep screenshots in memory and PyAutoGUI's fail-safe enabled.",

237 parameters: {type: :object, properties: {code: {type: :string}}, required: ["code"], additionalProperties: false},

238 strict: true

239 }]

240 next_input = []

241 next_input << {role: :user, content: prompt}

242 history = {}

243 20.times do |turn|

244 response = client.responses.create(

245 model: "gpt-6-astra", tools: tools, input: next_input, previous_response_id: history[:id]

246 )

247 raise "Response stopped with status: #{response.status}" unless response.status == OpenAI::Responses::ResponseStatus::COMPLETED

248 calls = response.output.grep(OpenAI::Responses::ResponseFunctionToolCall)

249 if calls.empty? && response.output.any? { |item| item.is_a?(OpenAI::Responses::ResponseOutputMessage) && item.phase != :commentary }

250 puts(response.output_text)

251 return response

252 end

253 raise "The task reached the 20-response limit" if turn == 19

254 next_input.clear

255 calls.each do |call|

256 raise "Unexpected tool: #{call.name}" unless call.name == "exec_py"

257 code = JSON.parse(call.arguments).fetch("code")

258 raise "Expected Python source text" unless code.is_a?(String)

259 output = execute_in_sandbox(code, session_id, endpoint)

260 next_input << {type: :function_call_output, call_id: call.call_id, output: output}

261 end

262 history[:id] = response.id

263 end

264end

265```

266 

267 

268 

219<a id="connect-to-your-execution-service"></a>269<a id="connect-to-your-execution-service"></a>

220 270 

221For a complete client adapter and the expected text and image output shape, see [Connect to your execution service](https://developers.openai.com/api/docs/guides/tools-computer-use-integration#connect-to-your-execution-service). The service interface in those examples belongs to your application; it is not an OpenAI-hosted endpoint.271For a complete client adapter and the expected text and image output shape, see [Connect to your execution service](https://developers.openai.com/api/docs/guides/tools-computer-use-integration#connect-to-your-execution-service). The service interface in those examples belongs to your application; it is not an OpenAI-hosted endpoint.

Details

2010 return observations2010 return observations

2011```2011```

2012 2012 

2013```ruby

2014require "net/http"

2015 

2016def execute_in_sandbox(code, session_id, endpoint)

2017 puts(code)

2018 print("Run this code in the isolated runtime? Type yes: ")

2019 unless $stdin.gets&.strip == "yes"

2020 return [{type: "input_text", text: "The user declined this execution."}]

2021 end

2022 uri = URI(endpoint)

2023 request = Net::HTTP::Post.new(uri)

2024 request["Content-Type"] = "application/json"

2025 token = ENV["OPENAI_EXAMPLE_CODE_EXECUTION_TOKEN"]

2026 request["Authorization"] = "Bearer #{token}" if token

2027 request.body = JSON.generate(session_id: session_id, language: "python", code: code)

2028 response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https", open_timeout: 10, read_timeout: 30) do |http|

2029 http.request(request)

2030 end

2031 response.value

2032 payload = JSON.parse(response.body)

2033 output = payload.is_a?(Hash) && payload["output"]

2034 raise "The execution service returned no observations" unless output.is_a?(Array) && !output.empty?

2035 output.map do |item|

2036 raise "Invalid execution-service output item" unless item.is_a?(Hash)

2037 if item["type"] == "input_text" && item["text"].is_a?(String)

2038 {type: "input_text", text: item["text"]}

2039 elsif item["type"] == "input_image" && item["image_url"].is_a?(String) && item["detail"] == "original"

2040 {type: "input_image", image_url: item["image_url"], detail: "original"}

2041 else

2042 raise "Expected input_text or input_image with original detail"

2043 end

2044 end

2045end

2046```

2047 

2013 2048 

2014Combine the adapter with the [API loop](https://developers.openai.com/api/docs/guides/tools-computer-use#connect-your-own-runtime), then call `run_computer_use` in Python or `runComputerUse` in JavaScript with your endpoint and task. The loop preserves the runtime session and uses `previous_response_id` to continue the model conversation. It stops after 20 responses if the task has not finished.2049Combine the adapter with the [API loop](https://developers.openai.com/api/docs/guides/tools-computer-use#connect-your-own-runtime), then call `run_computer_use` in Python or `runComputerUse` in JavaScript with your endpoint and task. The loop preserves the runtime session and uses `previous_response_id` to continue the model conversation. It stops after 20 responses if the task has not finished.

2015 2050 

Details

2 2 

3> For the complete documentation index, see [llms.txt](/llms.txt). Markdown versions of documentation pages are available by appending `.md` to the page URL.3> For the complete documentation index, see [llms.txt](/llms.txt). Markdown versions of documentation pages are available by appending `.md` to the page URL.

4 4 

5The image generation tool allows you to generate images using a text prompt, and optionally image inputs. It uses GPT Image models, including `gpt-image-2`, `gpt-image-1.5`, `gpt-image-1`, and `gpt-image-1-mini`, and automatically optimizes text inputs for improved performance.5The image generation tool allows you to generate images using a text prompt, and optionally image inputs. It uses GPT Image models, including `gpt-image-2.5-sunburst`, `gpt-image-2.5-flare`, `gpt-image-2`, `gpt-image-1.5`, `gpt-image-1`, and `gpt-image-1-mini`, and automatically optimizes text inputs for improved performance.

6 

7Set the `image_generation` tool's `model` to `gpt-image-2.5-sunburst` for precise editing, or `gpt-image-2.5-flare` for fast, high-quality image generation. Use a supported mainline model in the top-level Responses `model` field.

6 8 

7To learn more about image generation, refer to our dedicated [image generation9To learn more about image generation, refer to our dedicated [image generation

8 guide](https://developers.openai.com/api/docs/guides/image-generation?api=responses).10 guide](https://developers.openai.com/api/docs/guides/image-generation?api=responses).


23 model: "gpt-6-astra",25 model: "gpt-6-astra",

24 input:26 input:

25 "Generate an image of gray tabby cat hugging an otter with an orange scarf",27 "Generate an image of gray tabby cat hugging an otter with an orange scarf",

26 tools: [{ type: "image_generation" }],28 tools: [{ type: "image_generation", model: "gpt-image-2.5-sunburst" }],

27});29});

28 30 

29// Save the image to a file31// Save the image to a file


47response = client.responses.create(49response = client.responses.create(

48 model="gpt-6-astra",50 model="gpt-6-astra",

49 input="Generate an image of gray tabby cat hugging an otter with an orange scarf",51 input="Generate an image of gray tabby cat hugging an otter with an orange scarf",

50 tools=[{"type": "image_generation"}],52 tools=[{"type": "image_generation", "model": "gpt-image-2.5-sunburst"}],

51)53)

52 54 

53# Save the image to a file55# Save the image to a file


82 Input: responses.ResponseNewParamsInputUnion{84 Input: responses.ResponseNewParamsInputUnion{

83 OfString: openai.String("Generate an image of gray tabby cat hugging an otter with an orange scarf"),85 OfString: openai.String("Generate an image of gray tabby cat hugging an otter with an orange scarf"),

84 },86 },

85 Tools: []responses.ToolUnionParam{{OfImageGeneration: &responses.ToolImageGenerationParam{}}},87 Tools: []responses.ToolUnionParam{{OfImageGeneration: &responses.ToolImageGenerationParam{Model: "gpt-image-2.5-sunburst"}}},

86 })88 })

87 if err != nil {89 if err != nil {

88 panic(err)90 panic(err)


147 "Generate an image of a gray tabby cat hugging an otter with an orange scarf."149 "Generate an image of a gray tabby cat hugging an otter with an orange scarf."

148 )150 )

149);151);

150options.Tools.Add(ResponseTool.CreateImageGenerationTool(model: "gpt-image-2"));152options.Tools.Add(ResponseTool.CreateImageGenerationTool(model: "gpt-image-2.5-sunburst"));

151 153 

152ResponseResult response = await client.CreateResponseAsync(options);154ResponseResult response = await client.CreateResponseAsync(options);

153ImageGenerationCallResponseItem image = response155ImageGenerationCallResponseItem image = response


165response = client.responses.create(167response = client.responses.create(

166 model: "gpt-6-astra",168 model: "gpt-6-astra",

167 input: "Generate an image of a gray tabby cat hugging an otter with an orange scarf.",169 input: "Generate an image of a gray tabby cat hugging an otter with an orange scarf.",

168 tools: [{type: :image_generation}]170 tools: [{type: :image_generation, model: "gpt-image-2.5-sunburst"}]

169)171)

170 172 

171image_call = response.output.find do |item|173image_call = response.output.find do |item|


197 199 

198`size`, `quality`, and `background` support the `auto` option, where the model will automatically select the best option based on the prompt.200`size`, `quality`, and `background` support the `auto` option, where the model will automatically select the best option based on the prompt.

199 201 

200`gpt-image-2` supports flexible `size` values that meet its [resolution constraints](https://developers.openai.com/api/docs/guides/image-generation#size-and-quality-options). Transparent backgrounds are available in preview; set `background: "transparent"` to request one. Use `png` (the default) or `webp`; `jpeg` isn't supported with transparent backgrounds.202For `gpt-image-2.5-sunburst` and `gpt-image-2.5-flare`, `quality` also accepts `xhigh` and `max`. These values are not supported by earlier GPT Image models. The default quality remains `auto`.

203 

204`gpt-image-2` supports flexible `size` values that meet its [resolution constraints](https://developers.openai.com/api/docs/guides/image-generation#earlier-gpt-image-models). Transparent backgrounds are available in preview; set `background: "transparent"` to request one. Use `png` (the default) or `webp`; `jpeg` isn't supported with transparent backgrounds.

201 205 

202For more details on available options, refer to the [image generation guide](https://developers.openai.com/api/docs/guides/image-generation#customize-image-output).206For more details on available options, refer to the [image generation guide](https://developers.openai.com/api/docs/guides/image-generation#customize-image-output).

203 207 


243 model: "gpt-6-astra",247 model: "gpt-6-astra",

244 input:248 input:

245 "Generate an image of gray tabby cat hugging an otter with an orange scarf",249 "Generate an image of gray tabby cat hugging an otter with an orange scarf",

246 tools: [{ type: "image_generation" }],250 tools: [{ type: "image_generation", model: "gpt-image-2.5-sunburst" }],

247});251});

248 252 

249const imageData = response.output253const imageData = response.output


262 model: "gpt-6-astra",266 model: "gpt-6-astra",

263 previous_response_id: response.id,267 previous_response_id: response.id,

264 input: "Now make it look realistic",268 input: "Now make it look realistic",

265 tools: [{ type: "image_generation" }],269 tools: [{ type: "image_generation", model: "gpt-image-2.5-sunburst" }],

266});270});

267 271 

268const imageData_fwup = response_fwup.output272const imageData_fwup = response_fwup.output


288response = client.responses.create(292response = client.responses.create(

289 model="gpt-6-astra",293 model="gpt-6-astra",

290 input="Generate an image of gray tabby cat hugging an otter with an orange scarf",294 input="Generate an image of gray tabby cat hugging an otter with an orange scarf",

291 tools=[{"type": "image_generation"}],295 tools=[{"type": "image_generation", "model": "gpt-image-2.5-sunburst"}],

292)296)

293 297 

294image_data = [298image_data = [


310 model="gpt-6-astra",314 model="gpt-6-astra",

311 previous_response_id=response.id,315 previous_response_id=response.id,

312 input="Now make it look realistic",316 input="Now make it look realistic",

313 tools=[{"type": "image_generation"}],317 tools=[{"type": "image_generation", "model": "gpt-image-2.5-sunburst"}],

314)318)

315 319 

316image_data_fwup = [320image_data_fwup = [


344 Input: responses.ResponseNewParamsInputUnion{348 Input: responses.ResponseNewParamsInputUnion{

345 OfString: openai.String("Generate an image of gray tabby cat hugging an otter with an orange scarf"),349 OfString: openai.String("Generate an image of gray tabby cat hugging an otter with an orange scarf"),

346 },350 },

347 Tools: []responses.ToolUnionParam{{OfImageGeneration: &responses.ToolImageGenerationParam{}}},351 Tools: []responses.ToolUnionParam{{OfImageGeneration: &responses.ToolImageGenerationParam{Model: "gpt-image-2.5-sunburst"}}},

348 })352 })

349 if err != nil {353 if err != nil {

350 panic(err)354 panic(err)


357 Input: responses.ResponseNewParamsInputUnion{361 Input: responses.ResponseNewParamsInputUnion{

358 OfString: openai.String("Now make it look realistic"),362 OfString: openai.String("Now make it look realistic"),

359 },363 },

360 Tools: []responses.ToolUnionParam{{OfImageGeneration: &responses.ToolImageGenerationParam{}}},364 Tools: []responses.ToolUnionParam{{OfImageGeneration: &responses.ToolImageGenerationParam{Model: "gpt-image-2.5-sunburst"}}},

361 })365 })

362 if err != nil {366 if err != nil {

363 panic(err)367 panic(err)


448ResponsesClient client = new(key);452ResponsesClient client = new(key);

449 453 

450CreateResponseOptions options = new() { Model = "gpt-6-astra" };454CreateResponseOptions options = new() { Model = "gpt-6-astra" };

451options.Tools.Add(ResponseTool.CreateImageGenerationTool(model: "gpt-image-2"));455options.Tools.Add(ResponseTool.CreateImageGenerationTool(model: "gpt-image-2.5-sunburst"));

452options.InputItems.Add(456options.InputItems.Add(

453 ResponseItem.CreateUserMessageItem(457 ResponseItem.CreateUserMessageItem(

454 "Generate an image of a gray tabby cat hugging an otter with an orange scarf."458 "Generate an image of a gray tabby cat hugging an otter with an orange scarf."


466 Model = "gpt-6-astra",470 Model = "gpt-6-astra",

467 PreviousResponseId = first.Id,471 PreviousResponseId = first.Id,

468};472};

469followUp.Tools.Add(ResponseTool.CreateImageGenerationTool(model: "gpt-image-2"));473followUp.Tools.Add(ResponseTool.CreateImageGenerationTool(model: "gpt-image-2.5-sunburst"));

470followUp.InputItems.Add(ResponseItem.CreateUserMessageItem("Now make it look realistic."));474followUp.InputItems.Add(ResponseItem.CreateUserMessageItem("Now make it look realistic."));

471 475 

472ResponseResult second = await client.CreateResponseAsync(followUp);476ResponseResult second = await client.CreateResponseAsync(followUp);


487first = client.responses.create(491first = client.responses.create(

488 model: "gpt-6-astra",492 model: "gpt-6-astra",

489 input: "Generate an image of a gray tabby cat hugging an otter with an orange scarf.",493 input: "Generate an image of a gray tabby cat hugging an otter with an orange scarf.",

490 tools: [{type: :image_generation}]494 tools: [{type: :image_generation, model: "gpt-image-2.5-sunburst"}]

491)495)

492 496 

493first_image = first.output.find do |item|497first_image = first.output.find do |item|


504 model: "gpt-6-astra",508 model: "gpt-6-astra",

505 input: "Now make it look realistic.",509 input: "Now make it look realistic.",

506 previous_response_id: first.id,510 previous_response_id: first.id,

507 tools: [{type: :image_generation}]511 tools: [{type: :image_generation, model: "gpt-image-2.5-sunburst"}]

508)512)

509 513 

510follow_up_image = follow_up.output.find do |item|514follow_up_image = follow_up.output.find do |item|


535 model: "gpt-6-astra",539 model: "gpt-6-astra",

536 input:540 input:

537 "Generate an image of gray tabby cat hugging an otter with an orange scarf",541 "Generate an image of gray tabby cat hugging an otter with an orange scarf",

538 tools: [{ type: "image_generation" }],542 tools: [{ type: "image_generation", model: "gpt-image-2.5-sunburst" }],

539});543});

540 544 

541const imageGenerationCalls = response.output.filter(545const imageGenerationCalls = response.output.filter(


564 id: imageGenerationCalls[0].id,568 id: imageGenerationCalls[0].id,

565 },569 },

566 ],570 ],

567 tools: [{ type: "image_generation" }],571 tools: [{ type: "image_generation", model: "gpt-image-2.5-sunburst" }],

568});572});

569 573 

570const imageData_fwup = response_fwup.output574const imageData_fwup = response_fwup.output


588response = openai.responses.create(592response = openai.responses.create(

589 model="gpt-6-astra",593 model="gpt-6-astra",

590 input="Generate an image of gray tabby cat hugging an otter with an orange scarf",594 input="Generate an image of gray tabby cat hugging an otter with an orange scarf",

591 tools=[{"type": "image_generation"}],595 tools=[{"type": "image_generation", "model": "gpt-image-2.5-sunburst"}],

592)596)

593 597 

594image_generation_calls = [598image_generation_calls = [


618 "id": image_generation_calls[0].id,622 "id": image_generation_calls[0].id,

619 },623 },

620 ],624 ],

621 tools=[{"type": "image_generation"}],625 tools=[{"type": "image_generation", "model": "gpt-image-2.5-sunburst"}],

622)626)

623 627 

624image_data_fwup = [628image_data_fwup = [


653 Input: responses.ResponseNewParamsInputUnion{657 Input: responses.ResponseNewParamsInputUnion{

654 OfString: openai.String("Generate an image of gray tabby cat hugging an otter with an orange scarf"),658 OfString: openai.String("Generate an image of gray tabby cat hugging an otter with an orange scarf"),

655 },659 },

656 Tools: []responses.ToolUnionParam{{OfImageGeneration: &responses.ToolImageGenerationParam{}}},660 Tools: []responses.ToolUnionParam{{OfImageGeneration: &responses.ToolImageGenerationParam{Model: "gpt-image-2.5-sunburst"}}},

657 })661 })

658 if err != nil {662 if err != nil {

659 panic(err)663 panic(err)


669 followUp, err := client.Responses.New(context.Background(), responses.ResponseNewParams{673 followUp, err := client.Responses.New(context.Background(), responses.ResponseNewParams{

670 Model: "gpt-6-astra",674 Model: "gpt-6-astra",

671 Input: responses.ResponseNewParamsInputUnion{OfInputItemList: input},675 Input: responses.ResponseNewParamsInputUnion{OfInputItemList: input},

672 Tools: []responses.ToolUnionParam{{OfImageGeneration: &responses.ToolImageGenerationParam{}}},676 Tools: []responses.ToolUnionParam{{OfImageGeneration: &responses.ToolImageGenerationParam{Model: "gpt-image-2.5-sunburst"}}},

673 })677 })

674 if err != nil {678 if err != nil {

675 panic(err)679 panic(err)


786ResponsesClient client = new(key);790ResponsesClient client = new(key);

787 791 

788CreateResponseOptions options = new() { Model = "gpt-6-astra" };792CreateResponseOptions options = new() { Model = "gpt-6-astra" };

789options.Tools.Add(ResponseTool.CreateImageGenerationTool(model: "gpt-image-2"));793options.Tools.Add(ResponseTool.CreateImageGenerationTool(model: "gpt-image-2.5-sunburst"));

790options.InputItems.Add(794options.InputItems.Add(

791 ResponseItem.CreateUserMessageItem(795 ResponseItem.CreateUserMessageItem(

792 "Generate an image of a gray tabby cat hugging an otter with an orange scarf."796 "Generate an image of a gray tabby cat hugging an otter with an orange scarf."


800await File.WriteAllBytesAsync("cat_and_otter.png", initialImage.ImageResultBytes.ToArray());804await File.WriteAllBytesAsync("cat_and_otter.png", initialImage.ImageResultBytes.ToArray());

801 805 

802CreateResponseOptions followUp = new() { Model = "gpt-6-astra" };806CreateResponseOptions followUp = new() { Model = "gpt-6-astra" };

803followUp.Tools.Add(ResponseTool.CreateImageGenerationTool(model: "gpt-image-2"));807followUp.Tools.Add(ResponseTool.CreateImageGenerationTool(model: "gpt-image-2.5-sunburst"));

804followUp.InputItems.Add(ResponseItem.CreateUserMessageItem("Now make it look realistic."));808followUp.InputItems.Add(ResponseItem.CreateUserMessageItem("Now make it look realistic."));

805followUp.InputItems.Add(ResponseItem.CreateReferenceItem(initialImage.Id));809followUp.InputItems.Add(ResponseItem.CreateReferenceItem(initialImage.Id));

806 810 


822first = client.responses.create(826first = client.responses.create(

823 model: "gpt-6-astra",827 model: "gpt-6-astra",

824 input: "Generate an image of a gray tabby cat hugging an otter with an orange scarf.",828 input: "Generate an image of a gray tabby cat hugging an otter with an orange scarf.",

825 tools: [{type: :image_generation}]829 tools: [{type: :image_generation, model: "gpt-image-2.5-sunburst"}]

826)830)

827 831 

828first_image = first.output.find do |item|832first_image = first.output.find do |item|


844 },848 },

845 {type: :image_generation_call, id: first_image.id}849 {type: :image_generation_call, id: first_image.id}

846 ],850 ],

847 tools: [{type: :image_generation}]851 tools: [{type: :image_generation, model: "gpt-image-2.5-sunburst"}]

848)852)

849 853 

850follow_up_image = follow_up.output.find do |item|854follow_up_image = follow_up.output.find do |item|


883 input:887 input:

884 "Draw a gorgeous image of a river made of white owl feathers, snaking its way through a serene winter landscape",888 "Draw a gorgeous image of a river made of white owl feathers, snaking its way through a serene winter landscape",

885 stream: true,889 stream: true,

886 tools: [{ type: "image_generation", partial_images: 2 }],890 tools: [

891 { type: "image_generation", model: "gpt-image-2.5-sunburst", partial_images: 2 },

892 ],

887});893});

888 894 

889for await (const event of stream) {895for await (const event of stream) {


919 model="gpt-6-astra",925 model="gpt-6-astra",

920 input="Draw a gorgeous image of a river made of white owl feathers, snaking its way through a serene winter landscape",926 input="Draw a gorgeous image of a river made of white owl feathers, snaking its way through a serene winter landscape",

921 stream=True,927 stream=True,

922 tools=[{"type": "image_generation", "partial_images": 2}],928 tools=[

929 {"type": "image_generation", "model": "gpt-image-2.5-sunburst", "partial_images": 2}

930 ],

923)931)

924 932 

925for event in stream:933for event in stream:


957 Input: responses.ResponseNewParamsInputUnion{965 Input: responses.ResponseNewParamsInputUnion{

958 OfString: openai.String("Draw a gorgeous image of a river made of white owl feathers, snaking its way through a serene winter landscape"),966 OfString: openai.String("Draw a gorgeous image of a river made of white owl feathers, snaking its way through a serene winter landscape"),

959 },967 },

960 Tools: []responses.ToolUnionParam{{OfImageGeneration: &responses.ToolImageGenerationParam{PartialImages: openai.Int(2)}}},968 Tools: []responses.ToolUnionParam{{OfImageGeneration: &responses.ToolImageGenerationParam{Model: "gpt-image-2.5-sunburst", PartialImages: openai.Int(2)}}},

961 })969 })

962 for stream.Next() {970 for stream.Next() {

963 event := stream.Current()971 event := stream.Current()


1045stream = client.responses.stream(1053stream = client.responses.stream(

1046 model: "gpt-6-astra",1054 model: "gpt-6-astra",

1047 input: "Generate an image of a river made of white owl feathers.",1055 input: "Generate an image of a river made of white owl feathers.",

1048 tools: [{type: :image_generation, partial_images: 2}]1056 tools: [{type: :image_generation, model: "gpt-image-2.5-sunburst", partial_images: 2}]

1049)1057)

1050 1058 

1051stream.each do |event|1059stream.each do |event|


1084- `gpt-4.1-nano`1092- `gpt-4.1-nano`

1085- `gpt-4o`1093- `gpt-4o`

1086- `gpt-4o-mini`1094- `gpt-4o-mini`

1087 

1088The model used for the image generation process is always a GPT Image model, including `gpt-image-2`, `gpt-image-1.5`, `gpt-image-1`, and `gpt-image-1-mini`, but these models aren't valid values for the `model` field in the Responses API. Use a text-capable mainline model (for example, `gpt-5.5` or `gpt-5`) with the hosted `image_generation` tool.

Details

958print(response.output_text)958print(response.output_text)

959```959```

960 960 

961```ruby

962require "base64"

963require "openai"

964 

965client = OpenAI::Client.new

966inline_zip = Base64.strict_encode64(File.binread("csv_insights.zip"))

967base64_string = Base64.strict_encode64(File.binread("report.csv"))

968container = client.containers.create(

969 name: "inline-skill-container",

970 skills: [{

971 type: :inline,

972 name: "csv-insights",

973 description: "Summarize CSV files and produce a markdown report.",

974 source: {type: :base64, media_type: "application/zip", data: inline_zip}

975 }]

976)

977response = client.responses.create(

978 model: "gpt-6-astra",

979 tools: [{type: :shell, environment: {type: :container_reference, container_id: container.id}}],

980 input: [{role: :user, content: [

981 {type: :input_file, filename: "report.csv", file_data: "data:text/csv;base64,#{base64_string}"},

982 {type: :input_text, text: "Use the csv-insights skill to summarize report.csv."}

983 ]}]

984)

985puts(response.output_text)

986```

987 

961 988 

962For follow-up requests, pass the same `container_id` with `container_reference`. The mounted skills and existing container files remain available while the container is active.989For follow-up requests, pass the same `container_id` with `container_reference`. The mounted skills and existing container files remain available while the container is active.

963 990 

Details

14 14 

15## Connect and create responses15## Connect and create responses

16 16 

17Install the WebSocket dependencies with `pip install "openai[realtime]>=3.8.0"` for Python or `npm install openai@^7.10.0 ws` for JavaScript.17Install the WebSocket dependencies with `pip install "openai[realtime]>=3.8.0"` for Python, `npm install openai@^7.10.0 ws` for JavaScript, or `gem install openai async-websocket` for Ruby.

18 18 

19In WebSocket mode, start each turn by sending a `response.create` event from the client. The payload mirrors the normal [Responses create body](https://developers.openai.com/api/reference/resources/responses/methods/create), except that transport-specific fields like `stream` and `background` are not used.19In WebSocket mode, start each turn by sending a `response.create` event from the client. The payload mirrors the normal [Responses create body](https://developers.openai.com/api/reference/resources/responses/methods/create), except that transport-specific fields like `stream` and `background` are not used.

20 20 


91 raise RuntimeError(event.to_json())91 raise RuntimeError(event.to_json())

92```92```

93 93 

94```ruby

95require "async"

96require "async/http/endpoint"

97require "async/websocket/client"

98require "json"

99 

100def wait_for_response(connection)

101 while (message = connection.read)

102 event = JSON.parse(message.to_str)

103 case event.fetch("type")

104 when "response.completed" then return event.fetch("response")

105 when "response.failed", "response.incomplete", "error"

106 raise "Response failed: #{JSON.generate(event)}"

107 end

108 end

109 raise "Connection closed before the response finished"

110end

111 

112def print_response(response)

113 response.fetch("output").each do |item|

114 next unless item["type"] == "message"

115 item.fetch("content").each { |part| puts(part.fetch("text")) if part["type"] == "output_text" }

116 end

117end

118 

119endpoint = Async::HTTP::Endpoint.parse("wss://api.openai.com/v1/responses", timeout: 10, alpn_protocols: ["http/1.1"])

120headers = {"Authorization" => "Bearer #{ENV.fetch("OPENAI_API_KEY")}"}

121Sync do |task|

122 task.with_timeout(120) do

123 Async::WebSocket::Client.connect(endpoint, headers: headers) do |connection|

124 connection.write(JSON.generate(

125 type: "response.create", stream_id: "main", model: "gpt-6-astra", store: false,

126 input: [{role: "user", content: "Find fizz_buzz()"}], tools: []

127 ))

128 connection.flush

129 print_response(wait_for_response(connection))

130 end

131 end

132end

133```

134 

94 135 

95Clients can optionally warm up request state by sending `response.create` with `generate: false`. This is useful when you already know the tools, instructions, and/or custom messages you plan to send with an upcoming turn. `generate: false` does not return a model output, but prepares request state so the next generated turn can start faster. The warmup request returns a response ID that you can chain from with `previous_response_id`, including on later turns in a response chain. The next section explains how to continue a session using `previous_response_id` and incremental inputs.136Clients can optionally warm up request state by sending `response.create` with `generate: false`. This is useful when you already know the tools, instructions, and/or custom messages you plan to send with an upcoming turn. `generate: false` does not return a model output, but prepares request state so the next generated turn can start faster. The warmup request returns a response ID that you can chain from with `previous_response_id`, including on later turns in a response chain. The next section explains how to continue a session using `previous_response_id` and incremental inputs.

96 137 


263 print(wait_for_response(connection).output_text)304 print(wait_for_response(connection).output_text)

264```305```

265 306 

307```ruby

308require "async"

309require "async/http/endpoint"

310require "async/websocket/client"

311require "json"

312 

313def wait_for_response(connection)

314 while (message = connection.read)

315 event = JSON.parse(message.to_str)

316 case event.fetch("type")

317 when "response.completed" then return event.fetch("response")

318 when "response.failed", "response.incomplete", "error"

319 raise "Response failed: #{JSON.generate(event)}"

320 end

321 end

322 raise "Connection closed before the response finished"

323end

324 

325def print_response(response)

326 response.fetch("output").each do |item|

327 next unless item["type"] == "message"

328 item.fetch("content").each { |part| puts(part.fetch("text")) if part["type"] == "output_text" }

329 end

330end

331 

332tools = [{

333 type: "function", name: "get_test_results", description: "Read the demo test results.",

334 parameters: {type: "object", properties: {}, required: [], additionalProperties: false}, strict: true

335}]

336 

337endpoint = Async::HTTP::Endpoint.parse("wss://api.openai.com/v1/responses", timeout: 10, alpn_protocols: ["http/1.1"])

338headers = {"Authorization" => "Bearer #{ENV.fetch("OPENAI_API_KEY")}"}

339Sync do |task|

340 task.with_timeout(120) do

341 Async::WebSocket::Client.connect(endpoint, headers: headers) do |connection|

342 connection.write(JSON.generate(

343 type: "response.create", stream_id: "main", model: "gpt-6-astra", store: false,

344 input: "Find the failing test and suggest a fix.", tools: tools,

345 tool_choice: {type: "function", name: "get_test_results"}, parallel_tool_calls: false

346 ))

347 connection.flush

348 response = wait_for_response(connection)

349 call = response.fetch("output").find { |item| item["type"] == "function_call" }

350 unless call && call["name"] == "get_test_results" && JSON.parse(call.fetch("arguments")) == {}

351 raise "Expected a get_test_results call with no arguments"

352 end

353 # Demo data. Replace this with your test runner.

354 result = {test: "test_fizz_buzz", failure: 'Expected "FizzBuzz" for 15, got "Fizz".'}

355 connection.write(JSON.generate(

356 type: "response.create", stream_id: "main", model: "gpt-6-astra", store: false,

357 previous_response_id: response.fetch("id"),

358 input: [

359 {type: "function_call_output", call_id: call.fetch("call_id"), output: JSON.generate(result)},

360 {role: "user", content: "Now optimize it."}

361 ],

362 tools: tools, tool_choice: "none"

363 ))

364 connection.flush

365 print_response(wait_for_response(connection))

366 end

367 end

368end

369```

370 

266 371 

267## How continuation works372## How continuation works

268 373 


381 raise RuntimeError(event.to_json())486 raise RuntimeError(event.to_json())

382```487```

383 488 

489```ruby

490require "async"

491require "async/http/endpoint"

492require "async/websocket/client"

493require "json"

494 

495require "openai"

496 

497def wait_for_response(connection)

498 while (message = connection.read)

499 event = JSON.parse(message.to_str)

500 case event.fetch("type")

501 when "response.completed" then return event.fetch("response")

502 when "response.failed", "response.incomplete", "error"

503 raise "Response failed: #{JSON.generate(event)}"

504 end

505 end

506 raise "Connection closed before the response finished"

507end

508 

509def print_response(response)

510 response.fetch("output").each do |item|

511 next unless item["type"] == "message"

512 item.fetch("content").each { |part| puts(part.fetch("text")) if part["type"] == "output_text" }

513 end

514end

515 

516client = OpenAI::Client.new

517compacted = client.responses.compact(

518 model: "gpt-6-astra",

519 input: [{role: :user, content: "Find the failing test."}]

520)

521next_input = compacted.output.map(&:to_h)

522next_input << {role: :user, content: "Continue from here."}

523 

524endpoint = Async::HTTP::Endpoint.parse("wss://api.openai.com/v1/responses", timeout: 10, alpn_protocols: ["http/1.1"])

525headers = {"Authorization" => "Bearer #{ENV.fetch("OPENAI_API_KEY")}"}

526Sync do |task|

527 task.with_timeout(120) do

528 Async::WebSocket::Client.connect(endpoint, headers: headers) do |connection|

529 connection.write(JSON.generate(

530 type: "response.create", stream_id: "main", model: "gpt-6-astra", store: false,

531 input: next_input, tools: []

532 ))

533 connection.flush

534 print_response(wait_for_response(connection))

535 end

536 end

537end

538```

539 

384 540 

385## Run conversations in parallel541## Run conversations in parallel

386 542 


667 drain_until_complete(connection, {"critic", "planner"})823 drain_until_complete(connection, {"critic", "planner"})

668```824```

669 825 

826```ruby

827require "async"

828require "async/http/endpoint"

829require "async/websocket/client"

830require "json"

831 

832def send_create(connection, stream_id, text, previous_response_id = nil)

833 payload = {

834 type: "response.create", stream_id: stream_id, model: "gpt-6-astra", store: false,

835 input: [{role: "user", content: text}]

836 }

837 payload[:previous_response_id] = previous_response_id if previous_response_id

838 connection.write(JSON.generate(payload))

839 connection.flush

840end

841 

842def read_event(connection)

843 message = connection.read or raise "Connection closed before all responses finished"

844 event = JSON.parse(message.to_str)

845 if ["response.failed", "response.incomplete", "error"].include?(event["type"])

846 raise "Response failed: #{JSON.generate(event)}"

847 end

848 event

849end

850 

851def drain_responses(connection, lanes, latest_ids)

852 remaining = lanes.dup

853 until remaining.empty?

854 event = read_event(connection)

855 lane = event["stream_id"]

856 next unless remaining.include?(lane) && event["type"] == "response.completed"

857 latest_ids[lane] = event.fetch("response").fetch("id")

858 remaining.delete(lane)

859 end

860end

861 

862endpoint = Async::HTTP::Endpoint.parse("wss://api.openai.com/v1/responses", timeout: 10, alpn_protocols: ["http/1.1"])

863headers = {"Authorization" => "Bearer #{ENV.fetch("OPENAI_API_KEY")}"}

864Sync do |task|

865 task.with_timeout(120) do

866 Async::WebSocket::Client.connect(endpoint, headers: headers) do |connection|

867 latest_ids = {}

868 send_create(connection, "planner", "Draft a deployment plan for a stateless API service.")

869 send_create(connection, "research", "List common deployment risks for a stateless API service.")

870 drain_responses(connection, ["planner", "research"], latest_ids)

871 parent_id = latest_ids.fetch("planner")

872 send_create(connection, "critic", "Find gaps in this deployment plan.", parent_id)

873 # Let the fork load its parent before advancing the original lane's cache.

874 loop do

875 event = read_event(connection)

876 break if event["type"] == "response.in_progress" && event["stream_id"] == "critic"

877 end

878 send_create(connection, "planner", "Add rollback and monitoring steps.", parent_id)

879 drain_responses(connection, ["critic", "planner"], latest_ids)

880 puts(JSON.generate(latest_ids))

881 end

882 end

883end

884```

885 

670 886 

671A `stream_id` must be 1–256 characters and can contain only letters, numbers, underscores (`_`), hyphens (`-`), and periods (`.`). Use it only in WebSocket `response.create` events; do not include it in HTTP `POST /v1/responses`.887A `stream_id` must be 1–256 characters and can contain only letters, numbers, underscores (`_`), hyphens (`-`), and periods (`.`). Use it only in WebSocket `response.create` events; do not include it in HTTP `POST /v1/responses`.

672 888 

Details

110 110 

111#### `/v1/images`111#### `/v1/images`

112 112 

113- Image generation is Zero Data Retention compatible when using `gpt-image-2`, `gpt-image-1.5`, `gpt-image-1`, and `gpt-image-1-mini`.113- Image generation is Zero Data Retention compatible when using `gpt-image-2.5-sunburst`, `gpt-image-2.5-sunburst-2026-09-08`, `gpt-image-2.5-flare`, `gpt-image-2.5-flare-2026-09-08`, `gpt-image-2`, `gpt-image-1.5`, `gpt-image-1`, and `gpt-image-1-mini`.

114 114 

115#### `/v1/files`115#### `/v1/files`

116 116 


268| `/v1/evals` | Evals | United States, Europe (EEA + Switzerland) | United States, Europe (EEA + Switzerland) | Service-level support | None | — |268| `/v1/evals` | Evals | United States, Europe (EEA + Switzerland) | United States, Europe (EEA + Switzerland) | Service-level support | None | — |

269| `/v1/files` | Files | All listed regions | None | Service-level support | None | — |269| `/v1/files` | Files | All listed regions | None | Service-level support | None | — |

270| `/v1/fine_tuning/jobs` | Fine-tuning | All listed regions | United States, Europe (EEA + Switzerland) | `gpt-4o-2024-08-06`, `gpt-4o-mini-2024-07-18`, `gpt-4.1-2025-04-14`, `gpt-4.1-mini-2025-04-14` | None | — |270| `/v1/fine_tuning/jobs` | Fine-tuning | All listed regions | United States, Europe (EEA + Switzerland) | `gpt-4o-2024-08-06`, `gpt-4o-mini-2024-07-18`, `gpt-4.1-2025-04-14`, `gpt-4.1-mini-2025-04-14` | None | — |

271| `/v1/images/edits` | Images | All listed regions | United States, Europe (EEA + Switzerland) | `gpt-image-2`, `gpt-image-1`, `gpt-image-1.5`, `gpt-image-1-mini` | None | — |271| `/v1/images/edits` | Images | All listed regions | United States, Europe (EEA + Switzerland) | `gpt-image-2.5-sunburst`, `gpt-image-2.5-sunburst-2026-09-08`, `gpt-image-2.5-flare`, `gpt-image-2.5-flare-2026-09-08`, `gpt-image-2`, `gpt-image-1`, `gpt-image-1.5`, `gpt-image-1-mini` | None | — |

272| `/v1/images/generations` | Images | All listed regions | United States, Europe (EEA + Switzerland) | `gpt-image-2`, `gpt-image-1`, `gpt-image-1.5`, `gpt-image-1-mini` | None | — |272| `/v1/images/generations` | Images | All listed regions | United States, Europe (EEA + Switzerland) | `gpt-image-2.5-sunburst`, `gpt-image-2.5-sunburst-2026-09-08`, `gpt-image-2.5-flare`, `gpt-image-2.5-flare-2026-09-08`, `gpt-image-2`, `gpt-image-1`, `gpt-image-1.5`, `gpt-image-1-mini` | None | — |

273| `/v1/moderations` | Moderation | All listed regions | United States, Europe (EEA + Switzerland) | `omni-moderation-latest` | None | — |273| `/v1/moderations` | Moderation | All listed regions | United States, Europe (EEA + Switzerland) | `omni-moderation-latest` | None | — |

274| `/v1/realtime` | Realtime | United States, Europe (EEA + Switzerland) | United States, Europe (EEA + Switzerland) | `gpt-realtime`, `gpt-realtime-1.5`, `gpt-realtime-mini`, `gpt-realtime-2`, `gpt-realtime-2.1`, `gpt-realtime-2.1-mini` | None | — |274| `/v1/realtime` | Realtime | United States, Europe (EEA + Switzerland) | United States, Europe (EEA + Switzerland) | `gpt-realtime`, `gpt-realtime-1.5`, `gpt-realtime-mini`, `gpt-realtime-2`, `gpt-realtime-2.1`, `gpt-realtime-2.1-mini` | None | — |

275| `/v1/realtime/transcription_sessions` | Realtime | United States, Europe (EEA + Switzerland) | United States, Europe (EEA + Switzerland) | `gpt-realtime-whisper`, `gpt-live-transcribe`, `gpt-transcribe` | None | — |275| `/v1/realtime/transcription_sessions` | Realtime | United States, Europe (EEA + Switzerland) | United States, Europe (EEA + Switzerland) | `gpt-realtime-whisper`, `gpt-live-transcribe`, `gpt-transcribe` | None | — |

libraries.md +1 −1

Details

173<dependency>173<dependency>

174 <groupId>com.openai</groupId>174 <groupId>com.openai</groupId>

175 <artifactId>openai-java</artifactId>175 <artifactId>openai-java</artifactId>

176 <version>4.58.0</version>176 <version>4.61.0</version>

177</dependency>177</dependency>

178```178```

179 179 

models.md +2 −0

Details

85- [GPT-Image-1 Mini](/api/docs/models/gpt-image-1-mini.md): A cost-efficient version of GPT Image 185- [GPT-Image-1 Mini](/api/docs/models/gpt-image-1-mini.md): A cost-efficient version of GPT Image 1

86- [GPT-Image-1.5](/api/docs/models/gpt-image-1.5.md): Our previous image generation model86- [GPT-Image-1.5](/api/docs/models/gpt-image-1.5.md): Our previous image generation model

87- [GPT-Image-2](/api/docs/models/gpt-image-2.md): State-of-the-art image generation model87- [GPT-Image-2](/api/docs/models/gpt-image-2.md): State-of-the-art image generation model

88- [GPT-Image-2.5 Flare](/api/docs/models/gpt-image-2.5-flare.md): Fast, high-quality everyday image generation

89- [GPT-Image-2.5 Sunburst](/api/docs/models/gpt-image-2.5-sunburst.md): Our most capable model for image generation and editing

88- [GPT-Live-Transcribe](/api/docs/models/gpt-live-transcribe.md): Low-latency speech-to-text model for realtime transcription90- [GPT-Live-Transcribe](/api/docs/models/gpt-live-transcribe.md): Low-latency speech-to-text model for realtime transcription

89- [gpt-oss-120b](/api/docs/models/gpt-oss-120b.md): Most powerful open-weight model, fits into an H100 GPU91- [gpt-oss-120b](/api/docs/models/gpt-oss-120b.md): Most powerful open-weight model, fits into an H100 GPU

90- [gpt-oss-20b](/api/docs/models/gpt-oss-20b.md): Medium-sized open-weight model for low latency92- [gpt-oss-20b](/api/docs/models/gpt-oss-20b.md): Medium-sized open-weight model for low latency

models/all.md +2 −0

Details

85- [GPT-Image-1 Mini](/api/docs/models/gpt-image-1-mini.md): A cost-efficient version of GPT Image 185- [GPT-Image-1 Mini](/api/docs/models/gpt-image-1-mini.md): A cost-efficient version of GPT Image 1

86- [GPT-Image-1.5](/api/docs/models/gpt-image-1.5.md): Our previous image generation model86- [GPT-Image-1.5](/api/docs/models/gpt-image-1.5.md): Our previous image generation model

87- [GPT-Image-2](/api/docs/models/gpt-image-2.md): State-of-the-art image generation model87- [GPT-Image-2](/api/docs/models/gpt-image-2.md): State-of-the-art image generation model

88- [GPT-Image-2.5 Flare](/api/docs/models/gpt-image-2.5-flare.md): Fast, high-quality everyday image generation

89- [GPT-Image-2.5 Sunburst](/api/docs/models/gpt-image-2.5-sunburst.md): Our most capable model for image generation and editing

88- [GPT-Live-Transcribe](/api/docs/models/gpt-live-transcribe.md): Low-latency speech-to-text model for realtime transcription90- [GPT-Live-Transcribe](/api/docs/models/gpt-live-transcribe.md): Low-latency speech-to-text model for realtime transcription

89- [gpt-oss-120b](/api/docs/models/gpt-oss-120b.md): Most powerful open-weight model, fits into an H100 GPU91- [gpt-oss-120b](/api/docs/models/gpt-oss-120b.md): Most powerful open-weight model, fits into an H100 GPU

90- [gpt-oss-20b](/api/docs/models/gpt-oss-20b.md): Medium-sized open-weight model for low latency92- [gpt-oss-20b](/api/docs/models/gpt-oss-20b.md): Medium-sized open-weight model for low latency

quickstart.md +1 −1

Details

190<dependency>190<dependency>

191 <groupId>com.openai</groupId>191 <groupId>com.openai</groupId>

192 <artifactId>openai-java</artifactId>192 <artifactId>openai-java</artifactId>

193 <version>4.58.0</version>193 <version>4.61.0</version>

194</dependency>194</dependency>

195```195```

196 196 

Details

2 2 

3> For the complete documentation index, see [llms.txt](/llms.txt). Markdown versions of documentation pages are available by appending `.md` to the page URL.3> For the complete documentation index, see [llms.txt](/llms.txt). Markdown versions of documentation pages are available by appending `.md` to the page URL.

4 4 

5In this tutorial, we'll harness the power of OpenAI's Whisper and GPT models to develop an automated meeting minutes generator. The application transcribes audio from a meeting, provides a summary of the discussion, extracts key points and action items, and performs a sentiment analysis.5In this tutorial, you'll build an automated meeting minutes generator. The application transcribes a meeting recording, summarizes the discussion, extracts key points and action items, analyzes sentiment, and saves the result as a Word document.

6 6 

7## Getting started7## Getting started

8 8 

9This tutorial assumes a basic understanding of Python and an [OpenAI API key](https://platform.openai.com/settings/organization/api-keys). You can use the audio file provided with this tutorial or your own.9This tutorial assumes familiarity with one of the supported languages and an [OpenAI API key](https://platform.openai.com/settings/organization/api-keys). You can use the short smoke-test audio file or your own recording of up to 25 MB.

10 10 

11Additionally, you will need to install the [python-docx](https://python-docx.readthedocs.io/en/latest/) and [OpenAI](https://developers.openai.com/api/docs/libraries) libraries. You can create a new Python environment and install the required packages with the following commands:11Install the [OpenAI SDK](https://developers.openai.com/api/docs/libraries) and a DOCX library for your language:

12 12 

13```bash13- JavaScript: [`docx`](https://docx.js.org/)

14python -m venv env14- Python: [`python-docx`](https://python-docx.readthedocs.io/en/latest/)

15- Go: [`godocx`](https://github.com/gomutex/godocx)

16- Java: [Apache POI XWPF](https://poi.apache.org/components/document/quick-guide-xwpf.html)

17- Ruby: [`caracal`](https://github.com/urvin-compliance/caracal)

15 18 

16source env/bin/activate19## Transcribing audio

17 

18pip install openai

19pip install python-docx

20```

21 

22## Transcribing audio with Whisper

23 20 

24 21 

25 22 

26 23

27 24 

28 The first step in transcribing the audio from a meeting is to pass the25 The first step is to pass the meeting recording to the

29 audio file of the meeting into our 26 [/v1/audio API](https://developers.openai.com/api/reference/resources/audio). The current

30 [/v1/audio API](https://developers.openai.com/api/reference/resources/audio). Whisper, the27 file transcription model converts spoken language into written text. To

31 model that powers the audio API, is capable of converting spoken language28 start, omit the optional

32 into written text. To start, we will avoid passing a

33 [prompt](https://developers.openai.com/api/reference/resources/audio/subresources/transcriptions/methods/create#audio/createTranscription-prompt) 29 [prompt](https://developers.openai.com/api/reference/resources/audio/subresources/transcriptions/methods/create#audio/createTranscription-prompt)

34 or 30 and

35 [temperature](https://developers.openai.com/api/reference/resources/audio/subresources/transcriptions/methods/create#audio/createTranscription-temperature-4) 31 [temperature](https://developers.openai.com/api/reference/resources/audio/subresources/transcriptions/methods/create#audio/createTranscription-temperature-4)

36 (optional parameters to control the model's output) and stick with the32 parameters and use their default values.

37 default values.

38 33

39 34 

40 35


54 49 

55 50 

56 51 

57Next, we import the required packages and define a function that uses the Whisper model to take in the audio file and52Save the downloaded file as `meeting.wav` in the directory from which you run the example, or replace `meeting.wav` with the path to your recording. The short downloadable clip verifies the workflow; use an actual meeting recording of up to 25 MB to generate useful summaries and action items.

58transcribe it:53 

54Define a helper that opens the recording and sends the file contents to [`gpt-transcribe`](https://developers.openai.com/api/docs/models/gpt-transcribe):

55 

56```javascript

57import fs from "node:fs";

58 

59import { Document, HeadingLevel, Packer, Paragraph, TextRun } from "docx";

60import OpenAI from "openai";

61 

62const openai = new OpenAI();

63 

64async function transcribeAudio(audioFilePath) {

65 const transcription = await openai.audio.transcriptions.create({

66 file: fs.createReadStream(audioFilePath),

67 model: "gpt-transcribe",

68 });

69 return transcription.text;

70}

71```

59 72 

60```python73```python

74from pathlib import Path

75 

61from docx import Document76from docx import Document

62from openai import OpenAI77from openai import OpenAI

63 78 

64client = OpenAI()79client = OpenAI()

65 80 

66 81 

67def transcribe_audio(audio_file_path):82def transcribe_audio(audio_file_path: str | Path) -> str:

68 with open(audio_file_path, "rb") as audio_file:83 with Path(audio_file_path).open("rb") as audio_file:

69 transcription = client.audio.transcriptions.create(84 transcription = client.audio.transcriptions.create(

70 file=audio_file,85 file=audio_file,

71 model="whisper-1",86 model="gpt-transcribe",

72 )87 )

73 return transcription.text88 return transcription.text

74```89```

75 90 

91```go

92package main

76 93 

77In this function, `audio_file_path` is the path to the audio file you want to transcribe. The function opens this file and passes it to the Whisper ASR model (`whisper-1`) for transcription. The result is returned as raw text. It’s important to note that the `openai.Audio.transcribe` function requires the actual audio file to be passed in, not just the path to the file locally or on a remote server. This means that if you are running this code on a server where you might not also be storing your audio files, you will need to have a preprocessing step that first downloads the audio files onto that device.94import (

95 "context"

96 "fmt"

97 "os"

98 "strings"

78 99 

79## Summarizing and analyzing the transcript with a GPT model100 "github.com/gomutex/godocx"

101 "github.com/openai/openai-go/v3"

102)

80 103 

81Having obtained the transcript, we now pass it to a GPT model via the [Chat Completions API](https://developers.openai.com/api/reference/resources/chat). The snippets below use a tested model to generate a summary, extract key points, action items, and perform sentiment analysis. For new projects, start with [`gpt-6-astra`](https://developers.openai.com/api/docs/models/gpt-6-astra).104type meetingMinutes struct {

105 AbstractSummary string

106 KeyPoints string

107 ActionItems string

108 Sentiment string

109}

82 110 

83This tutorial uses distinct functions for each task we want the model to perform. This is not the most efficient way to do this task - you can put these instructions into one function, however, splitting them up can lead to higher quality summarization.111var client = openai.NewClient()

84 112 

85To split the tasks up, we define the `meeting_minutes` function which will serve as the main function of this application:113func transcribeAudio(ctx context.Context, audioFilePath string) (string, error) {

114 audioFile, err := os.Open(audioFilePath)

115 if err != nil {

116 return "", err

117 }

118 defer audioFile.Close()

119 

120 transcription, err := client.Audio.Transcriptions.New(ctx, openai.AudioTranscriptionNewParams{

121 File: audioFile,

122 Model: "gpt-transcribe",

123 })

124 if err != nil {

125 return "", err

126 }

127 return transcription.Text, nil

128}

129```

86 130 

87```python131```java

88def meeting_minutes(transcription):132import com.openai.client.OpenAIClient;

89 abstract_summary = abstract_summary_extraction(transcription)133import com.openai.client.okhttp.OpenAIOkHttpClient;

90 key_points = key_points_extraction(transcription)134import com.openai.models.audio.transcriptions.TranscriptionCreateParams;

91 action_items = action_item_extraction(transcription)135import com.openai.models.chat.completions.ChatCompletionCreateParams;

92 sentiment = sentiment_analysis(transcription)136import java.io.IOException;

93 return {137import java.io.OutputStream;

94 "abstract_summary": abstract_summary,138import java.math.BigInteger;

95 "key_points": key_points,139import java.nio.file.Files;

96 "action_items": action_items,140import java.nio.file.Path;

97 "sentiment": sentiment,141import org.apache.poi.xwpf.usermodel.XWPFDocument;

142import org.apache.poi.xwpf.usermodel.XWPFStyle;

143import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTStyle;

144import org.openxmlformats.schemas.wordprocessingml.x2006.main.STStyleType;

145 

146public final class TutorialMeetingMinutesExample {

147 private TutorialMeetingMinutesExample() {}

148 

149 record MeetingMinutes(

150 String abstractSummary, String keyPoints, String actionItems, String sentiment) {}

151 

152 private static final class ClientHolder {

153 private static final OpenAIClient INSTANCE = OpenAIOkHttpClient.fromEnv();

154 }

155 

156 private static OpenAIClient client() {

157 return ClientHolder.INSTANCE;

158 }

159 

160 static String transcribeAudio(Path audioFilePath) {

161 var transcription =

162 client()

163 .audio()

164 .transcriptions()

165 .create(

166 TranscriptionCreateParams.builder()

167 .file(audioFilePath)

168 .model("gpt-transcribe")

169 .build());

170 return transcription.asTranscription().text();

98 }171 }

99```172```

100 173 

174```ruby

175require "caracal"

176require "openai"

177require "pathname"

101 178 

102In this function, `transcription` is the text we obtained from Whisper. The transcription can be passed to the four other functions, each designed to perform a specific task: `abstract_summary_extraction` generates a summary of the meeting, `key_points_extraction` extracts the main points, `action_item_extraction` identifies the action items, and `sentiment_analysis performs` a sentiment analysis. If there are other capabilities you want, you can add those in as well using the same framework shown above.179client = OpenAI::Client.new

103 180 

104Here is how each of these functions works:181def transcribe_audio(client, audio_file_path)

182 transcription = client.audio.transcriptions.create(

183 file: Pathname(audio_file_path),

184 model: "gpt-transcribe"

185 )

186 transcription.text

187end

188```

105 189 

106### Summary extraction

107 190 

108The `abstract_summary_extraction` function takes the transcription and summarizes it into a concise abstract paragraph with the aim to retain the most important points while avoiding unnecessary details or tangential points. The main mechanism to enable this process is the system message as shown below. There are many different possible ways of achieving similar results through the process commonly referred to as prompt engineering. You can read our [prompt engineering guide](https://developers.openai.com/api/docs/guides/prompt-engineering) which gives in depth advice on how to do this most effectively.191The helper accepts a local audio path, opens the file with the language's standard file API, and passes the file contents to the transcription model. The transcription endpoint needs the audio bytes, not a local path or remote URL. If your server stores recordings elsewhere, download or stream the recording into the request before creating the transcription.

192 

193## Summarizing and analyzing the transcript with a GPT model

194 

195Pass the transcript to a GPT model through the [Chat Completions API](https://developers.openai.com/api/reference/resources/chat). This tutorial demonstrates the still-supported Chat Completions path for existing integrations. For new projects, use the [Responses API](https://developers.openai.com/api/docs/guides/migrate-to-responses) and start with [`gpt-6-astra`](https://developers.openai.com/api/docs/models/gpt-6-astra). The snippets below use a tested model to generate a summary, extract key points and action items, and analyze sentiment.

196 

197This tutorial uses a separate model call for each task. You can combine the instructions into one request to reduce calls, but separate prompts make each result easier to tune.

198 

199Define the shared helper that sends the transcript and task-specific instructions to the model:

200 

201```javascript

202async function complete(transcription, instructions) {

203 const response = await openai.chat.completions.create({

204 model: "gpt-5.5",

205 messages: [

206 { role: "system", content: instructions },

207 { role: "user", content: transcription },

208 ],

209 });

210 return response.choices[0].message.content ?? "";

211}

212```

109 213 

110```python214```python

111def abstract_summary_extraction(transcription):215def complete(transcription: str, instructions: str) -> str:

112 response = client.chat.completions.create(216 response = client.chat.completions.create(

113 model="gpt-5.5",217 model="gpt-5.5",

114 messages=[218 messages=[

115 {219 {"role": "system", "content": instructions},

116 "role": "system",

117 "content": "You are a highly skilled AI trained in language comprehension and summarization. I would like you to read the following text and summarize it into a concise abstract paragraph. Aim to retain the most important points, providing a coherent and readable summary that could help a person understand the main points of the discussion without needing to read the entire text. Please avoid unnecessary details or tangential points.",

118 },

119 {"role": "user", "content": transcription},220 {"role": "user", "content": transcription},

120 ],221 ],

121 )222 )

122 return response.choices[0].message.content or ""223 return response.choices[0].message.content or ""

123```224```

124 225 

226```go

227func complete(ctx context.Context, transcription, instructions string) (string, error) {

228 response, err := client.Chat.Completions.New(ctx, openai.ChatCompletionNewParams{

229 Model: "gpt-5.5",

230 Messages: []openai.ChatCompletionMessageParamUnion{

231 openai.SystemMessage(instructions),

232 openai.UserMessage(transcription),

233 },

234 })

235 if err != nil {

236 return "", err

237 }

238 return response.Choices[0].Message.Content, nil

239}

240```

125 241 

126### Key points extraction242```java

243private static String complete(String transcription, String instructions) {

244 var response =

245 client()

246 .chat()

247 .completions()

248 .create(

249 ChatCompletionCreateParams.builder()

250 .model("gpt-5.5")

251 .addSystemMessage(instructions)

252 .addUserMessage(transcription)

253 .build());

254 return response.choices().get(0).message().content().orElse("");

255}

256```

127 257 

128The `key_points_extraction` function identifies and lists the main points discussed in the meeting. These points should represent the most important ideas, findings, or topics crucial to the essence of the discussion. Again, the main mechanism for controlling the way these points are identified is the system message. You might want to give some additional context here around the way your project or company runs such as “We are a company that sells race cars to consumers. We do XYZ with the goal of XYZ”. This additional context could dramatically improve the models ability to extract information that is relevant.258```ruby

259def complete(client, transcription, instructions)

260 response = client.chat.completions.create(

261 model: "gpt-5.5",

262 messages: [

263 {role: :system, content: instructions},

264 {role: :user, content: transcription}

265 ]

266 )

267 response.choices.first.message.content || ""

268end

269```

270 

271 

272Define an orchestration helper that returns the four sections of the meeting minutes:

273 

274```javascript

275async function buildMeetingMinutes(transcription) {

276 return {

277 "Abstract summary": await extractAbstractSummary(transcription),

278 "Key points": await extractKeyPoints(transcription),

279 "Action items": await extractActionItems(transcription),

280 Sentiment: await analyzeSentiment(transcription),

281 };

282}

283```

129 284 

130```python285```python

131def key_points_extraction(transcription):286def meeting_minutes(transcription: str) -> dict[str, str]:

132 response = client.chat.completions.create(287 return {

133 model="gpt-5.5",288 "Abstract summary": abstract_summary_extraction(transcription),

134 messages=[289 "Key points": key_points_extraction(transcription),

290 "Action items": action_item_extraction(transcription),

291 "Sentiment": sentiment_analysis(transcription),

292 }

293```

294 

295```go

296func buildMeetingMinutes(ctx context.Context, transcription string) (meetingMinutes, error) {

297 summary, err := extractAbstractSummary(ctx, transcription)

298 if err != nil {

299 return meetingMinutes{}, err

300 }

301 keyPoints, err := extractKeyPoints(ctx, transcription)

302 if err != nil {

303 return meetingMinutes{}, err

304 }

305 actionItems, err := extractActionItems(ctx, transcription)

306 if err != nil {

307 return meetingMinutes{}, err

308 }

309 sentiment, err := analyzeSentiment(ctx, transcription)

310 if err != nil {

311 return meetingMinutes{}, err

312 }

313 return meetingMinutes{summary, keyPoints, actionItems, sentiment}, nil

314}

315```

316 

317```java

318static MeetingMinutes buildMeetingMinutes(String transcription) {

319 return new MeetingMinutes(

320 extractAbstractSummary(transcription),

321 extractKeyPoints(transcription),

322 extractActionItems(transcription),

323 analyzeSentiment(transcription));

324}

325```

326 

327```ruby

328def build_meeting_minutes(client, transcription)

135 {329 {

136 "role": "system",330 "Abstract summary" => extract_abstract_summary(client, transcription),

137 "content": "You are a proficient AI with a specialty in distilling information into key points. Based on the following text, identify and list the main points that were discussed or brought up. These should be the most important ideas, findings, or topics that are crucial to the essence of the discussion. Your goal is to provide a list that someone could read to quickly understand what was talked about.",331 "Key points" => extract_key_points(client, transcription),

138 },332 "Action items" => extract_action_items(client, transcription),

139 {"role": "user", "content": transcription},333 "Sentiment" => analyze_sentiment(client, transcription)

140 ],334 }

335end

336```

337 

338 

339The helper passes the transcript to four focused helpers: one each for the summary, key points, action items, and sentiment. Add another helper and output section if your application needs more analysis.

340 

341Here is how each of these functions works:

342 

343### Summary extraction

344 

345The summary helper asks the model for one concise paragraph that preserves important decisions and context while omitting tangents. The system message controls this behavior. For more ways to shape the result, see the [prompt engineering guide](https://developers.openai.com/api/docs/guides/prompt-engineering).

346 

347```javascript

348async function extractAbstractSummary(transcription) {

349 return complete(

350 transcription,

351 "Summarize the meeting transcript in one concise paragraph. Keep the most important decisions and context, and omit tangents."

352 );

353}

354```

355 

356```python

357def abstract_summary_extraction(transcription: str) -> str:

358 return complete(

359 transcription,

360 "Summarize the meeting transcript in one concise paragraph. "

361 "Keep the most important decisions and context, and omit tangents.",

141 )362 )

142 return response.choices[0].message.content or ""363```

364 

365```go

366func extractAbstractSummary(ctx context.Context, transcription string) (string, error) {

367 return complete(ctx, transcription, "Summarize the meeting transcript in one concise paragraph. Keep the most important decisions and context, and omit tangents.")

368}

369```

370 

371```java

372static String extractAbstractSummary(String transcription) {

373 return complete(

374 transcription,

375 "Summarize the meeting transcript in one concise paragraph. "

376 + "Keep the most important decisions and context, and omit tangents.");

377}

378```

379 

380```ruby

381def extract_abstract_summary(client, transcription)

382 complete(

383 client,

384 transcription,

385 "Summarize the meeting transcript in one concise paragraph. Keep the most important decisions and context, and omit tangents."

386 )

387end

388```

389 

390 

391### Key points extraction

392 

393The key-points helper lists the important ideas, findings, and topics discussed in the meeting. Add relevant project or company context to the system message when it helps the model identify what matters to your audience.

394 

395```javascript

396async function extractKeyPoints(transcription) {

397 return complete(

398 transcription,

399 "List the most important ideas, findings, and topics from the meeting. Use concise bullet points."

400 );

401}

402```

403 

404```python

405def key_points_extraction(transcription: str) -> str:

406 return complete(

407 transcription,

408 "List the most important ideas, findings, and topics from the meeting. "

409 "Use concise bullet points.",

410 )

411```

412 

413```go

414func extractKeyPoints(ctx context.Context, transcription string) (string, error) {

415 return complete(ctx, transcription, "List the most important ideas, findings, and topics from the meeting. Use concise bullet points.")

416}

417```

418 

419```java

420static String extractKeyPoints(String transcription) {

421 return complete(

422 transcription,

423 "List the most important ideas, findings, and topics from the meeting. "

424 + "Use concise bullet points.");

425}

426```

427 

428```ruby

429def extract_key_points(client, transcription)

430 complete(

431 client,

432 transcription,

433 "List the most important ideas, findings, and topics from the meeting. Use concise bullet points."

434 )

435end

143```436```

144 437 

145 438 

146### Action item extraction439### Action item extraction

147 440 

148The `action_item_extraction` function identifies tasks, assignments, or actions agreed upon or mentioned during the meeting. These could be tasks assigned to specific individuals or general actions the group decided to take. While not covered in this tutorial, the Chat Completions API provides a [function calling capability](https://developers.openai.com/api/docs/guides/function-calling) which would allow you to build in the ability to automatically create tasks in your task management software and assign it to the relevant person.441The action-items helper identifies tasks and follow-ups, including owners and deadlines when the transcript provides them. To create and assign tasks in another system, connect this step to [function calling](https://developers.openai.com/api/docs/guides/function-calling).

442 

443```javascript

444async function extractActionItems(transcription) {

445 return complete(

446 transcription,

447 "List every task or follow-up agreed to in the meeting. Include the owner and deadline when the transcript provides them."

448 );

449}

450```

149 451 

150```python452```python

151def action_item_extraction(transcription):453def action_item_extraction(transcription: str) -> str:

152 response = client.chat.completions.create(454 return complete(

153 model="gpt-5.5",455 transcription,

154 messages=[456 "List every task or follow-up agreed to in the meeting. "

155 {457 "Include the owner and deadline when the transcript provides them.",

156 "role": "system",

157 "content": "You are an AI expert in analyzing conversations and extracting action items. Please review the text and identify any tasks, assignments, or actions that were agreed upon or mentioned as needing to be done. These could be tasks assigned to specific individuals, or general actions that the group has decided to take. Please list these action items clearly and concisely.",

158 },

159 {"role": "user", "content": transcription},

160 ],

161 )458 )

162 return response.choices[0].message.content or ""459```

460 

461```go

462func extractActionItems(ctx context.Context, transcription string) (string, error) {

463 return complete(ctx, transcription, "List every task or follow-up agreed to in the meeting. Include the owner and deadline when the transcript provides them.")

464}

465```

466 

467```java

468static String extractActionItems(String transcription) {

469 return complete(

470 transcription,

471 "List every task or follow-up agreed to in the meeting. "

472 + "Include the owner and deadline when the transcript provides them.");

473}

474```

475 

476```ruby

477def extract_action_items(client, transcription)

478 complete(

479 client,

480 transcription,

481 "List every task or follow-up agreed to in the meeting. Include the owner and deadline when the transcript provides them."

482 )

483end

163```484```

164 485 

165 486 

166### Sentiment analysis487### Sentiment analysis

167 488 

168The `sentiment_analysis` function analyzes the overall sentiment of the discussion. It considers the tone, the emotions conveyed by the language used, and the context in which words and phrases are used. For less complicated tasks, it may also be worthwhile to try [`gpt-5.6-terra`](https://developers.openai.com/api/docs/models/gpt-5.6-terra) to see if you can get a similar level of performance at lower cost and latency. It might also be useful to experiment with taking the results of the `sentiment_analysis` function and passing it to the other functions to see how having the sentiment of the conversation impacts the other attributes.489The sentiment helper classifies the discussion as positive, negative, or neutral and explains the assessment. For simpler tasks, try [`gpt-5.6-terra`](https://developers.openai.com/api/docs/models/gpt-5.6-terra) to see whether it meets your quality target with lower cost and latency.

490 

491```javascript

492async function analyzeSentiment(transcription) {

493 return complete(

494 transcription,

495 "Describe the meeting's overall sentiment as positive, negative, or neutral, and briefly explain the assessment."

496 );

497}

498```

169 499 

170```python500```python

171def sentiment_analysis(transcription):501def sentiment_analysis(transcription: str) -> str:

172 response = client.chat.completions.create(502 return complete(

173 model="gpt-5.5",503 transcription,

174 messages=[504 "Describe the meeting's overall sentiment as positive, negative, or "

175 {505 "neutral, and briefly explain the assessment.",

176 "role": "system",

177 "content": "As an AI with expertise in language and emotion analysis, your task is to analyze the sentiment of the following text. Please consider the overall tone of the discussion, the emotion conveyed by the language used, and the context in which words and phrases are used. Indicate whether the sentiment is generally positive, negative, or neutral, and provide brief explanations for your analysis where possible.",

178 },

179 {"role": "user", "content": transcription},

180 ],

181 )506 )

182 return response.choices[0].message.content or ""507```

508 

509```go

510func analyzeSentiment(ctx context.Context, transcription string) (string, error) {

511 return complete(ctx, transcription, "Describe the meeting's overall sentiment as positive, negative, or neutral, and briefly explain the assessment.")

512}

513```

514 

515```java

516static String analyzeSentiment(String transcription) {

517 return complete(

518 transcription,

519 "Describe the meeting's overall sentiment as positive, negative, or neutral, "

520 + "and briefly explain the assessment.");

521}

522```

523 

524```ruby

525def analyze_sentiment(client, transcription)

526 complete(

527 client,

528 transcription,

529 "Describe the meeting's overall sentiment as positive, negative, or neutral, and briefly explain the assessment."

530 )

531end

183```532```

184 533 

185 534 


189 538 

190 539

191 540 

192 Once we've generated the meeting minutes, it's beneficial to save them541 Save the meeting minutes in a readable format that you can distribute.

193 into a readable format that can be easily distributed. One common format542 Microsoft Word is a common choice for this kind of report. The examples

194 for such reports is Microsoft Word. The Python docx library is a popular543 use a DOCX library suited to each language. In an end-to-end application,

195 open source library for creating Word documents. If you wanted to build an544 you could send the result in an email or write it to another system

196 end-to-end meeting minute application, you might consider removing this545 instead.

197 export step in favor of sending the summary inline as an email followup.

198 546

199 547 

200 548


205 553 

206</br>554</br>

207 555 

208To handle the exporting process, define a function `save_as_docx` that converts the raw text to a Word document:556Define a helper that writes each result section to a Word document:

557 

558```javascript

559async function saveAsDocx(minutes, filename) {

560 const children = Object.entries(minutes).flatMap(([heading, content]) => [

561 new Paragraph({ text: heading, heading: HeadingLevel.HEADING_1 }),

562 new Paragraph({

563 children: content

564 .split(/\r\n?|\n/)

565 .flatMap((line, index) => [

566 ...(index > 0 ? [new TextRun({ break: 1 })] : []),

567 new TextRun(line),

568 ]),

569 }),

570 ]);

571 const document = new Document({ sections: [{ children }] });

572 await fs.promises.writeFile(filename, await Packer.toBuffer(document));

573}

574```

209 575 

210```python576```python

211def save_as_docx(minutes, filename):577def save_as_docx(minutes: dict[str, str], filename: Path) -> None:

212 doc = Document()578 document = Document()

213 for key, value in minutes.items():579 for heading, content in minutes.items():

214 # Replace underscores with spaces and capitalize each word for the heading580 document.add_heading(heading, level=1)

215 heading = " ".join(word.capitalize() for word in key.split("_"))581 document.add_paragraph(content)

216 doc.add_heading(heading, level=1)582 document.save(filename)

217 doc.add_paragraph(value)583```

218 # Add a line break between sections584 

219 doc.add_paragraph()585```go

220 doc.save(filename)586func saveAsDocx(minutes meetingMinutes, filename string) error {

587 document, err := godocx.NewDocument()

588 if err != nil {

589 return err

590 }

591 for _, section := range []struct{ heading, content string }{

592 {"Abstract summary", minutes.AbstractSummary},

593 {"Key points", minutes.KeyPoints},

594 {"Action items", minutes.ActionItems},

595 {"Sentiment", minutes.Sentiment},

596 } {

597 document.AddHeading(section.heading, 1)

598 for _, line := range strings.Split(strings.ReplaceAll(section.content, "\r\n", "\n"), "\n") {

599 document.AddParagraph(line)

600 }

601 }

602 return document.SaveTo(filename)

603}

604```

605 

606```java

607static void saveAsDocx(MeetingMinutes minutes, Path filename) throws IOException {

608 try (var document = new XWPFDocument();

609 OutputStream output = Files.newOutputStream(filename)) {

610 addHeadingStyle(document);

611 addSection(document, "Abstract summary", minutes.abstractSummary());

612 addSection(document, "Key points", minutes.keyPoints());

613 addSection(document, "Action items", minutes.actionItems());

614 addSection(document, "Sentiment", minutes.sentiment());

615 document.write(output);

616 }

617}

618 

619private static void addHeadingStyle(XWPFDocument document) {

620 var headingStyle = CTStyle.Factory.newInstance();

621 headingStyle.setStyleId("Heading1");

622 headingStyle.addNewName().setVal("Heading 1");

623 headingStyle.setType(STStyleType.PARAGRAPH);

624 headingStyle.addNewPPr().addNewOutlineLvl().setVal(BigInteger.ZERO);

625 document.createStyles().addStyle(new XWPFStyle(headingStyle));

626}

627 

628private static void addSection(XWPFDocument document, String heading, String content) {

629 var headingParagraph = document.createParagraph();

630 headingParagraph.setStyle("Heading1");

631 var headingRun = headingParagraph.createRun();

632 headingRun.setBold(true);

633 headingRun.setFontSize(16);

634 headingRun.setText(heading);

635 var contentRun = document.createParagraph().createRun();

636 String[] lines = content.split("\\R", -1);

637 for (int index = 0; index < lines.length; index += 1) {

638 if (index > 0) contentRun.addBreak();

639 contentRun.setText(lines[index]);

640 }

641}

221```642```

222 643 

644```ruby

645def save_as_docx(minutes, filename)

646 Caracal::Document.save(filename) do |document|

647 minutes.each do |heading, content|

648 document.h1(heading)

649 content.split(/\r\n?|\n/, -1).each { |line| document.p(line) }

650 end

651 end

652end

653```

654 

655 

656The helper receives the generated sections and an output filename, adds a heading and paragraph for each section, and saves the document to the current working directory.

223 657 

224In this function, minutes is a dictionary containing the abstract summary, key points, action items, and sentiment analysis from the meeting. Filename is the name of the Word document file to be created. The function creates a new Word document, adds headings and content for each part of the minutes, and then saves the document to the current working directory.658Finally, combine the steps to generate meeting minutes from an audio file:

225 659 

226Finally, you can put it all together and generate the meeting minutes from an audio file:660```javascript

661const transcription = await transcribeAudio("meeting.wav");

662const minutes = await buildMeetingMinutes(transcription);

663console.log(minutes);

664await saveAsDocx(minutes, "meeting_minutes.docx");

665```

227 666 

228```python667```python

229audio_file_path = "Earningscall.wav"668audio_file_path = Path("meeting.wav")

230transcription = transcribe_audio(audio_file_path)669transcription = transcribe_audio(audio_file_path)

231minutes = meeting_minutes(transcription)670minutes = meeting_minutes(transcription)

232print(minutes)671print(minutes)

672save_as_docx(minutes, Path("meeting_minutes.docx"))

673```

674 

675```go

676func main() {

677 ctx := context.Background()

678 transcription, err := transcribeAudio(ctx, "meeting.wav")

679 if err != nil {

680 panic(err)

681 }

682 minutes, err := buildMeetingMinutes(ctx, transcription)

683 if err != nil {

684 panic(err)

685 }

686 fmt.Printf("%+v\n", minutes)

687 if err := saveAsDocx(minutes, "meeting_minutes.docx"); err != nil {

688 panic(err)

689 }

690}

691```

692 

693```java

694public static void main(String[] args) throws IOException {

695 String transcription = transcribeAudio(Path.of("meeting.wav"));

696 MeetingMinutes minutes = buildMeetingMinutes(transcription);

697 System.out.println(minutes);

698 saveAsDocx(minutes, Path.of("meeting_minutes.docx"));

699 }

700}

701```

233 702 

703```ruby

704transcription = transcribe_audio(client, "meeting.wav")

705minutes = build_meeting_minutes(client, transcription)

706puts minutes

234save_as_docx(minutes, "meeting_minutes.docx")707save_as_docx(minutes, "meeting_minutes.docx")

235```708```

236 709 

237 710 

238This code will transcribe the audio file `Earningscall.wav`, generates the meeting minutes, prints them, and then saves them into a Word document called `meeting_minutes.docx`.711This code resolves `meeting.wav` from the process working directory, generates and prints the meeting minutes, and saves them as `meeting_minutes.docx`.

239 712 

240Now that you have the basic meeting minutes processing setup, consider trying to optimize the performance with [prompt engineering](https://developers.openai.com/api/docs/guides/prompt-engineering) or build an end-to-end system with native [function calling](https://developers.openai.com/api/docs/guides/function-calling).713Now that you have a basic meeting minutes workflow, tune the prompts with [prompt engineering](https://developers.openai.com/api/docs/guides/prompt-engineering) or build an end-to-end system with [function calling](https://developers.openai.com/api/docs/guides/function-calling).