api

package
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 22, 2026 License: MIT Imports: 5 Imported by: 0

Documentation

Overview

Package api defines the agentsessions contracts: the Sessions control-plane API, the Harness BYOH SPI, and the Runtime compute SPI.

The .proto files in this directory are the wire format; these Go types are the hand-written SPI used by hosts and backends (to be reconciled with generated code).

Design rule: the core is vendor-neutral. Producers (GitHub, Foundry, custom apps) plug in on top as adapters; compute backends (pod, Kata, Cloud Hypervisor, substrate) plug in underneath via Runtime. No producer- or backend-specific fields in the core — specifics ride in Origin, annotations, and ComputeRef.Attributes.

Index

Constants

This section is empty.

Variables

View Source
var ErrApprovalParked = errors.New("approval parked")

ErrApprovalParked distinguishes a host-requested approval park from execution failure. A transport uses ApprovalParkedError.Ref, never error-string matching, for the park exchange.

View Source
var ErrCheckpointPending = errors.New("runtime: checkpoint upload is pending")

ErrCheckpointPending reports that a checkpoint's durable copy is still uploading. No usable checkpoint is returned and nothing is journaled; the upload may complete without operator intervention. The session service reports it as UNAVAILABLE, unlike an invalid checkpoint.

View Source
var ErrComputeBusy = errors.New("runtime: compute is busy with another operation")

ErrComputeBusy reports that the session's compute is in the middle of another operation (another host resuming or suspending it, say), so the backend could not place onto it or act on it right now. Nothing was journaled, and the state settles on its own, so the session service reports it as ABORTED and the caller retries. A stateful Fork also returns it when another caller replaced or captured the child compute it just created before it could resume it: no child is created, and the parent keeps the SUSPEND the fork took and its snapshot, so a retried Fork clones a new child.

View Source
var ErrInvalidCallerIdentity = errors.New("api: caller identity requires issuer and subject")

ErrInvalidCallerIdentity reports an incomplete owner passed to owned creation or an empty/incomplete owner filter passed to a session listing.

View Source
var ErrInvalidCheckpoint = errors.New("runtime: checkpoint does not meet the required contract")

ErrInvalidCheckpoint reports that a runtime cannot produce or resume a checkpoint with the required durable handle and fidelity. Capture may already have suspended compute; no usable ref is returned, and callers must inspect/correct the runtime evidence before retrying. The session service reports it as FAILED_PRECONDITION, not an internal transport failure.

View Source
var ErrInvalidModelPolicy = errors.New("model policy requires an explicit allowed default and nonempty model IDs")

ErrInvalidModelPolicy rejects host policy without an explicit, allowed default or with empty IDs.

View Source
var ErrMemoryStateLost = errors.New("runtime: session's in-memory harness state is lost")

