Documentation
¶
Overview ¶
Package agent provides the Scope Agent Framework execution kernel.
Definition owns immutable behavior and creates serializable Execution values; Engine owns Process lifecycle, Signal delivery, Effect dispatch, child composition, resource bounds, observation, and portable snapshots. Strategy payloads stay opaque to the kernel, and persistence stays a caller responsibility.
The kernel exists for one purpose: a multi-step agent with children and external side effects must resume after a process restart with a stated meaning for every operation that was in flight. Everything below follows from that.
The execution waist ¶
Every strategy intersects on exactly two interfaces:
type Definition interface {
Descriptor() Descriptor
Start(Input) (Execution, error)
Restore(ExecutionState) (Execution, error)
}
type Execution interface {
Step(context.Context, []Signal) (Transition, error)
Snapshot() (ExecutionState, error)
}
The waist is not generic, because the Engine holds heterogeneous definitions homogeneously. Input, Output, Signal, Effect, and ExecutionState cross it as bounded, defensively copied JSON. Generics belong to edge adapters that convert a Go input to raw input and raw output back to a Go output; they never enter the contract the Engine has to hold.
Step ¶
A Step is one cancellable, discardable, purely candidate reduction. It may not call a model, run a tool, perform any other external I/O, hide an unbounded loop, or start an unowned goroutine. An external operation can only be declared as an Effect and executed outside the Step.
These are cooperation contracts for implementations sharing one Go process. Capability checks mediate declared Effects; they do not sandbox arbitrary I/O. Cancellation and kill still depend on in-flight code returning and external operations settling. They cannot forcibly terminate a goroutine.
Three scales explain the kernel: the root tree is the consistency, commit, and recovery unit; a Process is the lifecycle and strategy-state isolation unit; a Step is the concurrency unit. Adding Processes to a tree adds isolated computation and external I/O concurrency, not authoritative commit parallelism. Independent commit throughput means separate root trees.
Each root tree has one private commit owner. Pure computation does not occupy the commit owner: a Process has at most one Step job in flight and siblings run in parallel. Only the owner revalidates and adopts a result. When a kill, pause, cancel, or a new incarnation expires an attempt, the result and its error are discarded whole and the Execution is rebuilt from committed Execution state.
The owner services continuously ready control requests, job completions, and queued Processes in bounded scheduling turns. Queries do not wake execution. Pending commits and held freezes still block work that cannot cross those boundaries; a checkpoint still requires a safe tree cut. This is a scheduling guarantee, not a wall-clock deadline: implementations must honor their bounded execution contracts, and the Host owns storage deadlines.
Before adopting initial or candidate state, the Engine captures Snapshot and successfully restores it through that Deployment's Definition. An unrestorable candidate cannot advance signal consumption or dispatch Effects. This admission check does not prove exact state equivalence or deterministic continuation: the Definition must establish those properties with conformance cases. Complete tree recovery also validates runtime identities, mailboxes, child ownership, settlements, and the exact Deployment binding.
Effects and settlement ¶
An Effect is the only way an Execution requests work outside a Step. The Engine derives a stable effect identity from the Process identity, step sequence, and effect index, then freezes the payload. It interprets only its own closed set of framework effects — child and wait operations — and hands a strategy effect whole to the dispatcher its Deployment bound. A Deployment without a dispatcher admits only framework Effects, including during recovery. A dispatcher never mutates an Execution; it produces deltas and one settlement Signal.
Each effect advances through planned, pending, and settled in declaration order, one at a time:
- the owner validates candidate state, signal consumption, budget, capability, and batch identity;
- the effect enters pending, and in durable mode the pending boundary commits the whole tree first;
- only then does the dispatcher job start, outside the owner;
- the result is normalized to a definite or an unknown settlement;
- only after the settled boundary succeeds does the owner install the settlement, candidate state, mailbox, and Process transition.
A planned effect that was never dispatched can never become unknown. Automatic redelivery is allowed only where replaying one effect identity is proven to be the same logical operation; where it is not, an unknown settlement stays observable and awaits explicit adjudication. It is never silently replayed and never assumed successful. Ephemeral mode runs the same state machine without calling the durability port. A prepared batch has one execution frontier: definitely settled Effects precede at most one pending or unknown Effect, followed only by planned Effects. Runtime scheduling and snapshot admission enforce this same order.
Signals and waiting ¶
A Signal is the only runtime input into an Execution. Process.DeliverSignals admits one ordered batch atomically, including a batch with one Signal. Repeated submission of one signal identity produces exactly one logical consumption and never charges the signal budget twice. The same identity with different immutable content is rejected as a conflict. In durable mode, successful admission is acknowledged only after mailbox records and budget charges commit to the authoritative tree head. The consumption cursor advances only when candidate state and transition commit, so a failed Step never permanently swallows input. Consumption is bounded by the Signal window delivered to that Step; input admitted while the Step runs belongs to a later window. Once consumed, a mailbox record keeps its identity, addressed wait, arrival order, and normalized payload digest. The payload itself is released with candidate adoption. Recovery retains exact pending inputs and validates wait history from these facts; consumed content is no longer a transcript.
A wait identity is minted by the Engine; an Execution cannot generate an external one. The Execution declares a logical wait through a Transition; the Engine saves the mapping and enqueues an internal Signal carrying the identity; on the next Step the Execution records it and enters Waiting explicitly. That round trip keeps the Execution the single writer of its own state. The Engine wall clock never enters strategy input — business time is submitted as an explicit payload. Wait registration and its opening Signal are one mailbox operation. Restoring history uses the same opening, admission, and consumption rules: an answer closes its wait when consumed, and Process termination closes all remaining waits. Snapshots whose wait facts contradict that history are rejected. Child completions remain queued while their parent is Paused or waiting on another WaitID. Only an answer to the current WaitID releases Waiting; an explicit pause still requires Resume. Unaddressed Strategy input can also queue while Paused or waiting for children without releasing either state.
Each strategy declares its own safe consumption boundary and proves it with contract tests.
Process lifecycle ¶
A Process moves through StatusNotStarted, StatusRunning, and then one of StatusWaiting, StatusPaused, StatusCompleted, StatusFailed, StatusCanceled, StatusTimedOut, or StatusKilled.
A terminal state is decided jointly by the recorded control intent and the Step result, never inferred from error text or from context.Canceled alone. The matrix is matched in priority order: an explicit kill wins; then a reached deadline; then parent or host cancellation; then a contract violation, external failure, or panic; then legal completion. A committed terminal state is first-terminal-wins, so a late cancellation cannot overwrite it. An effect's own cancellation first reaches the strategy as a settlement Signal — a local failure is never promoted to a Process terminal state on its own. Process.RequestCancellation also terminates active descendants through their owned lifecycle. The surviving parent receives the ordinary completion Signal and its Strategy chooses the next transition. Cancellation uses the same checkpoint acknowledgment as every other terminal transition.
A child-completion delivery failure is recorded as pending termination. Accepted external effects settle first, and any unknown identities remain in the terminal result. The pending failure survives tree capture.
A long-lived Engine retains completed trees for diagnostics and capture until the Host calls Engine.ReleaseTree. Release waits for all descendant work to settle, removes the tree from lookup, and leaves existing handles' results and runtime errors readable.
Signal identities, wait history, and descendants remain retained for that lifetime. Finite budgets and snapshot limits bound one execution; the kernel does not prune facts needed for deduplication or extend a tree indefinitely.
Engine.InspectTree is the sole live inspection entry. It composes existing ProcessSnapshot values with current job, commit, and freeze facts, and stays available while storage acknowledgment or a tree freeze blocks execution. Snapshots own lifecycle, usage, wait authority, and Unknown settlements; runtime work may be newer than a durable snapshot. Reports describe one owner turn, never drive execution, and add nothing to the recovery schema. Synchronous EventListener callbacks must not query, control, or Await their tree. Calls that forward the callback context receive ErrListenerReentrancy while that invocation is active. Different tree owners remain independently callable, but callbacks must avoid cyclic waits and return in bounded time. Engine.Close requires completed publication and bookkeeping in both durable and ephemeral mode; Await establishes that completion for each Process. Close(ctx) closes admission once and joins Engine-owned observation shutdown; canceling ctx ends only that caller's wait. DeltaListener callbacks must not call Close or FlushDeltas on their Engine because both join Delta delivery. Forwarding an active callback context makes those calls fail with ErrListenerReentrancy.
A durable writer can stop without terminating the logical execution. Storage failures and ownership conflicts reach Process.Await as a RuntimeError with no Result. The error preserves the original cause, the last acknowledged head, and uncertain Effect identities. EventRuntimeStopped describes this instance failure; it never substitutes for EventProcessFinished. Status and usage in durable mode project only acknowledged tree state. The Host reads its authoritative head before reactivation, since a lost commit response or another writer may have advanced it beyond the stopped instance's view.
Recovery ¶
ExecutionState is a discriminated envelope of a kind and an opaque payload. The kernel constrains the envelope and never interprets the payload recursively; each strategy owns and guards its own wire shape. A host may persist the envelope but must not parse it by kind and join strategy control flow. Recovery finds the Definition through an exact DeploymentRef; a global kind-to-factory switch is forbidden.
TreeSnapshot is the canonical recovery state of a complete root tree. It uses one current strict wire shape without a version envelope or migration dispatch; parsing validates the structure and the recorded domain facts. ProcessSnapshot is a single-Process diagnostic value and is not a recovery unit. Events and Delta values record attempts and observations only; they never substitute for an acknowledged TreeSnapshot. Committed events wait for durable acknowledgment. Event sequences describe publication within one runtime activation and restart when a nonterminal Process is restored; they do not change snapshot contents or trigger commits.
Strategies ¶
Three strategies run on this one kernel. The interaction package implements ReAct-style model and tool loops with working context, delegates, and artifacts. The planning package, with planning/goap, implements goal-driven search over immutable actions. The workflow package implements ordered deterministic stages over a closed vocabulary, composing through real child Processes rather than by nesting a second Execution.
The Engine never imports or type-switches a concrete strategy. A new strategy is admitted by implementing the waist, state codec, and safe consumption boundary, and binding a dispatcher when it declares external Effects.
Boundaries ¶
The framework owns definition validation, deployment freezing, the Process state machine, signal ordering and deduplication, effect identity and settlement, budgets, the lifecycle, framework events, and the snapshot and recovery protocol.
The host owns product identity, transports, stores and transactions, permissions and billing, deployment catalogs and routing, provider and model selection, storage acknowledgment, and retention of its own facts. A host depends only on this neutral lifecycle contract and never parses a strategy's snapshot payload.
Production database adapters and their storage-specific integration tests belong to the consuming application or an independently owned adapter. The agenttest package supplies shared durability and Definition conformance suites.
Chat, tools, embeddings, history, and telemetry stay in their own modules. Agent reuses them and duplicates none of them.
Index ¶
- Constants
- Variables
- type Budget
- type BudgetConfig
- type Capability
- type CapabilitySet
- func (c CapabilitySet) Allows(requested CapabilitySet) bool
- func (c CapabilitySet) Contains(capability Capability) bool
- func (c CapabilitySet) MarshalJSON() ([]byte, error)
- func (c *CapabilitySet) UnmarshalJSON(data []byte) error
- func (c CapabilitySet) Valid() bool
- func (c CapabilitySet) Values() []Capability
- type ChildKey
- type ChildOutcome
- type ChildSpec
- type ChildStartResult
- type ChildWaitCondition
- type ChildWaitOpened
- type ChildWaitSpec
- type ChildrenCompleted
- type Definition
- type Delta
- func (d Delta) EffectID() EffectID
- func (d Delta) EffectSequence() uint64
- func (d Delta) EmittedAt() time.Time
- func (d Delta) MarshalJSON() ([]byte, error)
- func (d Delta) Payload() json.RawMessage
- func (d Delta) ProcessID() ProcessID
- func (d Delta) TreeIncarnationID() (TreeIncarnationID, bool)
- func (d *Delta) UnmarshalJSON(data []byte) error
- func (d Delta) Valid() bool
- type DeltaDroppedFact
- type DeltaEmitter
- type DeltaListener
- type DeltaListenerFunc
- type Deployment
- type DeploymentConfig
- type DeploymentRef
- func (d DeploymentRef) ConfigurationDigest() Digest
- func (d DeploymentRef) ContractDigest() Digest
- func (d DeploymentRef) Digest() Digest
- func (d DeploymentRef) ImplementationDigest() Digest
- func (d DeploymentRef) MarshalJSON() ([]byte, error)
- func (d DeploymentRef) Name() string
- func (d DeploymentRef) String() string
- func (d *DeploymentRef) UnmarshalJSON(data []byte) error
- func (d DeploymentRef) Valid() bool
- type DeploymentResolver
- type Descriptor
- func (d Descriptor) DecodeOutput[T any](output Output) (T, error)
- func (d Descriptor) Description() string
- func (d Descriptor) Digest() Digest
- func (d Descriptor) EncodeInput[T any](value T) (Input, error)
- func (d Descriptor) InputSchema() Schema
- func (d Descriptor) MarshalJSON() ([]byte, error)
- func (d Descriptor) Name() string
- func (d Descriptor) OutputSchema() Schema
- func (d *Descriptor) UnmarshalJSON(data []byte) error
- func (d Descriptor) Valid() bool
- func (d Descriptor) ValidateInput(input Input) error
- func (d Descriptor) ValidateOutput(output Output) error
- type DescriptorConfig
- type Digest
- type Dispatcher
- type Effect
- type EffectBoundary
- type EffectBoundaryKind
- type EffectFinishedFact
- type EffectID
- type EffectRequest
- func (e EffectRequest) BatchIndex() uint32
- func (e EffectRequest) DeploymentRef() DeploymentRef
- func (e EffectRequest) Effect() Effect
- func (e EffectRequest) ID() EffectID
- func (e EffectRequest) ProcessID() ProcessID
- func (e EffectRequest) Relation() ProcessRelation
- func (e EffectRequest) StepSequence() uint64
- func (e EffectRequest) TreeIncarnationID() (TreeIncarnationID, bool)
- func (e EffectRequest) Valid() bool
- type EffectStartedFact
- type EffectTarget
- type Engine
- func (e *Engine) CaptureTree(ctx context.Context, rootID ProcessID) (TreeSnapshot, error)
- func (e *Engine) Close(ctx context.Context) error
- func (e *Engine) FlushDeltas(ctx context.Context) error
- func (e *Engine) InspectTree(ctx context.Context, rootID ProcessID) (TreeInspection, error)
- func (e *Engine) ObservationFailures() ObservationFailureCounts
- func (e *Engine) Process(id ProcessID) (*Process, bool)
- func (e *Engine) ReleaseTree(ctx context.Context, rootID ProcessID) error
- func (e *Engine) RestoreTree(ctx context.Context, rootDeployment Deployment, snapshot TreeSnapshot) (*Process, error)
- func (e *Engine) Run(ctx context.Context, deployment Deployment, input Input) (Result, error)
- func (e *Engine) Start(ctx context.Context, deployment Deployment, input Input) (*Process, error)
- type EngineConfig
- type Event
- func (e Event) DeltaDropped() (DeltaDroppedFact, bool)
- func (e Event) DeploymentRef() DeploymentRef
- func (e Event) EffectFinished() (EffectFinishedFact, bool)
- func (e Event) EffectID() (EffectID, bool)
- func (e Event) EffectStarted() (EffectStartedFact, bool)
- func (e Event) MarshalJSON() ([]byte, error)
- func (e Event) Name() string
- func (e Event) OccurredAt() time.Time
- func (e Event) Payload() json.RawMessage
- func (e Event) Phase() EventPhase
- func (e Event) ProcessFinished() (ProcessFinishedFact, bool)
- func (e Event) ProcessID() ProcessID
- func (e Event) ProcessSequence() uint64
- func (e Event) Relation() ProcessRelation
- func (e Event) RuntimeStopped() (RuntimeStoppedFact, bool)
- func (e Event) SignalAccepted() (SignalAcceptedFact, bool)
- func (e Event) StepCommitted() (StepCommittedFact, bool)
- func (e Event) StepFinished() (StepFinishedFact, bool)
- func (e Event) StepSequence() (uint64, bool)
- func (e Event) TreeIncarnationID() (TreeIncarnationID, bool)
- func (e *Event) UnmarshalJSON(data []byte) error
- func (e Event) Valid() bool
- type EventListener
- type EventListenerFunc
- type EventPhase
- type Execution
- type ExecutionState
- type Failure
- type FailureKind
- type Input
- type Limits
- type ObservationFailureCounts
- type Output
- type Process
- func (p *Process) Await(ctx context.Context) (Result, error)
- func (p *Process) Budget() Budget
- func (p *Process) Capabilities() CapabilitySet
- func (p *Process) DeliverSignals(ctx context.Context, requests ...SignalRequest) (accepted bool, err error)
- func (p *Process) DeploymentRef() DeploymentRef
- func (p *Process) ID() ProcessID
- func (p *Process) Kill(ctx context.Context, reason string) error
- func (p *Process) Pause(ctx context.Context, reason string) error
- func (p *Process) Relation() ProcessRelation
- func (p *Process) RequestCancellation(ctx context.Context, reason string) error
- func (p *Process) ResolveUnknownEffect(ctx context.Context, settlement Settlement) error
- func (p *Process) Resume(ctx context.Context) error
- func (p *Process) StartedAt() time.Time
- type ProcessAdmission
- type ProcessAdmitter
- type ProcessAdmitterFunc
- type ProcessFinishedFact
- type ProcessID
- type ProcessInspection
- type ProcessRelation
- func (p ProcessRelation) ChildKey() (ChildKey, bool)
- func (p ProcessRelation) Depth() uint32
- func (p ProcessRelation) IsRoot() bool
- func (p ProcessRelation) ParentID() (ProcessID, bool)
- func (p ProcessRelation) ProcessID() ProcessID
- func (p ProcessRelation) RootID() ProcessID
- func (p ProcessRelation) Valid() bool
- type ProcessSnapshot
- func (p ProcessSnapshot) Budget() Budget
- func (p ProcessSnapshot) Capabilities() CapabilitySet
- func (p ProcessSnapshot) CommittedExecutionState() ExecutionState
- func (p ProcessSnapshot) DeploymentRef() DeploymentRef
- func (p ProcessSnapshot) JSON() json.RawMessage
- func (p ProcessSnapshot) MarshalJSON() ([]byte, error)
- func (p ProcessSnapshot) ProcessID() ProcessID
- func (p ProcessSnapshot) Relation() ProcessRelation
- func (p ProcessSnapshot) Status() Status
- func (p ProcessSnapshot) UnknownEffectIDs() []EffectID
- func (p *ProcessSnapshot) UnmarshalJSON(data []byte) error
- func (p ProcessSnapshot) Usage() Usage
- func (p ProcessSnapshot) Valid() bool
- func (p ProcessSnapshot) WaitID() (WaitID, bool)
- func (p ProcessSnapshot) WaitKind() (WaitKind, bool)
- type ProcessStartOutcome
- type ProcessStartOutcomeAcknowledger
- type ProcessStartOutcomeAcknowledgerFunc
- type ProcessStartOutcomeStatus
- type ProcessWork
- type ReplayPolicy
- type Result
- type RuntimeError
- type RuntimeStoppedFact
- type Schema
- type Settlement
- type SettlementStatus
- type Signal
- type SignalAcceptedFact
- type SignalID
- type SignalRequest
- type Status
- type StepCommittedFact
- type StepFinishedFact
- type StepStatus
- type Termination
- func (t Termination) Cause() TerminationCause
- func (t Termination) Failure() (Failure, bool)
- func (t Termination) MarshalJSON() ([]byte, error)
- func (t Termination) Reason() string
- func (t Termination) Status() Status
- func (t *Termination) UnmarshalJSON(data []byte) error
- func (t Termination) UnresolvedEffectIDs() []EffectID
- func (t Termination) Valid() bool
- type TerminationCause
- type Transition
- func Complete(consumedSignals uint32, output Output) (Transition, error)
- func Continue(consumedSignals uint32, effects ...Effect) (Transition, error)
- func Fail(consumedSignals uint32, failure Failure) (Transition, error)
- func Pause(consumedSignals uint32, reason string) (Transition, error)
- func Wait(consumedSignals uint32, waitID WaitID) (Transition, error)
- func (t Transition) ConsumedSignals() uint32
- func (t Transition) Effects() []Effect
- func (t Transition) Failure() (Failure, bool)
- func (t Transition) Kind() TransitionKind
- func (t Transition) MarshalJSON() ([]byte, error)
- func (t Transition) Output() (Output, bool)
- func (t Transition) Reason() (string, bool)
- func (t *Transition) UnmarshalJSON(data []byte) error
- func (t Transition) Valid() bool
- func (t Transition) WaitID() (WaitID, bool)
- type TransitionKind
- type TreeActivation
- type TreeCheckpoint
- type TreeCheckpointKind
- type TreeDurability
- type TreeFreezePhase
- type TreeIncarnationID
- type TreeInspection
- type TreeLimits
- type TreeSnapshot
- func (t TreeSnapshot) Digest() Digest
- func (t TreeSnapshot) IncarnationID() (TreeIncarnationID, bool)
- func (t TreeSnapshot) JSON() json.RawMessage
- func (t TreeSnapshot) MarshalJSON() ([]byte, error)
- func (t TreeSnapshot) ProcessSnapshots() []ProcessSnapshot
- func (t TreeSnapshot) RootID() ProcessID
- func (t *TreeSnapshot) UnmarshalJSON(data []byte) error
- func (t TreeSnapshot) Valid() bool
- type Usage
- type WaitID
- type WaitKey
- type WaitKind
Examples ¶
Constants ¶
const ( // EventProcessStarted reports initial Process execution. EventProcessStarted = "agent.process.started" // EventProcessRestored reports execution resumed from a TreeSnapshot. EventProcessRestored = "agent.process.restored" // EventProcessPaused reports a committed scheduling pause. EventProcessPaused = "agent.process.paused" // EventProcessResumed reports committed scheduling resumption. EventProcessResumed = "agent.process.resumed" // EventProcessFinished reports one immutable terminal outcome. EventProcessFinished = "agent.process.finished" // EventRuntimeStopped reports loss of an active instance without a committed // logical terminal result. It never changes the durable Process lifecycle. EventRuntimeStopped = "agent.runtime.stopped" // EventSignalAccepted reports one newly accepted Signal. EventSignalAccepted = "agent.signal.accepted" // EventStepStarted reports an Execution.Step call about to begin. EventStepStarted = "agent.step.started" // EventStepFinished reports an Execution.Step return or failure. EventStepFinished = "agent.step.finished" // EventStepPrepared reports validated candidate Step state and fixed Effects. EventStepPrepared = "agent.step.prepared" // EventStepCommitted reports authoritative Step state publication. EventStepCommitted = "agent.step.committed" // EventEffectStarted reports a Framework or Dispatcher Effect attempt. EventEffectStarted = "agent.effect.started" // EventEffectFinished reports a definite or unknown attempt settlement. EventEffectFinished = "agent.effect.finished" // EventDeltaDropped reports best-effort increments lost to backpressure. EventDeltaDropped = "agent.delta.dropped" )
Variables ¶
var ( ErrInvalidEngineConfig = errors.New("agent: invalid engine configuration") ErrEngineClosed = errors.New("agent: engine is closed") ErrEngineHasActiveProcesses = errors.New("agent: engine has active processes") ErrProcessAlreadyExists = errors.New("agent: process identity already exists") )
var ( ErrSignalRejected = errors.New("agent: signal rejected") // ErrSignalConflict reports reuse of a SignalID with different immutable // content, including the addressed WaitID. ErrSignalConflict = errors.New("agent: signal identity conflicts with accepted content") )
var ( ErrProcessFinished = errors.New("agent: process has finished") ErrProcessNotRunning = errors.New("agent: process is not running") ErrEffectNotPending = errors.New("agent: effect does not require resolution") ErrInvalidProcessControl = errors.New("agent: invalid process control request") )
var ( ErrDurabilityConflict = errors.New("agent: durability boundary conflicts with committed content") ErrTreeIncarnationConflict = errors.New("agent: tree incarnation conflict") ErrTreeDurabilityMismatch = errors.New("agent: tree durability mode mismatch") )
var ( ErrInvalidInput = errors.New("agent: invalid input") ErrInvalidOutput = errors.New("agent: invalid output") )
var ErrInvalidCapability = errors.New("agent: invalid capability")
var ErrInvalidChildStart = errors.New("agent: invalid child process start")
var ErrInvalidChildWait = errors.New("agent: invalid child wait")
var ErrInvalidDelta = errors.New("agent: invalid delta")
var ErrInvalidDeployment = errors.New("agent: invalid deployment")
var ErrInvalidDeploymentRef = errors.New("agent: invalid deployment reference")
var ErrInvalidDescriptor = errors.New("agent: invalid descriptor")
var ErrInvalidDigest = errors.New("agent: invalid digest")
var ErrInvalidEffect = errors.New("agent: invalid effect")
var ErrInvalidEvent = errors.New("agent: invalid event")
var ErrInvalidExecutionState = errors.New("agent: invalid execution state")
var ErrInvalidFailure = errors.New("agent: invalid failure")
var ErrInvalidIdentity = errors.New("agent: invalid identity")
var ErrInvalidProcessRelation = errors.New("agent: invalid process relation")
var ErrInvalidSchema = errors.New("agent: invalid schema")
var ErrInvalidSettlement = errors.New("agent: invalid effect settlement")
var ErrInvalidSignal = errors.New("agent: invalid signal")
var ErrInvalidSignalRequest = errors.New("agent: invalid signal request")
var ErrInvalidSnapshot = errors.New("agent: invalid process snapshot")
var ErrInvalidStatus = errors.New("agent: invalid status")
var ErrInvalidTransition = errors.New("agent: invalid transition")
var ErrInvalidTreeIncarnationID = errors.New("agent: invalid tree incarnation identity")
var ErrInvalidTreeSnapshot = errors.New("agent: invalid process tree snapshot")
var ErrListenerReentrancy = errors.New("agent: operation would wait for its active listener")
ErrListenerReentrancy reports an operation that would wait for the active listener carrying its context: an EventListener's tree owner or a DeltaListener's delivery worker. Derived contexts retain this restriction until the callback returns. Replacing the context does not remove the listener's obligation to avoid waiting for itself.
var ErrProcessAdmissionRejected = errors.New("agent: process admission rejected")
ErrProcessAdmissionRejected marks failure at the policy boundary before execution starts.
var ErrResourceLimitExceeded = errors.New("agent: resource limit exceeded")
ErrResourceLimitExceeded reports a designed execution bound, not an Engine defect.
Functions ¶
This section is empty.
Types ¶
type Budget ¶
type Budget struct {
// Steps is the maximum committed Step count allocated to the child.
Steps uint64 `json:"steps"`
// Effects is the maximum prepared Effect count allocated to the child.
Effects uint64 `json:"effects"`
// Signals is the maximum accepted Signal count allocated to the child.
Signals uint64 `json:"signals"`
}
Budget is a non-renewable allocation of Framework-owned work units. A child allocation is permanently transferred from its parent's remaining budget; unused units are not silently reclaimed or duplicated. Remaining budget excludes the parent's prepared Step and its future settlement Signals.
func NewBudget ¶
func NewBudget(config BudgetConfig) (Budget, error)
NewBudget validates the bounds together, because a budget is attenuated when it passes to a child and an unvalidated zero would read as unlimited at exactly the point authority is meant to narrow.
type BudgetConfig ¶ added in v0.13.0
BudgetConfig names each bound so a call site cannot transpose them. Three positional counts of the same type are indistinguishable to the compiler, and a swapped pair produces a Process that runs far longer or dies far sooner than intended.
type Capability ¶
type Capability struct {
// contains filtered or unexported fields
}
Capability is one stable qualified authority name understood by a Deployment's dispatcher or another external boundary. The Framework only enforces possession and attenuation; it does not assign product meaning.
func ParseCapability ¶
func ParseCapability(name string) (Capability, error)
ParseCapability validates a lowercase qualified capability name.
func (Capability) MarshalText ¶
func (c Capability) MarshalText() ([]byte, error)
func (Capability) String ¶
func (c Capability) String() string
func (*Capability) UnmarshalText ¶
func (c *Capability) UnmarshalText(text []byte) error
func (Capability) Valid ¶
func (c Capability) Valid() bool
type CapabilitySet ¶
type CapabilitySet struct {
// contains filtered or unexported fields
}
CapabilitySet is an immutable, sorted set of authority names. Its zero value is the valid empty set.
func NewCapabilitySet ¶
func NewCapabilitySet(capabilities ...Capability) (CapabilitySet, error)
NewCapabilitySet builds the frozen grant a Process runs under. It is a set rather than a slice because a duplicated or reordered grant must not change authority, and because every child grant must be a subset of its parent's.
func (CapabilitySet) Allows ¶
func (c CapabilitySet) Allows(requested CapabilitySet) bool
Allows reports whether requested is a subset of c.
func (CapabilitySet) Contains ¶
func (c CapabilitySet) Contains(capability Capability) bool
Contains reports whether capability belongs to the set.
func (CapabilitySet) MarshalJSON ¶
func (c CapabilitySet) MarshalJSON() ([]byte, error)
func (*CapabilitySet) UnmarshalJSON ¶
func (c *CapabilitySet) UnmarshalJSON(data []byte) error
func (CapabilitySet) Valid ¶
func (c CapabilitySet) Valid() bool
func (CapabilitySet) Values ¶
func (c CapabilitySet) Values() []Capability
Values returns an independently owned, sorted capability slice.
type ChildKey ¶
type ChildKey struct {
// contains filtered or unexported fields
}
ChildKey is an Execution-owned stable identity for one logical child start. The Engine combines it with the parent Process identity and prepared Effect identity to make retries and restoration idempotent.
func ParseChildKey ¶
ParseChildKey validates an Execution-owned logical child identity.
func (ChildKey) MarshalText ¶
func (*ChildKey) UnmarshalText ¶
type ChildOutcome ¶
type ChildOutcome struct {
// contains filtered or unexported fields
}
ChildOutcome pairs a parent's logical ChildKey with one immutable terminal Process Result.
func (ChildOutcome) Key ¶
func (c ChildOutcome) Key() ChildKey
Key returns the parent-scoped logical child identity.
func (ChildOutcome) Result ¶
func (c ChildOutcome) Result() Result
Result returns the child's immutable terminal result.
func (ChildOutcome) Valid ¶
func (c ChildOutcome) Valid() bool
type ChildSpec ¶
type ChildSpec struct {
// Key is the parent-scoped logical identity of this child start.
Key ChildKey `json:"key"`
// DeploymentRef identifies the exact child behavior binding.
DeploymentRef DeploymentRef `json:"deployment_ref"`
// Input is the portable input validated by the target Descriptor.
Input Input `json:"input"`
// Budget is permanently allocated from the parent to this child.
Budget Budget `json:"budget"`
// Capabilities is the attenuated authority granted to this child.
Capabilities CapabilitySet `json:"capabilities"`
}
ChildSpec is the complete Strategy-declared intent for one child Process. Input is validated by the target Deployment before any Process is created.
type ChildStartResult ¶
type ChildStartResult struct {
// contains filtered or unexported fields
}
ChildStartResult is the definite result of one StartChild Effect. Success contains the Engine-created child ProcessID; failure contains a stable Framework Failure and never masquerades as an unknown external outcome.
func ParseChildStartResult ¶
func ParseChildStartResult(signal Signal) (ChildStartResult, error)
ParseChildStartResult decodes a Framework-owned child-start settlement Signal. The Signal must not address a wait.
func (ChildStartResult) DeploymentRef ¶
func (c ChildStartResult) DeploymentRef() DeploymentRef
DeploymentRef returns the exact child execution binding.
func (ChildStartResult) Failure ¶
func (c ChildStartResult) Failure() (Failure, bool)
Failure returns the definite start failure and true when no child was created.
func (ChildStartResult) Key ¶
func (c ChildStartResult) Key() ChildKey
Key returns the logical child identity declared by the Execution.
func (ChildStartResult) ProcessID ¶
func (c ChildStartResult) ProcessID() (ProcessID, bool)
ProcessID returns the created child identity and true on success.
func (ChildStartResult) Valid ¶
func (c ChildStartResult) Valid() bool
type ChildWaitCondition ¶
type ChildWaitCondition struct {
// contains filtered or unexported fields
}
ChildWaitCondition identifies when a set of child Processes releases its parent. It describes completion count only; it does not imply cancellation of unfinished children or reinterpret child terminal statuses.
func AllChildren ¶
func AllChildren() ChildWaitCondition
AllChildren waits until every named child is terminal.
func AnyChild ¶
func AnyChild() ChildWaitCondition
AnyChild waits until at least one named child is terminal.
func ChildQuorum ¶
func ChildQuorum(count uint32) (ChildWaitCondition, error)
ChildQuorum waits until count named children are terminal.
func (ChildWaitCondition) Valid ¶
func (c ChildWaitCondition) Valid() bool
type ChildWaitOpened ¶
type ChildWaitOpened struct {
// contains filtered or unexported fields
}
ChildWaitOpened is the definite acknowledgement that the Engine registered a child wait and minted its WaitID.
func ParseChildWaitOpened ¶
func ParseChildWaitOpened(signal Signal) (ChildWaitOpened, error)
ParseChildWaitOpened decodes the settlement Signal produced by WaitForChildren and verifies its Engine-attached WaitID.
func (ChildWaitOpened) Spec ¶
func (c ChildWaitOpened) Spec() ChildWaitSpec
Spec returns the immutable child-wait request acknowledged by Engine.
func (ChildWaitOpened) Valid ¶
func (c ChildWaitOpened) Valid() bool
func (ChildWaitOpened) WaitID ¶
func (c ChildWaitOpened) WaitID() WaitID
WaitID returns the Engine-minted wait identity to store in Execution state.
type ChildWaitSpec ¶
type ChildWaitSpec struct {
// Key is the Execution-owned logical identity of this wait request.
Key WaitKey
// Children lists direct child identities in result order.
Children []ProcessID
// Condition declares how many listed children must become terminal.
Condition ChildWaitCondition
}
ChildWaitSpec names one stable logical wait, its direct children in result order, and the completion predicate.
func (ChildWaitSpec) Valid ¶
func (c ChildWaitSpec) Valid() bool
type ChildrenCompleted ¶
type ChildrenCompleted struct {
// contains filtered or unexported fields
}
ChildrenCompleted is one condition-satisfying, request-ordered child result set. For any or quorum it includes every child already terminal at the atomic satisfaction check, without canceling or omitting based on status.
func ParseChildrenCompleted ¶
func ParseChildrenCompleted(signal Signal) (ChildrenCompleted, error)
ParseChildrenCompleted decodes an Engine-generated, WaitID-addressed child completion Signal.
func (ChildrenCompleted) Key ¶
func (c ChildrenCompleted) Key() WaitKey
Key returns the logical wait key declared by the Execution.
func (ChildrenCompleted) Outcomes ¶
func (c ChildrenCompleted) Outcomes() []ChildOutcome
Outcomes returns terminal children in the original ChildWaitSpec order.
func (ChildrenCompleted) Valid ¶
func (c ChildrenCompleted) Valid() bool
func (ChildrenCompleted) WaitID ¶
func (c ChildrenCompleted) WaitID() WaitID
WaitID returns the addressed wait identity.
type Definition ¶
type Definition interface {
// Descriptor returns the immutable, portable contract shared by every
// Execution created from this definition. Repeated and concurrent calls must
// return an equivalent value; runtime configuration and mutable state do not
// belong in the descriptor.
Descriptor() Descriptor
// Start validates input against Descriptor and creates a fresh, isolated
// Execution without performing external I/O. The returned Execution has not
// executed a Step and must not share mutable state with another Process.
Start(input Input) (Execution, error)
// Restore reconstructs one Execution from a state previously produced by
// Snapshot for this exact definition. It must reject malformed state and
// state belonging to another contract; restoration must
// not replay external work.
Restore(state ExecutionState) (Execution, error)
}
Definition is an immutable Agent behavior definition. Its methods may be called concurrently for different Processes. Implementations create a fresh Execution from validated Input or restore one from their own opaque ExecutionState. Definition methods must not depend on Host product identities, storage protocols, or mutable global registration.
Example ¶
An independently authored Definition binds through the same Deployment and Engine contracts as built-in strategies. TestExternalPackageCanComposeAndRunDefinition checks this implementation with agenttest.RunDefinitionConformance.
package main
import (
"context"
"encoding/json"
jsonv2 "encoding/json/v2"
"fmt"
"sync/atomic"
"github.com/Tangerg/scope/agent"
)
type echoInput struct {
Value string `json:"value"`
}
type echoOutput struct {
Value string `json:"value"`
}
type echoDefinition struct {
descriptor agent.Descriptor
}
type echoState struct {
Phase string `json:"phase"`
Value string `json:"value"`
}
func (e echoDefinition) Descriptor() agent.Descriptor { return e.descriptor }
func (e echoDefinition) Start(input agent.Input) (agent.Execution, error) {
if err := e.descriptor.ValidateInput(input); err != nil {
return nil, err
}
value, err := input.Decode[echoInput]()
if err != nil {
return nil, err
}
return &echoExecution{state: echoState{Phase: "ready", Value: value.Value}}, nil
}
func (echoDefinition) Restore(state agent.ExecutionState) (agent.Execution, error) {
if !state.Valid() || state.Kind() != "example.echo" {
return nil, agent.ErrInvalidExecutionState
}
var value echoState
if err := jsonv2.Unmarshal(state.Payload(), &value, jsonv2.RejectUnknownMembers(true)); err != nil {
return nil, err
}
switch value.Phase {
case "ready", "awaiting_echo", "completed":
return &echoExecution{state: value}, nil
default:
return nil, agent.ErrInvalidExecutionState
}
}
type echoExecution struct {
state echoState
}
func (e *echoExecution) Step(ctx context.Context, signals []agent.Signal) (agent.Transition, error) {
if err := ctx.Err(); err != nil {
return agent.Transition{}, err
}
switch e.state.Phase {
case "ready":
if len(signals) != 0 {
return agent.Transition{}, agent.ErrInvalidSignal
}
payload, err := json.Marshal(echoInput{Value: e.state.Value})
if err != nil {
return agent.Transition{}, err
}
effect, err := agent.NewDispatcherEffect(payload)
if err != nil {
return agent.Transition{}, err
}
e.state.Phase = "awaiting_echo"
return agent.Continue(0, effect)
case "awaiting_echo":
if len(signals) != 1 {
return agent.Transition{}, agent.ErrInvalidSignal
}
var result echoOutput
if err := jsonv2.Unmarshal(signals[0].Payload(), &result, jsonv2.RejectUnknownMembers(true)); err != nil {
return agent.Transition{}, err
}
output, err := agent.EncodeOutput(result)
if err != nil {
return agent.Transition{}, err
}
e.state.Phase = "completed"
return agent.Complete(1, output)
default:
return agent.Transition{}, agent.ErrInvalidExecutionState
}
}
func (e *echoExecution) Snapshot() (agent.ExecutionState, error) {
payload, err := json.Marshal(e.state)
if err != nil {
return agent.ExecutionState{}, err
}
return agent.NewExecutionState("example.echo", payload)
}
func newEchoDefinition() (echoDefinition, error) {
inputSchema, err := agent.SchemaFor[echoInput]()
if err != nil {
return echoDefinition{}, err
}
outputSchema, err := agent.SchemaFor[echoOutput]()
if err != nil {
return echoDefinition{}, err
}
descriptor, err := agent.NewDescriptor(agent.DescriptorConfig{
Name: "example.echo", Description: "Echoes a value through an Engine-managed Effect.",
InputSchema: inputSchema, OutputSchema: outputSchema,
})
if err != nil {
return echoDefinition{}, err
}
return echoDefinition{descriptor: descriptor}, nil
}
// echoDispatcher has no external mutation, so repeating an identity is safe.
type echoDispatcher struct{}
func (echoDispatcher) Dispatch(ctx context.Context, request agent.EffectRequest, emit agent.DeltaEmitter) (agent.Settlement, error) {
if err := ctx.Err(); err != nil {
return agent.Settlement{}, err
}
payload := request.Effect().Payload()
emit(payload)
return agent.NewSettlement(request.ID(), agent.SettlementStatusSucceeded, payload)
}
func (echoDispatcher) ReplayPolicy(agent.Effect) agent.ReplayPolicy {
return agent.ReplayPolicySameIdentity
}
// countingDispatcher counts attempts, including replay, rather than logical operations.
type countingDispatcher struct {
next agent.Dispatcher
attempts atomic.Int64
}
func (c *countingDispatcher) Dispatch(ctx context.Context, request agent.EffectRequest, emit agent.DeltaEmitter) (agent.Settlement, error) {
c.attempts.Add(1)
return c.next.Dispatch(ctx, request, emit)
}
func (c *countingDispatcher) ReplayPolicy(effect agent.Effect) agent.ReplayPolicy {
return c.next.ReplayPolicy(effect)
}
// An independently authored Definition binds through the same Deployment and
// Engine contracts as built-in strategies. TestExternalPackageCanComposeAndRunDefinition
// checks this implementation with agenttest.RunDefinitionConformance.
func main() {
ctx := context.Background()
definition, err := newEchoDefinition()
if err != nil {
panic(err)
}
dispatcher := &countingDispatcher{next: echoDispatcher{}}
deployment, err := agent.NewDeployment(agent.DeploymentConfig{
Definition: definition, Dispatcher: dispatcher,
ImplementationDigest: agent.ComputeDigest([]byte("example-echo-implementation")),
ConfigurationDigest: agent.ComputeDigest([]byte("example-echo-configuration")),
})
if err != nil {
panic(err)
}
engine, err := agent.NewEngine(agent.EngineConfig{})
if err != nil {
panic(err)
}
defer func() {
if closeErr := engine.Close(ctx); closeErr != nil {
panic(closeErr)
}
}()
input, err := definition.Descriptor().EncodeInput(echoInput{Value: "hello"})
if err != nil {
panic(err)
}
result, err := engine.Run(ctx, deployment, input)
if err != nil {
panic(err)
}
output, ok := result.Output()
if !ok {
panic("completed Result has no Output")
}
value, err := definition.Descriptor().DecodeOutput[echoOutput](output)
if err != nil {
panic(err)
}
inspection, err := engine.InspectTree(ctx, result.ProcessID())
if err != nil {
panic(err)
}
report, found := inspection.Process(result.ProcessID())
if !found {
panic("completed Process is absent from its tree")
}
if err := engine.ReleaseTree(context.Background(), result.ProcessID()); err != nil {
panic(err)
}
fmt.Println(result.Status(), value.Value, dispatcher.attempts.Load())
fmt.Println("inspected:", report.Snapshot.Status(), report.Snapshot.Usage().PreparedEffects)
}
Output: completed hello 1 inspected: completed 1
type Delta ¶
type Delta struct {
// contains filtered or unexported fields
}
Delta is a bounded, best-effort stream increment from one Effect attempt. EffectSequence preserves producer order. Delta is never replayed from a snapshot and never contributes to the authoritative final Output.
func (Delta) EffectID ¶
EffectID identifies the logical Effect and remains stable across replay attempts.
func (Delta) EffectSequence ¶
EffectSequence returns the one-based producer order within the Effect attempt.
func (Delta) MarshalJSON ¶
func (Delta) Payload ¶
func (d Delta) Payload() json.RawMessage
Payload returns an independently owned Strategy-defined increment.
func (Delta) TreeIncarnationID ¶
func (d Delta) TreeIncarnationID() (TreeIncarnationID, bool)
TreeIncarnationID returns the active durable writer that emitted this delta. Deltas from ephemeral trees return false.
func (*Delta) UnmarshalJSON ¶
type DeltaDroppedFact ¶
type DeltaDroppedFact struct {
// contains filtered or unexported fields
}
DeltaDroppedFact reports the number of increments rejected during one Effect attempt because validation failed or the bounded observation queue was full.
func (DeltaDroppedFact) Count ¶
func (d DeltaDroppedFact) Count() uint64
func (DeltaDroppedFact) Valid ¶
func (d DeltaDroppedFact) Valid() bool
type DeltaEmitter ¶
type DeltaEmitter func(payload json.RawMessage)
DeltaEmitter accepts Strategy-owned streaming payloads while Dispatch is active. The Engine validates, orders, bounds, and publishes each payload as a best-effort Delta. It intentionally returns no observer error. A Dispatcher must not retain or call it after Dispatch returns.
type DeltaListener ¶
type DeltaListener interface {
// OnDelta receives an accepted best-effort increment in queue order. Delivery
// is sequential per listener but may lag Process execution; slow callbacks can
// cause later increments to be dropped. The callback cannot affect execution.
// Close and FlushDeltas using this context, or a derived context, return
// [ErrListenerReentrancy] while this invocation is active because both would
// wait for the worker delivering this callback.
OnDelta(ctx context.Context, delta Delta)
}
DeltaListener observes best-effort Strategy streaming increments. Panics are isolated; slow listeners may cause bounded queue drops. Implementations must return in bounded time without closing or flushing their Engine.
type DeltaListenerFunc ¶
DeltaListenerFunc adapts a plain function to the delta listener interface. It returns nothing for the same reason as EventListenerFunc, and because a dropped delta must never change execution.
type Deployment ¶
type Deployment struct {
// contains filtered or unexported fields
}
Deployment is an immutable binding of one Definition, its optional external Dispatcher, and an exact value reference used by Process snapshots.
func NewDeployment ¶
func NewDeployment(config DeploymentConfig) (Deployment, error)
NewDeployment freezes a Definition and Dispatcher under explicit implementation and configuration digests. That binding lets recovery resolve the exact behavior a snapshot names instead of whatever now answers to the same Definition name.
func (Deployment) Definition ¶
func (d Deployment) Definition() Definition
Definition returns the erased behavior definition bound to this Deployment.
func (Deployment) DeploymentRef ¶
func (d Deployment) DeploymentRef() DeploymentRef
DeploymentRef returns the exact value identity stored in Process snapshots.
func (Deployment) Descriptor ¶
func (d Deployment) Descriptor() Descriptor
Descriptor returns the frozen static Definition contract.
func (Deployment) Valid ¶
func (d Deployment) Valid() bool
type DeploymentConfig ¶
type DeploymentConfig struct {
// Definition owns the Strategy contract and creates per-Process execution.
Definition Definition
// Dispatcher interprets this Definition's external Effects. Nil binds a
// Definition that uses only Framework Effects; a dispatcher-targeted Effect
// then fails admission before any Effect in its Step can execute.
Dispatcher Dispatcher
// ImplementationDigest identifies the exact executable Definition artifact.
ImplementationDigest Digest
// ConfigurationDigest identifies all frozen behavior-affecting Definition
// and Dispatcher configuration.
ConfigurationDigest Digest
}
DeploymentConfig contains the complete behavior binding of one Deployment. The digests must cover the exact code artifact and all frozen dispatcher or Strategy configuration that can affect execution or restoration.
type DeploymentRef ¶
type DeploymentRef struct {
// contains filtered or unexported fields
}
DeploymentRef is the immutable value identity of one exact Definition implementation and frozen execution configuration. It contains no registry pointer and is sufficient to reject restore against a different Deployment.
func (DeploymentRef) ConfigurationDigest ¶
func (d DeploymentRef) ConfigurationDigest() Digest
ConfigurationDigest returns the frozen behavior-affecting configuration identity, including dispatcher configuration.
func (DeploymentRef) ContractDigest ¶
func (d DeploymentRef) ContractDigest() Digest
ContractDigest returns the exact Descriptor contract identity.
func (DeploymentRef) Digest ¶
func (d DeploymentRef) Digest() Digest
Digest returns the complete Deployment value identity.
func (DeploymentRef) ImplementationDigest ¶
func (d DeploymentRef) ImplementationDigest() Digest
ImplementationDigest returns the exact executable implementation identity.
func (DeploymentRef) MarshalJSON ¶
func (d DeploymentRef) MarshalJSON() ([]byte, error)
func (DeploymentRef) Name ¶
func (d DeploymentRef) Name() string
Name returns the stable Definition name.
func (DeploymentRef) String ¶
func (d DeploymentRef) String() string
func (*DeploymentRef) UnmarshalJSON ¶
func (d *DeploymentRef) UnmarshalJSON(data []byte) error
func (DeploymentRef) Valid ¶
func (d DeploymentRef) Valid() bool
type DeploymentResolver ¶
type DeploymentResolver interface {
// Resolve returns the immutable binding for exactly reference. It must not
// fall back by name, perform routing or remote discovery, or retain
// caller state. Missing and mismatched bindings are errors; concurrent calls
// must be safe.
Resolve(reference DeploymentRef) (Deployment, error)
}
DeploymentResolver performs one bounded, deterministic, context-free lookup of an exact immutable Deployment. The Engine accepts only a result whose reference exactly matches the requested reference. Implementations must be safe for concurrent use, must not perform remote I/O, and must not re-enter any Process. Routing and caller-specific selection happen before an exact DeploymentRef reaches this contract.
type Descriptor ¶
type Descriptor struct {
// contains filtered or unexported fields
}
Descriptor is an immutable Definition contract. It contains no executable behavior or Deployment configuration.
func NewDescriptor ¶
func NewDescriptor(config DescriptorConfig) (Descriptor, error)
NewDescriptor validates the schemas at construction because they enter the Deployment digest. A schema accepted here and rejected later would change a Deployment's identity after Processes had already been started against it.
Example ¶
package main
import (
"fmt"
"github.com/Tangerg/scope/agent"
)
func main() {
schema, err := agent.SchemaFor[string]()
if err != nil {
panic(err)
}
descriptor, err := agent.NewDescriptor(agent.DescriptorConfig{
Name: "example.echo",
Description: "Returns the supplied text.",
InputSchema: schema,
OutputSchema: schema,
})
if err != nil {
panic(err)
}
fmt.Println(descriptor.Name(), descriptor.Valid())
}
Output: example.echo true
func (Descriptor) DecodeOutput ¶
func (d Descriptor) DecodeOutput[T any](output Output) (T, error)
DecodeOutput validates output against this Descriptor's authoritative output schema and strictly decodes it into T.
func (Descriptor) Description ¶
func (d Descriptor) Description() string
Description returns the human-readable purpose of the Definition.
func (Descriptor) Digest ¶
func (d Descriptor) Digest() Digest
Digest returns the SHA-256 identity of the complete descriptor contract.
func (Descriptor) EncodeInput ¶
func (d Descriptor) EncodeInput[T any](value T) (Input, error)
EncodeInput converts value into an Input and validates it against this Descriptor's authoritative input schema.
func (Descriptor) InputSchema ¶
func (d Descriptor) InputSchema() Schema
InputSchema returns an independently owned schema value.
func (Descriptor) MarshalJSON ¶
func (d Descriptor) MarshalJSON() ([]byte, error)
func (Descriptor) OutputSchema ¶
func (d Descriptor) OutputSchema() Schema
OutputSchema returns an independently owned schema value.
func (*Descriptor) UnmarshalJSON ¶
func (d *Descriptor) UnmarshalJSON(data []byte) error
func (Descriptor) Valid ¶
func (d Descriptor) Valid() bool
func (Descriptor) ValidateInput ¶
func (d Descriptor) ValidateInput(input Input) error
func (Descriptor) ValidateOutput ¶
func (d Descriptor) ValidateOutput(output Output) error
type DescriptorConfig ¶
type DescriptorConfig struct {
// Name is a stable lowercase qualified Definition name.
Name string
// Description states the Definition's behavior for human and model-facing
// discovery without execution-specific state.
Description string
// InputSchema is the authoritative structural contract for Process input.
InputSchema Schema
// OutputSchema is the authoritative structural contract for completed output.
OutputSchema Schema
}
DescriptorConfig contains the complete static contract of a Definition. Executable implementation and frozen configuration identity belong to a Deployment, not this contract.
type Digest ¶
type Digest struct {
// contains filtered or unexported fields
}
Digest is a canonical SHA-256 content identity. Its zero value is invalid.
func ComputeDigest ¶
ComputeDigest returns the canonical SHA-256 identity of data. Callers that assemble a Deployment use it for reproducible implementation artifacts and canonical frozen configuration bytes.
func ParseDigest ¶
ParseDigest validates a canonical sha256:<lowercase-hex> identity.
func (Digest) MarshalText ¶
func (*Digest) UnmarshalText ¶
type Dispatcher ¶
type Dispatcher interface {
// Dispatch performs one frozen Strategy Effect outside Execution.Step.
// Settlement must address request.ID; a non-nil error means the external
// outcome is unknown, not definitely failed. emit is valid only during this
// call. Implementations honor ctx and may be called concurrently.
Dispatch(ctx context.Context, request EffectRequest, emit DeltaEmitter) (Settlement, error)
// ReplayPolicy declares, without I/O or mutable side effects, whether this
// exact Effect can be repeated under its original EffectID after an unknown
// settlement. The answer must be deterministic for equivalent Effects.
ReplayPolicy(effect Effect) ReplayPolicy
}
Dispatcher executes Strategy-owned Effects outside Execution.Step. It must return a Settlement addressed to request.ID. A returned error means the Engine cannot prove the external result and records an unknown settlement. The same Dispatcher may serve Processes concurrently; implementations must be concurrency-safe, return in bounded time, not mutate an Execution, and not start unowned goroutines. ReplayPolicy must be a pure, deterministic declaration for the supplied immutable Effect.
A transparent decorator preserves the context, complete request identity, emitter, Settlement, and error of its wrapped Dispatcher. Its ReplayPolicy must also account for its own behavior: forwarding a SameIdentity claim is valid only when the added work is safe to repeat under the original identity. Observation counters may count dispatch attempts, including replay; they do not count distinct logical external operations. See the Definition example for a concurrency-safe attempt counter around a bound Dispatcher.
type Effect ¶
type Effect struct {
// contains filtered or unexported fields
}
Effect is an immutable request for an operation outside Execution.Step. Payload is frozen before dispatch and interpreted only by Target's owner. EffectID is deliberately absent because the Engine assigns it during prepare.
func NewDispatcherEffect ¶
func NewDispatcherEffect(payload json.RawMessage, required ...Capability) (Effect, error)
NewDispatcherEffect carries an opaque payload plus the capabilities it requires, so the Engine can refuse an effect the Process was never granted without understanding what the effect does. Keeping the payload opaque is what stops model and tool vocabulary from entering the kernel.
func RequestWait ¶
func RequestWait(key WaitKey, signalPayload json.RawMessage) (Effect, error)
RequestWait creates the Framework Effect that asks the Engine to mint one WaitID for key. signalPayload remains Strategy-owned and is returned unchanged in the internal Signal that carries the minted WaitID back to the Execution.
func StartChild ¶
StartChild creates a Framework-owned Effect requesting one independently managed child Process. The Engine derives the child ProcessID; Execution code cannot construct or start the Process directly.
func WaitForChildren ¶
func WaitForChildren(spec ChildWaitSpec) (Effect, error)
WaitForChildren creates a Framework Effect that opens an Engine-owned wait over direct children. Dispatch returns immediately with a WaitID; child work never blocks Execution.Step or holds a prepared Step open.
func (Effect) MarshalJSON ¶
func (Effect) Payload ¶
func (e Effect) Payload() json.RawMessage
Payload returns an independently owned copy of the operation intent.
func (Effect) RequiredCapabilities ¶
func (e Effect) RequiredCapabilities() CapabilitySet
RequiredCapabilities returns the immutable authority set the Process must possess before this Dispatcher Effect may be prepared.
func (Effect) Target ¶
func (e Effect) Target() EffectTarget
Target returns the owner responsible for interpreting Payload.
func (*Effect) UnmarshalJSON ¶
type EffectBoundary ¶
type EffectBoundary struct {
// contains filtered or unexported fields
}
EffectBoundary binds an external Effect fact to its prospective tree so a Host cannot acknowledge dispatch or settlement independently of recovery state.
func (EffectBoundary) Kind ¶
func (e EffectBoundary) Kind() EffectBoundaryKind
func (EffectBoundary) PreviousTreeDigest ¶
func (e EffectBoundary) PreviousTreeDigest() Digest
func (EffectBoundary) Request ¶
func (e EffectBoundary) Request() EffectRequest
func (EffectBoundary) Settlement ¶
func (e EffectBoundary) Settlement() (Settlement, bool)
func (EffectBoundary) TreeSnapshot ¶
func (e EffectBoundary) TreeSnapshot() TreeSnapshot
func (EffectBoundary) Valid ¶
func (e EffectBoundary) Valid() bool
type EffectBoundaryKind ¶
type EffectBoundaryKind string
EffectBoundaryKind is closed because recovery needs a defined continuation for every acknowledged external Effect boundary.
const ( EffectBoundaryInvalid EffectBoundaryKind = "" EffectBoundaryPending EffectBoundaryKind = "pending" EffectBoundarySettled EffectBoundaryKind = "settled" EffectBoundaryResolved EffectBoundaryKind = "resolved" )
func (EffectBoundaryKind) String ¶
func (e EffectBoundaryKind) String() string
func (EffectBoundaryKind) Valid ¶
func (e EffectBoundaryKind) Valid() bool
type EffectFinishedFact ¶
type EffectFinishedFact struct {
// contains filtered or unexported fields
}
EffectFinishedFact is the immutable settlement observation for one Effect attempt. It does not replace the durable Effect boundary.
func (EffectFinishedFact) Duration ¶
func (e EffectFinishedFact) Duration() time.Duration
func (EffectFinishedFact) SettlementStatus ¶
func (e EffectFinishedFact) SettlementStatus() SettlementStatus
func (EffectFinishedFact) Target ¶
func (e EffectFinishedFact) Target() EffectTarget
func (EffectFinishedFact) Valid ¶
func (e EffectFinishedFact) Valid() bool
type EffectID ¶
type EffectID struct {
// contains filtered or unexported fields
}
EffectID identifies one Effect at a stable Process, Step, and batch index.
func ParseEffectID ¶
ParseEffectID validates an externally encoded Effect identity.
func (EffectID) MarshalText ¶
func (*EffectID) UnmarshalText ¶
type EffectRequest ¶
type EffectRequest struct {
// contains filtered or unexported fields
}
EffectRequest is the immutable dispatch context prepared by the Engine.
func (EffectRequest) BatchIndex ¶
func (e EffectRequest) BatchIndex() uint32
BatchIndex returns the zero-based declaration order within the Step Effect batch.
func (EffectRequest) DeploymentRef ¶
func (e EffectRequest) DeploymentRef() DeploymentRef
DeploymentRef returns the exact behavior binding executing the Effect.
func (EffectRequest) Effect ¶
func (e EffectRequest) Effect() Effect
Effect returns an independently owned copy of the frozen intent.
func (EffectRequest) ID ¶
func (e EffectRequest) ID() EffectID
ID returns the stable identity assigned during Step preparation.
func (EffectRequest) ProcessID ¶
func (e EffectRequest) ProcessID() ProcessID
ProcessID returns the Process that owns the Effect.
func (EffectRequest) Relation ¶
func (e EffectRequest) Relation() ProcessRelation
Relation returns the immutable Process tree location executing the Effect.
func (EffectRequest) StepSequence ¶
func (e EffectRequest) StepSequence() uint64
StepSequence returns the one-based Step sequence that declared the Effect.
func (EffectRequest) TreeIncarnationID ¶ added in v0.16.0
func (e EffectRequest) TreeIncarnationID() (TreeIncarnationID, bool)
TreeIncarnationID identifies the active durable writer for observation and correlation. Ephemeral requests return false. It does not participate in the Effect's stable idempotency identity, which remains ID across restoration.
func (EffectRequest) Valid ¶
func (e EffectRequest) Valid() bool
Valid reports whether the request contains one complete Engine-minted dispatch identity and immutable Effect.
type EffectStartedFact ¶
type EffectStartedFact struct {
// contains filtered or unexported fields
}
EffectStartedFact identifies the target of one Effect attempt.
func (EffectStartedFact) Target ¶
func (e EffectStartedFact) Target() EffectTarget
func (EffectStartedFact) Valid ¶
func (e EffectStartedFact) Valid() bool
type EffectTarget ¶
type EffectTarget string
EffectTarget identifies which of the two execution boundaries owns an Effect. Framework Effects are interpreted by the Engine; Dispatcher Effects remain opaque to the Engine and are interpreted by the Deployment-bound dispatcher.
const ( // EffectTargetInvalid is the invalid zero value. EffectTargetInvalid EffectTarget = "" // EffectTargetFramework identifies an Engine-interpreted Effect. EffectTargetFramework EffectTarget = "framework" // EffectTargetDispatcher identifies a Strategy dispatcher Effect. EffectTargetDispatcher EffectTarget = "dispatcher" )
func (EffectTarget) String ¶
func (e EffectTarget) String() string
func (EffectTarget) Valid ¶
func (e EffectTarget) Valid() bool
type Engine ¶
type Engine struct {
// contains filtered or unexported fields
}
Engine keeps admission, publication, and execution under one owner because resource reservations and recoverable tree state must describe the same lifecycle. Construct it with NewEngine; copying an Engine would share its registries while duplicating their synchronization.
func NewEngine ¶
func NewEngine(config EngineConfig) (*Engine, error)
NewEngine validates the whole configuration up front because an Engine owns Process lifecycle: a defect discovered after Processes exist has no safe remedy, since stopping the Engine would abandon in-flight effects whose settlement is still unknown.
func (*Engine) CaptureTree ¶
CaptureTree quiesces one complete Engine-owned tree at Strategy-safe boundaries and captures a consistent portable cut. In-flight Effects settle according to their existing contract before a Process joins the barrier.
func (*Engine) Close ¶
Close rejects pending starts or restorations, Processes whose result publication or parent/child bookkeeping is incomplete, and trees that still own asynchronous work or a freeze. Await joins a Process's bookkeeping; callers must establish this completion before closing the Engine. Once closing begins, the Engine drains accepted Delta delivery and stops observation workers. Canceling ctx stops only this caller's wait; it does not interrupt that owned shutdown. A later Close joins the same shutdown. Concurrent callers join the same closure; existing handles retain results and RuntimeErrors for later reads.
func (*Engine) FlushDeltas ¶
FlushDeltas provides the ordering barrier needed before publishing a final value that must not overtake accepted streaming observations. Dropped Deltas remain lost because flushing cannot strengthen best-effort delivery. Closing the Engine prevents new flush barriers, even when no listeners are configured.
func (*Engine) InspectTree ¶ added in v0.16.0
InspectTree samples a registered root tree without freezing it or waiting for storage acknowledgment. It remains available during a commit, while a freeze is acquired or held, and after the owner stops or Engine.Close returns. ReleaseTree removes the lookup; an overlapping inspection may return its earlier valid sample. ctx bounds both admission and response waiting. The owner never calls user execution code to construct a report. Dependencies must still return in bounded time: synchronous EventListeners must not query or control their own tree. Query failures are returned as errors; runtime failures are reported through ProcessInspection.RuntimeError.
func (*Engine) ObservationFailures ¶
func (e *Engine) ObservationFailures() ObservationFailureCounts
func (*Engine) ReleaseTree ¶ added in v0.15.0
ReleaseTree waits for the complete root tree to settle and removes its in-memory registry entries and execution state. It does not cancel work or delete Host persistence. Capture any required TreeSnapshot before releasing. Existing Process handles retain their Result or RuntimeError; Engine.Process and tree operations no longer find the released identities. Canceling ctx before settlement leaves the tree registered and usable.
func (*Engine) RestoreTree ¶
func (e *Engine) RestoreTree( ctx context.Context, rootDeployment Deployment, snapshot TreeSnapshot, ) (*Process, error)
RestoreTree recreates a complete Process tree from one strict TreeSnapshot. rootDeployment must exactly bind the captured root; same-reference children reuse it, while other exact references are resolved through EngineConfig's DeploymentResolver. Registration is all-or-nothing within this Engine. Committed and prepared candidate states must both restore through their exact Definition before registration, durability activation, or Effect dispatch. Both completed and prepared completion outputs must satisfy that Definition's output schema before admission.
type EngineConfig ¶
type EngineConfig struct {
// TreeDurability makes publication wait for acknowledgment of a recoverable
// tree. Nil selects ephemeral execution without storage acknowledgment.
TreeDurability TreeDurability
// ProcessStartOutcomeAcknowledger optionally accepts initialization outcomes
// before publication. Its acknowledgment is separate from TreeDurability;
// nil omits this Host acceptance step.
ProcessStartOutcomeAcknowledger ProcessStartOutcomeAcknowledger
// Exact local bindings prevent restoration from silently selecting different
// behavior. Same-Deployment recursion needs no resolver.
DeploymentResolver DeploymentResolver
// ProcessAdmitter optionally applies Host policy before root or child
// initialization. Nil admits every start that satisfies Engine constraints.
ProcessAdmitter ProcessAdmitter
// EventListeners receive synchronous Framework facts. An empty slice disables
// delivery. Callbacks must be bounded and must not query or control their tree.
EventListeners []EventListener
// DeltaListeners receive queued, best-effort Strategy increments. An empty
// slice disables delivery. Callbacks run serially and must return so Engine
// shutdown can drain the queue and join its delivery worker.
DeltaListeners []DeltaListener
// A bounded queue prevents slow listeners from retaining unlimited Deltas.
// Zero selects the library default; negative capacities are invalid.
DeltaBufferCapacity int
// Zero fields inherit DefaultLimits so partial overrides still produce
// complete per-Process resource bounds.
Limits Limits
// TreeLimits bounds descendant count, depth, and active children. Zero fields
// inherit DefaultTreeLimits independently of per-Process Limits.
TreeLimits TreeLimits
// Children receive only subsets of root authority so composition cannot
// escalate privileges through a child Effect.
Capabilities CapabilitySet
}
EngineConfig keeps scheduling and authority policy outside Deployments so a strategy cannot change Engine-wide constraints through its behavior binding.
type Event ¶
type Event struct {
// contains filtered or unexported fields
}
Event is an immutable, ordered fact published by the Framework. Observers may project or instrument it, but observer failure never changes Process state. Payload is descriptive data, never a Signal or state mutation command.
func (Event) DeltaDropped ¶
func (e Event) DeltaDropped() (DeltaDroppedFact, bool)
DeltaDropped returns the typed loss fact for EventDeltaDropped.
func (Event) DeploymentRef ¶
func (e Event) DeploymentRef() DeploymentRef
DeploymentRef returns the exact execution binding that emitted the fact.
func (Event) EffectFinished ¶
func (e Event) EffectFinished() (EffectFinishedFact, bool)
EffectFinished returns the typed settlement fact for EventEffectFinished.
func (Event) EffectID ¶
EffectID returns the related Effect identity and true when this is an Effect fact.
func (Event) EffectStarted ¶
func (e Event) EffectStarted() (EffectStartedFact, bool)
EffectStarted returns the typed target fact for EventEffectStarted.
func (Event) MarshalJSON ¶
func (Event) OccurredAt ¶
OccurredAt returns when the fact occurred.
func (Event) Payload ¶
func (e Event) Payload() json.RawMessage
Payload returns an independently owned descriptive payload.
func (Event) Phase ¶
func (e Event) Phase() EventPhase
Phase returns whether the fact describes an attempt or committed state.
func (Event) ProcessFinished ¶
func (e Event) ProcessFinished() (ProcessFinishedFact, bool)
ProcessFinished returns the typed terminal fact for EventProcessFinished.
func (Event) ProcessSequence ¶
ProcessSequence returns the Process-local publication order within one tree runtime activation, starting at one. Restoration starts a new sequence; publication progress is observation state and is not part of a TreeSnapshot.
func (Event) Relation ¶
func (e Event) Relation() ProcessRelation
Relation returns the Process tree location that emitted the fact.
func (Event) RuntimeStopped ¶ added in v0.16.0
func (e Event) RuntimeStopped() (RuntimeStoppedFact, bool)
RuntimeStopped returns the typed instance failure for EventRuntimeStopped.
func (Event) SignalAccepted ¶
func (e Event) SignalAccepted() (SignalAcceptedFact, bool)
SignalAccepted returns the typed delivery fact for EventSignalAccepted.
func (Event) StepCommitted ¶
func (e Event) StepCommitted() (StepCommittedFact, bool)
StepCommitted returns the typed state fact for EventStepCommitted.
func (Event) StepFinished ¶
func (e Event) StepFinished() (StepFinishedFact, bool)
StepFinished returns the typed attempt fact for EventStepFinished.
func (Event) StepSequence ¶
StepSequence returns the one-based Step sequence and true, or zero and false for a Process fact outside a Step.
func (Event) TreeIncarnationID ¶
func (e Event) TreeIncarnationID() (TreeIncarnationID, bool)
TreeIncarnationID returns the active durable writer that emitted this event. Events from ephemeral trees return false.
func (*Event) UnmarshalJSON ¶
type EventListener ¶
type EventListener interface {
// OnEvent receives one committed or attempted Framework fact in increasing
// ProcessSequence for its Process within one tree runtime activation. A
// restored nonterminal Process starts with EventProcessRestored; durable
// activations also carry distinct TreeIncarnationIDs. Different tree runtimes
// may call the listener concurrently. It runs synchronously on the
// observed tree's owner, so it must return in bounded time without querying or
// controlling that tree, or calling Process.Await on it. Calls using this
// context, or a derived context, return [ErrListenerReentrancy] while the
// callback is active. The restriction ends when this invocation returns,
// including after a panic. Calls to other trees must still return in bounded
// time; distinct owners do not prevent cyclic waits between callbacks.
// The listener has no veto or acknowledgment authority.
OnEvent(ctx context.Context, event Event)
}
EventListener observes ordered Framework facts. Panics are isolated from Process execution and never alter committed state. Implementations must return in bounded time and must not query or control the observed tree.
type EventListenerFunc ¶
EventListenerFunc adapts a plain function to the event listener interface. A listener observes and must not steer execution, so the signature returns nothing to make that boundary hard to violate by accident.
type EventPhase ¶
type EventPhase string
EventPhase distinguishes runtime observations from facts supported by authoritative Process state. Durable trees publish committed facts only after TreeDurability acknowledges the resulting tree state. Attempt facts do not assert a committed Process state change.
const ( // EventPhaseInvalid is the invalid zero value. EventPhaseInvalid EventPhase = "" // EventPhaseAttempt identifies runtime work without a state commit guarantee. EventPhaseAttempt EventPhase = "attempt" // EventPhaseCommitted identifies a fact whose resulting state is acknowledged. EventPhaseCommitted EventPhase = "committed" )
func (EventPhase) String ¶
func (e EventPhase) String() string
func (EventPhase) Valid ¶
func (e EventPhase) Valid() bool
type Execution ¶
type Execution interface {
// Step reduces the current private state and the supplied ordered Signal
// prefix into one candidate Transition. It must honor ctx for bounded CPU
// work, perform no I/O, consume no hidden input, and never retain signals.
// The Engine serializes calls for one Execution.
Step(ctx context.Context, signals []Signal) (Transition, error)
// Snapshot returns a complete, independently owned state from
// which Definition.Restore can reproduce the current Execution exactly. It
// must fail rather than omit state required for deterministic continuation.
Snapshot() (ExecutionState, error)
}
Execution is the single Strategy-owned state machine inside one Process. Step must be a bounded, deterministic state reduction over the current state and the supplied Signal prefix. It must not perform external I/O, read clock, random or global state, or start ownerless goroutines. External operations are returned as Effects. Snapshot must fail rather than return partial state.
The Engine is the sole caller and never invokes Step concurrently for the same Execution. If Step or Snapshot fails, the instance is discarded and may only be rebuilt from the committed ExecutionState.
type ExecutionState ¶
type ExecutionState struct {
// contains filtered or unexported fields
}
ExecutionState is an immutable envelope owned by one Execution Strategy. The Engine persists and returns Payload without interpreting it. Its zero value is invalid.
func NewExecutionState ¶
func NewExecutionState(kind string, payload json.RawMessage) (ExecutionState, error)
NewExecutionState pairs a strategy kind with an opaque payload. The kind exists so a snapshot can be rejected when restored into the wrong strategy; the payload stays opaque so adding a strategy never widens the kernel.
func (ExecutionState) Kind ¶
func (e ExecutionState) Kind() string
Kind returns the Strategy that exclusively interprets Payload.
func (ExecutionState) MarshalJSON ¶
func (e ExecutionState) MarshalJSON() ([]byte, error)
func (ExecutionState) Payload ¶
func (e ExecutionState) Payload() json.RawMessage
Payload returns an independently owned copy of the opaque Strategy state.
func (*ExecutionState) UnmarshalJSON ¶
func (e *ExecutionState) UnmarshalJSON(data []byte) error
func (ExecutionState) Valid ¶
func (e ExecutionState) Valid() bool
type Failure ¶
type Failure struct {
// contains filtered or unexported fields
}
Failure separates stable codes from diagnostic text so wording changes cannot alter control flow. Its bounded UTF-8 message must survive snapshot JSON and must exclude secrets.
func NewFailure ¶
func NewFailure(kind FailureKind, code, message string) (Failure, error)
NewFailure requires a kind and code alongside the message so callers classify failures programmatically. Matching on message text is what makes error handling break on wording changes, and it does not survive the snapshot round trip. Message must be trimmed, valid UTF-8 and contain at most 4096 bytes.
func (Failure) Kind ¶
func (f Failure) Kind() FailureKind
func (Failure) MarshalJSON ¶
func (*Failure) UnmarshalJSON ¶
type FailureKind ¶
type FailureKind string
FailureKind stays independent of retryability so classifying a failure cannot silently select a recovery or business policy.
const ( FailureKindInvalid FailureKind = "" FailureKindExecution FailureKind = "execution" FailureKindContract FailureKind = "contract" FailureKindExternal FailureKind = "external" FailureKindPanic FailureKind = "panic" )
func (FailureKind) String ¶
func (f FailureKind) String() string
func (FailureKind) Valid ¶
func (f FailureKind) Valid() bool
type Input ¶
type Input struct {
// contains filtered or unexported fields
}
Input is the immutable JSON value used to start a Process. Its zero value is invalid. ParseInput and EncodeInput take ownership by copying and normalizing their input.
func EncodeInput ¶
EncodeInput converts a typed value into an independently owned Input.
Example ¶
package main
import (
"fmt"
"github.com/Tangerg/scope/agent"
)
func main() {
type request struct {
Topic string `json:"topic"`
}
input, err := agent.EncodeInput(request{Topic: "agent runtimes"})
if err != nil {
panic(err)
}
decoded, err := input.Decode[request]()
if err != nil {
panic(err)
}
fmt.Println(decoded.Topic, input.Valid())
}
Output: agent runtimes true
func ParseInput ¶
func ParseInput(data json.RawMessage) (Input, error)
ParseInput validates one JSON value and returns an independently owned Input.
func (Input) Decode ¶
Decode strictly decodes i into a typed value. Unknown object fields are rejected when T is a struct.
func (Input) JSON ¶
func (i Input) JSON() json.RawMessage
JSON returns an independently owned JSON representation.
func (Input) MarshalJSON ¶
func (*Input) UnmarshalJSON ¶
type Limits ¶
type Limits struct {
// MaxSteps bounds committed Steps.
MaxSteps uint64 `json:"max_steps"`
// MaxEffects bounds Effects prepared across all Steps.
MaxEffects uint64 `json:"max_effects"`
// MaxSignals bounds all accepted external and Engine-generated Signals.
MaxSignals uint64 `json:"max_signals"`
// MaxPendingSignals bounds the current unconsumed mailbox suffix and the
// suffix after the prepared Step consumes inputs and appends settlements.
// Every arriving Signal preserves both bounds regardless of its source.
MaxPendingSignals uint64 `json:"max_pending_signals"`
}
Limits bounds Framework-owned execution growth. Zero-valued fields in EngineConfig inherit DefaultLimits; ProcessSnapshot stores effective non-zero values so restoration preserves the same execution contract.
func DefaultLimits ¶
func DefaultLimits() Limits
DefaultLimits returns conservative hard bounds for one Process.
type ObservationFailureCounts ¶
type ObservationFailureCounts struct {
// contains filtered or unexported fields
}
ObservationFailureCounts is an immutable snapshot of listener panics isolated by one Engine. Counts are monotonic and saturate at math.MaxUint64.
func (ObservationFailureCounts) DeltaListenerPanics ¶
func (o ObservationFailureCounts) DeltaListenerPanics() uint64
func (ObservationFailureCounts) EventListenerPanics ¶
func (o ObservationFailureCounts) EventListenerPanics() uint64
type Output ¶
type Output struct {
// contains filtered or unexported fields
}
Output is the immutable final semantic result of a completed Process. Its zero value is invalid and it never represents streamed Delta content.
func EncodeOutput ¶
EncodeOutput converts a typed value into an independently owned Output.
func ParseOutput ¶
func ParseOutput(data json.RawMessage) (Output, error)
ParseOutput validates one JSON value and returns an independently owned Output.
func (Output) Decode ¶
Decode strictly decodes o into a typed value. Unknown object fields are rejected when T is a struct.
func (Output) JSON ¶
func (o Output) JSON() json.RawMessage
JSON returns an independently owned JSON representation.
func (Output) MarshalJSON ¶
func (*Output) UnmarshalJSON ¶
type Process ¶
type Process struct {
// contains filtered or unexported fields
}
Process is an Engine-issued handle to one managed execution. Its fields and construction remain private so a caller cannot create a second lifecycle owner. Identity and allocation are immutable; Engine.InspectTree owns live inspection. Control methods submit requests to the owning tree runtime. Except for RequestCancellation, ctx bounds both submission and response waiting. Once a command enters the runtime queue, canceling ctx does not revoke it. A context already canceled before submission never admits a command.
func (*Process) Await ¶
Await waits for the immutable terminal result and the Engine's immediate parent/child bookkeeping for that termination. Canceling ctx stops only the wait; Process cancellation is explicit or follows the context passed to Start. A durability failure stops this instance and returns a RuntimeError with no Result. A failed logical execution returns a valid Result and nil error.
func (*Process) Budget ¶
Budget returns the fixed non-renewable allocation assigned to this Process.
func (*Process) Capabilities ¶
func (p *Process) Capabilities() CapabilitySet
Capabilities returns the immutable authority set assigned to this Process.
func (*Process) DeliverSignals ¶
func (p *Process) DeliverSignals(ctx context.Context, requests ...SignalRequest) (accepted bool, err error)
DeliverSignals submits one or more immutable Strategy inputs as an ordered, atomic batch. Unaddressed input queues for the next Strategy-safe Step, including while Paused or waiting for child completion. It never resumes either state by itself. An externally addressable wait requires an answer. An addressed answer while Waiting must name the current WaitID; any other external wait answer returns ErrSignalRejected. The batch is accepted or the mailbox remains unchanged. Reusing a SignalID with different normalized payload bytes or a different WaitID returns ErrSignalConflict. If any SignalID repeats with identical content, accepted is false with nil error and the whole batch is unchanged, including resource usage. In durable mode, accepted is true only after the mailbox and budget changes commit to the authoritative tree head. A caller timeout does not revoke an admitted command; retry the identical batch to reconcile uncertain delivery.
func (*Process) DeploymentRef ¶
func (p *Process) DeploymentRef() DeploymentRef
DeploymentRef returns the exact Definition and dispatcher binding identity.
func (*Process) Kill ¶
Kill records the Engine control plane's highest-priority terminal intent. It does not silently abandon an in-flight Effect; settlement finishes first. A nil error acknowledges the local intent. Await establishes whether the resulting termination committed or this instance stopped with a RuntimeError.
func (*Process) Pause ¶
Pause requests a scheduling pause at the next safe Step boundary. An in-flight Effect is allowed to settle before the pause becomes visible. A nil error acknowledges the local control intent, not its durable publication or completion; Engine.InspectTree reports StatusPaused only after a tree commit acknowledges the paused state in durable mode.
func (*Process) Relation ¶
func (p *Process) Relation() ProcessRelation
Relation returns the immutable parent/root/depth location assigned by the Engine. It is a root relation for Processes created through Engine.Start.
func (*Process) RequestCancellation ¶
RequestCancellation submits a caller-owned cancellation intent. A nil error means the request entered the owning tree runtime's queue; it does not mean the Process has reached a safe boundary or become terminal. Once submitted, ctx cancellation cannot revoke the request. The first committed cancellation intent maps to StatusCanceled with a host-cancellation cause. Active descendants receive parent termination through the normal child lifecycle. A surviving parent receives the ordinary child-completion Signal and its Strategy decides how to continue. Await reports this Process's acknowledged terminal result; every descendant retains its own settlement.
func (*Process) ResolveUnknownEffect ¶
func (p *Process) ResolveUnknownEffect(ctx context.Context, settlement Settlement) error
ResolveUnknownEffect supplies a definite result after an Effect attempt became unknown. The Engine never converts unknown into retry or success implicitly.
func (*Process) Resume ¶
Resume makes an explicitly Paused Process schedulable again. External waits require an answer addressed to their WaitID; child waits require Framework child completion. Resume does not satisfy either wait. A nonterminal Process that is not Paused returns ErrInvalidProcessControl. A nil error acknowledges local resumption. Subsequent durable boundaries publish the resumed state before reporting their own acknowledgments.
type ProcessAdmission ¶
type ProcessAdmission struct {
// contains filtered or unexported fields
}
ProcessAdmission is the immutable Framework-owned information supplied to a ProcessAdmitter immediately before one root or child Process starts. It does not expose Input, Execution, Dispatcher, product identity, or Host state.
func (ProcessAdmission) Budget ¶
func (p ProcessAdmission) Budget() Budget
Budget returns the prospective Process's fixed non-renewable allocation.
func (ProcessAdmission) Capabilities ¶
func (p ProcessAdmission) Capabilities() CapabilitySet
Capabilities returns the prospective Process's immutable authority set.
func (ProcessAdmission) DeploymentRef ¶
func (p ProcessAdmission) DeploymentRef() DeploymentRef
DeploymentRef returns the exact prospective Deployment identity.
func (ProcessAdmission) Descriptor ¶
func (p ProcessAdmission) Descriptor() Descriptor
Descriptor returns the prospective Definition's static contract.
func (ProcessAdmission) Relation ¶
func (p ProcessAdmission) Relation() ProcessRelation
Relation returns the prospective Process identity and tree location.
func (ProcessAdmission) Valid ¶
func (p ProcessAdmission) Valid() bool
type ProcessAdmitter ¶
type ProcessAdmitter interface {
// Admit decides whether the immutable prospective Process may initialize.
// Returning nil accepts only the supplied identity and resources; it cannot
// enlarge Budget or Capabilities. Returning an error prevents initialization
// and publication. Implementations honor ctx, are bounded and concurrency-
// safe, and must tolerate the same prospective identity after recovery.
Admit(ctx context.Context, admission ProcessAdmission) error
}
ProcessAdmitter decides whether one prospective root or child Process may initialize. Implementations may coordinate caller-owned external admission work, but must not create a Process, mutate the admission, or allocate Framework resources. A prepared Step may replay the same child admission with the same prospective Process identity after recovery.
Implementations must respect ctx, return in bounded time, be safe for concurrent calls when shared, and must not re-enter the Engine or a Process. Framework identity is stable, but persistence, transactionality, charging, and business idempotency remain implementation responsibilities. Returning an error rejects only this prospective Process. Budget allocation, capability attenuation, and tree limits remain Engine invariants and cannot be changed by an admitter. Every accepted admission concludes with exactly one ProcessStartOutcome when an acknowledger is configured. Restore repeats neither admission nor its outcome for a captured Process.
type ProcessAdmitterFunc ¶
type ProcessAdmitterFunc func(ctx context.Context, admission ProcessAdmission) error
ProcessAdmitterFunc adapts a plain function to the admitter interface, so a host quota or policy check does not require a named type.
func (ProcessAdmitterFunc) Admit ¶
func (p ProcessAdmitterFunc) Admit(ctx context.Context, admission ProcessAdmission) error
type ProcessFinishedFact ¶
type ProcessFinishedFact struct {
// contains filtered or unexported fields
}
ProcessFinishedFact is the immutable terminal fact carried by a finished Process Event. Usage is the authoritative Framework-owned terminal usage.
func (ProcessFinishedFact) Cause ¶
func (p ProcessFinishedFact) Cause() TerminationCause
func (ProcessFinishedFact) Failure ¶
func (p ProcessFinishedFact) Failure() (FailureKind, string, bool)
func (ProcessFinishedFact) Status ¶
func (p ProcessFinishedFact) Status() Status
func (ProcessFinishedFact) Usage ¶
func (p ProcessFinishedFact) Usage() Usage
func (ProcessFinishedFact) Valid ¶
func (p ProcessFinishedFact) Valid() bool
type ProcessID ¶
type ProcessID struct {
// contains filtered or unexported fields
}
ProcessID is the stable identity of one Engine-owned Process.
func ParseProcessID ¶
ParseProcessID validates an externally encoded Process identity.
func (ProcessID) MarshalText ¶
func (*ProcessID) UnmarshalText ¶
type ProcessInspection ¶ added in v0.16.0
type ProcessInspection struct {
Snapshot ProcessSnapshot
Work ProcessWork
Stale bool
EffectID EffectID
RuntimeError *RuntimeError
}
ProcessInspection combines an existing execution capture with current work. A stale job is still draining but cannot publish its result. RuntimeError reports an instance failure; its unresolved Effects may exceed the Unknown settlements already present in Snapshot.
type ProcessRelation ¶
type ProcessRelation struct {
// contains filtered or unexported fields
}
ProcessRelation is the immutable location of one Process in an Engine-owned tree. Roots identify themselves as RootID at depth zero. Children have one parent and one stable ChildKey; a Process never has multiple parents.
func (ProcessRelation) ChildKey ¶
func (p ProcessRelation) ChildKey() (ChildKey, bool)
ChildKey returns the parent-scoped logical child identity and true for a child, or zero and false for a root.
func (ProcessRelation) Depth ¶
func (p ProcessRelation) Depth() uint32
Depth returns zero for a root and parent depth plus one for every child.
func (ProcessRelation) IsRoot ¶
func (p ProcessRelation) IsRoot() bool
IsRoot reports whether p identifies the root of its tree.
func (ProcessRelation) ParentID ¶
func (p ProcessRelation) ParentID() (ProcessID, bool)
ParentID returns the direct parent and true for a child, or zero and false for a root.
func (ProcessRelation) ProcessID ¶
func (p ProcessRelation) ProcessID() ProcessID
ProcessID returns the Process located by this relation.
func (ProcessRelation) RootID ¶
func (p ProcessRelation) RootID() ProcessID
RootID returns the stable root identity shared by the complete Process tree.
func (ProcessRelation) Valid ¶
func (p ProcessRelation) Valid() bool
type ProcessSnapshot ¶
type ProcessSnapshot struct {
// contains filtered or unexported fields
}
ProcessSnapshot is an immutable diagnostic capture of one Engine-owned Process. Strategy state and Effect payloads remain opaque. A ProcessSnapshot is not a recovery unit; only a complete TreeSnapshot can be restored. Parsing validates the captured state, not storage acknowledgment. Engine.InspectTree identifies the acknowledged head of its durable captures.
func ParseProcessSnapshot ¶
func ParseProcessSnapshot(data json.RawMessage) (ProcessSnapshot, error)
ParseProcessSnapshot strictly validates one Process snapshot wire value, including single-answer wait history and an open, unanswered current wait when the Process is Waiting. Prepared Effects must fit the captured Process capability grant.
func (ProcessSnapshot) Budget ¶
func (p ProcessSnapshot) Budget() Budget
Budget returns the Process work allocation captured by this snapshot.
func (ProcessSnapshot) Capabilities ¶
func (p ProcessSnapshot) Capabilities() CapabilitySet
Capabilities returns the Process authority set captured by this snapshot.
func (ProcessSnapshot) CommittedExecutionState ¶
func (p ProcessSnapshot) CommittedExecutionState() ExecutionState
CommittedExecutionState returns the latest committed opaque Strategy state. A prepared candidate, when present, remains an uncommitted Engine detail. Only the owning Definition or its typed inspection helpers may interpret the returned state's payload.
func (ProcessSnapshot) DeploymentRef ¶
func (p ProcessSnapshot) DeploymentRef() DeploymentRef
DeploymentRef returns the exact execution binding required for restoration.
func (ProcessSnapshot) JSON ¶
func (p ProcessSnapshot) JSON() json.RawMessage
JSON returns an independently owned snapshot representation.
func (ProcessSnapshot) MarshalJSON ¶
func (p ProcessSnapshot) MarshalJSON() ([]byte, error)
func (ProcessSnapshot) ProcessID ¶
func (p ProcessSnapshot) ProcessID() ProcessID
ProcessID returns the captured Process identity.
func (ProcessSnapshot) Relation ¶
func (p ProcessSnapshot) Relation() ProcessRelation
Relation returns the immutable parent/root/depth location captured with the Process.
func (ProcessSnapshot) Status ¶
func (p ProcessSnapshot) Status() Status
Status returns the captured common lifecycle state.
func (ProcessSnapshot) UnknownEffectIDs ¶ added in v0.16.0
func (p ProcessSnapshot) UnknownEffectIDs() []EffectID
UnknownEffectIDs returns Effects whose captured settlement requires explicit resolution. RuntimeError separately owns outcomes an instance could not confirm.
func (*ProcessSnapshot) UnmarshalJSON ¶
func (p *ProcessSnapshot) UnmarshalJSON(data []byte) error
func (ProcessSnapshot) Usage ¶ added in v0.16.0
func (p ProcessSnapshot) Usage() Usage
Usage returns the Framework counters recorded in this capture.
func (ProcessSnapshot) Valid ¶
func (p ProcessSnapshot) Valid() bool
func (ProcessSnapshot) WaitID ¶
func (p ProcessSnapshot) WaitID() (WaitID, bool)
WaitID returns the current Engine-minted wait identity and true when the captured Process is Waiting.
func (ProcessSnapshot) WaitKind ¶ added in v0.16.0
func (p ProcessSnapshot) WaitKind() (WaitKind, bool)
WaitKind distinguishes Host input from Framework child completion while the captured Process is Waiting. It derives from the existing wait authority.
type ProcessStartOutcome ¶
type ProcessStartOutcome struct {
// contains filtered or unexported fields
}
ProcessStartOutcome separates initialization acceptance from publication: persistence can still fail after a started outcome is accepted.
func (ProcessStartOutcome) Admission ¶
func (p ProcessStartOutcome) Admission() ProcessAdmission
func (ProcessStartOutcome) Failure ¶
func (p ProcessStartOutcome) Failure() (Failure, bool)
func (ProcessStartOutcome) Status ¶
func (p ProcessStartOutcome) Status() ProcessStartOutcomeStatus
func (ProcessStartOutcome) Valid ¶
func (p ProcessStartOutcome) Valid() bool
type ProcessStartOutcomeAcknowledger ¶
type ProcessStartOutcomeAcknowledger interface {
// AcknowledgeProcessStartOutcome must return before publication so a Host
// can reject initialization without exposing a usable Process.
AcknowledgeProcessStartOutcome(ctx context.Context, outcome ProcessStartOutcome) error
}
ProcessStartOutcomeAcknowledger lets a Host close each accepted admission even when initialization fails before a Process exists. Rejecting a started outcome prevents publication; accepting it does not guarantee later persistence. Implementations must be bounded, concurrency-safe, idempotent by admission identity, and must not re-enter Engine or Process, because initialization waits for this call. Restore produces no outcome because it does not initialize.
type ProcessStartOutcomeAcknowledgerFunc ¶
type ProcessStartOutcomeAcknowledgerFunc func( ctx context.Context, outcome ProcessStartOutcome, ) error
func (ProcessStartOutcomeAcknowledgerFunc) AcknowledgeProcessStartOutcome ¶
func (p ProcessStartOutcomeAcknowledgerFunc) AcknowledgeProcessStartOutcome( ctx context.Context, outcome ProcessStartOutcome, ) error
type ProcessStartOutcomeStatus ¶
type ProcessStartOutcomeStatus string
const ( ProcessStartOutcomeStatusInvalid ProcessStartOutcomeStatus = "" ProcessStartOutcomeStatusStarted ProcessStartOutcomeStatus = "started" ProcessStartOutcomeStatusAborted ProcessStartOutcomeStatus = "aborted" )
func (ProcessStartOutcomeStatus) String ¶
func (p ProcessStartOutcomeStatus) String() string
func (ProcessStartOutcomeStatus) Valid ¶
func (p ProcessStartOutcomeStatus) Valid() bool
type ProcessWork ¶ added in v0.16.0
type ProcessWork string
ProcessWork describes work owned by the current runtime, independently of the lifecycle state in its last acknowledged snapshot. Queued means waiting for an owner turn; a commit or freeze can still block it. Idle means no queued work or job, not a terminal Process or a successful execution.
const ( ProcessWorkIdle ProcessWork = "idle" ProcessWorkQueued ProcessWork = "queued" ProcessWorkStep ProcessWork = "step" ProcessWorkDispatch ProcessWork = "dispatch" ProcessWorkChildStart ProcessWork = "child_start" )
type ReplayPolicy ¶
type ReplayPolicy string
ReplayPolicy states whether a Dispatcher can prove that repeating an Effect with the same EffectID is the same logical external operation. It does not claim transactionality or allow replay under a different identity.
const ( // ReplayPolicyInvalid is the invalid zero value. ReplayPolicyInvalid ReplayPolicy = "" // ReplayPolicyNever forbids automatic replay after an unknown settlement. ReplayPolicyNever ReplayPolicy = "never" // ReplayPolicySameIdentity permits replay only with the original EffectID. ReplayPolicySameIdentity ReplayPolicy = "same_identity" )
func (ReplayPolicy) String ¶
func (r ReplayPolicy) String() string
func (ReplayPolicy) Valid ¶
func (r ReplayPolicy) Valid() bool
type Result ¶
type Result struct {
// contains filtered or unexported fields
}
Result is the immutable terminal outcome of one Process. A failed or canceled execution is represented by Termination, not by Await's error.
func (Result) FinishedAt ¶
FinishedAt returns the committed terminal time.
func (Result) Termination ¶
func (r Result) Termination() Termination
Termination returns the stable terminal cause and optional Failure.
type RuntimeError ¶ added in v0.16.0
type RuntimeError struct {
// contains filtered or unexported fields
}
RuntimeError reports that the active writer stopped without establishing a logical Process result. The Host may reconcile storage and restore its authoritative tree head in another Engine. This error does not terminate the durable execution or authorize replay of an uncertain Effect. Engine constructs these errors; the zero value carries no runtime identity. Process methods and tree reports return independent RuntimeError values; Unwrap preserves the original cause.
func (*RuntimeError) Error ¶ added in v0.16.0
func (r *RuntimeError) Error() string
func (*RuntimeError) HeadDigest ¶ added in v0.16.0
func (r *RuntimeError) HeadDigest() Digest
HeadDigest identifies the last tree head acknowledged to this instance. The store may have advanced further if a commit response was lost or a new writer acquired ownership; recovery must read the store's authoritative head.
func (*RuntimeError) IncarnationID ¶ added in v0.16.0
func (r *RuntimeError) IncarnationID() TreeIncarnationID
IncarnationID identifies the durable writer that stopped.
func (*RuntimeError) ProcessID ¶ added in v0.16.0
func (r *RuntimeError) ProcessID() ProcessID
ProcessID identifies the affected Process handle in the stopped instance.
func (*RuntimeError) UnresolvedEffectIDs ¶ added in v0.16.0
func (r *RuntimeError) UnresolvedEffectIDs() []EffectID
UnresolvedEffectIDs returns the sorted, distinct identities whose external outcomes this instance could not establish durably. Pending Effects that were never dispatched by this instance are not added solely for a failed pending-boundary acknowledgment.
func (*RuntimeError) Unwrap ¶ added in v0.16.0
func (r *RuntimeError) Unwrap() error
Unwrap preserves the durability failure, including ownership and content conflicts, for errors.Is and errors.As.
type RuntimeStoppedFact ¶ added in v0.16.0
type RuntimeStoppedFact struct {
// contains filtered or unexported fields
}
RuntimeStoppedFact describes an instance failure, not a logical Process termination. It contains only the failure classification, never storage error messages or application payloads. Event carries the Process and incarnation.
func (RuntimeStoppedFact) FailureCode ¶ added in v0.16.0
func (r RuntimeStoppedFact) FailureCode() string
func (RuntimeStoppedFact) FailureKind ¶ added in v0.16.0
func (r RuntimeStoppedFact) FailureKind() FailureKind
func (RuntimeStoppedFact) Valid ¶ added in v0.16.0
func (r RuntimeStoppedFact) Valid() bool
type Schema ¶
type Schema struct {
// contains filtered or unexported fields
}
Schema is an immutable, resolved JSON Schema used by Framework input and output contracts. Its zero value is invalid.
func ParseSchema ¶
func ParseSchema(data json.RawMessage) (Schema, error)
ParseSchema validates and resolves one JSON Schema.
func (Schema) JSON ¶
func (s Schema) JSON() json.RawMessage
JSON returns an independently owned JSON representation.
func (Schema) MarshalJSON ¶
func (*Schema) UnmarshalJSON ¶
func (Schema) ValidateInput ¶
func (Schema) ValidateOutput ¶
type Settlement ¶
type Settlement struct {
// contains filtered or unexported fields
}
Settlement is the immutable final fact for one EffectID. Payload is owned by the Effect target and becomes opaque Signal data for the next Step. The Engine uses Status only to preserve definite versus unknown execution facts.
func NewSettlement ¶
func NewSettlement(effectID EffectID, status SettlementStatus, payload json.RawMessage) (Settlement, error)
NewSettlement binds a result to the exact effect identity it settles, so a dispatcher cannot close an effect other than the one it was given. Ordering by completion time instead would let a slow settlement overwrite a newer one.
func (Settlement) EffectID ¶
func (s Settlement) EffectID() EffectID
EffectID returns the Effect this result settles.
func (Settlement) MarshalJSON ¶
func (s Settlement) MarshalJSON() ([]byte, error)
func (Settlement) Payload ¶
func (s Settlement) Payload() json.RawMessage
Payload returns an independently owned owner-defined result.
func (Settlement) Status ¶
func (s Settlement) Status() SettlementStatus
Status returns whether the external result is definite or unknown.
func (*Settlement) UnmarshalJSON ¶
func (s *Settlement) UnmarshalJSON(data []byte) error
func (Settlement) Valid ¶
func (s Settlement) Valid() bool
type SettlementStatus ¶
type SettlementStatus string
SettlementStatus records whether an Effect definitely succeeded, definitely failed, or has an unknown external result. Unknown never implies safe retry.
const ( // SettlementStatusInvalid is the invalid zero value. SettlementStatusInvalid SettlementStatus = "" // SettlementStatusSucceeded records a definite successful outcome. SettlementStatusSucceeded SettlementStatus = "succeeded" // SettlementStatusFailed records a definite failed outcome. SettlementStatusFailed SettlementStatus = "failed" // SettlementStatusUnknown records an externally indeterminate outcome. SettlementStatusUnknown SettlementStatus = "unknown" )
func (SettlementStatus) String ¶
func (s SettlementStatus) String() string
func (SettlementStatus) Valid ¶
func (s SettlementStatus) Valid() bool
type Signal ¶
type Signal struct {
// contains filtered or unexported fields
}
Signal is the immutable input envelope delivered by the Engine to an Execution. Dispatcher and ordinary wait payloads belong exclusively to the Strategy; Framework composition payloads are decoded only through their public typed helpers. SignalID identifies delivery, while an optional WaitID identifies the Engine-created wait target.
func (Signal) MarshalJSON ¶
func (Signal) Payload ¶
func (s Signal) Payload() json.RawMessage
Payload returns an independently owned copy. Strategy-owned payloads are interpreted only by their Strategy; Framework-owned payloads should be read through the corresponding typed parser rather than decoded ad hoc.
func (*Signal) UnmarshalJSON ¶
type SignalAcceptedFact ¶
type SignalAcceptedFact struct {
// contains filtered or unexported fields
}
SignalAcceptedFact is the immutable delivery identity carried by an accepted Signal Event. WaitID is present only for a wait-addressed Signal.
func (SignalAcceptedFact) SignalID ¶
func (s SignalAcceptedFact) SignalID() SignalID
func (SignalAcceptedFact) Valid ¶
func (s SignalAcceptedFact) Valid() bool
func (SignalAcceptedFact) WaitID ¶
func (s SignalAcceptedFact) WaitID() (WaitID, bool)
type SignalID ¶
type SignalID struct {
// contains filtered or unexported fields
}
SignalID is the stable identity used to deduplicate one Signal delivery.
func ParseSignalID ¶
ParseSignalID validates an externally supplied Signal delivery identity. Parsing does not accept or deliver the Signal.
func (SignalID) MarshalText ¶
func (*SignalID) UnmarshalText ¶
type SignalRequest ¶
type SignalRequest struct {
// contains filtered or unexported fields
}
SignalRequest is an immutable request to deliver Strategy-owned input to a Process. ID supplies caller-stable deduplication. WaitID is zero for ordinary next-boundary input and Engine-minted for an external wait answer.
func NewSignalRequest ¶
func NewSignalRequest(id SignalID, waitID WaitID, payload json.RawMessage) (SignalRequest, error)
NewSignalRequest requires a caller-chosen signal identity so that resubmitting the same delivery is exactly one logical consumption. Without it, a host retry after an ambiguous network failure would be indistinguishable from a second answer.
func (SignalRequest) ID ¶
func (s SignalRequest) ID() SignalID
ID returns the stable delivery and deduplication identity.
func (SignalRequest) Payload ¶
func (s SignalRequest) Payload() json.RawMessage
Payload returns an independently owned Strategy-defined value.
func (SignalRequest) Valid ¶
func (s SignalRequest) Valid() bool
func (SignalRequest) WaitID ¶
func (s SignalRequest) WaitID() (WaitID, bool)
WaitID returns the addressed wait and true, or a zero WaitID and false.
type Status ¶
type Status string
Status is the complete common lifecycle state of a Process. Strategy-specific conditions such as a Planning no-plan result do not add common statuses.
const ( // StatusInvalid is the invalid zero value. StatusInvalid Status = "" // StatusNotStarted identifies a Process before execution begins. StatusNotStarted Status = "not_started" // StatusRunning identifies a Process eligible to advance. StatusRunning Status = "running" // StatusWaiting identifies a Process awaiting a WaitID-addressed Signal. StatusWaiting Status = "waiting" // StatusPaused identifies an explicitly suspended Process. StatusPaused Status = "paused" // StatusCompleted identifies successful semantic completion. StatusCompleted Status = "completed" // StatusFailed identifies terminal execution failure. StatusFailed Status = "failed" // StatusCanceled identifies cooperative cancellation. StatusCanceled Status = "canceled" // StatusTimedOut identifies deadline termination. StatusTimedOut Status = "timed_out" // StatusKilled identifies an explicit Engine kill. StatusKilled Status = "killed" )
func (Status) MarshalText ¶
func (*Status) UnmarshalText ¶
type StepCommittedFact ¶
type StepCommittedFact struct {
// contains filtered or unexported fields
}
StepCommittedFact is the Process status installed by one committed Step.
func (StepCommittedFact) Status ¶
func (s StepCommittedFact) Status() Status
func (StepCommittedFact) Valid ¶
func (s StepCommittedFact) Valid() bool
type StepFinishedFact ¶
type StepFinishedFact struct {
// contains filtered or unexported fields
}
StepFinishedFact is the immutable outcome of one Execution.Step attempt.
func (StepFinishedFact) Duration ¶
func (s StepFinishedFact) Duration() time.Duration
func (StepFinishedFact) Status ¶
func (s StepFinishedFact) Status() StepStatus
func (StepFinishedFact) Valid ¶
func (s StepFinishedFact) Valid() bool
type StepStatus ¶
type StepStatus string
StepStatus reports whether one Step reduction succeeded, and is deliberately narrower than Status: a failed Step does not by itself terminate a Process, because the terminal decision also depends on recorded control intent.
const ( StepStatusSucceeded StepStatus = "succeeded" StepStatusFailed StepStatus = "failed" )
Step status is separate from Process status because a failed Step does not by itself terminate a Process; the terminal decision also weighs recorded control intent.
func (StepStatus) String ¶
func (s StepStatus) String() string
func (StepStatus) Valid ¶
func (s StepStatus) Valid() bool
type Termination ¶
type Termination struct {
// contains filtered or unexported fields
}
Termination is the immutable result of applying the terminal priority matrix.
func (Termination) Cause ¶
func (t Termination) Cause() TerminationCause
Cause returns the stable machine-readable terminal category.
func (Termination) Failure ¶
func (t Termination) Failure() (Failure, bool)
Failure returns the classified failure for StatusFailed.
func (Termination) MarshalJSON ¶
func (t Termination) MarshalJSON() ([]byte, error)
func (Termination) Reason ¶
func (t Termination) Reason() string
Reason returns a bounded diagnostic reason. Completion has an empty reason.
func (Termination) Status ¶
func (t Termination) Status() Status
Status returns the resolved terminal Process status.
func (*Termination) UnmarshalJSON ¶
func (t *Termination) UnmarshalJSON(data []byte) error
func (Termination) UnresolvedEffectIDs ¶
func (t Termination) UnresolvedEffectIDs() []EffectID
UnresolvedEffectIDs returns the canonical identities of external operations that may have occurred but were not durably resolved when the tree stopped.
func (Termination) Valid ¶
func (t Termination) Valid() bool
type TerminationCause ¶
type TerminationCause string
TerminationCause is the stable reason category of a terminal Process.
const ( // TerminationCauseInvalid is the invalid zero value. TerminationCauseInvalid TerminationCause = "" // TerminationCauseCompletion identifies successful semantic completion. TerminationCauseCompletion TerminationCause = "completion" // TerminationCauseEngineKill identifies an explicit Engine kill. TerminationCauseEngineKill TerminationCause = "engine_kill" // TerminationCauseProcessDeadline identifies the Process's own deadline. TerminationCauseProcessDeadline TerminationCause = "process_deadline" // TerminationCauseParentDeadline identifies deadline propagation from a parent. TerminationCauseParentDeadline TerminationCause = "parent_deadline" // TerminationCauseHostDeadline identifies expiry of the Host context. TerminationCauseHostDeadline TerminationCause = "host_deadline" // TerminationCauseParentCancellation identifies cancellation by a parent Process. TerminationCauseParentCancellation TerminationCause = "parent_cancellation" // TerminationCauseHostCancellation identifies cancellation by the Host context. TerminationCauseHostCancellation TerminationCause = "host_cancellation" // TerminationCauseExecutionFailure identifies an ordinary Strategy failure. TerminationCauseExecutionFailure TerminationCause = "execution_failure" // TerminationCauseContractFailure identifies a contract violation. TerminationCauseContractFailure TerminationCause = "contract_failure" // TerminationCauseExternalFailure identifies failed external infrastructure. TerminationCauseExternalFailure TerminationCause = "external_failure" // TerminationCausePanic identifies a recovered execution-boundary panic. TerminationCausePanic TerminationCause = "panic" )
func (TerminationCause) String ¶
func (t TerminationCause) String() string
func (TerminationCause) Valid ¶
func (t TerminationCause) Valid() bool
type Transition ¶
type Transition struct {
// contains filtered or unexported fields
}
Transition is an immutable candidate lifecycle intent. The Engine validates ConsumedSignals against the delivered Signal window, captures the candidate ExecutionState, and assigns EffectID values before committing anything.
func Complete ¶
func Complete(consumedSignals uint32, output Output) (Transition, error)
Complete supplies the final semantic Output. The Engine must validate it against the Definition Descriptor before committing Completed.
func Continue ¶
func Continue(consumedSignals uint32, effects ...Effect) (Transition, error)
Continue keeps the Process schedulable after consuming the stated Signal prefix. Effects are dispatched only after the Engine prepares the Step.
func Fail ¶
func Fail(consumedSignals uint32, failure Failure) (Transition, error)
Fail supplies a stable Strategy-declared failure without making the Execution instance untrusted. A Step error follows the separate discard path.
func Pause ¶
func Pause(consumedSignals uint32, reason string) (Transition, error)
Pause requests an explicit scheduling pause with a bounded diagnostic reason.
func Wait ¶
func Wait(consumedSignals uint32, waitID WaitID) (Transition, error)
Wait moves the Process to Waiting for an Engine-minted WaitID already stored in the candidate ExecutionState.
func (Transition) ConsumedSignals ¶
func (t Transition) ConsumedSignals() uint32
ConsumedSignals returns the length of the delivered Signal prefix to commit.
func (Transition) Effects ¶
func (t Transition) Effects() []Effect
Effects returns independently owned operation intents in declaration order.
func (Transition) Failure ¶
func (t Transition) Failure() (Failure, bool)
Failure returns the terminal failure for a Fail transition.
func (Transition) Kind ¶
func (t Transition) Kind() TransitionKind
Kind returns the requested lifecycle intent.
func (Transition) MarshalJSON ¶
func (t Transition) MarshalJSON() ([]byte, error)
func (Transition) Output ¶
func (t Transition) Output() (Output, bool)
Output returns the final result for a Complete transition.
func (Transition) Reason ¶
func (t Transition) Reason() (string, bool)
Reason returns the pause reason for a Pause transition.
func (*Transition) UnmarshalJSON ¶
func (t *Transition) UnmarshalJSON(data []byte) error
func (Transition) Valid ¶
func (t Transition) Valid() bool
func (Transition) WaitID ¶
func (t Transition) WaitID() (WaitID, bool)
WaitID returns the wait target for a Wait transition.
type TransitionKind ¶
type TransitionKind string
TransitionKind is the lifecycle intent produced by one bounded Step.
const ( // TransitionKindInvalid is the invalid zero value. TransitionKindInvalid TransitionKind = "" // TransitionKindContinue advances to another runnable Step. TransitionKindContinue TransitionKind = "continue" // TransitionKindWait enters an Engine-minted wait. TransitionKindWait TransitionKind = "wait" // TransitionKindPause enters an explicit scheduling pause. TransitionKindPause TransitionKind = "pause" // TransitionKindComplete commits a validated semantic Output. TransitionKindComplete TransitionKind = "complete" // TransitionKindFail commits a classified failure. TransitionKindFail TransitionKind = "fail" )
func (TransitionKind) String ¶
func (t TransitionKind) String() string
func (TransitionKind) Valid ¶
func (t TransitionKind) Valid() bool
type TreeActivation ¶
type TreeActivation struct {
// contains filtered or unexported fields
}
TreeActivation changes writer identity and recovery state together so the previous Engine cannot continue committing after restoration takes ownership.
func (TreeActivation) IncarnationID ¶
func (t TreeActivation) IncarnationID() TreeIncarnationID
func (TreeActivation) PreviousIncarnationID ¶
func (t TreeActivation) PreviousIncarnationID() TreeIncarnationID
func (TreeActivation) PreviousTreeDigest ¶
func (t TreeActivation) PreviousTreeDigest() Digest
func (TreeActivation) TreeSnapshot ¶
func (t TreeActivation) TreeSnapshot() TreeSnapshot
func (TreeActivation) Valid ¶
func (t TreeActivation) Valid() bool
type TreeCheckpoint ¶
type TreeCheckpoint struct {
// contains filtered or unexported fields
}
TreeCheckpoint keeps child publication, input acceptance, and execution progress on the same head so recovery cannot observe partially accepted work. Input and child cuts can coexist with sibling jobs because those jobs expose only committed Execution state or already recorded Effect intent.
func (TreeCheckpoint) Kind ¶
func (t TreeCheckpoint) Kind() TreeCheckpointKind
func (TreeCheckpoint) PreviousTreeDigest ¶
func (t TreeCheckpoint) PreviousTreeDigest() Digest
func (TreeCheckpoint) TreeSnapshot ¶
func (t TreeCheckpoint) TreeSnapshot() TreeSnapshot
func (TreeCheckpoint) Valid ¶
func (t TreeCheckpoint) Valid() bool
type TreeCheckpointKind ¶
type TreeCheckpointKind string
TreeCheckpointKind distinguishes absent-head creation from writer-fenced updates, and stable owner cuts from fully parked or terminal trees.
const ( TreeCheckpointInvalid TreeCheckpointKind = "" TreeCheckpointStart TreeCheckpointKind = "start" TreeCheckpointChild TreeCheckpointKind = "child" TreeCheckpointInput TreeCheckpointKind = "input" TreeCheckpointParked TreeCheckpointKind = "parked" TreeCheckpointTerminal TreeCheckpointKind = "terminal" )
func (TreeCheckpointKind) String ¶
func (t TreeCheckpointKind) String() string
func (TreeCheckpointKind) Valid ¶
func (t TreeCheckpointKind) Valid() bool
type TreeDurability ¶
type TreeDurability interface {
// ActivateTree must fence the previous writer before restored work can run.
ActivateTree(ctx context.Context, activation TreeActivation) error
// CommitEffect must keep the Effect fact and tree head atomic so recovery
// cannot disagree with the dispatch or settlement that was acknowledged.
CommitEffect(ctx context.Context, boundary EffectBoundary) error
// CommitCheckpoint must compare an absent head for start, or the current
// head otherwise, to prevent publication from overwriting another writer.
CommitCheckpoint(ctx context.Context, checkpoint TreeCheckpoint) error
}
TreeDurability keeps all recoverable state on one authoritative head so a restored writer cannot race its predecessor. Every commit must atomically compare and advance that head; accepting a duplicate requires identical content and a head that still matches the proposal. Hosts own storage, deadlines, and reconciliation when a commit response is lost.
A start checkpoint requires an absent head and a zero PreviousTreeDigest. Other checkpoints and Effects require the current incarnation and digest. Activation must replace both together to fence the previous writer before restoration can publish a Process. Initialization acknowledgment is separate because an aborted root has no execution tree to persist.
type TreeFreezePhase ¶ added in v0.16.0
type TreeFreezePhase string
TreeFreezePhase describes the current scheduling barrier. Acquiring blocks scheduling while in-flight Effects settle. Held also stops completion adoption; an in-flight Step may still be computing against its isolated state.
const ( TreeFreezeNone TreeFreezePhase = "none" TreeFreezeAcquiring TreeFreezePhase = "acquiring" TreeFreezeHeld TreeFreezePhase = "held" )
type TreeIncarnationID ¶
type TreeIncarnationID struct {
// contains filtered or unexported fields
}
TreeIncarnationID identifies the one active writer generation of a durable Process tree. Its zero value is invalid.
func ParseTreeIncarnationID ¶
func ParseTreeIncarnationID(value string) (TreeIncarnationID, error)
ParseTreeIncarnationID validates the canonical wire representation of a tree incarnation identity.
func (TreeIncarnationID) MarshalText ¶
func (t TreeIncarnationID) MarshalText() ([]byte, error)
func (TreeIncarnationID) String ¶
func (t TreeIncarnationID) String() string
func (*TreeIncarnationID) UnmarshalText ¶
func (t *TreeIncarnationID) UnmarshalText(text []byte) error
func (TreeIncarnationID) Valid ¶
func (t TreeIncarnationID) Valid() bool
type TreeInspection ¶ added in v0.16.0
type TreeInspection struct {
RootID ProcessID
IncarnationID TreeIncarnationID
HeadDigest Digest
CommitPending bool
Freeze TreeFreezePhase
Stopped bool
Processes []ProcessInspection
}
TreeInspection is a caller-owned report from one runtime owner turn. In durable mode, snapshots and HeadDigest come only from the last head this instance acknowledged. A lost response or a replacement writer may have advanced storage further. Recovery must load the authoritative stored tree. IncarnationID and HeadDigest are zero in ephemeral mode. Work and barriers describe the sampling turn and may be newer than the acknowledged snapshots. Stopped means the owner has exited after draining its work. Reports contain no recovery or scheduling authority and are not a persistence schema.
func (TreeInspection) Process ¶ added in v0.16.0
func (t TreeInspection) Process(processID ProcessID) (ProcessInspection, bool)
Process finds a published Process in the report's canonical depth/ID order.
type TreeLimits ¶
type TreeLimits struct {
// MaxDepth bounds the root-relative depth of any Process.
MaxDepth uint32 `json:"max_depth"`
// MaxChildren bounds the lifetime child count of one Process.
MaxChildren uint32 `json:"max_children"`
// MaxActiveChildren bounds concurrent non-terminal children of one Process.
MaxActiveChildren uint32 `json:"max_active_children"`
// MaxTreeProcesses bounds the lifetime Process count of one tree.
MaxTreeProcesses uint32 `json:"max_tree_processes"`
}
TreeLimits bounds structural expansion independently of per-Process work limits. Every zero field in EngineConfig inherits DefaultTreeLimits.
func DefaultTreeLimits ¶
func DefaultTreeLimits() TreeLimits
DefaultTreeLimits returns conservative structured-concurrency bounds.
func (TreeLimits) Valid ¶
func (t TreeLimits) Valid() bool
type TreeSnapshot ¶
type TreeSnapshot struct {
// contains filtered or unexported fields
}
TreeSnapshot is an immutable, portable capture of one complete Process tree. It owns Framework execution facts, a canonical content digest, and the optional active-writer identity of durable state. Persistence, transactions, revisions, and cleanup policy remain Host responsibilities.
func ParseTreeSnapshot ¶
func ParseTreeSnapshot(data json.RawMessage) (TreeSnapshot, error)
ParseTreeSnapshot validates the current wire shape and domain constraints of one complete Process tree. Unknown members are rejected. Every active child wait must have a registration belonging to its Process.
func (TreeSnapshot) Digest ¶
func (t TreeSnapshot) Digest() Digest
Digest returns the canonical content identity of this complete tree state.
func (TreeSnapshot) IncarnationID ¶
func (t TreeSnapshot) IncarnationID() (TreeIncarnationID, bool)
IncarnationID returns the active writer identity carried by a durable tree. Ephemeral snapshots return false.
func (TreeSnapshot) JSON ¶
func (t TreeSnapshot) JSON() json.RawMessage
JSON returns an independently owned tree snapshot representation.
func (TreeSnapshot) MarshalJSON ¶
func (t TreeSnapshot) MarshalJSON() ([]byte, error)
func (TreeSnapshot) ProcessSnapshots ¶
func (t TreeSnapshot) ProcessSnapshots() []ProcessSnapshot
ProcessSnapshots returns immutable captures ordered by depth and ProcessID.
func (TreeSnapshot) RootID ¶
func (t TreeSnapshot) RootID() ProcessID
RootID returns the identity of the tree's root Process.
func (*TreeSnapshot) UnmarshalJSON ¶
func (t *TreeSnapshot) UnmarshalJSON(data []byte) error
func (TreeSnapshot) Valid ¶
func (t TreeSnapshot) Valid() bool
type Usage ¶
type Usage struct {
// CommittedSteps counts finalized Steps.
CommittedSteps uint64 `json:"committed_steps"`
// PreparedEffects counts stable logical Effect identities, not replay attempts.
PreparedEffects uint64 `json:"prepared_effects"`
// AcceptedSignals counts external and Engine-generated mailbox entries.
AcceptedSignals uint64 `json:"accepted_signals"`
// DroppedDeltas counts increments rejected by validation or the bounded queue.
DroppedDeltas uint64 `json:"dropped_deltas"`
}
Usage contains monotonic Framework-owned counters. It deliberately excludes provider pricing and Strategy-specific concepts such as tokens or tool calls.
type WaitID ¶
type WaitID struct {
// contains filtered or unexported fields
}
WaitID identifies one Engine-created wait target owned by a Process. Parsing a WaitID does not create a wait; the Engine rejects identities it did not mint.
func ParseWaitID ¶
ParseWaitID validates the wire representation of a Wait identity.
func (WaitID) MarshalText ¶
func (*WaitID) UnmarshalText ¶
type WaitKey ¶
type WaitKey struct {
// contains filtered or unexported fields
}
WaitKey is an Execution-owned logical key used to associate a requested wait with the WaitID later minted by the Engine.
func ParseWaitKey ¶
ParseWaitKey validates an Execution-owned logical wait key.
func (WaitKey) MarshalText ¶
func (*WaitKey) UnmarshalText ¶
Source Files
¶
- capability.go
- child.go
- child_start.go
- child_wait.go
- definition.go
- delta.go
- deployment.go
- deployment_ref.go
- descriptor.go
- digest.go
- dispatcher.go
- doc.go
- effect.go
- effect_dispatch.go
- effect_phase.go
- engine.go
- event.go
- event_payload.go
- execution_boundary.go
- execution_state.go
- failure.go
- identity.go
- mailbox.go
- name.go
- observation.go
- observation_reentrancy.go
- process.go
- process_admission.go
- process_capture.go
- process_events.go
- process_handle_state.go
- process_relation.go
- process_restore.go
- process_snapshot.go
- process_start_outcome.go
- process_start_registration.go
- process_state.go
- resource.go
- runtime_error.go
- schema.go
- settlement.go
- signal.go
- signal_request.go
- status.go
- step_commit.go
- termination.go
- transition.go
- tree_commit.go
- tree_control.go
- tree_durability.go
- tree_head.go
- tree_incarnation.go
- tree_inspection.go
- tree_jobs.go
- tree_lifecycle.go
- tree_operation.go
- tree_release.go
- tree_restore.go
- tree_runtime.go
- tree_snapshot.go
- wire.go
Directories
¶
| Path | Synopsis |
|---|---|
|
Package agenttest provides deterministic consumer-side fixtures and reusable conformance suites for the Agent Framework's public execution boundaries.
|
Package agenttest provides deterministic consumer-side fixtures and reusable conformance suites for the Agent Framework's public execution boundaries. |
|
examples
|
|
|
autonomous
command
Command autonomous demonstrates an Interaction in which the model chooses a Tool from environment feedback and decides when to stop.
|
Command autonomous demonstrates an Interaction in which the model chooses a Tool from environment feedback and decides when to stop. |
|
composition
command
Command composition demonstrates that direct Engine embedding and a cross-Strategy composed Agent use the same Definition/Execution/Process contracts.
|
Command composition demonstrates that direct Engine embedding and a cross-Strategy composed Agent use the same Definition/Execution/Process contracts. |
|
direct_vs_managed
command
Command direct_vs_managed contrasts a direct model call with the same model capability managed as a recoverable agent Process.
|
Command direct_vs_managed contrasts a direct model call with the same model capability managed as a recoverable agent Process. |
|
evaluator_optimizer
command
Command evaluator_optimizer demonstrates bounded evaluator-optimizer composition with exact managed child Processes.
|
Command evaluator_optimizer demonstrates bounded evaluator-optimizer composition with exact managed child Processes. |
|
orchestrator_workers
command
Command orchestrator_workers demonstrates model-directed task decomposition, deterministic managed worker fan-out, and model synthesis without a Supervisor Strategy or runtime.
|
Command orchestrator_workers demonstrates model-directed task decomposition, deterministic managed worker fan-out, and model synthesis without a Supervisor Strategy or runtime. |
|
workflow
command
Command workflow demonstrates an ordered managed Workflow whose Call and Fork Stages create independently recoverable child Processes.
|
Command workflow demonstrates an ordered managed Workflow whose Call and Fork Stages create independently recoverable child Processes. |
|
workflow_patterns
command
Command workflow_patterns demonstrates prompt chaining, routing, parallel sectioning, and parallel voting through one managed Workflow.
|
Command workflow_patterns demonstrates prompt chaining, routing, parallel sectioning, and parallel voting through one managed Workflow. |
|
Package interaction provides the model-directed execution Strategy for the Agent Framework.
|
Package interaction provides the model-directed execution Strategy for the Agent Framework. |
|
internal
|
|
|
conformancetest
Package conformancetest captures real Engine boundaries for built-in Strategy tests.
|
Package conformancetest captures real Engine boundaries for built-in Strategy tests. |
|
Package planning provides goal-directed state planning as an Agent execution strategy.
|
Package planning provides goal-directed state planning as an Agent execution strategy. |
|
goap
Package goap provides deterministic goal-oriented action planning over immutable planning.WorldState values.
|
Package goap provides deterministic goal-oriented action planning over immutable planning.WorldState values. |
|
Package workflow provides deterministic orchestration of Framework-managed child Processes.
|
Package workflow provides deterministic orchestration of Framework-managed child Processes. |