agent

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jul 23, 2026 License: Apache-2.0 Imports: 19 Imported by: 0

Documentation

Overview

Package agent implements the durable, task-oriented HumanAgent surface.

Unlike the response-oriented completion gateway, an Agent Task survives individual transports and may alternate between working and input_required multiple times. Context is display/conversation grouping only; Workspace is the independent correctness scope used by Artifact publication and receipt CAS operations.

Index

Constants

View Source
const (
	// WorkerTransportContractID names the authenticated Agent worker transport
	// contract. It describes delivery semantics, not a particular wire protocol.
	WorkerTransportContractID framework.ContractID = "human.agent.worker.transport"
	// WorkerTransportContractMajor includes exact redelivery, commit-before-ACK,
	// terminal NACK, and explicit connection-lifetime semantics.
	WorkerTransportContractMajor uint16 = 1
)
View Source
const MaxPageSize = 100

MaxPageSize is the hard item limit for every Agent list operation. A zero request limit selects this value; larger or negative limits are rejected.

View Source
const StoreContractID framework.ContractID = "human.agent.store"

StoreContractID names the semantic contract implemented by an Agent Store. It is deliberately independent of any physical schema, database product, or serialization format.

View Source
const StoreContractMajor uint16 = 2

StoreContractMajor changes when an implementation must change its base transaction, query, or record semantics to remain correct. Minor revisions may add behavior without weakening the major contract.

Variables

View Source
var (
	// ErrStoreContractMismatch aliases the framework-wide construction error for
	// callers that classify failures at the Agent Store boundary.
	ErrStoreContractMismatch = framework.ErrContractMismatch
	// ErrStoreDescription means a Store returned missing, malformed, or unsafe
	// implementation metadata. Description metadata must never contain a DSN,
	// credential, or another secret.
	ErrStoreDescription = errors.New("invalid agent store description")
	// ErrStoreRecordNotFound is the storage-level absence sentinel. Agent maps
	// this to the appropriate domain error for the record being loaded.
	ErrStoreRecordNotFound = errors.New("agent store record not found")
	// ErrStoreConflict reports a uniqueness or immutable-record collision. A
	// compare-and-swap miss is reported by the mutation's boolean result instead.
	ErrStoreConflict = errors.New("agent store constraint conflict")
	// ErrStoreCommitUnknown is the only valid result when a Store cannot prove
	// whether an Update committed. The caller must retry the exact Agent command;
	// its command receipt resolves the ambiguity without repeating a committed
	// transition.
	ErrStoreCommitUnknown = errors.New("agent store commit outcome is unknown")
	// ErrStoreClosed means the resource behind a Store no longer admits View or
	// Update calls, or a callback-scoped StoreView/StoreTx was used after its
	// callback returned. Store itself has no lifecycle method; framework.Resource
	// owns release explicitly.
	ErrStoreClosed = errors.New("agent store is closed")
	// ErrStoreRecordTooLarge means a bounded read refused to materialize a record.
	ErrStoreRecordTooLarge = errors.New("agent store record exceeds read budget")
)
View Source
var (
	// ErrWorkerTransportContractMismatch aliases the framework-wide constructor
	// error so callers can classify all incompatible adapters consistently.
	ErrWorkerTransportContractMismatch = framework.ErrContractMismatch
	ErrWorkerTransportDescription      = errors.New("invalid Agent worker transport description")
	ErrWorkerPrincipal                 = errors.New("invalid authenticated Agent worker principal")
	ErrWorkerDelivery                  = errors.New("invalid Agent worker delivery")

	// Runtime errors below are deliberately transport-neutral. Concrete adapters
	// may wrap them in WorkerConnectionError or WorkerDeliveryError.
	ErrWorkerTransportClosed       = errors.New("Agent worker transport is closed")
	ErrWorkerConnectionClosed      = errors.New("Agent worker connection is closed")
	ErrWorkerConnectionConflict    = errors.New("Agent worker connection conflicts with an active session")
	ErrWorkerDeliveryNotFound      = errors.New("Agent worker delivery is not known to this connection")
	ErrWorkerDeliveryConflict      = errors.New("Agent worker delivery identity was reused with different input")
	ErrWorkerDeliveryIndeterminate = errors.New("Agent worker delivery commit outcome is indeterminate")
)
View Source
var (
	ErrInvalidArgument     = errors.New("invalid agent argument")
	ErrNotFound            = errors.New("agent task not found")
	ErrIdempotencyConflict = errors.New("agent command id reused with different input")
	ErrRevisionConflict    = errors.New("agent task revision conflict")
	ErrInvalidTransition   = errors.New("invalid agent task transition")
	ErrTerminalTask        = errors.New("agent task is terminal")
	ErrTaskConflict        = errors.New("agent task already exists")
	ErrMessageConflict     = errors.New("agent message id is already in use")
	ErrSubmissionConflict  = errors.New("agent submission id is already in use")
	ErrArtifactNotFound    = errors.New("agent artifact not found")
	ErrArtifactConflict    = errors.New("agent artifact id or task is already bound")
	ErrArtifactState       = errors.New("invalid agent artifact state")
	ErrWorkspaceConflict   = errors.New("agent workspace confirmed revision conflict")
	ErrWorkspaceNotFound   = errors.New("agent workspace head not found")
	ErrReceiptNotFound     = errors.New("agent apply receipt not found")
	ErrReceiptConflict     = errors.New("agent apply receipt is already decided differently")
	ErrLeaseNotFound       = errors.New("agent task lease not found")
	ErrLeaseUnavailable    = errors.New("agent task is already leased")
	ErrStaleLease          = errors.New("agent task lease is stale")
	ErrLeaseFenceExhausted = errors.New("agent task lease fence exhausted")
	ErrCorruptStore        = errors.New("corrupt agent store")
	ErrProtectionDowngrade = errors.New("agent protected record was replaced by plaintext")
	ErrClosed              = errors.New("agent is closed")
)
View Source
var ErrWorkerEndpointConfig = errors.New("invalid Agent worker endpoint configuration")

Functions

func StoreRequirements

func StoreRequirements() framework.Requirements

StoreRequirements returns the immutable base contract required by the Agent core. Atomicity, strict serializability, durable command receipts, lease fencing, snapshot reads, ordering, and byte ownership are all mandatory major-contract semantics, not optional features.

func WorkerTransportRequirements

func WorkerTransportRequirements() framework.Requirements

WorkerTransportRequirements returns the immutable contract required by the HumanAgent composition root.

Types

type AcquireLeaseCommand

type AcquireLeaseCommand struct {
	ID     CommandID `json:"id"`
	Task   TaskRef   `json:"task"`
	Worker WorkerID  `json:"worker"`
}

type Agent

type Agent struct {
	// contains filtered or unexported fields
}

Agent owns the durable HumanAgent domain store. It does not own an HTTP listener or worker transport; those are adapters over this lifecycle.

func New

func New(ctx context.Context, config Config) (*Agent, error)

New constructs an Agent from Config. It is equivalent to Open and exists so custom Store compositions read naturally alongside human.NewAgent.

func Open

func Open(ctx context.Context, config Config) (*Agent, error)

Open initializes or recovers a durable task-oriented Agent. ctx controls only the open operation; after Open returns, method contexts and Close own the Agent lifetime.

func (*Agent) AcceptTask

func (agent *Agent) AcceptTask(ctx context.Context, command WorkerTaskCommand) (Task, error)

func (*Agent) AcquireLease

func (agent *Agent) AcquireLease(ctx context.Context, command AcquireLeaseCommand) (LeaseAssignment, error)

AcquireLease durably grants one unleased, non-terminal Task to a worker. The returned assignment is not observable until the grant, immutable grant history, and command receipt have committed together.

func (*Agent) CancelTask

func (agent *Agent) CancelTask(ctx context.Context, command TaskCommand) (Task, error)

func (*Agent) ClaimLease

func (agent *Agent) ClaimLease(ctx context.Context, command ClaimLeaseCommand) (LeaseAssignment, error)

ClaimLease atomically selects and grants the oldest claimable Task within an authority. Exact retries observe the originally committed assignment even after that Task advances, terminates, or its lease is fenced.

func (*Agent) Close

func (agent *Agent) Close() error

Close is the compatibility form of Shutdown for io.Closer users.

func (*Agent) CompleteTask

func (agent *Agent) CompleteTask(ctx context.Context, command CompleteTaskCommand) (Task, error)

func (*Agent) CreateTask

func (agent *Agent) CreateTask(ctx context.Context, command CreateTaskCommand) (Task, error)

func (*Agent) Done

