# Boss Loops - Full Documentation > https://bossloops.io | Apache-2.0 Licensed | Created by Better Data (https://betterdata.co) > Generated: 2026-07-30T17:52:58.612Z > Source: https://github.com/loopengine/loopengine.io This file contains the complete Boss Loops documentation in a single plain-text file optimized for LLM context windows. Structured summary: https://bossloops.io /llms.txt --- ## Quick Start URL: https://bossloops.io /docs/getting-started/quick-start Summary: Install @loop-engine/sdk, define a loop, and run it in under 5 minutes. Section: Getting Started Install the **OSS governance runtime** locally, define a decision loop, and run a governed transition in minutes. For vocabulary (Providers, Channels, Integrations, guards, evidence), read [Runtime Taxonomy](/docs/concepts/runtime-taxonomy) first — or continue here and return to [Architecture](/docs/getting-started/architecture) for the full runtime model. For self-host direction vs hosted Cloud (and roadmap-only services), see [Runtime Platform Direction](/docs/concepts/runtime-platform-direction). ## Prerequisites Node.js 18+ and npm or pnpm. ## Install ```bash npm install @loop-engine/sdk ``` ## Define a loop and run it ```ts // @no-typecheck import { aggregateId, transitionId } from '@loop-engine/core' import { LoopBuilder, createLoopSystem } from '@loop-engine/sdk' const approval = LoopBuilder .create('expense.approval', 'finance') .description('Expense report approval') .state('SUBMITTED') .state('UNDER_REVIEW') .state('APPROVED', { isTerminal: true }) .state('REJECTED', { isTerminal: true }) .initialState('SUBMITTED') .transition({ id: 'start_review', from: 'SUBMITTED', to: 'UNDER_REVIEW', actors: ['automation'] }) .transition({ id: 'approve', from: 'UNDER_REVIEW', to: 'APPROVED', actors: ['human'] }) .transition({ id: 'reject', from: 'UNDER_REVIEW', to: 'REJECTED', actors: ['human'] }) .outcome({ id: 'expense_approved', description: 'Expense report approved', valueUnit: 'expense_approved', businessMetrics: [ { id: 'm_expense_approved', label: 'Expense report approved', unit: 'count' } ] }) .build() const { engine, eventBus } = await createLoopSystem({ loops: [approval] }) eventBus.subscribe(async (event) => console.log(event.type)) await engine.start({ loopId: 'expense.approval', aggregateId: aggregateId('EXP-2026-001'), actor: { type: 'automation', id: 'system:intake', serviceId: 'intake' } }) await engine.transition({ aggregateId: aggregateId('EXP-2026-001'), transitionId: transitionId('start_review'), actor: { type: 'automation', id: 'system:router', serviceId: 'router' } }) await engine.transition({ aggregateId: aggregateId('EXP-2026-001'), transitionId: transitionId('approve'), actor: { type: 'human', id: 'manager@acme.com', userId: 'manager-1', displayName: 'Manager' }, evidence: { comment: 'Approved for Q1 budget' } }) const state = await engine.getState(aggregateId('EXP-2026-001')) console.log(state?.currentState) // APPROVED console.log(state?.status) // completed ``` ## What just happened - The loop moved through 3 states (`SUBMITTED -> UNDER_REVIEW -> APPROVED`) - 2 actor types were used (`automation`, `human`) - Each successful transition emitted `loop.transition.executed` - Reaching a terminal state sets loop status to `completed` ## Next steps - [Runtime Taxonomy](/docs/concepts/runtime-taxonomy) - [Architecture](/docs/getting-started/architecture) - [Installation](/docs/getting-started/installation) - [Your First Loop](/docs/getting-started/your-first-loop) - [Runtime connections](/docs/integrations) - [Decision Governance](/docs/concepts/decision-governance) --- ## Installation URL: https://bossloops.io /docs/getting-started/installation Summary: Install the Boss Loops SDK or individual packages and configure TypeScript for strict, modern builds. Section: Getting Started ## Install @loop-engine/sdk ```bash npm install @loop-engine/sdk ``` This is the entire required install. Every other package is additive. Most of the `@loop-engine/*` family is published in the `1.0.0-rc.0` cohort. A small number of adapters may remain pre-1.0 while their API shape stabilizes (for example, `@loop-engine/adapter-kafka@0.1.7` and `@loop-engine/adapter-postgres@0.2.0`). Install the capability you need; cohort boundaries are explicit in the docs where they matter. ```bash pnpm add @loop-engine/sdk ``` ```bash yarn add @loop-engine/sdk ``` ## TypeScript configuration Use at least: ```json { "compilerOptions": { "target": "ES2022", "moduleResolution": "bundler", "strict": true } } ``` `moduleResolution: "node16"` also works. ## Install packages individually If you do not want the SDK aggregate package, install only what you need. Core primitives: - `@loop-engine/core` - domain model types and branded IDs - `@loop-engine/loop-definition` - `LoopBuilder`, parser, schema validation - `@loop-engine/runtime` - `LoopEngine` and runtime interfaces - `@loop-engine/events` - event types, schemas, and `InMemoryEventBus` - `@loop-engine/guards` - guard registry and built-in guards - `@loop-engine/actors` - actor types, constraints, evidence helpers - `@loop-engine/signals` - signal engine and built-in rules - `@loop-engine/observability` - metrics, timelines, replay - `@loop-engine/registry-client` - remote/local **loop catalog** client (package name retains `registry-client`) - `@loop-engine/ui-devtools` - React devtools components Stores: - `@loop-engine/adapter-memory` - in-memory `LoopStore` - `@loop-engine/adapter-postgres` - PostgreSQL `LoopStore` adapter - `@loop-engine/adapter-kafka` - Kafka `EventBus` adapter - `@loop-engine/adapter-http` - HTTP webhook `EventBus` adapter AI adapters: - `@loop-engine/adapter-anthropic` - Claude actor adapter - `@loop-engine/adapter-openai` - GPT actor adapter - `@loop-engine/adapter-gemini` - Gemini actor adapter - `@loop-engine/adapter-grok` - Grok actor adapter - `@loop-engine/adapter-perplexity` - Sonar grounded-search adapter Routing and framework adapters: - `@loop-engine/adapter-pagerduty` - PagerDuty approval routing - `@loop-engine/adapter-openclaw` - OpenClaw skill / approval bridge - `@loop-engine/adapter-vercel-ai` - Vercel AI SDK tool-call governance - `@loop-engine/adapter-commerce-gateway` - Commerce Gateway tool routing ## Runtime requirements - Node.js 18+ is required. ## Browser support Works in browser: - `@loop-engine/core` - `@loop-engine/loop-definition` - `@loop-engine/events` - `@loop-engine/actors` - `@loop-engine/guards` - `@loop-engine/observability` - `@loop-engine/signals` - `@loop-engine/adapter-memory` Notes: - `@loop-engine/runtime` needs a `LoopStore` implementation. - `@loop-engine/adapter-postgres` and `@loop-engine/adapter-kafka` are server-side adapters. --- ## Your First Loop URL: https://bossloops.io /docs/getting-started/your-first-loop Summary: Build an expense approval loop step by step, with states, actors, guards, and outcomes. Section: Getting Started ## 1) Design the loop before writing code Start with outcome first: - Outcome ID: `expense_approved` - Value unit: `expense_approved` - States: `SUBMITTED -> UNDER_REVIEW -> APPROVED` (or `REJECTED`) - Actors: `system`, `automation`, `human` ```text SUBMITTED -> UNDER_REVIEW -> APPROVED \-> REJECTED ``` ## 2) States and transitions `StateSpec` fields from `@loop-engine/core`: - `id` (required) - `isTerminal?: boolean` (default false) - `isError?: boolean` (default false) Terminal states close the loop (`status: "completed"`). Error states set `status: "failed"`. ## 3) Actors Boss Loops supports 5 actor types: - `human` - `automation` - `ai-agent` - `webhook` - `system` Actor authorization is checked against each transition's `allowedActors`. See [The Actor Model](/docs/concepts/actor-model) for full details. ## 4) Start and run the loop ```ts // @no-typecheck import { aggregateId, transitionId } from '@loop-engine/core' import { LoopBuilder, createLoopSystem } from '@loop-engine/sdk' const approval = LoopBuilder .create('expense.approval', 'finance') .description('Expense report approval') .state('SUBMITTED') .state('UNDER_REVIEW') .state('APPROVED', { isTerminal: true }) .state('REJECTED', { isTerminal: true }) .initialState('SUBMITTED') .transition({ id: 'start_review', from: 'SUBMITTED', to: 'UNDER_REVIEW', actors: ['automation'] }) .transition({ id: 'approve', from: 'UNDER_REVIEW', to: 'APPROVED', actors: ['human'], guards: [ { id: 'approval_obtained', severity: 'hard', evaluatedBy: 'runtime', description: 'Approval must be present', failureMessage: 'Approval not obtained' } ] }) .transition({ id: 'reject', from: 'UNDER_REVIEW', to: 'REJECTED', actors: ['human'] }) .outcome({ id: 'expense_approved', description: 'Expense report approved', valueUnit: 'expense_approved', businessMetrics: [ { id: 'm_expense_approved', label: 'Expense report approved', unit: 'count' } ] }) .build() const aggregate = aggregateId('EXP-2026-001') const { engine } = await createLoopSystem({ loops: [approval] }) await engine.start({ loopId: 'expense.approval', aggregateId: aggregate, actor: { type: 'system', id: 'system:intake' }, // StartOptions.actor metadata: { source: 'expense_form' } // optional application correlation (neutral keys only) }) const reviewResult = await engine.transition({ aggregateId: aggregate, transitionId: transitionId('start_review'), actor: { type: 'automation', id: 'system:router' } }) const approveResult = await engine.transition({ aggregateId: aggregate, transitionId: transitionId('approve'), actor: { type: 'human', id: 'manager@acme.com' }, evidence: { approved: true, comment: 'Within policy' } }) ``` ## 5) Inspect the result ```ts const instance = await engine.getState(aggregate) const history = await engine.getHistory(aggregate) console.log(instance?.currentState) // branded StateId console.log(instance?.status) // pending | active | completed | failed | cancelled | suspended // TransitionRecord fields for (const row of history) { console.log(row.transitionId, row.fromState, row.toState, row.actor.type, row.occurredAt) } ``` `engine.getState()` returns `Promise`. `engine.getHistory()` returns `Promise`. ## 6) Guard failure example If `approval_obtained` fails (for example `evidence.approved !== true`), `transition()` returns: ```ts { status: "guard_failed", fromState: "UNDER_REVIEW", guardFailures: [ { guardId: "approval_obtained", message: "Approval not obtained", severity: "hard" } ] } ``` The state does not advance, and `loop.guard.failed` is emitted. ## 7) Next steps - [What is a Loop?](/docs/concepts/what-is-a-loop) - [Guards and Policy](/docs/concepts/guards-and-policy) - [Transitions](/docs/running-loops/transitions) --- ## Architecture URL: https://bossloops.io /docs/getting-started/architecture Summary: Boss Loops runtime architecture — governance boundaries, evidence flow, Providers, Channels, Integrations, and runtime vs Cloud. Section: Getting Started Boss Loops is a **governance runtime**, not a generic workflow orchestrator or AI automation builder. This page describes how the runtime composes **decision loops**, **deterministic guards**, and **evidence** with external **Providers**, **Channels**, and **Integrations**. → Full glossary: [Runtime Taxonomy](/docs/concepts/runtime-taxonomy) ## Governance runtime (center of the model) Every operational change that Boss Loops owns passes through the same boundary: 1. A named **actor** requests a transition. 2. **Guards** evaluate policy in the runtime (hard failures block; soft failures may warn). 3. **Evidence** is attached to the allowed transition. 4. An immutable **event** is emitted for audit and learning. AI does not “run the business” inside Boss Loops — it operates **inside** deterministic governance boundaries. Orchestration frameworks may run elsewhere; **loops govern the transitions**. ```text Providers ← intelligence enters (LLMs, retrieval tools) ↓ Decision loops + Guards ← GOVERNANCE: Boss Loops (policy before commit) ↓ Channels ← humans participate (Slack, Teams, approvals) ↓ Integrations ← systems of record execute (CRM, tickets, APIs) ↓ Evidence + learning ← audit + operational improvement ``` | Stage | What enters | What exits | Who participates | | --- | --- | --- | --- | | Providers | Context, signals | Structured AI/human submissions | Models as governed actors | | Loops + Guards | Transition requests | Allow / block / escalate | Runtime policy (deterministic) | | Channels | `PENDING_HUMAN_*` events | Human actor transitions | Operators in Slack, email, etc. | | Integrations | Approved transitions | CRM rows, webhooks, staged applies | Enterprise systems | | Evidence | Each commit | Audit + learning signals | Compliance, RevOps, SRE | ### Evidence flow Evidence is produced **at transition time**: - Inputs the actor used (scores, documents, approval notes) - Guard outcomes and soft warnings - Provider metadata (`modelId`, `provider`, `promptHash` for AI actors) Downstream analytics and learning signals consume events — they do not replace the runtime evidence contract. ### Runtime boundaries | Boundary | Inside Boss Loops | Outside (but connected) | | --- | --- | --- | | Policy | Guards, allowed actors, transition graph | Prompt content alone is not policy | | State | Loop instance state, transition history | ERP/CRM records update via Integrations after approval | | Humans | Attribution + channel routing | Slack/Teams UIs are Channels | | Intelligence | Provider adapters submit decisions | Models do not call integrations directly | ## Runtime platform vs Boss Loops Cloud **Boss Loops can run inside your infrastructure, or connect to hosted governance services from Better Data.** Full positioning constraints and roadmap language: **[Runtime Platform Direction](/docs/concepts/runtime-platform-direction)**. ### OSS runtime platform (today) - **Local-first** — your Node.js process runs `createLoopSystem` with chosen stores and adapters (not a required multi-service mesh today). - **Self-host substrate** — operational governance in your stack: loops, guards, evidence, events via `@loop-engine/sdk`. - **Adapters** — Providers, Channels, and Integrations you wire and operate. → [Quick Start](/docs/getting-started/quick-start) · [Runtime Platform Direction](/docs/concepts/runtime-platform-direction) ### Boss Loops Cloud (hosted) - **Governance control plane** — multi-tenant HTTP API, connector credentials, documented `/api/v1` contract. - **Adds** — managed connector paths (e.g. Slack, Google) and fleet-style operations **without** replacing the OSS runtime model. - **Not claimed** — full OSS parity with every Cloud feature; Studio; docker compose kit; multi-service runtime **today**. → [Boss Loops Cloud HTTP API](/docs/cloud/api-reference) **Better Data company and application docs:** [docs.betterdata.co](https://docs.betterdata.co) — not loopengine.io. ## Connection types (taxonomy summary) | Type | Role in architecture | Examples | | --- | --- | --- | | **Provider** | Intelligence into the loop | Claude, GPT-4o, Gemini, Grok | | **Channel** | Human approval / escalation surface | Slack, Teams, OpenClaw routing | | **Integration** | Systems and persistence after governance | Postgres, Kafka, PagerDuty, Commerce Gateway | See [Runtime Taxonomy](/docs/concepts/runtime-taxonomy) for definitions and disambiguation (e.g. DCM “channels” vs human Channels). ## Runtime primitives (implementation layer) These packages implement the governance runtime. They are **not** the product category names — they are how the engine executes loops. ### Loops Loops are governed decision cycles: states, transitions, signals, and terminal outcomes. Transitions are triggered by **signals** and authorized by **actors** subject to **guards**. ```ts type LoopDefinition = { loopId: string; states: Array<{ stateId: string; terminal?: boolean }>; initialState: string; transitions: Array<{ transitionId: string; from: string; to: string; signal: string }>; }; ``` ### Signals Signals name the intent to move between states. They carry actor context into guard evaluation. ### Actors ```ts type ActorType = "human" | "automation" | "ai-agent"; ``` → [Actor Model](/docs/concepts/actor-model) ### Guards ```ts type GuardSpec = { guardId: string; severity: "hard" | "soft"; evaluatedBy: "runtime" | "module" | "external"; }; ``` Hard guard failure emits `loop.guard.failed` and does not advance state. → [Guards and Policy](/docs/concepts/guards-and-policy) ### Events ```ts type LoopTransitionExecutedEvent = { type: "loop.transition.executed"; loopId: string; aggregateId: string; transitionId: string; fromState: string; toState: string; actor: { type: ActorType; id: string }; evidence?: Record; }; ``` ### Learning signals When a loop completes, learning signals compare predicted vs actual outcomes for improvement loops. → [Learning Signals](/docs/concepts/learning-signals) ## End-to-end example (Provider → guards → Channel → Integration) ```ts // @no-typecheck import { createLoopSystem } from "@loop-engine/sdk"; import { createAnthropicActorAdapter } from "@loop-engine/adapter-anthropic"; const { engine } = await createLoopSystem({ loops: [/* procurement loop */] }); const ai = createAnthropicActorAdapter({ apiKey: process.env.ANTHROPIC_API_KEY!, model: "claude-opus-4-6" }); // Integration may have created the aggregate; automation opens the loop. await engine.start({ loopId: "procurement" as never, aggregateId: "PO-2001" as never, actor: { type: "automation", id: "system:intake" } }); // Provider: AI recommends a transition (does not bypass guards). const { actor, decision } = await ai.createSubmission({ loopId: "procurement", loopName: "SCM Procurement", currentState: "pending_analysis", availableSignals: [{ signalId: "submit_recommendation", name: "Submit Recommendation" }], instruction: "Recommend order action", evidence: { forecast: 0.83 } }); await engine.transition({ aggregateId: "PO-2001" as never, transitionId: "submit_recommendation" as never, actor, evidence: decision }); // Guards run in runtime — e.g. confidence threshold. // Channel: human approval transition (Slack/OpenClaw/PagerDuty routing). // Integration: ERP/Commerce Gateway executes only after approved transition. // Terminal state emits loop.completed + learning signal. ``` ## What Boss Loops is not - **Not** a replacement for Temporal, n8n, or BPM suites — use [Boss Loops vs Workflow Engines](/docs/concepts/loop-engine-vs-workflow-engines). - **Not** an AI automation builder that skips policy. - **Not** a Slack bot product — Slack is a **Channel** when used for human approval. ## Next steps - [Runtime Taxonomy](/docs/concepts/runtime-taxonomy) - [Quick Start](/docs/getting-started/quick-start) - [Runtime connections](/docs/integrations) - [Decision Governance](/docs/concepts/decision-governance) --- ## Boss Loops Cloud URL: https://bossloops.io /docs/cloud Summary: Boss Loops Cloud — the managed distribution of Boss Loops. Governed decision loops, user management scoped by location, outcome-based metering, and audit exports, operated by Better Data. Section: Boss Loops Cloud
Cloud Production: loops.betterdata.co
**Boss Loops Cloud** is the **managed** distribution of Boss Loops — run governed, observable decision loops without operating the runtime yourself. Same engine, same governance model as [Boss Loops OSS](/docs/getting-started/quick-start); Better Data operates scale, isolation, metering, and upgrades. Commercial tiers and early access: [Pricing](/pricing). ## See the product: the governed Decision Record The canonical product demo is the **Alpine demo Decision Record** — a supplier invoice decision (`INV-2026-004521`) carrying frozen evidence, the policy that applied, the approval captured with the evidence presented, and preview semantic evidence from [Looker](/docs/concepts/evidence-providers#looker-semantic-evidence-preview). It shows what Boss Loops sells: a decision you can defend a year later. ## Start - **Talk to us about Boss Loops Cloud** — we'll set up your organization and tenant with you Prefer to reach out directly? - Request early access - Join the waitlist - Contact sales > **OSS proves the loop. Cloud runs the workflow.** > > The [OSS quickstart](/docs/getting-started/quick-start) proves the loop state machine on > your machine. Boss Loops Cloud runs live workflows — managed connectors (Slack, Google, …), > tenancy, and audit exports. See [Cloud getting started](/docs/cloud/getting-started). ## What is Boss Loops Cloud? Boss Loops Cloud, hosted at **[loops.betterdata.co](https://loops.betterdata.co)**, runs the Boss Loops model as a **managed service**. You integrate via APIs and module manifests; Better Data operates scale, isolation, and upgrades. The runtime technology underneath is the **Boss Loops runtime** (`@loop-engine/*`) — see [Architecture](/docs/getting-started/architecture). **Self-hosted alternative:** Boss Loops OSS — start with the [quick start](/docs/getting-started/quick-start) and the engine docs on this site. ## What you get See [Cloud operations](/docs/cloud/operations) for the full capability list — org isolation, outcome-based metering, capability enforcement, tamper-evident audit trail, drift detection, and Industry Pack policy overlays. ## API The hosted runtime exposes a versioned HTTP API — see the [Cloud API reference](/docs/cloud/api-reference), which also links the generated OpenAPI reference and the monorepo contract. ## Boss Loops OSS vs Boss Loops Cloud | | Boss Loops OSS (`@loop-engine/sdk`) | Boss Loops Cloud ([loops.betterdata.co](https://loops.betterdata.co)) | | - | ------------------------- | ----------------------------------------------------------- | | Cost | Free (Apache-2.0) | See [Pricing](/pricing) | | Setup | You operate | No infrastructure setup | | User management & location scopes | Your implementation | Built in | | Industry Packs | No | Yes | | Audit / compliance exports | Your pipelines | Platform aggregation + reports | | SLA | Self-managed | Better Data SLA | --- ## Getting started with Boss Loops Cloud URL: https://bossloops.io /docs/cloud/getting-started Summary: Choose your path — prove the loop mechanics locally with Boss Loops OSS in five minutes, or start Boss Loops Cloud for live connectors, tenancy, and audit exports. Section: Boss Loops Cloud
Cloud
Two ways to experience Boss Loops: | | **Run locally in 5 minutes** | **Run live with integrations** | | - | --- | --- | | Product | **Boss Loops OSS** | **Boss Loops Cloud** | | What you get | dry-run of the Spreadsheet Approval loop over seeded evidence | live **Slack** approval + live **Google Sheets** apply | | Credentials | **none** | Slack app + Google OAuth | | Where | [OSS quick start](/docs/getting-started/quick-start) | [Start Boss Loops Cloud](/docs/cloud) | ## The OSS 5-minute proof ```bash # Boss Loops OSS — local, credential-free 5-minute proof pnpm boss-loops:demo --dry-run ``` The `boss-loops:demo` script runs from the Better Data monorepo checkout. If you are starting from the published packages instead, follow the [quick start](/docs/getting-started/quick-start) — same loop model, SDK-first. The dry-run walks the real loop state machine and prints the staged change, the approval, the applied result, and an audit trail — no Slack or Google credentials required. ## The Cloud path Live connectors (Slack approvals, Google Sheets apply) are **Cloud-only** — the OSS self-host runtime intentionally excludes hosted connectors: ```txt Slack approval request → Google Sheets staged update → Approve in Slack → Sheet updated → confirmation → execution history ``` Start from the [Cloud overview](/docs/cloud) — organization and tenant are created in seconds, no payment required. Commercial tiers: [Pricing](/pricing). --- ## Cloud operations URL: https://bossloops.io /docs/cloud/operations Summary: What Boss Loops Cloud operates for you — tenancy and isolation, outcome-based metering, capability enforcement, audit exports, drift detection, and the canonical loop types. Section: Boss Loops Cloud
Cloud
## What you get with Boss Loops Cloud - **User management** — roles and approval authority scoped by location (plants, regions, business units) - **Outcome-based metering** (billing tied to loop completions — see [Pricing](/pricing)) - **TenantCapabilitySnapshot**-style capability enforcement for RBAC - Tamper-evident **loop audit trail** and export paths for compliance workflows - **Drift detection** (scheduled validation of expected vs observed state) - **Outbox relay** for cross-module event delivery - **Industry Pack** policy overlays (hosted-only; not published as OSS) ## Loop types (canonical) | Loop | Module | What it governs | | ---- | ------ | ---------------- | | `scm.procurement` | SCM | AI-assisted PO recommendation + human approval gates | | `scm.fulfillment` | SCM | Multi-step order fulfillment | | `scm.quality` | SCM | Inspection, deviation, CAPA-style disposition | | `scm.replenishment` | SCM | Demand signal → reorder / replenishment | | `dcm.demand` | DCM | Demand signal detection and replenishment triggers | | `dcm.order` | DCM | Channel order routing and lifecycle | | `dcm.returns` | DCM | Return authorization and reverse logistics | For the platform conceptual model behind these loop types, see [Loops on the Better Data platform](https://docs.betterdata.co/docs/platform/loops). ## Hosted services The running hosted stack includes **hosted-loops** (runtime + loops database API) and the published loop definitions catalog. For how these relate to the wider Better Data platform apps, see [Hosted platform apps](https://docs.betterdata.co/docs/developer-resources/reference/hosted-platform-apps). ## API Versioned HTTP routes for loop lifecycle, runs, baselines, and connector health are documented in the [Cloud API reference](/docs/cloud/api-reference). --- ## Boss Loops Cloud API reference URL: https://bossloops.io /docs/cloud/api-reference Summary: The Boss Loops Cloud HTTP API — auth, versioned routes, the generated OpenAPI reference, and the canonical contract in the monorepo. Section: Boss Loops Cloud
Cloud Production: loops.betterdata.co Taxonomy: Integration (hosted control plane)
## What this is This site documents the **OSS governed engine** (`@loop-engine/*`). **Boss Loops Cloud** is the **hosted Integration** path: same loop/guard/evidence model, operated by Better Data with tenancy, API keys, and managed connectors (Slack, Google, …). | Surface | Where to read | | --- | --- | | Boss Loops engine, taxonomy, adapters | This site (bossloops.io/docs) | | Boss Loops Cloud HTTP contract | This page + the references below | | Better Data platform, SCM, CCO applications | **[docs.betterdata.co](https://docs.betterdata.co)** | **The OSS engine** defines states, signals, guards, transitions, and events in **your** infrastructure. **Boss Loops Cloud** exposes the execution contract over **HTTPS** when you want managed governance operations. - **Developers & integrations** → **`https://loops.betterdata.co`** (Bearer JWT for first-party services, **`le_` API keys** for external automation). - **Operators** → **Automation** at **`app.betterdata.co/automation`** (product UX; same loops conceptually). We document **shipped** Cloud capabilities here and in the references below. We do not imply undelivered OSS parity, Studio, docker compose runtime, or a multi-service mesh **today** — see [Runtime Platform Direction](/docs/concepts/runtime-platform-direction) and [changelog](/docs/changelog). ## Routes at a glance The **hosted-loops** service exposes versioned HTTP routes under **`/api/v1/...`**. **Production base URL** mapping (for example **`loops.betterdata.co`**) is environment-specific — confirm with your deployment or support. | Prefix | Purpose (high level) | | --- | --- | | **`/api/v1/loops`** | List/create loop concerns; catalog, start, transition, cancel, events, history, and integration helpers | | **`/api/v1/loops/runs`** | Run detail and comparison | | **`/api/v1/loops/definitions`** | Definition-scoped run listings | | **`/api/v1/baselines`** | Baselines CRUD, transitions, true-ups, delivery routes | | **`/api/v1/connectors/*`** | Connector health and OAuth/event surfaces (e.g. Slack, Google) | External callers should use the service's **authenticated API** only; **exact auth header and tenancy claims** are defined by the hosted-loops implementation — treat field names and JWT contracts as **implementation details** to verify in the references below. ## Canonical references - **[Generated OpenAPI reference](https://docs.betterdata.co/docs/developer-resources/api-reference/boss-loops)** — the route-by-route generated reference (from `apps/hosted-loops/openapi.yaml`, DP-07). It lives on the Better Data platform docs and stays there. - **[Boss Loops Cloud HTTP API contract (source)](https://github.com/betterdata-platform/bd-forge-main/blob/main/apps/hosted-loops/docs/api.md)** — the developer contract maintained alongside the implementation. Pull requests that change route handlers should update it in the same change-set when the public JSON contract moves. ## Related OSS docs - [HTTP adapter](/docs/integrations/http) — webhook-style **outbound** adapter from the OSS runtime; not the same as Boss Loops Cloud ingress. - [Architecture](/docs/getting-started/architecture) — core Boss Loops concepts reused by the hosted service. ## Pricing See [Pricing](/pricing) — open core plus Starter, Team, and Enterprise tiers. Launch pricing is being finalized; all commercial tiers are in early access. (Do not hardcode prices in integration guides.) --- ## Runtime Taxonomy URL: https://bossloops.io /docs/concepts/runtime-taxonomy Summary: Canonical terms for Boss Loops — Providers, Channels, Integrations, Loops, Guards, Evidence, and Actors — plus runtime vs Boss Loops Cloud. Section: Core Concepts Boss Loops is a **governed operational runtime platform**. This page is the canonical glossary for public docs on [loopengine.io](https://loopengine.io). Package names (`@loop-engine/*`) and developer types (`ActorAdapter`, `ToolAdapter`) are implementation details — see [IntegrationAdapter archetype](/docs/concepts/integration-adapter) for the implementer map. ## Runtime flow (read this first) ```text Providers → intelligence in (analyze, recommend, classify) ↓ Decision loops + Guards → governance (who may transition, under what policy) ↓ Channels → human coordination (approve, reject, escalate) ↓ Integrations → operational execution (CRM, tickets, apply writes) ↓ Evidence + learning → audit trail and improvement ``` **Rules this model enforces:** - **Channels are not integrations.** Slack approves; Salesforce updates. - **Providers are not workflow systems.** Temporal executes paths; loops govern commits. - **Integrations are not governance.** Guards run in the runtime, not in your CRM. - Providers do **not** bypass guards or write directly to integrations. - Integrations do **not** call models without a governed loop transition. - Durable workflow engines may **execute** approved work; **loops govern** whether transitions commit. ## Public taxonomy | Public term | Meaning | | --- | --- | | **Provider** | **Intelligence system** — generates analysis and recommendations; does not commit operational state. | | **Channel** | **Human coordination surface** — where people approve, reject, or escalate; not a system of record. | | **Integration** | **System of record / operational system** — executes actions and persists state after policy passes. | | **Loop** | Governed decision cycle — explicit states, transitions, signals, and outcomes (not a generic BPM template). | | **Guard** | Deterministic runtime policy — evaluated before a transition commits; not prompt instructions. | | **Evidence** | Auditability layer — structured context explaining why a transition was allowed. | | **Actor** | Participant — human, automation, or AI agent (and engineering types such as webhook where documented). | ## Providers **Providers** supply intelligence into a loop: recommendations, classifications, draft decisions, or research steps. **Includes:** Anthropic, OpenAI, Gemini, Grok, Vercel AI SDK–backed models. **Research steps:** Perplexity Sonar acts as a **tool** step (`ToolAdapter`) for grounded retrieval with citations — still governed by the same loop and guards. **Excludes:** MCP as a Provider. MCP is a [protocol/connectivity layer](#mcp-and-commerce-gateway) used with Commerce Gateway; Boss Loops governs whether operational transitions proceed. **npm adapters (examples):** `@loop-engine/adapter-anthropic`, `adapter-openai`, `adapter-gemini`, `adapter-grok`, `adapter-vercel-ai`, `adapter-perplexity`. ## Channels **Channels** are where **humans** interact with a governed loop — not where ERP writes occur. **Includes:** Slack, Microsoft Teams, email, Discord/Telegram via OpenClaw routing, in-app approval UIs. **Not Boss Loops “Channels” (disambiguation):** | Term elsewhere | What it means | | --- | --- | | **DCM commerce channel** | Sales/marketplace channel in Commerce Chain (Shopify, Amazon, etc.) | | **Event-bus channel** | Internal module queue name in workers — engineering only | | **`@betterdata/dcm-channels`** | Commerce Chain package — not this taxonomy | **npm adapters (examples):** `@loop-engine/adapter-openclaw` (routing). Slack/Teams adapters are planned; hosted connectors may use Boss Loops Cloud APIs. ## Integrations **Integrations** are operational systems and persistence layers that connect **after** governance: - Trigger or enrich loops (PagerDuty incidents, webhooks) - Persist state and events (Postgres, Kafka, memory store) - Execute commerce or tool calls (Commerce Gateway) - Apply approved writes (Google Workspace APIs in hosted patterns) Browse the [runtime connections index](/docs/integrations) grouped by this taxonomy. **npm adapters (examples):** `adapter-postgres`, `adapter-kafka`, `adapter-pagerduty`, `adapter-commerce-gateway`, `adapter-http`, `adapter-memory`. ## Loops, guards, evidence, actors ### Loop A **loop** is a versioned **governed decision cycle** with `LoopDefinition` states and transitions. Finite-state machinery is the runtime implementation — the product unit is the **decision loop**. → [What is a Loop?](/docs/concepts/what-is-a-loop) ### Guard **Guards** enforce policy at runtime: constrain execution, require evidence fields, escalate to humans, and block transitions that fail hard checks. → [Guards and Policy](/docs/concepts/guards-and-policy) ### Evidence **Evidence** is attached to transitions to support audit, dispute resolution, and operational learning. It is captured when the transition is evaluated — not assembled later from scattered logs. → [Confidence + Evidence](/docs/ai-and-automation/confidence-evidence) ### Actor Every transition names an **actor** (`human`, `automation`, `ai-agent`). Attribution is mandatory for governance. → [Actor Model](/docs/concepts/actor-model) ## MCP and Commerce Gateway **MCP (Model Context Protocol)** is a **protocol and controlled connectivity** pattern — not a Boss Loops Provider and not the runtime itself. Typical stack: 1. **Registry / Gateway** — discover and execute tools against operational data. 2. **Boss Loops** — govern whether operational **state** may change. 3. **Integrations** — systems of record that receive approved side effects. → [Commerce Gateway integration](/docs/integrations/commerce-gateway) · [Decision Governance](/docs/concepts/decision-governance) ## Runtime platform vs Boss Loops Cloud Boss Loops can run **inside your infrastructure**, or connect to **hosted governance services** from Better Data. ### Runtime platform (OSS) | Aspect | Description | | --- | --- | | **What** | Open governed operational runtime (`@loop-engine/sdk` and adapters) | | **Where** | Local execution in your environment — processes, containers, or services you operate | | **Primitives** | Loops, guards, actors, evidence, events, signals | | **Direction** | Self-host first; add Providers, Channels, and Integrations via adapters | | **Docs** | You are reading them on loopengine.io | Install and run: ```bash npm install @loop-engine/sdk ``` → [Quick Start](/docs/getting-started/quick-start) · [Architecture](/docs/getting-started/architecture) ### Boss Loops Cloud (hosted) | Aspect | Description | | --- | --- | | **What** | Better Data hosted **governance control plane** | | **Where** | Multi-tenant service at [loops.betterdata.co](https://loops.betterdata.co) | | **Adds** | Tenant isolation, connector OAuth (e.g. Slack, Google), API keys, metering, retention/compliance-oriented operations | | **Direction** | Optional path when you want managed connectors and fleet-style operations without operating every adapter yourself | | **Contract** | [Boss Loops Cloud HTTP API](/docs/cloud/api-reference) | We document **what is available today** on the Cloud API page. We do not imply undelivered surfaces (Studio, docker compose runtime, multi-service mesh, or full self-host parity with Cloud) — see [Runtime Platform Direction](/docs/concepts/runtime-platform-direction) and [changelog](/docs/changelog). ## Workflows vs loops | | Workflows (Temporal, n8n, app code) | Loops (Boss Loops) | | --- | --- | --- | | **Job** | Coordinate durable steps and retries | Govern **whether** a transition may commit | | **Policy** | Often external or implicit | **Guards** in the runtime | | **Audit** | Reconstructed from logs | **Evidence** on each transition | → [Boss Loops vs Workflow Engines](/docs/concepts/loop-engine-vs-workflow-engines) ## Next steps - [Runtime Platform Direction](/docs/concepts/runtime-platform-direction) — self-host direction, roadmap-only services, forbidden claims - [Architecture](/docs/getting-started/architecture) — how primitives compose in one system - [Integrations](/docs/integrations) — Providers, Channels, and Integrations index - [IntegrationAdapter archetype](/docs/concepts/integration-adapter) — developer interface map --- ## Runtime Platform Direction URL: https://bossloops.io /docs/concepts/runtime-platform-direction Summary: Self-host operational runtime direction — what ships in OSS today, what Boss Loops Cloud adds, and roadmap-only extensions (constrained language). Section: Core Concepts Boss Loops is evolving toward a **self-host operational runtime platform**: a **local-first** stack and **operational governance substrate** you run in your infrastructure. This page states that direction honestly — what exists on npm **today**, what **Boss Loops Cloud** adds, and which components are **roadmap-only**. → [Runtime Taxonomy](/docs/concepts/runtime-taxonomy) · [Architecture](/docs/getting-started/architecture) · [Boss Loops Cloud API](/docs/cloud/api-reference) ## Positioning (locked) | Phrase | Meaning | | --- | --- | | **Self-host runtime platform** | You operate the governance runtime (`@loop-engine/sdk`, adapters, stores) in your processes or containers | | **Operational governance substrate** | Loops + guards + evidence sit **under** AI and workflow layers — they authorize transitions | | **Local-first runtime stack** | Default path is install SDK, wire adapters, run in your environment — not a required multi-tenant SaaS | We describe Boss Loops as infrastructure for **governed operational decisions**, not as a generic cloud suite or workflow marketplace. ## What you can run today (OSS) | Capability | Status | How | | --- | --- | --- | | Loop definitions (YAML / TypeScript) | **Shipped** | `@loop-engine/sdk`, `@loop-engine/dsl` | | Transition execution + guards | **Shipped** | `@loop-engine/runtime`, `@loop-engine/guards` | | Actors, evidence, events | **Shipped** | `@loop-engine/actors`, `@loop-engine/events` | | Provider / Channel / Integration adapters | **Shipped** (per adapter) | See [runtime connections](/docs/integrations) | | In-process observability helpers | **Shipped** | `@loop-engine/observability`, `@loop-engine/ui-devtools` | | Remote registry client | **Shipped** | `@loop-engine/registry-client` (`localRegistry`, `httpRegistry`, …) | Typical **today** topology: one or more **application processes** embedding `createLoopSystem` with chosen `LoopStore` and `EventBus` adapters — not a mandatory multi-service mesh. ```bash npm install @loop-engine/sdk ``` → [Quick Start](/docs/getting-started/quick-start) ## Runtime platform vs Boss Loops Cloud | | **OSS runtime (self-host)** | **Boss Loops Cloud (hosted)** | | --- | --- | --- | | **Runs where** | Your infrastructure | Better Data operated (`loops.betterdata.co`) | | **Primary job** | Govern transitions in **your** apps | Hosted governance API + managed connectors | | **Tenancy** | Your app’s isolation model | Multi-tenant control plane | | **Connectors** | You implement OAuth/secrets | Documented hosted connector paths (Slack, Google, …) | | **Docs surface** | **loopengine.io** (this site) | Cloud API page + **[docs.betterdata.co](https://docs.betterdata.co)** for company/apps | **Boss Loops Cloud does not replace the OSS runtime model** — it hosts governance operations when you want managed connectors and fleet-style control. **Better Data application documentation** (SCM, CCO, company products) lives on **docs.betterdata.co**, not loopengine.io. We do **not** claim **full self-host parity** with every Cloud connector or operator feature on day one. ## Roadmap-only extensions (not available today) The following are **directional** components — **runtime extensions** and **governance layers**, not a sprawling separate cloud product. They may ship as optional services you run beside your app processes: | Component | Role (when shipped) | Category | | --- | --- | --- | | **Registry service** | Central loop catalog resolution (versioned definitions) | Runtime extension | | **Audit / event store** | Durable, queryable transition and guard history | Governance layer | | **Observability collector** | Fleet-wide metrics and timelines from loop events | Operational infrastructure | | **Replay service** | Reconstruct and analyze past transitions for audit | Governance layer | | **Studio** | Operator UI for loop inspection (scope TBD) | Governance layer | | **Docker Compose runtime** | Opinionated local/self-host bundle of OSS + optional services | Local-first stack | Until each item appears in [changelog](/docs/changelog) with a released version, treat it as **planned** — do not plan production dependencies on it. ```text Today (typical) Direction (optional self-host services) ───────────────── ───────────────────────────────────── Your app + @loop-engine/sdk → + registry service (roadmap) │ + audit/event store (roadmap) ├─ adapters + observability collector (roadmap) └─ your Postgres/Kafka + replay (roadmap) + Studio (roadmap, not announced GA) + compose kit (roadmap) ``` ## Language we avoid | Do not say | Why | | --- | --- | | “The Supabase for AI workflows” | Implies hosted DB + auth + realtime product parity we do not ship | | “Full self-host parity with Cloud” | Connectors and control-plane features differ by design | | “Multi-service runtime **today**” | OSS is embeddable; mesh is roadmap-only | | “Studio is available” | Unless changelog documents a release | | “X for Y” competitor mimicry | e.g. “Temporal for AI”, “Zapier for governance” — obscures the governance substrate | Prefer **concrete primitives**: loops, guards, evidence, Providers, Channels, Integrations. ## How future services should read **Do** frame additions as: - **Runtime extensions** — optional processes that help definitions, events, or replay - **Governance layers** — audit, policy visibility, operator tooling - **Operational infrastructure** — collectors and stores **you** operate **Do not** frame as: - A second “AI workflow cloud” unrelated to transition governance - Mandatory microservices for every deployment - Replacement for your existing data plane or identity system ## Choosing a path ```text Need governed loops in your app now? → OSS SDK + adapters (self-host) Need managed Slack/Google connectors + tenancy API? → Boss Loops Cloud (hosted Integration path) Need company / SCM / CCO product docs? → docs.betterdata.co (not loopengine.io) ``` ## Related - [Architecture](/docs/getting-started/architecture) — evidence flow and boundaries - [Runtime Taxonomy](/docs/concepts/runtime-taxonomy) — Providers, Channels, Integrations - [Boss Loops vs Workflow Engines](/docs/concepts/loop-engine-vs-workflow-engines) — execution vs governance - [Package taxonomy](/docs/packages) — what to install today --- ## What is a Loop? URL: https://bossloops.io /docs/concepts/what-is-a-loop Summary: A loop tracks operational outcomes with named states, attributed actors, and structured feedback - not task completion. Section: Core Concepts A **loop** is a **governed decision cycle** in the [runtime taxonomy](/docs/concepts/runtime-taxonomy). This page explains the loop as a product unit; finite states are the mechanism underneath. ## The problem Enterprise AI systems fail when actions are not bounded by explicit state, policy, and traceability. Boss Loops provides finite states, deterministic transition checks, and event traces that make decisions auditable. ## Workflow vs. State Machine vs. Decision Loop When designing operational processes, mixing up execution pipelines with governance models leads to brittle systems and decisions that cannot be defended later. | Dimension | Workflow Engine (e.g. Temporal, n8n) | Finite State Machine (pattern) | Boss Loops (Decision Loop) | |---|---|---|---| | Primary focus | Tasks & execution — orchestrating sequences, API calls, data pipelines | Status & transitions — ensuring an entity moves legally between named states | Governance & evidence — proving why a transition was authorized | | Progression | Linear / forward-moving pipelines | Cyclical, event-driven, multi-directional | Cyclical execution with strict policy and authority guardrails | | Core unit | The task (what runs next?) | The state (where are we right now?) | The Decision Record (what is the immutable proof?) | | Triggers | Completion of the previous programmatic step | External raw events or inputs | Signals paired with runtime evidence evaluation | | Handling rejection | Complex error branching or manual exception code | State reset (e.g. back to draft) | Attributed rejections, guard failures, and historical loop resets | **One-liner:** Workflow engines excel at sequential execution; state machines excel at status, events, and legal transitions; Boss Loops uses state-machine enforcement to govern decisions with durable evidence — and composes with workflow engines for everything that runs after approval. ### Reclaim approval chains from workflows Traditional guides classify document approvals as workflows. Boss Loops treats them as state-driven decisions. A sequential pipeline treats approval as another API step; an auditor asking why a $10M invoice was paid needs more than step completion logs. In Boss Loops, the invoice sits in `PENDING_APPROVAL` protected by active guards. It cannot transition to `APPROVED` without the required C10 authority and a frozen snapshot of the evidence as it was seen at that moment. ### Active governance, not passive status Generic explainers describe state machines as passive — waiting for external events. Boss Loops is an active gatekeeper: while it waits for signals (temperature excursion, invoice over threshold), invariant enforcement and authority configuration deny illegal transitions — for example `COMMIT_AUTHORITY_NOT_CONFIGURED`. ### Composition, not replacement Boss Loops does not replace your workflow engine. It governs the commit; the workflow engine executes the approved work. ```text Signal → Boss Loops (govern decision) → transition approved → Workflow engine (execute sequential APIs) ``` Example: AI drafts a proposal → Boss Loops governs draft → approved → Salesforce or Temporal runs the downstream pipeline. See [Workflow + Boss Loops](/docs/examples/workflow-plus-loop). :::note Alpine supplier invoice While naive tooling models invoice approvals as sequential workflows, the [Alpine demo](https://demo.bossloops.io) treats invoices as an FSM pattern — reset, exception handling, and strict state-based guardrails that a linear pipeline cannot enforce without brittle branching. ::: ## Anatomy of a loop (`LoopDefinition`) - `id: LoopId` - `version: string` - `description: string` - `domain: string` - `states: StateSpec[]` - `initialState: StateId` - `transitions: TransitionSpec[]` - `outcome: OutcomeSpec` - `participants?: string[]` - `spawnableLoops?: LoopId[]` - `metadata?: Record` Use optional fields (`participants`, `spawnableLoops`, `metadata`) only when needed by your platform model. ## Lifecycle (`LoopStatus`) `LoopStatus` values: `pending | active | completed | failed | cancelled | suspended`. ```text pending -> active -> completed pending -> active -> failed pending -> active -> cancelled ``` User-defined state IDs (like `OPEN`, `PO_CONFIRMED`, `SETTLED` below) are independent of `LoopStatus` — `LoopStatus` tracks the lifecycle of the instance itself, while state IDs track position within a specific loop definition. ## Real example (abbreviated from `loops/scm/procurement.yaml`) ```yaml id: scm.procurement version: 1.0.0 domain: scm description: Purchase order lifecycle from requisition through settlement states: - id: OPEN - id: PO_CONFIRMED - id: RECEIVED - id: INVOICE_MATCHED - id: SETTLED isTerminal: true initialState: OPEN transitions: - id: confirm_po from: OPEN to: PO_CONFIRMED allowedActors: [human, automation, ai-agent] guards: - id: approval_obtained severity: hard evaluatedBy: external description: PO must be approved before confirmation failureMessage: PO confirmation requires explicit approval outcome: id: po_settled description: Purchase order fully settled valueUnit: po_settled measurable: true ``` ## Related - [Decision Governance](/docs/concepts/decision-governance) - [When to Use Boss Loops](/docs/concepts/when-to-use) - [Boss Loops vs workflow engines](/docs/concepts/loop-engine-vs-workflow-engines) --- ## IntegrationAdapter Archetype URL: https://bossloops.io /docs/concepts/integration-adapter Summary: A package that implements a pluggable runtime interface and slots into LoopEngineOptions. Four canonical archetypes — Store, Registry, AI, EventBus. Section: Core Concepts Public docs use [Runtime Taxonomy](/docs/concepts/runtime-taxonomy) terms — **Providers**, **Channels**, and **Integrations**. This page maps **developer** adapter archetypes (`Store`, `Registry`, `AI`, `EventBus`) to those surfaces. ## Public taxonomy ↔ developer adapters Developer terminology remains valid in code and package APIs. Public taxonomy sits **above** these types: | Public (loopengine.io) | Developer type / archetype | Typical npm surface | | --- | --- | --- | | **Provider** | `ActorAdapter` — `createSubmission(...)` → governed AI transition | `@loop-engine/adapter-anthropic`, `adapter-openai`, … | | **Provider** (research step) | `ToolAdapter` — `invoke(...)` for grounded retrieval | `@loop-engine/adapter-perplexity` | | **Channel** | Human-surface routing on `EventBus` / approval delivery | `@loop-engine/adapter-openclaw` (Slack/Teams via [Boss Loops Cloud](/docs/cloud/api-reference)) | | **Integration** | `IntegrationAdapter` archetypes — `LoopStore`, `LoopRegistry`, `EventBus`, operational connectors | `adapter-postgres`, `adapter-kafka`, `adapter-pagerduty`, `adapter-commerce-gateway`, … | Browse the [runtime connections index](/docs/integrations) — each page is listed under **exactly one** public category. Package selection by role: [Package taxonomy](/docs/packages). ## What is an IntegrationAdapter? An **IntegrationAdapter** is a package that implements one of Boss Loops' pluggable interfaces and slots into `LoopEngineOptions` (or the matching registry-client option). Every adapter preserves the same governance model — guards enforced, actors attributed, audit trail intact — and is swappable without changing loop definitions or business logic. At rc.0 there are four canonical archetypes. All four share the same shape: 1. An **interface contract** exported from a runtime package. 2. An **options slot** on `LoopEngineOptions` (or `createLoopSystem` options) that accepts an implementation of that interface. 3. One or more **shipped adapters** that fulfill the interface. 4. A **"build your own"** path if the shipped adapters don't cover your backend. ```ts interface LoopEngineOptions { registry: LoopRegistry // Registry archetype store: LoopStore // Store archetype eventBus?: EventBus // EventBus archetype guardEvaluator?: GuardEvaluator clock?: () => string } ``` The AI archetype sits slightly outside this shape — AI adapters are invoked from transition execution paths rather than slotted into `LoopEngineOptions` directly — but follows the same "interface + shipped implementations + build-your-own" pattern. ## The four archetypes ### Store adapter | | | |---|---| | Interface | `LoopStore` from `@loop-engine/runtime` | | Slot | `options.store` | | Shipped | `memoryStore()` from `@loop-engine/adapter-memory`; PlanetScale store from `betterdata-loops` (proprietary) | | Docs | [`@loop-engine/adapter-memory`](/docs/packages/adapter-memory) · [In-Memory integration](/docs/integrations/memory) · [Postgres integration](/docs/integrations/postgres) | Store adapters persist loop instances and transition history. Swap backends without changing loop definitions. ### Registry adapter | | | |---|---| | Interface | `LoopRegistry` from `@loop-engine/registry-client` | | Slot | `options.registry` | | Shipped | `localRegistry`, `httpRegistry`, `betterDataRegistry` (from `@loop-engine/registry-client` and its `/betterdata` subpath) | | Docs | [`@loop-engine/registry-client`](/docs/packages/registry-client) | Registry adapters load `LoopDefinition` objects. Use `localRegistry` for in-process registration, `httpRegistry` for remote JSON catalogs, or `betterDataRegistry` for the Better Data catalog API. ### AI / LLM adapter | | | |---|---| | Interface | LLM-step contract — `AIActorAdapter.createSubmission(...)` returning `{ actor: AIAgentActor, decision: AIActorDecision }`; tool adapters implement `ToolAdapter.invoke(...)` | | Slot | Invoked from transition execution paths (not a `LoopEngineOptions` field) | | Shipped | `@loop-engine/adapter-anthropic`, `@loop-engine/adapter-openai`, `@loop-engine/adapter-gemini`, `@loop-engine/adapter-grok`, `@loop-engine/adapter-perplexity` (tool/retrieval) | | Docs | [AI as Actor](/docs/ai-and-automation/ai-as-actor) · [`createAIActor`](/docs/packages/sdk#createaiactor) · per-provider integration pages | Actor adapters return a structured decision that the runtime submits through `engine.transition(...)`. Guards evaluate after submission — an AI actor cannot bypass policy. ### EventBus adapter | | | |---|---| | Interface | `EventBus` from `@loop-engine/runtime` | | Slot | `options.eventBus` | | Shipped | `InMemoryEventBus` from `@loop-engine/events`; `OpenClawEventBus` from `@loop-engine/adapter-openclaw`; Kafka adapter (`@loop-engine/adapter-kafka`) | | Docs | [Event subscriptions](/docs/running-loops/event-subscriptions) · [Events package](/docs/packages/events) | EventBus adapters route lifecycle events (`loop.started`, `loop.transition.executed`, `loop.completed`, ...) to downstream consumers. The in-memory bus is the default; swap it for Kafka, OpenClaw, or a custom sink. ## Choosing between adapters | Situation | Store | Registry | EventBus | |---|---|---|---| | Local dev, tests | `memoryStore()` | `localRegistry` | `InMemoryEventBus` (default) | | Single-service prod | `PostgresAdapter` | `localRegistry` (definitions in code) | `InMemoryEventBus` or Kafka | | Multi-service catalog | `PostgresAdapter` | `httpRegistry` or `betterDataRegistry` | Kafka or OpenClaw | | Audit streaming | — | — | Kafka, OpenClaw | For AI adapters, switch on the provider API you have access to and whether you need tool-style grounding (Perplexity) or open-ended reasoning (Anthropic/OpenAI/Gemini/Grok). ## Cross-archetype patterns - **Zero-config dev**: `memoryStore()` + `localRegistry` + default `InMemoryEventBus` — no persistence, no network, fast feedback loop. - **Production single-service**: Postgres store + local registry + Kafka event bus — durable state, definitions live in code, events stream to analytics. - **Multi-tenant catalog**: Postgres store + `betterDataRegistry` + Kafka — definitions centrally managed, per-tenant loops, events replayable. - **Governed AI workflow**: any Store + any Registry + any AI adapter + Kafka or OpenClaw EventBus — AI decisions become governed transitions with full audit trail. ## Build your own Each archetype's interface is documented as the single-point-of-truth contract: - [`LoopStore` interface](/docs/running-loops/adapters#loopstore-interface) - [`LoopRegistry` and shipped registries](/docs/packages/registry-client) - [`EventBus` and event subscription model](/docs/running-loops/event-subscriptions) - AI actor adapter shape — see any of the provider integration pages; the per-provider `createXActorAdapter(...)` + `createSubmission(...)` contract is uniform across Anthropic, OpenAI, Gemini, and Grok. Implement the interface, pass your implementation into `createLoopSystem` or construct a `LoopEngine` directly with `createLoopEngine`. ## Related - [Adapters reference](/docs/running-loops/adapters) — interface signatures with code examples - [Runtime connections index](/docs/integrations) — every shipped connection, grouped by Providers / Channels / Integrations - [`createLoopSystem`](/docs/running-loops/create-loop-system) — the factory that wires options into a running engine --- ## Actor Model URL: https://bossloops.io /docs/concepts/actor-model Summary: Human, automation, and AI actors are first-class in Boss Loops - every transition is attributed and every action leaves evidence. Section: Core Concepts ## Why actors matter Every transition is attributed to an actor in the transition record and emitted events. Nothing executes anonymously. ## Actor types ### `human` Use when a person executes a transition. ```ts const actor = { type: 'human', id: actorId('drew@acme.com'), sessionId: 'sess_abc' } ``` ### `automation` Use for jobs, integrations, and rule engines. ```ts const actor = { type: 'automation', id: actorId('system:po-router'), serviceId: 'po-service' } ``` ### `ai-agent` Use for model-driven recommendations or execution. ```ts const actor = { type: 'ai-agent', id: actorId('agent:forecaster'), agentId: 'claude-3-5-sonnet', gatewaySessionId: 'gw_123' } ``` ### `system` Use for internal runtime/platform initiated actions. ```ts const actor = { type: 'system', id: actorId('system:loop-engine') } ``` ## Actor evidence Use `buildActorEvidence(actor, baseEvidence)` to normalize actor-attributed evidence. For all actors, the helper adds: - `actor_type` - `actor_id` For `ai-agent`, it also adds: - `ai_agent_id` - optional `ai_confidence` and `ai_reasoning` (when present in base evidence) ## Authorization checks `canActorExecuteTransition(actor, transition, constraints?)` returns: ```ts { authorized: boolean; requiresApproval: boolean; reason?: string } ``` ```ts import { canActorExecuteTransition } from '@loop-engine/actors' const auth = canActorExecuteTransition(actor, transition) if (!auth.authorized) { console.log(auth.reason) } ``` Do not make `ai-agent` the only allowed actor on a critical transition. Include `human` or `automation` as a fallback execution path. ## Related - [AI as Actor](/docs/ai-and-automation/ai-as-actor) - [Agents and RAG](/docs/concepts/agents-and-rag) --- ## Guards and Policy URL: https://bossloops.io /docs/concepts/guards-and-policy Summary: Guards are deterministic policy checks that run before a transition executes - hard guards block, soft guards warn. Section: Core Concepts ## What guards are Guards are deterministic policy checks evaluated before state advancement. In this runtime, a guard is a `GuardFunction` returning `{ passed, code?, message?, metadata? }`. ## Hard vs soft | | Hard | Soft | |---|---|---| | Blocks transition | Yes | No | | State advances | No | Yes | | Emitted event on failure | `loop.guard.failed` | Failure warning is attached to `_softGuardWarnings` evidence | | Typical use | Mandatory policy | Warning and monitoring | ## `evaluatedBy` `GuardSpec.evaluatedBy`: - `runtime` - evaluated by registered `GuardFunction` - `module` - declared for module-level policy contract - `external` - caller provides result context in evidence contract ## Built-in guards ### `actor_has_permission` - Reads: `required_role`, `roles` - Fails when `required_role` is missing from `roles` ### `approval_obtained` - Reads: `approved` - Fails when `approved !== true` ### `deadline_not_exceeded` - Reads: `deadline_iso` - Fails when deadline format is invalid or current time exceeds deadline ### `duplicate_check_passed` - Reads: `duplicate_found` - Fails when `duplicate_found === true` ### `field_value_constraint` - Reads: `constraint` plus referenced field - Supported operators: `eq`, `gt`, `lt`, `in` ## Add a custom guard ```ts // @no-typecheck import { guardId } from '@loop-engine/core' import { createGuardRegistry } from '@loop-engine/guards' const registry = createGuardRegistry() registry.register(guardId('my_custom_guard'), async (context) => { const passed = context.evidence.budget_available === true return { passed, message: passed ? 'Budget available' : 'Insufficient budget' } }) ``` Use this registry in `createLoopSystem({ loops, guards: registry })`. ## Related - [Decision Governance](/docs/concepts/decision-governance) - [Human Approval Gates](/docs/ai-and-automation/human-approval-gates) --- ## Signals URL: https://bossloops.io /docs/concepts/signals Summary: Signals detect meaningful patterns in loop events and trigger governed workflows when configured conditions match. Section: Core Concepts ## What signals are Signals are detected patterns derived from loop events. A `SignalRule` evaluates event streams and returns a detection result when matched. ## `SignalRule` anatomy ```ts interface SignalRule { id: string name: string description: string targetLoopId?: LoopId evaluate: (events: LoopEvent[]) => SignalDetectionResult | null } ``` ## Built-in signal rules ### `threshold-breach` - Signal type: `THRESHOLD_BREACH` - Detects numeric evidence crossing configured threshold - Config: `field`, `operator`, `threshold` ### `state-dwell` - Signal type: `STATE_DWELL_EXCEEDED` - Detects prolonged dwell in a target state - Config: `state`, `maxDwellMinutes` ### `repeated-guard-failure` - Signal type: `GUARD_FAILURE_PATTERN` - Detects repeated `loop.guard.failed` events for one guard ID - Config: `guardId`, `maxFailures` ### `loop-not-started` - Signal type: `LOOP_TRIGGER_DELAYED` - Detects when a signal is received but no loop started in time window - Config: `maxDelayMinutes` ## Create a signal engine ```ts // @no-typecheck // SR-024 will replace this block with the published `SignalRegistry` + event-bus flow. F-38 marker: legacy actor fields in related pages. import { createSignalEngine } from '@loop-engine/sdk' const signals = createSignalEngine() signals.subscribe((signal) => { console.log(signal.type, signal.subject, signal.confidence) }) ``` ## Connect signal detection to loop creation ```ts // @no-typecheck signals.subscribe(async (signal) => { if (signal.type !== 'THRESHOLD_BREACH') return await engine.start({ loopId: 'scm.replenishment', aggregateId: aggregateId(`repl-${Date.now()}`), actor: { type: 'system', id: 'system:signal-router' }, metadata: { triggeredBy: signal.id, source: 'signal-router' } }) }) ``` --- ## Observability URL: https://bossloops.io /docs/concepts/observability Summary: Boss Loops observability surfaces metrics, timelines, and replay diagnostics from runtime state and history. Section: Core Concepts ## What Boss Loops tracks Runtime state comes from: - `LoopInstance` records (`currentState`, `status`, timestamps) - `TransitionRecord[]` history (who did what, when, and with what evidence) The observability package computes aggregate metrics and timelines from that data. ## `LoopMetrics` `computeMetrics(instances, history, period)` returns: - `loopId` - `period` - `totalInstances` - `openInstances` - `closedInstances` - `errorInstances` - `avgDurationMs` - `medianDurationMs` - `p95DurationMs` - `completionRate` - `guardFailureRate` - `aiActorRate` - `humanActorRate` - `avgTransitionCount` ```ts import { computeMetrics } from '@loop-engine/observability' ``` ## Timelines and state residency Use `buildTimeline(instance, history)` for a normalized timeline view. Use `getStateResidency(timeline)` to see dwell per state: ```ts // @no-typecheck import { buildTimeline, getStateResidency } from '@loop-engine/observability' const timeline = buildTimeline(instance, history) const residency = getStateResidency(timeline) ``` State residency highlights bottlenecks (for example loops spending excessive time in `OPEN` or `INVOICE_MATCHED`). ## Replay and validation `replayLoop(definition, history)` validates transition history against a definition: ```ts // @no-typecheck import { replayLoop } from '@loop-engine/observability' const replay = replayLoop(definition, history) if (!replay.valid) { console.error(replay.errors) } ``` Use replay for: - audits - debugging invalid transitions - migration validation after definition updates ## Devtools `@loop-engine/ui-devtools` exports components for local diagnostics: - `DevtoolsPanel` - `LoopTimeline` - `EventStream` - `StateDiagram` - `MetricsCard` --- ## Learning Signals URL: https://bossloops.io /docs/concepts/learning-signals Summary: Learning signals capture predicted-versus-actual outcomes so loop performance can improve over time. Section: Core Concepts ## What learning signals are `LearningSignal` captures predicted vs actual outcome data at loop completion boundaries. It is produced by `extractLearningSignal()` in `@loop-engine/events`. ## `LearningSignal` fields - `loopId` - `aggregateId` - `outcomeId` - `predicted: Record` - `actual: Record` - `delta: Record` - `occurredAt` - `confidence?` ## `extractLearningSignal` signature ```ts extractLearningSignal( completed: LoopCompletedEvent, history: TransitionRecord[], predicted?: Record ): LearningSignal ``` Current implementation behavior: - derives `actual.cycle_time_days` from completion time minus first history timestamp - computes numeric deltas where both `predicted[key]` and `actual[key]` are numbers - returns empty `delta` when keys do not numerically align ## Business metrics `BusinessMetric` (from `@loop-engine/core`): - `id` - `label` - `unit` - `improvableByAI` Example metrics from `loops/scm/procurement.yaml`: - `cycle_time_days` - `three_way_match_first_attempt` - `supplier_lead_time_accuracy` Marking `improvableByAI: true` identifies metrics appropriate for model optimization loops. ## Feedback cycle ```text Loop completes -> extractLearningSignal() -> store signal in training dataset -> retrain/tune model -> deploy improved agent behavior -> faster, safer loop completion ``` --- ## AI as Actor URL: https://bossloops.io /docs/ai-and-automation/ai-as-actor Summary: AI is one actor among several in Boss Loops - it can recommend and execute transitions within defined bounds, never outside them. Section: Core Concepts ## AI as an actor, not the controller Boss Loops treats AI the same way it treats humans and automation: as an attributed actor constrained by transitions and guards. ## What AI can do - inspect loop state in your application layer - recommend transitions with evidence - execute transitions where `allowedActors` includes `ai-agent` ## What AI cannot do - bypass `allowedActors` - bypass hard guards - modify loop definitions at runtime - execute indefinitely if circuit-breaker constraints block it ## `AIAgentActor` shape ```ts interface AIAgentActor extends ActorRef { type: "ai-agent" agentId: string gatewaySessionId: string recommendedBy?: string } ``` ## AI submission flow ```ts // @no-typecheck // F-38: canonical `AIAgentActor` + submission types are being realigned in SR-024; this block stays illustrative. import { actorId, transitionId } from '@loop-engine/core' import { canActorExecuteTransition, buildActorEvidence, type AIAgentActor } from '@loop-engine/actors' const agent: AIAgentActor = { type: 'ai-agent', id: actorId('agent:demand-forecaster'), agentId: 'claude-3-5-sonnet', gatewaySessionId: session.id } const auth = canActorExecuteTransition(agent, transition) if (auth.authorized) { const evidence = buildActorEvidence(agent, { ai_confidence: 0.94, ai_reasoning: 'Stock level below reorder point; lead time elevated', recommended_qty: 500 }) await engine.transition({ aggregateId, transitionId: transitionId('trigger_po'), actor: { type: agent.type, id: String(agent.id) }, evidence }) } ``` ## Provider implementations The actor contract stays constant across providers. Only SDK wiring changes. ```ts // Anthropic path (Claude) const claudeActor: AIAgentActor = { type: "ai-agent", id: actorId("agent:demand-forecaster"), agentId: "claude-sonnet-4-20250514", gatewaySessionId: "claude-session-123" } // OpenAI path (GPT-4o) const openAiActor: AIAgentActor = { type: "ai-agent", id: actorId("agent:demand-forecaster"), agentId: "gpt-4o", gatewaySessionId: "openai-session-123" } ``` Anthropic and OpenAI both submit through the same transition path and evidence schema: - `ai_confidence` - `ai_reasoning` - `recommended_action` - `recommended_qty` ## Safety constraints - Confidence `0.58` on `recommend_replenishment` returns `guard_failed` and holds state at `AI_ANALYSIS`. - Confidence `0.82` passes `confidence_threshold` and advances to `PENDING_BUYER_APPROVAL`. - AI attempts on `approve_replenishment` are rejected when transition `allowedActors` is `["human"]`. ## Deep-dive example The full dual-provider walkthrough is in `/docs/examples/ai-replenishment`, with source links for both provider adapters: - [Anthropic actor example](https://github.com/loopengine/loop-examples/tree/main/ai-actors/claude) - [OpenAI actor example](https://github.com/loopengine/loop-examples/tree/main/ai-actors/openai) ## Available AI adapters | Package | Models | |---|---| | [`@loop-engine/adapter-anthropic`](/docs/packages/adapter-anthropic) | Claude (`claude-opus-4-6`, `claude-sonnet-4-6`) | | [`@loop-engine/adapter-openai`](/docs/packages/adapter-openai) | OpenAI (`gpt-4o`, o-series) | | [`@loop-engine/adapter-grok`](/docs/packages/adapter-grok) | Grok (`grok-3`, `grok-2`) via xAI | | [`@loop-engine/adapter-gemini`](/docs/packages/adapter-gemini) | Gemini (`gemini-1.5-pro`, `gemini-2.0-flash`) | | [`@loop-engine/adapter-perplexity`](/docs/packages/adapter-perplexity) | Perplexity Sonar (`sonar`, `sonar-pro`, …) — `ToolAdapter` with citations for research steps | The Perplexity package implements `ToolAdapter.invoke()` (text + citations), not the actor `createSubmission` flow. Use it where you need grounded retrieval inside a loop; use the actor adapters above for structured signal decisions. ## Related - [Agents and RAG](/docs/concepts/agents-and-rag) - [Decision Governance](/docs/concepts/decision-governance) - [@loop-engine/adapter-grok](/docs/packages/adapter-grok) - [@loop-engine/adapter-gemini](/docs/packages/adapter-gemini) - [@loop-engine/adapter-perplexity](/docs/packages/adapter-perplexity) --- ## Confidence and Evidence URL: https://bossloops.io /docs/ai-and-automation/confidence-evidence Summary: Evidence captures why actions happened, and confidence values power explicit policy thresholds for AI-driven transitions. Section: Core Concepts ## Why evidence matters Evidence is persisted in every `TransitionRecord`. For AI actions, evidence is the audit answer to: _why was this recommendation accepted?_. ## `buildActorEvidence()` From `@loop-engine/actors`: ```ts buildActorEvidence(actor: Actor, baseEvidence: Evidence): Evidence ``` For all actor types, it merges: - `actor_type` - `actor_id` For `ai-agent`, it also merges: - `ai_agent_id` - `ai_confidence` (if present in base evidence) - `ai_reasoning` (if present in base evidence) ## Confidence policy Boss Loops stores confidence but does not enforce policy thresholds itself. Implement thresholds in your app layer: - `>= 0.90`: can auto-execute when authorized - `0.70 - 0.89`: execute with review workflow - `< 0.70`: recommend only, require human gate ## Reasoning best practices - include concrete numeric drivers - include threshold context - keep concise for audit readability Good: ```text Stock 18% below reorder point (82 units). Lead time 12d. Trigger threshold: 95 units. ``` ## Reading AI evidence from history ```ts const history = await engine.getHistory(aggregateId) for (const row of history) { if (row.actor.type !== 'ai-agent') continue console.log(row.evidence.ai_confidence, row.evidence.ai_reasoning) } ``` --- ## Human Approval Gates URL: https://bossloops.io /docs/ai-and-automation/human-approval-gates Summary: Human approval gates keep high-impact actions controlled by policy and runtime authorization, not prompt wording. Section: Core Concepts ## When to require human approval Use human gates for: - high-value financial commitments - irreversible actions - regulated or compliance-heavy decisions ## Pattern A: exclude `ai-agent` from `allowedActors` ```yaml - id: settle_invoice from: MATCHED to: SETTLED allowedActors: [human, automation] ``` If an AI actor attempts this transition, authorization returns `requiresApproval: true`. ## Pattern B: AI constraints in authorization `AIActorConstraints` in `@loop-engine/actors`: ```ts interface AIActorConstraints { requiresHumanApprovalFor?: TransitionId[] } ``` When an `ai-agent` actor attempts a transition whose ID appears in `requiresHumanApprovalFor`, `canActorExecuteTransition()` returns unauthorized with `requiresApproval: true`. ## Pending approval sequence ```ts const aiAuth = canActorExecuteTransition(aiActor, transition, constraints) if (!aiAuth.authorized && aiAuth.requiresApproval) { // Create human review task using ai evidence } // Later, human executes same transition: await engine.transition({ aggregateId, transitionId, actor: { type: 'human', id: 'approver@acme.com' }, evidence: { approved: true, approval_ticket: 'APR-123' } }) ``` `AIActorConstraints` ships with a single field, `requiresHumanApprovalFor`. Boss Loops does not provide a built-in consecutive-AI-transition circuit breaker. Track that policy in your application and translate it into per-transition entries on this list (or into `allowedActors` exclusions). --- ## Decision Governance URL: https://bossloops.io /docs/concepts/decision-governance Summary: Why governed decision loops exist - the problem Boss Loops solves that workflow engines and agent frameworks leave open. Section: Core Concepts ## The Problem In modern enterprise systems, AI agents retrieve context, reason over it, and recommend or execute actions. This works well in development. In production, three requirements emerge that most stacks do not address: - Decisions must be attributable - who or what made each decision, and why - Policies must be enforced at the runtime level, not in prompts - Audit trails must be reconstructable - not reassembled from scattered logs Without an explicit governance layer, teams discover that decision trails are spread across prompt logs, API traces, application logs, and database records. Reconstructing the reasoning behind a decision after the fact is fragile. ## What Boss Loops Adds Boss Loops sits between AI reasoning and operational execution. Its job is to govern the decision lifecycle. ```text Enterprise Knowledge Sources ↓ RAG / Agent Reasoning Layer ↓ Boss Loops - Decision Governance ↓ Workflow / Execution Systems ``` Every transition through a loop: - Names the actor responsible (human, automation, or AI agent) - Evaluates guard policies before allowing the transition - Attaches evidence - what information the actor used - Emits a structured event with full attribution This creates a decision record at runtime, not a best-effort reconstruction later. ## What This Is Not Boss Loops is not a workflow engine. It does not schedule jobs, manage retries, or handle durable execution. Systems like Temporal or Prefect own those concerns. Boss Loops is not an agent framework. It does not orchestrate tool calls or manage model context. LangGraph, OpenAI Assistants, and your own agent runtime own that layer. Boss Loops governs the boundary between reasoning and action. It enforces who can do what, under what conditions, with what evidence. ## How the governance weighting works Boss Loops uses three types of weighting in sequence — all must pass for a transition to execute. 1. **Confidence threshold (numeric gate)** Every AI actor submission carries a `0–1` confidence score. The guard blocks the transition if the score falls below the configured threshold. In the fraud review example, `0.60` triggers escalation to human review and `0.80` allows auto-dismiss — two thresholds, two different outcomes from the same loop state. 2. **Guard priority (hard vs soft)** Guards have a failure mode: `hard` or `soft`. Hard failures block the transition regardless of everything else. Soft failures warn and continue. A human-only guard on an approval transition is an absolute block — no confidence score overrides it. This is intentional: policy is enforced at the runtime level, not in prompts. 3. **Evidence completeness (structural gate)** The evidence-required guard checks for the presence of specific fields before allowing a transition. The infrastructure change example requires `blast_radius_score`, `affected_services`, and `rollback_plan` — missing any one field blocks the transition. This ensures AI actors cannot submit incomplete reasoning. ### Evaluation order 1. Actor authorized for this signal? 2. Required evidence fields present? 3. Confidence score above threshold? 4. All hard guards pass? Any failure stops the sequence. The transition only executes when all checks pass. The key design principle is compositional governance. You stack guards, each with its own failure mode and parameters. Simple loops use one or two. Complex regulated workflows use four or five. ## Related - [Boss Loops vs Workflow Engines](/docs/concepts/loop-engine-vs-workflow-engines) - [Agents and RAG](/docs/concepts/agents-and-rag) - [Guards and Policy](/docs/concepts/guards-and-policy) - [Learning Signals](/docs/concepts/learning-signals) --- ## Evidence Providers URL: https://bossloops.io /docs/concepts/evidence-providers Summary: How Looker, Snowflake, and Samsara attach governed evidence to the Decision Record — frozen at capture, with qualification inherited from the source. Section: Core Concepts ## What an Evidence Provider is An **Evidence Provider** attaches governed evidence to a Decision Record. It is not a Model Provider (it supplies no intelligence) and not an Integration (it executes no side effects). It supplies one thing: **what was true, from a governed source, at the moment it informed the decision** — frozen into an immutable snapshot the record carries forever. Two archetypes: ``` Semantic evidence → governed definitions from your warehouse and BI stack (e.g. Snowflake semantic views, Looker explores) Operational evidence → live readings from fleet and field systems (e.g. Samsara telemetry at decision time) ``` Three properties make this different from linking to a dashboard: - **Frozen at capture.** The Decision Record holds the value, definition, source, and timestamp as they were when the decision was made — not a link that may have changed since. The vendor UI remains an optional live surface; the record is the frozen one. - **Qualification is inherited, never asserted.** How governed a definition is, how attestable its provenance, how fresh the reading — these come from the source's own mapping, not from whoever built the loop. - **Conformance is verifiable.** The provider contract and conformance suite live in Boss Loops OSS, so "every evidence source in this decision conformed to the contract" is a statement an auditor can check — not a marketing claim. ## Status legend | Badge | Meaning | |---|---| | **Preview** | A fixture/seed illustrates the architecture on the demo Decision Record; not a live vendor connection | | **Contract-validated** | The evidence shape passes the OSS contract exemplars and conformance checks | | **Conformant Provider** | Future — a production adapter that passes the public OSS conformance suite | | **Boss Loops Cloud** | Future hosted connector path, managed auth included | ## Looker — semantic evidence (Preview) Approvers see a number in Slack; nobody remembers which Explore, which band, as of when. With Looker as an Evidence Provider, the **certified metric definition** travels with the decision: the demo Alpine invoice record carries vendor spend vs. a 12-month band as a preview snapshot — definition, value, and qualification frozen on the record. **Today:** preview snapshot on the Alpine demo Decision Record. It illustrates qualification inherited from the provider — not asserted by the loop. There is no live Looker API connection yet. **Next:** a live connector with LookML mapping, an optional rendered tile, and two-clock freshness (when the value was bound vs. when it was observed). ## Snowflake — semantic evidence (Planned) Warehouse truth exists; decisions happen in email with screenshots and stale exports. With Snowflake as an Evidence Provider, **governed semantic views** become Evidence Snapshots with lineage and qualification. **Today:** the evidence shape is contract-validated in Boss Loops OSS (governed semantic metric exemplar); a reference JSON provider exercises it. There is no live warehouse connection on the demo. **Next:** a production semantic provider for semantic views and governed metrics. Ad-hoc SQL stays unreviewed — it must not map to governed. We document the governed path first. ## Samsara — operational evidence (Planned) Operational decisions need what was true on the ground — not a dashboard someone refreshed later. With Samsara as an Evidence Provider, **telemetry is captured at decision time**, with provenance up to origin-attested where hardware and process support it. **Today:** the evidence shapes are contract-validated in Boss Loops OSS (telemetry and origin-attested exemplars). There is no live fleet connection on the demo. Operational evidence is captured, not streamed as a live widget on the record. **Next:** a production operational provider with real-time freshness and origin attestation where warranted. ## Where the line sits (OSS vs. hosted) The **contract, reference providers, and conformance suite are open** in Boss Loops OSS — you can validate an evidence shape and verify the invariants yourself. **Production adapters** (managed auth, live vendor connections, full qualification presentation) ship in the hosted tier. Consuming your existing semantics — not re-modeling them — is the point: Boss Loops opens what Looker, Snowflake, and Samsara already govern; it does not replace them. --- ## Boss Loops vs Workflow Engines URL: https://bossloops.io /docs/concepts/loop-engine-vs-workflow-engines Summary: How Boss Loops and workflow engines like Temporal complement each other - execution vs decision governance. Section: Core Concepts ## Two Different Problems Workflow engines like Temporal solve durable execution: retries, timers, distributed coordination, and fault tolerance. Boss Loops solves decision governance: actor authorization, policy enforcement, evidence capture, and decision audit trail. These are different problems. Both can exist in the same system. ## Temporal's Responsibilities - Durable workflow execution - Activity retries with backoff - Long-running process coordination - Saga pattern and distributed transactions - Timer and scheduling primitives ## Boss Loops' Responsibilities - Defining who can trigger each transition - Enforcing guard policies before allowing state changes - Capturing evidence attached to each decision - Attributing every action to a named actor - Emitting structured events for audit and learning ## When to Use Each Use Temporal when: you need fault-tolerant execution of multi-step operations. Use Boss Loops when: you need governed, attributable decision checkpoints. Use both when: AI agents make recommendations inside durable workflows that require human approval, policy enforcement, and audit trail. ## Combined Architecture ```text AI Agent ↓ Boss Loops <- decision governance layer ↓ Temporal <- durable execution layer ↓ Infrastructure ``` The agent proposes an action. Boss Loops governs whether it is allowed and by whom. Temporal durably executes the approved action. ## Code Example ```ts import { createLoopSystem } from "@loop-engine/sdk"; import type { ActorRef, TransitionId } from "@loop-engine/core"; type TemporalActivityInput = { aggregateId: string; transitionId: TransitionId; actor: ActorRef; }; export async function runApprovedOperation(input: TemporalActivityInput) { const { engine } = await createLoopSystem({ loops: [/* registered loop definitions */] }); const decision = await engine.transition({ aggregateId: input.aggregateId as never, transitionId: input.transitionId, actor: input.actor, evidence: { source: "temporal-activity" } }); if (decision.status !== "executed") { throw new Error(`Operation blocked by governance: ${decision.status}`); } // Durable execution happens in workflow engine after approval. } ``` ## Related - [Decision Governance](/docs/concepts/decision-governance) - [AI as Actor](/docs/ai-and-automation/ai-as-actor) - [Guards and Policy](/docs/concepts/guards-and-policy) --- ## Agents and RAG URL: https://bossloops.io /docs/concepts/agents-and-rag Summary: How Boss Loops governs the decision boundary in AI agent systems and RAG pipelines. Section: Core Concepts ## What Agent Frameworks Do Agent frameworks like LangGraph, OpenAI Assistants, and custom agent loops focus on retrieving context, selecting tools, chaining operations, and generating recommendations from retrieved information. They are excellent at reasoning. They are not designed to govern whether the resulting action is authorized, attributable, or auditable. ## The Governance Gap A typical agentic flow: ```text Knowledge Base ↓ RAG Retrieval <- context retrieval ↓ LLM / Agent Reasoning <- recommendation ↓ Tool / API Execution <- action ``` This works for low-risk autonomous tasks. In enterprise production - supply chain, financial approvals, healthcare, infrastructure - the gap between "agent recommends" and "system executes" needs an explicit governance layer. ## Where Boss Loops Fits ```text Knowledge Base ↓ RAG Retrieval ↓ LLM / Agent Reasoning ↓ Boss Loops <- decision governance ↓ Workflow Execution ``` The agent's recommendation becomes a proposed transition in a decision loop. Guards evaluate it. A human approves when policy requires. The action executes only after the loop allows it. ## RAG Outputs as Evidence RAG systems already produce high-value evidence: retrieved documents, confidence scores, and graph relationships. Boss Loops attaches this context directly to transitions as structured evidence, creating a permanent record of what the model used, what it recommended, and why the system allowed the action. ## Code Example ```ts // @no-typecheck import Anthropic from "@anthropic-ai/sdk"; import { createAnthropicActorAdapter } from "@loop-engine/adapter-anthropic"; import { createLoopSystem } from "@loop-engine/sdk"; const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY }); const adapter = createAnthropicActorAdapter(anthropic, { modelId: "claude-opus-4-6" }); const { engine } = await createLoopSystem({ loops: [/* procurement loop */] }); const ragResults = { retrievedDocs: 12, confidence: 0.84, ragSource: "vendor-policy-kb" }; const { actor, decision } = await adapter.createSubmission({ loopId: "procurement", loopName: "SCM Procurement", currentState: "pending_analysis", availableSignals: [{ signalId: "submit_recommendation", name: "Submit Recommendation" }], instruction: "Recommend whether to proceed with purchase order issuance.", evidence: { ...ragResults } }); await engine.transition({ aggregateId: "PO-10042" as never, transitionId: "submit_recommendation" as never, actor, evidence: { ...decision, ragResults } }); ``` ## Commerce Chain and Boss Loops Boss Loops is the runtime that powers the [Commerce Chain](https://commercechain.io) platform. Each `@betterdata/scm-*` and `@betterdata/dcm-*` module declares how it participates in loops using a **`LoopParticipantManifest`** from `@betterdata/loop-definitions`—a typed map of which domain events the module handles and which loop IDs it joins. Canonical loop IDs and domain event names live in **`@betterdata/loop-definitions`** (`LoopIds`, `EventNames`) so modules and the host runtime stay aligned. - [Commerce Chain](https://commercechain.io) - [Loop participation guide](https://commercechain.io/docs/getting-started/loop-participation) - [Architecture](https://commercechain.io/docs/getting-started/architecture) ## Related - [AI as Actor](/docs/ai-and-automation/ai-as-actor) - [Confidence + Evidence](/docs/ai-and-automation/confidence-evidence) - [Decision Governance](/docs/concepts/decision-governance) - [Boss Loops vs Workflow Engines](/docs/concepts/loop-engine-vs-workflow-engines) --- ## When to Use Boss Loops URL: https://bossloops.io /docs/concepts/when-to-use Summary: Is Boss Loops right for your use case? Use this page to decide quickly. Section: Core Concepts ## Use Boss Loops When - AI agents make recommendations that affect operational systems - Human approvals are required at defined checkpoints - Policies must be enforced consistently, not through prompt instructions - Decisions must carry an attributable audit trail - Multiple actor types (human + AI + automation) participate in one flow - Your industry requires demonstrable decision governance (healthcare, finance, pharma, regulated manufacturing) ## You Probably Don't Need It When - Your workflow has a single actor and no approval gates - The operation is fully deterministic with no AI or human decision points - You only need retry logic and scheduling (use a workflow engine) - You are building a prototype or exploration system ## Good Fits by Industry - Healthcare and pharma: governed clinical and supply workflows with audit trails - Financial services: fraud review, credit decisions, and change approvals - Supply chain: AI-assisted procurement and demand signal response - Infrastructure: change management and deployment gates - Content and trust: moderation escalation and editorial approval ## Combined With Other Tools Boss Loops works alongside workflow engines and agent frameworks - it does not replace them. - [Boss Loops vs Workflow Engines](/docs/concepts/loop-engine-vs-workflow-engines) - [Agents and RAG](/docs/concepts/agents-and-rag) ## Not Sure? If you are asking, "can the AI just do this without approval?" that is usually the signal that you need Boss Loops. --- ## YAML Format URL: https://bossloops.io /docs/defining-loops/yaml-format Summary: Boss Loops YAML definitions map to the LoopDefinition schema and are validated before runtime use. Section: Defining Loops ## Loop definition YAML reference This format is validated by `LoopDefinitionSchema` in `@loop-engine/loop-definition`. ### Top-level fields - `id: string` (required) - `version: string` semver `x.y.z` (required) - `description: string` (required) - `domain: string` (required) - `states: StateSpec[]` (required, at least 1) - `initialState: string` (required, must exist in `states`) - `transitions: TransitionSpec[]` (required) - `outcome: OutcomeSpec` (required) - `participants?: string[]` - `spawnableLoops?: string[]` - `metadata?: Record` ### `StateSpec` - `id: string` (required) - `description?: string` - `isTerminal?: boolean` - `isError?: boolean` ### `TransitionSpec` - `id: string` - `from: string` - `to: string` - `allowedActors: ("human" | "automation" | "ai-agent" | "system")[]` - `guards?: GuardSpec[]` - `sideEffects?: SideEffectSpec[]` - `description?: string` ### `GuardSpec` - `id: string` - `description: string` - `failureMessage: string` - `severity: "hard" | "soft"` - `evaluatedBy: "runtime" | "module" | "external"` ### `OutcomeSpec` - `id: string` - `description: string` - `valueUnit: string` - `measurable: boolean` - `businessMetrics?: BusinessMetric[]` ## Annotated example (`scm.procurement`) ```yaml id: scm.procurement version: 1.0.0 domain: scm description: Purchase order lifecycle through settlement states: - id: OPEN - id: PO_CONFIRMED - id: RECEIVED - id: INVOICE_MATCHED - id: SETTLED isTerminal: true - id: DISPUTED isError: true initialState: OPEN transitions: - id: confirm_po from: OPEN to: PO_CONFIRMED allowedActors: [human, automation, ai-agent] guards: - id: approval_obtained severity: hard evaluatedBy: external description: PO must be approved before confirmation failureMessage: PO confirmation requires explicit approval outcome: id: po_settled description: Purchase order settled with matched invoice valueUnit: po_settled measurable: true businessMetrics: - id: cycle_time_days label: PO cycle time (days) unit: days improvableByAI: true ``` ## Common validation errors - `initialState` not found in `states` - transition `from`/`to` references unknown state - empty `allowedActors` - duplicate state IDs - invalid `version` format (must be semver) --- ## TypeScript Builder URL: https://bossloops.io /docs/defining-loops/typescript-builder Summary: LoopBuilder provides a fluent, type-guided way to define loops with runtime validation on build. Section: Defining Loops ## `LoopBuilder` API (`@loop-engine/sdk`) `LoopBuilder` is a fluent authoring API that validates on `.build()`. ### Signatures ```ts LoopBuilder.create(id: string, domain: string): LoopBuilder version(v: string): LoopBuilder description(d: string): LoopBuilder state(id: string, options?: { isTerminal?: boolean; isError?: boolean }): LoopBuilder initialState(id: string): LoopBuilder transition(spec: { id: string from: string to: string actors: ActorType[] guards?: Partial[] }): LoopBuilder outcome(spec: { id?: string description?: string valueUnit?: string measurable?: boolean businessMetrics?: Array<{ id: string; label: string; unit: string; improvableByAI: boolean }> }): LoopBuilder build(): LoopDefinition ``` ### Runtime behavior notes - `.transition()` throws if `actors` is empty. - `.build()` throws if outcome is missing. - `.build()` validates via `validateLoopDefinition()`. ## Example: procurement-style loop in TypeScript ```ts import { LoopBuilder } from '@loop-engine/sdk' const procurement = LoopBuilder .create('scm.procurement', 'scm') .version('1.0.0') .description('Purchase order lifecycle through settlement') .state('OPEN') .state('PO_CONFIRMED') .state('RECEIVED') .state('INVOICE_MATCHED') .state('SETTLED', { isTerminal: true }) .initialState('OPEN') .transition({ id: 'confirm_po', from: 'OPEN', to: 'PO_CONFIRMED', actors: ['human', 'automation', 'ai-agent'], guards: [ { id: 'approval_obtained', severity: 'hard', evaluatedBy: 'external', description: 'PO must be approved', failureMessage: 'PO confirmation requires explicit approval' } ] }) .outcome({ id: 'po_settled', description: 'Purchase order settled', valueUnit: 'po_settled', measurable: true, businessMetrics: [ { id: 'm_po_settled', label: 'PO settled', unit: 'count' } ] }) .build() ``` Use YAML when loop definitions are owned by ops/product teams; use builder when you prefer type-guided code review and composition. --- ## Loop Library URL: https://bossloops.io /docs/defining-loops/loop-library Summary: The loop library provides canonical YAML definitions you can run directly or use as patterns. Section: Defining Loops ## Canonical loop definitions Boss Loops currently ships these canonical definitions from `loops/`: | Loop ID | Domain | States | Terminal states | Business metrics | |---|---|---:|---:|---:| | `scm.procurement` | `scm` | 8 | 2 | 3 | | `scm.replenishment` | `scm` | 5 | 2 | 2 | | `crm.lead_qualification` | `crm` | 6 | 2 | 2 | | `finance.invoice_collection` | `finance` | 6 | 2 | 2 | | `support.ticket_resolution` | `support` | 6 | 2 | 2 | | `erp.purchase_approval` | `erp` | 6 | 2 | 2 | ## Featured definition: `scm.procurement` ```yaml id: scm.procurement version: 1.0.0 domain: scm description: > Purchase order lifecycle from requisition through receipt and settlement. states: - id: OPEN - id: PO_CONFIRMED - id: RECEIPT_SCHEDULED - id: RECEIVED - id: INVOICE_MATCHED - id: SETTLED isTerminal: true - id: CANCELLED isTerminal: true - id: DISPUTED isError: true initialState: OPEN transitions: - id: confirm_po from: OPEN to: PO_CONFIRMED allowedActors: [human, automation, ai-agent] outcome: id: po_settled description: Purchase order fully settled with matched invoice and inventory updated valueUnit: po_settled measurable: true ``` Raw files: - [procurement.yaml](https://github.com/loopengine/loop-engine/blob/main/loops/scm/procurement.yaml) - [replenishment.yaml](https://github.com/loopengine/loop-engine/blob/main/loops/scm/replenishment.yaml) - [lead-qualification.yaml](https://github.com/loopengine/loop-engine/blob/main/loops/crm/lead-qualification.yaml) ## Contributing a loop definition - Add YAML under `loops/{domain}/{name}.yaml` - Validate with `pnpm validate-loops` - Include a concrete `outcome` - Add `businessMetrics` when measurable - Prefer at least one non-human actor option (`automation`, `system`, or `ai-agent`) where domain-appropriate See [Contributing](/docs/governance/contributing) for full workflow. ## Naming conventions - Loop ID: `{domain}.{noun}` (for example `scm.procurement`) - State IDs: `SCREAMING_SNAKE_CASE` - Transition IDs: `snake_case` verbs (for example `confirm_po`, `receive_goods`) --- ## Guards Reference URL: https://bossloops.io /docs/defining-loops/guards-reference Summary: Built-in guards enforce policy checks before transitions execute, with deterministic failure behavior. Section: Defining Loops ## Built-in guard reference All built-ins are in `packages/guards/src/built-in/*` and are registered by default in `defaultRegistry`. ### `actor_has_permission` - Evaluated by: `runtime` - Implementation: checks `evidence.required_role` against `evidence.roles` - Failure message: `Missing actor roles in evidence` or `Actor missing required role: ` Required evidence fields: | Field | Type | Required | Description | |---|---|---|---| | `required_role` | `string` | conditional | role to require | | `roles` | `unknown[]` | conditional | actor role set | ### `approval_obtained` - Evaluated by: `runtime` - Check: `evidence.approved === true` - Failure message: `Approval not obtained` | Field | Type | Required | Description | |---|---|---|---| | `approved` | `boolean` | yes | explicit approval flag | ### `deadline_not_exceeded` - Evaluated by: `runtime` - Check: current time before `Date.parse(evidence.deadline_iso)` - Failures: `Invalid deadline format` or `Deadline exceeded` | Field | Type | Required | Description | |---|---|---|---| | `deadline_iso` | `string` | conditional | ISO deadline timestamp | ### `duplicate_check_passed` - Evaluated by: `runtime` - Check: `evidence.duplicate_found !== true` - Failure message: `Duplicate detected` | Field | Type | Required | Description | |---|---|---|---| | `duplicate_found` | `boolean` | conditional | duplicate marker | ### `field_value_constraint` - Evaluated by: `runtime` - Reads `evidence.constraint`: - `field` - `operator: "eq" | "gt" | "lt" | "in"` - `value` - Failure message: `Field constraint failed for ` | Field | Type | Required | Description | |---|---|---|---| | `constraint` | object | yes | rule descriptor | | `` | unknown | yes | value to compare | ## Loop definition usage ```yaml guards: - id: approval_obtained severity: hard evaluatedBy: runtime description: Approval must be present failureMessage: Approval not obtained ``` ## Failure behavior - Hard guard failure returns `TransitionResult.status: "guard_failed"` - Runtime emits `loop.guard.failed` - State does not advance - Soft guard failures are preserved under `_softGuardWarnings` in transition evidence ## Writing custom guards Use `GuardFunction` from `@loop-engine/guards`: ```ts type GuardFunction = (context: GuardContext) => Promise ``` See [Guards and Policy](/docs/concepts/guards-and-policy) for full custom registry setup. --- ## createLoopSystem URL: https://bossloops.io /docs/running-loops/create-loop-system Summary: The createLoopSystem factory wires together a LoopEngine, event bus, and optional loop catalog client in a single call. Section: Running Loops ## `createLoopSystem(options)` Factory from `@loop-engine/sdk`: ```ts createLoopSystem(options: { loops: LoopDefinition[] store?: LoopStore guards?: GuardRegistry signals?: boolean registry?: LoopRegistry }): Promise<{ engine: LoopEngine store: LoopStore eventBus: InMemoryEventBus signals?: SignalRegistry }> ``` - `loops` is required and becomes the in-memory set of definitions. - `store` defaults to `memoryStore()`. - `guards` defaults to `defaultRegistry` from `@loop-engine/guards`. - `signals: true` materializes a `SignalRegistry` for spec registration/validation; use the returned `eventBus` to observe `loop.*` and `loop.signal.received` events in this release. - `registry` is the optional **loop catalog** client (`LoopRegistry`); if `registry.list()` fails, startup falls back to `loops[]`. ## Pattern 1: zero-config ```ts // @no-typecheck import { createLoopSystem } from '@loop-engine/sdk' const { engine, eventBus } = await createLoopSystem({ loops: [definition] }) ``` ## Pattern 2: custom store (PostgreSQL adapter) ```ts // @no-typecheck import { createLoopSystem } from '@loop-engine/sdk' import { postgresStore } from '@loop-engine/adapter-postgres' import { Pool } from 'pg' const pool = new Pool({ connectionString: process.env.DATABASE_URL }) const { engine } = await createLoopSystem({ loops: [definition], store: postgresStore(pool) }) ``` ## Pattern 3: signals enabled `SignalRegistry` in `1.0.0-rc.0` is for spec registration/validation. React to live signal flow through the returned `eventBus` (for example, `loop.signal.received`). ```ts // @no-typecheck import { createLoopSystem } from '@loop-engine/sdk' const { signals, eventBus } = await createLoopSystem({ loops: [definition], signals: true }) // Optional: register or inspect specs on `signals` (instance of `SignalRegistry`). void signals?.list() eventBus.subscribe(async (event) => { if (event.type === "loop.signal.received") { console.log(event.signal, event.aggregateId) } }) ``` --- ## Starting Loops URL: https://bossloops.io /docs/running-loops/starting-loops Summary: Start loop instances with explicit actor attribution and aggregate identity using `engine.start`. Section: Running Loops ## `engine.start(options)` Signature (from runtime source): ```ts start(options: { loopId: string aggregateId: AggregateId actor: { type: "human" | "automation" | "ai-agent" | "system"; id: string } correlationId?: CorrelationId metadata?: Record }): Promise ``` ## Behavior - Throws if `loopId` is not registered. - Throws if an active instance already exists for the same `aggregateId` (source check: `status === "active"`). - Creates instance with: - `currentState = definition.initialState` - `status = "active"` - `startedAt` timestamp (also sets `updatedAt` to the same value) - generated correlation ID when omitted - Emits `loop.started`. ## Example ```ts import { aggregateId } from '@loop-engine/core' const instance = await engine.start({ loopId: 'scm.procurement', aggregateId: aggregateId('PO-001'), actor: { type: 'system', id: 'system:intake' }, metadata: { source: 'erp_sync' } }) ``` ## `LoopInstance` shape ```ts { loopId, aggregateId, currentState, status, // pending | active | completed | failed | cancelled | suspended startedAt, updatedAt, correlationId?, completedAt?, metadata? } ``` ## 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. --- ## Transitions URL: https://bossloops.io /docs/running-loops/transitions Summary: Transitions apply actor-attributed state changes and return explicit execution outcomes. Section: Running Loops ## `engine.transition(options)` Signature: ```ts transition(options: { aggregateId: AggregateId transitionId: TransitionId actor: { type: "human" | "automation" | "ai-agent" | "system"; id: string } evidence?: Evidence correlationId?: CorrelationId }): Promise ``` ## `TransitionResult` ```ts { status: "executed" | "guard_failed" | "rejected" | "pending_approval" fromState: StateId toState?: StateId guardFailures?: { guardId: GuardId; message: string; severity: "hard" | "soft" }[] rejectionReason?: string requiresApprovalFrom?: ActorId event?: TransitionExecutedEvent | GuardFailedEvent } ``` ## Handle all statuses ```ts const result = await engine.transition({ aggregateId, transitionId, actor, evidence }) switch (result.status) { case 'executed': console.log(result.toState) break case 'guard_failed': console.log(result.guardFailures) break case 'rejected': console.log(result.rejectionReason) break case 'pending_approval': console.log(result.requiresApprovalFrom) break } ``` ## 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. --- ## Event Subscriptions URL: https://bossloops.io /docs/running-loops/event-subscriptions Summary: Event subscriptions stream loop lifecycle events for audit, automation, and external integrations. Section: Running Loops ## EventBus subscription model `InMemoryEventBus` (`@loop-engine/events`) exposes: ```ts emit(event: LoopEvent): Promise subscribe(handler: (event: LoopEvent) => Promise): () => void ``` ## Event types - `loop.started` - `loop.completed` - `loop.cancelled` - `loop.failed` - `loop.transition.requested` - `loop.transition.executed` - `loop.transition.blocked` - `loop.guard.failed` - `loop.signal.received` ## Subscribe patterns ```ts eventBus.subscribe(async (event) => { console.log(event.type, event.aggregateId) }) ``` ```ts eventBus.subscribe(async (event) => { if (event.type === 'loop.completed') { console.log('Closed:', event.finalState, `${event.durationMs}ms`) } }) ``` ```ts const unsubscribe = eventBus.subscribe(async (event) => { console.log(event.type) }) unsubscribe() ``` ## Audit trail pattern Persist `loop.transition.executed` payloads and retain: - actor type/id - from/to state - evidence - timestamp That yields a complete decision history for compliance and incident review. ## External delivery adapters ### HTTP webhook bus ```ts import { httpEventBus } from '@loop-engine/adapter-http' const bus = httpEventBus({ webhookUrl: 'https://your-app.com/loop-events' }) ``` ### Kafka bus ```ts import { kafkaEventBus } from '@loop-engine/adapter-kafka' import { Kafka } from 'kafkajs' const bus = kafkaEventBus({ kafka: new Kafka({ brokers: ['localhost:9092'] }) as any, topic: 'loop-events' }) ``` --- ## Adapters URL: https://bossloops.io /docs/running-loops/adapters Summary: Adapters connect Boss Loops runtime contracts to concrete storage and delivery infrastructure. Section: Running Loops ## `LoopStore` interface All persistence adapters must implement: ```ts getInstance(aggregateId: AggregateId): Promise saveInstance(instance: LoopInstance): Promise getTransitionHistory(aggregateId: AggregateId): Promise saveTransitionRecord(record: TransitionRecord): Promise listOpenInstances(loopId: LoopId): Promise ``` ## `@loop-engine/adapter-memory` ```ts import { memoryStore } from '@loop-engine/adapter-memory' const store = memoryStore() ``` Use for tests, local development, browser demos. Data resets on process restart. ## `@loop-engine/adapter-postgres` `@loop-engine/adapter-postgres` ships at `0.2.0` while the rest of the `@loop-engine/*` family is at `1.0.0-rc.0`. The API shape is stable; the version reflects pre-1.0 commit to the migration surface rather than contract drift. Consumers can pin `@loop-engine/adapter-postgres@^0.2.0` alongside `1.0.0-rc.0` runtime packages. ```ts import { postgresStore, createSchema, createPool, runMigrations } from '@loop-engine/adapter-postgres' const pool = createPool({ connectionString: process.env.DATABASE_URL }) await runMigrations(pool) const store = postgresStore(pool) ``` Schema creates: - `loop_instances` - `aggregate_id`, `loop_id`, `current_state`, `status`, `started_at`, `updated_at`, `completed_at`, `correlation_id`, `metadata` - `loop_transitions` - `id`, `loop_id`, `aggregate_id`, `transition_id`, `from_state`, `to_state`, `actor`, `evidence`, `occurred_at`, `duration_ms` - `schema_migrations` - migration-tracking table managed by `runMigrations` Additional exports: `createSchema(pool)` (legacy DDL helper; prefer `runMigrations` for incremental upgrades), plus `Migration`, `MigrationRunResult`, `PoolOptions`, `PostgresStore` types and error classification utilities. Peer dependency: `pg@^8.0.0`. ## Event bus adapters ### `@loop-engine/adapter-kafka` - Provides `kafkaEventBus(...)` - Use for streaming and service-to-service fanout - Peer dependency: `kafkajs@^2.0.0` ### `@loop-engine/adapter-http` - Provides `httpEventBus(...)` - Use for webhooks and low-friction integrations - `subscribe()` is intentionally unsupported (emit-only adapter) ## Build a custom adapter Implement `LoopStore` exactly and pass it to: ```ts createLoopSystem({ loops, store: myStore }) ``` --- ## Package taxonomy URL: https://bossloops.io /docs/packages Summary: Select Boss Loops npm packages by runtime role — runtime core, Providers, Channels, and Integrations. Section: Packages Boss Loops installs in layers. The minimum floor is always `@loop-engine/sdk`. Additional packages are opt-in by capability. Public docs group connections as **[Providers](/docs/concepts/runtime-taxonomy#providers)**, **[Channels](/docs/concepts/runtime-taxonomy#channels)**, and **[Integrations](/docs/concepts/runtime-taxonomy#integrations)**. npm package names and developer types (`ActorAdapter`, `ToolAdapter`, `IntegrationAdapter` archetypes) sit underneath — see [IntegrationAdapter archetype](/docs/concepts/integration-adapter). → [Runtime connections index](/docs/integrations) · [Runtime Taxonomy](/docs/concepts/runtime-taxonomy) ## By runtime role | Runtime role | What you add | Required | Packages (current) | Planned | | --- | --- | --- | --- | --- | | **Runtime core** | Types, loop execution, guards, actors, events | always | `sdk`, `runtime`, `core`, `loop-definition`, `guards`, `actors`, `events`, `signals` | — | | **Provider** | Governed LLM actors and tool steps (intelligence) | one per model / use-case | `adapter-anthropic`, `adapter-openai`, `adapter-gemini`, `adapter-grok`, `adapter-perplexity`, `adapter-vercel-ai` | `adapter-ollama`, `adapter-cohere`, `adapter-mistral` | | **Channel** | Route `PENDING_HUMAN_APPROVAL` to human surfaces | when humans approve outside your app | `adapter-openclaw` | `adapter-slack`, `adapter-teams`, `adapter-discord`, `adapter-webhook` | | **Integration** | Persistence, event buses, operational backends | pick per environment | `adapter-memory`, `adapter-postgres`, `adapter-kafka`, `adapter-http`, `adapter-pagerduty`, `adapter-commerce-gateway` | `adapter-redis`, `adapter-sqlite`, `adapter-dynamodb` | | **Platform & tooling** | Catalog, metrics, devtools | optional | `observability`, `ui-devtools`, `registry-client` | `adapter-datadog`, `adapter-grafana` | | Public term | Developer primitives | | --- | --- | | Provider | `ActorAdapter` (LLM actors), `ToolAdapter` (e.g. Perplexity Sonar retrieval) | | Channel | EventBus routing to human surfaces (OpenClaw; Slack/Teams via Cloud connectors) | | Integration | `IntegrationAdapter` archetypes — `LoopStore`, `LoopRegistry`, `EventBus`, operational adapters | ## Minimum install ```bash npm install @loop-engine/sdk ``` Core primitives ship in `@loop-engine/sdk`. Standalone `@loop-engine/*` packages exist when you want explicit layer boundaries. ## Common install recipes ### Governed Claude tool calls (Provider + framework bridge) ```bash npm install @loop-engine/sdk @loop-engine/adapter-anthropic @loop-engine/adapter-vercel-ai ``` ### Human approval via messenger (Channel) ```bash npm install @loop-engine/sdk @loop-engine/adapter-openclaw @loop-engine/adapter-memory ``` ### Production loop with persistence + Provider + ops trigger (Integration + Provider) ```bash npm install @loop-engine/sdk @loop-engine/adapter-postgres @loop-engine/adapter-anthropic @loop-engine/adapter-pagerduty ``` ### Multi-model loop ```bash npm install @loop-engine/sdk @loop-engine/adapter-anthropic @loop-engine/adapter-openai @loop-engine/adapter-postgres ``` ### Observability stack ```bash npm install @loop-engine/sdk @loop-engine/observability @loop-engine/ui-devtools ``` ## Dependency direction **Runtime core** has no Boss Loops upstream dependencies. **Providers**, **Channels**, and **Integrations** depend on core. Add one package per capability — not every row in the table. **Today:** install OSS packages in your processes (local-first). **Direction:** optional self-host services (registry, audit store, replay, …) documented as roadmap-only on [Runtime Platform Direction](/docs/concepts/runtime-platform-direction). **Boss Loops Cloud** adds managed connectors — not full OSS parity. Better Data apps: **[docs.betterdata.co](https://docs.betterdata.co)**. Domain packs (`loops-healthcare`, `loops-fintech`, …) are under active development. [Open a discussion →](https://github.com/loopengine/loop-engine/discussions) --- ## @loop-engine/sdk URL: https://bossloops.io /docs/packages/sdk Summary: The @loop-engine/sdk package is the recommended entry point - it re-exports everything needed to define, run, and observe loops. Section: Packages `@loop-engine/sdk` is the fastest way to define loops, create a runtime, and wire guards, events, and optional signals. ## Install ```bash npm install @loop-engine/sdk ``` ## Re-export surface Source-verified exports include: - `LoopBuilder` - `createLoopSystem` (auto-wired aggregate; the runtime factory `createLoopEngine` is exported from `@loop-engine/runtime`) - `redactPiiEvidence` and `defaultRegistry` / `createGuardRegistry` from the guard stack (re-exported for convenience; see each package for full lists) - `InMemoryEventBus` and `SignalRegistry` (including when `createLoopSystem({ signals: true })` returns a `SignalRegistry` for spec metadata) - `computeMetrics` and `buildTimeline` - `localRegistry` and `httpRegistry` - core types: `LoopDefinition`, `LoopInstance`, `TransitionRecord`, and the signal/actor unions you need for authoring - `createAIActor` for provider-switched AI actor creation ## createAIActor `createAIActor()` gives a single SDK entrypoint for `anthropic`, `openai`, `gemini`, and `grok`. Switching providers is a config change only: ```ts import { createAIActor } from "@loop-engine/sdk" const actor = createAIActor({ provider: "gemini", model: "gemini-1.5-pro", apiKey: process.env.GOOGLE_AI_API_KEY ?? "" }) ``` If the underlying provider SDK is missing, it throws a targeted install command. Power users can still import individual adapter packages for custom client wiring. ## createLoopSystem ```ts createLoopSystem(options: { loops: LoopDefinition[] store?: LoopStore guards?: GuardRegistry signals?: boolean registry?: LoopRegistry }): Promise<{ engine: LoopEngine store: LoopStore signals?: SignalRegistry eventBus: InMemoryEventBus }> ``` Behavior from source: - `store` defaults to `memoryStore()` - `guards` defaults to `defaultRegistry` / `createGuardRegistry` patterns (see `@loop-engine/guards`) - `signals: true` materializes a `SignalRegistry` for spec registration/validation; runtime notification paths use the returned `eventBus` (for example, `loop.signal.received` events) rather than a `SignalRegistry#subscribe` API - `registry` (loop **catalog** client, type `LoopRegistry`) is additive; local `loops[]` win on ID conflicts - catalog load failures log a warning and fall back to local loops ```ts // @no-typecheck import { aggregateId, transitionId } from "@loop-engine/core" import { LoopBuilder, createLoopSystem } from "@loop-engine/sdk" const loop = LoopBuilder .create("expense.approval", "finance") .state("SUBMITTED") .state("APPROVED", { isTerminal: true }) .state("REJECTED", { isTerminal: true }) .initialState("SUBMITTED") .transition({ id: "approve", from: "SUBMITTED", to: "APPROVED", actors: ["human"] }) .transition({ id: "reject", from: "SUBMITTED", to: "REJECTED", actors: ["human"] }) .outcome({ id: "expense_approved", description: "Expense approved", valueUnit: "expense_approved", businessMetrics: [{ id: "m_expense_approved", label: "Expense approved", unit: "count" }] }) .build() const { engine, eventBus } = await createLoopSystem({ loops: [loop] }) eventBus.subscribe(async (event) => { if (event.type === "loop.transition.executed") { console.log(event.transitionId) } }) await engine.start({ loopId: "expense.approval", aggregateId: aggregateId("EXP-1"), actor: { type: "system", id: "system:intake" } }) await engine.transition({ aggregateId: aggregateId("EXP-1"), transitionId: transitionId("approve"), actor: { type: "human", id: "manager@acme.com" }, evidence: { approved: true } }) ``` ## Direct imports ```ts import { createLoopEngine, type LoopEngine } from "@loop-engine/runtime" import { LoopBuilder, createLoopSystem, InMemoryEventBus, type LoopDefinition } from "@loop-engine/sdk" ``` ## Package selection - Use `@loop-engine/sdk` for apps, scripts, and most services. - Use individual packages for tight bundle control or specialized integrations. --- ## @loop-engine/core URL: https://bossloops.io /docs/packages/core Summary: Shared TypeScript contracts and branded IDs define the Boss Loops boundary with zero runtime dependencies. Section: Packages `@loop-engine/core` defines the type contract used by every other `@loop-engine/*` package and ships no runtime implementations. ## Install ```bash npm install @loop-engine/core ``` ## Overview Core provides branded identifiers, actor and guard primitives, and canonical loop lifecycle interfaces. Runtime, DSL, adapters, and SDK layers all import these contracts. ## Branded IDs ```ts export type LoopId = string & { readonly __brand: "LoopId" } export type StateId = string & { readonly __brand: "StateId" } export type TransitionId = string & { readonly __brand: "TransitionId" } export type AggregateId = string & { readonly __brand: "AggregateId" } export type ActorId = string & { readonly __brand: "ActorId" } export type GuardId = string & { readonly __brand: "GuardId" } export type SignalId = string & { readonly __brand: "SignalId" } export type OutcomeId = string & { readonly __brand: "OutcomeId" } export type CorrelationId = string & { readonly __brand: "CorrelationId" } ``` Helper constructors cast incoming strings to branded IDs: ```ts import { aggregateId, transitionId } from "@loop-engine/core" const aggregate = aggregateId("EXP-2026-001") const transition = transitionId("approve") ``` ## Loop definition types ```ts export type ActorType = "human" | "automation" | "ai-agent" | "system" export type LoopStatus = | "pending" | "active" | "completed" | "failed" | "cancelled" | "suspended" export interface GuardSpec { id: GuardId description: string failureMessage: string severity: "hard" | "soft" evaluatedBy: "runtime" | "module" | "external" } export interface StateSpec { id: StateId description?: string isTerminal?: boolean isError?: boolean } export interface TransitionSpec { id: TransitionId from: StateId to: StateId allowedActors: ActorType[] guards?: GuardSpec[] sideEffects?: SideEffectSpec[] description?: string } export interface LoopDefinition { id: LoopId version: string description: string domain: string states: StateSpec[] initialState: StateId transitions: TransitionSpec[] outcome: OutcomeSpec participants?: string[] spawnableLoops?: LoopId[] metadata?: Record } ``` ## Runtime state types ```ts export interface ActorRef { id: ActorId type: ActorType displayName?: string metadata?: Record } export interface LoopInstance { loopId: LoopId aggregateId: AggregateId currentState: StateId status: LoopStatus startedAt: string updatedAt: string correlationId?: string completedAt?: string metadata?: Record } export interface TransitionRecord { aggregateId: AggregateId loopId: LoopId transitionId: TransitionId signal: SignalId fromState: StateId toState: StateId actor: ActorRef occurredAt: string evidence?: Record } ``` ## Signal and outcome types ```ts export interface OutcomeSpec { id: OutcomeId description: string valueUnit: string measurable: boolean businessMetrics?: BusinessMetric[] } export interface Signal { id: SignalId type: string subject: string confidence?: number observedAt: string payload: Record triggeredLoopId?: LoopId } ``` ## Design principles - Type-first boundaries keep packages interoperable without runtime coupling. - Zero runtime dependencies keep `core` safe for shared libraries and edge bundles. - Branded IDs reduce accidental string mixing across loop, actor, transition, and signal contexts. --- ## @loop-engine/runtime URL: https://bossloops.io /docs/packages/runtime Summary: The LoopEngine class starts loops, executes transitions, and stores state through the LoopStore interface. Section: Packages `@loop-engine/runtime` is the execution layer that mutates loop state and emits lifecycle events. ## Install ```bash npm install @loop-engine/runtime ``` ## Engine construction ```ts createLoopEngine(options: LoopEngineOptions): LoopEngine ``` `LoopEngineOptions`: The `registry` field is your **loop catalog** client (`LoopRegistry` in types) — definitions loaded from disk, HTTP, or Better Data, not the Commerce Gateway Registry. ```ts interface LoopEngineOptions { registry: LoopRegistry store: LoopStore eventBus?: EventBus guardEvaluator?: GuardEvaluator clock?: () => string } ``` ## Core methods ```ts start(options: StartOptions): Promise transition(options: TransitionOptions): Promise getState(aggregateId: AggregateId): Promise getHistory(aggregateId: AggregateId): Promise listOpen(loopId: string): Promise registerSideEffectHandler(sideEffectId: string, handler: SideEffectHandler): void ``` Transition result statuses from source: - `executed` - `guard_failed` - `rejected` - `pending_approval` ```ts const result = await engine.transition({ aggregateId, transitionId: transitionId("approve"), actor: { type: "human", id: "manager@acme.com" }, evidence: { approved: true } }) if (result.status === "guard_failed") { console.log(result.guardFailures) } ``` ## Store and bus interfaces ```ts interface LoopStore { getInstance(aggregateId: AggregateId): Promise saveInstance(instance: LoopInstance): Promise getTransitionHistory(aggregateId: AggregateId): Promise saveTransitionRecord(record: TransitionRecord): Promise listOpenInstances(loopId: LoopId): Promise } interface EventBus { emit(event: LoopEvent): Promise subscribe(handler: (event: LoopEvent) => Promise): () => void } ``` Use `@loop-engine/adapter-memory` in development and `@loop-engine/adapter-postgres` for a production persistence target. --- ## @loop-engine/loop-definition URL: https://bossloops.io /docs/packages/loop-definition Summary: LoopBuilder plus YAML and JSON parsing produce validated LoopDefinition objects from fluent or file-based authoring. Section: Packages `@loop-engine/loop-definition` turns fluent TypeScript or YAML/JSON documents into validated `LoopDefinition` contracts. Most users should import these APIs from `@loop-engine/sdk`, which re-exports the Loop Definition surface. Install `@loop-engine/loop-definition` directly when you need a tree-shakeable, narrow slice of the runtime. ## Install ```bash npm install @loop-engine/loop-definition ``` ## LoopBuilder ```ts LoopBuilder.create(id: string, domain: string): LoopBuilder ``` Builder methods implemented in source: - `.version(v: string): LoopBuilder` - `.description(d: string): LoopBuilder` - `.state(id: string, options?: { isTerminal?: boolean; isError?: boolean }): LoopBuilder` - `.initialState(id: string): LoopBuilder` - `.transition(spec: { id: string; from: string; to: string; actors: ActorType[]; guards?: Partial[] }): LoopBuilder` - `.outcome(spec: { id?: string; description?: string; valueUnit?: string; measurable?: boolean; businessMetrics?: ... }): LoopBuilder` - `.build(): LoopDefinition` `guard()`, `signal()`, and `actor()` are slated for `1.1.0+` as experimental builder methods and are not implemented in the current release. Guards are added today inside `.transition({ guards: [...] })`. ## Fluent example ```ts import { LoopBuilder } from "@loop-engine/loop-definition" const approval = LoopBuilder .create("expense.approval", "finance") .version("1.0.0") .description("Expense approval loop") .state("SUBMITTED") .state("UNDER_REVIEW") .state("APPROVED", { isTerminal: true }) .state("REJECTED", { isTerminal: true }) .initialState("SUBMITTED") .transition({ id: "start_review", from: "SUBMITTED", to: "UNDER_REVIEW", actors: ["automation"] }) .transition({ id: "approve", from: "UNDER_REVIEW", to: "APPROVED", actors: ["human"], guards: [ { id: "approval_obtained" as never, description: "Manager approval required", failureMessage: "Approval missing", severity: "hard", evaluatedBy: "runtime" } ] }) .outcome({ id: "expense_approved", description: "Expense approved", valueUnit: "expense_approved", measurable: true, businessMetrics: [ { id: "m_expense_approved", label: "Expense approved", unit: "count" } ] }) .build() ``` ## YAML parsing ```ts import { parseLoopYaml } from "@loop-engine/loop-definition" const definition = parseLoopYaml(yamlString) ``` Equivalent YAML for the same loop: ```yaml id: expense.approval version: 1.0.0 description: Expense approval loop domain: finance states: - id: SUBMITTED - id: UNDER_REVIEW - id: APPROVED isTerminal: true - id: REJECTED isTerminal: true initialState: SUBMITTED transitions: - id: start_review from: SUBMITTED to: UNDER_REVIEW allowedActors: [automation] - id: approve from: UNDER_REVIEW to: APPROVED allowedActors: [human] guards: - id: approval_obtained description: Manager approval required failureMessage: Approval missing severity: hard evaluatedBy: runtime outcome: id: expense_approved description: Expense approved valueUnit: expense_approved measurable: true ``` See `/docs/defining-loops/yaml-format` for the full format reference. ## Validation and serialization ```ts import { parseLoopJson, parseLoopYaml, serializeLoopJson, serializeLoopYaml, validateLoopDefinition } from "@loop-engine/loop-definition" ``` Validation signature: ```ts validateLoopDefinition(definition: LoopDefinition): ValidationResult interface ValidationResult { valid: boolean errors: ValidationError[] } interface ValidationError { code: string message: string path?: string } ``` Validation failure example: ```ts { valid: false, errors: [ { code: "INVALID_INITIAL_STATE", message: 'initialState "DRAFT" does not exist in states', path: "initialState" } ] } ``` --- ## @loop-engine/events URL: https://bossloops.io /docs/packages/events Summary: InMemoryEventBus and typed lifecycle event contracts provide pub-sub plumbing for loop runtime behavior. Section: Packages `@loop-engine/events` defines the event contract and ships an in-memory event bus implementation. ## Install ```bash npm install @loop-engine/events ``` ## Event catalog The exported `LOOP_EVENT_TYPES` constant enumerates the nine canonical lifecycle events: - `loop.started` - `loop.completed` - `loop.cancelled` - `loop.failed` - `loop.transition.requested` - `loop.transition.executed` - `loop.transition.blocked` - `loop.guard.failed` - `loop.signal.received` Every event extends: ```ts interface LoopEventBase { eventId: string type: string loopId: LoopId aggregateId: AggregateId occurredAt: string correlationId?: string causationId?: string } ``` ## InMemoryEventBus ```ts class InMemoryEventBus { emit(event: LoopEvent): Promise subscribe(handler: (event: LoopEvent) => Promise): () => void } ``` `subscribe()` returns an unsubscribe callback, and handler failures do not block other subscribers. ```ts import { InMemoryEventBus } from "@loop-engine/events" const bus = new InMemoryEventBus() const unsubscribe = bus.subscribe(async (event) => { if (event.type === "loop.transition.executed") { console.log(event.transitionId, event.actor.type) } }) unsubscribe() ``` ## Learning signal extraction ```ts extractLearningSignal( completed: LoopCompletedEvent, history: LoopTransitionExecutedEvent[], definition: LoopDefinitionLike, predicted?: Record ): LearningSignal ``` The helper derives `actual`, `predicted`, and numeric `delta` fields from the completed event, the executed-transition history, and the loop definition's declared business metrics. `predicted` keys not declared in `definition.outcome.businessMetrics` are dropped with a warning. --- ## @loop-engine/signals URL: https://bossloops.io /docs/packages/signals Summary: SignalRegistry is the current signal-spec surface; SignalEngine pattern detection lands in 1.1.0 as experimental. Section: Packages `@loop-engine/signals` ships `SignalRegistry` for declaring and validating signal specs. The pattern-detection engine (`SignalEngine`) is on the roadmap for `1.1.0+`. ## Install ```bash npm install @loop-engine/signals ``` ## SignalRegistry The current public surface is a registry that declares each signal's identity, optional Zod schema, and human-readable metadata. Runtime code uses it to look up and validate signal payloads. ```ts class SignalRegistry { register(spec: SignalSpec): void get(signalId: SignalId): SignalSpec | undefined validatePayload(signalId: SignalId, payload: unknown): { valid: boolean; error?: string } list(): SignalSpec[] } interface SignalSpec { signalId: SignalId name: string description?: string schema?: ZodType tags?: string[] } ``` ```ts import { z } from "zod" import { SignalRegistry } from "@loop-engine/signals" import { signalId } from "@loop-engine/core" const registry = new SignalRegistry() registry.register({ signalId: signalId("expense.submitted"), name: "Expense submitted", description: "A user has submitted an expense report for review.", schema: z.object({ amount: z.number().positive(), currency: z.string().length(3) }) }) const check = registry.validatePayload(signalId("expense.submitted"), { amount: 1200, currency: "USD" }) // => { valid: true } ``` ## SignalEngine (experimental, 1.1.0+) `SignalEngine`, `createSignalEngine()`, and the built-in rule factories listed below are slated for `1.1.0+` as experimental APIs and are **not** present in the current release. The shapes shown here are roadmap intent, not a contract — expect them to change before they ship. ```ts interface SignalEngine { registerRule(rule: SignalRule): void process(events: LoopEvent[]): Signal[] subscribe(handler: (signal: Signal) => void): () => void } createSignalEngine(): SignalEngine ``` Planned built-in rule factories: - `thresholdBreachRule(config: ThresholdRuleConfig): SignalRule` - `stateDwellRule(config: StateDwellRuleConfig): SignalRule` - `repeatedGuardFailureRule(config: RepeatedGuardFailureConfig): SignalRule` - `loopNotStartedRule(config: LoopNotStartedConfig): SignalRule` ## Detection model Signals are detections, not actors. Application code decides what to do with them — including whether to start or transition loops in response. --- ## @loop-engine/guards URL: https://bossloops.io /docs/packages/guards Summary: GuardRegistry and deterministic guard functions enforce policy checks before transitions execute. Section: Packages `@loop-engine/guards` provides deterministic policy checks that run inside transition execution. ## Install ```bash npm install @loop-engine/guards ``` ## Guard model Guards in this package are synchronous policy assertions wrapped as async functions. They do not call LLMs or network services. `GuardResult`: ```ts interface GuardResult { passed: boolean code?: string message?: string metadata?: Record } ``` ## Registry API ```ts class GuardRegistry { register(guardId: string, evaluator: GuardEvaluator): void get(guardId: string): GuardEvaluator | undefined registerBuiltIns(): void } ``` `registerBuiltIns()` populates the registry with every guard exported from `@loop-engine/guards` (see "Built-in guards" below). Call it once on a fresh registry, or use the pre-populated `defaultRegistry` constant. ```ts import { createGuardRegistry } from "@loop-engine/guards" import { guardId } from "@loop-engine/core" const registry = createGuardRegistry() registry.register(guardId("budget_available"), { async evaluate(context) { return { passed: context.evidence?.budget_ok === true, message: "Budget check failed" } } }) ``` ## Built-in guards `defaultRegistry` (and `GuardRegistry.registerBuiltIns()`) pre-registers: - `confidence-threshold` (`ConfidenceThresholdGuard`) - `human-only` (`HumanOnlyGuard`) - `evidence-required` (`EvidenceRequiredGuard`) - `cooldown` (`CooldownGuard`) ## Hard and soft behavior Hard/soft severity is defined on each `GuardSpec` in `@loop-engine/core`. Runtime blocks on hard failures and records soft failures under `_softGuardWarnings` in transition evidence. --- ## @loop-engine/actors URL: https://bossloops.io /docs/packages/actors Summary: Actor types, authorization checks, and evidence helpers keep transition attribution explicit and enforceable. Section: Packages `@loop-engine/actors` models all five actor categories and provides transition authorization + evidence utilities. ## Install ```bash npm install @loop-engine/actors ``` ## Actor types ```ts interface HumanActor extends ActorRef { type: "human" userId: string displayName: string roles?: string[] } interface AutomationActor extends ActorRef { type: "automation" serviceId: string version?: string } interface AIAgentActor extends ActorRef { type: "ai-agent" modelId: string provider: string confidence?: number promptHash?: string toolsUsed?: string[] } ``` ## Authorization ```ts canActorExecuteTransition( actor: Actor, transition: TransitionSpec, constraints?: AIActorConstraints ): { authorized: boolean; requiresApproval: boolean; reason?: string } ``` `canActorExecuteTransition()` validates `transition.allowedActors` and the optional `AIActorConstraints.requiresHumanApprovalFor` list for `ai-agent` actors. ```ts // @no-typecheck import { canActorExecuteTransition } from "@loop-engine/actors" const auth = canActorExecuteTransition(agentActor, transition) if (!auth.authorized) { console.log(auth.reason) } ``` ## Evidence building ```ts buildAIActorEvidence(params: { modelId: string provider: string reasoning: string confidence: number dataPoints?: Record rawResponse?: unknown prompt?: string }): Promise ``` Use `buildAIActorEvidence` when you have model metadata and need structured, attributable AI evidence to attach to a transition. ```ts import { buildAIActorEvidence } from "@loop-engine/actors" const evidence = await buildAIActorEvidence({ modelId: "gpt-4o", provider: "openai", reasoning: "Demand spike at DC-East", confidence: 0.82, dataPoints: { recommended_qty: 500 } }) ``` --- ## @loop-engine/adapter-anthropic URL: https://bossloops.io /docs/packages/adapter-anthropic Summary: AI actor adapter for Claude (Anthropic) — wire Claude as a governed actor in any operational loop. Section: Packages **Runtime role:** [Provider](/docs/concepts/runtime-taxonomy#providers) · Developer: `ActorAdapter` · [Runtime connections](/docs/integrations/anthropic) ## Overview `@loop-engine/adapter-anthropic` wraps the Anthropic Claude API as a Boss Loops AI actor. It handles prompt construction, response parsing, confidence extraction, and prompt hashing — returning an `AIAgentActor` and `AIAgentSubmission` ready for submission to the runtime. Guards run after the adapter returns. The adapter does not call `transition()` directly. ## Installation ```bash npm install @loop-engine/adapter-anthropic @anthropic-ai/sdk ``` ## Peer dependencies ```text @anthropic-ai/sdk ^0.39.0 ``` ## Basic usage ```typescript // @no-typecheck import Anthropic from '@anthropic-ai/sdk' import { createAnthropicActorAdapter } from '@loop-engine/adapter-anthropic' import { createLoopSystem } from '@loop-engine/sdk' const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY }) const adapter = createAnthropicActorAdapter(anthropic, { modelId: 'claude-opus-4-6', confidenceThreshold: 0.75, }) const loopSystem = await createLoopSystem({ loops: [] }) const aggregateId = 'procurement-1' // Get the AI actor's decision for the current loop state const { actor, decision } = await adapter.createSubmission({ loopId: 'procurement', loopName: 'SCM Procurement', currentState: 'pending_analysis', availableSignals: [ { signalId: 'submit_recommendation', name: 'Submit Recommendation', description: 'Submit a purchase order recommendation', allowedActors: ['ai-agent', 'automation'], }, ], instruction: 'Analyze the demand data and recommend whether to issue a purchase order.', evidence: { demandForecast: 0.89, currentStock: 42, reorderPoint: 50 }, }) // Submit to the runtime — guards evaluate after this point const result = await loopSystem.engine.transition({ aggregateId, transitionId: decision.transitionId, actor, evidence: decision, }) ``` ## Configuration reference | Option | Type | Default | Description | |--------|------|---------|-------------| | `modelId` | `string` | `claude-opus-4-6` | Anthropic model to use | | `maxTokens` | `number` | `1024` | Max tokens in response | | `systemPrompt` | `string` | — | Optional system prompt prepended to loop context | | `confidenceThreshold` | `number` | `0.7` | Minimum confidence required (0–1) | ## What the adapter produces The adapter returns an `AIAgentActor` with: - `type: "ai-agent"` - `provider: "anthropic"` - `modelId` — the model used - `confidence` — extracted from the model response - `promptHash` — SHA-256 of the prompt sent (for audit trail) ## Guard enforcement note The confidence guard runs at the runtime level — not inside the adapter. If you configure a `confidence-threshold` guard on the transition, the runtime will block the transition if the model's confidence falls below the threshold regardless of what the adapter returns. ```typescript // In your loop definition — this guard is structural, not prompt-based { guardId: 'confidence-threshold', severity: 'hard', evaluatedBy: 'runtime', parameters: { threshold: 0.75 }, } ``` ## Error handling The adapter throws `ActorDecisionError` with one of these codes: - `INVALID_SIGNAL` — model returned a signalId not in `availableSignals` - `INVALID_CONFIDENCE` — confidence value outside 0–1 range - `PARSE_FAILED` — model response could not be parsed as JSON - `API_ERROR` — Anthropic API returned an error ## Links - [View on npm](https://www.npmjs.com/package/@loop-engine/adapter-anthropic) - [Source](https://github.com/loopengine/loop-engine/tree/main/packages/adapter-anthropic) - Related: [AI as Actor concept](/docs/ai-and-automation/ai-as-actor), [@loop-engine/adapter-openai](/docs/packages/adapter-openai) --- ## @loop-engine/adapter-openai URL: https://bossloops.io /docs/packages/adapter-openai Summary: AI actor adapter for GPT-4o and o-series models — wire OpenAI as a governed actor in any operational loop. Section: Packages ## Overview `@loop-engine/adapter-openai` wraps the OpenAI API as a Boss Loops AI actor using `response_format: { type: "json_object" }` for structured output. Same governance model as `adapter-anthropic` — identical guard enforcement, same audit trail, drop-in pattern for multi-model loops. ## Installation ```bash npm install @loop-engine/adapter-openai openai ``` ## Peer dependencies ```text openai ^4.0.0 ``` ## Basic usage ```typescript // @no-typecheck import OpenAI from 'openai' import { createOpenAIActorAdapter } from '@loop-engine/adapter-openai' import { createLoopSystem } from '@loop-engine/sdk' const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY }) const adapter = createOpenAIActorAdapter(openai, { modelId: 'gpt-4o', confidenceThreshold: 0.75, }) const loopSystem = await createLoopSystem({ loops: [] }) const aggregateId = 'procurement-1' // Get the AI actor's decision for the current loop state const { actor, decision } = await adapter.createSubmission({ loopId: 'procurement', loopName: 'SCM Procurement', currentState: 'pending_analysis', availableSignals: [ { signalId: 'submit_recommendation', name: 'Submit Recommendation', description: 'Submit a purchase order recommendation', allowedActors: ['ai-agent', 'automation'], }, ], instruction: 'Analyze the demand data and recommend whether to issue a purchase order.', evidence: { demandForecast: 0.89, currentStock: 42, reorderPoint: 50 }, }) // Submit to the runtime — guards evaluate after this point const result = await loopSystem.engine.transition({ aggregateId, transitionId: decision.transitionId, actor, evidence: decision, }) ``` ## Configuration reference | Option | Type | Default | Description | |--------|------|---------|-------------| | `modelId` | `string` | `gpt-4o` | OpenAI model to use | | `maxTokens` | `number` | `1024` | Max tokens in response | | `systemPrompt` | `string` | — | Optional system prompt prepended to loop context | | `confidenceThreshold` | `number` | `0.7` | Minimum confidence required (0–1) | ## What the adapter produces The adapter returns an `AIAgentActor` with: - `type: "ai-agent"` - `provider: "openai"` - `modelId` — the model used - `confidence` — extracted from the model response - `promptHash` — SHA-256 of the prompt sent (for audit trail) ## Guard enforcement note The confidence guard runs at the runtime level — not inside the adapter. If you configure a `confidence-threshold` guard on the transition, the runtime will block the transition if the model's confidence falls below the threshold regardless of what the adapter returns. ```typescript // In your loop definition — this guard is structural, not prompt-based { guardId: 'confidence-threshold', severity: 'hard', evaluatedBy: 'runtime', parameters: { threshold: 0.75 }, } ``` ## Multi-model loops Both adapters return the same `AIAgentActor` shape. You can use Claude for one transition and GPT-4o for another in the same loop — the runtime treats them identically. The `provider` and `modelId` fields on the actor record distinguish them in the audit trail. ```typescript // @no-typecheck // Claude handles analysis, GPT-4o handles summarization — same loop const claudeActor = await claudeAdapter.createSubmission({ ... }) const openaiActor = await openaiAdapter.createSubmission({ ... }) ``` ## Error handling The adapter throws `ActorDecisionError` with one of these codes: - `INVALID_SIGNAL` — model returned a signalId not in `availableSignals` - `INVALID_CONFIDENCE` — confidence value outside 0–1 range - `PARSE_FAILED` — model response could not be parsed as JSON - `API_ERROR` — OpenAI API returned an error ## Links - [View on npm](https://www.npmjs.com/package/@loop-engine/adapter-openai) - [Source](https://github.com/loopengine/loop-engine/tree/main/packages/adapter-openai) - Related: [AI as Actor concept](/docs/ai-and-automation/ai-as-actor), [@loop-engine/adapter-anthropic](/docs/packages/adapter-anthropic) --- ## @loop-engine/adapter-gemini URL: https://bossloops.io /docs/packages/adapter-gemini Summary: AI actor adapter for Google Gemini — wire Gemini 1.5 Pro/Flash as a governed actor in any operational loop. Section: Packages ## Overview `@loop-engine/adapter-gemini` wraps Google's Gemini API as a Boss Loops AI actor using the `@google/generative-ai` SDK. Unlike OpenAI-compatible adapters, Gemini uses Google's native SDK and response shape. The adapter applies the same governance model as other Boss Loops AI adapters: guard enforcement in runtime and consistent actor audit fields. ## Installation ```bash npm install @loop-engine/adapter-gemini @google/generative-ai ``` ## Peer dependencies ```text @google/generative-ai ^0.21.0 ``` ## Basic usage ```typescript // @no-typecheck import { createGeminiActorAdapter } from '@loop-engine/adapter-gemini' const adapter = createGeminiActorAdapter(process.env.GOOGLE_AI_API_KEY!, { modelId: 'gemini-1.5-pro', confidenceThreshold: 0.75, }) const { actor, decision } = await adapter.createSubmission({ loopId: 'procurement', loopName: 'SCM Procurement', currentState: 'pending_analysis', availableSignals: [ { signalId: 'submit_recommendation', name: 'Submit Recommendation', allowedActors: ['ai-agent'], }, ], instruction: 'Analyze demand data and recommend a purchase order decision.', evidence: { demandForecast: 0.87, currentStock: 45 }, }) ``` ## Configuration reference | Option | Type | Default | Description | |--------|------|---------|-------------| | `modelId` | `string` | `gemini-1.5-pro` | Gemini model (`gemini-1.5-pro`, `gemini-1.5-flash`, `gemini-2.0-flash`) | | `maxOutputTokens` | `number` | `1024` | Max tokens in response | | `systemPrompt` | `string` | — | Prepended to the system instruction | | `confidenceThreshold` | `number` | `0.7` | Minimum confidence required (0-1) | ## What the adapter produces The adapter returns an `AIAgentActor` with: - `type: "ai-agent"` - `provider: "gemini"` - `modelId` — the model used - `confidence` — extracted from the model response - `promptHash` — SHA-256 of the prompt sent (for audit trail) ## Note on JSON parsing Gemini 1.5 occasionally wraps JSON responses in markdown code fences despite system instructions. The adapter strips these automatically before parsing. This cleanup becomes unnecessary in a later version that switches to `responseMimeType: "application/json"`. ## Guard enforcement note The confidence guard runs at the runtime level — not inside the adapter. If you configure a `confidence-threshold` guard on the transition, the runtime will block the transition if the model's confidence falls below the threshold regardless of what the adapter returns. ```typescript // In your loop definition — this guard is structural, not prompt-based { guardId: 'confidence-threshold', severity: 'hard', evaluatedBy: 'runtime', parameters: { threshold: 0.75 }, } ``` ## Error handling The adapter throws `ActorDecisionError` with one of these codes: - `INVALID_SIGNAL` — model returned a signalId not in `availableSignals` - `INVALID_CONFIDENCE` — confidence value outside 0–1 range - `PARSE_FAILED` — model response could not be parsed as JSON - `API_ERROR` — Gemini API returned an error (message prefixed with `[loop-engine/adapter-gemini]`) ## Multi-model loops All four adapters (`adapter-anthropic`, `adapter-openai`, `adapter-grok`, and `adapter-gemini`) return the same `AIAgentActor` shape. You can use different providers for different transitions in the same loop, while `provider` and `modelId` distinguish them in the audit trail. ## Links - [View on npm](https://www.npmjs.com/package/@loop-engine/adapter-gemini) - [Source](https://github.com/loopengine/loop-engine/tree/main/packages/adapter-gemini) - Related: [AI as Actor concept](/docs/ai-and-automation/ai-as-actor), [Google AI Studio](https://aistudio.google.com) --- ## @loop-engine/adapter-grok URL: https://bossloops.io /docs/packages/adapter-grok Summary: AI actor adapter for Grok (xAI) — wire Grok as a governed actor using xAI's OpenAI-compatible API. Section: Packages ## Overview `@loop-engine/adapter-grok` wraps xAI's Grok API as a Boss Loops AI actor. Grok uses an OpenAI-compatible API, and this adapter uses the `openai` npm package pointed at `https://api.x.ai/v1`. It follows the same governance model as `adapter-anthropic` and `adapter-openai`: identical guard enforcement and the same audit trail shape. ## Installation ```bash npm install @loop-engine/adapter-grok openai ``` ## Peer dependencies ```text openai ^4.0.0 ``` ## Basic usage ```typescript // @no-typecheck import OpenAI from 'openai' import { createGrokActorAdapter } from '@loop-engine/adapter-grok' // Grok uses the OpenAI SDK with xAI's base URL const grok = new OpenAI({ apiKey: process.env.XAI_API_KEY, baseURL: 'https://api.x.ai/v1', }) const adapter = createGrokActorAdapter(process.env.XAI_API_KEY!, { modelId: 'grok-3', confidenceThreshold: 0.75, }) const { actor, decision } = await adapter.createSubmission({ loopId: 'procurement', loopName: 'SCM Procurement', currentState: 'pending_analysis', availableSignals: [ { signalId: 'submit_recommendation', name: 'Submit Recommendation', allowedActors: ['ai-agent'], }, ], instruction: 'Analyze demand data and recommend a purchase order decision.', evidence: { demandForecast: 0.91, currentStock: 38 }, }) ``` ## Configuration reference | Option | Type | Default | Description | |--------|------|---------|-------------| | `modelId` | `string` | `grok-3` | Grok model to use (`grok-2`, `grok-2-mini`, `grok-3`, `grok-3-mini`) | | `maxTokens` | `number` | `1024` | Max tokens in response | | `systemPrompt` | `string` | — | Optional system prompt prepended to loop context | | `confidenceThreshold` | `number` | `0.7` | Minimum confidence required (0-1) | | `baseURL` | `string` | `https://api.x.ai/v1` | xAI API endpoint (override for testing) | ## What the adapter produces The adapter returns an `AIAgentActor` with: - `type: "ai-agent"` - `provider: "grok"` - `modelId` — the model used - `confidence` — extracted from the model response - `promptHash` — SHA-256 of the prompt sent (for audit trail) ## Guard enforcement note The confidence guard runs at the runtime level — not inside the adapter. If you configure a `confidence-threshold` guard on the transition, the runtime will block the transition if the model's confidence falls below the threshold regardless of what the adapter returns. ```typescript // In your loop definition — this guard is structural, not prompt-based { guardId: 'confidence-threshold', severity: 'hard', evaluatedBy: 'runtime', parameters: { threshold: 0.75 }, } ``` ## Error handling The adapter throws `ActorDecisionError` with one of these codes: - `INVALID_SIGNAL` — model returned a signalId not in `availableSignals` - `INVALID_CONFIDENCE` — confidence value outside 0–1 range - `PARSE_FAILED` — model response could not be parsed as JSON - `API_ERROR` — xAI API returned an error (message prefixed with `[loop-engine/adapter-grok]`) ## Multi-model loops All four adapters (`adapter-anthropic`, `adapter-openai`, `adapter-grok`, and `adapter-gemini`) return the same `AIAgentActor` shape. You can use different providers for different transitions in the same loop, while `provider` and `modelId` distinguish them in the audit trail. ## Links - [View on npm](https://www.npmjs.com/package/@loop-engine/adapter-grok) - [Source](https://github.com/loopengine/loop-engine/tree/main/packages/adapter-grok) - Related: [AI as Actor concept](/docs/ai-and-automation/ai-as-actor), [@loop-engine/adapter-openai](/docs/packages/adapter-openai) --- ## @loop-engine/adapter-perplexity URL: https://bossloops.io /docs/packages/adapter-perplexity Summary: Perplexity Sonar adapter — grounded retrieval with citations for Loop steps that need verifiable, real-time information. Section: Packages This package is staged for publication. Do not treat it as available on npm until its RC moves from **Draft** to **Locked**. The integration pattern in [Governed Incident Response with Perplexity and PagerDuty](/docs/integrations/perplexity-pagerduty) is safe to document independently. ## Overview `@loop-engine/adapter-perplexity` wraps the Perplexity Sonar chat API as a Boss Loops `ToolAdapter`. Sonar adds grounded web retrieval with cited sources. You use it for Loop steps that need real-time, verifiable information — regulatory lookups, compliance research, supplier or market news. It is not a general-purpose generation adapter; for broad LLM actor flows, use [Anthropic](/docs/packages/adapter-anthropic) or [OpenAI](/docs/packages/adapter-openai) actor adapters. ## Installation ```bash npm install @loop-engine/adapter-perplexity ``` ## Configuration ```typescript import { PerplexityAdapter } from "@loop-engine/adapter-perplexity"; const adapter = new PerplexityAdapter({ apiKey: process.env.PERPLEXITY_API_KEY, defaultModel: "sonar-pro", // sonar | sonar-pro | sonar-reasoning | sonar-reasoning-pro defaultSearchRecency: "month", // day | week | month timeout: 30_000, retries: 3, }); ``` ## Basic usage ```typescript import { PerplexityAdapter } from "@loop-engine/adapter-perplexity"; import type { AdapterInput } from "@loop-engine/core"; const adapter = new PerplexityAdapter({ apiKey: process.env.PERPLEXITY_API_KEY! }); const input: AdapterInput = { prompt: "What are the HIPAA breach notification requirements for PHI accessed outside approved hours?", model: "sonar-pro", metadata: { returnCitations: true, searchDomainFilter: ["hhs.gov", "nist.gov"], searchRecencyFilter: "month", }, }; const result = await adapter.invoke(input); console.log(result.text); // Sonar answer text console.log(result.citations); // { url, title, snippet }[] ``` ## Citation handling Citations are a first-class output on `SonarResult`. Each entry includes `url`, `title`, and `snippet` (for example derived from search metadata). ```typescript const result = await adapter.invoke({ prompt: "Summarize recent FDA guidance on AI/ML SaMD change control.", metadata: { returnCitations: true, searchRecencyFilter: "month" }, }); for (const citation of result.citations) { console.log(citation.url); console.log(citation.title); } ``` Always persist citations to your Loop audit trail. A Sonar result without citations is an unverifiable AI output — citations are the compliance evidence. ## Supported models | Model | Use case | Speed | | --- | --- | --- | | `sonar` | Fast retrieval, change detection | Fastest | | `sonar-pro` | Research, regulatory lookup | Fast | | `sonar-reasoning` | Multi-step analysis | Medium | | `sonar-reasoning-pro` | Policy classification, complex inference | Slower | ## guardEvidence `PerplexityAdapter` implements `guardEvidence` from `@loop-engine/core`, masking `pplx-*` API keys (and common secret field names) in payloads you log or export. You do not configure this — call `adapter.guardEvidence(payload)` before persisting raw request/response objects. ## Error handling | Error | Retryable | Description | | --- | --- | --- | | `PerplexityAdapterError` (400) | No | Bad prompt or parameter | | `PerplexityAdapterError` (401) | No | Invalid or missing API key | | `RateLimitError` (429) | Yes | Exponential backoff, up to `retries` (default 3) | | `PerplexityAdapterError` (500, 503) | Yes | Upstream or service errors — same backoff | | Timeout / network | Yes | Treated like a retryable failure when attempts remain | ## Environment variables ```text PERPLEXITY_API_KEY=pplx-... PERPLEXITY_BASE_URL=https://api.perplexity.ai # optional PERPLEXITY_DEFAULT_MODEL=sonar-pro # optional ``` ## Links - [Source](https://github.com/loopengine/loop-engine/tree/main/packages/adapter-perplexity) - Related: [Perplexity integration overview](/docs/integrations/perplexity), [PagerDuty](/docs/integrations/pagerduty), [Governed incident response guide](/docs/integrations/perplexity-pagerduty) --- ## @loop-engine/adapter-openclaw URL: https://bossloops.io /docs/packages/adapter-openclaw Summary: OpenClaw gateway EventBus adapter that forwards Boss Loops lifecycle events to OpenClaw-connected messaging channels. Section: Packages **Runtime role:** [Channel](/docs/concepts/runtime-taxonomy#channels) · Developer: `EventBus` routing · [Runtime connections](/docs/integrations/openclaw) ## Overview `@loop-engine/adapter-openclaw` wraps an internal event bus and forwards selected loop events to OpenClaw over its WebSocket gateway control plane. ## Install ```bash npm install @loop-engine/adapter-openclaw ws ``` ## Prerequisites - OpenClaw gateway reachable at `ws://127.0.0.1:18789` - Configured OpenClaw channel and target destination ## createLoopSystem usage `createLoopSystem` always wires an in-memory `InMemoryEventBus` today. To forward events to OpenClaw, wrap the bus returned from `createLoopSystem` with `OpenClawEventBus`: ```ts import { createLoopSystem } from '@loop-engine/sdk' import { OpenClawEventBus } from '@loop-engine/adapter-openclaw' import { LoopBuilder } from '@loop-engine/sdk' const loop = LoopBuilder .create('demo.forward', 'demo') .state('A', { isTerminal: true }) .initialState('A') .outcome({ id: 'done', description: 'done', valueUnit: 'done', businessMetrics: [{ id: 'm_done', label: 'Done', unit: 'count' }] }) .build() const { eventBus: inner } = await createLoopSystem({ loops: [loop] }) const forward = new OpenClawEventBus(inner, { channel: 'whatsapp', target: '+15551234567', events: ['loop.transition.executed', 'loop.completed'], approvalStates: ['PENDING_BUYER_APPROVAL'] }) void forward ``` ## OpenClawAdapterOptions ```ts interface OpenClawAdapterOptions { gatewayUrl?: string // default: ws://127.0.0.1:18789 channel: string target: string accountId?: string events?: string[] // default: ['loop.transition.executed','loop.completed','loop.guard.failed'] loopIds?: string[] // default: [] approvalStates?: string[] // default: [] inner?: EventBus // default: new InMemoryEventBus() autoReconnect?: boolean // default: true reconnectDelay?: number // default: 5000 } ``` ## Approval state detection The adapter marks a transition event as approval-required when `toState` matches `PENDING|APPROVAL` unless explicit `approvalStates` are configured. ## Lifecycle cleanup Call `disconnect()` during shutdown to stop reconnect timers and close the current socket cleanly. ## Related example See [OpenClaw Integration](/docs/examples/openclaw) for the end-to-end approval flow. --- ## @loop-engine/adapter-memory URL: https://bossloops.io /docs/packages/adapter-memory Summary: MemoryStore provides zero-config LoopStore persistence for local development, tests, and browser demos. Section: Packages `@loop-engine/adapter-memory` stores loop state and transition history in process memory. ## Install ```bash npm install @loop-engine/adapter-memory ``` ## Store API ```ts class MemoryStore implements LoopStore { getInstance(aggregateId: AggregateId): Promise saveInstance(instance: LoopInstance): Promise getTransitionHistory(aggregateId: AggregateId): Promise saveTransitionRecord(record: TransitionRecord): Promise listOpenInstances(loopId: LoopId): Promise } memoryStore(): LoopStore ``` ## SDK wiring ```ts // @no-typecheck import { memoryStore } from "@loop-engine/adapter-memory" import { createLoopSystem } from "@loop-engine/sdk" const { engine } = await createLoopSystem({ loops: [definition], store: memoryStore() }) ``` ## Runtime limits State resets when the process restarts. Use this adapter for development, test suites, and ephemeral demos. --- ## @loop-engine/adapter-postgres URL: https://bossloops.io /docs/packages/adapter-postgres Summary: createSchema provisions PostgreSQL tables and postgresStore provides a production LoopStore backed by node-postgres. Section: Packages **Runtime role:** [Integration](/docs/concepts/runtime-taxonomy#integrations) · Developer: `LoopStore` · [Runtime connections](/docs/integrations/postgres) `@loop-engine/adapter-postgres` provides schema setup and a concrete PostgreSQL `LoopStore` for runtime persistence. ## Install ```bash npm install @loop-engine/adapter-postgres pg ``` ## Schema bootstrap ```ts createSchema(pool: PgPoolLike): Promise ``` `createSchema()` creates: - `loop_instances` - `loop_transitions` ```ts import { Pool } from "pg" import { createSchema } from "@loop-engine/adapter-postgres" const pool = new Pool({ connectionString: process.env.DATABASE_URL }) await createSchema(pool) ``` ## Store factory ```ts postgresStore(pool: PgPoolLike): LoopStore ``` `postgresStore()` implements all `LoopStore` methods: - `getInstance` - `saveInstance` - `getTransitionHistory` - `saveTransitionRecord` - `listOpenInstances` ## Production notes - Use `pg` connection pooling. - Keep SSL, idle timeout, and max connection settings explicit in deployment config. - Run `createSchema()` during provisioning before serving runtime traffic. --- ## @loop-engine/adapter-kafka URL: https://bossloops.io /docs/packages/adapter-kafka Summary: kafkaEventBus bridges Boss Loops events to Kafka topics for distributed consumers and durable streaming. Section: Packages `@loop-engine/adapter-kafka` implements the runtime `EventBus` interface on top of a Kafka-like producer/consumer client. ## Install ```bash npm install @loop-engine/adapter-kafka kafkajs ``` ## Event bus factory ```ts kafkaEventBus(options: { kafka: KafkaLike topic: string groupId?: string }): EventBus ``` - `emit()` sends serialized `LoopEvent` payloads to `options.topic`. - `subscribe()` starts a consumer with `groupId` (default: `loopengine`) and forwards parsed messages to the handler. ```ts import { Kafka } from "kafkajs" import { kafkaEventBus } from "@loop-engine/adapter-kafka" const kafka = new Kafka({ brokers: ["localhost:9092"] }) // kafkajs `producer().send` return type is wider than the adapter's `KafkaLike` stub; emit path is compatible. const bus = kafkaEventBus({ kafka: kafka as any, topic: "loop-events", groupId: "loopengine-docs" }) ``` ## Topic strategy Use one topic per environment or domain boundary to keep replay and retention policies explicit. --- ## @loop-engine/adapter-http URL: https://bossloops.io /docs/packages/adapter-http Summary: httpEventBus forwards Boss Loops events to external webhooks with lightweight retry behavior. Section: Packages `@loop-engine/adapter-http` sends runtime events to an outbound webhook endpoint. ## Install ```bash npm install @loop-engine/adapter-http ``` ## Event bus factory ```ts httpEventBus(options: { webhookUrl: string headers?: Record retries?: number }): EventBus ``` - `emit()` posts JSON payloads to `webhookUrl`. - Retries default to `3`, with exponential backoff. - `subscribe()` throws because this adapter is push-only. ```ts import { httpEventBus } from "@loop-engine/adapter-http" const bus = httpEventBus({ webhookUrl: "https://hooks.example.com/loop-events", headers: { Authorization: "Bearer webhook-token" }, retries: 3 }) ``` ## Delivery model Use this adapter for outbound integrations (webhooks, automation tools, monitoring sinks) where event replay is handled outside Boss Loops. --- ## @loop-engine/adapter-commerce-gateway URL: https://bossloops.io /docs/packages/adapter-commerce-gateway Summary: LLM Commerce Gateway adapter that builds governed AI actors from live commerce data while keeping writes behind approval transitions. Section: Packages ## Install ```bash npm install @loop-engine/adapter-commerce-gateway ``` Install one LLM SDK based on provider choice: ```bash npm install @anthropic-ai/sdk # or npm install openai ``` ## Prerequisites - `COMMERCE_GATEWAY_URL` - `COMMERCE_GATEWAY_API_KEY` ## CommerceGatewayClient ```ts const client = new CommerceGatewayClient({ baseUrl: process.env.COMMERCE_GATEWAY_URL!, apiKey: process.env.COMMERCE_GATEWAY_API_KEY! }) ``` Methods: - `getInventory(sku)` - `getInventoryBatch(skus)` - `getDemandForecast(sku, horizon?)` - `getSuppliers(sku)` - `getCurrentPrice(sku)` - `getPriceHistory(sku, days)` - `createPurchaseOrder(order)` (write operation; post-approval only) - `recordLoopOutcome(outcome)` (optional endpoint support by deployment) ## buildProcurementActor ```ts const actor = buildProcurementActor({ gatewayClient: client, llmProvider: 'openai', apiKey: process.env.OPENAI_API_KEY!, confidenceThreshold: 0.8 }) ``` Returns `async (context) => Evidence`, where `context.instance.data.sku` drives Gateway queries and the actor returns evidence for a guarded transition. ## Evidence shape ```ts type ProcurementEvidence = { recommendedSku: string recommendedQty: number estimatedCost: number supplierId: string confidence: number rationale: string gatewayRequestIds: string[] modelUsed: string timestamp: string _confidence: number } ``` ## Read vs write boundary AI actor functions in this package call read endpoints only. Order creation stays in automation flows after a human approval transition passes guard checks. ## buildPricingActor Coming in v0.2: `buildPricingActor` currently throws a pending implementation error. ## Related example See [LLM Commerce Gateway Integration](/docs/examples/commerce-gateway) for the end-to-end procurement flow. --- ## @loop-engine/observability URL: https://bossloops.io /docs/packages/observability Summary: Metrics, timeline, and replay helpers turn loop history into audit and performance insights. Section: Packages `@loop-engine/observability` converts instance + transition data into metrics and replayable timelines. ## Install ```bash npm install @loop-engine/observability ``` ## Metrics ```ts interface LoopMetrics { loopId: LoopId period: { from: string; to: string } totalInstances: number openInstances: number closedInstances: number errorInstances: number avgDurationMs: number medianDurationMs: number p95DurationMs: number completionRate: number guardFailureRate: number aiActorRate: number humanActorRate: number avgTransitionCount: number } declare function computeMetrics( instances: LoopInstance[], history: TransitionRecord[], period: { from: string; to: string } ): LoopMetrics ``` The open/closed/error instance counters reflect `LoopStatus` groupings: `openInstances` counts `pending | active | suspended`, `closedInstances` counts `completed | cancelled`, and `errorInstances` counts `failed`. ```ts // @no-typecheck import { computeMetrics } from "@loop-engine/observability" const metrics = computeMetrics(instances, history, { from: "2026-03-01T00:00:00.000Z", to: "2026-03-31T23:59:59.999Z" }) ``` ## Timeline ```ts declare function buildTimeline( instance: LoopInstance, history: TransitionRecord[] ): LoopTimeline declare function getStateResidency( timeline: LoopTimeline ): StateResidency[] ``` `LoopTimeline` surfaces the ordered sequence of state entries and transitions for a single instance; `StateResidency` reports total duration spent in each state. Use them to power audit UIs and state-duration debugging. ## Replay ```ts declare function replayLoop( definition: LoopDefinition, history: TransitionRecord[] ): { valid: boolean; errors: string[] } ``` Replay verifies that recorded transitions are valid against the current loop definition. --- ## @loop-engine/registry-client URL: https://bossloops.io /docs/packages/registry-client Summary: Local and HTTP adapters for the loop catalog — load LoopDefinition objects, with Better Data support behind a subpath export. Section: Packages **Archetype:** [Registry](/docs/concepts/integration-adapter#registry-adapter) — implements `LoopRegistry`, slotted at `options.registry` on `LoopEngineOptions` / `createLoopSystem`. **Terminology:** In product docs we call this the **loop catalog** (versioned loop definitions for Boss Loops). The npm package remains `@loop-engine/registry-client` and TypeScript types still use the name `LoopRegistry`. That is **not** the [Commerce Gateway Registry](https://commercegateway.io/registry) (gateway discovery and verification). `@loop-engine/registry-client` provides local-first loop definition lookup with optional network adapters. ## Install ```bash npm install @loop-engine/registry-client ``` ## Local catalog ```ts // @no-typecheck import { localRegistry } from "@loop-engine/registry-client" const registry = localRegistry({ definitions: [customLoop], loopsDir: "./loops", watch: true }) ``` - `definitions` works in browser and Node. - `loopsDir` loads `.yaml`, `.yml`, and `.json` definitions in Node. - Browser usage with `loopsDir` logs a warning and ignores filesystem mode. ## HTTP catalog ```ts import { httpRegistry } from "@loop-engine/registry-client" const registry = httpRegistry({ baseUrl: "https://registry.example.com", headers: { Authorization: `Bearer ${token}` }, timeoutMs: 10_000, retries: 2 }) ``` Expected server contract: - `GET /loops` - `GET /loops?domain={domain}` - `GET /loops/{loopId}` - `GET /loops/{loopId}/{version}` - `POST /loops` - `DELETE /loops/{loopId}` ## Better Data adapter ```ts import { betterDataRegistry } from "@loop-engine/registry-client/betterdata" const registry = betterDataRegistry({ apiKey: process.env.BD_API_KEY!, orgId: "your-org-id", env: "production" }) ``` The Better Data adapter is intentionally excluded from the main package entrypoint. Import it from `@loop-engine/registry-client/betterdata`. ## `LoopRegistry` interface The runtime type is still named `LoopRegistry`: ```ts interface LoopRegistry { get(id: LoopId): Promise getVersion(id: LoopId, version: string): Promise list(options?: { domain?: string }): Promise has(id: LoopId): Promise register(definition: LoopDefinition, options?: { force?: boolean }): Promise remove(id: LoopId): Promise } ``` ## SDK integration `createLoopSystem({ loops, registry })` merges **catalog** results with local loops. Local `loops[]` definitions override matching catalog IDs, and catalog load failures fall back to local-only startup. ## Error classes The package exports three typed errors. Catch by class to distinguish missing definitions from conflicts and from network/IO failures. ```ts import { RegistryNotFoundError, RegistryConflictError, RegistryNetworkError } from "@loop-engine/registry-client" ``` ### RegistryNotFoundError Thrown by `get()` and `getVersion()` when a loop (or specific version) is not found. Exposes `loopId` and optional `version`. ### RegistryConflictError Thrown by `register()` when a loop with the same `loopId@version` already exists. Pass `{ force: true }` (development only) to overwrite. Exposes `loopId` and `version`. ### RegistryNetworkError Thrown by `httpRegistry` and the Better Data adapter on network or HTTP failures. Exposes `url`, optional `statusCode`, and the underlying `cause` when available. ```ts try { await registry.register(definition) } catch (error) { if (error instanceof RegistryConflictError) { console.warn(`Already registered: ${error.loopId}@${error.version}`) return } throw error } ``` --- ## @loop-engine/ui-devtools URL: https://bossloops.io /docs/packages/ui-devtools Summary: React devtools components for visualizing loop state, timelines, events, and local diagnostics. Section: Packages # @loop-engine/ui-devtools React components for local loop debugging and visualization. ## Install ```bash npm install @loop-engine/ui-devtools ``` Peer dependencies: - `react` (`^18 || ^19`) - `react-dom` (`^18 || ^19`) ## API reference Exported components: - `LoopStateBadge` - `ActorBadge` - `LoopTimeline` - `StateDiagram` - `EventStream` - `MetricsCard` - `DevtoolsPanel` Example: ```tsx import { DevtoolsPanel } from '@loop-engine/ui-devtools' export function Page() { return } ``` `DevtoolsPanel` returns `null` unless `NODE_ENV === "development"`. ## Related packages - Depends on core, events, observability --- ## All Packages URL: https://bossloops.io /docs/packages/all-packages Summary: Boss Loops publishes modular packages for authoring, runtime execution, events, guards, adapters, and tooling. Section: Packages # All packages The Boss Loops monorepo publishes the following packages: - [`@loop-engine/sdk`](/docs/packages/sdk) - [`@loop-engine/core`](/docs/packages/core) - [`@loop-engine/loop-definition`](/docs/packages/loop-definition) - [`@loop-engine/runtime`](/docs/packages/runtime) - [`@loop-engine/events`](/docs/packages/events) - [`@loop-engine/guards`](/docs/packages/guards) - [`@loop-engine/actors`](/docs/packages/actors) - [`@loop-engine/signals`](/docs/packages/signals) - [`@loop-engine/observability`](/docs/packages/observability) - [`@loop-engine/registry-client`](/docs/packages/registry-client) - [`@loop-engine/ui-devtools`](/docs/packages/ui-devtools) - [`@loop-engine/adapter-memory`](/docs/packages/adapter-memory) - [`@loop-engine/adapter-postgres`](/docs/packages/adapter-postgres) - [`@loop-engine/adapter-kafka`](/docs/packages/adapter-kafka) - [`@loop-engine/adapter-http`](/docs/packages/adapter-http) Most users should start with `@loop-engine/sdk`, then move to package-specific imports only when they need custom wiring. --- ## Loop catalog URL: https://bossloops.io /docs/catalog Summary: Discovery and trust layer for governed Boss Loops definitions — not related to the Commerce Gateway Registry. Section: Loop catalog The **Boss Loops catalog** at `registry.betterdata.co` is the discovery layer for governed loop definitions. We call it a **catalog** to distinguish it from registries in other products (for example, the [Commerce Gateway Registry](https://commercegateway.io/registry), which handles gateway discovery and domain verification under the Commerce Registry Protocol). Think of the loop catalog as **npm for reusable governed loops** — policy-gated operational definitions you can install and compose: same versioning model, same CLI ergonomics (planned), plus semantic search instead of keyword-only search. ## Trust model The catalog uses three trust tiers: 1. **Core** — Boss Loops maintained definitions. 2. **Verified Partner** — signed publisher identity with reviewed definitions. 3. **Community** — open publish surface, use-at-own-risk. ## Security properties Every published loop definition declares its actor types, guard registrations, transition surface, and external service calls in a machine-readable manifest. This is designed to prevent hidden behavior and make review/audit straightforward. ## CLI preview (coming soon) ```bash loop catalog search "hipaa approval" loop catalog install @betterdata/loops-healthcare loop catalog publish ``` The catalog is in private beta. Join the waitlist at loopengine.io/catalog. --- ## Examples URL: https://bossloops.io /docs/examples Summary: Runtime flow patterns — Provider, Loop + Guards, Channel, Integration, Evidence — not integration catalogs or chatbot demos. Section: Examples Examples teach **how governed operational decisions move through the runtime**, not how to wire a single adapter. Each pattern names **who** may transition state, **what evidence** is required, and **where humans** intervene — before any side effect reaches an operational system. → [Runtime Taxonomy](/docs/concepts/runtime-taxonomy) · [Architecture](/docs/getting-started/architecture) · [Boss Loops vs Workflow Engines](/docs/concepts/loop-engine-vs-workflow-engines) ## Canonical runtime flow Every priority pattern on this page follows the same spine: ```text Provider (intelligence) ↓ Loop + Guards (governance) ↓ Channel (human surface) ↓ Integration (operational system) ↓ Evidence (audit + learning) ``` **Providers** (intelligence systems) recommend or classify — they do not commit transitions alone. **Guards** enforce deterministic policy before state changes. **Channels** (human coordination) are where operators approve, reject, or escalate — not where CRM writes occur. **Integrations** (systems of record) persist state and execute side effects after approval. **Evidence** explains *why* each transition was allowed. | Layer | Role in examples | | --- | --- | | Provider | Score, draft, classify | | Channel | Slack, Teams, doc review | | Integration | Salesforce, Sheets apply, PagerDuty, MAP | They are **not** simple automation recipes, chatbot demos, or “agent magic” that skips policy. Boss Loops governs **whether** a transition commits; workflow engines and apps **execute** work after approval. ## What examples demonstrate | Principle | In practice | | --- | --- | | **Governance** | `human-only`, `confidence-threshold`, `evidence-required` guards block unauthorized transitions | | **Evidence** | Structured fields on every material transition — not reconstructed logs | | **Deterministic boundaries** | Guards are runtime checks, not prompt instructions | | **Human escalation** | Low confidence or high risk → `PENDING_*` states routed to a **Channel** | | **AI assistance** | Providers submit **recommendations** inside the loop — never self-approve | ## ABM and RevOps operational AI