workflow

package
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Mar 30, 2026 License: EUPL-1.2 Imports: 9 Imported by: 0

Documentation

Overview

Package workflow provides the core domain entities for AWF workflow execution.

This package defines the workflow entity model, state machine execution, and configuration types for orchestrating AI agent interactions. It follows hexagonal architecture principles with zero dependencies on infrastructure.

Architecture

The workflow package is the heart of the domain layer:

  • Defines workflow entities (Workflow, Step, State) with validation logic
  • Implements state machine execution model with transitions
  • Provides thread-safe execution context for concurrent step execution
  • Declares port interfaces via ExpressionCompiler for infrastructure adapters

All types in this package are pure domain models with business logic only. Infrastructure concerns (file I/O, HTTP, shell execution) are delegated to ports defined in internal/domain/ports.

Core Entities

## Workflow (workflow.go)

The root entity representing a complete workflow definition:

  • Workflow: Complete workflow with name, inputs, steps, and hooks
  • Input: Input parameter definition with type and validation rules
  • InputValidation: Validation constraints for input parameters

## Step (step.go)

Step types define the state machine nodes:

  • Step: Single step in workflow state machine (8 types supported)
  • StepType: Enum for step types (command, parallel, terminal, for_each, while, operation, call_workflow, agent)
  • RetryConfig: Retry behavior with backoff and jitter
  • CaptureConfig: Output capture configuration for command steps

## ExecutionContext (context.go)

Thread-safe runtime state management:

  • ExecutionContext: Thread-safe workflow execution state with sync.RWMutex
  • StepState: Execution state of a single step (status, output, timing)
  • ExecutionStatus: Status enum (pending, running, completed, failed, cancelled)
  • LoopContext: Loop iteration state for for_each and while steps

Configuration Types

## Parallel Execution (parallel.go)

Parallel step configuration and strategies:

  • Strategy values: all_succeed, any_succeed, best_effort
  • MaxConcurrent: Limit concurrent branch execution
  • DependsOn: Declare ordering constraints between branches

## Loops (loop.go)

Iterative execution with for_each and while:

  • LoopConfig: Loop configuration with type, items, condition, and body
  • LoopContext: Runtime iteration state with item, index, first/last flags
  • Nested loops supported via Parent reference (F043)

## Conditional Transitions (condition.go)

Expression-based state transitions:

  • Transition: Single conditional transition with condition expression and target
  • Transitions: Ordered list of transitions evaluated sequentially
  • Condition: Boolean expression evaluated against execution context

## Hooks (hooks.go)

Pre/post execution actions:

  • WorkflowHooks: Lifecycle hooks (WorkflowStart, WorkflowEnd, WorkflowError, WorkflowCancel)
  • StepHooks: Step-level hooks (Pre, Post)
  • HookAction: Log message or shell command to execute

Execution Results

## Step Execution (context.go)

Step execution captures:

  • StepState: Status, output, stderr, exit code, timing, error
  • Response: Parsed JSON response from agent steps (map[string]any)
  • Tokens: Token usage tracking for AI agent steps
  • OutputPath/StderrPath: Temp file paths for streamed output (C019)

## Workflow Outcomes (workflow.go)

Terminal step status:

  • TerminalStatus: success or failure
  • Terminal steps define workflow completion state

Templates

## Workflow Templates (template.go)

Reusable workflow fragments:

  • Template: Named template with parameters and state definitions
  • TemplateParam: Parameter definition (name, required, default)
  • WorkflowTemplateRef: Reference to template from step with parameter bindings

## Template Validation (template_validation.go)

Template-specific validation:

  • ValidateTemplateReference: Check parameter bindings match template signature
  • ValidateTemplateExpansion: Verify expanded template produces valid workflow fragment

AI Agent Integration (F039)

## Agent Configuration (agent_config.go)

AI agent invocation:

  • AgentConfig: Provider, prompt, options, timeout, mode
  • Provider values: claude, codex, gemini, opencode, custom
  • Mode: single (one-shot) or conversation (multi-turn)

## Conversation Mode (F033, conversation.go)

Multi-turn agent interactions:

  • ConversationConfig: Max turns, stop conditions, context window management
  • ConversationState: Conversation history and message accumulation
  • ConversationMessage: Single message with role (user/assistant/system) and content
  • ContextWindowState: Token budget tracking and history truncation state

Subworkflows (F023)

## Call Workflow (subworkflow.go)

Invoke child workflows:

  • CallWorkflowConfig: Workflow name, inputs, circular detection
  • CallStack: Active workflow names for circular call prevention

Validation

## Workflow Validation (validation.go)

Comprehensive validation rules:

  • Workflow.Validate(): Check name, initial state, terminal states, step graph
  • Step.Validate(): Type-specific validation (command, agent, parallel, loop, operation)
  • Graph validation: Detect unreachable states, cycles, missing targets

## Validation Errors (validation_errors.go)

Structured error types:

  • ValidationError: Base validation error with field and reason
  • GraphValidationError: Graph-specific errors (unreachable, cycle, missing target)
  • InputValidationError: Input parameter validation failures

Usage Examples

## Basic Workflow Construction

Create a simple workflow with command and terminal steps:

wf := &workflow.Workflow{
    Name:    "hello-world",
    Version: "1.0.0",
    Initial: "greet",
    Steps: map[string]*workflow.Step{
        "greet": {
            Name:      "greet",
            Type:      workflow.StepTypeCommand,
            Command:   "echo 'Hello, {{inputs.name}}'",
            OnSuccess: "end",
        },
        "end": {
            Name:   "end",
            Type:   workflow.StepTypeTerminal,
            Status: workflow.TerminalSuccess,
        },
    },
}

// Validate workflow
if err := wf.Validate(validator, nil); err != nil {
    log.Fatal(err)
}

## Execution Context Management

Thread-safe execution context for workflow runs:

ctx := workflow.NewExecutionContext("wf-123", "hello-world")
ctx.SetInput("name", "Alice")
ctx.SetCurrentStep("greet")

// Record step execution
state := workflow.StepState{
    Name:        "greet",
    Status:      workflow.StatusCompleted,
    Output:      "Hello, Alice",
    ExitCode:    0,
    StartedAt:   time.Now().Add(-1 * time.Second),
    CompletedAt: time.Now(),
}
ctx.SetStepState("greet", state)

// Access results thread-safely
if output, ok := ctx.GetStepOutput("greet"); ok {
    fmt.Println(output) // "Hello, Alice"
}

## Parallel Execution

Workflow with parallel branches:

wf := &workflow.Workflow{
    Name:    "parallel-demo",
    Initial: "parallel",
    Steps: map[string]*workflow.Step{
        "parallel": {
            Name:          "parallel",
            Type:          workflow.StepTypeParallel,
            Branches:      []string{"task1", "task2", "task3"},
            Strategy:      "all_succeed",
            MaxConcurrent: 2,
            OnSuccess:     "end",
        },
        "task1": {
            Name:    "task1",
            Type:    workflow.StepTypeCommand,
            Command: "echo 'Task 1'",
        },
        "task2": {
            Name:    "task2",
            Type:    workflow.StepTypeCommand,
            Command: "echo 'Task 2'",
        },
        "task3": {
            Name:    "task3",
            Type:    workflow.StepTypeCommand,
            Command: "echo 'Task 3'",
        },
        "end": {
            Name:   "end",
            Type:   workflow.StepTypeTerminal,
            Status: workflow.TerminalSuccess,
        },
    },
}

## Loop Execution

For-each loop over items:

loopStep := &workflow.Step{
    Name: "process_items",
    Type: workflow.StepTypeForEach,
    Loop: &workflow.LoopConfig{
        Items: []string{"apple", "banana", "cherry"},
        Body:  []string{"print_item"},
    },
    OnSuccess: "end",
}

printStep := &workflow.Step{
    Name:    "print_item",
    Type:    workflow.StepTypeCommand,
    Command: "echo 'Item {{loop.index}}: {{loop.item}}'",
}