func (agent *Agent) Done() <-chan struct{}

Done closes after Shutdown has drained calls and released owned resources.

func (*Agent) Err

func (agent *Agent) Err() error

Err returns the terminal resource-release error after Done closes. Before then it returns nil.

func (*Agent) FailTask

func (agent *Agent) FailTask(ctx context.Context, command WorkerTaskCommand) (Task, error)

func (*Agent) FenceLease

func (agent *Agent) FenceLease(ctx context.Context, command FenceLeaseCommand) error

FenceLease retires exactly one current lease generation. It never rewinds the durable fence; a later acquisition therefore cannot authorize an event produced under this grant, even when the same worker reconnects.

func (*Agent) FreezeArtifact

func (agent *Agent) FreezeArtifact(ctx context.Context, command FreezeArtifactCommand) (FreezeArtifactResult, error)

FreezeArtifact records one immutable declarative workspace payload. The first Artifact observed for a Workspace initializes its confirmed head from the trusted caller adapter's ExpectedBaseRevision; later freezes must match that durable head exactly.

func (*Agent) GetApplyReceipt

func (agent *Agent) GetApplyReceipt(ctx context.Context, ref ArtifactRef) (ApplyReceipt, error)

func (*Agent) GetArtifact

func (agent *Agent) GetArtifact(ctx context.Context, ref ArtifactRef) (ArtifactContent, error)

func (*Agent) GetLease

func (agent *Agent) GetLease(ctx context.Context, ref TaskRef) (LeaseAssignment, error)

GetLease returns the current committed assignment for a Task. An unleased Task and a retired generation both return ErrLeaseNotFound.

func (*Agent) GetMessage

func (agent *Agent) GetMessage(ctx context.Context, authority AuthorityID, id MessageID) (Message, error)

GetMessage resolves a globally unique message inside one authenticated Authority. It is primarily useful to recognize an exact transport retry after the Task revision has already advanced.

func (*Agent) GetTask

func (agent *Agent) GetTask(ctx context.Context, ref TaskRef) (Task, error)

func (*Agent) GetWorkspaceHead

func (agent *Agent) GetWorkspaceHead(ctx context.Context, ref WorkspaceRef) (WorkspaceHead, error)

func (*Agent) ListAuthorityTasks

func (agent *Agent) ListAuthorityTasks(ctx context.Context, authority AuthorityID, request TaskQuery) (TaskQueryPage, error)

ListAuthorityTasks returns a live authority-wide view ordered by UpdatedAt descending. It is intended for task transports such as A2A, whose public task identifier omits Workspace and whose list operation spans Contexts.

func (*Agent) ListLeases

func (agent *Agent) ListLeases(
	ctx context.Context,
	authority AuthorityID,
	worker WorkerID,
	request LeasePageRequest,
) (LeasePage, error)

ListLeases returns current assignments for one authenticated worker. This is the restart recovery scan: dispatchers must republish these exact Task/Fence pairs instead of acquiring replacement generations.

func (*Agent) ListMessages

func (agent *Agent) ListMessages(ctx context.Context, ref TaskRef, request PageRequest) (MessagePage, error)

func (*Agent) ListTasks

func (agent *Agent) ListTasks(ctx context.Context, contextRef ContextRef, request TaskPageRequest) (TaskPage, error)

func (*Agent) ReadEvents

func (agent *Agent) ReadEvents(ctx context.Context, ref TaskRef, request PageRequest) (EventPage, error)

func (*Agent) RecordApplyReceipt

func (agent *Agent) RecordApplyReceipt(ctx context.Context, command RecordApplyReceiptCommand) (ApplyReceipt, error)

RecordApplyReceipt records the caller-side durable decision. It never invokes filesystem code. Success advances the confirmed Workspace head only when the exact frozen base still matches in the same Store transaction.

func (*Agent) RejectTask

func (agent *Agent) RejectTask(ctx context.Context, command WorkerTaskCommand) (Task, error)

func (*Agent) ReplyTask

func (agent *Agent) ReplyTask(ctx context.Context, command MessageCommand) (Task, error)

func (*Agent) RequestInput

func (agent *Agent) RequestInput(ctx context.Context, command WorkerMessageCommand) (Task, error)

func (*Agent) ResolveTask

func (agent *Agent) ResolveTask(ctx context.Context, authority AuthorityID, id TaskID) (TaskRef, error)

ResolveTask maps an authority-scoped public Task ID to the internal Workspace-qualified correctness key. Task IDs are unique only inside the authenticated Authority; callers must never use a tenant or wire-provided Workspace as a substitute for this lookup.

func (*Agent) Shutdown

func (agent *Agent) Shutdown(ctx context.Context) error

Shutdown stops admission, waits for already admitted method calls, then releases explicitly owned dependencies in reverse construction order: Protector, then Store. Borrowed dependencies are never closed. ctx bounds only this caller's wait; once initiated, draining and cleanup continue in the background and Done closes after both bounded release attempts finish.

func (*Agent) SnapshotTask

func (agent *Agent) SnapshotTask(ctx context.Context, ref TaskRef) (TaskSnapshot, error)

SnapshotTask returns a Task and the exact event cursor from one Store read snapshot. A subscriber can emit this snapshot, then call ReadEvents with the returned cursor without a snapshot-to-stream gap.

type AgentWorkerEndpoint

type AgentWorkerEndpoint struct {
	// contains filtered or unexported fields
}

AgentWorkerEndpoint is the official transport-neutral WorkerEndpoint. It borrows Agent: neither the endpoint nor any connection shuts the Agent down. One live session is allowed per authenticated authority/worker pair. A second session is rejected with ErrWorkerConnectionConflict instead of silently superseding the first and causing a reconnect fight.

func NewWorkerEndpoint

func NewWorkerEndpoint(
	ctx context.Context,
	service *Agent,
	config WorkerEndpointConfig,
) (*AgentWorkerEndpoint, error)

NewWorkerEndpoint validates and borrows service. ctx bounds construction only; successful connections own independent Runtime lifecycles.

func (*AgentWorkerEndpoint) OpenWorker

func (endpoint *AgentWorkerEndpoint) OpenWorker(
	ctx context.Context,
	principal AuthenticatedWorker,
) (WorkerConnection, error)

type ApplyReceipt

type ApplyReceipt struct {
	ID               ApplyReceiptID          `json:"id"`
	Artifact         ArtifactRef             `json:"artifact"`
	ArtifactDigest   workspace.Digest        `json:"artifact_digest"`
	BaseRevision     workspace.Revision      `json:"base_revision"`
	ResultRevision   workspace.Revision      `json:"result_revision"`
	Decision         workspace.ApplyDecision `json:"decision"`
	ObservedRevision workspace.Revision      `json:"observed_revision,omitempty"`
	Code             string                  `json:"code,omitempty"`
	Message          string                  `json:"message,omitempty"`
	RecordedAt       time.Time               `json:"recorded_at"`
}

type ApplyReceiptID

type ApplyReceiptID string

type Artifact

type Artifact struct {
	Ref            ArtifactRef        `json:"ref"`
	Task           TaskRef            `json:"task"`
	State          ArtifactState      `json:"state"`
	BaseRevision   workspace.Revision `json:"base_revision"`
	ResultRevision workspace.Revision `json:"result_revision"`
	Digest         workspace.Digest   `json:"digest"`
	PayloadDigest  workspace.Digest   `json:"payload_digest"`
	PayloadSize    int64              `json:"payload_size"`
	MediaType      string             `json:"media_type"`
	FrozenAt       time.Time          `json:"frozen_at"`
	PublishedAt    *time.Time         `json:"published_at,omitempty"`
	DiscardedAt    *time.Time         `json:"discarded_at,omitempty"`
}

Artifact is immutable workspace content plus its publication state. Payload bytes are returned separately so ordinary Task listing remains bounded.

type ArtifactContent

type ArtifactContent struct {
	Artifact Artifact          `json:"artifact"`
	Payload  workspace.Payload `json:"payload"`
}

type ArtifactID

type ArtifactID string

type ArtifactRef

type ArtifactRef struct {
	Workspace WorkspaceRef `json:"workspace"`
	ID        ArtifactID   `json:"id"`
}

type ArtifactState

type ArtifactState string
const (
	ArtifactFrozen    ArtifactState = "frozen"
	ArtifactPublished ArtifactState = "published"
	ArtifactDiscarded ArtifactState = "discarded"
)

type AuthenticatedWorker

type AuthenticatedWorker struct {
	Authority AuthorityID     `json:"-"`
	Worker    WorkerID        `json:"-"`
	Session   WorkerSessionID `json:"-"`
}

