Agent sessions
An agent runs as a first-party program built on the Oh My Pi SDK inside its
own container (the per-agent isolation substrate), emitting compass.v1 frames
natively — there is no Agent Client Protocol
anywhere in the system, and no translator. The agent is spawned on the container
host — the Runner — over a long-lived streaming exec, and its
newline-delimited compass.v1 stream is relayed up to the server, which fans it
out to clients. One container holds one agent, driven by one session.
The topology is Client → Server → Runner: the server holds no container-engine code; the Runner owns every container operation and dials out to the server (a NAT-friendly outbound connection, like a CI runner). Container lifecycle commands flow Client → Server → RunnerHub → Runner over the internal Runner seam; agent frames flow Runner → Server → Client.
Requirement: Provisioning a workstream creates its isolated container
Section titled “Requirement: Provisioning a workstream creates its isolated container”The server SHALL expose ProvisionAgentWorkspace — agent ref + repo/workstream
spec in, a stable container_name out. It routes the request Client → Server →
RunnerHub → Runner, where the Runner drives the built lifecycle façade to create
the isolated per-agent container; the server itself runs no container-engine
code. Provisioning and starting are separate operations: a container can
exist idle before a session runs in it, so ProvisionAgentWorkspace and
StartAgentSession stay distinct RPCs. When the request carries a
client_request_id, it is an idempotency key: a timeout-retry with the same id
SHALL return the same container_name rather than creating a second container.
Scenario: A retried provision creates no duplicate container
Section titled “Scenario: A retried provision creates no duplicate container”- Given a provision request carrying a
client_request_id - When the client’s first call times out and it retries with the same id
- Then the server returns the same
container_nameand the Runner has created exactly one container.
Requirement: The lifecycle RPCs manage one agent session per container
Section titled “Requirement: The lifecycle RPCs manage one agent session per container”The server SHALL expose StartAgentSession, StopAgentSession,
ReloadAgentSession, and GetAgentStatus, each routing Client → Server →
RunnerHub → Runner. StartAgentSession SHALL bring the first-party agent in a
provisioned container online — spawning it over the streaming-exec bridge — and
return a server-assigned session id. StopAgentSession SHALL deliberately
terminate the in-container agent and release the session, and SHALL succeed for
an unknown or already-stopped session (idempotent teardown). GetAgentStatus
SHALL return one session’s status, or every retained session’s when no id is
given, reconciled to the owning Runner’s authoritative session set; retained
sessions include ERRORED ones awaiting ReloadAgentSession.
Scenario: Starting an agent session streams its status
Section titled “Scenario: Starting an agent session streams its status”- Given a provisioned agent container with no live session
- When a client calls
StartAgentSessionfor it - Then the server brings the first-party agent online and publishes an
AgentSessionStatustransition toSTARTINGthenREADYon the event stream, and returns the session id.
Requirement: One live session per container; replacing goes through reload
Section titled “Requirement: One live session per container; replacing goes through reload”A container holds at most one live session. StartAgentSession for a container
that already has a live session SHALL be rejected (the existing session is
unaffected); replacing a live session SHALL go through ReloadAgentSession.
Reload is defined as teardown-then-fresh-start against the same container: the
server stops the current agent and session, then starts a new one under the
same session id (so the id stays a stable handle) and the agent reloads from
its workspace state.
Requirement: One container per agent account
Section titled “Requirement: One container per agent account”The server SHALL bind at most one live container to a given agent account. A
SpawnAgent for an agent account that already holds a live session SHALL be
rejected with ALREADY_EXISTS before any container is provisioned (the
existing session is unaffected). A SpawnAgent for an account whose only
session is ERRORED SHALL be rejected with FAILED_PRECONDITION (“agent
errored; reload or stop it”), also before any provisioning. This binds the
reject-on-live rule to the
agent account, not merely to the container name: the existing
one-session-per-container requirement above coincides with it today only
because the container name is derived from the account, an incidental property
a future Runner naming containers differently would break.
Requirement: A deliberate stop is distinct from an unexpected exit or a lost Runner
Section titled “Requirement: A deliberate stop is distinct from an unexpected exit or a lost Runner”The server SHALL distinguish three session-ending conditions. A deliberate
stop/reload SHALL NOT be reported as ERRORED. An unexpected agent exit (a
crash, out-of-memory, or engine restart) SHALL transition the session to
ERRORED on the event stream and SHALL NOT be auto-reconnected; recovery is an
explicit ReloadAgentSession. A lost Runner link is distinct from both: the
session SHALL transition to DISCONNECTED — live session truth is temporarily
unreachable but not lost — and a bounded reattach window SHALL govern recovery.
A reattach within the window resumes the session; window expiry falls to
ERRORED, after which the no-auto-reconnect policy applies.
Implementation status (RIG-4075): The Runner observes an unexpected agent process exit and publishes
ERRORED, including when the agent cannot send its own terminal frame. The Runner retains the session forReloadAgentSession. Only a Runner-link loss before T9 has no process-exit frame; its bounded reattach-window behavior remains governed by the T9 implementation status below.
Scenario: A Runner disconnect moves its sessions to DISCONNECTED, not ERRORED
Section titled “Scenario: A Runner disconnect moves its sessions to DISCONNECTED, not ERRORED”- Given a Runner with a live agent session
- When the Runner’s link to the server drops
- Then the session transitions to
DISCONNECTEDon the event stream, and a reattach within the bounded window resumes it rather than ending it asERRORED.
Implementation status (RIG-1243 T4): T4 ships the
DISCONNECTEDstate on the contract and the disconnect signal — a lost Runner link fails the session’s in-flight commands. The server-side reattach-window enforcement — the per-session registry that publishesDISCONNECTEDon link loss, the bounded timer, the expiry→ERROREDtransition, andGetAgentStatusreconciliation to the Runner’s set on reattach — is T9 (RIG-1328). Until T9 lands, the window/expiry state machine in this Requirement is not yet enforced.
Requirement: Recover a session after its container is removed outside Compass
Section titled “Requirement: Recover a session after its container is removed outside Compass”When an agent’s container was removed outside Compass while the Runner still
holds its handle, ProvisionAgentWorkspace for the same agent SHALL replace it:
the Runner retires the ERRORED session, drops the stale handle, and launches a
new container under the same name. A following StartAgentSession with the
original resume_session_id SHALL then recover the session. Until then,
StartAgentSession and ReloadAgentSession for that container SHALL fail with
NOT_FOUND before any exec, and RemoveAgentWorkspace SHALL succeed and drop
the handle and placement. A message wake that receives NOT_FOUND SHALL
re-provision the agent and retry the start.
Scenario: Removing a stale container releases its placement
Section titled “Scenario: Removing a stale container releases its placement”- Given the container was removed outside Compass and the Runner still holds the handle
- When
StartAgentSessionorReloadAgentSessionis called - Then it fails with
NOT_FOUNDand no agent exec runs - And
RemoveAgentWorkspacesucceeds and releases the placement.
Scenario: Re-provisioning recovers a container removed outside Compass
Section titled “Scenario: Re-provisioning recovers a container removed outside Compass”- Given a session is
ERROREDand its container was removed outside Compass, while the Runner still has the container handle - When a client calls
ProvisionAgentWorkspacefor the same agent with a new or emptyclient_request_id, thenStartAgentSessionwith the originalresume_session_id - Then the Runner launches a replacement container instead of rejecting the provision as already provisioned, and the resumed session starts on it.
Requirement: Agent repository credentials follow each owner’s App installation
Section titled “Requirement: Agent repository credentials follow each owner’s App installation”The Server SHALL mint an agent’s GitHub credential separately for each repository owner the agent
is granted, on that owner’s GitHub App installation. The agent’s git and jj-vine SHALL each use
the credential for the repository they act on. Every forge call, including subscriptions and
reviews, SHALL use that owner’s installation. Granting a repository whose owner lacks an
installation of a configured App SHALL fail with FAILED_PRECONDITION. A wildcard grant SHALL
cover the default installation; repositories under other owners SHALL need exact grants.
Scenario: Agent holds repositories under two owners
Section titled “Scenario: Agent holds repositories under two owners”- Given the GitHub App is installed on owners A and B
- And an agent is granted
A/oneandB/two - When the agent pushes to each repository and opens a pull request on
B/two - Then each push and the pull request use a credential minted on that owner’s installation
- And the credential for
A/onedoes not reachB/two
Scenario: Owner without an installation
Section titled “Scenario: Owner without an installation”- Given the GitHub App has no installation for owner C
- When a user grants an agent
C/three - Then the grant fails with
FAILED_PRECONDITION - And the agent’s other credentials are unchanged
Scenario: Forge tools use the owner’s installation
Section titled “Scenario: Forge tools use the owner’s installation”- Given an agent granted
B/two, where B is not the default installation’s owner - When the agent creates, edits, subscribes to, or reviews on
B/twowith the forge tools - Then the Server makes each call with a credential for owner B’s installation