Engines and adapters
How Codex, Claude, and OpenCode are driven behind a neutral adapter, the runtime path versus ACP, and the Codex subscription relay.
An engine is the rented inner loop. UseAgent does not build the agent that decides what to do; it drives an existing one and owns everything around it.
Engine
The coding agent runtime, such as Codex, Claude, or OpenCode. It decides what to
do and emits native events. The harness drives each turn one-shot from outside
the sandbox, but the engine process itself is resident inside the thread’s
sandbox and reused across turns: OpenCode runs a persistent opencode serve
(backend/src/engines/opencode-server.ts), and the ACP Claude and Codex route
keeps a resident relay whose session is reloaded turn to turn
(backend/src/engines/acp-server.ts). The settled invariants are narrower than
“exits per run”: no engine UI servers or iframes, and no engine process
outliving its thread’s sandbox.
Engine adapter
The translator between an engine’s protocol and UseAgent’s thread, command, and
event contracts. Adapters live in backend/src/engines/. The adapter’s job is to
turn an engine’s native stream into canonical steps and to accept control (start,
cancel, and reply turns) from the command lane.
Runtime path versus ACP
There are two adapter routes, with different levels of authoritative lifecycle support:
Runtime path
The primary orchestration route (backend/src/engines/runtime-*). It carries
authoritative history, approvals, questions, child agents, patches, todos,
reasoning, and usage. It is an adapter path, not a second product UI.
ACP
Agent Client Protocol, used by the legacy resident Codex and Claude route when the runtime path is not selected. It has fewer authoritative lifecycle surfaces than the runtime path.
Selection of the runtime path is operator-gated: RUNTIME_RUN_ADAPTER_ENABLED
turns it on (off unless 1 or true), and RUNTIME_RUN_ADAPTER_MODE chooses
canary, which uses a thread and run allowlist, or all
(backend/src/engines/runtime-adapter.ts). With no
RUNTIME_RUN_ADAPTER_ENGINES list configured, the runtime lane covers codex and
opencode while claude stays on the ACP compatibility path. The shipped
deployment enables the lane in mode=all (deploy/hetzner/configure-host.sh).
The production worker resolves an engine registry before each turn. Native
OpenCode and selected runtime-path routes receive a concrete ProviderDriver;
legacy ACP Claude and Codex execution is declared as an EngineAdapter
compatibility path.
Codex subscription relay
A one-use, run-bound WebSocket capability. It lets a managed ChatGPT subscription drive a run without ever copying OAuth state into the sandbox: the Codex app-server and the ChatGPT OAuth stay on the trusted backend, while only the Codex exec-server runs inside Cube or Daytona.
One grant per run: the backend issues a one-use relay URL, the sandbox dials it through the Caddy public origin, and the relay bridges to a backend codex app-server so OAuth never enters the sandbox.
It is proven end to end in production: first turns, multi-turn replies (the relay continues a bound thread when the driver restarts), and the run-bound tool surface all run live. This is also the one direct backend WebSocket ingress; other product traffic stays behind the frontend.
Engine readiness is credential-mode aware
A release proves the path that matches how an engine authenticates. A subscription-only Codex release proves the connected account and the native turn path; an API-key engine proves its mapped gateway provider. Readiness checks do not assume a single credential shape across engines.