> ## Documentation Index
> Fetch the complete documentation index at: https://docs.openagents.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Runtime Codex Worker API

> Current implementation of per-user Codex worker lifecycle control through Laravel and openagents-runtime, including ownership, idempotency, and event sequencing semantics.

## Integration model

The Codex integration is now implemented as a layered control path. Authenticated clients call Laravel under `/api/runtime/codex/*`, Laravel validates and forwards requests through a signed internal contract, and `openagents-runtime` owns worker lifecycle state, event sequencing, and ownership enforcement. This keeps user auth, token handling, and product-facing APIs in Laravel while moving long-running worker state and control semantics into the runtime where they can be made restart-safe and evented.

The runtime side of this integration is not a thin passthrough. It persists worker records, appends durable worker events, and increments monotonic sequence numbers that power deterministic snapshots and stream resume behavior. This is why the Codex worker API is treated as runtime infrastructure instead of a controller-level helper.

## Public API routes in Laravel

The currently exposed authenticated routes are:

```http theme={null}
POST /api/runtime/codex/workers
GET /api/runtime/codex/workers/{workerId}
POST /api/runtime/codex/workers/{workerId}/requests
POST /api/runtime/codex/workers/{workerId}/stop
```

The create route accepts optional `worker_id`, `workspace_ref`, `codex_home_ref`, `adapter`, and `metadata`. The show route returns a runtime snapshot. The request route accepts a JSON-RPC style `request` object. The stop route accepts an optional `reason` and transitions a running worker to a stopped state.

## Security and principal enforcement

Calls into Laravel require Sanctum auth. Laravel then issues signed internal requests that include runtime signature headers and an authenticated principal header (`X-OA-USER-ID`). Runtime does not trust caller-supplied ownership claims; it checks worker ownership against runtime records before allowing snapshot, request, stream, or stop operations.

This is important for multi-tenant safety. A caller who knows a `worker_id` cannot operate it unless the durable runtime ownership row matches the caller principal. The ownership check happens in runtime for every worker mutation and read path, not just at worker creation time.

## Lifecycle semantics and idempotency

Worker creation is explicitly idempotent on `worker_id` for a matching owner. If the worker already exists for the same principal, runtime reattaches and returns `idempotentReplay=true` rather than creating duplicate runtime state. When a worker is first created, runtime returns accepted semantics; when reattached, it returns replay semantics.

Worker stop is also idempotent. Stopping an already stopped worker returns replay semantics and does not append duplicate terminal transitions. Stopping a running worker marks status as stopped, records the stop reason, and appends a durable `worker.stopped` event.

## Request contract and runtime event flow

Request submission supports a JSON-RPC style envelope:

```json theme={null}
{
  "request": {
    "request_id": "req_001",
    "method": "thread/start",
    "params": { "prompt": "Audit this PR" }
  }
}
```

At runtime, each request goes through this sequence: ownership check, request validation, event append (`worker.request.received`), adapter dispatch, and terminal append of either `worker.response` or `worker.error`. The response sent back to Laravel includes `worker_id`, `request_id`, `ok`, and `response`, so callers always get a stable request-level envelope even when adapter behavior changes.

If `request_id` is omitted, runtime generates one. If `method` is missing or invalid, runtime returns `invalid_request` instead of attempting adapter execution.

## Snapshot and field shapes

Snapshot responses currently return runtime-native snake\_case fields, including `worker_id`, `status`, `latest_seq`, `workspace_ref`, `codex_home_ref`, `adapter`, `metadata`, `started_at`, `stopped_at`, and `updated_at`. Create responses currently use camelCase (`workerId`, `latestSeq`, `idempotentReplay`) while stop responses include `idempotent_replay`. This mixed shape is a real detail of the current implementation and should be normalized in a later compatibility pass once clients are pinned to a canonical format.

## Streaming behavior

Worker event streaming is implemented internally at:

```http theme={null}
GET /internal/v1/codex/workers/{worker_id}/stream
```

The stream supports cursor resume through either `?cursor=` or `Last-Event-ID`, rejects mismatched cursor sources, and enforces stale-cursor handling. SSE `id` values are runtime worker sequence values, which allows deterministic reconnect semantics for stream consumers.

Laravel does not yet expose a public `/api/runtime/codex/workers/{id}/stream` endpoint, but runtime support is complete. Public exposure can be added as a relay endpoint without redesigning runtime worker state.

## Adapter state today and production path

The active default adapter is `in_memory`, which is deterministic and primarily used to validate lifecycle contracts, event sequencing, and ownership logic. It echoes method and params and increments request count so tests and smoke checks can assert deterministic behavior.

This is by design. The transport adapter for real Codex session execution can be swapped in later behind the same worker contract. Because lifecycle APIs and event semantics are already in place, integrating a real adapter is now an execution change, not a control-plane redesign.

## End-to-end usage example

Create a worker:

```bash theme={null}
curl -X POST "$API_BASE/api/runtime/codex/workers" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "worker_id": "codexw_demo_1",
    "workspace_ref": "gs://tenant-workspaces/u_42/repo-a",
    "codex_home_ref": "gs://tenant-codex-home/u_42",
    "adapter": "in_memory"
  }'
```

Send a request:

```bash theme={null}
curl -X POST "$API_BASE/api/runtime/codex/workers/codexw_demo_1/requests" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "request": {
      "request_id": "req_demo_1",
      "method": "thread/start",
      "params": { "prompt": "Audit this PR for regressions." }
    }
  }'
```

Fetch snapshot:

```bash theme={null}
curl -X GET "$API_BASE/api/runtime/codex/workers/codexw_demo_1" \
  -H "Authorization: Bearer $TOKEN"
```

Stop worker:

```bash theme={null}
curl -X POST "$API_BASE/api/runtime/codex/workers/codexw_demo_1/stop" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "reason": "session complete" }'
```

## Why this matters for OpenAgents

This Codex integration gives OpenAgents a runtime-native worker control substrate while preserving the existing Laravel product surface. It is the foundation for hosted coding sessions where worker state must survive reconnects, preserve ownership boundaries, and expose deterministic event histories. With this in place, the remaining work is primarily adapter maturation and public stream/UI wiring, not architectural replacement.