AuthenticatedWorker is constructed by a transport after authentication. No inbound WorkerEventDelivery contains WorkerID; WorkerEndpoint binds every event to this principal when it constructs the durable LeaseGrant.

func (AuthenticatedWorker) Validate

func (principal AuthenticatedWorker) Validate() error

type Author

type Author string
const (
	AuthorCaller Author = "caller"
	AuthorAgent  Author = "agent"
)

type AuthorityID

type AuthorityID string

type ClaimLeaseCommand

type ClaimLeaseCommand struct {
	ID        CommandID   `json:"id"`
	Authority AuthorityID `json:"authority"`
	Worker    WorkerID    `json:"worker"`
}

ClaimLeaseCommand asks the durable dispatcher to select the oldest claimable Task within one authenticated authority. Authority and Worker must come from the authenticated transport principal, never an untrusted payload.

type CommandID

type CommandID string

type CommandMeta

type CommandMeta struct {
	ID               CommandID `json:"id"`
	ExpectedRevision uint64    `json:"expected_revision"`
}

CommandMeta supplies durable idempotency and optimistic concurrency. An exact retry of a committed command returns its original result snapshot even if the Task has advanced since then. Once committed, reusing ID with different input fails. A command rejected before commit does not reserve ID.

type CompleteTaskCommand

type CompleteTaskCommand struct {
	Meta       WorkerCommandMeta `json:"meta"`
	Task       TaskRef           `json:"task"`
	Submission SubmissionID      `json:"submission"`
	Message    MessageInput      `json:"message"`
	Artifact   *ArtifactRef      `json:"artifact,omitempty"`
}

type Config

type Config struct {
	// Store injects a complete Agent persistence consistency domain. Borrowed
	// resources remain caller-owned; owned resources are released by Shutdown.
	// It is not a distributed live-owner lease; see agent.Store's contract.
	Store framework.Resource[Store]
	// Protector optionally seals static message and Artifact payloads before they
	// enter Store callbacks. Borrowed Protectors remain caller-owned; owned
	// Protectors are released before the Store during Shutdown.
	Protector protect.Resource
	// AllowPlaintextReads is an explicit migration policy. With a configured
	// Protector the default rejects plain StoredValues, preventing a database
	// attacker from downgrading authenticated ciphertext to plaintext. Enable it
	// only while reading records written by a deliberately unprotected runtime.
	AllowPlaintextReads bool
	// MaxArtifactBytes limits newly frozen payloads. Reads continue to accept
	// already committed payloads up to the schema hard limit of 64 MiB.
	MaxArtifactBytes int64
	// Clock supplies core-owned timestamps. It must be safe for concurrent use
	// and return UTC-normalizable wall-clock values. Nil uses time.Now.
	Clock func() time.Time
	// ReleaseTimeout bounds each owned Protector and Store release independently.
	// Shutdown's context only bounds the caller's wait; cleanup continues after a
	// caller timeout and a broken adapter cannot prevent the next dependency's
	// release attempt.
	ReleaseTimeout time.Duration
}

Config controls one durable HumanAgent domain instance. Store is required and is the persistence extension point. Physical drivers such as agent/sqlite are composed by the caller and injected as borrowed or owned resources.

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns Agent defaults without selecting a Store resource.

type ContextID

type ContextID string

type ContextRef

type ContextRef struct {
	Authority AuthorityID `json:"authority"`
	ID        ContextID   `json:"id"`
}

ContextRef is an authority-qualified display/conversation scope. Two Tasks in one Context are allowed to be active concurrently.

type CreateTaskCommand

type CreateTaskCommand struct {
	Meta    CommandMeta  `json:"meta"`
	Task    TaskRef      `json:"task"`
	Context ContextRef   `json:"context"`
	Message MessageInput `json:"message"`
}

type Event

type Event struct {
	Task       TaskRef      `json:"task"`
	Sequence   uint64       `json:"sequence"`
	Type       EventType    `json:"type"`
	State      TaskState    `json:"state"`
	Revision   uint64       `json:"revision"`
	Message    MessageID    `json:"message,omitempty"`
	Submission SubmissionID `json:"submission,omitempty"`
	Artifact   ArtifactID   `json:"artifact,omitempty"`
	OccurredAt time.Time    `json:"occurred_at"`
}

Event is an append-only status stream. Status/progress belongs here rather than in Message history, whose caller/agent turn alternation stays strict.

type EventPage

type EventPage struct {
	Items   []Event `json:"items"`
	Next    uint64  `json:"next,omitempty"`
	HasMore bool    `json:"has_more"`
}

type EventType

type EventType string
const (
	EventTaskSubmitted  EventType = "task_submitted"
	EventTaskAccepted   EventType = "task_accepted"
	EventTaskRejected   EventType = "task_rejected"
	EventInputRequired  EventType = "input_required"
	EventCallerReplied  EventType = "caller_replied"
	EventTaskCanceled   EventType = "task_canceled"
	EventTaskFailed     EventType = "task_failed"
	EventTaskCompleted  EventType = "task_completed"
	EventArtifactFrozen EventType = "artifact_frozen"
)

type FenceLeaseCommand

type FenceLeaseCommand struct {
	ID    CommandID  `json:"id"`
	Grant LeaseGrant `json:"grant"`
}

type FreezeArtifactCommand

type FreezeArtifactCommand struct {
	Meta                 WorkerCommandMeta  `json:"meta"`
	Task                 TaskRef            `json:"task"`
	Artifact             ArtifactID         `json:"artifact"`
	ExpectedBaseRevision workspace.Revision `json:"expected_base_revision"`
	Payload              workspace.Payload  `json:"payload"`
}

type FreezeArtifactResult

type FreezeArtifactResult struct {
	Task     Task     `json:"task"`
	Artifact Artifact `json:"artifact"`
}

type LeaseAssignment

type LeaseAssignment struct {
	Grant     LeaseGrant `json:"grant"`
	Task      Task       `json:"task"`
	GrantedAt time.Time  `json:"granted_at"`
}

LeaseAssignment is returned only after both the current grant and its immutable history row have committed. Dispatchers may therefore publish this value directly and can recover the same assignment after a process restart.

type LeaseFence

type LeaseFence uint64

type LeaseGrant

type LeaseGrant struct {
	Task   TaskRef    `json:"task"`
	Worker WorkerID   `json:"worker"`
	Fence  LeaseFence `json:"fence"`
}

LeaseGrant is the durable, fenced authority for one worker to mutate a Task. It deliberately has no wall-clock expiry: a dispatcher fences a disconnected worker explicitly, then acquires the next monotonically larger generation. Remote adapters must construct Worker from the authenticated principal, never from an untrusted request body.

type LeasePage

type LeasePage struct {
	Items   []LeaseAssignment `json:"items"`
	Next    *LeasePageCursor  `json:"next,omitempty"`
	HasMore bool              `json:"has_more"`
}

type LeasePageCursor

type LeasePageCursor struct {
	GrantedAt time.Time   `json:"granted_at"`
	Workspace WorkspaceID `json:"workspace"`
	Task      TaskID      `json:"task"`
	Fence     LeaseFence  `json:"fence"`
}

type LeasePageRequest

type LeasePageRequest struct {
	After *LeasePageCursor `json:"after,omitempty"`
	Limit int              `json:"limit,omitempty"`
}

type Message

type Message struct {
	ID        MessageID `json:"id"`
	Task      TaskRef   `json:"task"`
	Sequence  uint64    `json:"sequence"`
	Author    Author    `json:"author"`
	Parts     []Part    `json:"parts"`
	CreatedAt time.Time `json:"created_at"`
}

type MessageCommand

type MessageCommand struct {
	Meta    CommandMeta  `json:"meta"`
	Task    TaskRef      `json:"task"`
	Message MessageInput `json:"message"`
}

type MessageID

type MessageID string

type MessageInput

type MessageInput struct {
	ID    MessageID `json:"id"`
	Parts []Part    `json:"parts"`
}

type MessagePage

type MessagePage struct {
	Items   []Message `json:"items"`
	Next    uint64    `json:"next,omitempty"`
	HasMore bool      `json:"has_more"`
}

type PageRequest

type PageRequest struct {
	After uint64 `json:"after,omitempty"`
	Limit int    `json:"limit,omitempty"`
}

PageRequest pages append-only Message and Event streams by sequence. Next is always the last returned sequence, or After when the page is empty, so a caller can use it as the next tail-poll cursor even when HasMore is false.

type Part

type Part struct {
	MediaType string `json:"media_type"`
	Data      []byte `json:"data"`
}

