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
1"cmt">// @no-typecheck2import { createLoopSystem } from "@loop-engine/sdk";3import { createAnthropicActorAdapter } from "@loop-engine/adapter-anthropic";4 5const { engine } = await createLoopSystem({ loops: [/* procurement loop */] });6const ai = createAnthropicActorAdapter({7 apiKey: process.env.ANTHROPIC_API_KEY!,8 model: "claude-opus-4-6"9});10 11await engine.start({12 loopId: "procurement" as never,13 aggregateId: "PO-2001" as never,14 actor: { type: "automation", id: "system:intake" }15});16 17const { actor, decision } = await ai.createSubmission({18 loopId: "procurement",19 loopName: "SCM Procurement",20 currentState: "pending_analysis",21 availableSignals: [{ signalId: "submit_recommendation", name: "Submit Recommendation" }],22 instruction: "Recommend order action",23 evidence: { forecast: 0.83 }24});25 26await engine.transition({27 aggregateId: "PO-2001" as never,28 transitionId: "submit_recommendation" as never,29 actor,30 evidence: decision31});32 33"cmt">// Runtime evaluates confidence guard.34"cmt">// Human approval transition executes next if required.35"cmt">// Terminal transition emits loop.completed + learning signal.