Skip to content

Latest commit

 

History

History
345 lines (265 loc) · 39.8 KB

runtime-protocol.md

File metadata and controls

345 lines (265 loc) · 39.8 KB
title Core–Runtime protocol

The Core–Runtime protocol connects Core to a Runtime daemon and defines the meaning and order of the messages on the daemon connection. Hosted and self-hosted Runtimes use the same protocol.

Property Value
Caller Core's gateway
Implementations The reference Runtime's dispatcher. A Harness joins through the Harness protocol, which owns the Executor and Turn lifecycle obligations behind the Runtime registry.
Code internal/agentdaemon/proto: wire types, limits and validators, defined once and used by both sides, so there is no second payload schema to keep in sync
Transport JSON envelopes over a WebSocket at /api/v1/agent-daemon/ws. The HTTP routes that issue credentials and open the connection are in the Machine connection API.
Version rule Exact match of proto.Version (Versioning)

Ownership and connection

Party Owns Never does
Core Durable Session, Turn, input and Environment records, scheduling and reconciliation Replays input, initialization, transfers or unresolved mutations after a reconnection
Runtime Native Executors, active Turns, transfer state and cleanup until settlement Deletes, suspends or reclaims a sandbox when it releases an execution admission or closes an Executor; the daemon is not an isolation boundary (Runtime and outer isolation)
Sandbox Provider Placement and the surrounding compute Owns Executors or Turns

A Runtime connects in this order:

sequenceDiagram
    participant R as Runtime
    participant C as Core
    R->>C: POST /api/v1/agent-daemon/bootstrap (device ID, Bearer credential)
    C-->>R: connection URL, heartbeat interval
    R->>C: WebSocket /api/v1/agent-daemon/ws?device_id&version
    alt version differs from proto.Version
        C-->>R: HTTP 426 incompatible_version
    end
    R->>C: heartbeat (supported_agent_kinds, availability, capabilities)
    loop every heartbeat interval
        R->>C: heartbeat
    end
    C->>R: ordered envelopes
    R->>C: ordered envelopes
Loading
  • The Machine connection API lists the credential kinds. Project API keys and the Core key are never Runtime credentials.
  • Both requests carry the credential as a Bearer header. A credential never appears in a URL, a payload log or a trace.
  • The first heartbeat is sent at once, then at the interval that bootstrap returned. Each heartbeat declares supported_agent_kinds, their availability and their capabilities. Before the first heartbeat, capabilities are unknown; a kind missing from a heartbeat is not advertised. Neither permits inference.
  • Heartbeats establish liveness only, never execution progress or a receipt for an earlier message.

Each physical connection has fresh routing, admission handles and transfer state. A newer connection for the same device replaces the previous one: Core evicts the old Run routes, and the new connection inherits none of them. A valid credential and connection are never authority to choose another Session or Environment binding.

Versioning

The wire version is proto.Version, independent of the Runtime build version that heartbeats report. Core accepts only an exact match, including the patch component. A mismatch returns HTTP 426 incompatible_version before any dispatch; the daemon treats it as permanent and stops reconnecting. Deploy matching peers together; a change to a payload or its semantics changes proto.Version.

Capability declarations

AgentKindCapabilities in inbound.go describes one composed Runtime and Harness, independently of available. It starts from the Harness's declared capabilities, which state the most it can do, and discovery only narrows them to what the installation verified. Every field is a CapabilitySupport: supported or unsupported. The zero value is unspecified and invalid, even for an unavailable Harness. Registration validates the complete declaration before changing the registry; there is no implicit basic descriptor.

On the wire each field is a JSON boolean, and every field is present, including false. Encoding an incomplete declaration fails. Decoding rejects omitted, null, invalid and unknown fields, and a missing capability object. An invalid heartbeat clears the connection's admission snapshot and closes its transport; that establishes no native completion or cancellation result.

Each admitted Executor and Turn keeps the declaration it was admitted with. A later heartbeat cannot add operations to an existing owner. Optional operations check this snapshot before any native call; the presence of a Go interface never grants support. A declared operation that returns agent.ErrUnsupportedOperation is a contract violation, distinct from unavailability, a failed native call or an uncertain write. Uncertain operations keep their receipts and ownership and are never replayed automatically. Workspace support includes the common Runtime workspace implementation, so a native adapter's unsupported workspace method does not disable that composition.

