---
title: Agent Adapters (public)
description: Harness Runtime adapters select which coding agent or framework runs in the sandbox and which platform features, such as approvals and checkpoints, …
product: Managed Agents
url: https://docs.digitalocean.com/products/managed-agents/agent-harness-runtime/concepts/agent-adapters/
last_updated: "2026-09-23"
---

> **For AI agents:** The documentation index is at [https://docs.digitalocean.com/llms.txt](https://docs.digitalocean.com/llms.txt). Markdown versions of pages use the same URL with `index.html.md` in place of the HTML page (for example, append `index.html.md` to the directory path instead of opening the HTML document).

# Agent Adapters (public)

DigitalOcean Harness Runtime provides managed, hardware-isolated microVM sandboxes with built-in tools such as Chromium to run harnesses and execute arbitrary code. Rich lifecycle APIs preserve conversational history and working state across sessions, letting you pause, resume, and fork work to control costs and adapt to the nonlinear nature of agentic workflows. Scale complete agents such as Claude Code or use sandboxes independently for code execution, all through the same service. See [What You Can Build](https://docs.digitalocean.com/products/managed-agents/agent-harness-runtime/details/what-you-can-build/index.html.md) for example use cases.

An adapter is the value of the `agent` field in a Harness Runtime environment spec. It selects the coding agent or framework that runs inside the sandbox, the sandbox image that boots, and the set of platform features the session supports. Choosing an adapter is the first decision in a spec, and it constrains everything after it.

## Available Adapters

| Adapter | Runs |
|---|---|
| `codex` | Codex CLI |
| `claude-code` | Claude Code |
| `opencode` | OpenCode |
| `hermes` | Hermes |
| `langgraph` | A LangGraph application |
| `codex-agentapi` | Codex through the OpenAI Agents environment |
| `custom` | A container image you supply |

## What `codex-agentapi` Does Differently

Almost every adapter works the same way: DigitalOcean runs the agent inside the sandbox and watches what it does, translating the agent’s native output into a single event vocabulary and enforcing your permission policy as it goes.

The `codex-agentapi` adapter is the exception. There, OpenAI runs the agent and DigitalOcean supplies only the sandbox, which runs an execution server that OpenAI drives. Conversation history and session state live with OpenAI. Because DigitalOcean never sees the agent’s individual actions, the platform features built on seeing them do not apply.

| Capability | Other adapters | `codex-agentapi` |
|---|---|---|
| Session lifecycle, billing, and sandbox isolation | Yes | Yes |
| DigitalOcean event stream and `doctl harness-runtime logs` | Yes | No, events come from OpenAI |
| [Permission policy](https://docs.digitalocean.com/products/managed-agents/agent-harness-runtime/concepts/permissions/index.html.md) enforcement | Yes | No |
| [Approvals](https://docs.digitalocean.com/products/managed-agents/agent-harness-runtime/concepts/approvals/index.html.md) | Yes | No |
| Checkpoint, fork, and rollback | Yes | No, these return `501` |
| [Action Gateway](https://docs.digitalocean.com/products/managed-agents/action-gateway/index.html.md) tools | Yes | No |

Both use the same environment spec and the same session commands, so nothing in day-to-day use signals which one you are on.

Choose `codex-agentapi` when you want the OpenAI-managed Codex experience and need DigitalOcean only for the sandbox. Choose `codex` when you want Codex CLI under DigitalOcean supervision with permissions, approvals, and checkpoints. For procedures, along with the egress, permission, webhook, and cleanup requirements, see [Run an OpenAI Agents API Session](https://docs.digitalocean.com/products/managed-agents/agent-harness-runtime/how-to/run-openai-agents-api-session/index.html.md).

## OpenAI Agents API Ownership

With `codex-agentapi`, OpenAI owns the agent loop and session state. DigitalOcean runs the sandbox and the executor. The sandbox image includes Codex and starts `codex exec-server`, which connects outbound to the OpenAI Agents API. No custom image, Dockerfile, entrypoint, or inbound public address is required.

Your application creates the OpenAI session, sends input, and reads the OpenAI event stream. A provisioning controller, your application, or `doctl` creates the corresponding DigitalOcean sandbox.

The sandbox receives two OpenAI-specific values:

- `CODEX_ENVIRONMENT_ID`: Identifies the self-hosted environment associated with the OpenAI session.
- `CODEX_API_KEY`: Contains an OpenAI environment key that authorizes the executor connection.

The application or CLI uses `OPENAI_API_KEY` for OpenAI API operations. Pass only the separate executor environment key into the sandbox as `CODEX_API_KEY`.

```
flowchart LR
    App["Your application"]
    OpenAI["OpenAI Agents API"]
    Controller["Provisioning controller"]
    Sandbox["DigitalOcean sandbox"]

    App -->|"Create session and send input"| OpenAI
    OpenAI -->|"Request environment connection"| Controller
    Controller -->|"Create or resume sandbox"| Sandbox
    Sandbox -->|"Register executor"| OpenAI
    OpenAI -->|"Commands"| Sandbox
    Sandbox -->|"Results"| OpenAI
    OpenAI -->|"Event stream"| App
```

The CLI flow combines session and sandbox creation in `doctl harness-runtime create --spec`. The application-managed flow creates the OpenAI session first and then calls the DigitalOcean API. The webhook-managed flow responds to OpenAI events.

## OpenAI Provisioning Models

Choose one provisioning model for each OpenAI session. Do not mix models for the same session.

| Model | Who creates the sandbox | Typical use |
|---|---|---|
| CLI | `doctl harness-runtime create --spec` | Interactive terminal sessions |
| Application-managed | Your application through PyDo | Application-owned orchestration |
| Webhook-managed | An HTTPS controller on OpenAI lifecycle events | Unattended provisioning from OpenAI |

CLI provisioning reads the OpenAI create-session request from `config` in the environment spec, creates both resources, waits for readiness, and lets you attach from a terminal. It does not use a webhook controller.

Application-managed provisioning creates the OpenAI session first, obtains its environment ID, and calls PyDo to create the DigitalOcean sandbox. The application owns connection handling, execution timeouts, and cleanup. Do not attach a provisioning webhook to an application-managed session. Concurrent provisioning paths can create duplicate sandboxes for the same OpenAI session.

Webhook-managed provisioning subscribes to `agent.session.action_required` and `agent.session.failed`. When OpenAI requests an `environment_connection`, the controller verifies the webhook signature, retrieves the current session, validates the stored agent ID and required action, and serializes provisioning for that session. It resumes a paused sandbox when one exists, or creates a sandbox when none is active. On `agent.session.failed`, it retrieves the session again and destroys the matching DigitalOcean sandbox only if the current OpenAI session status remains `failed`.

## OpenAI Session Identifiers

An OpenAI self-hosted session has an environment ID that identifies the executor connection it expects. Pass that value into the DigitalOcean sandbox as `CODEX_ENVIRONMENT_ID`.

Keep these identifiers together for each workload:

- OpenAI session ID for OpenAI API operations
- OpenAI environment ID for the executor connection
- DigitalOcean session ID for sandbox operations

OpenAI input waits for the executor to connect. Preserve both session IDs because the two systems manage separate resources.

## OpenAI Lifecycle and Recovery

Keep both resources for follow-up turns. In a webhook-managed flow, an `environment_connection` action can cause the controller to resume a paused sandbox or create a replacement.

Serialize provisioning per OpenAI session. Duplicate and concurrent webhook deliveries are normal, so handlers must be idempotent. If sandbox creation times out before returning an ID, reconcile DigitalOcean sessions before retrying. Creating another sandbox without checking can leave more than one DigitalOcean resource associated with the same OpenAI session.

When work is complete, save any required files, delete the OpenAI session, and remove the DigitalOcean sandbox. Deleting the OpenAI session does not emit a cleanup webhook, so perform both operations and report either failure. See [Run an OpenAI Agents API Session](https://docs.digitalocean.com/products/managed-agents/agent-harness-runtime/how-to/run-openai-agents-api-session/index.html.md).

## Adapters and Sandbox Images

Each adapter maps to a sandbox image that has the agent, its dependencies, and the in-sandbox runtime already installed. Setting `agent` selects the image for you. Setting `template` in the spec pins a different image, including a custom image your team has built.

The `custom` adapter takes a container image and an entrypoint instead of a named agent, which lets you run an agent Harness Runtime does not have an adapter for. You give up the adapter-specific translation of agent output, so the event stream carries less structure.

## Adapter Names in Specs and API Responses

The spec field uses the names in the table. API responses and event payloads use an underlying enumeration whose members do not always match, most visibly `codex`, which appears as `AGENT_KIND_CODEX_CLI`. Write specs against the spec names. For the full field reference, see the [environment spec reference](https://docs.digitalocean.com/products/managed-agents/agent-harness-runtime/reference/environment-spec/index.html.md).