For the complete documentation index, see llms.txt. Markdown versions of documentation pages are available by appending .md to the page URL.
Primary navigation

DigitalOcean

Connect a DigitalOcean sandbox to an Agents API session.

Run commands and work with files in a DigitalOcean sandbox while OpenAI runs the agent and maintains session state.

How it works

DigitalOcean’s Managed Agents Runtime Services (M.A.R.S.) starts a Firecracker microVM using the codex-agentapi image. The image includes Codex and starts the executor, which connects outbound to the Agents API.

Choose webhook-managed provisioning to start or resume sandboxes from OpenAI events, or application-managed provisioning to control them from your application. For an interactive quickstart, use the optional DigitalOcean CLI flow. See Sandbox lifecycle for connection and recovery behavior.

M.A.R.S. is in invite-only private preview. Request access through DigitalOcean’s private-preview announcement.

Before you begin

You need a sandbox-enabled DigitalOcean account with access to codex-agentapi and an OpenAI project with Agents API access.

Set OPENAI_API_KEY for your application or CLI and a separate restricted OPENAI_EXECUTOR_API_KEY for the sandbox. The keys must have the same owner, organization, and project. Store only the executor key in the sandbox’s CODEX_API_KEY secret. See executor authentication.

For webhook controllers or Python applications, set DIGITALOCEAN_TOKEN and install the PyDo beta SDK with async support (pydo[aio]). Use the OpenAI SDK for Agents API requests. CLI installation is needed only for the CLI flow.

Webhook-managed

  1. Create a stored agent and save its ID as OPENAI_AGENT_ID. Deploy an HTTPS webhook controller in DigitalOcean App Platform with this ID, OPENAI_API_KEY for session reads, DIGITALOCEAN_TOKEN, and OPENAI_EXECUTOR_API_KEY.
  2. Register its /webhook endpoint with your OpenAI project. Enable agent.session.action_required and agent.session.failed, then store the signing secret as OPENAI_WEBHOOK_SECRET and redeploy the controller.
  3. Follow the session steps with the same OPENAI_AGENT_ID and /workspace as the working directory. Open the event stream and send input. When OpenAI requests an environment_connection, the controller verifies the signature, retrieves the current session, and checks its agent ID and required actions. It looks up mars-{session_id} in DigitalOcean and resumes a paused sandbox or creates one if none is active.
  4. On agent.session.failed, retrieve the session again and delete its sandbox only if the current session status is still failed.

The image connects the executor to the session’s environment. Your application sends input and streams results through the Agents API; the controller handles provisioning and reconnection. Serialize provisioning per session to handle duplicate and concurrent deliveries. See webhook-managed lifecycle guidance for controller requirements.

Try it with the DigitalOcean CLI

The CLI creates both resources and lets you interact with the agent from your terminal. It provisions the sandbox directly, without a webhook controller.

Install the doctl beta release that includes harness-runtime, then authenticate:

doctl auth init

Save this manifest as agents.yaml:

name: openai-codex-session
agent: codex-agentapi
config:
  agent:
    model: gpt-5.6-sol
    instructions: Work from the files in /workspace.
  environment:
    type: self_hosted
    workspace_directory: /workspace
egress:
  - api.openai.com
  - codex-cloud-environments.chatgpt.com
env:
  CODEX_ENVIRONMENT_ID: ${ENV_ID}
secrets:
  CODEX_API_KEY: ${OPENAI_EXECUTOR_API_KEY}

The config block is the OpenAI create-session request. The CLI authenticates that request with OPENAI_API_KEY, fills ${ENV_ID} from the response, and passes only the restricted executor key to the sandbox. Keep resolved manifests out of logs and source control. Add any destinations your tools need to egress.

Create the session and sandbox:

doctl harness-runtime create --spec agents.yaml

The command waits up to 300 seconds for readiness by default. Save the OpenAI session ID and DigitalOcean session ID from the session details, then attach:

doctl harness-runtime launch openai-codex-session

Ask the agent to write hello to /workspace/hello.txt and read it back. Press Ctrl+D to detach without deleting the session, and run the same launch command to reattach. Follow Cleanup when finished.

Application-managed

Use this path when your application owns session creation and sandbox provisioning. Create the OpenAI session first:

Create a self-hosted session
import OpenAI from "openai";
const client = new OpenAI();

const session = await client.beta.agents.sessions.create({
  agent: {
    model: "gpt-6-astra",
    instructions:
      "You are a helpful coding assistant. Write clean code and verify that it works.",
  },
  environment: {
    type: "self_hosted",
    workspace_directory: "/workspace",
  },
});

console.log(session);

Save session.id and the environment ID as described in Connect a sandbox. Save this sandbox-only manifest as sandbox.yaml; the agent configuration was already sent to OpenAI:

agent: codex-agentapi
egress:
  - api.openai.com
  - codex-cloud-environments.chatgpt.com
env:
  CODEX_ENVIRONMENT_ID: ${ENV_ID}
secrets:
  CODEX_API_KEY: ${OPENAI_EXECUTOR_API_KEY}
  1. Create a pydo.aio.Client using DIGITALOCEAN_TOKEN and call client.agents.create_session. Set params.openai_session_id to the OpenAI session ID, body.manifest to the contents of sandbox.yaml, and body.variables to a mapping of ENV_ID and OPENAI_EXECUTOR_API_KEY to their values. Save the returned DigitalOcean session_id.
  2. Open the event stream and send input, asking the agent to write and read /workspace/hello.txt. Input waits for the executor to connect. Confirm the connection event and a completed turn, and inspect the agent’s output for tool failures.
  3. Retrieve the file with workspace_download, using the relative path hello.txt. Keep both resources for follow-up turns, or clean up.

Use bounded setup and execution timeouts and handle connection failures in your application. Do not attach a provisioning webhook handler to sessions your application or CLI manages directly.

Cleanup

Save any files you need, then delete the OpenAI session and destroy the DigitalOcean sandbox. Session deletion does not emit a webhook, so perform both operations and report cleanup failures.

With PyDo, call client.agents.destroy_session with the DigitalOcean session ID. With the CLI, pass that ID or the sandbox’s name:

doctl harness-runtime remove openai-codex-session

Remove the OpenAI webhook registration before deleting a webhook controller.

References