A new field requires an explicit decision in every production declaration. Contract tests enumerate every field for registration, wire round trips and the persisted boolean projection; the shared test fixture lists fields individually and supplies no defaults for future ones. The Harness protocol owns the adapter side of each declaration.

A declaration describes what the Runtime can do. Core admits a public feature only when the Harness's declaration also admits it, and checks the declaration of the selected device during device selection and again at the final check before it claims a Turn:

Capability Core requires it when
streaming, durable_turns, durable_input_receipts, preparation, execution_controls, tool_observations Always, for every execution on that Harness (with available true)
environment_none The Environment type is none
local_environment, workspace_read_preparation, workspace_output_export The Environment type is openai_hosted or self_hosted
workspace_read_preparation An idle Files directory read needs a read-only preparation
native_session_recovery A Session with a started Turn has no recorded native Session ID
retained_native_history The Environment uses an external workspace binding; a Provider's own disk does not require this capability
structured_output and message_items The Agent requests json_schema output. A Runtime that declares message_items tags text deltas with the native item ID and reports message start, completion, phase and the completion text in output_message frames
subagent_observations multi_agent.enabled is true
subagent_control multi_agent.enabled is false
tool_search The Agent enables tool search or defers function loading
function_tools The Agent declares function tools
message_images, function_result_images A message, or a function result, carries an image
mcp_http_tools, mcp_http_required, mcp_http_bearer_auth The Agent declares MCP servers (HTTP or stdio); one is required; a Vault credential is selected for one

Core has no admission rule for usage and resume.

retained_native_history means the composed Runtime and Harness can reopen the same native Session from its private retained state after confirmed native shutdown. It does not promise process memory, background processes or external connection recovery. The selected filesystem must separately provide retained storage. Core uses the previous device's persisted declaration to determine whether compute can be released without terminating the Session, and validates the replacement Runtime before admitting execution. Missing or invalid native history fails explicitly; it never authorizes a new native root or replay of prior input.

Envelope and identity

Every data frame is one JSON Envelope: type, a type-dependent id, a typed payload and an optional W3C trace. The trace is diagnostic correlation only; missing or invalid trace data creates a local trace and never changes ownership. Never use a trace ID as a request ID.

Identity Scope and meaning
Device ID and connection Authenticated Runtime routing and connection ownership
Session ID / Environment ID Core-owned configuration and workspace binding; canonical UUIDs where the payload validator requires them
Executor ID Runtime-owned native resource, possibly retained across settled Turns with identical configuration
Preparation request ID Envelope.id for prepare, start, release and status; distinct from a Run
Admission handle Runtime-generated reservation, valid only on the connection that accepted it
Run ID One execution attempt; Envelope.id for output, cancellation, active input and functions
Delivery ID / input ID / call ID Resolve attempt, active-input receipt and native function identity; never interchangeable
Transfer ID / suspension ID Connection-local transfer correlation / persisted suspension-attempt fencing

Cancellation and function-result acknowledgements use the Run ID and match the delivery ID. A reply without the required correlation cannot establish acceptance.

Message families

The linked source files define the required fields, validators, limits and finite error categories.

Core → Runtime Runtime → Core Definition
runtime_prepare runtime_prepare_result Initialization and capability transfer
execution_prepare, execution_start, execution_release preparation_status Execution admission
prompt_cancel delta, thinking, output_message, tool_call, usage, error, done, heartbeat, interaction_decision_ack Requests, events and capabilities
prompt_steer prompt_steer_ack Active input receipts
function_result function_call, function_call_withdrawn, interaction_decision_ack Function calls
workspace_read, workspace_write, workspace_export Matching *_result Read, write, export
environment_quiesce, environment_resume environment_quiesced, environment_resumed Suspension fencing

Initial, prepared and active input use the same ordered MessageInput. Adapters keep message and content order and reject unsupported content explicitly; a text-only transport rejects image content rather than dropping it. The message input contract owns the public image profile, whitespace rules and each Harness's native conversion.