Part is an ordered, transport-neutral content part. A2A, JSON, or another wire adapter must translate at the boundary instead of leaking its DTOs into this domain package.

type RecordApplyReceiptCommand

type RecordApplyReceiptCommand struct {
	CommandID        CommandID               `json:"command_id"`
	Receipt          ApplyReceiptID          `json:"receipt"`
	Artifact         ArtifactRef             `json:"artifact"`
	ArtifactDigest   workspace.Digest        `json:"artifact_digest"`
	BaseRevision     workspace.Revision      `json:"base_revision"`
	ResultRevision   workspace.Revision      `json:"result_revision"`
	Decision         workspace.ApplyDecision `json:"decision"`
	ObservedRevision workspace.Revision      `json:"observed_revision,omitempty"`
	Code             string                  `json:"code,omitempty"`
	Message          string                  `json:"message,omitempty"`
}

type RevisionConflictError

type RevisionConflictError struct {
	Expected uint64
	Actual   uint64
}

RevisionConflictError reports the exact failed CAS values.

func (*RevisionConflictError) Error

func (failure *RevisionConflictError) Error() string

func (*RevisionConflictError) Unwrap

func (failure *RevisionConflictError) Unwrap() error

type Store

type Store interface {
	// Description returns static, non-secret implementation metadata. It must be
	// safe before and during resource release and must not perform network or
	// storage I/O.
	Description() StoreDescription
	// View executes one callback against a stable, read-only snapshot. On a valid,
	// live invocation it calls the callback exactly once and returns an error
	// matching the callback's result. The context bounds snapshot acquisition and
	// every StoreView primitive.
	View(context.Context, func(StoreView) error) error
	// Update executes one callback in one atomic, strictly serializable transaction
	// with read-your-writes. On a valid, live invocation it calls the callback
	// exactly once. A callback error rolls back and remains matchable in the return;
	// a nil callback result enters the commit-ambiguity contract described above.
	// The context bounds transaction acquisition, every StoreTx primitive, and
	// commit, but cancellation never permits a partial commit.
	Update(context.Context, func(StoreTx) error) error
}

Store is the complete persistence consistency boundary for HumanAgent. Tasks, command receipts, messages, events, lease history, Artifacts, submissions, apply receipts, and Workspace heads deliberately share this one Store. Splitting them across independently committed implementations would invalidate the Agent state machine.

A non-nil context and callback are required. A nil argument is rejected with ErrInvalidArgument without invoking the callback; a context already done is returned without invoking it. Once admitted, View and Update call the callback exactly once. Implementations must never retry a callback: Agent callbacks can derive timestamps and return precise conflict information from the snapshot they observed. The enclosing context supplies every primitive's cancellation and deadline; an implementation must not replace it with a background context.

View supplies one stable read snapshot. Update supplies one atomic, strictly serializable read/write transaction with read-your-writes. A callback and its StoreView or StoreTx are valid only until the enclosing method returns and must not be retained or used concurrently. A primitive used outside that lifetime returns an error matching ErrStoreClosed and performs no work.

If an Update callback returns an error, none of its writes may become visible. View and Update return an error matching the callback error; a rollback failure may be joined without hiding it. If it returns nil, all writes, including the command receipt, become visible atomically or none do. A definite commit failure returns an ordinary error and guarantees no commit. A failure that may have committed must return an error matching ErrStoreCommitUnknown. An exact retry then observes either the whole command receipt and replays it, or no receipt and safely attempts the command.

Successful Update effects are durable across a process restart. View and Update must be safe for concurrent callers. Implementations own copies of all byte slices after a successful write and return caller-owned copies from all reads; mutable aliases may not cross a transaction boundary.

Store serializability is not a live-runtime lease. Unless the embedding host adds external generation/fencing coordination, exactly one active Agent may drive a Store correctness namespace. Two Agent instances can otherwise present the same durable Task to different Humans before either one commits.

Store intentionally has no Close method. Construction receives it through a framework.Resource[Store], which makes borrowed versus owned lifetime and the release callback explicit without contaminating this business port.

type StoreApplyReceiptRecord

type StoreApplyReceiptRecord struct {
	Receipt ApplyReceipt
}

StoreApplyReceiptRecord is the caller-side terminal decision for one exact published Artifact.

type StoreArtifactMutation

type StoreArtifactMutation struct {
	Ref           ArtifactRef
	Task          TaskRef
	ExpectedState ArtifactState
	NextState     ArtifactState
	PublishedAt   *time.Time
	DiscardedAt   *time.Time
}

StoreArtifactMutation changes only publication state and its associated terminal timestamp without materializing the immutable payload. Exactly one of PublishedAt or DiscardedAt is set according to NextState. Identity, payload, digests, revisions, media type, Task, and FrozenAt remain unchanged. A false result means the record is absent or ExpectedState or Task no longer matches.

type StoreArtifactRecord

type StoreArtifactRecord struct {
	Artifact       Artifact
	EncodedPayload []byte
}

StoreArtifactRecord contains immutable plaintext payload identity, its mutable publication state, and a versioned opaque StoredValue. Artifact PayloadSize and PayloadDigest always describe canonical plaintext; EncodedPayload has an independent physical size and is preserved byte-for-byte. State transitions may not change EncodedPayload or any identity field.

type StoreCommandKey

type StoreCommandKey struct {
	Authority AuthorityID
	ID        CommandID
}

StoreCommandKey is authority-qualified because command IDs are unique only inside an authenticated Authority.

type StoreCommandRecord

type StoreCommandRecord struct {
	Authority    AuthorityID
	ID           CommandID
	Kind         string
	IntentDigest StoreDigest
	ResultKind   string
	Result       []byte
	ResultDigest StoreDigest
	CreatedAt    time.Time
}

StoreCommandRecord is the durable idempotency receipt for one Agent command. Result contains the exact canonical result bytes produced by Agent; the Store does not decode or re-encode them. The key is (Authority, ID).

type StoreCommitUnknownError

type StoreCommitUnknownError struct {
	Cause error
}

StoreCommitUnknownError preserves an infrastructure cause while supporting errors.Is for both ErrStoreCommitUnknown and the cause. Cause may be nil.

func (*StoreCommitUnknownError) Error

func (failure *StoreCommitUnknownError) Error() string

func (*StoreCommitUnknownError) Unwrap

func (failure *StoreCommitUnknownError) Unwrap() []error

type StoreConflictError

type StoreConflictError struct {
	Constraint StoreConstraint
	Key        string
}

StoreConflictError reports a typed logical constraint collision and supports errors.Is(err, ErrStoreConflict).

func (*StoreConflictError) Error

func (failure *StoreConflictError) Error() string

func (*StoreConflictError) Unwrap

func (*StoreConflictError) Unwrap() error

type StoreConstraint

type StoreConstraint string

StoreConstraint identifies the logical uniqueness or immutability rule that rejected an insert. Store implementations must not expose vendor index names or parse error strings at the Agent boundary.

const (
	StoreConstraintCommandID       StoreConstraint = "command_id"
	StoreConstraintTaskKey         StoreConstraint = "task_key"
	StoreConstraintPublicTaskID    StoreConstraint = "public_task_id"
	StoreConstraintMessageID       StoreConstraint = "message_id"
	StoreConstraintMessageSequence StoreConstraint = "message_sequence"
	StoreConstraintEventSequence   StoreConstraint = "event_sequence"
	StoreConstraintLeaseFence      StoreConstraint = "lease_fence"
	StoreConstraintArtifactID      StoreConstraint = "artifact_id"
	StoreConstraintArtifactTask    StoreConstraint = "artifact_task"
	StoreConstraintSubmissionID    StoreConstraint = "submission_id"
	StoreConstraintReceiptID       StoreConstraint = "receipt_id"
)

type StoreDescription

type StoreDescription struct {
	Contract framework.Contract
	Provider string
	Version  string
}

StoreDescription identifies an implementation without exposing its backing location. Provider should identify the driver (for example, "sqlite" or a Go module path); Version is the driver's own release version. Contract describes behavior, not the driver's schema version.

Description values are suitable for diagnostics and audit metadata. They must not contain database paths, network addresses with credentials, DSNs, tokens, key identifiers, or tenant data.

func (StoreDescription) Validate

func (description StoreDescription) Validate() error

Validate checks the implementation metadata and exact semantic contract.

type StoreDigest

type StoreDigest string

StoreDigest is an opaque digest emitted and verified by the Agent core. A Store must preserve it byte-for-byte and must not recalculate it with a driver-specific serialization.

type StoreEventRecord

