Skip to content

Managed Runtime Host

The Managed Runtime Host is the deployment-side layer around a worker or an in-sandbox harness. It owns compute lifetime, /workspace, final deliverables, and split-brain fencing. It does not change the Managed Agents API.

An official self-hosted Environment remains exactly:

await client.beta.environments.create({
name: "my worker pool",
config: { type: "self_hosted" },
});

Provider, volume, checkpoint, output, and retention settings belong to the Runtime Host deployment. Do not put them in Environment.config or Environment.metadata.

The API client creates the Session. It never creates a sandbox and a webhook never owns a work item. OpenMA supports three embedded activation strategies:

StrategyOuter control planeRuntime owner
claim_then_acquireOfficial SDK poller claims and ACKs, then Runtime Host acquires computeOuter Runtime Host owns heartbeat/stop
poll_unacked_then_dispatchRaw work.poll reserves delivery without ACK, then dispatches to a session runtimeCloudflare/GKE runtime sends the first heartbeat/ACK and owns heartbeat/stop
acquire_then_session_pollDurable webhook intent launches compute before Work is polledAWS in-VM worker polls, claims, heartbeats, and stops Work

The common host-owned sequence is:

API client OpenMA control plane Environment Worker sandbox
| POST Session | | |
|----------------------->| durable enqueue | |
| |-- signed run_started -->| wake hint |
| |<------ work.poll -------| atomic claim |
| |<------ work.ack --------| |
| |<-- GET claimed Session -| sessions_token |
| | |-- acquire/restore ->|
| | |-- stage inputs ---->|
| | |---- start -------->|
| |<----- heartbeat -----------------------------|
| |<----- Session events/results ----------------|
| |<----- work.stop ------------------------------|

session.status_run_started contains the Session ID and workspace identity, not the queued work payload. The receiver verifies the Standard Webhooks signature and then calls the official Work poller. A missing, duplicate, late, or out-of-order webhook is harmless because work is claimed only by GET /v1/environments/{environment_id}/work/poll. run() polls immediately at startup and then every five seconds by default, so it is also the durable fallback when webhook delivery is lost.

Only the claim_then_acquire lane uses the SDK poller that ACKs before yielding. Cloudflare and GKE use the raw poll endpoint and intentionally leave the item unacknowledged until the session runtime establishes ownership with its first heartbeat. AWS does not poll from the launcher at all. A reserved but unacknowledged item becomes reclaimable after reclaim_older_than_ms; an acknowledged item becomes reclaimable only after its heartbeat lease expires. Two replacement replicas may race, but the server-side CAS selects one. The old generation then receives 412 Precondition Failed on heartbeat. OpenMA keeps any provider launch generation as internal fencing metadata; it does not add fields to the official Work response.

Work and webhook payloads do not carry a Session snapshot. After a Session Work is claimed, the embedded OpenMA worker decodes the claim’s sessions_token, calls GET /v1/sessions/{session_id}, and validates both the Session ID and Environment ID. Only then may profileFor(work, session) choose the runtime profile. session.metadata is the same opaque string map written by the Session creator; OpenMA does not assign generic meanings to keys such as repo, commit_sha, or input_file.

session.resources is not opaque metadata. The same Session response includes the official file, github_repository, and memory_store resource records, including file IDs, repository URLs, mount paths, and branch/commit checkout data. The control plane returns these records; it does not itself write them into the sandbox.

If the deployment supplies SessionInputMaterializerPort, the Runtime Host invokes it after workspace/output/credential-egress attachment and before the harness process starts. It receives both the official resource array and the opaque metadata map; this is where a runtime clones repositories, downloads files, and interprets any application keys. A Session with one or more official resources is rejected before compute allocation when this Port is absent; OpenMA never starts a harness with silently missing file/repository/memory inputs. Opaque metadata alone does not require a materializer. A failed Session GET or failed input materialization does not start the harness and leaves the Work reclaimable after its lease expires.

Webhook delivery is an optimization with official delivery semantics: the event ID and body remain stable across at most three attempts, while each attempt receives a fresh timestamp and signature. OpenMA applies jittered exponential backoff from five to 120 seconds. Only a 3xx redirect is non-retryable because official delivery disables that endpoint immediately; other non-2xx responses consume the three-attempt budget. The deployment must still operate a periodic poller because webhooks are not a durable log.

Set these control-plane variables to emit the wake hint:

Terminal window
OMA_MANAGED_AGENTS_WEBHOOK_URL=https://worker.example/webhooks/managed-agents
OMA_MANAGED_AGENTS_WEBHOOK_SIGNING_KEY=whsec_...
OMA_MANAGED_AGENTS_ORGANIZATION_ID=org_... # optional; workspace ID is the fallback