ErrMemoryStateLost reports that a backend cannot give a session whose harness keeps its state only in RAM (REQUIRES_MEMORY_SNAPSHOT) the compute that held that state, because the compute is gone or came back without that state. Create returns it rather than create fresh compute when the journal already records a started turn on that harness (SessionSpec.StartedTurns). Restore returns it for any such session whose compute no longer exists, whatever the journal records, since the snapshot it would restore went with the compute; the recorded compute, still there after a failed restore, keeps the restore error whatever snapshot it holds (see InstanceRestorer). A backend also returns it from Create, Restore, Fork and Snapshot when the compute is there but did not get back the memory its snapshot held (substrate resuming it on a worker that restored only its files). The host returns it when the compute a turn or a Resume was placed on reports another Incarnation.ComputeInstance than the journal recorded: the compute was replaced under the same name. Snapshot returns it when the compute behind Incarnation.ID is not the instance the caller required (a stateful fork). A backend whose compute can hold a snapshot the journal never recorded returns it from Create, Restore and Snapshot when the compute holds one other than the checkpoint the journal last recorded (SessionSpec.RecordedCheckpoint, Incarnation.RecordedCheckpoint, Restore's ref), before it resumes the compute or, from Create and Restore, after, on what the resume reports. The journal cannot rebuild the state (I4), so fresh compute would continue the journal with a harness that has forgotten it. Retrying does not fix it, except when the missing record is still being written or was written after the caller read it: another host's Snapshot between its capture and its SUSPEND append is refused until that append lands, and Restore's check after the resume refuses a SUSPEND another host recorded after Restore's ref was read, which a retry reads. The session service reports it as FAILED_PRECONDITION.

View Source
var ErrModelNotAllowed = errors.New("model is not allowed by the host policy")

ErrModelNotAllowed rejects a session default, declared model, or mediated request outside the host's allowed set. A mediated rejection is execution-fatal even if the harness handles it.

View Source
var ErrPermissionDenied = errors.New("api: permission denied")

ErrPermissionDenied is returned by OwnerAuthorizer when the caller does not own the session, either identity is incomplete, the session UID is missing, or the action is not an ordinary owner action (including create, approve and mint).

View Source
var ErrSnapshotSuperseded = errors.New("runtime: fork source snapshot was superseded")

ErrSnapshotSuperseded reports that a fork's source snapshot is no longer the one the parent holds, because the parent was resumed (and possibly checkpointed again) after the snapshot was taken. The fork cannot clone it without pairing the children's journal prefix with different RAM; the caller can retry the fork at the parent's new head.

Functions

func IsParkUnwind

func IsParkUnwind(err error, ref ApprovalRef) bool

IsParkUnwind reports whether err contains only wrapped or joined parks for ref, with no independent failure elsewhere in the error tree. A matching park alone does not prove that the host has checkpointed compute or durably recorded a successful pause.

Types

type Action added in v0.3.0

type Action string

Action identifies a permission independently of the RPC or transport.

const (
	ActionRead             Action = "read"
	ActionExec             Action = "exec"
	ActionFork             Action = "fork"
	ActionSuspend          Action = "suspend"
	ActionResume           Action = "resume"
	ActionDelete           Action = "delete"
	ActionCancel           Action = "cancel"
	ActionCreate           Action = "create"
	ActionApprove          Action = "approve"
	ActionMint             Action = "mint"
	ActionList             Action = "list"
	ActionRegistryRead     Action = "registry.read"
	ActionRegistryList     Action = "registry.list"
	ActionRegistryRegister Action = "registry.register"
	ActionRegistryRetire   Action = "registry.retire"
)

type ApprovalDecision

type ApprovalDecision struct {
	ExecutionID string
	ToolCallID  string
	RequestSeq  int64
	Approved    bool
	Reason      string
	Identity    IdentityRef
}

ApprovalDecision is a caller's decision for one request. Identity records provenance only; it is not an authorization credential. The wire request uses explicit Approved presence so an omitted decision can be rejected; this domain value represents a supplied decision.

type ApprovalParkedError

type ApprovalParkedError struct {
	Ref ApprovalRef
}

ApprovalParkedError carries the request correlation for a parked Run. It does not commit a request or decision; durable approval state belongs to the host's journal.

func (*ApprovalParkedError) Error

func (e *ApprovalParkedError) Error() string

func (*ApprovalParkedError) Unwrap

func (e *ApprovalParkedError) Unwrap() error

type ApprovalRef

type ApprovalRef struct {
	ExecutionID string
	ToolCallID  string
	RequestSeq  int64
}

ApprovalRef identifies one host-owned approval request within the enclosing session. RequestSeq is the positive journal sequence, not a harness-chosen correlation number.

type ApprovalRequest

type ApprovalRequest struct {
	ToolCallID string
	Reason     string
}

ApprovalRequest asks a human or policy engine to allow a tool call.

type ApprovalResult

type ApprovalResult struct {
	ToolCallID string
	Approved   bool
	Reason     string
	RequestSeq int64 `json:",omitempty"` // sequence of the host-owned APPROVAL_REQUEST; zero for legacy decisions
}

ApprovalResult answers an ApprovalRequest (sent by the host).

type AuthorizationRequest added in v0.3.0

type AuthorizationRequest struct {
	Caller     CallerIdentity
	Action     Action
	SessionUID string
	Owner      CallerIdentity
	// Method is the full originating RPC name, for example
	// "/agentsessions.v1.Sessions/Exec" (Sessions_Exec_FullMethodName in genpb).
	// All checks for that RPC retain this value, including compound permissions,
	// auto-creation and recovery. Direct Go handler calls populate it too.
	// OwnerAuthorizer and OwnerAllowlistAuthorizer decide by Action, not Method.
	Method string
}

AuthorizationRequest carries the verified caller and trusted stored owner of one session. Owner is empty for legacy unbound sessions and global actions; policies may authorize legacy history, but OwnerAuthorizer denies an empty owner. It is not a request-supplied ownership assignment. Stateful Fork requires a separate suspend check; Resume that drives effects also requires exec.

type Authorizer added in v0.3.0

type Authorizer interface {
	Authorize(context.Context, AuthorizationRequest) error
}

Authorizer decides one resource permission. A denial must precede disclosure or effects. Listing needs an authorized storage query, not post-filtered pages. Sessions and HarnessRegistry invoke it when their authorization option is set. Return ErrPermissionDenied (possibly wrapped) for denial; other errors are host failures, not policy denials. The policy owns logging and metrics for its own failures: services sanitize them without logging the original policy error.

type CallerIdentity added in v0.3.0

type CallerIdentity struct {
	Issuer  string
	Subject string
}

CallerIdentity is the exact issuer/subject pair of a caller verified by a trusted host. It is not IdentityRef (agent provenance), and constructing it performs no cryptographic verification. Do not populate it from caller-supplied metadata.

func (CallerIdentity) Valid added in v0.3.0

func (c CallerIdentity) Valid() bool

Valid reports whether both parts of the authority key are present. No trimming, case folding or issuer-prefix mapping is performed.

type Capabilities

type Capabilities struct {
	Resumability Resumability
	ForkSafe     bool // no un-replayable side effects mid-turn -> fork via replay is safe
	RequiresGPU  bool
	Streaming    bool
	// ReasoningReplay: the harness persists and replays opaque provider reasoning parts
	// verbatim via the provider's stateless path (not previous_response_id / server lineage).
	// This keeps a reasoning harness on STATELESS_REPLAY — it adds NO snapshot edge. Verified
	// across Anthropic/OpenAI/Gemini in the Track A reasoning-continuity spike.
	ReasoningReplay bool
}

Capabilities is what a harness needs from the runtime and how it may be moved.

type ComputeRef

type ComputeRef struct {
	Runtime      string
	Worker       string // pod/worker id when live/warm; empty when cold
	Snapshot     *SnapshotRef
	Capabilities RuntimeCapabilities
	Attributes   map[string]string // backend-specific, e.g. substrate actor/atespace
}

ComputeRef describes the session's current incarnation.

type ComputeState

type ComputeState string

ComputeState is the incarnation (compute/sandbox) axis of a session's lifecycle.

const (
	ComputeNone       ComputeState = "NONE" // no incarnation
	ComputeLive       ComputeState = "LIVE" // running
	ComputeWarm       ComputeState = "WARM" // paused: resident, worker held
	ComputeCold       ComputeState = "COLD" // suspended: snapshot in storage, worker freed
	ComputeTerminated ComputeState = "TERMINATED"
)

type DeletionState

type DeletionState string

DeletionState is the permanent-deletion axis, independent of execution and compute. Pending acknowledges durable intent only; retained resources have not been reclaimed. Any other value is unrecognized and fails closed: it is treated as deleted, never as ACTIVE.

const (
	DeletionActive  DeletionState = "ACTIVE"
	DeletionPending DeletionState = "PENDING"
)

type Delta

type Delta struct {
	ExecutionID string
	PartIndex   int32
	Chunk       string
	Done        bool
}

Delta is an ephemeral streaming chunk. It is transport only: never appended to the log, never hash-chained, and never produced on replay. Chunks coalesce into the finalized EVENT_OUTPUT the log does record, so the journal is identical whether or not anyone was watching the turn.

type Descriptor

type Descriptor struct {
	ID           string
	Version      string   // stable author-owned replay version; empty is supported as unknown
	Models       []string // supported/required IDs; a subset of explicit host policy, never its default
	Tools        []ToolSpec
	Capabilities Capabilities
}

Descriptor is a harness's static contract.

type Error

type Error struct {
	Code        int32
	Description string
}

Error mirrors a gRPC status code + description.

type Event

type Event struct {
	// ExecutionID, timestamp, and content live on the Event; ordering (seq) and integrity
	// (prev_hash / content_hash) are host-assigned and live on the log-record envelope
	// (eventlog.Record / proto LogRecord), not on the harness-emitted Event.
	ExecutionID   string
	Timestamp     time.Time
	SchemaVersion int32 // versions the event body; replay survives schema skew

	Kind EventKind

	// typed body (exactly one set)
	Message        *Message
	ModelCall      *ModelCall
	ToolCall       *ToolCall
	Result         *ToolResult
	Approval       *ApprovalRequest
	ApprovalResult *ApprovalResult
	Usage          *Usage
	Lifecycle      *Lifecycle
	End            *HarnessEnd
	Err            *Error
	ExecutionStart *ExecutionStart
	Parked         *ApprovalRef `json:",omitempty"` // transport only, excluded from durable history

	Actor IdentityRef // emitter principal -> provenance on every action
}

Event is the shared unit of the session log and the harness stream. The host assigns the authoritative Seq on append. Ordering + integrity + identity live on the envelope; typed content lives in the body.

type EventKind

type EventKind string

EventKind classifies an Event. Typed events (vs opaque messages) are what make provenance, audit, cost, and tool-approval first-class.

const (
	EventInput           EventKind = "INPUT"
	EventModelCall       EventKind = "MODEL_CALL"
	EventOutput          EventKind = "OUTPUT"
	EventToolCall        EventKind = "TOOL_CALL"
	EventToolResult      EventKind = "TOOL_RESULT"
	EventApprovalRequest EventKind = "APPROVAL_REQUEST"
	EventApprovalResult  EventKind = "APPROVAL_RESULT"
	EventUsage           EventKind = "USAGE"
	EventLifecycle       EventKind = "LIFECYCLE"
	EventEnd             EventKind = "END"
	EventError           EventKind = "ERROR"
	EventExecutionStart  EventKind = "EXECUTION_START"
	EventParked          EventKind = "PARKED" // transport-only approval park acknowledgement; never journaled
)

type EventSink

type EventSink interface {
	// Model performs a model call and returns the completion. Live: the host invokes the
	// model and records the result. Replay: the host serves the recorded result from the
	// journal and does not invoke the model. Because the result flows back through this
	// mediated call, the harness never touches a provider SDK directly — the load-bearing
	// replay rule. Reasoning parts ride in the returned ModelResponse.Message and are
	// recorded verbatim for replay/fork continuity (I2). The completion is recorded as the
	// turn's output by the host; do not also emit the same content via Output (double-record).
	//
	// ctx carries the execution's cancellation and deadline through to the provider call, so
	// a cancelled turn stops an in-flight completion instead of orphaning it. Pass the ctx
	// from Run, or one derived from it.
	Model(ctx context.Context, req ModelRequest) (ModelResponse, error)
	// Output streams assistant output (a delta or a full message).
	Output(ctx context.Context, delta string) error
	// ToolCall emits a tool call and returns its result. For CONTROLLER_MEDIATED or
	// REQUIRES_APPROVAL tools it blocks until the host returns a result; for
	// IN_HARNESS_REPORTED tools the author executes the tool and calls Report instead.
	// ctx bounds that wait: a cancelled ctx unblocks it rather than hanging on a host that
	// never replies.
	ToolCall(ctx context.Context, tc ToolCall) (ToolResult, error)
	// Report records the result of a tool the harness executed itself.
	Report(ctx context.Context, tr ToolResult) error
	// Usage records token/cost accounting. To record a model call's usage, pass the
	// ModelResponse.Usage that Model returned: Replay and Resume serve the recorded usage with
	// the recorded completion, so the same call matches the record.
	Usage(ctx context.Context, u Usage) error
}

EventSink is the harness author's handle for emitting events. The SDK hides the gRPC stream, sequence assignment, and the emit -> wait-for-host round-trip.

type ExecState

type ExecState string

ExecState is the execution/turn axis of a session's lifecycle — the event-log axis. It is modeled separately from ComputeState (the incarnation axis) rather than flattened into a single enum, matching the durable-log & replay contract (§6). Both axes are authoritative and are reported independently on the wire.

const (
	ExecPending   ExecState = "PENDING"
	ExecRunning   ExecState = "RUNNING"
	ExecAwaiting  ExecState = "AWAITING" // blocked on approval/input, resolved from the log
	ExecCompleted ExecState = "COMPLETED"
	ExecFailed    ExecState = "FAILED"
	ExecCanceled  ExecState = "CANCELED"
)

type ExecutionStart

type ExecutionStart struct {
	// Model is the effective default under an explicit host policy. Empty keeps pre-policy
	// semantics, including unvalidated model requests. Omit it to preserve old journal hashes.
	Model          string `json:",omitempty"`
	Config         []byte
	ResumeFromSeq  int64
	InputCount     *int64
	Harness        string // resolved registry name; empty legacy values use the session harness
	HarnessVersion string // advertised opaque version; empty is unknown and retains legacy behavior
	// ComputeInstance is Incarnation.ComputeInstance of the compute the turn was placed on; empty when
	// the backend set none (a stateless harness, or a backend that cannot tell instances apart).
	ComputeInstance string
}

ExecutionStart is host-owned invocation state, recorded before the harness runs. Config is opaque and preserved verbatim; ResumeFromSeq is the harness's cursor, not the log's CAS cursor. InputCount records the expected number of INPUT events; zero explicitly permits inputless turns. A nil count cannot establish completeness and is rejected when reconstructing this invocation. Executions without this event reconstruct with empty config and a zero cursor (legacy defaults).

type FilePart

type FilePart struct {
	MIME   string
	Bytes  []byte
	URI    string
	Digest string // content digest of the URI target, so the hash-chain covers externalized bytes
	Name   string
}

FilePart carries media inline or by URI (A2A file part; MCP resource_link).

type ForkOpts

type ForkOpts struct {
	ChildSessionUID string
}

ForkOpts parameterizes a fork.

type Harness

type Harness interface {
	// Describe returns the static contract, used to match the harness to a Runtime.
	Describe(ctx context.Context) (Descriptor, error)

	// Run drives exactly one execution (turn). It reads the Start, emits events via
	// sink, and returns nil on COMPLETED or an error on FAILED. Cancellation via ctx.
	Run(ctx context.Context, s *Start, sink EventSink) error
}

Harness is the Bring-Your-Own-Harness SPI. 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 Run; the harness runs inside the sandbox provided by a Runtime.

The wire contract is api/harness.proto (Harness.Connect / Harness.Describe); an SDK adapts between them and hides sequence numbers and the tool-mediation round-trip.

type HarnessEnd

type HarnessEnd struct {
	State string // COMPLETED | FAILED | CANCELED
	Error *Error
}

HarnessEnd is the terminal state of one execution.

type IdentityContext

type IdentityContext struct {
	Principal IdentityRef
	MintToken TokenMinter // nil when identity is not configured (dev)
}

IdentityContext carries the session principal and, optionally, a minter so the harness can obtain scoped, delegated tokens (Transaction Tokens) for tool calls rather than passing the raw principal downstream.

type IdentityRef

type IdentityRef struct {
	Principal string
	Issuer    string
	Subject   string // session-scoped sub
}

IdentityRef is the bound agent principal. It is OIDC-neutral: an Entra Agent ID is one issuer; a SPIFFE ID or a GitHub App identity are others. Carried on every event.

type Incarnation

type Incarnation struct {
	ID         string
	Worker     string // pod/worker id
	Address    string // where the harness server listens, or the ingress that routes to it
	Runtime    string // "pod" | "kata" | "clh" | "substrate"
	FenceToken int64  // monotonic; the log rejects appends from a superseded incarnation
	// CallMetadata is request metadata the host must attach to every call it makes to the harness at
	// Address. A backend whose harness sits behind a shared ingress uses it to name the target
	// sandbox (substrate: ate-target-actor); a backend that hands out a direct address leaves it
	// empty. It is routing, not authentication: nothing here proves the caller's identity.
	CallMetadata map[string]string
	// ComputeInstance is an opaque identity of the compute instance behind ID that differs between two
	// instances reusing one ID (substrate: the actor's server-assigned UID, while ID is the actor
	// name). A backend sets it only when the harness keeps its state in that instance's memory
	// (REQUIRES_MEMORY_SNAPSHOT). The host records it in the turn's EXECUTION_START and refuses a turn
	// or a Resume placed on an instance other than the latest one the journal recorded for that
	// harness since the session's FORK marker, or the clone that marker recorded from Fork's
	// incarnation (ErrMemoryStateLost): a replacement holds none of the state. Suspend and a stateful
	// fork pass that recorded instance to Snapshot, which refuses another one.
	// Empty records nothing and skips the check.
	ComputeInstance string
	// RecordedCheckpoint, on the Incarnation passed to Snapshot, is the checkpoint the session's
	// journal last recorded for the session (see SessionSpec.RecordedCheckpoint); the zero value
	// means none. Suspend and a stateful fork set it. A backend whose compute can hold a snapshot
	// the journal never recorded (substrate: a capture a memory-tier Snapshot refused) refuses with
	// ErrMemoryStateLost, before capturing, compute that holds another one: capturing it again
	// would record state that is not the session's. Create, Restore and Fork leave it empty.
	RecordedCheckpoint SnapshotRef
}

Incarnation is a live compute instance of a session (a sandbox).

type InstanceRestorer added in v0.3.0

type InstanceRestorer interface {
	RestoreInstance(ctx context.Context, ref SnapshotRef, recorded func() (string, error)) (Incarnation, error)
}

InstanceRestorer is an optional extension of Runtime for a backend that sets Incarnation.ComputeInstance. RestoreInstance is Restore with a way to read the compute instance the journal last recorded for the session's harness, so the backend can distinguish that instance from a replacement before reattaching, and classify permanent loss after a failed restore. recorded returns "" when no instance is recorded. The backend may call it during admission and again after a failed restore; each call must read current journal state, so another host's intervening turn is seen. A read failure can refuse admission before any resume. A backend reports ErrMemoryStateLost from RestoreInstance only when it can show the recorded instance gone or replaced or, with none recorded, finds an instance it cannot tell from a replacement, and otherwise returns the restore error: an instance that is still there may fail a restore for another reason. The host calls RestoreInstance in place of Restore when the backend implements it.

type Lifecycle

type Lifecycle struct {
	Kind     LifecycleKind
	Detail   string
	Snapshot *SnapshotRef // captured state, set on SUSPEND (§5.1)
	// ComputeInstance is set only on FORK: Incarnation.ComputeInstance of the compute the child was
	// cloned onto. The child's turns are compared with it until the child records its own; empty
	// (a stateless fork, or a marker written before the field existed) compares nothing.
	ComputeInstance string
}

Lifecycle marks a compute/session transition in the log (§7). Baseline is a replay / compaction checkpoint (§1).

type LifecycleKind

type LifecycleKind string

LifecycleKind enumerates the lifecycle transitions recorded in the log.

const (
	LifecycleSuspend  LifecycleKind = "SUSPEND"
	LifecycleResume   LifecycleKind = "RESUME"
	LifecycleFork     LifecycleKind = "FORK"
	LifecycleBaseline LifecycleKind = "BASELINE"
	LifecycleCancel   LifecycleKind = "CANCEL"
	LifecycleDelete   LifecycleKind = "DELETE" // host-owned permanent intent, not compute teardown
)

type Mediation

type Mediation string

Mediation controls how a tool call is executed.

const (
	// MediationInHarnessReported: the harness executes the tool in-sandbox and reports
	// the result as an event for audit. Default; fastest.
	MediationInHarnessReported Mediation = "IN_HARNESS_REPORTED"
	// MediationControllerMediated: the harness emits the call; the host/gateway executes
	// it (authz + policy + audit) and returns the result.
	MediationControllerMediated Mediation = "CONTROLLER_MEDIATED"
	// MediationRequiresApproval: the call pauses for human or policy approval.
	MediationRequiresApproval Mediation = "REQUIRES_APPROVAL"
)

type Message

type Message struct {
	Role  string // system | user | assistant (A2A calls this "agent") | tool
	Parts []Part
}

Message is a role-tagged sequence of content parts (A2A Message = role + Part[]).

func TextMessage

func TextMessage(role, text string) *Message

TextMessage constructs a single-text-part message.

func (*Message) Text

func (m *Message) Text() string

Text concatenates the text parts of a message (ignoring non-text parts).

type ModelCall

type ModelCall struct {
	Model     string
	Params    map[string]string
	InputHash string // required for STATELESS_REPLAY so the §9.1 I0 check can run
	ID        string // correlation id for the served ModelResult (proto ModelCall.id)
}

ModelCall records a call to a model (model-agnostic) for audit and cost.

type ModelPolicy added in v0.3.0

type ModelPolicy struct {
	Default string
	Allowed []string
}

ModelPolicy is host-owned, opt-in model admission for one harness route. It is configured through the embedder Go API, never supplied by a Sessions client or inferred from Descriptor.Models. IDs are opaque. Default must be nonempty and present in Allowed; empty Allowed IDs are invalid. Without a policy the host retains its existing model behavior.

func (ModelPolicy) Resolve added in v0.3.0

func (p ModelPolicy) Resolve(model string) (string, error)

Resolve validates the policy and returns model, or the explicit default when model is empty.

func (ModelPolicy) ValidateDescriptor added in v0.3.0

func (p ModelPolicy) ValidateDescriptor(desc Descriptor) error

ValidateDescriptor requires every declared model to be allowed. An empty declaration is valid; it never widens the host policy or supplies its default.

type ModelRequest

type ModelRequest struct {
	// Model may override Start.Model within host policy. Empty resolves to that default only
	// for policy-aware invocations; old invocations retain their original requests and hashes.
	Model    string
	Messages []Message // context (history + new input) sent to the model
	Params   map[string]string
	// Tools are the definitions offered to the model on this call. Order is significant.
	Tools []ToolDefinition `json:",omitempty"`
	// ToolChoice constrains whether and which tool the model calls. Nil means the provider default.
	ToolChoice *ToolChoice `json:",omitempty"`
}

ModelRequest is a model call: the message context + model selection.

The controller hashes the JSON encoding of ModelRequest for the I0 check, so fields added after the first three carry `json:",omitempty"`: a request that does not use them hashes exactly as it did before they existed, and logs recorded earlier keep replaying.

type ModelResponse

type ModelResponse struct {
	Message Message
	Usage   Usage
}

ModelResponse is the model's completion: an assistant message (which may carry text, opaque reasoning, and tool call parts) plus usage.

type Origin

type Origin struct {
	Source     string            // e.g. "github.com/acme/repo", "foundry/project-x"
	Subject    string            // e.g. "issues/42", "threads/abc"
	URI        string            // optional link
	Attributes map[string]string // adapter-specific extras; well-known keys via profiles
}

Origin is the neutral external context a session is tied to: where it came from and what it is about. Producer adapters (GitHub, Foundry, custom apps) fill it; the core defines no producer-specific fields. Modeled on CloudEvents source/subject.

type OwnerAllowlistAuthorizer added in v0.3.0

type OwnerAllowlistAuthorizer struct {
	Allow map[Action][]CallerIdentity
}

OwnerAllowlistAuthorizer composes ordinary owner permissions with explicit exact-caller allowlists for create, list, approve and registry operator actions. Approve RPCs check read separately: an approver must also own the session with this policy. Allowlists cannot override owner checks or enable mint/unknown actions. Configure Allow before serving and do not mutate it during use. Global actions use an empty SessionUID and Owner. This policy interprets no grants or identity/provenance supplied in requests.

func (OwnerAllowlistAuthorizer) Authorize added in v0.3.0

type OwnerAuthorizer added in v0.3.0

type OwnerAuthorizer struct{}

OwnerAuthorizer is the first owner/grants policy implementation. It supports owner checks only; no grants are interpreted. Approval decisions, audience minting and creation require separate policy and are denied even to owners. ActionFork authorizes the parent only; it does not assign child ownership. The current fork path creates unbound children. Enforcing hosts need a separate owned-child reservation/publication primitive before exposing owned forks.

func (OwnerAuthorizer) Authorize added in v0.3.0

type Part

type Part struct {
	Text      *TextPart
	File      *FilePart
	Data      map[string]any
	Reasoning *ReasoningPart
	// ToolCall is a model's request to call a tool, carried in an assistant message. Mediation
	// and IdempotencyKey are unset on a model output. To execute the call, copy it, set them on
	// the copy, and pass the copy to EventSink.ToolCall: the returned message can share this
	// pointer with the recorded completion, so changing it in place alters a hashed event.
	ToolCall *ToolCall `json:",omitempty"`
	// ToolResult 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.
	ToolResult *ToolResult `json:",omitempty"`
}

Part is one unit of content: text, file (inline or URI), structured data, an opaque reasoning block, a model's tool call, or a tool's result. Aligned with A2A Part + MCP content. Exactly one field is set.

Fields added after the first four carry `json:",omitempty"`: the controller's model input hash (I0) is computed over the JSON encoding of ModelRequest, so a new field that encoded as null would change the hash of every request recorded before it existed.

type ReasoningPart

type ReasoningPart struct {
	Provider      string // "anthropic" | "openai" | "google"
	ModelID       string
	Opaque        []byte // set, OR OpaqueURI when externalized
	OpaqueURI     string
	OpaqueDigest  string // content digest of OpaqueURI target (hash-chain covers externalized bytes)
	Summary       []Part // optional, non-authoritative, compaction-droppable
	ItemID        string
	Ordinal       int32
	ValidityScope string // = execution id (turn)
}

ReasoningPart is an opaque, provider-tagged reasoning block replayed verbatim to preserve reasoning continuity within a turn (I2). agentsessions never interprets Opaque; provider specifics live inside it. One part type across all providers (Track A spike: no per-provider sub-shapes, no memory-snapshot edge).

type Resumability

type Resumability string

Resumability declares how a harness survives suspend/resume/fork.

const (
	// ResumabilityStatelessReplay: the harness holds no durable in-memory state beyond
	// the event log. On resume/fork the host replays history via Start.History. Runs on
	// any runtime, including a plain pod. Default.
	ResumabilityStatelessReplay Resumability = "STATELESS_REPLAY"
	// ResumabilityRequiresMemorySnapshot: the harness holds in-process state (a REPL, a
	// browser, a long-running process). The host only schedules it on a runtime whose
	// RuntimeCapabilities.MemorySnapshot is true.
	ResumabilityRequiresMemorySnapshot Resumability = "REQUIRES_MEMORY_SNAPSHOT"
)

type Runtime

type Runtime interface {
	// Create starts a cold incarnation (sandbox) for a session and returns a handle
	// including the address where the harness server listens.
	Create(ctx context.Context, s *SessionSpec) (Incarnation, error)

	// Snapshot captures the incarnation's state. SnapshotLocal (warm/pause) keeps it
	// node-resident. SnapshotExternal owns the cold transition: it captures required state,
	// releases dedicated per-incarnation compute where applicable, and preserves the state
	// and any backend handles Restore needs. A backend without memory snapshots may return
	// a filesystem/journal handle; without dedicated per-session compute, its shared harness
	// server may remain running.
	//
	// A non-empty in.ComputeInstance is the instance the caller requires behind in.ID (the
	// latest one the journal recorded). A backend that sets ComputeInstance refuses with
	// ErrMemoryStateLost when another instance is there, or none is, before it captures anything
	// if it can tell, and in any case before returning a ref: a snapshot of a replacement would
	// hand its callers compute that holds none of the session's state. in.RecordedCheckpoint is
	// the checkpoint the journal last recorded; a backend may refuse, with ErrMemoryStateLost,
	// compute that holds another one (see Incarnation.RecordedCheckpoint).
	Snapshot(ctx context.Context, in Incarnation, kind SnapshotKind) (SnapshotRef, error)

	// Restore brings an incarnation back from a snapshot. Sub-second on memory-capable
	// backends; a filesystem-only backend restores the workspace and relies on the host
	// replaying the event log.
	Restore(ctx context.Context, ref SnapshotRef) (Incarnation, error)

	// Fork creates a child incarnation. A backend with MemorySnapshot clones ref's captured state so
	// the child continues from the parent's RAM; a filesystem-only backend returns a fresh incarnation
	// and relies on the host replaying the child's copied log prefix. Implementations must not leak a
	// partially-provisioned child: on any failure after the child exists, tear it down before returning.
	// A backend that finds ref no longer held by the parent returns an error wrapping
	// ErrSnapshotSuperseded. The host records the returned ComputeInstance on the child's FORK
	// marker, and compares the child's compute with it until the child's first turn records one.
	Fork(ctx context.Context, ref SnapshotRef, opts ForkOpts) (Incarnation, error)

	// Stop is destructive teardown: it destroys the incarnation and frees its dedicated compute.
	// Callers must not assume a captured SnapshotRef remains restorable after Stop.
	Stop(ctx context.Context, in Incarnation) error

	// Status reports the incarnation's compute-lifecycle state.
	Status(ctx context.Context, in Incarnation) (ComputeState, error)

	// Capabilities reports what this backend supports.
	Capabilities() RuntimeCapabilities
}

Runtime is the compute/sandbox SPI. Pod, Kata Pod Sandboxing, Cloud Hypervisor, Dragonball, Hyperlight, and agent-substrate all implement it. There is no gVisor requirement — backends are interchangeable, and the host reads Capabilities to place harnesses and degrade honestly.

This is the seam that lets "different folks on top" (via producer adapters + the Sessions API) run on "substrate underneath" (or pod, Kata, ...) with no API change.

type RuntimeCapabilities

type RuntimeCapabilities struct {
	MemorySnapshot bool // can capture/restore RAM+process (pod: false, kata/clh: true)
	CoWFork        bool // copy-on-write fork
	Attest         bool // attestation on restore (confidential)
	GPUState       bool // accelerator state capture
}

RuntimeCapabilities is what a backend can do. The host matches these against a harness's Capabilities before scheduling.

type Session

type Session struct {
	UID     string
	Project string // tenant / namespace
	Name    string

	Harness string
	Model   string // model-agnostic id, e.g. "azure-openai/gpt-x", "anthropic/..."

	Exec         ExecState    // execution/turn axis (the event-log axis)
	ComputeState ComputeState // incarnation axis
	LastSeq      int64        // event-log cursor = the resume/replay point

	ParentUID string // set iff this session was forked
	ForkSeq   int64  // parent event seq forked at

	Identity IdentityRef
	Compute  *ComputeRef // current incarnation; nil when SUSPENDED/TERMINATED
	Origin   *Origin     // neutral external context; filled by a producer adapter

	Labels      map[string]string
	Annotations map[string]string // free-form adapter metadata (K8s-style)
}

Session is the durable unit: a conversation (event log) plus zero-or-one live compute incarnation. Unifying the two into one resource is what makes fork, provenance, and identity first-class.

type SessionSpec

type SessionSpec struct {
	SessionUID string
	Image      string
	Harness    string
	Identity   IdentityRef
	// StartedTurns counts the turns the session's journal records as started (an EXECUTION_START) on
	// the harness being placed, whether they completed, failed or were interrupted: any of them may
	// have changed that harness's in-memory state. For a forked child it counts the turns of the copied
	// prefix that ran on this harness. A turn another harness ran (an ExecRequest.harness override) is
	// not counted, since it left no state in this harness's compute; a turn the host cannot attribute
	// (no recorded harness name, or a name it does not serve) is.
	//
	// A backend uses it to refuse creating fresh compute for a REQUIRES_MEMORY_SNAPSHOT session that
	// already has state only its old compute held (ErrMemoryStateLost). It is a function rather than a
	// number so that the backend counts only after it has seen the compute is missing: a turn is
	// journaled before it runs, so every turn that ran on the lost compute is then visible, including
	// one another host sharing the journal recorded while this call was being placed. A backend that
	// does not need it does not call it. Nil declares a session with no started turns on this harness.
	StartedTurns func() (int, error)
	// RecordedCheckpoint reads the checkpoint the session's journal last recorded for this session:
	// the SnapshotRef of its latest SUSPEND whose Local names the session, or a zero SnapshotRef
	// (ExternalURI "") when there is none, as for a session never suspended or a fork child before
	// its first Suspend (a parent's SUSPEND in a child's copied prefix is not the child's).
	//
	// A backend whose compute can hold a snapshot the journal never recorded (substrate: a capture a
	// memory-tier Snapshot refused stays on the actor) compares it with the snapshot the existing
	// compute holds before attaching to or resuming it, and refuses another with
	// ErrMemoryStateLost. Like StartedTurns it is a function, so the backend reads the journal only
	// after it has read the compute, and sees a SUSPEND another host recorded in between. A backend
	// that does not need it does not call it. Nil declares no recorded checkpoint.
	RecordedCheckpoint func() (SnapshotRef, error)
}

SessionSpec is what a Runtime needs to create an incarnation.

type SnapshotKind

type SnapshotKind string

SnapshotKind selects local (warm/pause) vs external (cold/suspend) storage.

const (
	// SnapshotLocal keeps the captured state warm and node-resident.
	SnapshotLocal SnapshotKind = "LOCAL"
	// SnapshotExternal transitions to cold, releasing dedicated compute while retaining restore state.
	SnapshotExternal SnapshotKind = "EXTERNAL"
)

type SnapshotRef

type SnapshotRef struct {
	Local       string // node/handle-local ref, or (filesystem-only) the session handle to replay
	ExternalURI string // external blob (cold/suspend)
	Memory      bool   // RAM/process captured? kata/clh: true, pod: false
	Sealed      bool   // encrypted + attested (confidential)
}

SnapshotRef points at a captured incarnation state. This Go SPI type is the canonical, WIRED representation: Runtime backends produce/consume it, and the durable log carries it inline on the SUSPEND Lifecycle event (api.Lifecycle.Snapshot -> proto Lifecycle.snapshot_* fields). The proto message agentsessions.v1.SnapshotRef (session.proto, used by ComputeRef) is a SEPARATE, not-yet- wired session-status shape — see its TODO. Unlike that oneof, this holds both Local and ExternalURI (a substrate ref sets both).

type Start

type Start struct {
	// ExecutionID identifies this Run on the wire. Modern runs share it with journal events;
	// legacy runs use a session-scoped legacy- compatibility token that is never journaled.
	ExecutionID string
	// SessionUID carries the ControllerFrame session envelope for tool/approval correlation.
	// Model-only callers that do not use that envelope may leave it empty.
	// Model is the host-resolved default for a policy-enabled execution. Empty retains the
	// harness's existing default. Replay/resume restore the recorded value, not today's policy.
	Model         string    `json:",omitempty"`
	SessionUID    string    `json:",omitempty"`
	Config        []byte    // opaque per-execution config; journaled verbatim and restored on replay/resume
	History       []Event   // every event before this execution's start, also after a memory restore
	Inputs        []Message // invocation inputs; originals are restored on controller replay/resume
	Identity      IdentityContext
	ResumeFromSeq int64 // opaque harness cursor, journaled with Config; distinct from the append CAS cursor
}

Start is the per-execution invocation the host sends to the harness.

type TextPart

type TextPart struct{ Text string }

TextPart is a text content block.

type TokenMinter

type TokenMinter func(ctx context.Context, audience []string) (string, error)

TokenMinter returns a scoped token for a downstream audience.

type ToolCall

type ToolCall struct {
	ID             string
	Tool           string // tool name / MCP method
	Args           map[string]any
	Mediation      Mediation
	IdempotencyKey string // dedups a retried side-effecting call tool-side (§3/I3)
}

ToolCall is a tool invocation. Its shape aligns with an MCP tool call (name + structured arguments) so MCP tools map onto it directly.

type ToolChoice

type ToolChoice struct {
	Mode ToolChoiceMode
	Name string
}

ToolChoice constrains whether and which tool the model calls. An empty Mode is the provider default. Name forces one specific tool and is meaningful only with ToolChoiceRequired.

type ToolChoiceMode

type ToolChoiceMode string

ToolChoiceMode constrains whether the model calls a tool.

const (
	// ToolChoiceAuto: the model decides whether to call a tool.
	ToolChoiceAuto ToolChoiceMode = "AUTO"
	// ToolChoiceNone: the model must not call a tool.
	ToolChoiceNone ToolChoiceMode = "NONE"
	// ToolChoiceRequired: the model must call at least one tool.
	ToolChoiceRequired ToolChoiceMode = "REQUIRED"
)

type ToolDefinition

type ToolDefinition struct {
	Name        string
	Description string
	InputSchema map[string]any // JSON Schema object; JSON-shaped values only (see package wire)
}

ToolDefinition is a tool offered to a model on one call, aligned with an MCP Tool. ToolSpec declares a tool and its default mediation to the host; ToolDefinition is what the model sees.

type ToolResult

type ToolResult struct {
	ID           string
	Output       map[string]any
	OutputURI    string // externalized large output (MCP resource_link); else inline Output
	OutputDigest string // content digest of OutputURI target (hash-chain covers externalized bytes)
	IsError      bool
	Error        string
	// Content is the model-facing result (MCP CallToolResult.content). A harness records on the
	// TOOL_RESULT event the same ToolResult it feeds back as a tool_result part, so history rebuilt
	// from the log can give the model what it saw live.
	Content []Part `json:",omitempty"`
	// Additive durable receipt fields are omitted at zero to preserve old model-input hashes.
	Code                ToolResultCode `json:",omitempty"`
	ApprovalRequestSeq  int64          `json:",omitempty"`
	ApprovalDecisionSeq int64          `json:",omitempty"`
	// Approval carries a host decision to a direct sink caller. It is transient: neither Go JSON
	// nor wire conversion includes it in a receipt or model history. The durable decision is a
	// separate APPROVAL_RESULT event; the receipt binds it by sequence above.
	Approval *ApprovalResult `json:"-"`
}

ToolResult is the outcome of a ToolCall.

type ToolResultCode

type ToolResultCode int32

ToolResultCode is the machine-readable receipt status, matching common.proto ToolResult.Code. Zero preserves legacy receipts and also denotes a successful result when IsError is false.

const (
	ToolResultCodeUnspecified    ToolResultCode = 0
	ToolResultCodeApprovalDenied ToolResultCode = 1
	ToolResultCodeExecutorError  ToolResultCode = 2
)

type ToolSpec

type ToolSpec struct {
	Name        string
	Description string
	Mediation   Mediation
}

ToolSpec declares a tool the harness can call and its default mediation.

type Usage

type Usage struct {
	Model           string
	InputTokens     int64
	OutputTokens    int64
	ReasoningTokens int64
}

Usage is per-model-call token/cost accounting.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL