A customer starts a long document analysis, closes the tab and returns to an empty screen. Your backend may still be waiting for a response, may have lost the connection or may have completed the work without saving the result. Asking the customer to click again can create a second task while the first is still running.
OpenAI background mode provides asynchronous response generation through the Responses API. It helps separate model execution from a single connection. It does not replace your application's job record, customer permissions or recovery process. The architecture below is a recommended implementation pattern around the API, not a native end-to-end customer workflow guarantee.
Choose the task boundary before enabling background mode
Start with a bounded task such as preparing a document comparison or drafting a migration analysis for review. Define the inputs, the expected output and who can view the result. Do not combine open-ended research, customer approval and external writes into an indistinguishable background operation.
Create the response with background set to true. The returned response object gives your backend an ID to retain. OpenAI documents retrieving that response through the Responses GET endpoint and polling while its status remains queued or in_progress.
A terminal response state means the polling loop can stop waiting for generation. Your application still needs to decide whether the outcome is acceptable. A completed generation can contain an unusable answer. A different terminal outcome can require operator review, a corrected input or a deliberately approved new attempt.
Keep your job ID separate from the response ID
Give the customer an application job ID that your system owns. Associate it with the provider response ID, the customer account, the initiating user, the input version and the approved task type. These fields are suggested application records, not additional fields that OpenAI automatically maintains for your business.
| Record | Purpose | Recovery question |
|---|---|---|
| Application job ID | Stable customer reference | Which requested task is this? |
| Response ID | Retrieve the provider response | Which model execution is attached? |
| Customer and actor | Authorize access and cancellation | Who may see or stop the work? |
| Input version | Bind the result to its source | Was the source changed after submission? |
| Action journal | Track external business effects separately | What was attempted outside generation? |
Write the returned response ID as soon as it is available. If the create request fails before your system receives an ID, preserve the attempt as unresolved rather than claiming that no execution exists. Your recovery design must distinguish a confirmed rejection from a lost acknowledgement.
Run polling from a recoverable backend worker
Let the browser read your job status rather than making the browser responsible for the whole task. A worker retrieves the saved response, updates the application record and continues polling when the provider reports queued or in_progress. Set a polling schedule and an operational deadline appropriate to the task.
A failed retrieval is not the same as a failed generation. Keep the last confirmed provider status, the last successful check and the current retrieval problem separately. This prevents a temporary network error from turning a still-running task into a second generation request.
When your deadline is reached, move the application job into an explicit state such as review required or cancellation requested. Define what happens next. An alert without an owner can leave customer work running without anyone responsible for resolving it.
Make cancellation a separate authorized action
OpenAI provides a cancel operation for an in-flight background response. Its guide says repeated cancellation is idempotent and subsequent calls return the final Response object. That property applies to cancelling the model response, not to every business action your application might have performed.
Authorize the cancellation request against the customer job before using its response ID. Record the request, call the provider operation and reconcile the returned state. If generation already finished, the interface should reflect the verified final state rather than promise that a completed result was stopped.
Track any external writes separately. Cancelling generation does not demonstrate that an email was unsent, a CRM update was reversed or a file was removed. For tools with side effects, keep an action journal and a recovery owner. The same separation belongs in an AI agent operating handoff.
Review temporary storage before sensitive deployments
Do not equate store=false with no temporary storage. OpenAI's current background guide says response data is temporarily stored to disk for roughly ten minutes to enable asynchronous execution and polling. It also says background requests from Zero Data Retention projects run with store=false while still using temporary storage.
For projects using Modified Abuse Monitoring, including its enhanced form, the guide distinguishes foreground defaults from background responses. Background responses are retained beyond the temporary polling period only when store=true is explicitly supplied. Verify the actual project settings and current documentation before selecting the request configuration.
Bring that behavior to the customer's security review. Check whether the intended data can use this feature under the customer's requirements. Review your own job database, result archive and logs separately. The provider's temporary response behavior does not define retention for copies your application keeps or data sent to other services.
Resume streams only when the request supports it
If the product needs incremental output, OpenAI documents creating the response with both background and stream set to true. Its guide supports resuming with the response ID and a cursor based on stored event sequence numbers. It also states that starting a new stream requires the original background response to have stream=true.
Persist the last handled stored-event cursor with the job. Do not treat transport keepalive counters as stored-event resume positions. After reconnection, make result rendering tolerant of repeated delivery around a reconnect so the interface does not append the same content twice.
Polling may be enough for a first release. A clear running state and a verified final result can be easier to operate than a streaming interface whose recovery behavior has not been tested.
Test the gaps between submission and delivery
- Close the browser after creation and reopen the same job.
- Restart the worker after saving the response ID.
- Interrupt a retrieval without submitting another generation.
- Request cancellation during execution and again after a terminal result.
- Change the source input and verify that the old result stays tied to its original version.
- Attempt to read or cancel another customer's job and confirm access is denied.
Use these as release checks alongside output review. Our agent acceptance testing guide explains how to define observable outcomes instead of relying only on a plausible final answer.
How Remqa can help
Remqa provides forward deployed engineering for AI customer rollouts. We can help scope a background task, connect it to customer data and build the status, cancellation and recovery paths around it.
Bring one long-running customer workflow and its current failure cases. Start with a recoverable task boundary and a clear owner for each outcome before expanding the rollout.