type StoreEventRecord struct {
	Event Event
}

StoreEventRecord is one append-only Task revision event.

type StoreEventScan

type StoreEventScan struct {
	Task  TaskRef
	After uint64
	Limit int
}

StoreEventScan selects Task events with Sequence strictly greater than After in ascending order. Limit is an item cap in 1..MaxPageSize+1 and has no zero default at this port.

type StoreLeaseGrantRecord

type StoreLeaseGrantRecord struct {
	Grant     LeaseGrant
	GrantedAt time.Time
}

StoreLeaseGrantRecord is immutable history for one monotonically increasing Task fence. Current lease state may be empty, but committed history is never deleted or rewritten.

type StoreLeaseScan

type StoreLeaseScan struct {
	Authority AuthorityID
	Worker    WorkerID
	After     *LeasePageCursor
	Limit     int
}

StoreLeaseScan selects current (not historical) leases for one authenticated worker, ordered by GrantedAt, Workspace ID, Task ID, and Fence, all ascending. After is an exclusive lexicographic cursor in that order. Limit is an item cap in 1..MaxPageSize+1 and has no zero default at this port.

type StoreLeaseState

type StoreLeaseState struct {
	Owner WorkerID
	Fence LeaseFence
}

StoreLeaseState is the mutable lease pointer embedded in a Task record. A zero Owner means unleased. Fence never decreases and identifies the latest immutable StoreLeaseGrantRecord even after that generation is fenced.

type StoreLimitError

type StoreLimitError struct {
	Record StoreRecordKind
	Limit  int64
}

StoreLimitError describes a bounded read refusal and supports errors.Is(err, ErrStoreRecordTooLarge).

func (*StoreLimitError) Error

func (failure *StoreLimitError) Error() string

func (*StoreLimitError) Unwrap

func (*StoreLimitError) Unwrap() error

type StoreMessageKey

type StoreMessageKey struct {
	Authority AuthorityID
	ID        MessageID
}

StoreMessageKey is authority-qualified because message IDs are unique only inside an authenticated Authority.

type StoreMessageRecord

type StoreMessageRecord struct {
	ID           MessageID
	Task         TaskRef
	Sequence     uint64
	Author       Author
	EncodedParts []byte
	PartsDigest  StoreDigest
	CreatedAt    time.Time
}

StoreMessageRecord keeps a versioned opaque StoredValue containing canonical encoded Parts and their plaintext digest alongside message metadata. Store implementations preserve EncodedParts byte-for-byte and never decrypt it.

type StoreMessageScan

type StoreMessageScan struct {
	Task      TaskRef
	After     uint64
	Limit     int
	ReadLimit StoreReadLimit
}

StoreMessageScan selects Task messages with Sequence strictly greater than After in ascending order. Limit is an item cap in 1..MaxPageSize+1. ReadLimit is a hard aggregate EncodedParts budget. A Store fails with ErrStoreRecordTooLarge when the first record cannot fit; after at least one record fits it returns the largest ordered contiguous prefix within the budget. Agent compares the last sequence with Task.MessageCount to derive HasMore without a driver-specific continuation flag.

type StoreNotFoundError

type StoreNotFoundError struct {
	Record StoreRecordKind
	Key    string
}

StoreNotFoundError adds a logical record kind and non-secret stable key to ErrStoreRecordNotFound. Implementations may return the sentinel directly when no safe key is available.

func (*StoreNotFoundError) Error

func (failure *StoreNotFoundError) Error() string

func (*StoreNotFoundError) Unwrap

func (*StoreNotFoundError) Unwrap() error

type StoreReadLimit

type StoreReadLimit struct {
	MaxBytes int64
}

StoreReadLimit is a hard materialization budget for one opaque record field. MaxBytes must be positive. A Store must reject a larger value before returning the blob, using an error matching ErrStoreRecordTooLarge. It must never treat a zero value as unlimited.

type StoreRecordKind

type StoreRecordKind string

StoreRecordKind identifies a logical record without exposing a table or a document collection. Values are stable diagnostics and conformance labels.

const (
	StoreRecordCommand       StoreRecordKind = "command"
	StoreRecordTask          StoreRecordKind = "task"
	StoreRecordMessage       StoreRecordKind = "message"
	StoreRecordEvent         StoreRecordKind = "event"
	StoreRecordLeaseGrant    StoreRecordKind = "lease_grant"
	StoreRecordWorkspaceHead StoreRecordKind = "workspace_head"
	StoreRecordArtifact      StoreRecordKind = "artifact"
	StoreRecordSubmission    StoreRecordKind = "submission"
	StoreRecordApplyReceipt  StoreRecordKind = "apply_receipt"
)

type StoreSubmissionRecord

type StoreSubmissionRecord struct {
	Submission Submission
}

StoreSubmissionRecord contains only durable identity, routing, and timestamp metadata. Final user content lives in its referenced protected Message and optional Artifact; Store implementations must not duplicate that payload here. It is written once, in the same transaction that publishes an optional Artifact and moves its Task to completed.

type StoreTaskAuthorityResult

type StoreTaskAuthorityResult struct {
	Records   []StoreTaskRecord
	TotalSize uint64
}

StoreTaskAuthorityResult is the raw authority query result from one View.

type StoreTaskAuthorityScan

type StoreTaskAuthorityScan struct {
	Authority        AuthorityID
	Context          ContextID
	State            TaskState
	UpdatedAtOrAfter *time.Time
	After            *TaskQueryCursor
	Limit            int
}

StoreTaskAuthorityScan selects a bounded authority-wide page ordered by UpdatedAt descending, then Workspace ID and Task ID ascending. Context and State zero values do not filter; UpdatedAtOrAfter is inclusive. After is an exclusive lexicographic cursor in the mixed direction above. Limit is the physical maximum, must be in 1..MaxPageSize+1, and has no zero default at the Store port. TotalSize counts the filtered set before applying After and must be observed in the same View snapshot as Records.

type StoreTaskCondition

type StoreTaskCondition struct {
	ExpectedRevision uint64
	ExpectedLease    *StoreLeaseState
}

StoreTaskCondition is the compare-and-swap precondition for a Task mutation. ExpectedRevision is always matched. ExpectedLease nil ignores the lease (for caller-authorized transitions); a non-nil zero value requires an unleased Task, and a non-zero value requires that exact owner/fence generation.

type StoreTaskContextScan

type StoreTaskContextScan struct {
	Context ContextRef
	After   *TaskPageCursor
	Limit   int
}

StoreTaskContextScan selects a bounded page ordered by CreatedAt ascending, then Workspace ID and Task ID ascending. After is an exclusive lexicographic cursor in that order. Limit is the physical maximum number of records returned and must be in 1..MaxPageSize+1; zero has no default meaning at the Store port. Agent normally requests one extra record to derive HasMore.

type StoreTaskMutation

type StoreTaskMutation struct {
	Ref       TaskRef
	Condition StoreTaskCondition
	Next      StoreTaskRecord
}

StoreTaskMutation replaces one existing Task aggregate when Condition still matches. Ref and Next.Task.Ref must be identical; Context and CreatedAt are immutable, and every nested Task/Workspace reference must remain in the same identity scope. ExpectedRevision must be non-zero. A false result from CompareAndSwapTask means no field was changed.

type StoreTaskRecord

type StoreTaskRecord struct {
	Task          Task
	Lease         StoreLeaseState
	ArtifactState *ArtifactState
}

StoreTaskRecord is the materialized Task aggregate plus its non-public current lease. ArtifactState is nil exactly when Task.Artifact is nil; Agent uses it to fail closed when an implementation returns a Task/Artifact state mismatch.

type StoreTx

