Skip to content

Concepts

Lucidos is built from a small set of concepts that compose. Everything you do is recorded as an event; your files are artifacts; what you want is an intent and how to do it is knowhow; apps give that a UI and triggers make it happen automatically. A webhook lets an outside service set a trigger off. This page defines each one, straight from the canonical glossary and taxonomy.

Events and artifacts

The two ways Lucidos remembers: events are the immutable record of what happened (the source of truth), and artifacts are your durable, git-tracked files.

Event

A past-tense fact about something that happened in the workspace. Always past-tense, including transient ones. Two persistence flavors live side by side: persisted events (written to the events table, replayable, drive projections, match triggers) and transient events (broadcast over SSE only, never persisted, never reach projections or the trigger matcher). Concrete subtypes: thread lifecycle events (MessageReceived, ResponseGenerated, …), system events (notifications, preferences, …), and domain events. There is no command concept — anything that would look imperative is reframed as a request event (e.g. AppUiRefreshRequested, not RefreshAppUI); a subscriber chooses whether to act.

Artifact

A user-owned file under data/artifacts/. Git-tracked, never auto-deleted. Includes notes, imported API data, project folders, screenshots, generated images. The durable counterpart to ephemeral runtime state under .lucidos/. See also: system-knowhow/best-practices.md § artifacts/.

Because events are the authority, a few things always hold:

Key Invariants

  • Events are immutable
  • Git commits are consequences, not causes
  • No hidden state or silent decisions
  • Replay reconstructs truth, not creativity

Intent, knowhow, and scripts

Lucidos separates what you want (stable, in your words) from how to do it well (technical, evolving) from the code that does it.

Three Content Types

Type Stability Who maintains Example
Intent Stable — changes when the user's needs change User "Find relevant jobs, store them, notify me of new ones and deadlines"
Knowhow Evolves — refined every time Lucidos learns something new Lucidos "Use .product-card img selector, vendor CDN requires base64 conversion"
Script Changes when tools or APIs change Either download_images.py, validate_images.py

Intent vs Knowhow

The intent describes what the user wants — written in user terms, like what you'd tell a competent assistant. The knowhow describes how to do it well — technical details that Lucidos accumulates over time.

Test: "Would a non-technical person understand this file?" - Yes → it's an intent - No → it's knowhow

Example: A product-watch intent says "find relevant listings for me, store them, notify me if there are new ones or upcoming deadlines." The knowhow explains how vendor logos are extracted, how prices are normalized, what CORS workarounds are needed. When Lucidos discovers a new quirk, it updates the knowhow — the intent stays the same.

Apps and triggers

An app is a UI you open repeatedly; a trigger runs work on a schedule or in response to an event.

App

A user-installed mini-application with its own UI (HTML/CSS/JS) at data/apps/<id>/, plus optional knowhow / intents / scripts / triggers. Chat is not per-app: every conversation is a regular chat thread. When an app is open in the panel-overlay slot, its manifest.json and discovered context flow into the Lucidos Agent's prompt, so the agent can answer in-context. Quick edits to an app happen through the agent's file tools on the chat path; heavier edits spawn an app coding-agent thread. The app manifest is user-facing metadata shown in the UI; knowhow/ and intents/ are engine-facing context loaded into the LLM when the app is active. The app's interactive surface is the app UI — see entry. See also: system-knowhow/building-an-app.md, docs/taxonomy.md § Apps.

Trigger

A workspace configuration that fires either on a schedule (run.cron) or on one of its event subscriptions (on). The run is one of two shapes: - run.type: "intent" — spawns a trigger thread whose LLM is given run.intent (the user's voice — non-technical prose) as a user message and discovers the knowhow it needs via load_knowhow at fire time. No per-trigger knowhow allowlist. - run.type: "script" — executes the script at run.path directly, no LLM. The engine sets TRIGGER_EVENT_TYPE / TRIGGER_EVENT_PAYLOAD / TRIGGER_EVENT_ID / TRIGGER_EVENT_THREAD_ID env vars on event fires so the script can branch deterministically and deep-link any notification back to the originating event. Right when the work is a deterministic transformation that doesn't need LLM judgement.

Lifecycle (both shapes): defined by TriggerCreated; each firing emits TriggerStarted then TriggerCompleted. The trigger's panel row surfaces its last-run status (OK / failed — the most recent firing's outcome) beside the last-run time; there is no built-in run-history view. Deeper run detail comes from the trigger's own event stream — ask the Lucidos Agent ("what has this trigger been finding?") or build an app on the events. The row also shows the next runs: the next few fire times, merged across every cron expression. A cron that can never fire (0 0 9 31 2 *, Feb 31) is rejected at create and update, with an error naming the offending fields. A trigger stored before that guard existed keeps loading and wears a schedule error instead of the "No more runs" a spent one-shot earns. Both have no next run, but one never worked and the other finished its job. See also: system-knowhow/triggers.md, docs/taxonomy.md § Triggers.

