Documentation
¶
Overview ¶
Package workflow provides deterministic orchestration of Framework-managed child Processes. A Workflow is an ordered sequence of sealed Stages; it is not a general in-process task graph, scheduler, journal, or node registry.
Use this package when each delegated operation needs its own Process identity, snapshot, budget, capabilities, cancellation, and tree recovery. Ordinary in-process control flow belongs outside the Agent Framework.
Stage constructors validate and freeze static bindings. Restore validates execution progress against those bindings without reconstructing them. Fork and Map share window admission, settlement, and ordered output handling.
Child admission and execution Failures propagate unchanged, preserving their kind, code, and complete diagnostic text. Fan-out waits for the active window to drain and propagates its first failure in declaration order. The Process tree retains the child identity and Stage binding; Workflow-owned decisions use workflow-prefixed failure codes. Every Stage rejects output adoption when the drained subtree retains unresolved Effects; no subsequent Stage, Loop iteration, or fan-out window starts. Single-child Stages also wait for the child subtree to drain. Restoring any handshake boundary resumes the same invocation and its Runtime-assigned wait.
Transform, Switch, Fork, and Loop callbacks run inside a discardable Step. They must be bounded, deterministic, side-effect-free, and cooperate with context cancellation during CPU work. Context carries cancellation, never hidden domain input. A canceled candidate cannot advance committed state.
Definitions reject unaddressed Host Signals through Descriptor.SignalSchema. Runtime-owned settlements are consumed only at their matching protocol phase; Wait openings may share a window with the following completion. InputGate replies, when used as children, must address the child's current WaitID.
Index ¶
- Variables
- func Compile[I, O any](ctx context.Context, cfg Config) (run.Program[I, O], error)
- type BindingRole
- type BindingTopology
- type CallConfig
- type Config
- type Definition
- func (d *Definition) ChildDeployments() []run.Program[run.Payload, run.Payload]
- func (d *Definition) Descriptor() run.Descriptor
- func (d *Definition) Restore(ctx context.Context, state run.ExecutionState) (run.Execution, error)
- func (d *Definition) Start(input run.Payload) (run.Execution, error)
- func (d *Definition) Topology() Topology
- type DefinitionConfig
- type ForkBranch
- type ForkConfig
- type ForkReducer
- type LoopConfig
- type LoopPredicate
- type LoopResult
- type MapConfig
- type Stage
- func Call(config CallConfig) (Stage, error)
- func Fork[I, B, O any](config ForkConfig[I, B, O]) (Stage, error)
- func Loop[T any](config LoopConfig[T]) (Stage, error)
- func Map[I, O any](config MapConfig[I, O]) (Stage, error)
- func Switch[I any](config SwitchConfig[I]) (Stage, error)
- func Transform[I, O any](id string, transform TransformFunc[I, O]) (Stage, error)
- type StageKind
- type StageTopology
- type SwitchCase
- type SwitchConfig
- type SwitchSelector
- type Topology
- type TransformFunc
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( ErrInvalidStage = errors.New("workflow: invalid stage") ErrInvalidDefinitionConfig = errors.New("workflow: invalid definition configuration") )
Construction sentinels reject caller data before execution and therefore carry no Failure classification.
var ( ErrInvalidExecutionState = run.NewClassifiedError( run.FailureKindContract, "workflow.state.invalid", "workflow: invalid execution state", ) ErrInvalidProtocol = run.NewClassifiedError( run.FailureKindContract, "workflow.protocol.invalid", "workflow: invalid protocol payload", ) )
Execution sentinels own the Failure persisted when they reach Step. Wrapping one is the only way a Step error acquires its classification.
Functions ¶
Types ¶
type BindingRole ¶
type BindingRole string
const ( BindingRoleInvalid BindingRole = "" BindingRoleCall BindingRole = "call" BindingRoleCase BindingRole = "case" BindingRoleBranch BindingRole = "branch" BindingRoleItem BindingRole = "item" BindingRoleBody BindingRole = "body" )
func (BindingRole) String ¶ added in v0.59.0
func (b BindingRole) String() string
func (BindingRole) Valid ¶ added in v0.59.0
func (b BindingRole) Valid() bool
type BindingTopology ¶
type BindingTopology struct {
Role BindingRole `json:"role"`
ID string `json:"id,omitempty"`
ProgramRef run.ProgramRef `json:"program_ref"`
InputSchema jsonschema.Schema `json:"input_schema"`
OutputSchema jsonschema.Schema `json:"output_schema"`
// Budget is the non-renewable allocation for each child start.
Budget run.Budget `json:"budget"`
Capabilities run.CapabilitySet `json:"capabilities"`
}
BindingTopology is a function-free projection of one exact child binding. ID is present only for named Switch cases and Fork branches.
type CallConfig ¶
type CallConfig struct {
// ID is unique within the Workflow and remains stable across restoration.
ID string
// Deployment is the exact child program. The Workflow owns it as
// one of its ChildDeployments.
Deployment run.Program[run.Payload, run.Payload]
// Budget is permanently allocated from the parent when the child starts.
Budget run.Budget
Capabilities run.CapabilitySet
}
CallConfig declares one exact child Program and its non-renewable Framework resource allocation.
type Config ¶ added in v0.59.0
type Config struct {
Name string
Description string
Stages []Stage
BuildIdentity run.Digest
CallbackIdentity run.Digest
}
Config binds the declared graph to executable code. CallbackIdentity covers captured settings of transforms, selectors and reducers that cannot be inferred.
type Definition ¶
type Definition struct {
// contains filtered or unexported fields
}
Definition is an immutable managed Workflow Strategy.
func NewDefinition ¶
func NewDefinition(config DefinitionConfig) (*Definition, error)
func (*Definition) ChildDeployments ¶ added in v0.59.0
ChildDeployments returns the exact child binding of every Stage.
func (*Definition) Descriptor ¶
func (d *Definition) Descriptor() run.Descriptor
func (*Definition) Restore ¶
func (d *Definition) Restore(ctx context.Context, state run.ExecutionState) (run.Execution, error)
Restore rejects progress inconsistent with the exact Definition bindings.
func (*Definition) Topology ¶
func (d *Definition) Topology() Topology
Topology returns a fresh, function-free projection of this Definition. An invalid or nil Definition returns the zero Topology.
type DefinitionConfig ¶
DefinitionConfig contains one immutable managed Workflow behavior. Stages execute in declaration order and must have exactly matching adjacent schemas.
type ForkBranch ¶
type ForkConfig ¶
type ForkConfig[I, B, O any] struct { // ID is unique within the Workflow and remains stable across restoration. ID string // Branches is a non-empty list in stable declaration order. Every branch // accepts I and produces B. Branches []ForkBranch // WindowSize is the positive number of branches started and settled as one // execution window before the next window begins. WindowSize uint32 Reduce ForkReducer[I, B, O] }
type ForkReducer ¶
ForkReducer combines the Fork's input with its branch outputs in declaration order; branches therefore return only what they add. It must be bounded, deterministic, side-effect-free, honor ctx cancellation, and never retain the slice. Context is not a source of domain input.
type LoopConfig ¶
type LoopConfig[T any] struct { // ID is unique within the Workflow and remains stable across restoration. ID string // Body is the exact T-to-T child Program used for every iteration. Body run.Program[run.Payload, run.Payload] // Budget is permanently allocated from the parent for each iteration. Budget run.Budget Capabilities run.CapabilitySet // MaxIterations bounds body child Processes. Its zero value is unlimited; // a finite zero is rejected because a Loop runs its body at least once. MaxIterations run.Quota Predicate LoopPredicate[T] }
type LoopPredicate ¶
LoopPredicate is a bounded, deterministic, side-effect-free completion test evaluated after each successful body child Process. It must honor ctx cancellation; context is not a source of domain input.
type LoopResult ¶
type LoopResult[T any] struct { // Value is the output of the last completed body iteration. Value T `json:"value"` Iterations uint64 `json:"iterations"` Satisfied bool `json:"satisfied"` }
LoopResult is the exact semantic output of a Loop Stage. Satisfied is false when MaxIterations was exhausted; that outcome is still a valid completion.
func (LoopResult[T]) Valid ¶
func (l LoopResult[T]) Valid() bool
type MapConfig ¶
type MapConfig[I, O any] struct { // ID is unique within the Workflow and remains stable across restoration. ID string Deployment run.Program[run.Payload, run.Payload] // Budget is permanently allocated from the parent for each started item. Budget run.Budget Capabilities run.CapabilitySet // WindowSize is the positive number of items started and settled as one // execution window before the next window begins. Only that window is // decoded into I values; snapshot recovery still validates the full input. WindowSize uint32 // MaxItems is the positive maximum accepted input length. MaxItems uint32 }
MapConfig declares a bounded homogeneous item fan-out. The Stage input is []I, each exact child Program consumes one I and produces one O, and the Stage output is []O in original item order.
type Stage ¶
type Stage struct {
// contains filtered or unexported fields
}
Stage is an immutable operation in one Workflow Definition. Values can only be constructed by this package, keeping the execution algebra closed.
func Call ¶
func Call(config CallConfig) (Stage, error)
Call constructs one managed child-Process Stage. No child Process is created until the Workflow Execution returns a Framework NewChildStartEffect Effect.
func Fork ¶
func Fork[I, B, O any](config ForkConfig[I, B, O]) (Stage, error)
Fork constructs one windowed managed fan-out Stage. Branch inputs and outputs are homogeneous; heterogeneous work can be wrapped by child Workflows that expose a shared contract.
func Loop ¶
func Loop[T any](config LoopConfig[T]) (Stage, error)
Loop constructs one at-least-once managed iteration Stage. Body must accept and produce exactly T; the Stage itself produces LoopResult[T].
func Map ¶
Map constructs one bounded managed item fan-out Stage. Empty input is valid and produces a non-nil empty []O without creating child Processes.
func Switch ¶
func Switch[I any](config SwitchConfig[I]) (Stage, error)
Switch constructs one selected managed child-Process Stage. Every case must accept the same I schema and produce one exactly matching output schema.
func Transform ¶
func Transform[I, O any](id string, transform TransformFunc[I, O]) (Stage, error)
Transform constructs one typed pure Stage. JSON schemas derived from I and O remain the authoritative erased boundary used by the Workflow Definition.
Example ¶
package main
import (
"context"
"fmt"
"strings"
"github.com/Tangerg/scope/agent/workflow"
)
func main() {
stage, err := workflow.Transform("normalize", func(_ context.Context, input string) (string, error) {
return strings.ToUpper(input), nil
})
if err != nil {
panic(err)
}
fmt.Println(stage.Valid())
}
Output: true
type StageTopology ¶
type StageTopology struct {
ID string `json:"id"`
Kind StageKind `json:"kind"`
InputSchema jsonschema.Schema `json:"input_schema"`
OutputSchema jsonschema.Schema `json:"output_schema"`
// Bindings are exact child bindings in stable declaration order.
Bindings []BindingTopology `json:"bindings,omitempty"`
// WindowSize is the fixed Fork or Map execution-window size.
WindowSize uint32 `json:"window_size,omitzero"`
// MaxItems is the maximum accepted Map input length.
MaxItems uint32 `json:"max_items,omitzero"`
// MaxIterations is present only for a Loop, including an unlimited Loop.
MaxIterations *run.Quota `json:"max_iterations,omitzero"`
}
StageTopology is a function-free projection of one sealed Stage. Limits are present only for the Stage kinds that own them.
type SwitchCase ¶
type SwitchConfig ¶
type SwitchConfig[I any] struct { // ID is unique within the Workflow and remains stable across restoration. ID string Select SwitchSelector[I] // Cases is a non-empty list in stable declaration order. Cases []SwitchCase }
type SwitchSelector ¶
SwitchSelector is a bounded, deterministic, side-effect-free case selector. It must honor ctx cancellation and returns the exact SwitchCase ID to invoke for the current value. Context is not a source of domain input.
type Topology ¶
type Topology struct {
Descriptor run.Descriptor `json:"descriptor"`
// Stages are projected in execution order.
Stages []StageTopology `json:"stages"`
}
Topology is a detached Definition-derived, function-free projection for diagnostics, documentation, UI rendering, and deployment audit. Mutating a projection never changes the Definition or a later projection.
type TransformFunc ¶
TransformFunc is a bounded, deterministic, side-effect-free reduction. It must honor ctx cancellation during CPU work. External work belongs in a Call stage that starts a child Process; ctx is not a source of domain input.