{
  "schema": "leumas.docs.page/1",
  "id": "how-to:programmability",
  "slug": "how-to/programmability",
  "kind": "pages",
  "bucket": "how-to",
  "title": "Build-knowledge — the Leviathan programmability layer",
  "name": "the Leviathan programmability...",
  "eyebrow": "build knowledge",
  "chip": null,
  "summary": "- A Rule (db('rules')) wires { trigger: { type, props }, actions: [{ type, props }] } with a runtime: server rules arm in the API on boot (re-arm: POST /api/automation/rearm); client rules arm in the...",
  "keywords": [
    "programmability",
    "catalogs shipped hydration",
    "mental model",
    "leumas programmability",
    "how to programmability"
  ],
  "audience": "both",
  "funnel": {
    "product": null,
    "cta": null
  },
  "body": "# Build-knowledge — the Leviathan programmability layer\n\n> How Triggers · Actions · Chatbots · Functioncalls · Toolbanks · Providers · the Capability SDK fit\n> together, and how an agent extends each one. This is the build-knowledge entry for the layer that\n> makes Leviathan programmable from the frontend and Studio.\n\n## The mental model\n\n```\nTRIGGER (fires) ──rule──-> ACTION(s) (do) ← @leumas/triggers + @leumas/actions (+ rule engine)\nCHATBOT = persona + provider + voice + TOOLBANKS of FUNCTIONCALLS   ← @leumas/chatbots\nPROVIDER = the LLM brain (ollama/openai/claude/gemini/realtime/…)   ← @leumas/providers\nCAPABILITY = a live functioncall a PAGE registers at runtime         ← @leumas/capability-sdk\n```\n\n- A **Rule** (`db('rules')`) wires `{ trigger: { type, props }, actions: [{ type, props }] }` with a\n  `runtime`: `server` rules arm in the API on boot (re-arm: `POST /api/automation/rearm`); `client`\n  rules arm in the browser (capability-sdk `TriggerRuntime`). Server rules reach the browser through\n  the SSE stream `GET /api/automation/stream` as `directive` events.\n- A **Chatbot** (`db('chatbots')`) resolves its `provider` ('auto' → first available) and its tools\n  (toolbanks ∪ functioncalls ∪ the live client capabilities sent with the request) and runs the\n  tool loop (`@leumas/chatbots` `runProgrammedTurn`): server tools execute in the API; client tools\n  pause the turn (`clientToolCalls` + `turnId`) and resume with `toolResults`.\n- A **Functioncall** (`db('functioncalls')`) is a named tool `{ parameters: JSON-Schema, executor }`;\n  `executor.kind` = `adapter` (\"system.fn\") · `http` · `grid-cell` · `action` · `client`.\n- A **Toolbank** (`db('toolbanks')`) is a named group of functioncall names assigned to bots.\n\n## Where everything lives\n\n| Piece | Path | Contract |\n|---|---|---|\n| Doc schemas + validators | `shared/packages/schemas/src/programmability.js` | zod; `defineFunctioncall/…` + `validate*` |\n| Trigger engine | `shared/engines/triggers` | `defineTrigger({ id, metadata, arm(onFire, props) → disarm })`; seeds in `seeds/` |\n| Action engine + rules | `shared/engines/actions` | `defineAction({ id, metadata, inputs, run(props) })`; `createRuleEngine({ triggers, actions, onEvent })` |\n| Chatbots engine | `shared/engines/chatbots` | `runProgrammedTurn`, `bindExecutor`, `createTurnStore`; seeds (bots/banks/functioncalls) in `seeds/` |\n| Providers | `shared/engines/adapters/providers` | `defineProvider({ id, capabilities, available, adapter | complete, realtimeSession })`; registry `resolve(bot)` |\n| Capability SDK (frontend) | `shared/packages/capability-sdk` | `CapabilityProvider` + `useRegisterCapability(caps, { scopeId })` + `TriggerRuntime` + `createClientActionRegistry` + `useRealtimeVoice` + shared `bus` |\n| Leviathan widget | `shared/packages/leviathan` | picks up capabilities, executes `clientToolCalls`, voice modes |\n| Leviathan runtime | `shared/engines/leviathan` | `/leviathan/chat` (tool loop), `/leviathan/realtime/session` (SDP, key stays server-side) |\n| Studio admin | `products/leumas-studio/src/admin/{Chatbots,Triggers,ActionsManager,ToolbanksManager,FunctionCallsManager}.jsx` | FunctionCallsManager anatomy; demos in `admin/demos/` |\n| MCP exposure | `shared/engines/mcp/mcp-servers/leumas-automation` | thin HTTP adapters over `/api/automation/*` |\n| EXE distribution | `ops/tools/exe-builder` | builds Studio dist + packages the API |\n\n## How to add one of each (the agent recipes)\n\n- **New server trigger**: add `shared/engines/triggers/src/adapters/<id>.js` exporting a\n  `defineTrigger` factory with `arm(onFire, props)`, register it in `src/index.js`. It appears in\n  `GET /api/automation/triggers` automatically.\n- **New client trigger**: implement `{ id, arm(onFire, props) → disarm }` in\n  `capability-sdk/src/triggers/adapters.js` (`CLIENT_TRIGGER_ADAPTERS`), and add the matching manifest\n  to `shared/engines/triggers/src/manifests.js` so Studio lists it.\n- **New action**: same split — server: `actions/src/adapters/*` + register; client:\n  `capability-sdk/src/actions/registry.js` + `actions/src/manifests.js`.\n- **New provider**: folder under `shared/engines/adapters/providers/src/<id>/` exporting\n  `provider = defineProvider({...})` (lazy SDK imports, cheap `available()`), then add it to the\n  barrel `src/index.js`. `GET /api/providers` and Studio's Chatbots picker list it automatically.\n- **New page capability**: inside any React page under the `CapabilityProvider`:\n  `useRegisterCapability([{ name, description, parameters, call }], { scopeId, pageTitle })` —\n  registers on mount, unregisters on unmount. `simulateHear('<phrase>')` tests wakeword rules mic-free.\n- **New seeds**: add records to the owning engine's `seeds/` (data-only ESM) — hydration runs on API\n  boot via `hydrateCollection` (idempotent; `userModified: true` docs are never clobbered).\n\n## Catalogs shipped (hydration)\n\n`triggers_catalog` + `actions_catalog` hold the not-yet-implemented manifests (`implemented: false`,\ngreyed out in Studio) so the CRM shows the full roadmap surface. Live counts: see\n`GET /api/automation/triggers|actions`, `GET /api/providers`, and `/index/capabilities|chatbots|automations`\n(the registry entries that make functioncalls/toolbanks/bots/rules searchable and priceable in the CRM).\n",
  "source": {
    "path": "shared/services/knowledge/build-knowledge/programmability.md",
    "blobSha": "",
    "commit": "",
    "committedAt": "",
    "provenance": "no-git",
    "bytes": 5576,
    "hash": "41fa54533a590621b1ea2e59a7f7f766448406b3"
  },
  "urls": {
    "html": "/p/how-to/programmability",
    "json": "/docs/how-to/programmability.json",
    "md": "/docs/how-to/programmability.md"
  },
  "links": {
    "composes": [],
    "usedBy": [],
    "product": [],
    "howTo": [],
    "skills": []
  }
}
