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: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 onworker_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: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, includingworker_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:?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 isin_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.