This page defines the concepts that keep showing up across the module documentation.
Runtime Areas¶
democrai/core/: backend runtime, orchestration, storage, protocols, and internal servicesdemocrai/sdk/: public Python boundary for modules, engines, and extractorsclients/qtdesktop/: Qt desktop clientclients/webclient/: browser clientmodules/: extension modules loaded through the SDK boundaryengines/: installable AI engines loaded through the SDK boundaryextractors/: installable extractors loaded through the SDK boundary
The important consequence is: module code is not allowed to treat the desktop transport, web transport, storage backend, or runtime wiring as implementation details it can bypass.
Runtime Modes¶
The executable supports two public runtime modes:
desktopserver
Behavior:
python main.pydefaults todesktopdesktopmode uses IPC as the primary backend transportdesktopmode startsclients/qtdesktopby defaultservermode exposes WebSocket/HTTP and starts no client by defaultdesktop --httpkeeps IPC and also enables HTTP/WebSocket--client webclientasks the runner to executeyarn devin the web client root
The transport is not a module concern. Modules must expose actions, pages, tools, agents, and effects in a transport-agnostic way.
The runner also sets the runtime extension path environment variables when they are missing:
DEMOCRAI_MODULES_PATHDEMOCRAI_ENGINES_PATHDEMOCRAI_EXTRACTORS_PATH
Setup Mode¶
If config.yaml is missing, bootstrap enters setup mode.
In setup mode:
- minimal local providers are initialized
- full migrations and normal provider wiring are deferred
- the installation flow is expected to produce the real config
This matters when you write setup-sensitive code or document the first boot experience.
Module¶
A module is an extension package discovered from the runtime module paths.
Typical responsibilities:
- UI pages under
ui/* - action entrypoints under
actions/* - helper logic under
utils/actions/*andutils/ui/* - tools, agents, hooks, commands, and other registered assets
Render¶
A render entrypoint is a route/page function that returns a democrai.sdk.ui.Builder.
Typical render responsibilities:
- load YAML or create the component tree
- seed the initial UI state
- set component properties or bindings
- keep business logic light
Render should not turn into a giant action handler.
YAML-first UI¶
The documentation should privilege YAML-first UI authoring because it is easier to read, easier to translate, and easier to keep stable.
That does not mean Python-defined UI is unsupported.
Python-first UI still exists and is used in real modules such as demo, but the preferred documentation path is:
- define static structure in YAML
- load it from
democrai.sdk.ui.load(...)or the injected SDK object - use actions and effects for runtime mutations
Action¶
An action is a registered entrypoint decorated with @action(...).
UI calls actions by fully qualified name:
module_name.action_nameAction handlers usually:
- read
ctx - call the relevant SDK domains
- return effects through
sdk.effects.respond(...)
Effects¶
Effects are typed runtime instructions returned by actions.
Common examples:
sdk.effects.render()sdk.effects.navigate(...)sdk.effects.notify(...)sdk.effects.ui_property_update(...)sdk.effects.ui_collection_append/remove/replace(...)
Important: effects are not usually returned raw one by one. They are wrapped in sdk.effects.respond(...).
Example:
return sdk.effects.respond(
sdk.effects.notify(
"toast",
{"title": "Saved", "text": "Changes applied", "variant": "success"},
),
sdk.effects.navigate("/demo/anonim/index", render=True),
)Store and Binding¶
The UI can bind properties to client-side store state.
Main scopes:
- page store: route-local state
- global store: cross-page/shared client state
Use bindings, show_if, hide_if, and capability-based updates to avoid unnecessary full rerenders.
Surface¶
A surface is a UI target area.
Examples:
- the main content surface
- auxiliary surfaces such as drawers or modals
Some effects and UI messages target a specific surface rather than replacing the entire page tree.
Tool / Agent / Pipeline¶
Tool¶
A tool is a callable runtime capability registered with @tool(...).
Use it when you want a structured operation exposed to the agent runtime.
Agent¶
An agent is a runtime AI asset registered with @agent(...).
If the agent declares tools=[...], those tools belong to the agent contract.
Today that means:
- in the runtime-managed agent loop, the runtime injects and uses them directly
- in a custom handler, resolve the provider with
sdk.ai.get_provider_for_objective(...)and pass the registered tools explicitly when calling the provider
For normal module integration, call the agent with sdk.ai.run_agent(...).
If the action needs live visibility into what the agent is doing, pass listener= to sdk.ai.run_agent(...).
Pipeline¶
A pipeline is a deterministic orchestration asset, useful when you want an explicit runtime flow instead of open-ended agent behavior.
Core Models vs Module Models¶
This distinction must stay explicit in every guide:
sdk.models.<entity>is for core-managed entitiessdk.databaseis for module-owned tables
Examples:
sdk.models.users-> core users table and model-driven schemassdk.database.add(MyModuleEntity(...))-> module-specific persistence
Do not mix them.
Media¶
Dynamic files are not “just local files”.
The active media provider may be:
- local filesystem
- distributed/object-backed storage
That is why modules must use sdk.media for uploads, downloads, persistence, file references, and retrieval.
If a module bypasses sdk.media, it may work locally and then break as soon as the deployment switches media backend.
Model Access Scope¶
When using sdk.models, access scoping is handled by the model layer.
The module author does not manually inject ownership constraints like user_id or organization_id into every CRUD call unless the specific API explicitly requires it for another reason.
The model layer is responsible for:
- access-level prefilters
- allowed filters enforcement
- organization/user visibility constraints
This is one of the reasons modules should prefer sdk.models instead of custom direct data access for core entities.