Table of Contents

1. System Boundary Contracts

All data entering or leaving pagantic flows through two types: SystemRequest (inbound) and SystemResponse (outbound). These types define the system boundary. No internal layer is accessible without passing through them first.

SystemRequest

Input from adapters into the system. Adapters construct this from external input - HTTP requests, CLI arguments, TUI interactions - and pass it to the orchestration facade.

SystemRequest {
    // Correlation
    RequestID   string          // Unique per request, generated by adapter if not provided
    SessionID   string          // Stable per conversation (AgentLoop sessions)
    TraceID     string          // Distributed tracing root

    // Intent
    Messages    []core.Message  // Conversation messages
    Mode        Mode            // chat | structured | plan | redundant

    // Execution Hints
    Hints       ExecutionHints  // Optional tuning knobs

    // Output Contract
    Output      OutputContract  // Schema/grammar expectations

    // Capabilities
    Tools       []string        // Allowed tool names (empty = all registered)
}
RequestID
Unique identifier for this request. If the adapter does not provide one, pagantic generates a UUID at the system boundary. Used to correlate all events, logs, and spans belonging to this request.
SessionID
Stable identifier for a multi-turn conversation. All requests in the same AgentLoop session share a SessionID. Single-shot requests may leave this empty.
TraceID
Distributed tracing root. Propagated from external callers (e.g., HTTP trace headers) or generated internally. All spans created during execution are children of this trace.
Messages
Ordered conversation history. Each core.Message carries a role (system, user, assistant, tool) and content. The orchestration layer reads these to build inference prompts.
Mode
Selects the orchestration pattern: chat routes to AgentLoop, structured to SpecializedLoop, plan to PlanExecutor, redundant to RedundantLoop.
Hints
Optional execution tuning. See ExecutionHints below. Adapters pass these through without interpretation.
Output
Defines expected output structure. See OutputContract below. When a schema is provided, the system uses constraint enforcement to guarantee conformance.
Tools
Whitelist of tool names the request is allowed to use. Empty means all registered tools are available. This enables per-request capability scoping.

SystemResponse

Returned by the orchestration facade after execution completes (or fails). Adapters map this back to whatever format the external caller expects.

SystemResponse {
    // Correlation (echo)
    RequestID       string
    SessionID       string

    // Output
    Content         string              // Text response
    StructuredOutput any                // Parsed output when schema provided
    ToolCallsMade   []core.ToolCall     // Log of tool invocations during execution

    // Quality
    Confidence      *float64            // Optional [0..1] confidence score
    ConfidenceSource string             // "voting" | "validation" | "retrieval"

    // Usage
    TokenUsage      core.TokenUsage

    // Error
    Error           *SystemError        // Non-nil on failure
}
RequestID / SessionID
Echoed from SystemRequest for correlation. Callers match response to request using RequestID.
Content
Plain text response from the model. Always populated for successful requests. For structured mode, this contains the raw text before parsing.
StructuredOutput
Parsed and validated output when OutputContract includes a schema. Type is any because the shape depends on the caller's schema. Nil when no schema was provided.
ToolCallsMade
Ordered log of every tool invocation that occurred during execution. Each record includes tool name, arguments, result, and duration. Useful for auditing and debugging.
Confidence
Optional score in [0..1] range. Populated by RedundantLoop (voting consensus), validation (rule pass rate), or retrieval (relevance score).
ConfidenceSource
Identifies which mechanism produced the Confidence value: "voting", "validation", or "retrieval".
ValidationResult
Summary of constraint and rule validation. Includes pass/fail counts, repair attempts, and any remaining violations. Nil when no validation was performed.
TokenUsage
Aggregated token consumption across all inference calls in this request. Includes prompt tokens, completion tokens, and total.
Error
Non-nil when execution failed. Contains a SystemError with category, error code, and retry guidance. When Error is set, Content may still contain partial output.

SystemError

Structured error type returned in SystemResponse.Error. Designed for programmatic handling - callers inspect Category and Retryable rather than parsing message strings.

SystemError {
    Code        string              // Stable error code, e.g. "TOOL_EXECUTION_FAILED"
    Category    FailureCategory     // From failure taxonomy
    Retryable   bool                // Whether caller should retry
    Message     string              // Human-readable description
    Details     map[string]any      // Structured diagnostic data
    CausedBy    error               // Optional wrapped cause
}
Code
Stable, machine-readable error code. Follows pattern CATEGORY_SPECIFIC_ERROR (e.g., TOOL_EXECUTION_FAILED, CONSTRAINT_SCHEMA_INVALID). Callers switch on this for programmatic handling.
Category
Broad failure classification from the failure taxonomy. Determines retry eligibility and recovery path.
Retryable
Hint to callers. When true, re-submitting the same request (possibly after backoff) has a reasonable chance of success. When false, the request needs modification or configuration change.
Message
Human-readable description for logs and debugging. Not stable - do not parse programmatically.
Details
Structured key-value pairs with diagnostic context. May include model name, token count at failure, schema path that failed validation, etc.
CausedBy
Wrapped underlying error for error chain traversal. May be nil when the error originated at the pagantic boundary.

ExecutionHints

Optional tuning knobs passed through SystemRequest.Hints. Adapters forward these without interpretation. The orchestration layer applies them during PREPARE and EXECUTE phases.

ExecutionHints {
    MaxTokens   int             // Token limit for inference response
    Timeout     time.Duration   // Deadline for entire execution
    Temperature float64         // Model temperature (0.0 = deterministic)
    TopP        float64         // Nucleus sampling parameter
    Options     map[string]any  // Vendor-specific pass-through
}
MaxTokens
Upper bound on tokens the model may generate in a single inference call. Zero means use engine default.
Timeout
Deadline for the entire request lifecycle. When exceeded, execution transitions to CANCELLED state. Zero means no timeout.
Temperature
Controls randomness. 0.0 produces deterministic output (greedy decoding). Higher values increase creativity and variance. Typical range: 0.0 - 1.0.
TopP
Nucleus sampling threshold. Model considers only tokens whose cumulative probability reaches TopP. Works alongside Temperature. Zero means use engine default.
Options
Vendor-specific parameters passed directly to the inference engine. pagantic does not inspect these - they flow through to the engine unchanged.

OutputContract

Defines the expected shape of model output. When populated, the system enforces conformance using constraint and validation layers.

OutputContract {
    Schema          *core.Schema    // JSON schema for structured output
    Grammar         *string         // GBNF grammar for decoder constraint
    RepairAllowed   bool            // Whether JSON repair is permitted
    StrictValidation bool           // Fail on any validation error (no partial)
}
Schema
JSON Schema definition. When set, model output is parsed and validated against this schema. Drives schema validation in Layer 5.
Grammar
GBNF grammar string. When set, the inference engine constrains token generation at the decoder level. See GBNF Grammar Constraints.
RepairAllowed
When true, the system attempts JSON repair before failing on malformed output. When false, any structural error is terminal.
StrictValidation
When true, any validation failure is terminal - no partial results are returned. When false, the system may return partially valid output with validation warnings.
Adapter boundary rule. Every adapter (cli, tui, api) maps external input into SystemRequest and maps SystemResponse back to the user. Adapters never access orchestration, inference, or tool layers directly.

Mode-to-Pattern Mapping

Each Mode selects an orchestration pattern. The pattern determines which SystemResponse fields are populated:

Pattern Mode SystemResponse fields produced
AgentLoop chat Content, ToolCallsMade, TokenUsage
SpecializedLoop structured Content, StructuredOutput, ValidationResult, TokenUsage
PlanExecutor plan Content, StructuredOutput (per step), ToolCallsMade, TokenUsage
RedundantLoop redundant Content, StructuredOutput, Confidence, ConfidenceSource, TokenUsage

2. Execution Lifecycle

Every SystemRequest passes through a state machine from receipt to response. The states are fixed; which states are visited depends on the orchestration pattern selected by Mode.

State Machine

+--------+ | INIT | Received request; validate envelope +----+---+ | +----v---+ | PLAN | Optional: create ExecutionPlan (mode=plan) +----+---+ | +-----v------+ | PREPARE | Gather context, tools, schema, grammar +-----+------+ | +-----v------+ | EXECUTE | Run loop / steps / inference +-----+------+ | +-----v------+ | VALIDATE | Constraints + rules + semantic checks +-----+------+ | +-----v------+ | COMPLETE | Final response assembled +------------+ Any state may transition to: +-------+ +-----------+ | ERROR | Terminal failure | CANCELLED | Context cancelled / timeout +-------+ +-----------+

State Definitions

INIT
Received SystemRequest. Validate envelope (required fields, mode validity). Assign correlation ids if missing. Transition: INIT -> PLAN (if mode=plan) or INIT -> PREPARE.
PLAN
Create ExecutionPlan from SystemRequest. Only entered when mode=plan or when a Planner is configured. Transition: PLAN -> PREPARE.
PREPARE
Assemble execution environment - resolve context provider, load tools, prepare schema/grammar, build system prompt. Transition: PREPARE -> EXECUTE.
EXECUTE
Run the selected Loop pattern. May include multiple inference calls, tool invocations, and inner loops. Transition: EXECUTE -> VALIDATE.
VALIDATE
Apply constraint pipeline and validation rules. Three outcomes: pass (-> COMPLETE), repairable (-> EXECUTE with repaired input), terminal failure (-> ERROR). This is where RetryPolicy controls the EXECUTE -> VALIDATE -> EXECUTE cycle.
COMPLETE
Assemble SystemResponse from execution results. Terminal state. No further transitions.
ERROR
Terminal failure. SystemError populated with failure category. No further transitions.
CANCELLED
Context was cancelled or timeout expired. Terminal state. No further transitions.

ExecutionState

Tracks the current position in the lifecycle state machine. Updated on every state transition.

ExecutionState {
    Current     LifecycleState  // Current state in the machine
    EnteredAt   time.Time       // When current state was entered
    Attempt     int             // Current attempt number (incremented on retry)
    TotalSteps  int             // Steps completed (PlanExecutor)
    LastError   *SystemError    // Most recent error (may be recovered from)
    LastStep    string          // Name of last completed step
}

ExecutionContext

Carries all state for a single request execution. Immutable fields are set at INIT. Mutable fields are updated as execution progresses through states.

ExecutionContext {
    // Immutable (set at INIT)
    RequestID   string
    SessionID   string
    TraceID     string
    Mode        Mode
    StartedAt   time.Time

    // Mutable (updated during execution)
    State       ExecutionState
    SelectedTools []string      // Tools resolved during PREPARE
    Candidates  []CandidateIR   // Current candidate set (rerank/voting)
    Metadata    map[string]any  // Extension point
}
Retry is a lifecycle transition. RetryPolicy is not a separate mechanism - it is a lifecycle transition: EXECUTE -> VALIDATE -> (back to EXECUTE on repair/retry, or -> ERROR on terminal failure). Each retry increments ExecutionState.Attempt.

Lifecycle per Orchestration Pattern

Pattern States Traversed Retry Path Tool Loop Notes
AgentLoop INIT -> PREPARE -> EXECUTE -> COMPLETE EXECUTE -> VALIDATE -> EXECUTE (per turn) Yes, within EXECUTE Multi-turn: EXECUTE/VALIDATE cycle repeats per user turn
SpecializedLoop INIT -> PREPARE -> EXECUTE -> VALIDATE -> COMPLETE VALIDATE -> EXECUTE No Single-shot with validation
PlanExecutor INIT -> PLAN -> PREPARE -> EXECUTE -> VALIDATE -> COMPLETE Per-step: EXECUTE -> VALIDATE -> EXECUTE Per step EXECUTE contains sub-cycles for each Step
RedundantLoop INIT -> PREPARE -> EXECUTE -> VALIDATE -> COMPLETE N/A (voting replaces retry) No EXECUTE runs N parallel inferences

3. Failure Taxonomy

Every error in pagantic belongs to exactly one FailureCategory. Categories determine retry eligibility, recovery path, and which layer emitted the error.

Category Error Code Pattern Retryable Recovery Path Emitting Layer
InferenceFailure INFERENCE_* Sometimes Retry with backoff inference (L01)
ToolFailure TOOL_* If idempotent Retry tool or skip tool (L04)
ConstraintFailure CONSTRAINT_* Yes JSON repair, re-infer constraint (L05)
ValidationFailure VALIDATION_* Yes Repair + re-infer, or prompt adjustment validate (L07)
OrchestrationFailure ORCHESTRATION_* No Manual intervention orchestrate (L02)
ConfigurationFailure CONFIG_* No Fix configuration Any layer at init
Cancellation CANCELLED No Re-submit request Any layer

InferenceFailure

Engine returned error, model unavailable, context window exceeded, or malformed response from the model.

INFERENCE_ENGINE_ERROR
Inference engine returned an unrecoverable error (HTTP 5xx, connection refused, etc.).
INFERENCE_MODEL_UNAVAILABLE
Requested model is not loaded or does not exist on the engine.
INFERENCE_CONTEXT_EXCEEDED
Input tokens exceed the model's context window. Reduce message history or context chunks.
INFERENCE_MALFORMED_RESPONSE
Engine returned a response that could not be parsed into the expected format.

ToolFailure

Tool not found in registry, execution returned error, timed out, or became unavailable mid-loop.

TOOL_NOT_FOUND
Model requested a tool name that is not in the registry.
TOOL_EXECUTION_FAILED
Tool's Execute method returned an error. Details include tool name and error message.
TOOL_TIMEOUT
Tool execution exceeded its deadline. The tool was cancelled via context.
TOOL_UNAVAILABLE
Tool's Available() returned false mid-execution. May happen when external dependencies go down.

ConstraintFailure

Grammar rejected output, schema validation failed, JSON is not valid, or enum value not recognized.

CONSTRAINT_GRAMMAR_REJECTED
Output violated the GBNF grammar. Should be rare when grammar is enforced at decoder level.
CONSTRAINT_SCHEMA_INVALID
Output failed JSON Schema validation. Details include the schema path and violation description.
CONSTRAINT_JSON_INVALID
Output is not valid JSON. If RepairAllowed is true, repair is attempted first.
CONSTRAINT_ENUM_UNRECOGNIZED
Output contains an enum value not in the allowed set. Enum normalization may recover from minor mismatches.

ValidationFailure

Rule check failed or semantic validation detected issues (hallucination, nonsensical output).

VALIDATION_RULE_FAILED
One or more validation rules returned failure. Details include which rules failed and why.
VALIDATION_SEMANTIC_FAILED
Semantic validation detected issues - hallucination, contradictions, or nonsensical output.

OrchestrationFailure

Plan step received unexpected input type, iteration limit exceeded, or no voting consensus reached.

ORCHESTRATION_STEP_MISMATCH
A PlanExecutor step received input that does not match its expected type.
ORCHESTRATION_ITERATION_LIMIT
Loop exceeded its maximum iteration count without reaching a terminal condition.
ORCHESTRATION_NO_CONSENSUS
RedundantLoop voting could not reach consensus across replicas.

ConfigurationFailure

Missing or invalid configuration detected at initialization time.

CONFIG_NO_ENGINE
No inference engine configured. At least one engine must be registered before requests can be processed.
CONFIG_SCHEMA_REQUIRED
Mode requires a schema (e.g., structured mode) but none was provided in OutputContract.
CONFIG_GRAMMAR_NOT_FOUND
OutputContract references a grammar file that does not exist on disk.

Cancellation

Request was cancelled externally or exceeded its deadline.

CANCELLED_TIMEOUT
ExecutionHints.Timeout or context deadline exceeded. Execution was interrupted at whatever state it had reached.
CANCELLED_SIGNAL
Explicit cancellation signal received (e.g., caller cancelled the context, HTTP client disconnected).
Pattern-failure contract. Every loop pattern documents which failure categories it can emit and which it can recover from. See the Pattern-Failure Matrix below.

Pattern-Failure Matrix

Pattern Can Emit Can Recover From
AgentLoop InferenceFailure, ToolFailure, Cancellation ToolFailure (retry tool call)
SpecializedLoop InferenceFailure, ConstraintFailure, ValidationFailure, Cancellation ConstraintFailure (repair), ValidationFailure (retry)
PlanExecutor All categories ConstraintFailure, ValidationFailure (per step), ToolFailure (if step uses tools)
RedundantLoop InferenceFailure, ConstraintFailure, OrchestrationFailure, Cancellation InferenceFailure (other replicas succeed), ConstraintFailure (repair per replica)

4. Observability Correlation Model

All observability events - logs, traces, metrics - carry correlation identifiers that link them back to the originating SystemRequest and execution context.

Correlation Identifiers

CorrelationContext {
    RequestID       string  // Stable per SystemRequest
    SessionID       string  // Stable per conversation (AgentLoop)
    TraceID         string  // Distributed tracing root
    SpanID          string  // Current execution unit
    ParentSpanID    string  // Parent in span hierarchy
    CausedBy        string  // Causal link: tool_call_id, step_name, etc.
}
RequestID
Ties all events for one SystemRequest together. Every event emitted during a request carries the same RequestID.
SessionID
Groups requests in a multi-turn conversation. Query all events with the same SessionID to see the full conversation history.
TraceID + SpanID
Form hierarchical execution tree. TraceID is the root; SpanID identifies the current unit of work. ParentSpanID links child spans to their parent, enabling tree reconstruction.
CausedBy
Links effects to causes. For example, a tool execution event's CausedBy points to the tool_call_id from the inference response that requested the tool call. A plan step's CausedBy points to the step_name.

Required Event Fields

All observability events must include these fields (when applicable):

Field Always Condition
request_id Yes Every event
session_id No When in AgentLoop (multi-turn)
step_name No When inside PlanExecutor
tool_call_id No When tool-related

Event Schema: Inference

InferenceStartEvent {
    CorrelationContext
    MessageCount    int
    ToolDefsCount   int
    SchemaPresent   bool
    GrammarPresent  bool
    Temperature     float64
}

InferenceEndEvent {
    CorrelationContext
    DurationMs      int64
    TokensIn        int
    TokensOut       int
    FinishReason    string  // "stop" | "tool" | "error"
    ToolCallCount   int
}

Event Schema: Tools

ToolStartEvent {
    CorrelationContext
    ToolName        string
    ToolCallID      string  // Links to inference ToolCall.ID
    ArgsHash        string  // Deterministic hash for dedup
}

ToolEndEvent {
    CorrelationContext
    ToolName        string
    ToolCallID      string
    DurationMs      int64
    Success         bool
    ErrorCode       string  // From failure taxonomy if failed
}

Event Schema: Lifecycle

LifecycleTransitionEvent {
    CorrelationContext
    FromState       string
    ToState         string
    Attempt         int
    Reason          string  // Why this transition happened
}
Full request timeline. With correlation ids on all events, you can reconstruct the full request execution timeline. Tool start/end events link to the inference response that emitted the tool call via ToolCallID.

5. Planning Contract

PlanExecutor is the executor of a plan, not the creator. Plans are produced by a Planner (or manually authored) and handed to PlanExecutor for execution.

Planner Interface

// Planner creates an ExecutionPlan from a SystemRequest.
// Implementations range from static plan builders to LLM-based planners.
Planner {
    CreatePlan(ctx context.Context, req SystemRequest) (ExecutionPlan, error)
}

Planner is a single-method interface. Implementations decide how to decompose a request into steps. A static planner might use a lookup table; an LLM-based planner makes an inference call to generate the plan.

PlanPolicy

Constraints on plan shape and execution. Applied by PlanExecutor before running any steps.

PlanPolicy {
    MaxSteps        int             // Upper bound on plan length
    AllowedStepTypes []string       // Which step types this mode permits
    RequireLinear   bool            // If true, no branching/parallel steps
    TimeoutPerStep  time.Duration   // Per-step deadline
}
MaxSteps
Upper bound on plan length. Plans exceeding this are rejected before execution begins.
AllowedStepTypes
Whitelist of step types permitted in this plan. Steps with unlisted types are rejected.
RequireLinear
When true, the plan must be a linear sequence - no branching or parallel steps. Simplifies execution and debugging.
TimeoutPerStep
Individual deadline for each step. Steps exceeding this are cancelled and the step transitions to ERROR.

PlanTrace

Metadata about plan creation. Attached to the ExecutionPlan for observability and debugging.

PlanTrace {
    PlannerID   string              // Which planner created this plan
    Rationale   string              // Why these steps were chosen
    CreatedAt   time.Time
    StepCount   int
}
Routing through the facade. Adapters route requests through a single facade. When mode=plan, the facade calls the configured Planner to produce an ExecutionPlan, then passes it to PlanExecutor. When a plan is provided directly, Planner is skipped.