# Grid-agent control plane v1 The grid agent exposes one transport-neutral request/response and event API. Integrated clients receive an `InProcessControlClient`; split clients use the same `ControlRequestEnvelope`, `ControlResponseEnvelope`, and `ControlEvent` types over TCP. No terminal, Unix socket, named-pipe, permission-bit, or platform-specific type appears in the core API. ## Transport and negotiation TCP frames are a four-byte unsigned big-endian length followed by one UTF-8 JSON value. Empty, partial, malformed, idle, and oversized frames close the connection within configured deadlines. The first frame must be: ```json {"frame":"hello","body":{"version":1,"token":"separate-operator-capability"}} ``` The server answers with a `hello` containing version `1`, the authenticated `operator` or `observer` role, or a typed error. Every later client frame is a `request`; server frames are `response` or `event`. Request IDs contain at most 96 ASCII identifier bytes and cannot be replayed on a connection. A caller can cancel an active request by its ID. Responses and events can arrive in either order, so clients correlate responses by request ID. Plain TCP binds only to IPv4 or IPv6 loopback. Remote control is off by default and a non-loopback address is rejected unless both DER certificate and private key paths are explicitly configured. Remote mode uses Rustls before the hello exchange and emits an operator warning at startup. The TLS client API requires the embedding client to supply its certificate roots and server-name policy. Every split connection must still authenticate with a dedicated control token; observer and operator tokens must differ and configuration rejects reuse of an LLM API key or grid password. Tokens are absent from protocol errors, audit, serialization traits, and diagnostics. Remote service configuration uses the JSON fields `control.remote_tls_certificate_der` and `control.remote_tls_private_key_der` together with a non-loopback `control.listen` value. Both files are bounded, non-symlink DER files. Omitting either field, or selecting a non-loopback address without both, fails configuration before a listener is created. ## Requests The JSON request envelope is stable and versioned. For example: ```json {"version":1,"request_id":"health-1","request":{"method":"health"}} ``` Observers can call `health`, `runtime`, `list_sessions`, `list_scheduled_jobs`, `list_pending_approvals`, `list_audit_events`, and `subscribe_events`. Operators can additionally call `cancel_request`, `pause_autonomy`, `resume_autonomy`, `cancel_action`, `decide_approval`, `force_reconnect`, `expire_conversation`, `set_roaming_job`, `inject_operator_message`, and `graceful_shutdown`. Cancellation is a mutation and is operator-only. List requests use an opaque numeric cursor and a page size of 1 through 100. Runtime projections contain lifecycle/readiness, session generation, safe region and pose fields when known, behavior mode, control-queue utilization, and aggregate budget use. Conversation responses contain metadata only. Audit and approval responses exclude arguments, prompt contents, credentials, authorization headers, capability URLs, model reasoning, and filesystem data. `cancel_action` binds to the exact bounded action ID carried by behavior audit observations; it can cancel a queued or executing embodied action without preempting unrelated work. The built-in roaming job ID is `default-roaming`. Errors are typed as `authentication_failed`, `version_mismatch`, `permission_denied`, `invalid_request`, `replay`, `not_found`, `conflict`, `cancelled`, `timed_out`, `busy`, `backpressure`, `frame_too_large`, `idle_timeout`, `transport_closed`, or `internal`, with a bounded safe message and a retryable flag. ## Events, bounds, and reconnect Events carry monotonically increasing sequence numbers. A subscription can resume after its last observed sequence. If retained history no longer covers that point, its first item is an explicit `gap` with `first_available` and `last_missed`, followed by retained events. Mutation events record the authenticated role/connection principal, operation name, and completed or rejected outcome, never request contents. Connections, unauthenticated handshakes, in-flight request tasks, subscriptions, command/event queues, replay history, event history, event bytes, event rate, frames, pages, idle time, request time, and writes all have validated hard bounds. A full event or writer queue disconnects the slow consumer instead of blocking the headless service. With zero clients, event publication retains only the configured history and creates no background work. Server shutdown cancels and joins all listener, connection, request, and writer tasks within its deadline.