Loop Engine

Running Loops

Starting Loops

engine.start(options)

Signature (from runtime source):

1start(options: {
2 loopId: string
3 aggregateId: AggregateId
4 orgId: string
5 actor: { type: "human" | "automation" | "ai-agent" | "webhook" | "system"; id: string }
6 correlationId?: CorrelationId
7 metadata?: Record<string, unknown>
8}): Promise<LoopInstance>

Behavior

  • Throws if loopId is not registered.
  • Throws if an open instance already exists for the same aggregateId.
  • Creates instance with:
    • currentState = definition.initialState
    • status = "OPEN"
    • startedAt timestamp
    • generated correlation ID when omitted
  • Emits loop.started.

Example

1import { aggregateId } from '@loop-engine/core'
2 
3const instance = await engine.start({
4 loopId: 'scm.procurement',
5 aggregateId: aggregateId('PO-001'),
6 orgId: 'acme',
7 actor: { type: 'system', id: 'system:intake' },
8 metadata: { source: 'erp_sync' }
9})

LoopInstance shape

1{
2 loopId,
3 aggregateId,
4 orgId,
5 currentState,
6 status, "cmt">// OPEN | IN_PROGRESS | CLOSED | ERROR | CANCELLED
7 startedAt,
8 closedAt?,
9 correlationId,
10 metadata?
11}

Choosing aggregateId

Use your existing entity identifier:

  • PO number
  • order ID
  • invoice number
  • ticket ID
  • lead ID

Same aggregateId can be reused across different loop IDs. Same loopId + aggregateId cannot have multiple open instances.