A function_call carries native_id and turn_id when a Subagent made the call, with the meaning they have in subagent_turn; both are empty for a call of the Run itself. The adapter sends the child's subagent_identity and subagent_turn before the call, and Core answers with function_result under the same call_id.

A function_call_withdrawn carries the call_id, native_id and turn_id of a function_call and tells that the native Harness will never apply a result for it, for example because a Codex Subagent Turn ended and native dropped its request. Core stops requiring an answer for the call and rejects a later result for it. The adapter acknowledges a function_result already in flight with not_pending, and Core then waits for the withdrawal or the Turn's end instead of failing the Turn or resending the result.

Usage frames and the final usage snapshot each carry the cumulative measurement of the current execution and replace the previous snapshot; never add them. An absent measurement is unknown, not zero.

Preparation and execution order

Environment initialization uses runtime_prepare on every connection, managed or user-owned; the Environment contract owns what is prepared and when. A file or archive moves in one transfer, shown below.

sequenceDiagram
    participant C as Core
    participant R as Runtime
    C->>R: runtime_prepare begin (budget_ms)
    R-->>C: runtime_prepare_result ready
    loop each chunk
        C->>R: runtime_prepare chunk (offset)
        R-->>C: runtime_prepare_result received (offset)
    end
    C->>R: runtime_prepare commit
    R-->>C: runtime_prepare_result completed
Loading

Initialization and finalization have typed headers without file data. Every begin carries budget_ms, the remaining Core-owned initialization budget; chunks and commits omit it. The Runtime enforces that relative budget from receipt of begin, and Core waits no longer than its original operation deadline. The begin–commit staging phase has its own limit; applying a committed operation and waiting for completed use the remaining initialization budget, not the staging limit. Expiry before application rejects the transfer; expiry during application reports unknown after local mutations stop and never authorizes replay. Validate the expected outcome, offset, size and finite error code with the shared validator. One transfer is allowed per connection. A chunk receipt confirms staged bytes, not installation; a completed commit confirms that operation, not that a later Turn ran.

An execution Turn runs as follows. Core subscribes to preparation status before it sends execution_prepare and to the Run before it sends execution_start, because output can race the status.

sequenceDiagram
    participant C as Core
    participant R as Runtime
    participant H as Harness adapter
    Note over C: Subscribe to preparation status
    C->>R: execution_prepare (Session configuration, no Run input)
    alt new Executor
        R-->>C: preparation_status preparing
        R->>H: ExecutorFactory
        R-->>C: preparation_status ready (Executor ID, handle, revision, expiry)
    else reused healthy Executor
        R-->>C: preparation_status ready
    end
    alt abandon before start
        C->>R: execution_release
        R-->>C: preparation_status released
    else start
        Note over C: Subscribe to the Run
        C->>R: execution_start (Executor ID, handle, Run ID, input)
        R-->>C: preparation_status starting
        R->>H: StartTurn
        R-->>C: preparation_status started
        loop until a native terminal outcome
            R-->>C: delta, tool_call, usage, error
        end
        alt Run ends
            R-->>C: done
        else cancel during the Run
            C->>R: prompt_cancel
            R-->>C: interaction_decision_ack
        end
    end
Loading
  • preparing means the Runtime owns preparation. ready supplies the Executor ID, admission handle, revision and expiry. Neither submits user input.
  • A valid execution_start transfers the reservation once. started confirms the transfer to the Turn, not its completion.
  • Consume Run events until a native terminal outcome or loss of observation. An execution error is followed by done, which closes the stream; the preceding errors remain part of its outcome.
  • To abandon before start, send execution_release. After ownership passes to a Run, use prompt_cancel; releasing the old handle cannot cancel its successor.

A preparation reserves a per-Turn admission, not a new Executor. It carries an explicit Session identity and immutable configuration without model input or a Run ID. A fresh request returns a connection-local handle and the owning Executor ID; a reused healthy Executor returns ready without native preparation. Per-handle revisions order status observations: ignore older or repeated revisions and never apply a status to another handle. An admission moves through the states below. A rejected control operation carries an operation and error code and does not replace the handle's current revision. Releasing an admission abandons only that admission; it does not close the Session's idle Executor or cancel a later Turn.

