Getting Started
Architecture
The Core Model
A loop is a finite state machine with governed transitions. Every transition has a signal that triggers it, actors who can send it, and guards that must pass before it executes.
1 signal2State A --------> State B3 ^4 actor + guards5 + evidenceThe Six Building Blocks
1) Loops
Loops are the unit of governed work. They define states, transitions, and outcomes.
1type LoopDefinition = {2 loopId: string;3 states: Array<{ stateId: string; terminal?: boolean }>;4 initialState: string;5 transitions: Array<{ transitionId: string; from: string; to: string; signal: string }>;6};2) Signals
Signals are the triggers for state transitions. They carry actor context and evidence.
1type SignalSpec = {2 signalId: string;3 name: string;4 description?: string;5};3) Actors
Actors represent who initiated a transition. Loop Engine supports three primary actor classes.
1type ActorType = "human" | "automation" | "ai-agent";4) Guards
Guards are policy checks evaluated before state advancement. Hard failures block. Soft failures warn.
1type GuardSpec = {2 guardId: string;3 severity: "hard" | "soft";4 evaluatedBy: "runtime" | "module" | "external";5};6 7declare function evaluateGuards(...args: unknown[]): Promise<{8 hardFailures: unknown[];9 softFailures: unknown[];10 allPassed: boolean;11}>;5) Events
Every transition produces immutable events with actor attribution and evidence.
1type LoopTransitionExecutedEvent = {2 type: "loop.transition.executed";3 loopId: string;4 aggregateId: string;5 transitionId: string;6 fromState: string;7 toState: string;8 actor: { type: ActorType; id: string };9 evidence?: Record<string, unknown>;10};6) Learning Signals
When a loop closes, learning signals capture predicted vs actual outcomes for evaluation and model improvement.
1type LearningSignal = {2 loopId: string;3 aggregateId: string;4 durationMs: number;5 predicted?: Record<string, number>;6 actual?: Record<string, number>;7 delta?: Record<string, number>;8};How They Fit Together
1import { createLoopSystem } from "@loop-engine/sdk";2import { createAnthropicActorAdapter } from "@loop-engine/adapter-anthropic";3import Anthropic from "@anthropic-ai/sdk";4 5const { engine } = await createLoopSystem({ loops: [/* procurement loop */] });6const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });7const ai = createAnthropicActorAdapter(anthropic, { modelId: "claude-opus-4-6" });8 9await engine.start({10 loopId: "procurement" as never,11 aggregateId: "PO-2001" as never,12 actor: { type: "automation", id: "system:intake" }13});14 15const { actor, decision } = await ai.createSubmission({16 loopId: "procurement",17 loopName: "SCM Procurement",18 currentState: "pending_analysis",19 availableSignals: [{ signalId: "submit_recommendation", name: "Submit Recommendation" }],20 instruction: "Recommend order action",21 evidence: { forecast: 0.83 }22});23 24await engine.transition({25 aggregateId: "PO-2001" as never,26 transitionId: "submit_recommendation" as never,27 actor,28 evidence: decision29});30 31"cmt">// Runtime evaluates confidence guard.32"cmt">// Human approval transition executes next if required.33"cmt">// Terminal transition emits loop.completed + learning signal.