// Runtime loop context access
loopCtx := &workflow.LoopContext{
    Item:   "apple",
    Index:  0,
    First:  true,
    Last:   false,
    Length: 3,
}

## AI Agent Invocation

Single-shot agent execution:

agentStep := &workflow.Step{
    Name: "analyze",
    Type: workflow.StepTypeAgent,
    Agent: &workflow.AgentConfig{
        Provider: "claude",
        Prompt:   "Analyze this log: {{inputs.log_file}}",
        Options: map[string]any{
            "model":       "claude-3-sonnet",
            "temperature": 0.7,
            "max_tokens":  1000,
        },
        Timeout: 60,
        Mode:    "single",
    },
    OnSuccess: "end",
}

## Conversation Mode Agent

Multi-turn agent conversation:

conversationStep := &workflow.Step{
    Name: "chat",
    Type: workflow.StepTypeAgent,
    Agent: &workflow.AgentConfig{
        Provider:      "claude",
        Mode:          "conversation",
        SystemPrompt:  "You are a helpful coding assistant.",
        InitialPrompt: "Help me debug this code: {{inputs.code}}",
        Conversation: &workflow.ConversationConfig{
            MaxTurns: 10,
            StopConditions: []string{
                "{{conversation.last_message}} contains 'DONE'",
            },
            ContextWindow: &workflow.ContextWindowConfig{
                Strategy:     "truncate_middle",
                MaxTokens:    4000,
                ReserveRatio: 0.1,
            },
        },
    },
    OnSuccess: "end",
}

## Conditional Transitions

Expression-based state transitions:

step := &workflow.Step{
    Name:    "check_status",
    Type:    workflow.StepTypeCommand,
    Command: "curl https://api.example.com/status",
    Transitions: workflow.Transitions{
        {
            Condition: "{{states.check_status.exit_code}} == 0",
            Target:    "success",
        },
        {
            Condition: "{{states.check_status.exit_code}} == 404",
            Target:    "not_found",
        },
        {
            Condition: "true", // default fallback
            Target:    "error",
        },
    },
}

## Retry Configuration

Exponential backoff with jitter:

step := &workflow.Step{
    Name:    "flaky_api",
    Type:    workflow.StepTypeCommand,
    Command: "curl https://api.example.com",
    Retry: &workflow.RetryConfig{
        MaxAttempts:        3,
        InitialDelayMs:     1000,
        MaxDelayMs:         10000,
        Backoff:            "exponential",
        Multiplier:         2.0,
        Jitter:             0.1,
        RetryableExitCodes: []int{1, 2, 7}, // connection errors
    },
    OnSuccess: "end",
}

## Hooks

Lifecycle event handlers:

wf := &workflow.Workflow{
    Name:    "hooked-workflow",
    Initial: "main",
    Hooks: workflow.WorkflowHooks{
        WorkflowStart: workflow.Hook{
            {Log: "Starting workflow execution"},
            {Command: "date > /tmp/start.txt"},
        },
        WorkflowEnd: workflow.Hook{
            {Log: "Workflow completed successfully"},
        },
        WorkflowError: workflow.Hook{
            {Log: "Workflow failed: {{error.message}}"},
            {Command: "notify-admin.sh '{{error.message}}'"},
        },
    },
    Steps: map[string]*workflow.Step{
        "main": {
            Name:    "main",
            Type:    workflow.StepTypeCommand,
            Command: "echo 'Main task'",
            Hooks: workflow.StepHooks{
                Pre: workflow.Hook{
                    {Log: "Starting main task"},
                },
                Post: workflow.Hook{
                    {Log: "Main task completed"},
                },
            },
            OnSuccess: "end",
        },
        "end": {
            Name:   "end",
            Type:   workflow.StepTypeTerminal,
            Status: workflow.TerminalSuccess,
        },
    },
}

Design Principles

## Pure Domain Logic

Zero infrastructure dependencies:

  • No file I/O, HTTP, database, or shell execution code
  • Infrastructure concerns delegated to ports (interfaces)
  • Domain logic expressed through validation rules and state transitions

## Thread Safety

ExecutionContext uses sync.RWMutex for concurrent access:

  • Parallel step execution requires thread-safe state management
  • All context mutations acquire write lock
  • Read operations use read lock for performance
  • Validated with `go test -race ./...`

## Validation First

Static validation before execution:

  • Workflow.Validate() checks structure before runtime
  • Graph validation detects unreachable states and cycles
  • Type-specific validation for each step type
  • Expression validation delegated to ExpressionCompiler port

## Expression Compilation Interface

ExpressionCompiler port abstraction:

  • Domain declares interface, infrastructure implements
  • Used for validating conditional expressions in agent configs
  • Enables testing without concrete template engine

See also:

  • internal/domain/ports: Port interfaces for adapters
  • internal/application: Application services orchestrating workflow execution
  • docs/architecture.md: Hexagonal architecture overview
  • CLAUDE.md: Project conventions and workflow execution semantics

Index

Constants

View Source
const (
	EventWorkflowStarted   = "workflow.started"
	EventWorkflowCompleted = "workflow.completed"
)
View Source
const DefaultAgentTimeout = 300

DefaultAgentTimeout is the default timeout in seconds for agent execution.

View Source
const DefaultMaxConcurrent = 0

DefaultMaxConcurrent is the default concurrency limit (0 = unlimited).

View Source
const DefaultMaxIterations = 100

DefaultMaxIterations is the default iteration limit.

View Source
const DefaultParallelStrategy = StrategyAllSucceed

DefaultParallelStrategy is used when no strategy is specified.

View Source
const DefaultSubWorkflowTimeout = 300

DefaultSubWorkflowTimeout is the default timeout in seconds for sub-workflow execution.

View Source
const MaxAllowedIterations = 10000

MaxAllowedIterations is the hard limit for safety.

View Source
const MaxCallStackDepth = 10

MaxCallStackDepth is the maximum allowed nesting depth for sub-workflow calls.

Variables

View Source
var (
	ErrNilTurn = errors.New("cannot add nil turn")
)

Conversation errors

View Source
var ValidContextProperties = map[string]bool{
	"WorkingDir": true,
	"User":       true,
	"Hostname":   true,
}

ValidContextProperties lists known context properties.

View Source
var ValidErrorProperties = map[string]bool{
	"Message":  true,
	"State":    true,
	"ExitCode": true,
	"Type":     true,
}

ValidErrorProperties lists known error properties in error hooks.

View Source
var ValidLoopProperties = map[string]bool{
	"Item":   true,
	"Index":  true,
	"Index1": true,
	"First":  true,
	"Last":   true,
	"Length": true,
	"Parent": true,
}

ValidLoopProperties lists known loop properties accessible during loop iteration.

View Source
var ValidStateProperties = map[string]bool{
	"Output":     true,
	"Stderr":     true,
	"ExitCode":   true,
	"Status":     true,
	"Response":   true,
	"TokensUsed": true,
	"JSON":       true,
}

ValidStateProperties lists known step state properties that can be referenced. NOTE: This map is duplicated in pkg/interpolation/reference.go — keep both in sync until dedup cleanup.

View Source
var ValidWorkflowProperties = map[string]bool{
	"ID":           true,
	"Name":         true,
	"CurrentState": true,
	"StartedAt":    true,
	"Duration":     true,
}

ValidWorkflowProperties lists known workflow properties that can be referenced.

Functions

func BuildCyclePath

func BuildCyclePath(path []string, startIndex int, target string) []string

BuildCyclePath constructs the cycle path from startIndex to the end of path, appending target to close the cycle loop.

func ComputeExecutionOrder

func ComputeExecutionOrder(steps map[string]*Step, initial string) ([]string, error)

ComputeExecutionOrder determines the topological order of step execution. This is needed to detect forward references (step A references step B's output, but B runs after A in the execution order). Returns the ordered list of step names, or an error if a valid order cannot be computed.

func DetectCycles

func DetectCycles(steps map[string]*Step, initial string) []string

DetectCycles uses DFS with color marking to detect cycles in the state graph. Returns a list of cycle paths found (e.g., ["A -> B -> C -> A"]).

func EnqueueIfNotVisited

func EnqueueIfNotVisited(queue *[]string, visited map[string]bool, state string)

EnqueueIfNotVisited adds state to queue if it hasn't been visited yet. This helper consolidates the repeated pattern of checking visited status before enqueueing in BFS traversal algorithms.

Parameters:

  • queue: pointer to the queue slice to modify in-place
  • visited: map tracking which states have been visited
  • state: the state name to potentially add to the queue

The function modifies queue in-place only if visited[state] is false or state is not present in the visited map.

func FindCycleStart

func FindCycleStart(path []string, target string) int

FindCycleStart finds the index of target in path, returning -1 if not found. Used for locating where a cycle begins in a DFS path during cycle detection.

func FindReachableStates

func FindReachableStates(steps map[string]*Step, initial string) map[string]bool

FindReachableStates performs DFS from initial to find all reachable states.

func GetTransitions

func GetTransitions(step *Step) []string

GetTransitions returns all outbound transitions from a step. For command/operation/loop/call_workflow steps: on_success, on_failure For parallel steps: on_success, on_failure, and all branches For terminal steps: empty

Types

type AgentConfig

type AgentConfig struct {
	Provider      string              `yaml:"provider"`       // agent provider: claude, codex, gemini, opencode, openai_compatible
	Prompt        string              `yaml:"prompt"`         // prompt template with {{inputs.*}} and {{states.*}} (single mode) or initial prompt (conversation mode)
	PromptFile    string              `yaml:"prompt_file"`    // path to external prompt template file (mutually exclusive with Prompt)
	Options       map[string]any      `yaml:"options"`        // provider-specific options (model, temperature, max_tokens, etc.)
	Timeout       int                 `yaml:"timeout"`        // seconds, 0 = use DefaultAgentTimeout
	Mode          string              `yaml:"mode"`           // execution mode: "single" (default) or "conversation"
	SystemPrompt  string              `yaml:"system_prompt"`  // system prompt preserved across conversation (conversation mode only)
	InitialPrompt string              `yaml:"initial_prompt"` // first user message in conversation mode (overrides Prompt if set)
	Conversation  *ConversationConfig `yaml:"conversation"`   // conversation-specific configuration (conversation mode only)
	OutputFormat  OutputFormat        `yaml:"output_format"`  // output post-processing: json (strip fences + validate), text (strip fences only), or empty (no processing)
}

AgentConfig holds configuration for invoking an AI agent.

func (*AgentConfig) GetEffectivePrompt

func (c *AgentConfig) GetEffectivePrompt() string

GetEffectivePrompt returns the appropriate prompt based on the mode. In conversation mode, returns InitialPrompt if set, otherwise Prompt. In single mode, returns Prompt.

func (*AgentConfig) GetTimeout

func (c *AgentConfig) GetTimeout() time.Duration

GetTimeout returns the effective timeout as a time.Duration. Returns DefaultAgentTimeout seconds if not explicitly set.

func (*AgentConfig) IsConversationMode

func (c *AgentConfig) IsConversationMode() bool

IsConversationMode returns true if the agent is configured for conversation mode.

func (*AgentConfig) Validate

func (c *AgentConfig) Validate(validator ExpressionCompiler) error

Validate checks if the agent configuration is valid. The validator parameter is used to check expression syntax in conversation config.

type AgentResult

type AgentResult struct {
	Provider        string         // provider name used
	Output          string         // raw output from agent CLI
	Response        map[string]any // parsed JSON response (if applicable)
	Tokens          int            // token usage (if reported by provider)
	TokensEstimated bool           // true if Tokens is an estimation, false if actual count
	Error           error          // execution error, if any
	StartedAt       time.Time
	CompletedAt     time.Time
	Conversation    *ConversationResult // conversation-specific result (conversation mode only)
}

AgentResult holds the result of an agent execution.

func NewAgentResult

func NewAgentResult(provider string) *AgentResult

NewAgentResult creates a new AgentResult with initialized values.

func (*AgentResult) Duration

func (r *AgentResult) Duration() time.Duration

Duration returns the execution time of the agent invocation.

func (*AgentResult) HasJSONResponse

func (r *AgentResult) HasJSONResponse() bool

HasJSONResponse returns true if a JSON response was successfully parsed.

func (*AgentResult) Success

func (r *AgentResult) Success() bool

Success returns true if the agent execution completed without error.

type AuditEvent

type AuditEvent struct {
	SchemaVersion   int            `json:"schema_version"`
	Event           string         `json:"event"`
	Timestamp       time.Time      `json:"timestamp"`
	ExecutionID     string         `json:"execution_id"`
	User            string         `json:"user"`
	WorkflowName    string         `json:"workflow_name"`
	Inputs          map[string]any `json:"inputs,omitempty"`
	InputsTruncated bool           `json:"inputs_truncated,omitempty"`
	Status          string         `json:"status,omitempty"`
	ExitCode        *int           `json:"exit_code,omitempty"`
	DurationMs      *int64         `json:"duration_ms,omitempty"`
	Error           string         `json:"error,omitempty"`
}

AuditEvent represents a single audit trail entry for a workflow execution. Two events are emitted per execution: workflow.started and workflow.completed.

func NewCompletedEvent

func NewCompletedEvent(execCtx *ExecutionContext, user, errorMsg string) AuditEvent

NewCompletedEvent creates an audit event for workflow completion.

func NewStartedEvent

func NewStartedEvent(execCtx *ExecutionContext, maskedInputs map[string]any, user string) AuditEvent

NewStartedEvent creates an audit event for workflow start. Inputs should already be secret-masked by the caller. Called immediately after ExecutionContext creation, before WorkflowStart hooks.

func (AuditEvent) MarshalJSON

func (e AuditEvent) MarshalJSON() ([]byte, error)

MarshalJSON produces ordered JSON with millisecond timestamp precision. Field order: event, execution_id, timestamp, user, workflow_name, then event-specific fields, then schema_version.

type BranchResult

type BranchResult struct {
	Name        string
	Output      string
	Stderr      string
	ExitCode    int
	Error       error
	StartedAt   time.Time
	CompletedAt time.Time
}

BranchResult holds the result of a single parallel branch execution.

func (*BranchResult) Duration

func (r *BranchResult) Duration() time.Duration

Duration returns the execution time of the branch.

func (*BranchResult) Success

func (r *BranchResult) Success() bool

Success returns true if the branch completed without error and exit code 0.

type CallWorkflowConfig

type CallWorkflowConfig struct {
	Workflow string            `yaml:"workflow"` // workflow name to invoke
	Inputs   map[string]string `yaml:"inputs"`   // parent var → sub-workflow input template
	Outputs  map[string]string `yaml:"outputs"`  // sub-workflow output → parent var name
	Timeout  int               `yaml:"timeout"`  // seconds, 0 = inherit from step
}

CallWorkflowConfig holds configuration for calling another workflow as a sub-workflow.

func (*CallWorkflowConfig) GetTimeout

func (c *CallWorkflowConfig) GetTimeout() int

GetTimeout returns the effective timeout in seconds. Returns DefaultSubWorkflowTimeout if not explicitly set.

func (*CallWorkflowConfig) Validate

func (c *CallWorkflowConfig) Validate() error

Validate checks if the call workflow configuration is valid.

type CaptureConfig

type CaptureConfig struct {
	Stdout   string // variable name to store stdout
	Stderr   string // variable name to store stderr
	MaxSize  string // max bytes (e.g., "10MB")
	Encoding string // e.g., "utf-8"
}

CaptureConfig defines output capture behavior.

type CircularTemplateError

type CircularTemplateError struct {
	Chain []string // chain of template names forming the cycle
}

CircularTemplateError indicates a circular dependency in template references.

func (*CircularTemplateError) Error

func (e *CircularTemplateError) Error() string

type ContextWindowManager

type ContextWindowManager interface {
	ApplyStrategy(turns []Turn, maxTokens int, strategy ContextWindowStrategy) ([]Turn, bool, error)
	PreserveSystemPrompt(turns []Turn) (*Turn, []Turn)
	CalculateTotalTokens(turns []Turn) int
	EstimateTokens(content string) int
}

func NewContextWindowManager

func NewContextWindowManager() ContextWindowManager

type ContextWindowState

type ContextWindowState struct {
	Strategy        ContextWindowStrategy
	TruncationCount int
	TurnsDropped    int
	TokensDropped   int
	LastTruncatedAt int
}

func NewContextWindowState

func NewContextWindowState(strategy ContextWindowStrategy) *ContextWindowState

func (*ContextWindowState) RecordTruncation

func (s *ContextWindowState) RecordTruncation(turnsDropped, tokensDropped, currentTurn int)

func (*ContextWindowState) WasTruncated

func (s *ContextWindowState) WasTruncated() bool

type ContextWindowStrategy

type ContextWindowStrategy string

ContextWindowStrategy defines the strategy for managing context window limits.

const (
	StrategyNone           ContextWindowStrategy = ""
	StrategySlidingWindow  ContextWindowStrategy = "sliding_window"
	StrategySummarize      ContextWindowStrategy = "summarize"
	StrategyTruncateMiddle ContextWindowStrategy = "truncate_middle"
)

type ConversationConfig

type ConversationConfig struct {
	MaxTurns         int                   // maximum number of turns (default 10, max 100)
	MaxContextTokens int                   // maximum tokens in context window (0 = provider default)
	Strategy         ContextWindowStrategy // context window management strategy
	StopCondition    string                // expression to evaluate for early exit
	ContinueFrom     string                // step name to continue conversation from
	InjectContext    string                // additional context to inject mid-conversation
}

ConversationConfig holds configuration for conversation mode execution.

func (*ConversationConfig) GetMaxTurns

func (c *ConversationConfig) GetMaxTurns() int

GetMaxTurns returns the effective max turns with default fallback.

func (*ConversationConfig) Validate

func (c *ConversationConfig) Validate(validator ExpressionCompiler) error

Validate checks if the conversation configuration is valid. The validator parameter is used to check stop condition expression syntax.

type ConversationResult

type ConversationResult struct {
	Provider        string             // provider name used
	State           *ConversationState // final conversation state
	Output          string             // final assistant response (last turn)
	Response        map[string]any     // parsed JSON response from last turn (if applicable)
	TokensInput     int                // total input tokens across all turns
	TokensOutput    int                // total output tokens across all turns
	TokensTotal     int                // sum of input + output tokens
	TokensEstimated bool               // true if token counts are estimates
	Error           error              // execution error, if any
	StartedAt       time.Time
	CompletedAt     time.Time
}

ConversationResult holds the result of a conversation execution.

func NewConversationResult

func NewConversationResult(provider string) *ConversationResult

NewConversationResult creates a new ConversationResult with initialized values.

func (*ConversationResult) Duration

func (r *ConversationResult) Duration() time.Duration

Duration returns the total execution time of the conversation.

func (*ConversationResult) HasJSONResponse

func (r *ConversationResult) HasJSONResponse() bool

HasJSONResponse returns true if a JSON response was successfully parsed.

func (*ConversationResult) Success

func (r *ConversationResult) Success() bool

Success returns true if the conversation completed without error.

func (*ConversationResult) TurnCount

func (r *ConversationResult) TurnCount() int

TurnCount returns the number of turns in the conversation.

type ConversationState

type ConversationState struct {
	SessionID   string     // provider-assigned session identifier for resume capability
	Turns       []Turn     // ordered array of conversation turns
	TotalTurns  int        // total number of turns executed
	TotalTokens int        // cumulative token count across all turns
	StoppedBy   StopReason // reason the conversation stopped
}

ConversationState represents the state of an ongoing or completed conversation.

func NewConversationState

func NewConversationState(systemPrompt string) *ConversationState

NewConversationState creates a new conversation state with system prompt.

func (*ConversationState) AddTurn

func (s *ConversationState) AddTurn(turn *Turn) error

AddTurn appends a turn to the conversation history. Returns an error if the turn is nil.

func (*ConversationState) GetLastAssistantResponse

func (s *ConversationState) GetLastAssistantResponse() string

GetLastAssistantResponse returns the content of the last assistant turn.

func (*ConversationState) GetLastTurn

func (s *ConversationState) GetLastTurn() *Turn

GetLastTurn returns the most recent turn, or nil if no turns exist.

func (*ConversationState) GetTotalTokens

func (s *ConversationState) GetTotalTokens() int

GetTotalTokens returns the sum of tokens across all turns.

func (*ConversationState) IsStopped

func (s *ConversationState) IsStopped() bool

IsStopped returns true if the conversation has a stop reason set.

type DryRunAgent

type DryRunAgent struct {
	Provider       string
	ResolvedPrompt string
	CLICommand     string
	Options        map[string]any
	Timeout        int
	OutputFormat   OutputFormat
}

type DryRunCapture

type DryRunCapture struct {
	Stdout  string
	Stderr  string
	MaxSize string
}

type DryRunHook

type DryRunHook struct {
	Type    string
	Content string
}

type DryRunHooks

type DryRunHooks struct {
	Pre  []DryRunHook
	Post []DryRunHook
}

type DryRunInput

type DryRunInput struct {
	Name     string
	Value    any
	Default  bool
	Required bool
}

type DryRunLoop

type DryRunLoop struct {
	Type           string
	Items          string
	Condition      string
	Body           []string
	MaxIterations  int
	BreakCondition string
	OnComplete     string
}

type DryRunPlan

type DryRunPlan struct {
	WorkflowName string
	Description  string
	Inputs       map[string]DryRunInput
	Steps        []DryRunStep
}

type DryRunRetry

type DryRunRetry struct {
	MaxAttempts        int
	InitialDelayMs     int
	MaxDelayMs         int
	Backoff            string
	Multiplier         float64
	Jitter             float64
	RetryableExitCodes []int
}

type DryRunStep

type DryRunStep struct {
	Name            string
	Type            StepType
	Description     string
	Command         string
	ScriptFile      string
	Dir             string
	Hooks           DryRunHooks
	Transitions     []DryRunTransition
	Timeout         int
	Retry           *DryRunRetry
	Capture         *DryRunCapture
	ContinueOnError bool
	Branches        []string
	Strategy        string
	MaxConcurrent   int
	Loop            *DryRunLoop
	Status          TerminalStatus
	Agent           *DryRunAgent
}

type DryRunTransition

type DryRunTransition struct {
	Condition string
	Target    string
	Type      string
}

type EvaluatorFunc

type EvaluatorFunc func(expr string) (bool, error)

type ExecutionContext

type ExecutionContext struct {
	WorkflowID   string
	WorkflowName string
	Status       ExecutionStatus
	CurrentStep  string
	ExitCode     int // process exit code propagated from terminal steps (FR-004)
	Inputs       map[string]any
	States       map[string]StepState
	Env          map[string]string
	StartedAt    time.Time
	UpdatedAt    time.Time
	CompletedAt  time.Time
	CurrentLoop  *LoopContext // current loop iteration context (nil when not in a loop)
	CallStack    []string     // active workflow names for circular detection (F023)
	// contains filtered or unexported fields
}

ExecutionContext holds the runtime state of a workflow execution. Thread-safe for concurrent access during parallel execution.

func NewExecutionContext

func NewExecutionContext(workflowID, workflowName string) *ExecutionContext

NewExecutionContext creates a new execution context.

func (*ExecutionContext) CallStackDepth

func (c *ExecutionContext) CallStackDepth() int

CallStackDepth returns the current depth of the call stack. Used to enforce maximum nesting depth for sub-workflows.

func (*ExecutionContext) GetAllStepStates

func (c *ExecutionContext) GetAllStepStates() map[string]StepState

GetAllStepStates returns a copy of all step states in a thread-safe manner.

func (*ExecutionContext) GetInput

func (c *ExecutionContext) GetInput(key string) (any, bool)

GetInput retrieves an input value.

func (*ExecutionContext) GetStepState

func (c *ExecutionContext) GetStepState(stepName string) (StepState, bool)

GetStepState retrieves the state of a step.

func (*ExecutionContext) IsInCallStack

func (c *ExecutionContext) IsInCallStack(workflowName string) bool

IsInCallStack checks if a workflow name is already in the call stack. Used to detect circular workflow calls.

func (*ExecutionContext) PopCallStack

func (c *ExecutionContext) PopCallStack()

PopCallStack removes the last workflow name from the call stack. Used when exiting a sub-workflow. Does nothing if stack is empty.

func (*ExecutionContext) PushCallStack

func (c *ExecutionContext) PushCallStack(workflowName string)

PushCallStack adds a workflow name to the call stack. Used when entering a sub-workflow to track the call chain.

func (*ExecutionContext) SetInput

func (c *ExecutionContext) SetInput(key string, value any)

SetInput sets an input value.

func (*ExecutionContext) SetStepState

func (c *ExecutionContext) SetStepState(stepName string, state StepState)

SetStepState sets the state of a step.

type ExecutionRecord

type ExecutionRecord struct {
	ID           string
	WorkflowID   string
	WorkflowName string
	Status       string // success, failed, cancelled
	ExitCode     int
	StartedAt    time.Time
	CompletedAt  time.Time
	DurationMs   int64
	ErrorMessage string
}

ExecutionRecord represents a completed workflow execution for history tracking. It captures essential metadata for reporting and analysis.

type ExecutionStatus

type ExecutionStatus string

ExecutionStatus represents the status of a workflow execution.

const (
	StatusPending   ExecutionStatus = "pending"
	StatusRunning   ExecutionStatus = "running"
	StatusCompleted ExecutionStatus = "completed"
	StatusFailed    ExecutionStatus = "failed"
	StatusCancelled ExecutionStatus = "cancelled"
)

func (ExecutionStatus) String

func (s ExecutionStatus) String() string

type ExpressionCompiler

type ExpressionCompiler func(expression string) error

ExpressionCompiler is a function type for validating expression syntax. This type mirrors the ports.ExpressionValidator.Compile signature but is defined in the workflow package to avoid import cycles while maintaining hexagonal architecture. Returns nil if the expression is syntactically valid, error otherwise.

type HistoryFilter

type HistoryFilter struct {
	WorkflowName string
	Status       string
	Since        time.Time
	Until        time.Time
	Limit        int
}

HistoryFilter defines criteria for querying execution history.

type HistoryStats

type HistoryStats struct {
	TotalExecutions int
	SuccessCount    int
	FailedCount     int
	CancelledCount  int
	AvgDurationMs   int64
}

HistoryStats contains aggregated execution statistics.

type Hook

type Hook []HookAction

type HookAction

type HookAction struct {
	Log     string
	Command string
}

Either Log or Command should be set, not both.

type Input

type Input struct {
	Name        string
	Type        string // string, integer, boolean
	Description string
	Required    bool
	Default     any
	Validation  *InputValidation // validation rules
}

Input defines an input parameter for a workflow.

type InputValidation

type InputValidation struct {
	Pattern       string   // regex pattern for strings
	Enum          []string // allowed values
	Min           *int     // minimum for integers
	Max           *int     // maximum for integers
	FileExists    bool     // file must exist
	FileExtension []string // allowed file extensions
}

InputValidation defines validation rules for an input parameter.

type InteractiveAction

type InteractiveAction string

InteractiveAction represents user actions during interactive execution.

const (
	ActionContinue InteractiveAction = "continue" // execute the step
	ActionSkip     InteractiveAction = "skip"     // skip to next step (on_success)
	ActionAbort    InteractiveAction = "abort"    // stop workflow execution
	ActionInspect  InteractiveAction = "inspect"  // show context details
	ActionEdit     InteractiveAction = "edit"     // modify an input value
	ActionRetry    InteractiveAction = "retry"    // re-run previous step
)

type InteractiveResult

type InteractiveResult struct {
	StepName   string          // executed step name
	Status     ExecutionStatus // completion status
	Output     string          // stdout
	Stderr     string          // stderr
	ExitCode   int             // process exit code
	DurationMs int64           // execution duration in milliseconds
	NextStep   string          // next step to execute
	WasSkipped bool            // true if step was skipped
	WasRetried bool            // true if this was a retry
	RetryCount int             // number of retries attempted
}

InteractiveResult holds the outcome of an interactive step execution.

type InteractiveStepInfo

type InteractiveStepInfo struct {
	Name        string   // step name
	Index       int      // 1-based step index
	Total       int      // total steps discovered
	Step        *Step    // reference to the step definition
	Command     string   // resolved command (with interpolation)
	Transitions []string // formatted transition descriptions
}

InteractiveStepInfo provides step details for interactive display.

type IterationResult

type IterationResult struct {
	Index       int
	Item        any // for for_each
	StepResults map[string]*StepState
	Error       error
	StartedAt   time.Time
	CompletedAt time.Time
}

IterationResult holds the result of a single loop iteration.

func (*IterationResult) Duration

func (r *IterationResult) Duration() time.Duration

Duration returns the execution time of the iteration.

func (*IterationResult) Success

func (r *IterationResult) Success() bool

Success returns true if the iteration completed without error.

type LoopConfig

type LoopConfig struct {
	Type                       LoopType          // for_each or while
	Items                      string            // template expression for items (for_each)
	Condition                  string            // expression to evaluate (while)
	Body                       []string          // step names to execute each iteration
	MaxIterations              int               // safety limit (default: 100, max: 10000)
	MaxIterationsExpr          string            // dynamic expression for max_iterations (e.g., "{{inputs.limit}}")
	MaxIterationsExplicitlySet bool              // true if max_iterations was explicitly set in YAML (even if zero)
	BreakCondition             string            // optional early exit expression
	OnComplete                 string            // next state after loop completes
	MemoryConfig               *LoopMemoryConfig // C019: Rolling window memory management
}

LoopConfig holds configuration for loop execution.

func (*LoopConfig) IsMaxIterationsDynamic

func (c *LoopConfig) IsMaxIterationsDynamic() bool

IsMaxIterationsDynamic returns true if max_iterations uses a dynamic expression.

func (*LoopConfig) Validate

func (c *LoopConfig) Validate() error

Validate checks if the loop configuration is valid.

type LoopContext

type LoopContext struct {
	Item   any          // current item value (for_each)
	Index  int          // 0-based iteration index
	First  bool         // true on first iteration
	Last   bool         // true on last iteration (for_each only)
	Length int          // total items count (for_each only, -1 for while)
	Parent *LoopContext // reference to enclosing loop (F043: nested loops)
}

LoopContext holds the current loop iteration state.

type LoopMemoryConfig

type LoopMemoryConfig struct {
	MaxRetainedIterations int // 0 = keep all (default for backward compatibility)
}

LoopMemoryConfig configures loop memory retention behavior. C019: Prevents OOM from unbounded LoopResult.Iterations accumulation.

func DefaultLoopMemoryConfig

func DefaultLoopMemoryConfig() LoopMemoryConfig

DefaultLoopMemoryConfig returns the default loop memory configuration. Maintains backward compatibility with unlimited iteration retention.

type LoopResult

type LoopResult struct {
	Iterations  []IterationResult
	TotalCount  int
	BrokeAt     int    // -1 if completed normally, index if break triggered
	NextStep    string // F048 T007: Target step when loop exits early via transition
	StartedAt   time.Time
	CompletedAt time.Time

	// C019: Memory management fields
	PrunedCount int // Number of iterations pruned from memory (for rolling window)
}

LoopResult holds aggregated results of loop execution.

func NewLoopResult

func NewLoopResult() *LoopResult

NewLoopResult creates a new LoopResult with initialized values.

func (*LoopResult) AllSucceeded

func (r *LoopResult) AllSucceeded() bool

AllSucceeded returns true if all iterations succeeded.

func (*LoopResult) Duration

func (r *LoopResult) Duration() time.Duration

Duration returns the total execution time.

func (*LoopResult) WasBroken

func (r *LoopResult) WasBroken() bool

WasBroken returns true if the loop was terminated by a break condition.

type LoopType

type LoopType string

LoopType defines the type of loop construct.

const (
	LoopTypeForEach LoopType = "for_each"
	LoopTypeWhile   LoopType = "while"
)

func (LoopType) String

func (t LoopType) String() string

type MissingParameterError

type MissingParameterError struct {
	TemplateName  string   // template name
	ParameterName string   // missing parameter name
	Required      []string // list of all required parameters
}

MissingParameterError indicates a required template parameter was not provided.

func (*MissingParameterError) Error

func (e *MissingParameterError) Error() string

type OutputFormat

type OutputFormat string

OutputFormat represents the format for agent output post-processing.

const (
	OutputFormatNone OutputFormat = ""
	OutputFormatJSON OutputFormat = "json"
	OutputFormatText OutputFormat = "text"
)

type OutputLimits

type OutputLimits struct {
	MaxSize           int64  // Max bytes per output field (0 = unlimited)
	StreamLargeOutput bool   // If true, stream to file; if false, truncate
	TempDir           string // Directory for temp files
}

OutputLimits configures output capture limits and streaming behavior. C019: Prevents OOM from unbounded StepState.Output/Stderr growth.

func DefaultOutputLimits

func DefaultOutputLimits() OutputLimits

DefaultOutputLimits returns the default output configuration. Maintains backward compatibility with no limits.

type ParallelConfig

type ParallelConfig struct {
	Strategy      ParallelStrategy
	MaxConcurrent int
}

ParallelConfig holds configuration for parallel execution.

type ParallelResult

type ParallelResult struct {
	Results      map[string]*BranchResult
	FirstError   error
	SuccessCount int
	FailureCount int
	StartedAt    time.Time
	CompletedAt  time.Time
}

ParallelResult holds the aggregated results of parallel execution.

func NewParallelResult

func NewParallelResult() *ParallelResult

NewParallelResult creates a new ParallelResult.

func (*ParallelResult) AddResult

func (r *ParallelResult) AddResult(result *BranchResult)

AddResult records a branch result and updates counters.

func (*ParallelResult) AllSucceeded

func (r *ParallelResult) AllSucceeded() bool

AllSucceeded returns true if all branches succeeded.

func (*ParallelResult) AnySucceeded

func (r *ParallelResult) AnySucceeded() bool

AnySucceeded returns true if at least one branch succeeded.

func (*ParallelResult) Duration

func (r *ParallelResult) Duration() time.Duration

Duration returns the total execution time.

type ParallelStrategy

type ParallelStrategy string

ParallelStrategy defines how parallel execution results are evaluated.

const (
	// StrategyAllSucceed requires all branches to succeed; cancels remaining on first failure.
	StrategyAllSucceed ParallelStrategy = "all_succeed"
	// StrategyAnySucceed succeeds if at least one branch succeeds.
	StrategyAnySucceed ParallelStrategy = "any_succeed"
	// StrategyBestEffort runs all branches and collects all results regardless of failures.
	StrategyBestEffort ParallelStrategy = "best_effort"
)

func ParseParallelStrategy

func ParseParallelStrategy(s string) ParallelStrategy

ParseParallelStrategy converts a string to ParallelStrategy. Returns DefaultParallelStrategy for empty or invalid values.

func (ParallelStrategy) String

func (s ParallelStrategy) String() string

type ReferenceType

type ReferenceType string

ReferenceType categorizes the namespace of a template reference.

const (
	// TypeInputs references workflow input parameters ({{inputs.name}}).
	TypeInputs ReferenceType = "inputs"
	// TypeStates references step output data ({{states.step.output}}).
	TypeStates ReferenceType = "states"
	// TypeWorkflow references workflow metadata ({{workflow.id}}).
	TypeWorkflow ReferenceType = "workflow"
	// TypeEnv references environment variables ({{env.VAR}}).
	TypeEnv ReferenceType = "env"
	// TypeError references error data in error hooks ({{error.message}}).
	TypeError ReferenceType = "error"
	// TypeContext references runtime context ({{context.working_dir}}).
	TypeContext ReferenceType = "context"
	// TypeLoop references loop runtime data ({{loop.Index}}).
	TypeLoop ReferenceType = "loop"
	// TypeUnknown for unrecognized namespaces.
	TypeUnknown ReferenceType = "unknown"
)

type RetryConfig

type RetryConfig struct {
	MaxAttempts        int     // max retry attempts (default: 1)
	InitialDelayMs     int     // initial delay in milliseconds
	MaxDelayMs         int     // max delay in milliseconds
	Backoff            string  // constant, linear, exponential
	Multiplier         float64 // for exponential backoff
	Jitter             float64 // ± randomization (0.0-1.0)
	RetryableExitCodes []int   // exit codes to retry on
}

RetryConfig defines retry behavior for a step.

func (*RetryConfig) Validate

func (r *RetryConfig) Validate() error

Validate checks if the retry configuration values are within valid ranges.

type RuntimeContext

type RuntimeContext struct {
	Inputs   map[string]any
	States   map[string]RuntimeStepState
	Workflow RuntimeWorkflowData
	Env      map[string]string
	Context  RuntimeContextData
	Error    *RuntimeErrorData
	Loop     *RuntimeLoopData
}

RuntimeContext provides all variable namespaces available during execution. This is a domain-pure representation used for displaying context to users.

type RuntimeContextData

type RuntimeContextData struct {
	WorkingDir string
	User       string
	Hostname   string
}

RuntimeContextData holds runtime context information.

type RuntimeErrorData

type RuntimeErrorData struct {
	Message  string
	State    string
	ExitCode int
	Type     string
}

RuntimeErrorData holds error information for error hooks.

type RuntimeLoopData

type RuntimeLoopData struct {
	Item   any
	Index  int
	First  bool
	Last   bool
	Length int
	Parent *RuntimeLoopData
}

RuntimeLoopData holds loop iteration context.

func (*RuntimeLoopData) Index1

func (l *RuntimeLoopData) Index1() int

Index1 returns the 1-based iteration index.

type RuntimeStepState

type RuntimeStepState struct {
	Output   string
	Stderr   string
	ExitCode int
	Status   string
}

RuntimeStepState holds step execution results.

type RuntimeWorkflowData

type RuntimeWorkflowData struct {
	ID           string
	Name         string
	CurrentState string
	StartedAt    time.Time
}

RuntimeWorkflowData holds workflow metadata.

func (RuntimeWorkflowData) Duration

func (w RuntimeWorkflowData) Duration() string

Duration returns workflow duration as a formatted string.

type SlidingWindowStrategy

type SlidingWindowStrategy struct{}

func NewSlidingWindowStrategy

func NewSlidingWindowStrategy() *SlidingWindowStrategy

func (*SlidingWindowStrategy) Apply

func (s *SlidingWindowStrategy) Apply(turns []Turn, maxTokens int) ([]Turn, bool, error)

type StateReferenceError

type StateReferenceError struct {
	StepName        string
	ReferencedState string
	AvailableStates []string
	Field           string // "initial", "on_success", "on_failure", "transition", "loop_body", "on_complete"
}

StateReferenceError represents a reference to an undefined state. This domain error carries structured information about invalid state references for conversion to StructuredError in the application layer.

func (*StateReferenceError) Error

func (e *StateReferenceError) Error() string

type Step

type Step struct {
	Name            string
	Type            StepType
	Description     string
	Command         string               // for command type
	ScriptFile      string               // F064: external script file (XOR with Command)
	Dir             string               // working directory for command execution
	Operation       string               // F021: plugin operation name (e.g., "slack.send")
	OperationInputs map[string]any       // F021: plugin operation input parameters
	Branches        []string             // for parallel type
	Strategy        string               // for parallel: all_succeed, any_succeed, best_effort
	MaxConcurrent   int                  // for parallel: max concurrent branches
	Timeout         int                  // seconds
	OnSuccess       string               // next state name (legacy, use Transitions)
	OnFailure       string               // next state name (legacy, use Transitions)
	Transitions     Transitions          // conditional transitions (takes precedence over OnSuccess/OnFailure)
	DependsOn       []string             // for ordering in parallel execution
	Retry           *RetryConfig         // retry configuration
	Capture         *CaptureConfig       // output capture configuration
	Hooks           StepHooks            // pre/post hooks
	ContinueOnError bool                 // don't fail workflow on error
	Status          TerminalStatus       // for terminal type: success or failure
	Message         string               // for terminal type: message template (interpolated at runtime)
	ExitCode        int                  // for terminal type: process exit code (FR-004: inline default 1)
	Loop            *LoopConfig          // for for_each and while types
	TemplateRef     *WorkflowTemplateRef // template reference (for use_template steps)
	CallWorkflow    *CallWorkflowConfig  // for call_workflow type: sub-workflow configuration
	Agent           *AgentConfig         // for agent type: AI agent configuration
	Config          map[string]any       // C069: plugin-provided step type configuration
}

Step represents a single step in a workflow state machine.

func (*Step) Validate

func (s *Step) Validate(validator ExpressionCompiler, checker StepTypeChecker) error

Validate checks if the step configuration is valid. The validator parameter is used to check expression syntax in agent configurations. The checker parameter is used to accept unknown step types registered by plugins; pass nil to reject all unknown types (backward-compatible behavior).

type StepHooks

type StepHooks struct {
	Pre  Hook
	Post Hook
}

type StepState

type StepState struct {
	Name        string
	Status      ExecutionStatus
	Output      string
	Stderr      string
	ExitCode    int
	Attempt     int
	Error       string
	StartedAt   time.Time
	CompletedAt time.Time
	Response    map[string]any // parsed JSON response from agent steps
	JSON        any            // parsed JSON output when output_format: json is specified (map[string]any or []any)
	// F033: Conversation mode fields
	Conversation       *ConversationState  // conversation history and state (nil for non-conversation steps)
	TokensUsed         int                 // total tokens used in conversation mode
	ContextWindowState *ContextWindowState // context window management state (nil if not applicable)

	// C019: Output streaming fields for memory management
	OutputPath string // Path to temp file if output was streamed (empty if in-memory)
	StderrPath string // Path to temp file if stderr was streamed (empty if in-memory)
	Truncated  bool   // True if output was truncated (not streamed)

	// C069: Structured output from custom step types, accessible via {{states.step_name.Data.key}}
	Data map[string]any
}

StepState holds the execution state of a single step.

type StepType

type StepType string

StepType defines the type of workflow step.

const (
	StepTypeCommand      StepType = "command"
	StepTypeParallel     StepType = "parallel"
	StepTypeTerminal     StepType = "terminal"
	StepTypeForEach      StepType = "for_each"
	StepTypeWhile        StepType = "while"
	StepTypeOperation    StepType = "operation"     // F021: plugin-provided operation
	StepTypeCallWorkflow StepType = "call_workflow" // F023: invoke another workflow
	StepTypeAgent        StepType = "agent"         // F039: AI agent invocation
)

func (StepType) String

func (s StepType) String() string

type StepTypeChecker added in v0.5.0

type StepTypeChecker func(typeName string) bool

StepTypeChecker is a function type for querying whether a step type name is registered by a plugin provider. Defined in the workflow package to avoid import cycles. Returns true if the type is known (custom step type accepted), false otherwise.

type StopReason

type StopReason string

StopReason indicates why a conversation stopped.

const (
	StopReasonCondition StopReason = "condition"
	StopReasonMaxTurns  StopReason = "max_turns"
	StopReasonMaxTokens StopReason = "max_tokens"
	StopReasonError     StopReason = "error"
)

type SubWorkflowResult

type SubWorkflowResult struct {
	WorkflowName string         // name of the executed sub-workflow
	Outputs      map[string]any // mapped output values
	Error        error          // execution error, if any
	StartedAt    time.Time
	CompletedAt  time.Time
}

SubWorkflowResult holds the result of a sub-workflow execution.

func NewSubWorkflowResult

func NewSubWorkflowResult(workflowName string) *SubWorkflowResult

NewSubWorkflowResult creates a new SubWorkflowResult with initialized values.

func (*SubWorkflowResult) Duration

func (r *SubWorkflowResult) Duration() time.Duration

Duration returns the execution time of the sub-workflow.

func (*SubWorkflowResult) Success

func (r *SubWorkflowResult) Success() bool

Success returns true if the sub-workflow completed without error.

type SummarizeStrategy

type SummarizeStrategy struct{}

func NewSummarizeStrategy

func NewSummarizeStrategy() *SummarizeStrategy

func (*SummarizeStrategy) Apply

func (s *SummarizeStrategy) Apply(turns []Turn, maxTokens int) ([]Turn, bool, error)

type Template

type Template struct {
	Name       string
	Parameters []TemplateParam
	States     map[string]*Step
}

Template represents a reusable workflow template.

func (*Template) GetDefaultValues

func (t *Template) GetDefaultValues() map[string]any

GetDefaultValues returns a map of parameter defaults.

func (*Template) GetRequiredParams

func (t *Template) GetRequiredParams() []string

GetRequiredParams returns names of required parameters.

func (*Template) Validate

func (t *Template) Validate() error

Validate checks if the template is valid.

type TemplateAnalyzer

type TemplateAnalyzer interface {
	// ExtractReferences parses a template string and returns all interpolation references.
	ExtractReferences(template string) ([]TemplateReference, error)
}

TemplateAnalyzer parses templates and extracts interpolation references.

type TemplateNotFoundError

type TemplateNotFoundError struct {
	TemplateName string // name of the missing template
	ReferencedBy string // file or step that referenced it
}

TemplateNotFoundError indicates a referenced template does not exist.

func (*TemplateNotFoundError) Error

func (e *TemplateNotFoundError) Error() string

type TemplateParam

type TemplateParam struct {
	Name     string
	Required bool
	Default  any
}

TemplateParam defines a template parameter.

type TemplateReference

type TemplateReference struct {
	Type      ReferenceType // namespace type (inputs, states, etc.)
	Namespace string        // first path segment (e.g., "inputs")
	Path      string        // full dot-separated path (e.g., "name" for inputs.name)
	Property  string        // property being accessed (e.g., "output" for states.step.output)
	Raw       string        // original template string (e.g., "{{inputs.name}}")
}

TemplateReference represents a parsed template interpolation reference.

type TemplateValidator

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

TemplateValidator validates template interpolation references in workflows.

func NewTemplateValidator

func NewTemplateValidator(w *Workflow, analyzer TemplateAnalyzer) *TemplateValidator

NewTemplateValidator creates a validator for the given workflow. The analyzer parameter is used to extract template references.

func (*TemplateValidator) Validate

func (v *TemplateValidator) Validate() *ValidationResult

Validate performs template reference validation on the entire workflow. Returns a ValidationResult containing all errors and warnings found. Does not fail-fast; collects all issues in a single pass.

func (*TemplateValidator) ValidateReference

func (v *TemplateValidator) ValidateReference(ref *TemplateReference, stepName, fieldName string, currentStepIndex int, isErrorHook bool)

ValidateReference validates a single reference against the workflow context.

func (*TemplateValidator) ValidateStep

func (v *TemplateValidator) ValidateStep(step *Step, isErrorHook bool)

ValidateStep validates template references within a single step. The isErrorHook parameter indicates if this is an error hook context (where {{error.*}} references are allowed).

func (*TemplateValidator) ValidateTemplate

func (v *TemplateValidator) ValidateTemplate(template, stepName, fieldName string, currentStepIndex int, isErrorHook bool)

ValidateTemplate extracts and validates all references in a template string. stepName and fieldName provide context for error messages. currentStepIndex is used to detect forward references.

type TerminalStatus

type TerminalStatus string

TerminalStatus defines the outcome of a terminal state.

const (
	TerminalSuccess TerminalStatus = "success"
	TerminalFailure TerminalStatus = "failure"
)

type Transition

type Transition struct {
	When string
	Goto string
}

func (Transition) String

func (tr Transition) String() string

func (Transition) Validate

func (tr Transition) Validate() error

type Transitions

type Transitions []Transition

Evaluated in order; first match wins. A transition with empty When serves as the default fallback.

func (Transitions) DefaultIndex

func (t Transitions) DefaultIndex() int

func (Transitions) EvaluateFirstMatch

func (t Transitions) EvaluateFirstMatch(eval EvaluatorFunc) (nextStep string, found bool, err error)

func (Transitions) GetTargetStates

func (t Transitions) GetTargetStates() []string

func (Transitions) HasDefault

func (t Transitions) HasDefault() bool

func (Transitions) Validate

func (t Transitions) Validate() error

type TruncateMiddleStrategy

type TruncateMiddleStrategy struct{}

func NewTruncateMiddleStrategy

func NewTruncateMiddleStrategy() *TruncateMiddleStrategy

func (*TruncateMiddleStrategy) Apply

func (t *TruncateMiddleStrategy) Apply(turns []Turn, maxTokens int) ([]Turn, bool, error)

type Turn

type Turn struct {
	Role    TurnRole // system, user, or assistant
	Content string   // message content
	Tokens  int      // token count for this turn
}

Turn represents a single message in a conversation.

func NewTurn

func NewTurn(role TurnRole, content string) *Turn

NewTurn creates a new Turn with the given role and content.

func (*Turn) Validate

func (t *Turn) Validate() error

Validate checks if the turn is valid.

type TurnRole

type TurnRole string

TurnRole represents the role of a conversation turn participant.

const (
	TurnRoleSystem    TurnRole = "system"
	TurnRoleUser      TurnRole = "user"
	TurnRoleAssistant TurnRole = "assistant"
)

type ValidationCode

type ValidationCode string

ValidationCode identifies specific validation issues.

const (
	ErrCycleDetected       ValidationCode = "cycle_detected"
	ErrUnreachableState    ValidationCode = "unreachable_state"
	ErrInvalidTransition   ValidationCode = "invalid_transition"
	ErrNoTerminalState     ValidationCode = "no_terminal_state"
	ErrMissingInitialState ValidationCode = "missing_initial_state"

	// Template reference validation codes
	ErrUndefinedInput           ValidationCode = "undefined_input"
	ErrUndefinedStep            ValidationCode = "undefined_step"
	ErrForwardReference         ValidationCode = "forward_reference"
	ErrInvalidWorkflowProperty  ValidationCode = "invalid_workflow_property"
	ErrInvalidStateProperty     ValidationCode = "invalid_state_property"
	ErrInvalidErrorProperty     ValidationCode = "invalid_error_property"
	ErrInvalidContextProperty   ValidationCode = "invalid_context_property"
	ErrInvalidLoopProperty      ValidationCode = "invalid_loop_property"
	ErrUnknownReferenceType     ValidationCode = "unknown_reference_type"
	ErrErrorRefOutsideErrorHook ValidationCode = "error_ref_outside_error_hook"

	// Loop expression validation codes
	ErrUndefinedLoopVariable ValidationCode = "undefined_loop_variable"

	// Sub-workflow validation codes
	ErrCircularWorkflowCall ValidationCode = "circular_workflow_call"
	ErrUndefinedSubworkflow ValidationCode = "undefined_subworkflow"
	ErrMaxNestingExceeded   ValidationCode = "max_nesting_exceeded"
)

type ValidationError

type ValidationError struct {
	Level   ValidationLevel
	Code    ValidationCode
	Message string
	Path    string // e.g., "states.validate.on_success"
}

ValidationError represents a single validation issue.

func (ValidationError) Error

func (e ValidationError) Error() string

Error implements the error interface.

func (ValidationError) IsError

func (e ValidationError) IsError() bool

IsError returns true if this is an error-level issue (not a warning).

type ValidationLevel

type ValidationLevel string

ValidationLevel indicates the severity of a validation issue.

const (
	ValidationLevelError   ValidationLevel = "error"
	ValidationLevelWarning ValidationLevel = "warning"
)

type ValidationResult

type ValidationResult struct {
	Errors   []ValidationError
	Warnings []ValidationError
}

ValidationResult holds the complete result of graph validation.

func ValidateGraph

func ValidateGraph(steps map[string]*Step, initial string) *ValidationResult

ValidateGraph performs graph validation on a workflow's state machine. It checks for: - All referenced states exist (on_success, on_failure targets) - All states are reachable from the initial state (orphan detection) - At least one terminal state exists - Cycle detection (warning, not error)

Returns a ValidationResult containing errors and warnings.

func (*ValidationResult) AddError

func (r *ValidationResult) AddError(code ValidationCode, path, message string)

AddError adds an error-level validation issue.

func (*ValidationResult) AddWarning

func (r *ValidationResult) AddWarning(code ValidationCode, path, message string)

AddWarning adds a warning-level validation issue.

func (*ValidationResult) AllIssues

func (r *ValidationResult) AllIssues() []ValidationError

AllIssues returns all errors and warnings combined.

func (*ValidationResult) HasErrors

func (r *ValidationResult) HasErrors() bool

HasErrors returns true if there are any error-level issues.

func (*ValidationResult) HasWarnings

func (r *ValidationResult) HasWarnings() bool

HasWarnings returns true if there are any warning-level issues.

func (*ValidationResult) ToError

func (r *ValidationResult) ToError() error

ToError converts the validation result to a single error if there are errors. Returns nil if no errors (warnings don't cause an error).

type VisitState

type VisitState string

VisitState represents the DFS visit state of a node during graph traversal. Used for three-color marking in cycle detection: - Unvisited: node has not been encountered yet - Visiting: node is currently in the DFS path (on stack) - Visited: node has been fully processed (all descendants explored)

const (
	// VisitStateUnvisited indicates a node has not been encountered yet (white in DFS).
	VisitStateUnvisited VisitState = "unvisited"
	// VisitStateVisiting indicates a node is currently in the DFS path (gray in DFS).
	VisitStateVisiting VisitState = "visiting"
	// VisitStateVisited indicates a node has been fully processed (black in DFS).
	VisitStateVisited VisitState = "visited"
)

func (VisitState) String

func (v VisitState) String() string

String returns the string representation of the VisitState.

type Workflow

type Workflow struct {
	Name        string
	Description string
	Version     string
	Author      string
	Tags        []string
	Inputs      []Input
	Env         []string          // required environment variables
	Initial     string            // initial state name
	Steps       map[string]*Step  // state name -> step
	Hooks       WorkflowHooks     // workflow-level hooks
	Plugins     map[string]string // alias → manifest name (e.g. "pg" → "database")
	SourceDir   string            // workflow file directory for path resolution (runtime metadata)
}

Workflow represents a complete workflow definition.

func (*Workflow) GetStep

func (w *Workflow) GetStep(name string) (*Step, bool)

GetStep retrieves a step by name.

func (*Workflow) ResolveStepType added in v0.5.0

func (w *Workflow) ResolveStepType(typeName string) string

ResolveStepType resolves a step type name through plugin aliases. "pg.query" with alias pg→database returns "database.query". Names without aliases or without a dot pass through unchanged.

func (*Workflow) Validate

func (w *Workflow) Validate(validator ExpressionCompiler, checker StepTypeChecker) error

Validate checks if the workflow configuration is valid. The validator parameter is used to check expression syntax in agent configurations. The checker parameter is forwarded to each Step.Validate() call; pass nil to reject unknown step types.

type WorkflowHooks

type WorkflowHooks struct {
	WorkflowStart  Hook
	WorkflowEnd    Hook
	WorkflowError  Hook
	WorkflowCancel Hook
}

type WorkflowTemplateRef

type WorkflowTemplateRef struct {
	TemplateName string
	Parameters   map[string]any
}

WorkflowTemplateRef references a template from a step.

Jump to

Keyboard shortcuts

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