stateDiagram-v2
    direction LR
    [*] --> preparing: execution_prepare
    [*] --> ready: reused Executor
    preparing --> ready
    ready --> starting: execution_start
    starting --> started
    starting --> failed
    preparing --> released: execution_release
    ready --> released: execution_release
    preparing --> expired
    ready --> expired
    preparing --> failed
    ready --> failed
Loading

Preparation and start run outside the receive loop and router lock. An admission expires at a fixed deadline that retries do not extend; expiry does not remove the Runtime's obligation to settle cleanup. The Runtime bounds active preparation and execution separately from idle retained resources and counts closing or uncertain resources until their cleanup succeeds. A definite execution_prepare rejection with preparation_capacity leaves the queued Turn unclaimed for the Worker to retry, including when cleanup holds the capacity; any other error or uncertain delivery authorizes no replay. The Runtime retains a bounded number of admission records, and an old handle never consumes a replacement's admission. These records are connection-local, not durable input replay.

Idle expiry of an Executor is a Runtime resource policy, separate from Core's active-Turn concurrency. On shutdown the Runtime closes active and idle Executors, keeps any target whose close failed and allows a later serialized retry. An ordinary disconnection closes the failed transport and keeps the exact router until shutdown succeeds; a wait timeout or failed cleanup never authorizes reconnection, and process shutdown keeps waiting rather than discarding owned native resources. For Runtime initialization, shutdown joins the synchronous apply operation and its receipt delivery before releasing the connection; an unknown result remains unknown and blocks further preparation on that Router, but does not prevent reconnection after local mutations have stopped. Core retains the failed initialization and never replays it. Workspace operations keep their binding and settlement rules across Turn boundaries and Executor closure.

Suspension closes admission and drains admitted work and receipts while retaining settled idle Executors before acknowledging environment_quiesced. Active, preparing, invalid or otherwise unsettled owners prevent suspension. Idle expiry is stopped and its callbacks fenced throughout suspension; exact authenticated environment_resume restores a fresh idle interval on the same owners. Only this planned reconnect preserves the Router and native owners across sockets; ordinary disconnect, shutdown and cancellation of the connection lifecycle still require confirmed cleanup. A drain failure keeps admission closed until shutdown. Preparation after resume retains the same native identity and immutable-configuration checks, including credential conflicts; it never silently replaces a conflicting resident Executor. The Sandbox Provider remains responsible for the filesystem flush and compute-stop guarantees of its checkpoint implementation; Runtime quiescence alone proves neither those guarantees nor restoration of native RAM or external network connections.

Execution configuration

The execution_prepare configuration carries the opt-ins Core sets for each Run:

Field Set by Core
agent_options Always model and system_prompt from the Agent; model_provider when the Session froze one; harness_config when the Agent sets x_agents_core.harness_config. Core sends no other key; the Runtime rejects any other key with unsupported_configuration before preparation
execution_controls Always: the resolved text verbosity (default medium) plus each option the Agent sets, whether web search (mode, context_size, allowed_domains, location), programmatic tool calling, reasoning effort and summary, a non-auto service tier or a json_schema output format. Core validates every value against the Harness declaration before dispatch; native option names belong to the adapter
observe_subagent_identities, disable_subagents From the Agent's multi_agent.enabled
disable_execution_environment For an Environment of type none
local_environment For openai_hosted and self_hosted, with the exact Environment binding. The request carries no working directory; the Runtime checks workspace_directory against its binding
require_existing_native_session When a native Session must be recovered

An execution configuration requires exactly one of local_environment and disable_execution_environment; execution_prepare rejects neither or both with unsupported_configuration.

Requests without an opt-in keep the frames and fields they had without it. A tool_call frame carries the engine-neutral observation whenever the adapter maps the native tool.

Active input receipts

Core delivers active input as prompt_steer, one input at a time per Run, and waits for its receipt before sending the next.