The receiving Worker must subscribe to session.status_run_started, call handleWebhook() for signed requests, and keep run() active. For claim_then_acquire and poll_unacked_then_dispatch, run() periodically polls Work as the lost-webhook fallback. For acquire_then_session_poll, it reconciles a durable activation-intent queue instead; the provider runtime is the only Work poller. Scaling is replica-based and every state transition is CAS/fence protected.

createManagedEnvironmentWorkerInstallation() is the provider-neutral entry point. Set mode to runtime_host, provider_dispatch, provider_activation, or external_worker. Dispatch and activation modes dynamically import only their selected isolated adapter package. The external mode starts no local scheduler: OpenMA exposes the unchanged Work API and the operator owns the Worker below it.

For runtime_host, the same entry point can load a provider driver and project its resource Ports into the common fence/persistence/output state machine:

const installation = await createManagedEnvironmentWorkerInstallation({
mode: "runtime_host",
adapter: {
provider: "daytona",
moduleSpecifier: "@open-managed-agents/managed-runtime-daytona",
factoryOptions: daytonaOptions,
},
runtime: {
placement: "in_process",
providerConfig: {},
ownerId: processId,
leaseTtlMs: 90_000,
heartbeatIntervalMs: 30_000,
fences,
orphans,
},
worker: environmentWorkerOptions,
});

factoryOptions is the adapter constructor. Provider-specific deployment facts stay there: for example GKE namespace/template/warmPool, Cloudflare backend bindings and runtime resolvers, or an AWS launcher/AMI configuration. Direct provider factory calls expose the corresponding strong TypeScript type. The shared Work and Runtime Port payloads stay provider-neutral; they do not erase or reinterpret those constructor fields.

Embedded workers and BYOW/external workers use the same control-plane path. Create a dedicated Environment service key instead of reusing the workspace API key:

POST /v1/oma/api_keys
X-API-Key: <workspace-admin-key>
Content-Type: application/json
{"name":"production workers","environment_id":"env_..."}

