Top
Shared wire types for the agentsessions Session and Harness services.
The Event message is used by BOTH the session log (Sessions.Exec / Replay) and the
harness stream (Harness.Connect) — durable harness events become the log alongside host-owned
records. EVENT_PARKED is a transport-only acknowledgement and is never journaled.
The content model (Part) is aligned with A2A Part + MCP content for interop; the
event/log model is native. Derived from the durable-log & replay contract §7 (record
schema) and §8 (interop). See agentsessions-replay-determinism-contract.md.
ApprovalRef identifies an unresolved, host-owned APPROVAL_REQUEST within the enclosing
session. All fields are required by the approval protocol and request_seq must be positive.
A reference inherited through Fork cannot authorize a new effect in the child session.
| Field |
Type |
Label |
Description |
| execution_id |
string |
|
|
| tool_call_id |
string |
|
|
| request_seq |
int64 |
|
|
Approval is durable journal state, not a mutable session flag or side table. For a
REQUIRES_APPROVAL call the host commits TOOL_CALL then APPROVAL_REQUEST before parking;
only the host may commit the request or its later APPROVAL_RESULT. The harness cannot mint
requests or decisions by emitting these events. Identity on a decision's Event.actor is
recorded provenance only, not authorization. This gate supports STATELESS_REPLAY only;
it defines no policy hook, expiry, automatic decision, or Cancel behavior.
| Field |
Type |
Label |
Description |
| tool_call_id |
string |
|
|
| reason |
string |
|
|
ApprovalResult resolves one request in the enclosing session and Event.execution_id.
A committed decision allows recovery via Resume; Approve itself never invokes the executor.
The host also sends this body in ControllerFrame.approval before the correlated tool receipt
during decided recovery/replay. approved=false is a real denial, not an absent decision.
| Field |
Type |
Label |
Description |
| tool_call_id |
string |
|
|
| approved |
bool |
|
non-optional durable value; request-level decision presence is in ApproveRequest |
| reason |
string |
|
|
| request_seq |
int64 |
|
Positive sequence of the resolved APPROVAL_REQUEST. Zero is retained for legacy decisions; it cannot identify a new durable approval request. |
DataPart is structured JSON (A2A data part; MCP structuredContent).
| Field |
Type |
Label |
Description |
| code |
int32 |
|
grpc status code |
| description |
string |
|
|
Event is the shared journal/stream content unit; EXECUTION_START, APPROVAL_REQUEST and
APPROVAL_RESULT are host-owned journal entries. PARKED is transport only, never journaled.
Ordering (seq) and integrity (prev_hash /
content_hash) are host-assigned and live on LogRecord — the harness, which does not know
seq/prev, emits a hash-free Event, so there is no circular hashing. Streaming deltas are
transport (see Delta in session.proto) and coalesce into the finalized event (§3).
ExecutionStart is host-owned invocation state, committed before inputs and harness execution.
The host emits it for every new execution, including default-config and inputless turns.
Logs without this event reconstruct with empty config and a zero cursor. Older discarded
non-empty values cannot be recovered. Config is opaque: preserve bytes verbatim, never parse it.
| Field |
Type |
Label |
Description |
| config |
bytes |
|
|
| resume_from_seq |
int64 |
|
harness cursor, distinct from the append CAS cursor |
| input_count |
int64 |
optional |
Expected number of INPUT events for this invocation, always set by new writers (including zero). Replay/resume reject a completed or selected invocation with a missing/negative count or a different committed INPUT count before running the harness. An incomplete trailing invocation is skipped by completed replay. Count-less experimental start markers fail closed; truly markerless legacy executions retain their existing reconstruction behavior. |
| harness |
string |
|
Host-resolved registry name used for this execution, not necessarily HarnessDescriptor.id. Interrupted Resume resolves this exact name; absent legacy names use the session harness. |
| harness_version |
string |
|
Advertised, opaque harness replay-compatibility version. Empty means unknown/unversioned. When nonempty, controller replay and interrupted resume require an exact served-version match (including rejection of an empty served version) before running the harness. Empty recorded versions retain existing behavior; this field is opt-in, not required. |
FilePart carries binary/media content inline or by reference (A2A file part; MCP
resource_link / embedded resource). mime is an IANA media type.
| Field |
Type |
Label |
Description |
| mime |
string |
|
|
| bytes |
bytes |
|
|
| uri |
string |
|
|
| name |
string |
|
optional display name |
| digest |
string |
|
content digest of the uri target (chain covers externalized bytes) |
| Field |
Type |
Label |
Description |
| state |
string |
|
COMPLETED |
| error |
Error |
|
|
IdentityRef is the bound agent principal. OIDC-neutral: an Entra Agent ID is one issuer;
a SPIFFE ID or a GitHub App identity are others. Carried on every event.
| Field |
Type |
Label |
Description |
| principal |
string |
|
|
| issuer |
string |
|
|
| subject |
string |
|
session-scoped sub |
Lifecycle marks a compute/session transition in the log (§7). BASELINE is a replay /
compaction checkpoint (§1).
| Field |
Type |
Label |
Description |
| kind |
Lifecycle.Kind |
|
|
| detail |
string |
|
e.g. "fork parent=<uid>@<seq>", baseline id |
| snapshot_local |
string |
|
SnapshotRef captured on SUSPEND (§5.1), carried inline (mirroring the canonical api.SnapshotRef) so it rides the tamper-evident chain with no side table and no cross-file message dependency. This is distinct from the aspirational session-status message SnapshotRef in session.proto. A filesystem-only backend sets only snapshot_local (the session handle to replay) with snapshot_memory=false; a memory backend also sets snapshot_external_uri. |
| snapshot_external_uri |
string |
|
|
| snapshot_memory |
bool |
|
|
| snapshot_sealed |
bool |
|
|
LogRecord is the host's durable, ordered wrapper around an Event. The host assigns seq,
links the hash-chain (content_hash = H(prev_hash || seq || canonical(event)); at a fork
child.first.prev_hash = parent@R.content_hash), and records the incarnation fence token.
Externalized payloads (FilePart.uri, ReasoningPart.opaque_uri, ToolResult.output_uri)
carry their own content digest so the chain covers them by reference.
Message is a role-tagged sequence of content parts (A2A Message = role + Part[]).
| Field |
Type |
Label |
Description |
| role |
string |
|
system, user, assistant, or tool |
| parts |
Part |
repeated |
|
ModelCall is a model REQUEST emitted by the harness (EVENT_MODEL_CALL). The host records
it with input_hash and answers via ControllerFrame.ModelResult (correlated by id). The
completion (text, reasoning, and tool_call parts) is recorded separately as an EVENT_OUTPUT
message. Under STATELESS_REPLAY the harness never calls a provider directly.
| Field |
Type |
Label |
Description |
| model |
string |
|
|
| params |
ModelCall.ParamsEntry |
repeated |
|
| input_hash |
string |
|
§7/§9.1: required for STATELESS_REPLAY so the I0 check can run |
| id |
string |
|
correlation id for the served ModelResult |
| messages |
Message |
repeated |
messages is the request context the host needs to INVOKE the model on the live path. It is wire-only: the host records the call with input_hash alone (messages stripped), since the recorded form only needs the hash to re-check I0 on replay. |
| tools |
ToolDefinition |
repeated |
tools are the definitions offered to the model on this call. Wire-only like messages: the recorded form keeps input_hash, which covers them. |
| tool_choice |
ToolChoice |
|
tool_choice constrains whether and which tool the model calls. Wire-only like messages and covered by input_hash. Unset means the provider default. |
Origin is the neutral external context a session is tied to. Producer adapters
(GitHub, Foundry, custom apps) fill it. Modeled on CloudEvents source/subject.
Part is one unit of message content. Text, file (inline or URI), structured data, or an
opaque reasoning block. Large payloads are externalized by URI, never inlined (§8).
| Field |
Type |
Label |
Description |
| text |
TextPart |
|
|
| file |
FilePart |
|
|
| data |
DataPart |
|
|
| reasoning |
ReasoningPart |
|
|
| tool_call |
ToolCall |
|
tool_call is a model's request to call a tool, carried in an assistant message. It reuses ToolCall so one id runs from the model output through EVENT_TOOL_CALL / EVENT_TOOL_RESULT to the next model input. On a model output, mediation and idempotency_key are unset; to execute the call, the harness sets them on a copy and never changes the recorded output's ToolCall. |
| tool_result |
ToolResult |
|
tool_result is a tool's result fed back to the model, carried in a message with role "tool". ToolResult.id is the id of the ToolCall it answers. |
ReasoningPart is an opaque, provider-tagged reasoning block that MUST be replayed
verbatim to preserve reasoning continuity within a turn (I2). agentsessions never
interprets opaque — all provider specifics live inside it. Verified across
Anthropic/OpenAI/Gemini in the Track A reasoning-continuity spike: one part type, no
per-provider sub-shapes, and no memory-snapshot edge (stateless verbatim replay).
| Field |
Type |
Label |
Description |
| provider |
string |
|
"anthropic" |
| model_id |
string |
|
model that produced it (cross-model resend case) |
| opaque_bytes |
bytes |
|
|
| opaque_uri |
string |
|
externalized when large; retained for the turn's fork lifetime |
| summary |
Part |
repeated |
optional, NON-authoritative, compaction-droppable (may be multimodal) |
| item_id |
string |
|
optional provider id (e.g. OpenAI rs_…) for dedup/order |
| ordinal |
int32 |
|
position within the turn relative to text/tool parts |
| validity_scope |
string |
|
= execution_id (turn); see replay contract §5 |
| opaque_digest |
string |
|
content digest of opaque_uri target (chain covers externalized bytes) |
ResourceMetadata is carried by every top-level resource.
| Field |
Type |
Label |
Description |
| text |
string |
|
|
ToolCall aligns with an MCP tool call (name + structured args).
ToolChoice constrains whether and which tool the model calls.
| Field |
Type |
Label |
Description |
| mode |
ToolChoice.Mode |
|
|
| name |
string |
|
name forces one specific tool. It is meaningful only with MODE_REQUIRED. |
ToolDefinition is a tool offered to a model on one call. It aligns with an MCP Tool (name,
description, inputSchema). It differs from the harness's ToolSpec, which declares a tool and its
default mediation to the host; ToolDefinition is what the model sees.
ToolResult is a durable execution receipt, also usable as model-facing history. A decision
itself is a separate host-owned APPROVAL_RESULT; it is not embedded in this message.
| Field |
Type |
Label |
Description |
| id |
string |
|
|
| output |
google.protobuf.Struct |
|
|
| output_uri |
string |
|
externalized large output (MCP resource_link), else inline output |
| output_digest |
string |
|
content digest of output_uri target (chain covers externalized bytes) |
| is_error |
bool |
|
|
| error |
string |
|
|
| content |
Part |
repeated |
content is the model-facing result (MCP CallToolResult.content: text, file, structured data). A harness records on EVENT_TOOL_RESULT the same ToolResult it feeds back as a tool_result part, so history rebuilt from the journal can give the model what it saw live. |
| code |
ToolResult.Code |
|
|
| approval_request_seq |
int64 |
|
For approval-gated calls, the positive journal sequences of the host-owned request and decision. Both are set on success, denial, or executor failure after approval. Other calls and legacy receipts leave both zero. The host checks these against the same session, execution_id and tool call id; a receipt cannot resolve a different request/decision. |
| approval_decision_seq |
int64 |
|
|
| Name |
Number |
Description |
| EVENT_KIND_UNSPECIFIED |
0 |
|
| EVENT_INPUT |
1 |
a user/producer message |
| EVENT_MODEL_CALL |
2 |
model-call metadata (+ input_hash); output is an OUTPUT message |
| EVENT_OUTPUT |
3 |
a finalized assistant message; streaming deltas are transport, not logged |
| EVENT_TOOL_CALL |
4 |
|
| EVENT_TOOL_RESULT |
5 |
|
| EVENT_APPROVAL_REQUEST |
6 |
|
| EVENT_APPROVAL_RESULT |
7 |
|
| EVENT_USAGE |
8 |
|
| EVENT_LIFECYCLE |
9 |
|
| EVENT_END |
10 |
|
| EVENT_ERROR |
11 |
|
| EVENT_EXECUTION_START |
12 |
host-owned config/cursor/input count, before inputs and harness effects |
| EVENT_PARKED |
13 |
Harness acknowledgement of ControllerFrame.park with the exact ApprovalRef. Transport only: the host MUST NOT journal/hash-chain it or treat it as a terminal execution outcome. |
| Name |
Number |
Description |
| LIFECYCLE_UNSPECIFIED |
0 |
|
| LIFECYCLE_SUSPEND |
1 |
|
| LIFECYCLE_RESUME |
2 |
|
| LIFECYCLE_FORK |
3 |
|
| LIFECYCLE_BASELINE |
4 |
|
| LIFECYCLE_CANCEL |
5 |
|
Mediation controls how a tool call is executed / who enforces record-before-effect (§3).
| Name |
Number |
Description |
| MEDIATION_UNSPECIFIED |
0 |
|
| MEDIATION_IN_HARNESS_REPORTED |
1 |
harness runs it, reports for audit (cooperative WAL) |
| MEDIATION_CONTROLLER_MEDIATED |
2 |
host/gateway executes (host-enforced WAL; trustless) |
| MEDIATION_REQUIRES_APPROVAL |
3 |
Host-owned durable approval gate for STATELESS_REPLAY only. The harness emits a tool call, then awaits a decision/receipt or park control frame; it never executes the effect itself. REQUIRES_MEMORY_SNAPSHOT is unsupported for this gate and fails closed before the effect. |
| Name |
Number |
Description |
| MODE_UNSPECIFIED |
0 |
provider default |
| MODE_AUTO |
1 |
the model decides whether to call a tool |
| MODE_NONE |
2 |
the model must not call a tool |
| MODE_REQUIRED |
3 |
the model must call at least one tool |
| Name |
Number |
Description |
| CODE_UNSPECIFIED |
0 |
Legacy/unspecified status. With is_error=false this is also a successful receipt. Old is_error=true receipts retain their legacy, unclassified failure shape. |
| APPROVAL_DENIED |
1 |
A denied approval: is_error=true and the executor MUST NOT have been invoked. |
| EXECUTOR_ERROR |
2 |
An attempted executor call failed: is_error=true; error describes the failure. This is a durable handled receipt, not an unrecorded effect or an approval denial. |
Top
The Harness BYOH SPI: the contract between the host and an agent implementation.
A Microsoft Agent Framework (MAF) agent, a GitHub Copilot agent, or a custom agent
implements it via a thin adapter. The host drives one execution per Connect stream;
the harness streams typed Events terminated by one EVENT_END, except a host-requested approval
park, which ends with a correlated EVENT_PARKED acknowledgement and stream closure, not END.
Beyond plain streaming, it adds tool-call / approval mediation, per-call usage, and capabilities.
The host and bridge implement durable approval/park for STATELESS_REPLAY only. Unsupported
peers and memory-snapshot harnesses must not execute REQUIRES_APPROVAL effects.
| Field |
Type |
Label |
Description |
| reason |
string |
|
USER |
| Field |
Type |
Label |
Description |
| resumability |
Resumability |
|
|
| fork_safe |
bool |
|
no un-replayable side effects mid-turn |
| requires_gpu |
bool |
|
|
| streaming |
bool |
|
|
| reasoning_replay |
bool |
|
reasoning_replay: harness replays opaque reasoning parts verbatim via the provider stateless path; keeps reasoning on STATELESS_REPLAY (no memory-snapshot edge). |
ControllerFrame is sent by the host to the harness during an execution. Tool/approval control
frames MUST match the Start envelope's session and execution_id and the outstanding tool call
id. The session is the effect namespace; a reused tool id in another session is unrelated.
For a STATELESS_REPLAY REQUIRES_APPROVAL call, the host owns the durable request/decision.
While unresolved, it sends park after committing the request. The harness checks the full
session/execution/call/request tuple, stops this Run, sends one matching EVENT_PARKED, and
closes its sending side WITHOUT EVENT_END. The host receives and validates that acknowledgement
before closing the stream. Missing/mismatched acknowledgements fail the exchange; the durable
unresolved request remains recoverable. The host never journals EVENT_PARKED. This is not
Cancel and does not record a completed, failed, or canceled execution.
On decided recovery or replay the host sends approval BEFORE tool, even if a receipt already
exists. The harness must correlate approval.tool_call_id/request_seq with the waiting call and
receipt.id/approval_request_seq; the receipt's approval_decision_seq must identify the committed
decision in that session's journal, which the host validates. Denial requires APPROVAL_DENIED
and is_error=true without an executor call. Approval permits a success (CODE_UNSPECIFIED with
is_error=false) or EXECUTOR_ERROR with is_error=true. Conflicting decisions or receipt tuples
fail closed rather than being served to a different call. The harness may not manufacture
durable APPROVAL_REQUEST/APPROVAL_RESULT events. The gate is not supported for memory-snapshot
harnesses; reject it before executing an effect rather than pretending a park is a snapshot.
Host sink operations for an execution are serialized; callbacks must not re-enter that sink.
Once a recorded-prefix identity/correlation mismatch occurs, the execution remains divergent:
catching the error cannot authorize a later model/tool effect or mark recovery complete.
| Field |
Type |
Label |
Description |
| session |
string |
|
|
| execution_id |
string |
|
|
| start |
Start |
|
|
| cancel |
Cancel |
|
|
| approval |
ApprovalResult |
|
host-owned committed decision, before the correlated tool receipt |
| tool |
ToolResult |
|
result for a CONTROLLER_MEDIATED or decided REQUIRES_APPROVAL call |
| model |
ModelResult |
|
served completion for a mediated/replayed model call |
| park |
ApprovalRef |
|
host-owned unresolved request; requires correlated EVENT_PARKED |
| Field |
Type |
Label |
Description |
| id |
string |
|
|
| models |
string |
repeated |
model-agnostic: supported/required model ids |
| tools |
ToolSpec |
repeated |
|
| capabilities |
Capabilities |
|
|
| version |
string |
|
Stable, opaque implementation replay-compatibility version, owned by the harness author. Change it when deterministic execution or config interpretation changes. Hosts record it in ExecutionStart and compare known recorded versions exactly on replay/recovery. Empty is supported for older/unversioned harnesses and records an unknown version. |
IdentityContext carries the principal and signals whether the harness may mint
scoped, delegated tokens (Transaction Tokens) via the host for tool calls.
ModelResult is a model completion served to the harness (live invocation or replay).
The Message carries text, opaque reasoning, and tool_call parts, recorded verbatim for continuity.
| Field |
Type |
Label |
Description |
| message |
Message |
|
|
| usage |
Usage |
|
|
| model_call_id |
string |
|
correlates to the emitted ModelCall.id |
Start begins one execution. History is pushed here (pull-by-range is a later
addition); it is empty when the sandbox was memory-restored.
| Field |
Type |
Label |
Description |
| config |
bytes |
|
|
| history |
Event |
repeated |
|
| inputs |
Message |
repeated |
Invocation input messages. Controller replay and interrupted recovery restore the original messages from the journal; empty inputs describe an intentionally inputless invocation. |
| identity |
IdentityContext |
|
|
| resume_from_seq |
int64 |
|
|
| Field |
Type |
Label |
Description |
| name |
string |
|
|
| description |
string |
|
|
| mediation |
Mediation |
|
default mediation for this tool |
Resumability declares how a harness survives suspend/resume/fork. The host matches
this against a runtime's RuntimeCapabilities.
| Name |
Number |
Description |
| RESUMABILITY_UNSPECIFIED |
0 |
|
| RESUMABILITY_STATELESS_REPLAY |
1 |
default: rehydrate from history; any runtime |
| RESUMABILITY_REQUIRES_MEMORY_SNAPSHOT |
2 |
needs a memory-snapshot-capable runtime |
| Method Name |
Request Type |
Response Type |
Description |
| Describe |
DescribeRequest |
HarnessDescriptor |
Describe returns the static contract; used to match the harness to a runtime. |
| Connect |
ControllerFrame stream |
Event stream |
Connect drives ONE execution. The host sends Start (and optional control frames). Normally the harness streams Events terminated by exactly one EVENT_END. An unresolved approval instead follows park -> correlated EVENT_PARKED -> stream closure, with no EVENT_END. Durable requests/decisions belong to the host; this protocol applies to STATELESS_REPLAY only. After ACK and actual stream closure, the host closes the invocation connection, performs an external snapshot and commits SUSPEND before reporting a successful live pause. Handoff failures retain the durable request and their actual error; they are not park success. |
Top
The HarnessRegistry admin API: register, inspect and retire harnesses on a running host.
A registration is immutable. Its spec is content-addressed by spec_digest, so registering the
same spec under the same name again changes nothing, and a different spec under a taken name is
refused. Retiring a harness refuses new sessions on it while every existing session keeps
running, resuming and forking. Registering the identical spec again reactivates it.
This service decides what the host dials and pays model calls for, so it is an operator
surface, not a client one. agentsessionsd serves it only on a separate optional literal-loopback
listener (-registry-addr); Sessions never serves this API. Both listeners are plaintext and
unauthenticated. Every local or same-pod process that can reach the operator port can administer
registrations. See docs/security.md.
| Field |
Type |
Label |
Description |
| name |
string |
|
|
| observe |
bool |
|
Also ask the harness to Describe itself, bounded by a host timeout. The result is in observed or observe_error; a failed Describe does not fail the call. |
HarnessRegistration is one entry in the host's harness registry.
| Field |
Type |
Label |
Description |
| metadata |
ResourceMetadata |
|
metadata.name is the key that Session.harness and ExecRequest.harness refer to. metadata.uid is server-assigned and stays the same across UNCHANGED and REACTIVATED. metadata.project is unused: a registration is host-scoped. |
| spec |
HarnessSpec |
|
Unset for a STATIC harness, or for a stored registration whose spec this host cannot decode or validate. No partial spec is returned in the latter case; see unservable_reason. |
| spec_digest |
string |
|
"sha256:" followed by the lowercase hex SHA-256 of the RFC 8785 (JCS) form of the originally stored spec's proto3-JSON mapping, with proto field names, enum names, and unpopulated fields omitted. This is the same canonical form the journal hashes. Empty for a STATIC harness. Preserved when spec is unset for an undecodable registration: this host cannot recompute the original digest without understanding the complete spec. |
| state |
HarnessState |
|
|
| source |
HarnessSource |
|
|
| retire_time |
google.protobuf.Timestamp |
|
Set while RETIRED: when the harness was first retired. |
| retire_reason |
string |
|
Set while RETIRED: the reason given when the harness was first retired. |
| observed |
HarnessDescriptor |
|
Set only when GetHarnessRequest.observe is true and Describe succeeded: what the harness reported just now. Never stored. |
| observe_error |
string |
|
Set only when GetHarnessRequest.observe is true: why this host cannot serve the harness (isolated or not loaded), or why Describe failed. Never stored. |
| unservable_reason |
string |
|
Nonempty if this host cannot serve a stored registration. The row remains visible and its name reserved in the journal, ACTIVE or RETIRED. A registration isolated during this host's startup load remains known locally; Sessions operations needing it fail FAILED_PRECONDITION. A row added by another host after startup is visible here but unknown to this host's Sessions routing until restart or a local RegisterHarness with the identical compatible spec; selecting it for Create or auto-create Exec fails INVALID_ARGUMENT until loaded. For a RETIRED row, restart this host to serve its existing sessions without reactivating it: RegisterHarness reactivates the row for every host sharing the journal. A pending recorded Resume can still fail FAILED_PRECONDITION under the existing recovery rule. Strict decoding refuses unsupported stored fields and enum values, rather than accepting a partial spec. This is a host-local status, never stored: another compatible host may serve the same row. Do not match on this human-readable explanation. |
HarnessSpec is everything that decides what a session on this harness runs. It is the only
input to spec_digest, so nothing descriptive (labels, operation ids, timestamps) belongs here.
| Field |
Type |
Label |
Description |
| remote |
RemotePlacement |
|
|
| substrate |
SubstratePlacement |
|
|
| capabilities |
Capabilities |
|
The contract the harness declares. resumability is required. Placement still gates every turn on the capabilities the harness reports through Describe. |
| descriptor_id |
string |
|
Expected HarnessDescriptor.id. When set, Exec, Resume and Fork are refused with FAILED_PRECONDITION, before anything is journaled, if the harness's Describe reports a different id. It is checked on every call, not at registration. Empty means not checked. The id is what the harness reports about itself, so this catches an address that reaches the wrong harness; it is not authentication. |
| Field |
Type |
Label |
Description |
| page_size |
int32 |
|
Maximum entries per page. 0 means 50; values above 500 are clamped to 500. Negative is INVALID_ARGUMENT. |
| page_token |
string |
|
Opaque cursor from a prior ListHarnessesResponse.next_page_token. Empty means the first page. |
| include_retired |
bool |
|
Include RETIRED entries. STATIC entries are always included. |
| Field |
Type |
Label |
Description |
| harnesses |
HarnessRegistration |
repeated |
In name order, STATIC and REGISTERED entries together. |
| next_page_token |
string |
|
Empty on the last page. |
| Field |
Type |
Label |
Description |
| name |
string |
|
An RFC 1123 DNS label: lowercase alphanumerics and '-', starting and ending alphanumeric, at most 63 characters. |
| spec |
HarnessSpec |
|
|
RemotePlacement is a harness already running at address, dialed over the Harness service.
| Field |
Type |
Label |
Description |
| address |
string |
|
unix:///path/to.sock or host:port. |
| Field |
Type |
Label |
Description |
| name |
string |
|
|
| reason |
string |
|
Recorded on the first retire only. |
SubstratePlacement runs each session in its own actor created from an ActorTemplate. A host
serves it only if it was built with a substrate placement backend; otherwise RegisterHarness
returns FAILED_PRECONDITION.
| Field |
Type |
Label |
Description |
| atespace |
string |
|
|
| template |
string |
|
ActorTemplate name. |
| Name |
Number |
Description |
| HARNESS_SOURCE_UNSPECIFIED |
0 |
|
| HARNESS_SOURCE_STATIC |
1 |
Built into the host or configured when it started. Never stored, always ACTIVE, and read-only through this API: its name cannot be registered or retired. |
| HARNESS_SOURCE_REGISTERED |
2 |
Created through RegisterHarness and stored in the host's journal database. |
| Name |
Number |
Description |
| HARNESS_STATE_UNSPECIFIED |
0 |
|
| HARNESS_STATE_ACTIVE |
1 |
New sessions may select it. |
| HARNESS_STATE_RETIRED |
2 |
New sessions are refused with FAILED_PRECONDITION. Existing sessions keep Exec, Resume, Suspend and Fork; fork children inherit the harness and are not new selections. |
| Name |
Number |
Description |
| REGISTER_OUTCOME_UNSPECIFIED |
0 |
|
| REGISTER_OUTCOME_CREATED |
1 |
The name was free; the registration is new and ACTIVE. |
| REGISTER_OUTCOME_UNCHANGED |
2 |
The name already held this spec and was ACTIVE. Stored registration unchanged; a host that had not loaded a row added since startup may now serve it locally. |
| REGISTER_OUTCOME_REACTIVATED |
3 |
The name already held this spec and was RETIRED. It is ACTIVE again for every host sharing the journal. To load a RETIRED row for existing sessions without reactivating it, restart the host. |
HarnessRegistry manages the harnesses a host can place sessions on. It is an admin API: a caller
that can register a harness decides where the host sends session history and whose model calls it
pays for. Keep it off the Sessions listener and control access to it.
See docs/security.md#operator-access for operator setup and CLI usage.
| Method Name |
Request Type |
Response Type |
Description |
| RegisterHarness |
RegisterHarnessRequest |
RegisterHarnessResponse |
Returns CREATED, UNCHANGED or REACTIVATED. ALREADY_EXISTS when the name holds a different spec, or is taken by or reserved for a STATIC harness. FAILED_PRECONDITION when the host cannot serve a new placement. An identical repeat of a registration isolated during startup returns UNCHANGED or REACTIVATED with unservable_reason set; it does not claim this host serves it. An identical compatible repeat of a row added since startup can load it locally without restart. Repeating a RETIRED registration reactivates it for every host sharing the journal; restart the host instead to serve only its existing sessions without reactivation. |
| GetHarness |
GetHarnessRequest |
HarnessRegistration |
NOT_FOUND for a name that is neither STATIC nor registered. |
| ListHarnesses |
ListHarnessesRequest |
ListHarnessesResponse |
|
| RetireHarness |
RetireHarnessRequest |
HarnessRegistration |
Idempotent: retiring a RETIRED harness returns it unchanged. FAILED_PRECONDITION for a STATIC harness; NOT_FOUND for an unknown name. |
Top
The Sessions control-plane API (client-facing) and the Runtime compute types.
A Session is a durable conversation (event log) plus zero-or-one live incarnation.
Each Exec is one execution/turn. Fork branches the log at a sequence.
Approve supplies an explicit decision for one unresolved request in a stateless execution.
All tuple fields are required and request_seq must be positive. A decision resolves only a
request owned by this session, not an inherited parent request. Identity is recorded on the
decision's Event.actor as provenance, never checked as authorization. No policy hook, expiry,
automatic decision, or Cancel semantics are implied by this API.
| Field |
Type |
Label |
Description |
| session |
string |
|
|
| execution_id |
string |
|
|
| tool_call_id |
string |
|
|
| request_seq |
int64 |
|
|
| approved |
bool |
optional |
Required presence: false means deny; absent is INVALID_ARGUMENT. Unlike this request, the journal's ApprovalResult.approved remains a non-optional bool for compatibility. |
| reason |
string |
|
|
| identity |
IdentityRef |
|
|
A successful Approve commits the decision only, never resumes compute or executes a tool.
The caller invokes Resume separately. decision is the committed APPROVAL_RESULT LogRecord;
an exact retry returns that same record, not a new decision or receipt.
| Field |
Type |
Label |
Description |
| session |
Session |
|
|
| Field |
Type |
Label |
Description |
| uid |
string |
|
|
Delta is an ephemeral streaming chunk that coalesces into a finalized EVENT_OUTPUT (or
reasoning) part. No seq; never hash-chained (§8, A2A TaskArtifactUpdateEvent).
| Field |
Type |
Label |
Description |
| execution_id |
string |
|
|
| part_index |
int32 |
|
which content part it accumulates into |
| chunk |
string |
|
text chunk; binary/media deltas are a later addition |
| done |
bool |
|
last delta for this part |
| Field |
Type |
Label |
Description |
| session |
string |
|
The session to run against. Empty creates one first, using the server defaults and the harness below, and returns it as the stream's first frame. A caller that wants to set a project, name, or model still calls CreateSession; this exists so the common case is one call rather than three (create, read the cursor, exec). |
| inputs |
Message |
repeated |
Input messages for a new turn. While this session owns an unreceipted approval call, new inputs are FAILED_PRECONDITION, including after a decision but before its receipt. For an existing current approval-bearing, non-terminal execution, empty inputs recover that recorded invocation via Resume, without a new EXECUTION_START. Recorded inputs, config, harness, version and resume cursor win over this request's invocation overrides. Pending requests return a paused Session without runtime IO; a call-only crash cut repairs the request first. expected_last_seq is checked under the session guard before runtime IO or repair, and deadline_unix bounds recovery. Other inputless Exec calls retain their ordinary new-turn behavior; use Resume for general interrupted-turn recovery. |
| resume_from_seq |
int64 |
|
Cursor handed to the harness as Start.resume_from_seq. The host does not interpret it; only a harness knows what resuming from a sequence means for its own state. To re-read committed records after a disconnect, use Replay, which is the read path for exactly that. Non-zero cursors are journaled in EXECUTION_START and restored during controller replay/interrupted resume. |
| harness |
string |
|
Empty = the session's harness. A different harness runs this turn only, unless either one is a registered harness (see HarnessRegistry): then the session is pinned and the call is FAILED_PRECONDITION. A stored REQUIRES_MEMORY_SNAPSHOT harness also refuses a STATELESS_REPLAY override before any fence or journal write: parking only the override cannot checkpoint the stored harness's live memory. |
| config |
bytes |
|
Opaque per-execution config, passed through to Start.config. Non-empty bytes are journaled verbatim in EXECUTION_START before the harness runs, and restored for controller replay/resume. Do not put credentials here: config is durable journal content exposed by Replay. |
| expected_last_seq |
int64 |
optional |
Single-writer CAS: the host commits this execution's first event only if the log head equals expected_last_seq. A mismatch is ABORTED, meaning another writer advanced the log. It is optional because the guarantee should be opt-in rather than the price of a simple call. Unset means "append at whatever the head is now", which is what a caller with a single writer wants. Set means the strict check, and 0 is a real value there: it asserts the session has no events yet. That distinction is why this carries explicit presence instead of treating 0 as "unset" – a caller could not otherwise say "this must be the first turn". |
| deadline_unix |
int64 |
|
optional execution deadline (unix seconds); host cancels past it |
ExecUpdate is what the live Exec stream carries: the session, a committed LogRecord, or an
ephemeral streaming Delta (transport only — not logged, not hash-chained).
| Field |
Type |
Label |
Description |
| record |
LogRecord |
|
|
| delta |
Delta |
|
|
| session |
Session |
|
The session this execution runs against, sent as the FIRST frame of every Exec stream. It is how a caller learns the uid of a session Exec created for it, and it reports the cursor the turn started from. A successful approval park or approval-bearing no-input recovery also sends a FINAL current Session before OK stream closure. That frame carries the latest cursor and pending approval, when present; use the latest Session and committed record cursors for the next CAS, not the initial frame alone. A pause is not a terminal END/ERROR, and a pending query alone is not proof that compute has been made cold. It is sent before the turn runs, so a failed execution still tells the caller which session it was against. A caller therefore sees this frame BEFORE any error, and must read the stream to completion rather than treating the first receive as the result. |
Children inherit the parent's annotations and origin.
| Field |
Type |
Label |
Description |
| session |
string |
|
|
| at_seq |
int64 |
|
0 = HEAD. A REQUIRES_MEMORY_SNAPSHOT harness forks by cloning a memory snapshot, which captures RAM as of now, so it accepts only HEAD; a historical seq is FAILED_PRECONDITION. |
| count |
int32 |
|
fan-out N children; must be 1..128, else INVALID_ARGUMENT |
| identity |
IdentityRef |
|
Unsupported: per-child principals are not enforced. Any supplied identity, including an empty message, is INVALID_ARGUMENT before placement or mutation. Leave unset to fork. |
| labels |
ForkRequest.LabelsEntry |
repeated |
Applied to every child instead of the parent's labels; never merged or inherited. Unset or empty gives children an empty label map. The parent's annotations are inherited unchanged. |
| child_names |
string |
repeated |
Display names for the children, in the order they are returned. Length must be 0 or exactly count, else INVALID_ARGUMENT. Left unset, a child's name is empty rather than a copy of the parent's. A fork inherits the parent's workload (project, harness, model) because that is what defines the run, but a name is a caller-supplied label the server has no basis to invent. Copying it makes a listing report N+1 rows that claim to be the same session, and synthesizing one ("<parent> fork 2") would put a presentation convention in the wire contract and be wrong the moment the same parent is forked by two separate calls. Lineage is already on the child as parent_uid and fork_seq, so a caller that wants a derived label can render one without the server denormalizing it into a string. |
| Field |
Type |
Label |
Description |
| children |
Session |
repeated |
|
| Field |
Type |
Label |
Description |
| uid |
string |
|
|
ListSessions enumerates sessions from the durable store, so it returns sessions that have no
events and no live incarnation yet. Paging is keyset over (create_time DESC, uid ASC), which is
stable when a session is created mid-pagination; an offset would skip or repeat rows.
| Field |
Type |
Label |
Description |
| project |
string |
|
tenant / namespace; exact-match filter, not a prefix or wildcard |
| page_size |
int32 |
|
Maximum sessions to return. 0 = the server default; a value above the server maximum is clamped rather than rejected. |
| page_token |
string |
|
Opaque cursor taken verbatim from a prior ListSessionsResponse.next_page_token. Empty = first page. A token the server cannot parse is INVALID_ARGUMENT, never a silent restart from page 1. |
| Field |
Type |
Label |
Description |
| sessions |
Session |
repeated |
|
| next_page_token |
string |
|
empty on the last page |
| Field |
Type |
Label |
Description |
| session |
string |
|
|
| from_seq |
int64 |
|
|
| to_seq |
int64 |
|
0 = to head |
| Field |
Type |
Label |
Description |
| session |
string |
|
|
| boot |
bool |
|
Deprecated. Ignored. The service never reads it; the Runtime backend decides how a resumed session comes back. On substrate that is the actor's own snapshot, else the template's golden snapshot, else a cold boot, and substrate has no per-resume boot flag to forward it to. The field stays so existing clients keep encoding; do not reuse its number. |
| Field |
Type |
Label |
Description |
| memory_snapshot |
bool |
|
|
| cow_fork |
bool |
|
|
| attest |
bool |
|
|
| gpu_state |
bool |
|
|
| Field |
Type |
Label |
Description |
| metadata |
ResourceMetadata |
|
|
| harness |
string |
|
|
| model |
string |
|
model-agnostic id |
| exec_state |
ExecState |
|
Every Session reply uses the same append-transaction projection at last_seq: no events reports EXEC_PENDING; a valid owned unanswered host approval request in the latest first-seen execution reports EXEC_AWAITING; other histories retain EXEC_COMPLETED. COMPLETED is a compatibility fallback, not proof of END, a receipt, or admission. |
| compute_state |
ComputeState |
|
incarnation axis |
| pending_approval |
ApprovalRef |
|
Set for a valid unanswered host-owned APPROVAL_REQUEST in the latest first-seen execution at last_seq. Requests/decisions match execution_id, tool_call_id and request_seq. Calls whose TOOL_CALL precedes the child's latest FORK are excluded. Unset when no request is reportable, approval-bearing evidence is invalid, or the projection lags last_seq. |
| last_seq |
int64 |
|
event-log cursor |
| parent_uid |
string |
|
fork lineage |
| fork_seq |
int64 |
|
|
| identity |
IdentityRef |
|
Recorded provenance, never enforced: it says on whose behalf a session was created, and the hash chain makes that record tamper-evident. Nothing in this implementation treats it as authorization. See docs/security.md. |
| compute |
ComputeRef |
|
empty when SUSPENDED/TERMINATED |
| origin |
Origin |
|
neutral external context; filled by a producer adapter |
| labels |
Session.LabelsEntry |
repeated |
|
| annotations |
Session.AnnotationsEntry |
repeated |
free-form adapter metadata (K8s-style) |
SnapshotRef is the session-STATUS ref carried in ComputeRef below. Its shape mirrors the canonical
Go SPI type api.SnapshotRef and the durable form the log carries inline on the SUSPEND Lifecycle
event (common.proto Lifecycle.snapshot_*), so the three agree field for field.
local and external_uri are deliberately NOT a oneof: a memory-capable backend sets both at once
(substrate reports an actor handle in local and the object-storage URI in external_uri), which a
oneof cannot express. A filesystem-only backend sets only local, with memory=false.
ComputeRef is not yet populated on the wire; the Placer records the ref on the SUSPEND event
instead. Wiring session status is tracked separately.
| Field |
Type |
Label |
Description |
| local |
string |
|
|
| external_uri |
string |
|
|
| memory |
bool |
|
RAM/process captured? pod: false, kata/clh: true |
| sealed |
bool |
|
encrypted + attested (confidential) |
| Field |
Type |
Label |
Description |
| session |
string |
|
|
| Name |
Number |
Description |
| COMPUTE_STATE_UNSPECIFIED |
0 |
|
| COMPUTE_NONE |
1 |
no incarnation |
| COMPUTE_LIVE |
2 |
|
| COMPUTE_WARM |
3 |
paused: resident, worker held |
| COMPUTE_COLD |
4 |
suspended: snapshot in storage, worker freed |
| COMPUTE_TERMINATED |
5 |
|
ExecState is the execution/turn axis; ComputeState is the incarnation axis. The two are
modeled explicitly (§6 of the replay contract) and reported independently: there is no
flattened lifecycle enum, because collapsing them loses which axis actually moved.
| Name |
Number |
Description |
| EXEC_STATE_UNSPECIFIED |
0 |
|
| EXEC_PENDING |
1 |
|
| EXEC_RUNNING |
2 |
|
| EXEC_AWAITING |
3 |
blocked on approval/input, resolved from the log |
| EXEC_COMPLETED |
4 |
|
| EXEC_FAILED |
5 |
|
| EXEC_CANCELED |
6 |
|
| Method Name |
Request Type |
Response Type |
Description |
| CreateSession |
CreateSessionRequest |
Session |
|
| GetSession |
GetSessionRequest |
Session |
|
| ListSessions |
ListSessionsRequest |
ListSessionsResponse |
|
| DeleteSession |
DeleteSessionRequest |
Session |
Not implemented: the server returns UNIMPLEMENTED. Declared so the delete path can land without a breaking change to the service. |
| Exec |
ExecRequest |
ExecUpdate stream |
Exec runs one execution/turn. The live stream carries committed LogRecords plus ephemeral Deltas; Replay re-delivers committed records only (read-only). |
| Replay |
ReplayRequest |
LogRecord stream |
|
| Approve |
ApproveRequest |
ApproveResponse |
Implemented durable approval decisions for STATELESS_REPLAY executions. OK commits only a decision; the caller must Resume to continue. An exact retry of the tuple, approved value, reason and identity returns the existing decision, even after resolution. A changed decision/reason/identity for that request is FAILED_PRECONDITION, never an overwrite. INVALID_ARGUMENT: missing session/execution/tool-call tuple, non-positive request_seq, or absent approved. NOT_FOUND: unknown session. FAILED_PRECONDITION: stale, inherited, or wrong request tuple, changed decision, or invalid recorded approval evidence. The gate cannot be created for a non-stateless execution; Approve does not Describe or resolve a harness. ABORTED: local contention, append-CAS conflict or superseded fence; retry after reading the session. Identity is provenance only; this method provides no authorization, policy hook, expiry, implicit Resume, or Cancel behavior. |
| Cancel |
CancelRequest |
Session |
In-flight control: cancel the running execution. Not implemented: the server returns UNIMPLEMENTED. |
| Suspend |
SuspendRequest |
Session |
Compute-layer durability. There is no warm Pause: no Runtime backend implements a node-local warm checkpoint, so a session goes straight from live to a cold snapshot. Suspend routes an owned unreceipted approval to its recorded harness; inherited approvals and ordinary sessions use their stored default. An unserved recorded name is FAILED_PRECONDITION, with no fallback. cold, free worker |
| Resume |
ResumeRequest |
Session |
A recorded STATELESS_REPLAY override of a stored REQUIRES_MEMORY_SNAPSHOT harness is FAILED_PRECONDITION before compute changes or journal repair, as for Exec admission. Otherwise an unresolved owned approval returns its current paused Session without runtime IO. A call-only cut repairs the request; neither outcome proves cold compute. After a decision, recovery uses the recorded invocation and SnapshotRef. It may park at another gate (without RESUME), or finish and commit RESUME. A missing executor is FAILED_PRECONDITION and leaves the decision recoverable. Approved executor failures are durable EXECUTOR_ERROR receipts, available to the harness for continuation, not transport failures. Snapshots and unresolved requests are retained indefinitely; there is no approval expiry or automatic decision. |
| Fork |
ForkRequest |
ForkResponse |
The differentiator: branch a session at a sequence into one or more children. Forking a REQUIRES_MEMORY_SNAPSHOT harness first checkpoints the parent (it suspends, and a SUSPEND event lands on its chain) because the children are cloned from that snapshot; resume brings it back. |
| .proto Type |
Notes |
C++ |
Java |
Python |
Go |
C# |
PHP |
Ruby |
| double |
|
double |
double |
float |
float64 |
double |
float |
Float |
| float |
|
float |
float |
float |
float32 |
float |
float |
Float |
| int32 |
Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead. |
int32 |
int |
int |
int32 |
int |
integer |
Bignum or Fixnum (as required) |
| int64 |
Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead. |
int64 |
long |
int/long |
int64 |
long |
integer/string |
Bignum |
| uint32 |
Uses variable-length encoding. |
uint32 |
int |
int/long |
uint32 |
uint |
integer |
Bignum or Fixnum (as required) |
| uint64 |
Uses variable-length encoding. |
uint64 |
long |
int/long |
uint64 |
ulong |
integer/string |
Bignum or Fixnum (as required) |
| sint32 |
Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. |
int32 |
int |
int |
int32 |
int |
integer |
Bignum or Fixnum (as required) |
| sint64 |
Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. |
int64 |
long |
int/long |
int64 |
long |
integer/string |
Bignum |
| fixed32 |
Always four bytes. More efficient than uint32 if values are often greater than 2^28. |
uint32 |
int |
int |
uint32 |
uint |
integer |
Bignum or Fixnum (as required) |
| fixed64 |
Always eight bytes. More efficient than uint64 if values are often greater than 2^56. |
uint64 |
long |
int/long |
uint64 |
ulong |
integer/string |
Bignum |
| sfixed32 |
Always four bytes. |
int32 |
int |
int |
int32 |
int |
integer |
Bignum or Fixnum (as required) |
| sfixed64 |
Always eight bytes. |
int64 |
long |
int/long |
int64 |
long |
integer/string |
Bignum |
| bool |
|
bool |
boolean |
boolean |
bool |
bool |
boolean |
TrueClass/FalseClass |
| string |
A string must always contain UTF-8 encoded or 7-bit ASCII text. |
string |
String |
str/unicode |
string |
string |
string |
String (UTF-8) |
| bytes |
May contain any arbitrary sequence of bytes. |
string |
ByteString |
str |
[]byte |
ByteString |
string |
String (ASCII-8BIT) |