Technical contracts / run control

Open Engine Cluster Protocol

OECP is the versioned message contract for checking and controlling a run after the controller admits it.

When you need OECP

Suppose Cloud has chosen the repository revision and the controller has accepted the fixed graph, input, and runtime settings. A client can now check status, resume saved logs, follow one live node, or request a hard stop. OECP defines the messages for that work; a protocol is the shared message format and rules used by the client and controller.

The contract calls the controller handoff admission. Target login, repository setup, queueing, and credential resolution happen before it on the Cloud side; the contract calls that separation the host boundary.

OECP calls the latest saved view of one run its run projection. As state and logs change, the controller appends ordered records to stored history, which the contract calls the durable ledger. Credentials reach a worker through a private startup route that the contract calls the bootstrap path; OECP does not expose that route or its values.

One active dispatch of a graph node is an execution. OECP identifies it with an opaque reference that clients copy unchanged rather than parse.

Submission and control use different paths

The CLI sends fixed run intent and exact connection values to the private Cloud host API. Cloud authenticates the request, resolves the branch, and assigns the run ID; if no lane is free, the run waits in the queue. OECP begins only after the controller admits it.

Hosted boundary
Zeroshot
Submit:  CLI -> Zeroshot Cloud -> queue -> controller
Control: CLI -> OECP WebSocket -> controller and durable ledger
OwnsRun identity, admitted lifecycle, status, durable watch and logs, live attach, and force-stop.
ExcludesTarget login, repository setup, queueing, template expansion, runtime selection, and secret values.

Wire contract

The wire contract fixes the version, transport, frame shape, and maximum message size. A client must follow these rules before method-level validation can begin.

  • Protocol version: openengine.cluster/v1.
  • JSON-RPC 2.0; one object per WebSocket text frame; no batching or binary frames.
  • Hosted targets use a WebSocket on the same authority with a short-lived bearer token.
  • Local runs use NDJSON, one JSON object per line, over a private mode-0600 Unix socket.
  • Maximum WebSocket frame or NDJSON line: 1,048,576 UTF-8 bytes.

Lifecycle

Every projection reports one of four lifecycle states. While work runs or stops, the response keeps active executions visible; once the run finishes, it reports a terminal result instead.

admittedThe immutable run exists, but no execution is active.
runningThe projection lists zero or more activeExecutions. Each one has an opaque execution reference and graph node name.
stoppingThe durable force request exists, and every execution still active remains visible.
finishedNo execution is active. terminalResult contains succeeded(output) or failed(reason).

Run methods

Status gives one snapshot, whereas watch and logs replay stored records after a saved cursor before following new ones. Attach skips history and follows one live execution. Force records a hard-stop request.

run/listReturns every retained run projection.
run/statusReturns immutable metadata, the current cursor, and the current lifecycle state.
run/watchReplays durable status changes after, but not including, a cursor, then follows new changes.
run/logsReplays safe logs after, but not including, a cursor, optionally for one execution.
run/attachFollows one active execution live. It is read-only and has no cursor, replay, or input.
run/forceRecords a hard-stop request and returns the new projection. Repeating it does not create another stop.

Cursors and reconnects

Each saved event or log record has a stable position in the run's stored history. OECP calls that opaque position a cursor. Save the cursor from the last record you handled, then pass it as fromCursor when watch or logs reconnect; the named record will not replay, and later records will follow.

A terminal stream closes with done. If a client reads too slowly, the stream closes with SLOW_CONSUMER and may include lastDeliveredCursor. Reconnect from that cursor; closing a subscription never stops the run itself.

SOURCE_UNAVAILABLE means stored history could not be read completely. Check run/status for the run outcome; an incomplete history is not a successful result.

Attach and safe output

Status pairs each active graph node with an opaque execution reference. While that execution remains live, pass the reference to attach and read its working, output, and settled events; use run/logs when you need earlier output.

For GitHub App runs, organization owners and administrators can read logs and attach live. Cloud requires runs:connect for live access and also runs:write to use run/force.

Safe logs contain only level, target, and message. The protocol has no fields for provider identity, session identity, reasoning, tool frames, raw environment data, or credentials.

Errors and exclusions

Application errors use finite codes so a client can respond without parsing a message string.

SCHEMA_VIOLATIONThe request contains malformed or unknown parameters.
NOT_FOUNDThe client named a run or execution reference that does not exist.
GONEThe named execution exists in history but has settled or is no longer live.
RUN_CONFLICTThe client tried to submit a run through the deployed target's OECP endpoint.

OECP has no writable attach, graceful stop, update, retry, resubmit, delete, runtime replacement, or artifact reference in terminal outcomes.