sequenceDiagram
    participant C as Core
    participant R as Runtime
    participant H as Harness adapter
    C->>R: prompt_steer
    Note over C,R: written wait limit, from delivery
    R->>H: SteerWithReceipt
    Note over R,H: native write limit
    H-->>R: write complete
    Note over R,C: receipt send limit
    R-->>C: prompt_steer_ack written
    H-->>R: native application receipt
    Note over R,C: receipt send limit
    R-->>C: prompt_steer_ack accepted
    R-->>C: done after Turn settlement
Loading

accepted arrives under the Turn lifetime, with no automatic redelivery. The Runtime sends done after native Turn settlement and after the receipt send of any in-flight input; the native write and receipt send limits bound that input. The limits are in Timeouts and limits.

Neither written nor a send failure advances Core's input cursor. Once cancellation is sent, its receipt owns the terminal outcome even if an input becomes unknown first; Core records cancel_unconfirmed when no cancellation confirmation arrives before its limit expires. A cancellation receipt carries the stopped Turn's confirmed continuity snapshot when no done is emitted.

What each acknowledgement proves

Observation Proven fact
Core gateway Send returns nil The envelope entered the local send queue
Runtime transport Send returns nil The WebSocket write completed locally
Transfer received, active-input written The defined receive or write phase occurred; native execution or consumption is unconfirmed
Preparation preparing / ready Preparation accepted / reservation ready, with no Run input submitted
Preparation started Admission transferred to the identified Turn
Active-input accepted The adapter confirmed native consumption under its declared receipt semantics
interaction_decision_ack.applied=true The identified operation settled; a cancellation also requires native settlement
done and the preceding execution events The execution stream completed with its observed outcome

No generic receipt exists for every envelope. A successful send does not prove that the peer received, accepted or completed a request. Process exit, a stop signal or a canceled local context does not prove cancellation. A done frame may also close a settled cancellation stream; it does not override the cancellation receipt or imply success. A cancellation receipt may keep partial content, native identity and usage in outcome even when no done is published. A failure to obtain settlement stays failed or unknown; it never becomes applied=true.

Failures, retries and cleanup

Transport and execution outcomes are separate. Core's only Run subscription entry point is SubscribeDurable; inspect Subscription.Err() when its event channel closes. Disconnection and subscriber overflow close it with an explicit observation error and fabricate no error or done. Core keeps the durable truth and reconciles from confirmed facts. The Runtime keeps cleanup ownership until native work, input receipts, function results and child work have settled.

The public Turn status is a separate projection. execution/delivery.go records an unsuccessful orchestration attempt as failed, including delivery_unknown after an unconfirmed send and event_stream_incomplete after a subscription failure; a closed subscription can replace the send reason with event_stream_incomplete. Both mean the native effect is unknown: a public failed status does not prove that the Harness failed, that no side effect occurred or that cleanup completed. Keep the observation reason and any native evidence distinct.

Condition Responsibility
Unsupported capability or invalid binding Reject before starting the operation; never select another Harness
Confirmed preparation or execution failure Keep the finite error category and any observed result; the Runtime settles its resources
Deadline or connection loss after dispatch The effect is unknown unless an application receipt proves otherwise; do not convert it to an execution failure
Reconnection Reestablish the transport and the capability declaration; never replay input, initialization, transfers or unresolved mutations
Duplicate preparation or start Connection-local identity and fingerprint rules apply; a conflicting request rejects, and an old handle cannot start replacement work
Duplicate input, function result or decision That family's receipt identity and conflict rules apply; there is no transport-wide deduplication or exactly-once promise
Cleanup failure Keep resource ownership and report unconfirmed cleanup; a waiter's timeout does not make a resource reusable
Lost cancellation receipt Cancellation may have happened; the missing receipt neither establishes success nor authorizes another execution

Retry only an operation whose own contract makes retry safe. A retired preparation request ID may eventually allocate a new handle, so request IDs are not durable idempotency keys. Resuming a native Session is an explicit operation with verified identity, never a response to a socket failure. A transient connection error permits reconnecting; an authentication or version rejection requires operator correction. Executor cleanup is separate from the Sandbox Provider's confirmed reclamation of compute.

Native failure classification

An adapter may add code and http_status to a Run's error frame. They are optional neutral metadata, not a terminal event or a public error contract; the frame's text, Usage, done, native Session identity and cancellation receipts keep their order and meaning.

