Repository Public
1# API deployment checklist23> For the complete documentation index, see [llms.txt](/llms.txt). Markdown versions of documentation pages are available by appending `.md` to the page URL.45| Contents | Expected impact |6| ------------------------------------------------------------------------------- | ----------------------------------- |7| [Use the Responses API](#use-the-responses-api) | Quality, cost, latency, reliability |8| [Choose a GPT-5.6 model](#choose-a-gpt-56-model) | Quality, cost, latency |9| [Set up `reasoning.effort`](#set-up-reasoningeffort) | Quality, cost, latency |10| [Set up `text.verbosity`](#set-up-textverbosity) | Quality, cost, latency |11| [Set up the assistant `phase` parameter](#set-up-the-assistant-phase-parameter) | Quality, cost |12| [Use `tool_search`](#use-toolsearch) | Cost, latency |13| [Use Programmatic Tool Calling](#use-programmatic-tool-calling) | 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 |16| [Leverage compaction](#leverage-compaction) | Cost |17| [Optimize prompt caching](#optimize-prompt-caching) | Latency, cost |18| [Use `reasoning.encrypted_content`](#use-reasoningencryptedcontent) | Quality, latency |19| [Set image detail intentionally](#set-image-detail-intentionally) | Quality, cost, latency |20| [Send a safety identifier](#send-a-safety-identifier) | Safety, reliability |21| [Use `background=True`](#use-backgroundtrue) | Resuming work |22| [Use WebSocket mode](#use-websocket-mode) | Latency |2324## Use the Responses API2526**Always start** with the27[Responses API](https://developers.openai.com/api/docs/guides/migrate-to-responses). It is OpenAI's flagship28API and the best place to access the newest model behavior, built-in tools,29stateful workflows, and agent features.3031## Choose a GPT-5.6 model3233Choose a [GPT-5.6 model](https://developers.openai.com/api/docs/guides/latest-model?model=gpt-5.6) for the workload instead34of routing every request to the most capable tier. Use `gpt-5.6` or35`gpt-5.6-sol` for flagship capability, `gpt-5.6-terra` for strong performance36at a lower price, and `gpt-5.6-luna` for efficient, high-volume workloads.3738When migrating, preserve the current model's workload role and effective39reasoning effort for the first comparison. Run representative evals before40changing prompts or adding new capabilities. Compare task success, latency,41input, output, reasoning, and cache-write tokens, and cost per successful task.4243## Set up `reasoning.effort`4445Use `reasoning.effort` to decide how much thinking the model should do before it46answers.4748For GPT-5.6 models, the supported values are `none`, `low`, `medium`, `high`,49`xhigh`, and `max`. The default is `medium`. Lower effort is faster and uses50fewer reasoning tokens. Higher effort gives the model more time for planning,51debugging, synthesis, and multi-step tradeoffs.5253Use `low` when the job is mostly extraction, routing, classification, or a54routine rewrite. Use `medium` or `high` when the model needs to diagnose a55problem, compare options, write a plan, or reason through code. Use `xhigh` or56`max` only when representative evals show that the quality gain justifies the57extra latency and cost. When migrating from GPT-5.5 or GPT-5.4, start with the58current effort and compare the same setting with one level lower. GPT-5.6 can59often maintain or improve quality with fewer reasoning tokens, so the lower60setting may also reduce latency and cost.6162For the hardest quality-first workloads, also compare63[`reasoning.mode: "pro"`](https://developers.openai.com/api/docs/guides/reasoning#reasoning-mode) with64standard mode at the same effort. Reasoning mode and effort are independent.65Pro mode can improve reliability by applying more model work before returning a66single final answer, but it increases latency and token usage.6768Tune reasoning effort for the task6970```javascript71import OpenAI from "openai";7273const openai = new OpenAI();7475const prompt = [76 "Our CI job started failing after a dependency bump.",77 "",78 "Error:",79 "TypeError: Timeout.__init__() got an unexpected keyword argument 'connect'",80 "",81 "Identify the likeliest root cause and the smallest safe fix.",82].join("\n");8384const response = await openai.responses.create({85 model: "gpt-6-astra",86 reasoning: { effort: "xhigh", mode: "pro" },87 input: prompt,88});8990console.log(response.output_text);91```9293```python94from openai import OpenAI9596client = OpenAI()9798prompt = """99Our CI job started failing after a dependency bump.100101Error:102TypeError: Timeout.__init__() got an unexpected keyword argument 'connect'103104Identify the likeliest root cause and the smallest safe fix.105"""106107response = client.responses.create(108 model="gpt-6-astra",109 reasoning={"effort": "xhigh", "mode": "pro"},110 input=prompt,111)112113print(response.output_text)114```115116```go117package main118119import (120 "context"121 "fmt"122 "strings"123124 "github.com/openai/openai-go/v3"125 "github.com/openai/openai-go/v3/responses"126 "github.com/openai/openai-go/v3/shared"127)128129func main() {130 client := openai.NewClient()131 prompt := strings.Join([]string{132 "Our CI job started failing after a dependency bump.",133 "",134 "Error:",135 "TypeError: Timeout.__init__() got an unexpected keyword argument 'connect'",136 "",137 "Identify the likeliest root cause and the smallest safe fix.",138 }, "\n")139 reasoning := shared.ReasoningParam{Effort: shared.ReasoningEffortXhigh}140 reasoning.SetExtraFields(map[string]any{"mode": "pro"})141 response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{142 Model: "gpt-6-astra",143 Reasoning: reasoning,144 Input: responses.ResponseNewParamsInputUnion{OfString: openai.String(prompt)},145 })146 if err != nil {147 panic(err)148 }149 fmt.Println(response.OutputText())150}151```152153```java154import com.openai.client.OpenAIClient;155import com.openai.client.okhttp.OpenAIOkHttpClient;156import com.openai.core.JsonValue;157import com.openai.models.Reasoning;158import com.openai.models.ReasoningEffort;159import com.openai.models.responses.ResponseCreateParams;160161ResponseCreateParams params =162 ResponseCreateParams.builder()163 .model("gpt-6-astra")164 .input(165 "Our CI job started failing after a dependency bump. Error: TypeError: Timeout.__init__() got an unexpected keyword argument 'connect'. Identify the likeliest root cause and the smallest safe fix.")166 .reasoning(167 Reasoning.builder()168 .effort(ReasoningEffort.XHIGH)169 .putAdditionalProperty("mode", JsonValue.from("pro"))170 .build())171 .build();172173client.responses().create(params).output().stream()174 .flatMap(item -> item.message().stream())175 .flatMap(message -> message.content().stream())176 .flatMap(content -> content.outputText().stream())177 .forEach(text -> System.out.println(text.text()));178```179180```ruby181require "openai"182183client = OpenAI::Client.new184prompt = <<~PROMPT185 Our CI job started failing after a dependency bump.186187 Error:188 TypeError: Timeout.__init__() got an unexpected keyword argument 'connect'189190 Identify the likeliest root cause and the smallest safe fix.191PROMPT192193response = client.responses.create(194 model: "gpt-6-astra",195 reasoning: {196 effort: :xhigh,197 mode: :pro198 },199 input: prompt200)201202puts(response.output_text)203```204205206## Set up `text.verbosity`207208`text.verbosity` is the main lever for balancing brevity against completeness.209Use lower verbosity when the product needs a quick, compact answer, and higher210verbosity when the response needs richer explanation, clearer structure, or211complete context. Lower verbosity means fewer output tokens, so the model212generates less and returns output faster.213214For coding, `medium` and `high` tend to produce longer, more organized output215with clearer structure. `low` keeps the answer tighter and more minimal.216217GPT-5.6 tends to be more concise by default than GPT-5.5. When migrating, check218whether broad instructions like "Be concise" still help. In some cases, they may219make responses too brief. Keep them only when they still help, and prefer using220`text.verbosity` to control the default level of detail; then use the prompt to221specify required content, structure, and a more specific length, if applicable.222223Set lower verbosity for compact output224225```javascript226import OpenAI from "openai";227228const openai = new OpenAI();229230const incident = [231 "Summarize this incident for the next on-call engineer.",232 "- checkout latency spiked from 220 ms to 4.8 s",233 "- only us-east-1 was affected",234 "- rollback is complete",235 "- likely trigger: cache stampede after deploy",236].join("\n");237238const response = await openai.responses.create({239 model: "gpt-6-astra",240 text: { verbosity: "low" },241 input: incident,242});243244console.log(response.output_text);245```246247```python248from openai import OpenAI249250client = OpenAI()251252response = client.responses.create(253 model="gpt-6-astra",254 text={"verbosity": "low"},255 input="""256 Summarize this incident for the next on-call engineer.257 - checkout latency spiked from 220 ms to 4.8 s258 - only us-east-1 was affected259 - rollback is complete260 - likely trigger: cache stampede after deploy261 """,262)263264print(response.output_text)265```266267```go268package main269270import (271 "context"272 "fmt"273 "strings"274275 "github.com/openai/openai-go/v3"276 "github.com/openai/openai-go/v3/responses"277)278279func main() {280 client := openai.NewClient()281 incident := strings.Join([]string{282 "Summarize this incident for the next on-call engineer.",283 "- checkout latency spiked from 220 ms to 4.8 s",284 "- only us-east-1 was affected",285 "- rollback is complete",286 "- likely trigger: cache stampede after deploy",287 }, "\n")288 response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{289 Model: "gpt-6-astra",290 Text: responses.ResponseTextConfigParam{Verbosity: "low"},291 Input: responses.ResponseNewParamsInputUnion{OfString: openai.String(incident)},292 })293 if err != nil {294 panic(err)295 }296 fmt.Println(response.OutputText())297}298```299300```java301import com.openai.client.OpenAIClient;302import com.openai.client.okhttp.OpenAIOkHttpClient;303import com.openai.models.responses.ResponseCreateParams;304import com.openai.models.responses.ResponseTextConfig;305306ResponseCreateParams params =307 ResponseCreateParams.builder()308 .model("gpt-6-astra")309 .input(310 "Summarize this incident for the next on-call engineer: checkout latency spiked from 220 ms to 4.8 s, only us-east-1 was affected, rollback is complete, and the likely trigger was a cache stampede.")311 .text(ResponseTextConfig.builder().verbosity(ResponseTextConfig.Verbosity.LOW).build())312 .build();313314client.responses().create(params).output().stream()315 .flatMap(item -> item.message().stream())316 .flatMap(message -> message.content().stream())317 .flatMap(content -> content.outputText().stream())318 .forEach(text -> System.out.println(text.text()));319```320321```ruby322require "openai"323324client = OpenAI::Client.new325incident = <<~INCIDENT326 Summarize this incident for the next on-call engineer.327 - checkout latency spiked from 220 ms to 4.8 s328 - only us-east-1 was affected329 - rollback is complete330 - likely trigger: cache stampede after deploy331INCIDENT332333response = client.responses.create(334 model: "gpt-6-astra",335 text: { verbosity: :low },336 input: incident337)338339puts(response.output_text)340```341342343## Set up the assistant `phase` parameter344345`phase` is a label on assistant messages in the conversation history. It346indicates to the model whether a prior assistant message was an intermediate347working commentary or the final answer. Use `phase: "commentary"` for progress348updates, pre-tool-call notes, and other in-between messages. Use349`phase: "final_answer"` for the completed response.350351The assistant might say something like:352353Assistant commentary message354355```json356{357 "role": "assistant",358 "phase": "commentary",359 "content": "I'm checking the logs and comparing them to the last successful deploy."360}361```362363364That is not the answer. It is a progress note. Later, the assistant might say:365366Assistant final answer message367368```json369{370 "role": "assistant",371 "phase": "final_answer",372 "content": "The deploy failed because the migration referenced a column that does not exist in production."373}374```375376377This is useful in long-running or tool-heavy workflows where the assistant may378produce visible progress updates before it finishes. When you send that history379back on follow-up requests for `gpt-5.3-codex` and later models,380**preserve and resend `phase`** on assistant messages so the model can distinguish381progress updates from the final result. This helps reduce early stopping, making382the agent more likely to continue until it reaches the final answer.383384## Use `tool_search`385386Instead of loading the full tool catalog into every request, use387[tool search](https://developers.openai.com/api/docs/guides/tools-tool-search): add388`{"type": "tool_search"}` and mark expensive tool definitions with389`defer_loading: true`. The model can then load the subset it needs at runtime.390At request start, the model only sees the search tool name and description. If391the model decides it needs a deferred tool, it runs tool search, and only then392are the deferred tool definitions loaded into context. Only then will the model393call them. This saves tokens and preserves cache performance.394395Tool search has two modes:396397- **Hosted tool search** is the simpler option. Use it when you already know398 which tools could be available for the request.399- **Client-executed tool search** is for cases where your app has to decide what400 tools are available, like based on the user's tenant, project, permissions, or401 internal registry.402403**Start with hosted tool search** unless your app really needs to control404discovery itself.405406Group your tools by user intent. Use namespaces or MCP servers when you can. It407is easier for the model to choose between a few clear groups than a long flat408list of functions. We recommend keeping each namespace under about 10 functions409for optimal token efficiency and model performance.410411Keep namespace descriptions short and discriminative. Put the detailed412instructions inside the deferred tool definitions. Avoid making one giant413namespace for everything.414415Use hosted tool search with deferred tools416417```javascript418import OpenAI from "openai";419420const openai = new OpenAI();421422const billingNamespace = {423 type: "namespace",424 name: "billing",425 description: "Billing tools for invoices, payments, taxes, and credits.",426 tools: [427 {428 type: "function",429 name: "lookup_invoice",430 description:431 "Look up invoice state, taxes, credits, and payment attempts.",432 parameters: {433 type: "object",434 properties: {435 invoice_id: { type: "string" },436 },437 required: ["invoice_id"],438 additionalProperties: false,439 },440 strict: true,441 defer_loading: true,442 },443 ],444};445446const crmNamespace = {447 type: "namespace",448 name: "crm",449 description:450 "CRM tools for account ownership, plans, health, and payment history.",451 tools: [452 {453 type: "function",454 name: "get_account",455 description: "Fetch account owner, plan, health, and payment history.",456 parameters: {457 type: "object",458 properties: {459 account_id: { type: "string" },460 },461 required: ["account_id"],462 additionalProperties: false,463 },464 strict: true,465 defer_loading: true,466 },467 ],468};469470const response = await openai.responses.create({471 model: "gpt-6-astra",472 input:473 "Find the right billing tool and explain why invoice INV-1043 still " +474 "shows overdue after a payment yesterday.",475 tools: [billingNamespace, crmNamespace, { type: "tool_search" }],476});477478console.log(response.output);479```480481```python482from openai import OpenAI483484client = OpenAI()485486billing_namespace = {487 "type": "namespace",488 "name": "billing",489 "description": "Billing tools for invoices, payments, taxes, and credits.",490 "tools": [491 {492 "type": "function",493 "name": "lookup_invoice",494 "description": "Look up invoice state, taxes, credits, and payment attempts.",495 "parameters": {496 "type": "object",497 "properties": {498 "invoice_id": {"type": "string"},499 },500 "required": ["invoice_id"],501 "additionalProperties": False,502 },503 "strict": True,504 "defer_loading": True,505 }506 ],507}508509crm_namespace = {510 "type": "namespace",511 "name": "crm",512 "description": "CRM tools for account ownership, plans, health, and payment history.",513 "tools": [514 {515 "type": "function",516 "name": "get_account",517 "description": "Fetch account owner, plan, health, and payment history.",518 "parameters": {519 "type": "object",520 "properties": {521 "account_id": {"type": "string"},522 },523 "required": ["account_id"],524 "additionalProperties": False,525 },526 "strict": True,527 "defer_loading": True,528 }529 ],530}531532response = client.responses.create(533 model="gpt-6-astra",534 input=(535 "Find the right billing tool and explain why invoice INV-1043 still "536 "shows overdue after a payment yesterday."537 ),538 tools=[billing_namespace, crm_namespace, {"type": "tool_search"}],539)540541print(response.output)542```543544```go545package main546547import (548 "context"549 "fmt"550551 "github.com/openai/openai-go/v3"552 "github.com/openai/openai-go/v3/responses"553)554555func main() {556 client := openai.NewClient()557 billing := namespaceTool(558 "billing",559 "Billing tools for invoices, payments, taxes, and credits.",560 "lookup_invoice",561 "Look up invoice state, taxes, credits, and payment attempts.",562 "invoice_id",563 )564 crm := namespaceTool(565 "crm",566 "CRM tools for account ownership, plans, health, and payment history.",567 "get_account",568 "Fetch account owner, plan, health, and payment history.",569 "account_id",570 )571 toolSearch := responses.ToolUnionParam{OfToolSearch: &responses.ToolSearchToolParam{}}572 response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{573 Model: "gpt-6-astra",574 Input: responses.ResponseNewParamsInputUnion{OfString: openai.String(575 "Find the right billing tool and explain why invoice INV-1043 still shows overdue after a payment yesterday.",576 )},577 Tools: []responses.ToolUnionParam{billing, crm, toolSearch},578 })579 if err != nil {580 panic(err)581 }582 fmt.Println(response.Output)583}584585func namespaceTool(namespace, namespaceDescription, name, description, argument string) responses.ToolUnionParam {586 parameters := map[string]any{587 "type": "object",588 "properties": map[string]any{589 argument: map[string]any{"type": "string"},590 },591 "required": []string{argument},592 "additionalProperties": false,593 }594 function := responses.NamespaceToolToolFunctionParam{595 Name: name, Description: openai.String(description), Parameters: parameters, Strict: openai.Bool(true), DeferLoading: openai.Bool(true),596 }597 return responses.ToolParamOfNamespace(598 namespaceDescription,599 namespace,600 []responses.NamespaceToolToolUnionParam{{OfFunction: &function}},601 )602}603```604605```java606import com.openai.client.OpenAIClient;607import com.openai.client.okhttp.OpenAIOkHttpClient;608import com.openai.core.JsonValue;609import com.openai.models.responses.NamespaceTool;610import com.openai.models.responses.ResponseCreateParams;611import com.openai.models.responses.ToolSearchTool;612import java.util.List;613import java.util.Map;614615ResponseCreateParams params =616 ResponseCreateParams.builder()617 .model("gpt-6-astra")618 .input(619 "Find the right billing tool and explain why invoice INV-1043 still shows overdue after a payment yesterday.")620 .addTool(621 namespace(622 "billing",623 "Billing tools for invoices, payments, taxes, and credits.",624 "lookup_invoice",625 "Look up invoice state, taxes, credits, and payment attempts.",626 "invoice_id"))627 .addTool(628 namespace(629 "crm",630 "CRM tools for account ownership, plans, health, and payment history.",631 "get_account",632 "Fetch account owner, plan, health, and payment history.",633 "account_id"))634 .addTool(ToolSearchTool.builder().execution(ToolSearchTool.Execution.SERVER).build())635 .build();636637client.responses().create(params).output().forEach(System.out::println);638639private static NamespaceTool namespace(640 String name,641 String description,642 String function,643 String functionDescription,644 String argument) {645 return NamespaceTool.builder()646 .name(name)647 .description(description)648 .addTool(649 NamespaceTool.Tool.Function.builder()650 .name(function)651 .description(functionDescription)652 .deferLoading(true)653 .strict(true)654 .parameters(655 JsonValue.from(656 Map.of(657 "type",658 "object",659 "properties",660 Map.of(argument, Map.of("type", "string")),661 "required",662 List.of(argument),663 "additionalProperties",664 false)))665 .build())666 .build();667}668```669670```ruby671require "openai"672673def namespace_tool(name, description, function_name, function_description, argument)674 {675 type: :namespace,676 name: name,677 description: description,678 tools: [679 {680 type: :function,681 name: function_name,682 description: function_description,683 defer_loading: true,684 strict: true,685 parameters: {686 type: "object",687 properties: { argument => { type: "string" } },688 required: [argument],689 additionalProperties: false690 }691 }692 ]693 }694end695696client = OpenAI::Client.new697billing = namespace_tool(698 "billing",699 "Billing tools for invoices, payments, taxes, and credits.",700 "lookup_invoice",701 "Look up invoice state, taxes, credits, and payment attempts.",702 "invoice_id"703)704crm = namespace_tool(705 "crm",706 "CRM tools for account ownership, plans, health, and payment history.",707 "get_account",708 "Fetch account owner, plan, health, and payment history.",709 "account_id"710)711712response = client.responses.create(713 model: "gpt-6-astra",714 input: "Find the right billing tool and explain why invoice INV-1043 still shows overdue after a payment yesterday.",715 tools: [billing, crm, { type: :tool_search }]716)717718puts(response.output)719```720721722## Use Programmatic Tool Calling723724[Programmatic Tool Calling](https://developers.openai.com/api/docs/guides/tools-programmatic-tool-calling)725lets GPT-5.6 write JavaScript that calls eligible tools and reduces their726intermediate results inside a hosted runtime. Use it for bounded stages where727code can filter, join, rank, remove duplicates, combine, or check large tool728results before returning a smaller structured result to the model.729730Add the `programmatic_tool_calling` tool and opt in each eligible tool. Use731`allowed_callers: ["programmatic"]` for program-only tools, or use732`allowed_callers: ["direct", "programmatic"]` when the model may also call the733tool directly. Keep calls direct when each result may change the model's next734decision, an action requires approval, or the final answer must preserve735citations or native artifacts. Document tool return fields and error behavior so736the model can write a correct program without first inspecting a result.737738Your tool loop must handle `program` and `program_output` items, as well as739program-issued `function_call` items and their `function_call_output` items.740Preserve each `call_id`, and copy the function call's `caller` into its output so741the service can resume the correct program.742743Test both the `program_output` and the final assistant message. A correct program744result can still become an incomplete final answer. Compare task success,745required evidence, total tokens, latency, and cost against the same workflow746using direct tool calls.747748## Use Multi-agent for parallel work749750[Multi-agent](https://developers.openai.com/api/docs/guides/responses-multi-agent) is a GPT-5.6 feature that751lets a root agent delegate independent workstreams to subagents and synthesize752their results. Use it when you can split research, analysis, or implementation753into concrete, bounded tasks that use separate context and run in parallel.754755Set `multi_agent.enabled` to `true` in the request. For HTTP, use the beta756Responses SDK with `client.beta.responses` and pass `responses_multi_agent=v1`757in `betas`. For raw HTTP or WebSocket connections, send758`OpenAI-Beta: responses_multi_agent=v1`. Item schemas can change while759Multi-agent is in beta.760761Prefer one agent for short tasks, ordered chains where each step depends on the762last, or work that writes to the same mutable resource. Subagents can increase763token usage, so start with the default `max_concurrent_subagents` value of `3`764and measure end-to-end quality, latency, and cost. For tool-heavy or long-running765Multi-agent workflows, WebSocket mode can reduce continuation overhead.766767Before enabling Multi-agent, account for its current limitations:768`/responses/compact`, `reasoning.summary`, and `max_tool_calls` are not769supported. The server automatically compacts the root context and every770subagent context.771772## Leverage built-in tools773774[Built-in tools](https://developers.openai.com/api/docs/guides/tools) are native capabilities of the API.775Instead of building every tool yourself, you can give the model access to tools776that already work inside the Responses API. The model can then decide when to777use them.778779OpenAI keeps adding more native tools, so start with built-in tools when they780fit your workflow. Build custom tools when native options do not cover the task.781Current built-in tools and related tool options include:782783- **Web search**: Search the web for up-to-date information784- **File search**: Search uploaded files or vector stores785- **Code interpreter**: Run Python for analysis, math, charts, and file786 processing787- **Shell**: Run shell commands in a hosted container or your own runtime788- **Computer use**: Operate a UI through screenshots, clicks, typing, and789 scrolling790- **Image generation**: Generate or edit images791- **MCP/connectors**: Connect the model to external services and tools792- **Skills**: Attach reusable instruction bundles and workflow files793- **Apply patch**: Make structured code edits794795Model quality is another reason to prefer them. Built-in tools are796in-distribution for our post-training, meaning that the models are trained and797evaluated around these tool shapes, behaviors, and outputs. With built-in tools,798OpenAI models support better tool selection, cleaner execution, and fewer799failures than with new tools.800801## Leverage compaction802803[Compaction](https://developers.openai.com/api/docs/guides/compaction) is a context engineering tool: it804decides what information the model carries forward across many turns. In805long-running agents, the problem is not just, "Will I hit the context limit?" It806is that old messages, tool logs, retries, and stale details crowd out the state807the model needs.808809Compaction gives you a controlled way to reduce context size while preserving810state needed for subsequent turns. After a meaningful milestone, like finishing811a debugging phase or narrowing a root cause, you can compact the prior window812and continue from the compacted output. This keeps the model sharp because the813next turn is built around the important state, not every intermediate reasoning,814failed command, and obsolete branch of reasoning.815816You can use compaction in two ways:817818- **Let the server handle it**: if you use `previous_response_id`, turn on819 `context_management` with a `compact_threshold`. The server will automatically820 compact the conversation when it gets too large. You keep sending only the821 newest user message.822- **Do it yourself**: if you manage the full input array yourself, call823 `client.responses.compact()`. It gives back a smaller context window. Use that824 returned output directly in the next `responses.create()` call.825826**Do not edit the compacted output.** It is not a human summary, but the machine827state that helps the model continue. Pass it forward as-is, then add the next828user message.829830Continue from compacted response state831832```javascript833import OpenAI from "openai";834import { toResponseInputItems } from "openai/lib/responses/ResponseInputItems";835836const openai = new OpenAI();837838// Full window collected from a long debugging session:839// user messages, assistant outputs, tool calls, and tool outputs.840const longWindow = sessionItems;841842const compacted = await openai.responses.compact({843 model: "gpt-6-astra",844 input: longWindow,845});846847const nextResponse = await openai.responses.create({848 model: "gpt-6-astra",849 store: false,850 input: [851 // Preserve replayable compacted items.852 ...toResponseInputItems(compacted.output),853 {854 type: "message",855 role: "user",856 content:857 "We found the bad cache invalidation path. Write the fix plan " +858 "and the verification checklist.",859 },860 ],861});862863console.log(nextResponse.output_text);864```865866```python867from openai import OpenAI868869client = OpenAI()870871# Full window collected from a long debugging session:872# user messages, assistant outputs, tool calls, and tool outputs.873long_window = session_items874875compacted = client.responses.compact(876 model="gpt-6-astra",877 input=long_window,878)879880next_response = client.responses.create(881 model="gpt-6-astra",882 store=False,883 input=[884 *compacted.output, # Use compact output as-is.885 {886 "type": "message",887 "role": "user",888 "content": (889 "We found the bad cache invalidation path. Write the fix plan "890 "and the verification checklist."891 ),892 },893 ],894)895896print(next_response.output_text)897```898899```go900package main901902import (903 "context"904 "encoding/json"905 "fmt"906907 "github.com/openai/openai-go/v3"908 "github.com/openai/openai-go/v3/responses"909)910911func main() {912 client := openai.NewClient()913 longWindow := []responses.ResponseInputItemUnionParam{914 responses.ResponseInputItemParamOfMessage("Find the cache invalidation bug in this debugging session.", responses.EasyInputMessageRoleUser),915 }916 compacted, err := client.Responses.Compact(context.Background(), responses.ResponseCompactParams{917 Model: "gpt-6-astra",918 Input: responses.ResponseCompactParamsInputUnion{OfResponseInputItemArray: longWindow},919 })920 if err != nil {921 panic(err)922 }923 input := append(outputAsInput(compacted.Output),924 responses.ResponseInputItemParamOfMessage(925 "We found the bad cache invalidation path. Write the fix plan and the verification checklist.",926 responses.EasyInputMessageRoleUser,927 ),928 )929 nextResponse, err := client.Responses.New(context.Background(), responses.ResponseNewParams{930 Model: "gpt-6-astra",931 Store: openai.Bool(false),932 Input: responses.ResponseNewParamsInputUnion{OfInputItemList: input},933 })934 if err != nil {935 panic(err)936 }937 fmt.Println(nextResponse.OutputText())938}939940func outputAsInput(output []responses.ResponseOutputItemUnion) []responses.ResponseInputItemUnionParam {941 input := make([]responses.ResponseInputItemUnionParam, 0, len(output))942 for _, item := range output {943 var converted responses.ResponseInputItemUnion944 if err := json.Unmarshal([]byte(item.RawJSON()), &converted); err != nil {945 panic(err)946 }947 input = append(input, converted.ToParam())948 }949 return input950}951```952953```java954import com.openai.client.OpenAIClient;955import com.openai.client.okhttp.OpenAIOkHttpClient;956import com.openai.models.responses.EasyInputMessage;957import com.openai.models.responses.ResponseCompactParams;958import com.openai.models.responses.ResponseCompactionItemParam;959import com.openai.models.responses.ResponseCreateParams;960import com.openai.models.responses.ResponseInputItem;961import java.util.ArrayList;962963var compacted =964 client965 .responses()966 .compact(967 ResponseCompactParams.builder()968 .model("gpt-6-astra")969 .input("Find the cache invalidation bug in this debugging session.")970 .build());971var input = new ArrayList<ResponseInputItem>();972for (var item : compacted.output()) {973 item.message().map(ResponseInputItem::ofResponseOutputMessage).ifPresent(input::add);974 item.reasoning().map(ResponseInputItem::ofReasoning).ifPresent(input::add);975 item.compaction()976 .map(977 value ->978 ResponseInputItem.ofCompaction(979 ResponseCompactionItemParam.builder()980 .id(value.id())981 .encryptedContent(value.encryptedContent())982 .build()))983 .ifPresent(input::add);984}985input.add(986 ResponseInputItem.ofEasyInputMessage(987 EasyInputMessage.builder()988 .role(EasyInputMessage.Role.USER)989 .content(990 "We found the bad cache invalidation path. Write the fix plan and the verification checklist.")991 .build()));992993client994 .responses()995 .create(996 ResponseCreateParams.builder()997 .model("gpt-6-astra")998 .inputOfResponse(input)999 .store(false)1000 .build())1001 .output()1002 .stream()1003 .flatMap(item -> item.message().stream())1004 .flatMap(message -> message.content().stream())1005 .flatMap(content -> content.outputText().stream())1006 .forEach(text -> System.out.println(text.text()));1007```10081009```ruby1010require "openai"10111012client = OpenAI::Client.new1013long_window = [1014 {1015 role: :user,1016 content: "Find the cache invalidation bug in this debugging session."1017 }1018]10191020compacted = client.responses.compact(1021 model: "gpt-6-astra",1022 input: long_window1023)1024input = compacted.output.dup1025input << {1026 role: :user,1027 content: "We found the bad cache invalidation path. Write the fix plan and the verification checklist."1028}10291030response = client.responses.create(1031 model: "gpt-6-astra",1032 store: false,1033 input: input1034)10351036puts(response.output_text)1037```103810391040<a id="use-promptcachekey"></a>10411042<a id="separate-prompts-with-promptcachekey"></a>10431044## Optimize prompt caching10451046[Prompt caching](https://developers.openai.com/api/docs/guides/prompt-caching) automatically reduces latency1047and cost when requests reuse the same long prefix. Put stable instructions,1048examples, and reference material first, followed by dynamic user-specific1049content. Keep tool definitions and ordering stable, and append new conversation1050turns without rewriting earlier context.10511052GPT-5.6 introduced explicit prompt caching. Implicit caching remains the1053default, but GPT-5.6 models and later model families also support explicit1054cache breakpoints and request-wide cache policy. If a changing suffix comes1055after a stable prefix, add an explicit `prompt_cache_breakpoint` at the reusable boundary. Set1056`prompt_cache_options.mode` to `explicit` only when the request should use only1057the breakpoints you provide and no implicit breakpoint. Earlier models continue1058to use automatic prompt caching only.10591060On GPT-5.6 models and later model families, cache writes cost 1.25× the1061uncached input token rate. Log `cached_tokens` and `cache_write_tokens`, then1062compare write volume with later cache reads to measure net cost and tune1063breakpoint placement.10641065Use a stable `prompt_cache_key` for requests that share a reusable prefix to1066help route related requests to the same cache and optimize cache hit rates on1067models before GPT-5.6. For busy groups, follow the [guidance for distributing1068traffic across more keys](https://developers.openai.com/api/docs/guides/prompt-caching#prompt-cache-keys).10691070On GPT-5.6 and later, `prompt_cache_key` is optional: you can achieve optimal1071cache hit rates without it. You can use it to maintain separate cache accounting1072for customers, users, or workspaces. This can make cached token usage and billing1073easier to explain for each group. Assign a distinct key to each customer and1074keep it stable across that customer's related requests. Separate keys also help1075prevent cache-hit probing across customers. See [Separate cache accounting with1076keys](https://developers.openai.com/api/docs/guides/prompt-caching#separate-prompts-with-cache-keys).10771078Maintain separate cache accounting for a customer10791080```javascript1081import OpenAI from "openai";10821083const openai = new OpenAI();10841085const instructions = [1086 "You are the support agent for Acme.",1087 "Follow the Acme support policy and escalation rubric.",1088 "Use the same tone, safety rules, and tool plan for each ticket.",1089].join("\n");10901091const response = await openai.responses.create({1092 model: "gpt-6-astra",1093 prompt_cache_key: "tenant-acme-support-agent",1094 instructions,1095 input: "Summarize the current escalation for the on-call lead.",1096});10971098console.log(response.output_text);1099```11001101```python1102from openai import OpenAI11031104client = OpenAI()11051106instructions = """1107You are the support agent for Acme.1108Follow the Acme support policy and escalation rubric.1109Use the same tone, safety rules, and tool plan for each ticket.1110"""11111112response = client.responses.create(1113 model="gpt-6-astra",1114 prompt_cache_key="tenant-acme-support-agent",1115 instructions=instructions,1116 input="Summarize the current escalation for the on-call lead.",1117)11181119print(response.output_text)1120```11211122```go1123package main11241125import (1126 "context"1127 "fmt"1128 "strings"11291130 "github.com/openai/openai-go/v3"1131 "github.com/openai/openai-go/v3/responses"1132)11331134func main() {1135 client := openai.NewClient()1136 instructions := strings.Join([]string{1137 "You are the support agent for Acme.",1138 "Follow the Acme support policy and escalation rubric.",1139 "Use the same tone, safety rules, and tool plan for each ticket.",1140 }, "\n")1141 response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{1142 Model: "gpt-6-astra",1143 PromptCacheKey: openai.String("tenant-acme-support-agent"),1144 Instructions: openai.String(instructions),1145 Input: responses.ResponseNewParamsInputUnion{OfString: openai.String("Summarize the current escalation for the on-call lead.")},1146 })1147 if err != nil {1148 panic(err)1149 }1150 fmt.Println(response.OutputText())1151}1152```11531154```java1155import com.openai.client.OpenAIClient;1156import com.openai.client.okhttp.OpenAIOkHttpClient;1157import com.openai.models.responses.ResponseCreateParams;11581159ResponseCreateParams params =1160 ResponseCreateParams.builder()1161 .model("gpt-6-astra")1162 .instructions(1163 "You are the support agent for Acme.\n"1164 + "Follow the Acme support policy and escalation rubric.\n"1165 + "Use the same tone, safety rules, and tool plan for each ticket.")1166 .input("Summarize the current escalation for the on-call lead.")1167 .promptCacheKey("tenant-acme-support-agent")1168 .build();11691170client.responses().create(params).output().stream()1171 .flatMap(item -> item.message().stream())1172 .flatMap(message -> message.content().stream())1173 .flatMap(content -> content.outputText().stream())1174 .forEach(text -> System.out.println(text.text()));1175```11761177```csharp1178using OpenAI.Responses;1179#pragma warning disable OPENAI00111801181string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;1182ResponsesClient client = new(key);11831184CreateResponseOptions options = new()1185{1186 Model = "gpt-6-astra",1187 PromptCacheKey = "tenant-acme-support-agent",1188 Instructions = "Follow the Acme support policy and escalation rubric.",1189};1190options.InputItems.Add(1191 ResponseItem.CreateUserMessageItem("Summarize the current escalation for the on-call lead.")1192);11931194ResponseResult response = await client.CreateResponseAsync(options);1195Console.WriteLine(response.GetOutputText());1196```11971198```ruby1199require "openai"12001201client = OpenAI::Client.new1202instructions = <<~INSTRUCTIONS1203 You are the support agent for Acme.1204 Follow the Acme support policy and escalation rubric.1205 Use the same tone, safety rules, and tool plan for each ticket.1206INSTRUCTIONS12071208response = client.responses.create(1209 model: "gpt-6-astra",1210 prompt_cache_key: "tenant-acme-support-agent",1211 instructions: instructions,1212 input: "Summarize the current escalation for the on-call lead."1213)12141215puts(response.output_text)1216```121712181219## Use `reasoning.encrypted_content`12201221GPT-5.6 can [preserve reasoning across1222calls](https://developers.openai.com/api/docs/guides/reasoning#preserve-reasoning-across-calls). Use1223`reasoning.context: "all_turns"` when the task's goals, assumptions, and1224priorities remain stable. Use `current_turn` when earlier reasoning is no longer1225relevant and might anchor the model to an outdated approach. If you omit1226`reasoning.context` or set it to `auto`, inspect the response's1227`reasoning.context` field to confirm the effective mode.12281229[Persisted reasoning](https://developers.openai.com/api/docs/guides/reasoning#keeping-reasoning-items-in-context)1230works only when earlier reasoning items are available. Use `previous_response_id`1231for stored responses. If your [Zero Data Retention1232(ZDR)](https://developers.openai.com/api/docs/guides/your-data#zero-data-retention) requirements do not allow1233storing response data, encrypted reasoning content enables a stateless1234handoff.12351236Reasoning items in the response output include encrypted reasoning content by1237default. You can access the encrypted reasoning content from each reasoning1238item's `encrypted_content` property. Your app does not need to understand that1239value. It just keeps each reasoning item exactly as returned and sends it back1240during the next turn, so the model can use it to continue the workflow.12411242Pass encrypted reasoning between stateless turns12431244```javascript1245import OpenAI from "openai";1246import { toResponseInputItems } from "openai/lib/responses/ResponseInputItems";12471248const openai = new OpenAI();12491250const history = [1251 {1252 role: "user",1253 content: "Investigate why invoice INV-1043 has mismatched tax totals.",1254 },1255];12561257const first = await openai.responses.create({1258 model: "gpt-6-astra",1259 store: false,1260 reasoning: { effort: "medium", context: "current_turn" },1261 input: history,1262});12631264history.push(...toResponseInputItems(first.output));1265history.push({1266 role: "user",1267 content: "Now write the customer-facing explanation in plain English.",1268});12691270const second = await openai.responses.create({1271 model: "gpt-6-astra",1272 store: false,1273 reasoning: { effort: "medium", context: "all_turns" },1274 input: history,1275});12761277console.log(second.output_text);1278```12791280```python1281from openai import OpenAI12821283client = OpenAI()12841285history = [1286 {1287 "role": "user",1288 "content": "Investigate why invoice INV-1043 has mismatched tax totals.",1289 }1290]12911292first = client.responses.create(1293 model="gpt-6-astra",1294 store=False,1295 reasoning={"effort": "medium", "context": "current_turn"},1296 input=history,1297)12981299history.extend(item.model_dump(exclude={"status"}) for item in first.output)1300history.append(1301 {1302 "role": "user",1303 "content": "Now write the customer-facing explanation in plain English.",1304 }1305)13061307second = client.responses.create(1308 model="gpt-6-astra",1309 store=False,1310 reasoning={"effort": "medium", "context": "all_turns"},1311 input=history,1312)13131314print(second.output_text)1315```13161317```go1318package main13191320import (1321 "context"1322 "encoding/json"1323 "fmt"13241325 "github.com/openai/openai-go/v3"1326 "github.com/openai/openai-go/v3/responses"1327 "github.com/openai/openai-go/v3/shared"1328)13291330func main() {1331 client := openai.NewClient()1332 history := []responses.ResponseInputItemUnionParam{1333 responses.ResponseInputItemParamOfMessage("Investigate why invoice INV-1043 has mismatched tax totals.", responses.EasyInputMessageRoleUser),1334 }1335 first, err := client.Responses.New(context.Background(), responses.ResponseNewParams{1336 Model: "gpt-6-astra",1337 Store: openai.Bool(false),1338 Reasoning: shared.ReasoningParam{Effort: shared.ReasoningEffortMedium, Context: shared.ReasoningContextCurrentTurn},1339 Include: []responses.ResponseIncludable{responses.ResponseIncludableReasoningEncryptedContent},1340 Input: responses.ResponseNewParamsInputUnion{OfInputItemList: history},1341 })1342 if err != nil {1343 panic(err)1344 }1345 history = append(history, outputAsInput(first.Output)...)1346 history = append(history, responses.ResponseInputItemParamOfMessage(1347 "Now write the customer-facing explanation in plain English.",1348 responses.EasyInputMessageRoleUser,1349 ))1350 second, err := client.Responses.New(context.Background(), responses.ResponseNewParams{1351 Model: "gpt-6-astra",1352 Store: openai.Bool(false),1353 Reasoning: shared.ReasoningParam{Effort: shared.ReasoningEffortMedium, Context: shared.ReasoningContextAllTurns},1354 Input: responses.ResponseNewParamsInputUnion{OfInputItemList: history},1355 })1356 if err != nil {1357 panic(err)1358 }1359 fmt.Println(second.OutputText())1360}13611362func outputAsInput(output []responses.ResponseOutputItemUnion) []responses.ResponseInputItemUnionParam {1363 input := make([]responses.ResponseInputItemUnionParam, 0, len(output))1364 for _, item := range output {1365 var converted responses.ResponseInputItemUnion1366 if err := json.Unmarshal([]byte(item.RawJSON()), &converted); err != nil {1367 panic(err)1368 }1369 input = append(input, converted.ToParam())1370 }1371 return input1372}1373```13741375```java1376import com.openai.client.OpenAIClient;1377import com.openai.client.okhttp.OpenAIOkHttpClient;1378import com.openai.core.JsonValue;1379import com.openai.models.Reasoning;1380import com.openai.models.responses.EasyInputMessage;1381import com.openai.models.responses.ResponseCreateParams;1382import com.openai.models.responses.ResponseIncludable;1383import com.openai.models.responses.ResponseInputItem;1384import java.util.ArrayList;13851386var history = new ArrayList<ResponseInputItem>();1387history.add(1388 ResponseInputItem.ofEasyInputMessage(1389 EasyInputMessage.builder()1390 .role(EasyInputMessage.Role.USER)1391 .content("Investigate why invoice INV-1043 has mismatched tax totals.")1392 .build()));13931394var first =1395 client1396 .responses()1397 .create(1398 ResponseCreateParams.builder()1399 .model("gpt-6-astra")1400 .inputOfResponse(history)1401 .store(false)1402 .reasoning(1403 Reasoning.builder()1404 .effort(com.openai.models.ReasoningEffort.MEDIUM)1405 .putAdditionalProperty("context", JsonValue.from("current_turn"))1406 .build())1407 .addInclude(ResponseIncludable.of("reasoning.encrypted_content"))1408 .build());1409first.output().stream()1410 .map(item -> JsonValue.from(item).convert(ResponseInputItem.class))1411 .forEach(history::add);1412history.add(1413 ResponseInputItem.ofEasyInputMessage(1414 EasyInputMessage.builder()1415 .role(EasyInputMessage.Role.USER)1416 .content("Now write the customer-facing explanation in plain English.")1417 .build()));14181419client1420 .responses()1421 .create(1422 ResponseCreateParams.builder()1423 .model("gpt-6-astra")1424 .inputOfResponse(history)1425 .store(false)1426 .reasoning(1427 Reasoning.builder()1428 .effort(com.openai.models.ReasoningEffort.MEDIUM)1429 .putAdditionalProperty("context", JsonValue.from("all_turns"))1430 .build())1431 .build())1432 .output()1433 .stream()1434 .flatMap(item -> item.message().stream())1435 .flatMap(message -> message.content().stream())1436 .flatMap(content -> content.outputText().stream())1437 .forEach(text -> System.out.println(text.text()));1438```14391440```ruby1441require "openai"14421443client = OpenAI::Client.new1444history = [1445 {1446 role: :user,1447 content: "Investigate why invoice INV-1043 has mismatched tax totals."1448 }1449]14501451first = client.responses.create(1452 model: "gpt-6-astra",1453 store: false,1454 reasoning: {1455 effort: :medium,1456 context: :current_turn1457 },1458 include: ["reasoning.encrypted_content"],1459 input: history1460)1461history.concat(first.output)1462history << {1463 role: :user,1464 content: "Now write the customer-facing explanation in plain English."1465}14661467second = client.responses.create(1468 model: "gpt-6-astra",1469 store: false,1470 reasoning: {1471 effort: :medium,1472 context: :all_turns1473 },1474 input: history1475)14761477puts(second.output_text)1478```147914801481## Set image detail intentionally14821483On GPT-5.6 models, omitted image `detail` and `detail: "auto"` use the same1484sizing behavior as `original`. The service preserves the input dimensions,1485except that images larger than 65,535 pixels on either side are scaled down to1486fit that limit. The API rejects images that still exceed the1487[30,000-patch limit](https://developers.openai.com/api/docs/guides/images-vision#image-input-requirements),1488rather than resizing them to fit it. Large images can use more input tokens and1489add latency as a result.14901491Choose [`detail`](https://developers.openai.com/api/docs/guides/images-vision#choose-an-image-detail-level)1492for the task. Resize the image, use `low` when fine visual detail is not1493important, or use `high` for standard high-fidelity image understanding. Keep1494`original` for large, dense, coordinate-sensitive, OCR, localization, or1495visual-inspection tasks where the extra detail improves quality. Measure1496worst-case image tokens and latency before deployment.14971498## Send a safety identifier14991500If your application serves individual end users, send a stable,1501privacy-preserving1502[`safety_identifier`](https://developers.openai.com/api/docs/guides/safety-best-practices#implement-safety-identifiers)1503with each request. It helps OpenAI detect misuse and gives your team a stable way1504to trace policy violations. It also reduces the chance that one user's misuse1505disrupts access for your broader organization.15061507Hash the user's username or email address instead of sending identifying1508information. For logged-out experiences, use a stable session ID.15091510## Use `background=True`15111512Use [`background=True`](https://developers.openai.com/api/docs/guides/background) for requests that may take1513a long time. Instead of keeping the client connection open, the API starts a job1514and returns an ID. Your app can poll that job until it finishes, fails, or is1515canceled. Use it for large analyses, long tool runs, or work that needs status1516and retry behavior.15171518Run and poll a background response15191520```javascript1521// Replace the illustrative IDs and URLs below with your own resource values.1522import OpenAI from "openai";15231524const openai = new OpenAI();1525const logBundleFileId = "file_123";15261527let job = await openai.responses.create({1528 model: "gpt-6-astra",1529 background: true,1530 store: false,1531 input: "Analyze this large log bundle and cluster the primary failure modes.",1532 tools: [1533 {1534 type: "code_interpreter",1535 container: {1536 type: "auto",1537 file_ids: [logBundleFileId],1538 },1539 },1540 ],1541});15421543while (["queued", "in_progress"].includes(job.status)) {1544 await new Promise((resolve) => setTimeout(resolve, 2000));1545 job = await openai.responses.retrieve(job.id);1546}15471548console.log(job.output_text);1549```15501551```python1552# Replace the illustrative IDs and URLs below with your own resource values.1553from openai import OpenAI1554import time15551556client = OpenAI()1557log_bundle_file_id = "file_123"15581559job = client.responses.create(1560 model="gpt-6-astra",1561 background=True,1562 store=False,1563 input="Analyze this large log bundle and cluster the primary failure modes.",1564 tools=[1565 {1566 "type": "code_interpreter",1567 "container": {1568 "type": "auto",1569 "file_ids": [log_bundle_file_id],1570 },1571 }1572 ],1573)15741575while job.status in {"queued", "in_progress"}:1576 time.sleep(2)1577 job = client.responses.retrieve(job.id)15781579print(job.output_text)1580```15811582```go1583package main15841585import (1586 "context"1587 "fmt"1588 "time"15891590 "github.com/openai/openai-go/v3"1591 "github.com/openai/openai-go/v3/responses"1592)15931594func main() {1595 client := openai.NewClient()1596 tool := responses.ToolParamOfCodeInterpreter(responses.ToolCodeInterpreterContainerCodeInterpreterContainerAutoParam{1597 FileIDs: []string{"file_abc123"},1598 })1599 job, err := client.Responses.New(context.Background(), responses.ResponseNewParams{1600 Model: "gpt-6-astra",1601 Background: openai.Bool(true),1602 Store: openai.Bool(false),1603 Input: responses.ResponseNewParamsInputUnion{OfString: openai.String("Analyze this large log bundle and cluster the primary failure modes.")},1604 Tools: []responses.ToolUnionParam{tool},1605 })1606 if err != nil {1607 panic(err)1608 }1609 for job.Status == responses.ResponseStatusQueued || job.Status == responses.ResponseStatusInProgress {1610 time.Sleep(2 * time.Second)1611 job, err = client.Responses.Get(context.Background(), job.ID, responses.ResponseGetParams{})1612 if err != nil {1613 panic(err)1614 }1615 }1616 fmt.Println(job.OutputText())1617}1618```16191620```java1621import com.openai.client.OpenAIClient;1622import com.openai.client.okhttp.OpenAIOkHttpClient;1623import com.openai.models.responses.ResponseCreateParams;1624import com.openai.models.responses.ResponseStatus;1625import com.openai.models.responses.Tool;16261627String fileId = "file_abc123";16281629ResponseCreateParams params =1630 ResponseCreateParams.builder()1631 .model("gpt-6-astra")1632 .input("Analyze this large log bundle and cluster the primary failure modes.")1633 .background(true)1634 .store(false)1635 .addCodeInterpreterTool(1636 Tool.CodeInterpreter.Container.CodeInterpreterToolAuto.builder()1637 .addFileId(fileId)1638 .build())1639 .build();16401641var response = client.responses().create(params);1642while (response.status().filter(ResponseStatus.QUEUED::equals).isPresent()1643 || response.status().filter(ResponseStatus.IN_PROGRESS::equals).isPresent()) {1644 Thread.sleep(1000);1645 response = client.responses().retrieve(response.id());1646}1647if (response.status().filter(ResponseStatus.COMPLETED::equals).isEmpty()) {1648 throw new IllegalStateException(1649 "Research ended with status: " + response.status().orElseThrow());1650}16511652response.output().stream()1653 .flatMap(item -> item.message().stream())1654 .flatMap(message -> message.content().stream())1655 .flatMap(content -> content.outputText().stream())1656 .forEach(text -> System.out.println(text.text()));1657```16581659```ruby1660require "openai"16611662client = OpenAI::Client.new16631664job = client.responses.create(1665 model: "gpt-6-astra",1666 background: true,1667 store: false,1668 input: "Analyze this large log bundle and cluster the primary failure modes.",1669 tools: [1670 {1671 type: :code_interpreter,1672 container: {1673 type: :auto,1674 file_ids: ["file_abc123"]1675 }1676 }1677 ]1678)16791680while [:queued, :in_progress].include?(job.status)1681 sleep(2)1682 job = client.responses.retrieve(job.id)1683end16841685puts(job.output_text)1686```168716881689You can combine it with `stream=True` for progress events, but the first event1690may take longer than a normal request.16911692From the UI perspective, background mode indicates, "This is running; here is1693the status; the result will appear here when it's ready."16941695## Use WebSocket mode16961697[WebSocket mode](https://developers.openai.com/api/docs/guides/websocket-mode) is built for long-running,1698tool-call-heavy workflows where you keep a persistent connection open and1699continue by sending only new input items plus `previous_response_id`. For1700runs with 20 or more tool calls, this approach is roughly 40% faster1701end-to-end.17021703**How this works**: The first message will look like a normal Responses request:1704model, instructions, tools, and user input. The server streams events back. If1705the model asks for a tool, your app runs the tool. Then, instead of sending a new1706HTTP request, you send another `response.create` event on the same socket with1707the prior `previous_response_id` and the new item. That is where the latency win1708comes from. In plain HTTP, every follow-up is a fresh request. In WebSocket mode,1709the connection stays open and the most recent response state stays warm in1710memory on that connection. When the next turn continues from that response, the1711backend has to do less setup work.17121713If your workflow is one request, one answer, then **keep HTTP**. If your1714workflow behaves like a long-running agent, try WebSocket mode.17151716A single WebSocket connection handles one in-flight response at a time, so1717parallel work needs multiple connections. Connections currently top out at 601718minutes. Continuation uses the same `previous_response_id` semantics as HTTP1719mode, with a connection-local cache for the most recent response.17201721Note: WebSocket mode works with ZDR because your data is not stored to disk,1722only stored in memory.17231724The Python sample uses `pip install "openai[realtime]>=3.8.0"`.1725The JavaScript sample uses `npm install openai@^7.10.0 ws`.1726The Ruby sample uses `gem install openai async-websocket`.17271728Start a Responses API WebSocket session17291730```javascript1731import OpenAI from "openai";1732import { ResponsesWS } from "openai/resources/responses/ws";17331734const openai = new OpenAI();17351736const ws = new ResponsesWS(openai);17371738ws.on("event", (event) => {1739 console.log(event.type);1740 if (1741 event.type === "response.completed" ||1742 event.type === "response.failed" ||1743 event.type === "response.incomplete"1744 ) {1745 ws.close();1746 }1747});1748ws.on("error", (error) => {1749 console.error(error);1750 ws.close();1751});17521753ws.send({1754 type: "response.create",1755 model: "gpt-6-astra",1756 store: false,1757 input: [1758 {1759 type: "message",1760 role: "user",1761 content: [1762 {1763 type: "input_text",1764 text:1765 "Find the flaky test in this run, call the tools you need, " +1766 "and keep going until you can explain the root cause.",1767 },1768 ],1769 },1770 ],1771 tools: [testLogTool, codeSearchTool],1772});1773```17741775```python1776from openai import OpenAI17771778client = OpenAI()17791780with client.responses.connect() as connection:1781 # Use the same typed parameters as client.responses.create(...).1782 connection.response.create(1783 model="gpt-6-astra",1784 store=False,1785 input=[1786 {1787 "type": "message",1788 "role": "user",1789 "content": [1790 {1791 "type": "input_text",1792 "text": (1793 "Find the flaky test in this run, call the tools "1794 "you need, and keep going until you can explain "1795 "the root cause."1796 ),1797 }1798 ],1799 }1800 ],1801 tools=[test_log_tool, code_search_tool],1802 )1803 first_event = connection.recv()1804 print(first_event.type)1805```18061807```ruby1808require "async"1809require "openai"1810require "json"18111812def wait_for_response(connection)1813 while (event = connection.receive)1814 case event.type.to_s1815 when "response.completed" then return event.response1816 when "response.failed", "response.incomplete", "error"1817 raise "Response failed: #{event.to_json}"1818 end1819 end1820 raise "Connection closed before the response finished"1821end18221823test_log_tool = {1824 type: "function",1825 name: "search_test_logs",1826 description: "Search test logs.",1827 parameters: {1828 type: "object",1829 properties: { query: { type: "string" } },1830 required: ["query"],1831 additionalProperties: false1832 },1833 strict: true1834}1835code_search_tool = {1836 type: "function",1837 name: "search_code",1838 description: "Search source code.",1839 parameters: {1840 type: "object",1841 properties: { query: { type: "string" } },1842 required: ["query"],1843 additionalProperties: false1844 },1845 strict: true1846}18471848client = OpenAI::Client.new1849Sync do |task|1850 task.with_timeout(120) do1851 client.responses.connect(request_options: { timeout: 10 }) do |connection|1852 connection.response.create(1853 stream_id: "main", model: "gpt-6-astra", store: false,1854 input: [1855 {1856 role: "user",1857 content: "Find the flaky test in this run, call the tools you need, and keep going until you can explain the root cause."1858 }1859 ],1860 tools: [test_log_tool, code_search_tool]1861 )1862 puts(JSON.pretty_generate(wait_for_response(connection).output.map(&:to_h)))1863 end1864 end1865end1866```186718681869## Final takeaway18701871Responses API is the foundation for building smarter, more capable OpenAI1872applications. The real advantage is that it lets developers move from one-off1873prompts to durable, tool-using, context-aware workflows that can adapt to the1874complexity of the task. Follow this guide to see higher performance in real1875deployments.