type StoreTx interface {
	StoreView
	// InsertCommand inserts the immutable (Authority, ID) receipt. Any collision
	// returns ErrStoreConflict with StoreConstraintCommandID.
	InsertCommand(StoreCommandRecord) error
	// InsertTask inserts an initial Task. It must be unleased at fence zero and
	// have no pre-bound Artifact, ArtifactState, or Submission. Task.Ref is unique;
	// (Authority, Task ID) is also unique across Workspaces. Collisions use
	// StoreConstraintTaskKey and StoreConstraintPublicTaskID respectively.
	InsertTask(StoreTaskRecord) error
	// CompareAndSwapTask replaces an existing Task when ExpectedRevision and, when
	// non-nil, ExpectedLease match. A revision/lease miss returns (false, nil); an
	// absent Task matches ErrStoreRecordNotFound. Invalid or changed identity is an
	// error. Artifact and Submission links in Next are backed by their paired
	// immutable inserts in the same Update, rather than created by this primitive.
	CompareAndSwapTask(StoreTaskMutation) (bool, error)
	// InsertMessage inserts an immutable message. (Authority, Message ID) and
	// (TaskRef, Sequence) are unique; collisions use StoreConstraintMessageID and
	// StoreConstraintMessageSequence respectively.
	InsertMessage(StoreMessageRecord) error
	// InsertEvent inserts an immutable event keyed by (TaskRef, Sequence). A
	// collision uses StoreConstraintEventSequence.
	InsertEvent(StoreEventRecord) error
	// InsertLeaseGrant inserts immutable history keyed by (TaskRef, Fence). A
	// collision uses StoreConstraintLeaseFence. It does not itself change the
	// Task's current lease; core pairs it with CompareAndSwapTask in this Update.
	InsertLeaseGrant(StoreLeaseGrantRecord) error
	// InsertArtifact inserts one immutable payload identity. Artifact IDs are
	// authority-wide unique and a Task owns at most one Artifact; collisions use
	// StoreConstraintArtifactID and StoreConstraintArtifactTask respectively.
	InsertArtifact(StoreArtifactRecord) error
	// CompareAndSwapArtifact changes only the state and terminal timestamps when
	// the exact ArtifactRef, bound TaskRef, and ExpectedState match. Absence or a
	// Task/state miss returns (false, nil); identity-invalid input is an error.
	CompareAndSwapArtifact(StoreArtifactMutation) (bool, error)
	// InsertSubmission inserts the immutable, sole Submission for its Task. Its
	// (Authority, Submission ID) is also unique. Any collision returns
	// ErrStoreConflict with StoreConstraintSubmissionID.
	InsertSubmission(StoreSubmissionRecord) error
	// InsertWorkspaceHead is first-writer-wins for Head.Workspace. It returns true
	// only when it inserted the row. An existing row returns (false, nil), remains
	// unchanged even when its value differs, and must be loaded before deciding the
	// next action.
	InsertWorkspaceHead(StoreWorkspaceHeadRecord) (bool, error)
	// CompareAndSwapWorkspaceHead replaces an existing head only when
	// ExpectedRevision matches. An absent head or revision miss returns (false,
	// nil); a Workspace/Next identity mismatch is an error.
	CompareAndSwapWorkspaceHead(StoreWorkspaceHeadMutation) (bool, error)
	// InsertApplyReceipt inserts the immutable, sole receipt for its Artifact.
	// (Authority, Receipt ID) is also unique. Any collision returns
	// ErrStoreConflict with StoreConstraintReceiptID.
	InsertApplyReceipt(StoreApplyReceiptRecord) error
}

StoreTx extends one StoreView with typed mutation primitives. These methods do not commit independently. All successful calls become visible together only when the enclosing Store.Update commits.

Immutable inserts return an error matching ErrStoreConflict on any logical uniqueness collision, including an exact duplicate; the typed constraint named below is part of the portable contract. InsertWorkspaceHead is the sole first-writer-wins exception and reports existence with its boolean. CAS and first-writer methods return (false, nil) for the documented miss and must not partially modify a record. The Agent core, not the Store, owns state-transition policy, command digests, timestamps, replay validation, and lease authorization.

type StoreView

type StoreView interface {
	// LookupCommand loads the immutable command keyed by (Authority, ID). MaxBytes
	// applies to Result only; absence matches ErrStoreRecordNotFound.
	LookupCommand(StoreCommandKey, StoreReadLimit) (StoreCommandRecord, error)
	// LoadTask loads the aggregate whose Task.Ref exactly equals ref. It includes
	// the current lease and any Artifact/Submission links visible in this snapshot;
	// absence matches ErrStoreRecordNotFound.
	LoadTask(TaskRef) (StoreTaskRecord, error)
	// ResolveTask resolves the authority-wide public identity (authority, task ID)
	// to its unique Workspace-qualified TaskRef. It must never cross authority
	// boundaries; absence matches ErrStoreRecordNotFound.
	ResolveTask(AuthorityID, TaskID) (TaskRef, error)
	// LoadMessage loads the immutable message keyed by (Authority, Message ID). The
	// returned record ID and Task authority must match that key. MaxBytes applies
	// to EncodedParts; absence matches ErrStoreRecordNotFound.
	LoadMessage(StoreMessageKey, StoreReadLimit) (StoreMessageRecord, error)
	// LoadArtifact loads the Artifact whose Artifact.Ref exactly equals ref.
	// MaxBytes applies to EncodedPayload; absence matches ErrStoreRecordNotFound.
	LoadArtifact(ArtifactRef, StoreReadLimit) (StoreArtifactRecord, error)
	// LoadApplyReceipt loads the immutable terminal receipt keyed by its exact
	// ArtifactRef; absence matches ErrStoreRecordNotFound.
	LoadApplyReceipt(ArtifactRef) (StoreApplyReceiptRecord, error)
	// LoadWorkspaceHead loads the head whose WorkspaceRef exactly equals ref;
	// absence matches ErrStoreRecordNotFound.
	LoadWorkspaceHead(WorkspaceRef) (StoreWorkspaceHeadRecord, error)
	// LoadLeaseGrant loads immutable history for the exact (TaskRef, Fence) key;
	// absence matches ErrStoreRecordNotFound.
	LoadLeaseGrant(TaskRef, LeaseFence) (StoreLeaseGrantRecord, error)
	// LoadLatestLeaseGrant returns the record with the greatest Fence for ref, not
	// the record with the greatest wall-clock time. No history matches
	// ErrStoreRecordNotFound.
	LoadLatestLeaseGrant(TaskRef) (StoreLeaseGrantRecord, error)
	// FindClaimableTask returns the deterministic oldest unleased, non-terminal
	// Task in authority: CreatedAt, Workspace ID, then Task ID, all ascending. It
	// only selects; it does not reserve or mutate the Task. No candidate matches
	// ErrStoreRecordNotFound.
	FindClaimableTask(AuthorityID) (StoreTaskRecord, error)
	// ScanContextTasks returns only records in scan.Context, in the exact order and
	// exclusive-cursor semantics defined by StoreTaskContextScan. It returns at
	// most Limit records; zero matches are a successful empty result.
	ScanContextTasks(StoreTaskContextScan) ([]StoreTaskRecord, error)
	// ScanAuthorityTasks applies all filters and returns Records, ordering, and
	// TotalSize exactly as StoreTaskAuthorityScan specifies. Zero matches are a
	// successful result with TotalSize zero.
	ScanAuthorityTasks(StoreTaskAuthorityScan) (StoreTaskAuthorityResult, error)
	// ScanMessages returns at most Limit messages in the exact order, cursor, and
	// aggregate byte-budget semantics defined by StoreMessageScan. Zero matches are
	// a successful empty result.
	ScanMessages(StoreMessageScan) ([]StoreMessageRecord, error)
	// ScanEvents returns at most Limit events in the exact order and exclusive
	// cursor semantics defined by StoreEventScan. Zero matches are a successful
	// empty result.
	ScanEvents(StoreEventScan) ([]StoreEventRecord, error)
	// ScanLeases returns at most Limit assignments in StoreLeaseScan order. Each
	// item couples the current Task lease with the immutable grant at that same
	// Fence from this snapshot. Zero matches are a successful empty result.
	ScanLeases(StoreLeaseScan) ([]LeaseAssignment, error)
}

StoreView is a transaction-bound logical snapshot. It intentionally exposes no SQL, table, driver cursor, or transport type. Every returned record and byte slice belongs to the caller. Single-record lookup, load, resolve, and find methods report absence with an error matching ErrStoreRecordNotFound; scan methods instead return a successful empty result. Every read made through the StoreView embedded in StoreTx observes earlier writes in that Update.

type StoreWorkspaceHeadMutation

type StoreWorkspaceHeadMutation struct {
	Workspace        WorkspaceRef
	ExpectedRevision workspace.Revision
	Next             StoreWorkspaceHeadRecord
}

StoreWorkspaceHeadMutation advances a Workspace head by exact revision CAS. Workspace and Next.Head.Workspace must be identical. A false result means the head is absent or ExpectedRevision is no longer confirmed.

type StoreWorkspaceHeadRecord

type StoreWorkspaceHeadRecord struct {
	Head WorkspaceHead
}

StoreWorkspaceHeadRecord is the confirmed caller Workspace revision. A successful apply receipt advances it by compare-and-swap in the same Update.

type Submission

