Deleting an OpenAI Agents API session does not stop the self-hosted compute attached to it. A cleanup button that only deletes the conversation can leave the executor and its files running in your infrastructure. OpenAI documents this separation in its sandbox lifecycle guide.
The Agents API entered public beta on September 10, 2026. OpenAI operates the Codex harness; your application can supply the execution environment. That split is useful when you need control over compute and network access, but it gives your application responsibility for startup, reconnection, and teardown.
The procedure below combines the API documentation with General Analysis recommendations. We have not run a deployment for this article. For the wider rollout baseline, see securing coding agents.
Decide whether this deployment fits your data requirements#
With self-hosting, your infrastructure executes tools while OpenAI continues to run the harness. The API overview says the service retains session state, currently supports data residency only in the United States, and does not support Zero Data Retention. A self-hosted sandbox does not change that eligibility.
Make this decision before connecting internal data. If a workload requires ZDR or another residency region, this beta is not a fit for that requirement. A private network around the executor cannot change what the API retains.
See how your AI systems hold up under real attacks
General Analysis maps AI applications and agents, red teams prompts, retrieval, tools, MCP servers, browser actions, permissions, and business workflows, then turns findings into evidence your team can reproduce and retest.
Connect the executor with its own identity#
In a self-hosted environment, codex exec-server carries out shell, file, and local MCP operations requested by the harness. Its connection is outbound. OpenAI's setup guide lists https://api.openai.com for registration and wss://codex-cloud-environments.chatgpt.com for commands and results.
Prepare an isolated environment with the required files and Codex CLI. The current beta setup uses @openai/codex@alpha; record the resolved version in your image build so a later rollout can be reviewed. Create a session from the application with environment.type set to self_hosted and a working directory such as /workspace.
Store the returned session ID, environment ID, and remote URL with the provider's compute identifier. Start one executor for that session. Reuse the returned remote URL unchanged, including on reconnect.
Code source: OpenAI self-hosted executor setup, adapted to named environment variables. Run inside the prepared environment with its restricted key already supplied as CODEX_API_KEY.
codex exec-server \
--remote "$REMOTE_URL" \
--environment-id "$ENVIRONMENT_ID"
Create a restricted environment key in the platform dashboard, with every other permission set to None. The executor key must match the session owner's organization, project, and user or service account. It only permits environment connections. Keep the broader application API key outside the sandbox: agent-generated code can read credentials available inside it.
OpenAI's sandbox security guidance separates application permissions (api.agents.read, api.agents.write, and api.responses.write) from the environment key. It also recommends brokering third-party credentials outside execution. Fetching a secret from a secrets manager and then injecting it into the sandbox still exposes it to generated code.
Executor MCP connections originate in your environment; remote MCP connections originate in OpenAI's service. An executor egress rule cannot govern both paths. Record which connection type each integration uses before treating a firewall log as a complete account of tool traffic.
Let the event trigger a state check#
Choose one component to own provisioning for each session. Give it a durable mapping to provider compute and a way to serialize concurrent requests. Otherwise, a repeated startup request can allocate another environment while the first one is still connecting.
For webhook-managed startup, subscribe to agent.session.action_required and distinguish environment_connection from function_call. OpenAI's webhook documentation says to retrieve the session and inspect its current required_actions. The event can arrive after the condition has changed. A request for a function result should not start a sandbox.
Verify the signature, queue the work durably, then acknowledge it. The provisioning worker should confirm that the session belongs to its workload and still needs a connection before allocating compute. Use the session's current environment ID and remote URL. In the session stream, the corresponding required-action event is named agent.session.requires_action; it is not the webhook event name.
OpenAI's connection-wait rules allow up to five minutes for an input-time environment connection. Configure the application's request and proxy timeouts for that wait. Do not send the same input again while the original submission is waiting: a timely connection lets it continue.
Separate connection health from work completion#
The application needs two records: whether the executor connected, and whether the requested work finished successfully.
An idle session can follow a failed turn, and a completed turn can contain failed tool calls. Check the target turn and its tool results before marking the application job successful. The session and turn outcome rules explicitly distinguish these states.
A mid-turn disconnect deserves an outcome check before a retry. The reconnection documentation says it does not automatically restart a killed command or request reconnection through a webhook. Later input can request a connection; a late connection does not replay input that already timed out. Reusing an environment ID also does not restore files onto replacement compute.
Consider a reporting task that writes an output file, then loses its connection before returning the path. Reconnecting alone cannot tell the application whether the file exists or whether another run would overwrite it. Check the recorded tool outcome and the provider's workspace before accepting another attempt. For operations with external effects, inspect the destination system too.
Make shutdown and deletion explicit application operations#
Keep compute available between turns until your controller can coordinate shutdown with incoming work. The shutdown guidance warns that an idle event can occur just before waiting input begins execution. A timer that stops compute on every idle notification can therefore interrupt new work.
For permanent cleanup, the recommended application procedure is:
- Mark the job as closing and reject new input. Have the same owner drain or cancel pending provisioning so cleanup cannot race with a new allocation.
- Record the session and provider resource identifiers outside the sandbox. Retain only the output and evidence your policy requires.
- Delete the API session and separately stop its provider compute. Record each result independently and retry whichever operation remains incomplete.
- Apply the provider's deletion policy to retained workspace volumes, snapshots, and application exports. Keep the cleanup record until every required resource is accounted for.
The session management reference notes that deletion removes the session from the API while physical cleanup may continue asynchronously. To interrupt work while retaining the conversation, use active-turn cancellation instead of session deletion. Neither an API deletion receipt nor a missing session is proof that your provider's stored files have been purged.
This procedure needs a periodic reconciliation pass. Compare your owned compute inventory with the application registry, then investigate resources with no valid owner. A failed API call must not erase the only record of where the executor is running. The related CI recovery guide covers the same need to preserve resource identity when a deployment partially succeeds.
Set acceptance criteria before unattended use#
Use the following cases in an isolated pilot with synthetic files. These are proposed acceptance criteria, not completed tests or claims about a particular sandbox provider.
| Case | Evidence the application should retain |
|---|---|
| Two startup requests reach the worker | One owned compute allocation, or an explicit reconciliation record for any surplus |
| A connection request is already resolved | A fresh session lookup and no unnecessary allocation |
| Input arrives during a shutdown delay | Shutdown cancellation or a documented reconnect path that preserves the input outcome |
| The executor disconnects during a file write | Tool outcome plus workspace inspection before retry approval |
| A turn completes with a failed tool | Application job remains incomplete until the required result is verified |
| Session deletion succeeds but provider cleanup fails | A remaining cleanup task with the provider ID and bounded retry policy |
| Replacement compute starts | Verified required files or an explicit decision to start with an empty workspace |
Before enabling unattended use, have the operator recover a job after an application restart. They should be able to find its compute, resolve any uncertain input outcome, and show separate receipts for session deletion and provider cleanup.