The accepted codes are authentication_error, rate_limit_exceeded, usage_limit_exceeded, server_overloaded, server_error, invalid_request, resource_not_found, request_timeout, context_length_exceeded, cyber_policy and connection_failed (engine_failure.go). Only connection_failed keeps http_status, and only an integer from 100 to 599; every other status is discarded. A missing, malformed or unknown value leaves the error unclassified without discarding Usage or done.

Core stores accepted values in the Turn outcome as engine_error_code and engine_http_status. A Run may carry more than one error frame, such as an adapter's classified failure followed by the Runtime's own settlement failure; a frame without an accepted code leaves the stored classification in place, and a later accepted code replaces it. The classification is subordinate to the terminal status and Core's error_code: it cannot turn a completed or cancelled Turn into a failure, hide an incomplete event stream, or override a persistence or cancellation-receipt failure. Normal delivery and terminal journal draining use the same extraction. Session diagnostics expose the category only for a failed Turn whose Core error is engine_failed. The Codex and Claude Code adapter guides give each Harness's mapping. An adapter classifies only from structured error data: the Harness's own error variant or status, or a model provider's JSON error body that the Harness passes through, whose own error.code or error.type may name an accepted code. It never classifies from error prose.

Workspace operations

A workspace read that needs no running Turn uses the read-only preparation profile: execution_prepare with workspace_read_only, which requires the workspace_read_preparation capability. It accepts only the bound Environment and resource identity; execution options, model and MCP credentials, native Session continuation and model or tool input are excluded, and the owner rejects execution_start. The Runtime serves it from its bound local workspace without starting a Harness process. The profile publishes released after the Runtime drops the preparation's ownership; a stale status snapshot never publishes success. A release request, HTTP disconnect or remote socket closure alone does not confirm the release.

workspace_read targets an existing preparation handle, or the Run it was transferred to, on the same authenticated device connection, with the exact frozen Environment identity; callers cannot supply sockets, credentials or workspace roots. operation: directory lists one workspace-relative directory (an empty path selects the root) with mutually exclusive byte and entry limits. A result carries a bounded number of single-component UTF-8 names, the entry kind, regular-file sizes and explicit truncation, and is returned only after directory access and handle cleanup settle. There is no snapshot, recursion or pagination at this layer. Byte and directory reads share target checks, correlation, capacity and retained operation waits.

Request payloads and correlation IDs are bounded before admission; oversized IDs are not echoed, and oversized trace metadata is omitted from replies. Raw read results are bounded within the transport frame. These are private transport limits, not public Files parameters. A successful read requires complete bytes or explicit truncation and an acknowledged native close. A safe native rejection carries no bytes; an interrupted or ambiguous read stays unknown and stops further reads on that owner. A dispatched read keeps its bounded waiter across observer cancellation and resource transfer or release, and resource closure stops new admission. The gateway bounds subscriptions and never retries or replays a read on reconnect; a duplicate pending operation ID cannot start another read.

Core runs an idle directory read on the Worker's Session scheduling reservation and targets the exact Run during active execution. It keeps the reservation through the bounded read and release, returns data only after a confirmed close (an incomplete read or uncertain cleanup returns unavailable without data), releases the reservation before delivering the result, and revokes the scoped read credential on completion or failure. The Runtime keeps uncertain cleanup ownership and capacity. The Environment Files contract owns public authorization, paths and pagination.

workspace_write transfers a complete bounded body in acknowledged frames before the native writer runs, verifies the declared digest and runs no model. The private transfer bound is separate from the public decoded inline bound that the API checks before any Runtime work. The Runtime excludes execution while it receives or applies a write; a malformed, incomplete or expired transfer never reaches the installer. An exact commit or rejection receipt releases the mutation owner. A missing or ambiguous receipt keeps the uncertainty: observer cancellation and local process exit cannot prove that nothing changed. Before public admission Core durably reserves the write under the Session lock and blocks successor mutations across restarts until exact settlement; the request is never replayed. Every platform uses the daemon's Go implementation for bounded reads, directory listing, file creation and output export, with no external helper or staging directory.