Webhooks

A trigger can react to an event an outside service sent you. A webhook is where that event comes from, and it is the one surface a stranger can reach.

Webhook

An endpoint you point a third party at, so their service can tell Lucidos something happened. Each webhook emits exactly one domain event, which a trigger can then react to. Manage them at Settings > Webhooks, or with lucidos webhooks.

The event is pinned when you create the webhook, and no caller can change it. So an endpoint you gave GitHub can only ever fire the event you chose, whatever GitHub posts. To handle several kinds of message from one sender, fire one event and discriminate in the trigger's condition, which reads the sender's own fields.

Only you create one. There is no agent tool for it and no app can reach it, for the same reason an agent cannot grant itself a side-effect grant: a webhook opens a door, and an agent must not widen its own authority.

A delivery has to prove itself. An unsigned webhook carries a token, shown once when you create it, that the sender sends back as Authorization: Bearer <token>. A webhook can instead carry a signature configuration, which is how GitHub, Stripe and Slack authenticate: they sign the request body with a shared secret. Those senders attach no token, so a signed webhook gets none. That secret is a credential you save once and name here, never a copy kept beside the webhook.

A delivery becomes an event shaped {summary, headers, payload}. The sender's own body is under payload, so a trigger condition reads payload.action; the request headers you allow-listed are under headers, read as headers.X-GitHub-Event.

A sender will resend the same delivery, and by default that emits the event again. GitHub retries a slow response and offers a Redeliver button, Stripe retries for days. Leaving it that way is a real choice: every arrival stays on the event log, so you can see how often a sender repeats itself. Switch on delivery deduping when you would rather each delivery counted once.

Deliveries arrive on their own port, the hook socket, which answers webhook URLs and nothing else. That is what makes it the one surface you can safely expose to the public internet with tailscale funnel. See also: trigger, domain event, credential, delivery deduping, system-knowhow/lucidos-cli.md § lucidos webhooks.

The prompt-first model

The prompt is the primary interface: you describe what you want, and the system materializes it — data and presentation together, live, with no build-and-deploy gap.

Live co-creation

The principle at the heart of Lucidos: you and the Lucidos Agent shape the whole living system — data and presentation together — continuously and in place, with no build → deploy → observe gap. Because the Conversation and the Canvas are both always live and a gesture apart — side by side on desktop, a swipe apart on mobile — and the Canvas is backed by the real workspace (apps read live data through the SDK), you research, build, and iterate the whole thing inside Lucidos in one continuous motion, instead of building something, deploying it, and only then seeing how it behaves against real data. The back-and-forth between Conversation and Canvas — whichever way it's rendered — is the surface of live co-creation; the depth is that a single conversation reaches the entire stack.

Coming from other AI tools? The "skill" question

If you've used other AI assistants, you're probably looking for skills — the common name for a packaged unit of "here's how to do X." Lucidos deliberately has no single thing called a skill; it splits that idea into sharper, separately-useful pieces:

Where a "skill" elsewhere bundles… In Lucidos it's a…
Instructions the agent follows for a task Knowhow — how-to docs the Lucidos Agent loads on demand
A reusable interface for the capability App — a persistent UI under data/apps/<id>/
Helper code the instructions call Script
The whole capability shipped as one installable Plugin — a bundle of apps + knowhow + triggers + scripts
"Do this automatically / when X happens" Trigger

The closest single analog to a skill is knowhow — but with one defining difference: you don't invoke knowhow by name. The agent discovers the right knowhow semantically at runtime, matching your request against each file's description, and loads it when it's relevant. Adding a new recipe just works; there's no command to register and no menu to wire up.

Why you'll still see \"Skills\" in a few places

Some older material (release notes, design records) uses Skills for what is now split into apps and knowhow. The vocabulary moved on: the canonical terms are the ones in the table above.