type Submission struct {
	ID           SubmissionID `json:"id"`
	Task         TaskRef      `json:"task"`
	FinalMessage MessageID    `json:"final_message"`
	Artifact     *ArtifactRef `json:"artifact,omitempty"`
	PublishedAt  time.Time    `json:"published_at"`
}

Submission is published atomically with its final Agent message and the Task's transition to completed. Artifact is added by the workspace delivery phase; a nil/absent Artifact is a first-class content-only result.

type SubmissionID

type SubmissionID string

type Task

type Task struct {
	Ref          TaskRef      `json:"ref"`
	Context      ContextRef   `json:"context"`
	State        TaskState    `json:"state"`
	Revision     uint64       `json:"revision"`
	MessageCount uint64       `json:"message_count"`
	EventCount   uint64       `json:"event_count"`
	Artifact     *ArtifactRef `json:"artifact,omitempty"`
	Submission   *Submission  `json:"submission,omitempty"`
	CreatedAt    time.Time    `json:"created_at"`
	UpdatedAt    time.Time    `json:"updated_at"`
}

type TaskCommand

type TaskCommand struct {
	Meta CommandMeta `json:"meta"`
	Task TaskRef     `json:"task"`
}

type TaskID

type TaskID string

type TaskPage

type TaskPage struct {
	Items   []Task          `json:"items"`
	Next    *TaskPageCursor `json:"next,omitempty"`
	HasMore bool            `json:"has_more"`
}

type TaskPageCursor

type TaskPageCursor struct {
	CreatedAt time.Time   `json:"created_at"`
	Workspace WorkspaceID `json:"workspace"`
	Task      TaskID      `json:"task"`
}

TaskPageCursor is a stable keyset cursor over a live view, not a snapshot. Context is supplied separately; the cursor cannot move a query across an authenticated authority boundary.

type TaskPageRequest

type TaskPageRequest struct {
	After *TaskPageCursor `json:"after,omitempty"`
	Limit int             `json:"limit,omitempty"`
}

type TaskQuery

type TaskQuery struct {
	Context          ContextID        `json:"context,omitempty"`
	State            TaskState        `json:"state,omitempty"`
	UpdatedAtOrAfter *time.Time       `json:"updated_at_or_after,omitempty"`
	After            *TaskQueryCursor `json:"after,omitempty"`
	Limit            int              `json:"limit,omitempty"`
}

TaskQuery filters an authenticated Authority's Tasks. Zero Context and State values mean "any". UpdatedAtOrAfter is inclusive. TotalSize in the result is evaluated in the same stable Store snapshot as the returned page.

type TaskQueryCursor

type TaskQueryCursor struct {
	UpdatedAt time.Time   `json:"updated_at"`
	Workspace WorkspaceID `json:"workspace"`
	Task      TaskID      `json:"task"`
}

TaskQueryCursor is a stable keyset cursor over an authority-wide live view. Tasks are ordered by most recently updated first, then by their stable key. Task IDs are unique inside one authenticated Authority; Workspace remains in the cursor so a corrupt store cannot silently alias two correctness scopes.

type TaskQueryPage

type TaskQueryPage struct {
	Items     []Task           `json:"items"`
	Next      *TaskQueryCursor `json:"next,omitempty"`
	HasMore   bool             `json:"has_more"`
	TotalSize uint64           `json:"total_size"`
}

type TaskRef

type TaskRef struct {
	Workspace WorkspaceRef `json:"workspace"`
	ID        TaskID       `json:"id"`
}

TaskRef is the durable Agent task key. The "agent" surface discriminator is implicit in this package and in its Store namespace; it never aliases a completion task key.

type TaskSnapshot

type TaskSnapshot struct {
	Task        Task   `json:"task"`
	EventCursor uint64 `json:"event_cursor"`
}

TaskSnapshot couples a Task with the exact append-only Event cursor observed in the same database snapshot. Reading events after EventCursor cannot miss a concurrent commit; it either appears in the subsequent page or a later poll.

type TaskState

type TaskState string
const (
	TaskSubmitted     TaskState = "submitted"
	TaskWorking       TaskState = "working"
	TaskInputRequired TaskState = "input_required"
	TaskCompleted     TaskState = "completed"
	TaskCanceled      TaskState = "canceled"
	TaskRejected      TaskState = "rejected"
	TaskFailed        TaskState = "failed"
)

func (TaskState) Terminal

func (state TaskState) Terminal() bool

type TransitionError

type TransitionError struct {
	Operation string
	State     TaskState
	Terminal  bool
}

TransitionError retains the operation and state while supporting errors.Is.

func (*TransitionError) Error

func (failure *TransitionError) Error() string

func (*TransitionError) Unwrap

func (failure *TransitionError) Unwrap() error

type WorkerArtifactFreeze

type WorkerArtifactFreeze struct {
	Artifact             ArtifactID         `json:"artifact"`
	ExpectedBaseRevision workspace.Revision `json:"expected_base_revision"`
	Payload              workspace.Payload  `json:"payload"`
}

WorkerArtifactFreeze is present only for WorkerEventFreezeArtifact. Payload is declarative workspace data; the worker transport never applies it locally.

type WorkerAssignmentDelivery

type WorkerAssignmentDelivery struct {
	ID         WorkerDeliveryID `json:"delivery_id"`
	Assignment LeaseAssignment  `json:"assignment"`
}

WorkerAssignmentDelivery contains a previously committed lease assignment. Repetition is normal protocol behavior and never creates a new lease fence.

func CloneWorkerAssignmentDelivery

func CloneWorkerAssignmentDelivery(delivery WorkerAssignmentDelivery) WorkerAssignmentDelivery

CloneWorkerAssignmentDelivery and CloneWorkerEventDelivery make ownership explicit at asynchronous adapter boundaries. Returned byte slices do not alias their inputs.

func (WorkerAssignmentDelivery) ValidateFor

func (delivery WorkerAssignmentDelivery) ValidateFor(principal AuthenticatedWorker) error

ValidateFor verifies both the delivery shape and its authenticated routing. Session is intentionally not compared because it is not correctness identity.

type WorkerCommandMeta

type WorkerCommandMeta struct {
	ID               CommandID  `json:"id"`
	ExpectedRevision uint64     `json:"expected_revision"`
	Grant            LeaseGrant `json:"grant"`
}

WorkerCommandMeta couples ordinary command idempotency/revision CAS with the grant that must still be current at the exact Store commit boundary.

type WorkerConnection

type WorkerConnection interface {
	framework.Runtime
	Principal() AuthenticatedWorker
	Assignments() <-chan WorkerAssignmentDelivery
	AckAssignment(context.Context, WorkerDeliveryID) error
	CommitEvent(context.Context, WorkerEventDelivery) (WorkerEventReceipt, error)
}

WorkerConnection binds every operation to one authenticated principal.

Assignments has one sender and closer: the connection. The transport is its only receiver. A delivery remains owned by the connection until AckAssignment succeeds or the connection ends. The transport may ACK only after the remote worker has durably stored the exact assignment. Lack of ACK, an ACK lost in transit, or reconnect permits exact value-equivalent redelivery with the same Delivery ID; task acceptance is a separate WorkerEvent.

CommitEvent is the only event-to-ACK boundary. An ACK receipt may be returned only after the corresponding Agent command and its durable command receipt have committed (or an exact committed command was replayed). A NACK is a deterministic terminal rejection and also tells a durable worker outbox to delete that record. An error settles nothing: the outbox retains the exact delivery and retries or reconciles according to its error classification.

type WorkerConnectionError

type WorkerConnectionError struct {
	Principal AuthenticatedWorker
	Cause     error
}

WorkerConnectionError adds authenticated session context while preserving errors.Is/errors.As classification through Cause.

func (*WorkerConnectionError) Error

func (failure *WorkerConnectionError) Error() string

func (*WorkerConnectionError) Unwrap

func (failure *WorkerConnectionError) Unwrap() error

type WorkerDeliveryError

type WorkerDeliveryError struct {
	Delivery WorkerDeliveryID
	Event    CommandID
	Cause    error
}

WorkerDeliveryError identifies an unsettled delivery while preserving its typed cause. In particular, ErrWorkerDeliveryIndeterminate requires exact replay/reconciliation and must never be translated into ACK or NACK.

func (*WorkerDeliveryError) Error

func (failure *WorkerDeliveryError) Error() string

func (*WorkerDeliveryError) Unwrap

func (failure *WorkerDeliveryError) Unwrap() error

type WorkerDeliveryID

type WorkerDeliveryID string

WorkerDeliveryID identifies one transport delivery. It is intentionally distinct from a domain CommandID and remains stable across retransmission.

type WorkerEndpoint

