Loop Engine

Running Loops

Transitions

engine.transition(options)

Signature:

1transition(options: {
2 aggregateId: AggregateId
3 transitionId: TransitionId
4 actor: { type: "human" | "automation" | "ai-agent" | "webhook" | "system"; id: string }
5 evidence?: Evidence
6 correlationId?: CorrelationId
7}): Promise<TransitionResult>

TransitionResult

1{
2 status: "executed" | "guard_failed" | "rejected" | "pending_approval"
3 fromState: StateId
4 toState?: StateId
5 guardFailures?: { guardId: GuardId; message: string; severity: "hard" | "soft" }[]
6 rejectionReason?: string
7 requiresApprovalFrom?: ActorId
8 event?: TransitionExecutedEvent | GuardFailedEvent
9}

Handle all statuses

1const result = await engine.transition({
2 aggregateId,
3 transitionId,
4 actor,
5 evidence
6})
7 
8switch (result.status) {
9 case 'executed':
10 console.log(result.toState)
11 break
12 case 'guard_failed':
13 console.log(result.guardFailures)
14 break
15 case 'rejected':
16 console.log(result.rejectionReason)
17 break
18 case 'pending_approval':
19 console.log(result.requiresApprovalFrom)
20 break
21}

Evidence best practices

Evidence is persisted in TransitionRecord.evidence and emitted in loop.transition.executed.

  • Human actions: include user decision context
  • Automation actions: include triggering rule or source
  • AI actions: include ai_confidence and ai_reasoning (via buildActorEvidence)

Use evidence to answer: why was this action taken? without reconstructing from logs.