MCP connection authority

Every public MCPHTTPServer in an execution_prepare configuration carries an explicit connection_origin; a missing or unknown value rejects rather than selecting a default, and Core freezes the public default before dispatch. MCPHTTPServer.headers carries non-secret literal headers; credentials travel only in bearer_token. MCPHTTPServer.stdio (command, args, cwd, env_vars) declares a process of the Environment instead of a URL: it requires origin environment and carries no headers or bearer, and env_vars names variables the process inherits, never their values. The Runtime validates the origin with the common validator before selecting a factory and resolves public and installed MCP into transient effective bindings. The Environment contract owns the supported combinations, native limits and failure ownership.

Timeouts and limits

Every number in this protocol is stated here. The Harness side of the Turn lifetime is in the Harness protocol.

Value Applies to On expiry or breach
5 minutes An execution admission, from the moment it is granted; retries do not extend it The admission becomes expired. The Runtime still owes cleanup settlement.
64 records Admission records a Runtime retains per connection execution_prepare is rejected with preparation_capacity, and Core leaves the queued Turn unclaimed for the Worker to retry.
64 frames The bounded output channel of a Turn A single consumer, started before native Start, drains it.
10 seconds The Runtime's settlement wait around a Turn A timeout is not proof of quiescence; the resources stay owned until cleanup is confirmed.
1 to 1,800,000 ms budget_ms of a runtime_prepare begin: the remaining Core-owned initialization budget Expiry before application rejects the transfer; expiry during application reports unknown and is never replayed.
2 minutes The begin–commit staging phase of one runtime_prepare transfer The transfer is rejected.
64 KiB One chunk of a runtime_prepare transfer or a workspace_write body A larger chunk fails validation.
50 MiB One runtime_prepare transfer or workspace_write body (private bound) The transfer is rejected before it reaches the installer.
5 MiB The decoded inline body of a public write, checked by the API before any Runtime work The API rejects the request.
4 MiB One inbound transport frame The frame is refused.
8 KiB, 128 bytes A workspace_read request payload, and a correlation ID, checked before admission The request is rejected; an oversized ID is not echoed and oversized trace metadata is omitted from replies.
1 MiB The raw result of a workspace_read, within the transport frame The result is explicitly truncated.
1024 names, 255 bytes each One directory result The result is explicitly truncated.
10 seconds The adapter's native write of an active input; the timer stops when the write completes The Runtime acknowledges outcome_unknown and never redelivers the input automatically.
30 seconds Core's wait for written, from delivery The input outcome is unknown.
5 seconds Each receipt send, which is shutdown-aware The send fails; a send failure does not advance Core's input cursor.
15 seconds Core's wait for a cancellation confirmation Core records cancel_unconfirmed.

Contract verification

Run make check-runtime-contract from the repository root. It exercises the shared wire validators, gateway, transport and dispatcher, the shared wire scenarios on both sides, the observation-result regression and the Harness declaration tests. It needs no model credentials or external sandbox, and make check runs the same tests through check-go and check-core.

Each wire scenario lists once, in order, the frames Core and the Runtime send, together with native settlement, connection loss and reconnection. Each side runs its real implementation against a scripted peer that replays the other side's frames over a WebSocket: Core's gateway test and the Runtime's transport and dispatcher test, which uses a controlled Harness adapter. Each side asserts the frames it sends and the behavior it owns; neither imports the other. Values the Runtime generates, such as the Executor ID, admission handle and expiry, are placeholders that the Runtime side binds to the values its Runtime sends.

The suite covers incompatible versions, preparation failure, cancellation settlement, connection loss without invented terminal events, reconnection without replay, stale or duplicate handles and receipts, cleanup failures, bounded transfer validation and resource ownership after a timeout. Detailed fault injection stays next to the gateway and dispatcher code it tests.

Another Runtime replays the same scenarios against a scripted Core, then runs native acceptance for every capability it declares. A controlled-adapter test establishes the transport contract, not native Harness behavior, operating-system support, provider authentication or sandbox isolation. Change the shared types, this document and the contract checks together. Harness adapters also run the shared text assertions described in Harness protocol.