The plaintext oma_env_... key is returned once. It is accepted only as a Bearer token on /v1/environments/{that_environment}/work/**; it cannot access another Environment, Session/Agent APIs, or the Work API through x-api-key. Every claim then receives a separate Session-scoped secret. Revoking the Environment key blocks subsequent poll/claim requests immediately; reclaiming Work rotates the Session secret and fences the old owner.

Environment service key
-> Work poll / claim+ACK
-> per-claim sessions_token
-> Work heartbeat / stop + claimed Session APIs
-> external BYOW process OR OpenMA embedded kernel + provider driver

For a disposable queued Session, the repository includes a destructive conformance probe. It refuses to touch any Work other than the exact expected ID and leaves failed Work reclaimable:

Terminal window
OMA_BASE_URL=https://openma.example \
OMA_ENVIRONMENT_ID=env_... \
OMA_ENVIRONMENT_KEY=oma_env_... \
OMA_CONFORMANCE_WORK_ID=work_... \
pnpm test:e2e:external-worker-conformance

The probe uses the official WorkPoller (therefore exercising poll + ACK), then switches to the claim’s sessions_token for heartbeat, claimed-Session access, scope-escape rejection and force-stop. Its reusable core is runExternalEnvironmentWorkerConformance().

LaneAgent-loop ownerWorker requirementRuntime behavior
ama_workerManaged Agents control planeAny official/community EnvironmentWorker command or imageStarted unchanged; it keeps its Work lease through the official API
openma_supervisedPi, ACP, or another OpenMA harness in the sandboxImplements openma-harness-supervisor-v1Ready, heartbeat, completion, drain, bounded stop

Both lanes use the same sandbox, workspace, output, and resource-fence Ports. The supervisor protocol is never required for an ordinary Managed Agents worker. In the ama_worker lane, the official worker inside the sandbox owns Work heartbeat and stop, so the outer poller uses autoStop: false. In the openma_supervised lane, the outer Environment Worker owns the official Work heartbeat and stop; a 412 aborts the inner host and prevents a stale generation from publishing candidates.

Harness-native session data and user-visible outputs share the Runtime Host’s drain/checkpoint/finalize lifecycle. They do not share a namespace or a data contract: outputs are immutable published artifacts, while native session data is private recovery state inside the workspace candidate. Each agent adapter declares an exclusive session-artifact allowlist. The native-session contract does not include the agent’s complete profile, config, credentials, cache, or ordinary home. A coarse provider workspace snapshot can physically carry unrelated workspace bytes, but a replacement harness must not use those bytes as native recovery state. OpenMA does not run a second continuous state-sync sidecar.

For an ACP harness, interaction stays provider-neutral while native recovery is agent-specific. @open-managed-agents/harness-runtime-acp runs the Session command stream and ACP child inside the sandbox. It selects a native-session profile, isolates the live agent root under /tmp/openma-harness-state/, copies only the declared resume artifacts into /workspace/.openma/harness-state/, and stores the ACP logical session id beside them. The Runtime Host persists that durable copy as part of the workspace candidate. If a restored candidate lacks required native state, the host starts a new ACP session with one bounded semantic-recovery message derived from canonical Session events; it never replays old tool calls. See ACP native session persistence for the exact Claude Code, Codex, Gemini, OpenCode, Pi, MCode, Copilot, Cortex, Goose, Junie, Kimi, Qwen, Vibe, DeepSeek Harness ACP, and Hermes session artifacts.

The application talks to SessionEventDispatchPort in both deployments:

PresetSingle-owner mechanismDurable pending work
CloudflareOne SessionDO identity per SessionDO SQLite event queue
Node PostgreSQL/SQLite/MySQLRenewable SQL claim with owner, attempt and generation fencemanaged_session_executions outbox

The Node server is therefore horizontally scalable. Every accepted actionable Event batch and its execution row commit under the same Session revision CAS; replicas claim different Sessions in parallel but preserve FIFO within one Session. A lost lease rejects late canonical output and allows a different replica to reclaim the attempt. An indeterminate renewal stops the local runtime instead of assuming it still owns the Session.

The execution table is Node-only infrastructure. It does not change the Managed Agents SDK shape, add fields to managed_sessions, or appear in the Cloudflare D1 schema. Node deployments apply it through the normal generated PostgreSQL/SQLite migrations or the MySQL schema adapter.

Placement selects exactly one scheduling authority:

PlacementSole execution claimWhat the claim owns
Harness outside sandboxSession execution claimThe application-side harness attempt and any tool sandbox it drives
Harness inside a self-hosted sandboxOfficial Environment Work claimOne combined sandbox executor containing supervisor, harness and tools

The in-sandbox lane never acquires a nested Session execution claim. The Runtime Host resource generation is a subordinate publication fence for workspace, checkpoint and output candidates; the supervisor heartbeat is a process-health signal. Neither is a second scheduler.

Session execution and Environment Work use a shared internal lease controller for serialized renewals, bounded uncertainty, cancellation and graceful stop, but keep separate stores and wire protocols. This preserves the official Environment Worker shape while giving both planes the same failure semantics.

Every Work reclaim rotates its claim-bound Session bearer. Requests from the old sandbox are rejected even if its sealed token has not expired. An expired current bearer may call Work heartbeat/stop so the official endpoint can return 412 or finish cleanup, but it cannot append Session Events.

ANTHROPIC_WORK_SECRET contains the official base64-encoded Work secret. Its sessions_token is the only credential an in-sandbox worker uses for Session data. OpenMA seals these exact capabilities into that token and rechecks the live Work claim on every request:

Session resourceWork-token capabilityFilesystem behavior
Session and eventsRetrieve the claimed Session; list/stream/send its eventsNo implicit files
Agent skillList versions and download only a skill declared by the resolved Session agentThe official EnvironmentWorker resolves latest, extracts it below <workdir>/skills/<name>, and removes it at teardown
Memory StoreAccess only an attached store; mutations require read_writeThe official worker downloads to mount_path, periodically reconciles, performs a final sync, and enforces read_only
FileRetrieve metadata/content only for a file attached to the SessionThe official worker SDK does not auto-mount files; a custom worker downloads it or an OpenMA/provider resource mounter writes it to mount_path
GitHub repositoryNo repository token appears in the Session or Work secretThe runtime/provider clones it at mount_path; authenticated egress resolves the Session resource credential outside the sandbox
HTTP MCP serverCall only the claimed Session/server gateway pathThe sandbox receives the OpenMA proxy URL, never the upstream MCP credential

File listing, upload, deletion, unrelated skills/files/stores, and another Session’s APIs are not part of the capability. The Cloudflare egress handler also forwards the token only to the configured OpenMA origin and those route families; the API-side claim remains the final authorization boundary.

For an embedded runtime_host, OpenMA constructs a claim-scoped SessionInputAccessPort around that Session client. The host keeps the sessions_token; the provider adapter receives only the downloaded bytes and verified metadata. Before the harness starts, the preinstalled generic materializer writes binary files exactly to mount_path and clones repository resources there. A repository resource makes credential egress mandatory, so admission fails before allocation when the selected provider has no verified wire point. When a canonical workspace checkpoint was restored, repository clone is skipped so resumed edits are not overwritten.

The official ama_worker remains the owner of Skill and Memory Store hydration/sync. In openma_supervised, the host materializer owns all declared Session resources. The preinstalled generic materializer implements files and repositories only, so a supervised Session with a Memory Store requires an operator-supplied synchronization materializer and otherwise fails before the harness starts. The Port input carries this ownership explicitly; a generic adapter may never silently skip materializer-owned memory. In provider_dispatch, provider_activation, and external_worker modes, the dispatched or external Worker owns this same official resource contract because OpenMA does not run an embedded Runtime Host below it.

Built-in entrypoint ownership and current boundaries

Section titled “Built-in entrypoint ownership and current boundaries”

The same public Session shape does not mean every process owns resource materialization. Use this matrix when choosing an entrypoint:

EntrypointFiles and repositoriesSkills and Memory StoresMCP and Environment policyOutputsDynamic changes
Node local Managed Session (apps/main-node, harness outside sandbox)OpenMA downloads binary Files, clones the exact branch/commit, scopes a private-repository header to git, and validates a retained repository before preserving editsOpenMA mounts custom Skills and tells the model their exact SKILL.md root. Managed Memory is projected to an immutable read-only snapshot; read_write is rejected before materializationURL MCP supports toolset enablement/per-tool permission. A limited Environment with allow_mcp_servers !== true never contacts MCP. Sandbox-local stdio without a host-reachable URL is rejectedDurable local mount plus GET /v1/sessions/:id/outputs[/:filename]File/resource, Skill, and Environment changes are fingerprinted at each turn boundary; a changed snapshot rebuilds and prepares the sandbox before execution
Cloudflare local Managed Session (apps/main + SessionDO)Session resources are mounted during sandbox warmup; any declared File, Memory, env, or repository that cannot be prepared now fails warmup instead of being skippedSessionDO resolves and mounts the configured resources and Skills using Cloudflare bindingsThe same URL-MCP checks apply; Vault-backed MCP and HTTPS use fenced Worker/DO egress. Sandbox-local stdio is not host-reachable and is rejectedRequired R2 mount and the same OpenMA output endpoints when FILES_BUCKET is bound. Local workerd without bucket-mount support creates an explicitly non-durable test directoryA warm sandbox uses its warmup snapshot. Resource changes are guaranteed after a cold/recreated sandbox, not as live injection into an already-running turn
Embedded runtime_host + ama_workerOpenMA materializes Files/repositories before startThe unmodified official Worker owns Skill and Memory hydration/final syncThe Worker uses the official claim-scoped token and configured gatewayRuntime Host output PortOne immutable claimed-Session snapshot per Work item
Embedded runtime_host + openma_supervisedThe generic materializer supports Files/repositoriesThe selected harness/agent adapter owns Skills. Materializer-owned Memory requires an operator synchronization Port and otherwise fails closedSupervisor/runtime profile owns wiringRuntime Host output PortRe-acquire/restart boundary; no mid-turn mutation
external_worker / provider dispatchExternal Worker owns all materializationExternal Worker owns all synchronizationOfficial Work API is exposed unchangedExternal Worker/deployment owns itDefined by that Worker

The output endpoints are an OpenMA REST extension, not a method currently projected by @anthropic-ai/sdk. They still require the Managed Agents beta header, authenticate through the normal API middleware, verify that the Session exists in the current workspace, reject traversal filenames, and stream from the selected Node or Cloudflare output adapter.

Private Git credentials have different security strengths in the two local lanes. Cloudflare uses its enforced outbound handler. Node local execution uses command-scoped Git configuration and is appropriate for trusted local or isolated deployments; it is not advertised as non-bypassable transparent egress. Select a Runtime Host provider that passes required credential-egress conformance when the repository credential is high blast radius.

The host uses five independent boundaries:

  • ManagedSandboxPort owns isolated compute and hard cleanup.
  • WorkspacePersistencePort materializes /workspace and creates immutable restore candidates.
  • SessionOutputPort exposes /mnt/session/outputs, collects files, and creates an immutable content-addressed manifest.
  • SessionInputMaterializerPort stages official claimed-Session resources and interprets opaque metadata after resource attachment but before harness start.
  • SessionInputAccessPort is the ephemeral, per-claim content reader used by that materializer. It is never serialized into a lease, checkpoint, provider configuration, or sandbox environment.
  • RuntimeResourceFencePort is the only authority allowed to publish a workspace/output candidate as active.

The Work heartbeat, runtime resource fence, and supervised-harness heartbeat are separate liveness signals. Only the Work lease is the in-sandbox scheduling claim; the resource fence gates publication and the supervisor heartbeat reports process health. Losing an authoritative lease aborts the execution. A stale process can remain alive briefly after a network failure, but it cannot append canonical Session Events or publish a new canonical workspace/final output manifest. External tool side effects still need their own idempotency key.

PresetWorkspaceOutputsHard cleanupProcess-memory recovery
Node + Dockerportable filesystem checkpointfilesystem final collectorDocker force removenone
Cloudflare Sandboxportable createBackup / restoreBackup checkpointR2 final collector when FILES_BUCKET is boundSandbox destroy + durable orphan reapernone
Node → Cloudflare Sandbox Bridgeportable /workspace tar in the configured BlobStorecanonical /mnt/session/outputs final collectorauthenticated Bridge DELETE + durable orphan reaper after handle publicationnone
E2B / E2B-compatibleretained runtime or portable E2B snapshotS3-compatible final collector when FILES_S3_* is configuredreconnect + kill + durable orphan reaper supplied by hostnot advertised
Daytonaretained sandbox or portable filesystem snapshotBlobStore final collector when configuredstable-name ownership check + delete/reapnot advertised
LiteBox / BoxRunprovider-local retained boxBlobStore final collector when configuredstable-name ownership check + force remove/reapnot advertised
Spritesprovider-persistent ext4 filesystemBlobStore final collector when configuredowner-validated delete/reapnot advertised
Vercelpersistent named sandbox with automatic filesystem snapshotsBlobStore final collector when configuredsandbox plus orphan snapshots delete/reapnot advertised
ModalSession-scoped Volume v2 subpathBlobStore final collector when configuredcompute terminate/reap; Volume remains canonicalexperimental memory snapshot not advertised
Superserveindefinitely retained pause/resume by defaultBlobStore final collector when configuredowner-validated idempotent kill/reapprovider pause is not promoted to a portable checkpoint

Cloudflare and E2B may internally capture more runtime state. OpenMA treats those snapshots only as workspace restore candidates until a separate RuntimeCheckpointPort is configured. Durable Session events remain the source of truth for rebuilding the agent loop.

The conformance registry is intentionally stricter than the generic SandboxPort adapter registry:

ProviderManagedRuntimeHost conformanceWhat the raw SandboxPort adapter can still do
Node + Dockermanaged-runtimeDocker process/stdio and filesystem workspace/output ports
Cloudflare Sandboxmanaged-runtimeSandbox DO process/stdio, createBackup/restoreBackup, and configured R2 output mount
Cloudflare Sandbox Bridgemanaged-runtime (ama_worker only)Bearer-authenticated lifecycle, argv/SSE execution, workspace files and tar persist/hydrate
E2B / compatiblemanaged-runtime (ama_worker, openma_supervised)E2B suspend/resume, provider memory snapshot, live stdin, and configured S3-compatible output collection
Daytonamanaged-runtime (ama_worker, openma_supervised)Stable names and ownership labels, start/stop, portable snapshots, session-process stdio, and configured BlobStore output collection
LiteBoxmanaged-runtime (ama_worker, openma_supervised)Official low-level embedded client, stable get-or-create, detached filesystem, native stdio, stop/start and native network/secret creation options
BoxRunmanaged-runtime (ama_worker, openma_supervised)Same managed BoxLite driver through the official REST client; legacy hand-written REST remains SandboxPort-only
Blaxelmanaged-runtime (ama_worker, openma_supervised)Stable external identity, archive/unarchive retention, named full-duplex process, native network policy and optional persistent volume
Spritesmanaged-runtime (ama_worker, openma_supervised)Stable Sprite, persistent ext4, automatic pause/wake, full-duplex process and native network policy
Vercelmanaged-runtime (ama_worker only)Persistent named Sandbox, automatic filesystem snapshot restore, deny-by-default firewall and request transforms; no streaming stdin
Modalmanaged-runtime (ama_worker, openma_supervised)Named compute over a pre-created Volume v2 Session subpath, full-duplex process and domain/CIDR allowlists
Superservemanaged-runtime (ama_worker, openma_supervised)Stable metadata ownership, retained pause/resume, token-rotating reconnect, full-duplex process, strict egress and provider-side secret proxy

sandbox-port-only remains a deliberate fail-closed status for any raw or future adapter that has not supplied the complete composition. Such an adapter must not be passed to a ManagedRuntimeHost until it supplies a fenced lease, workspace candidate publication, output manifest publication, orphan reaping, and one of the declared harness lanes. The machine-readable source is MANAGED_RUNTIME_PROVIDER_CONFORMANCE from @open-managed-agents/managed-runtime-host.

Provider dependencies are isolated by package. The provider-neutral @open-managed-agents/sandbox and @open-managed-agents/managed-runtime-sandbox packages contain only Ports and composition code. SDKs live in sandbox-adapter-*, managed-runtime-*, environment-dispatch-*, or environment-activation-* provider packages, so a deployment installs only the adapter packages it selects. Every vendor SDK is an optional peer of exactly its adapter package; the monorepo sets autoInstallPeers: false, so merely checking out or building OpenMA does not resolve all provider dependency trees. The deployment that selects a provider installs its adapter and matching SDK together, then passes that adapter package to the lazy driver loader. For example:

Terminal window
pnpm add @open-managed-agents/managed-runtime-daytona @daytona/sdk

The host never imports a provider adapter statically. It loads only the configured package’s createManagedRuntimeProviderDriver(), createManagedEnvironmentWorkDispatchPort(), or createManagedEnvironmentActivationPort() export and rejects a descriptor whose provider ID or lifecycle strategy does not match the selection. Unit tests use structural fake clients and therefore run without any provider SDK. A credentialed provider conformance lane installs the provider SDK explicitly. The architecture gate rejects an SDK placed in runtime dependencies, a source import without an optional peer declaration, a cross-provider runtime dependency, a missing uniform factory export, automatic peer installation, or any provider import that leaks into a neutral package.

Offline adapter certification is part of ordinary CI and requires no provider account, network access, or secret. It runs the complete adapter suites for Blaxel, Cloudflare, Modal, Sprites, Superserve, and Vercel against structural implementations of their SDK boundaries. Every lane must execute: there is no credential-based skip path, one failed lane does not prevent the remaining lanes from running, and any failure makes the command fail. The report is written with mode 0600 to artifacts/certification/offline-certification.json:

Terminal window
# Run every keyless provider-adapter lane.
pnpm test:certification:offline
# Focus one or more adapters while retaining the same reporting contract.
pnpm test:certification:offline -- --providers cloudflare,vercel

This gate proves OpenMA’s mapping of provider SDK semantics: stable identity, ownership validation, lifecycle/status mapping, ready-before-publish barriers, stdio and filesystem behavior, deny-by-default egress, suspend/resume or recreation behavior, fencing failures, idempotent destruction, and orphan reaping where supported. It does not prove provider availability, deployed images, account policy, regional behavior, or compatibility with a live vendor control plane.

Credentialed certification therefore remains separate from the offline gate; unit and contract tests cannot masquerade as real-provider evidence. The live gate always prints one of PASS, FAIL, or NOT_RUN_NO_CREDENTIAL for every selected provider and writes a redacted JSON report to artifacts/certification/live-certification.json:

Terminal window
# Configure local credentials once; this file is ignored by Git.
cp .env.certification.example .env.certification.local
$EDITOR .env.certification.local
# Audit every registered provider. Missing credentials make the gate fail.
pnpm test:certification:live
# Run only configured providers. This remains strict for the selected set.
E2B_API_KEY=... pnpm test:certification:live -- --providers e2b
# Cloudflare also accepts the local Wrangler OAuth profile; no API token copy
# is required after `pnpm exec wrangler login`.
pnpm test:certification:live -- --providers cloudflare
# Production R2 checkpoint/restore is a separate lane and requires S3 keys.
pnpm test:certification:live -- --providers cloudflare-r2
# Exercise Node, the official SDK, CLI, Console browser, and a real local
# subprocess sandbox against one isolated local cluster.
pnpm test:certification:local-release
# If ~/.dsh contains a DeepSeek credential, certify harness-out tool use,
# compaction/prefix-cache behavior, and harness-in ACP native resume.
pnpm test:certification:live -- --providers deepseek-model
# Inventory mode is explicit; it never changes FAIL into success.
pnpm test:certification:live -- --allow-missing

The live runner automatically loads .env.certification.local; an already exported environment variable wins over the file value. Use --credentials-file /absolute/path/to/provider.env to select a different file. CI should inject the same variable names from its secret manager instead of creating this local file. GitHub Actions Secrets are write-only from the runner’s perspective and cannot be downloaded for local reuse; use a password manager or secret broker as the source of truth if local and CI must share one managed copy.

Both reports record the exact Git revision and dirty state, timestamps, per-provider duration and sanitized diagnostics. Credential values are never written to stdout or the report. Exit code 1 means a provider test failed; exit code 2 means at least one provider was not run because required credentials or provider configuration were absent. The latter is deliberately non-zero in the default/release-gate mode, so a skipped real-provider lane cannot be reported as a successful certification.

The executable live lanes are Cloudflare lifecycle/egress, Cloudflare R2 checkpoint/restore, E2B, BoxLite, the isolated local release stack, and the DeepSeek model matrix. Other registered providers already appear in the matrix and remain NOT_RUN_NO_CREDENTIAL when not configured; if configured before their credentialed test is implemented, the missing package script becomes an explicit FAIL, not a silent pass.

Individual provider lanes remain available for focused diagnosis:

Terminal window
E2B_API_KEY=... pnpm --filter @open-managed-agents/sandbox-adapter-e2b test:certification
pnpm --filter @open-managed-agents/managed-runtime-boxlite test:certification
pnpm --filter @open-managed-agents/managed-runtime-cloudflare test:certification
pnpm --filter @open-managed-agents/managed-runtime-cloudflare test:certification:r2

The Cloudflare lane accepts either CLOUDFLARE_API_TOKEN plus CLOUDFLARE_ACCOUNT_ID, or a successful local wrangler whoami OAuth probe. It deploys a uniquely named Worker and standard-1 Sandbox application, then tests the actual OpenMA CloudflareSandbox wrapper: command and file I/O, stable sandbox identity across Worker requests, Worker-side outbound handler attachment and revocation, absence of the proxy secret from the container process environment, hard destruction, and fresh state after re-creation. The Worker, Container application, and local mode-0600 secrets file are removed in the test cleanup, and any residual Container application fails the lane. Transient Cloudflare 429/502/503/504 and post-push manifest-visibility errors are retried at most three times.

That lane does not claim production R2 backup/restore coverage. The separate cloudflare-r2 lane binds an R2 bucket as BACKUP_BUCKET, writes a workspace marker, creates a portable filesystem checkpoint, destroys the Sandbox, restores it into a new container, and proves the marker survived. It requires CLOUDFLARE_ACCOUNT_ID, R2_ACCESS_KEY_ID, and R2_SECRET_ACCESS_KEY from a dedicated R2 Object Read & Write token; Wrangler OAuth can authorize Worker and bucket management but cannot replace those S3 credentials.

By default the lane creates, empties, and deletes a uniquely named temporary bucket. Set OMA_CLOUDFLARE_R2_BUCKET to reuse an existing dedicated bucket with least-privilege bucket-scoped credentials. In reuse mode the cleanup never lists or deletes unrelated objects: it deletes only the two keys emitted for each checkpoint created by the run, backups/<checkpoint-id>/data.sqsh and backups/<checkpoint-id>/meta.json, and leaves the bucket intact. Keeping persistence separate prevents a lifecycle pass from being mistaken for checkpoint certification.

The local-release lane builds the Console, starts an isolated Node deployment with SQLite and the real local-subprocess sandbox, exercises the official Managed Agents SDK through a complete streamed turn, verifies the CLI managed projection, and drives the Console with Playwright through the same API. It also asserts that child processes and temporary state are removed.

The deepseek-model lane uses the local DSH credential without printing or copying it. It verifies Pi harness-out execution with a real sandbox tool call, explicit no-thinking model behavior, active compaction at a low test threshold, prefix-cache hit ratios before and after compaction, and harness-in ACP native session restore with cache usage preserved.

The BoxLite certification lane starts a real embedded MicroVM and verifies workspace creation, stop/start retention, worker stdio, ownership, and hard removal. On macOS its temporary runtime root deliberately uses a short path so nested Unix sockets remain below the platform SUN_LEN limit. Its optional SDK-dependent TypeScript project is isolated behind typecheck:certification; the default monorepo typecheck remains provider neutral. The architecture gate prevents credentialed certification sources from accidentally reintroducing optional vendor SDKs into that default lane.

Set E2B_API_URL for an E2B-compatible control plane and OMA_E2B_TEMPLATE for the template to certify. The lane exercises real command execution, lease renewal, memory suspend/resume, and a portable provider snapshot. It does not promote that snapshot to process-memory checkpoint semantics; that still requires an explicit RuntimeCheckpointPort.

CredentialEgressPort is the provider-neutral lifecycle for credentials used by an untrusted sandbox. It prepares an opaque binding after the runtime fence is acquired, attaches and verifies the provider wire point before the harness starts, revokes it before sandbox cleanup, and finally releases it. The binding is scoped to (workspace, environment, Session, Work, generation) and never contains a Vault token.

Profiles choose required, best_effort, or disabled. required starts only when the provider reports a tested, non-bypassable implementation. Missing ports, advisory proxy environment variables, an invalid fence, or a failed Vault lookup cause startup/request failure rather than a silent direct connection.

Provider/pathCurrent declarationNotes
Cloudflare transparent HTTP/HTTPSenforced, live credentialsenableInternet = false; every lookup checks the exact active runtime fence; revoke installs a deny handler
Cloudflare or Node harness-in-sandbox HTTP MCPscoped gatewayACP receives proxy URLs plus the current Work sessions_token; the upstream URL/token are omitted
Node/Docker transparent proxyadvisorythe legacy oma-vault env proxy is bypassable and not safe as a multi-tenant boundary
E2B / Daytona / LiteBoxprovider-dependentcurrent generic adapters are advisory; a deployment may inject a native enforced adapter through the Port after conformance
BoxRununsupportedfail closed until its deployed API proves the required creation-time network/secret controls

The Work sessions_token is a short-lived capability, not a Vault credential. It is accepted only for the Session, events, attached files, declared skills, attached Memory Stores, Work heartbeat/stop, and MCP gateway paths encoded by its workspace/environment/Session/Work claim. It is checked against the current stored claim and heartbeat TTL on every request. Reclaim rotates the stored token, immediately fencing the old sandbox from every resource API and the MCP gateway. Pass it only in the Authorization header; never persist or log it.

This is an OpenMA Runtime Host extension. It does not change the official Managed Agents Environment Worker, Work, webhook, or Session wire shapes. The repository’s docs/adr/0007-sandbox-credential-egress.md contains the full provider and chaos matrix.

import Anthropic from "@anthropic-ai/sdk";
import { createNodeManagedEnvironmentWorker } from
"@open-managed-agents/managed-runtime-node";
const cluster = await createNodeManagedEnvironmentWorker({
runtime: {
rootDir: "/var/lib/openma/runtime",
sql,
initializeFenceSchema: true,
ownerId: `environment-worker:${process.pid}`,
leaseTtlMs: 90_000,
heartbeatIntervalMs: 30_000,
image: "my-community-worker:latest",
sessionInputs: repoAndFileMaterializer,
},
worker: {
client: new Anthropic({
apiKey: null,
authToken: environmentKey,
baseURL: openmaBaseUrl,
webhookKey,
}),
environmentId,
environmentKey,
workspaceId,
profileFor: async (_work, session) => ({
workspace: { requirement: "durable" },
outputs: { requirement: "durable" },
runtimeCheckpoint: "disabled",
driver: {
type: "ama_worker",
process: { command: "node", args: ["worker.mjs"] },
},
}),
},
});
// Immediate + periodic poll fallback. Your HTTP route may concurrently
// call cluster.environmentWorker.handleWebhook(...).
await cluster.environmentWorker.run(shutdown.signal);

For the official SDK-inside-sandbox lane, worker.mjs can be only:

import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic({
apiKey: null,
authToken: process.env.ANTHROPIC_ENVIRONMENT_KEY,
baseURL: process.env.ANTHROPIC_BASE_URL,
});
await client.beta.environments.work.worker({
workdir: "/workspace",
}).handleItem();

The host injects ANTHROPIC_ENVIRONMENT_ID, ANTHROPIC_ENVIRONMENT_KEY, ANTHROPIC_SESSION_ID, ANTHROPIC_WORK_ID, ANTHROPIC_WORK_SECRET, and ANTHROPIC_BASE_URL. It never injects the API client’s parent key.

The activation and commit sequence is input-gated and candidate-first:

  1. claim Work, retrieve the Session with its per-claim bearer, and validate identity;
  2. materialize and attach workspace/output/credential-egress bindings;
  3. stage application-owned Session metadata inputs;
  4. run and drain the worker or harness;
  5. create and hash an immutable workspace candidate;
  6. enumerate output files, re-read them to detect mutation, upload content-addressed blobs, and create an immutable manifest;
  7. compare-and-set both candidates through the current fence generation;
  8. release compute without deleting the canonical candidates.

If hard termination fails, the host persists a token-free orphan record. The reconciler reconnects by the serialized provider/runtime ID and retries an idempotent destroy. Fence tokens are never stored in the orphan queue.

An interrupted candidate upload is not active. A duplicate upload is accepted only when its bytes hash to the expected content address. Corrupt checkpoint metadata or content is rejected; OpenMA never silently creates an empty workspace and calls it a restore.

Run the deterministic lifecycle and fault matrix with:

Terminal window
pnpm test:chaos:runtime
pnpm test:coverage:runtime
pnpm test:integration:runtime # real Docker engine
pnpm test:integration:storage # PostgreSQL, MinIO, SQLite

The chaos lane injects failure at every post-acquire boundary, lease loss during finalization, failed hard kill, host restart/orphan reap, corrupt checkpoints, output mutation/collision, duplicate finalize, and seeded multi-owner schedules. Real provider smoke tests supplement this deterministic gate; they do not replace it.

The resource conformance lane additionally runs an unmodified Anthropic EnvironmentWorker inside a real Docker container. It resolves a latest skill through the public API, extracts and reads its SKILL.md, downloads a Memory Store to its declared mount path, modifies a memory through a normal tool, and verifies the final write-back. Node and Cloudflare API tests exercise attached-file download, skill alias resolution, read-only/read-write Memory Store authorization, cross-Session rejection, Work reclaim, and stale-token fencing. The Cloudflare harness tests cover binary file materialization, repository checkout without credential injection, env secrets, and memory mount flags.

For the exact runtime profile, Port method ownership, provider capability matrix, destruction/recovery transaction, and the distinction between harness-outside-sandbox and harness-inside-sandbox, see Sandbox and persistence contracts.