type WorkerEndpoint interface {
	OpenWorker(context.Context, AuthenticatedWorker) (WorkerConnection, error)
}

WorkerEndpoint is the narrow Agent-core surface borrowed by a transport. OpenWorker is called only after transport authentication and policy checks. Its context bounds initialization only; after success the returned connection has an independent lifecycle. The transport must call connection.Shutdown when the wire session ends, but it never shuts down the endpoint itself. Implementations must allow concurrent OpenWorker calls.

type WorkerEndpointConfig

type WorkerEndpointConfig struct {
	PollInterval       time.Duration
	RedeliveryInterval time.Duration
	AssignmentBuffer   int
}

WorkerEndpointConfig controls the official in-process bridge between an Agent core and any WorkerTransport. PollInterval discovers newly submitted tasks and caller-side Task updates. RedeliveryInterval repeats an assignment until the transport reports that the remote worker durably stored it.

func DefaultWorkerEndpointConfig

func DefaultWorkerEndpointConfig() WorkerEndpointConfig

type WorkerEvent

type WorkerEvent struct {
	ID               CommandID             `json:"event_id"`
	Kind             WorkerEventKind       `json:"kind"`
	Task             TaskRef               `json:"task"`
	Fence            LeaseFence            `json:"fence"`
	ExpectedRevision uint64                `json:"expected_revision"`
	Message          *MessageInput         `json:"message,omitempty"`
	Submission       SubmissionID          `json:"submission,omitempty"`
	Artifact         *ArtifactRef          `json:"artifact,omitempty"`
	Freeze           *WorkerArtifactFreeze `json:"freeze,omitempty"`
}

WorkerEvent is transport-neutral input to one worker-authorized Agent command. ID is the durable domain command/event identity; Fence and Task identify the lease generation. WorkerID is structurally absent and must be taken from the WorkerConnection principal at the commit boundary.

Message is required only by request_input and complete_task. Submission and optional Artifact are used only by complete_task. Freeze is used only by freeze_artifact. Unused fields must be zero so an adapter cannot smuggle an ignored interpretation through different codecs.

type WorkerEventDecision

type WorkerEventDecision string

WorkerEventDecision is a terminal transport settlement. Both values remove the exact event from a durable worker outbox; an error from CommitEvent does not. ACK means committed/replayed. NACK means deterministically rejected without accepting the requested domain transition.

const (
	WorkerEventACK  WorkerEventDecision = "ack"
	WorkerEventNACK WorkerEventDecision = "nack"
)

type WorkerEventDelivery

type WorkerEventDelivery struct {
	ID    WorkerDeliveryID `json:"delivery_id"`
	Event WorkerEvent      `json:"event"`
}

WorkerEventDelivery is the worker outbox unit. Exact retries use the same ID and the same Event. Reusing ID with different Event is a deterministic NACK.

func CloneWorkerEventDelivery

func CloneWorkerEventDelivery(delivery WorkerEventDelivery) WorkerEventDelivery

func (WorkerEventDelivery) Validate

func (delivery WorkerEventDelivery) Validate() error

func (WorkerEventDelivery) ValidateFor

func (delivery WorkerEventDelivery) ValidateFor(principal AuthenticatedWorker) error

ValidateFor additionally checks the authenticated authority. There is no payload WorkerID to compare or trust; CommitEvent supplies principal.Worker when binding Event.Fence into a LeaseGrant.

type WorkerEventKind

type WorkerEventKind string

WorkerEventKind is the closed set of Agent domain commands accepted from a worker. Adding a kind requires a transport-contract minor or major revision; adapters must never pass unknown values through as generic executable tools.

const (
	WorkerEventAcceptTask     WorkerEventKind = "accept_task"
	WorkerEventRejectTask     WorkerEventKind = "reject_task"
	WorkerEventRequestInput   WorkerEventKind = "request_input"
	WorkerEventFailTask       WorkerEventKind = "fail_task"
	WorkerEventFreezeArtifact WorkerEventKind = "freeze_artifact"
	WorkerEventCompleteTask   WorkerEventKind = "complete_task"
)

type WorkerEventReceipt

type WorkerEventReceipt struct {
	Delivery WorkerDeliveryID    `json:"delivery_id"`
	Event    CommandID           `json:"event_id"`
	Decision WorkerEventDecision `json:"decision"`
	Code     WorkerRejectionCode `json:"code,omitempty"`
	Message  string              `json:"message,omitempty"`
}

WorkerEventReceipt is exact-retry stable. ACK receipts may be emitted only at the domain durability boundary described by WorkerConnection.CommitEvent. NACK Code is safe for protocol logic; Message is diagnostic and must not be parsed for behavior.

func (WorkerEventReceipt) ValidateFor

func (receipt WorkerEventReceipt) ValidateFor(delivery WorkerEventDelivery) error

ValidateFor prevents a cumulative or reordered wire ACK from settling the wrong durable outbox record.

type WorkerID

type WorkerID string

type WorkerMessageCommand

type WorkerMessageCommand struct {
	Meta    WorkerCommandMeta `json:"meta"`
	Task    TaskRef           `json:"task"`
	Message MessageInput      `json:"message"`
}

type WorkerRejectionCode

type WorkerRejectionCode string

WorkerRejectionCode is a stable machine code selected by WorkerEndpoint. It is intentionally more specific than an HTTP or WebSocket status.

const (
	WorkerRejectInvalid         WorkerRejectionCode = "invalid"
	WorkerRejectForbidden       WorkerRejectionCode = "forbidden"
	WorkerRejectNotFound        WorkerRejectionCode = "not_found"
	WorkerRejectStaleLease      WorkerRejectionCode = "stale_lease"
	WorkerRejectRevision        WorkerRejectionCode = "revision_conflict"
	WorkerRejectState           WorkerRejectionCode = "state_conflict"
	WorkerRejectCommandConflict WorkerRejectionCode = "command_conflict"
)

type WorkerSessionID

type WorkerSessionID string

WorkerSessionID identifies one live connection only. It is deliberately not part of Task, command, lease, delivery, or idempotency identity and therefore changes on reconnect.

type WorkerTaskCommand

type WorkerTaskCommand struct {
	Meta WorkerCommandMeta `json:"meta"`
	Task TaskRef           `json:"task"`
}

type WorkerTransport

type WorkerTransport interface {
	Description() WorkerTransportDescription
	Start(context.Context, WorkerEndpoint) (WorkerTransportRuntime, error)
}

WorkerTransport owns its listeners, sessions, and background delivery loops, but only borrows endpoint. Start must not retain ctx after initialization; the returned runtime owns its lifetime. Shutdown must stop admission, shut down all WorkerConnections opened through endpoint, and wait for adapter goroutines. It must never close endpoint, type-assert it to *Agent, or close dependencies reachable through endpoint.

type WorkerTransportDescription

type WorkerTransportDescription struct {
	Contract framework.Contract
	Provider string
	Version  string
}

WorkerTransportDescription is static, non-secret adapter metadata. Provider identifies an implementation (for example "websocket" or "grpc") and Version identifies that implementation, not its negotiated wire version.

func (WorkerTransportDescription) Validate

func (description WorkerTransportDescription) Validate() error

type WorkerTransportRuntime

type WorkerTransportRuntime interface {
	framework.Runtime
}

WorkerTransportRuntime is separated from WorkerTransport so a reusable adapter value is not itself confused with one running instance.

type WorkspaceHead

type WorkspaceHead struct {
	Workspace         WorkspaceRef       `json:"workspace"`
	ConfirmedRevision workspace.Revision `json:"confirmed_revision"`
	UpdatedAt         time.Time          `json:"updated_at"`
}

type WorkspaceID

type WorkspaceID string

type WorkspaceRef

type WorkspaceRef struct {
	Authority AuthorityID `json:"authority"`
	ID        WorkspaceID `json:"id"`
}

WorkspaceRef is an authority-qualified correctness scope. Context and Workspace are deliberately orthogonal: different Contexts may share one Workspace and therefore its future Artifact CAS baseline.

Directories

Path Synopsis
Package sqlite provides the official local SQLite adapter for agent.Store.
Package sqlite provides the official local SQLite adapter for agent.Store.
Package workerws implements the official WebSocket adapter for the public HumanAgent WorkerTransport port.
Package workerws implements the official WebSocket adapter for the public HumanAgent WorkerTransport port.
sqlite
Package sqlite provides the official durable SQLite implementation of the Agent remote-worker Journal port.
Package sqlite provides the official durable SQLite implementation of the Agent remote-worker Journal port.

Jump to

Keyboard shortcuts

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