# Daat Locus Architecture
> This is the public architecture document for users and contributors. It
> describes the current implementation boundaries. For stricter coding rules,
> agent-facing constraints, and contribution policy, see `AGENTS.md` and
> `CONTRIBUTING.md`.
Daat Locus is a long-running local, tool-driven agent runtime. The runtime owns
durable state, claims structured work, injects structured context, exposes
explicit tools, executes tool calls, and records the resulting evidence. The
model's natural-language output is recorded as explanation; external effects are
produced by explicit tools and completion actions.
Its architecture is organized around explicit tool calls, stateful capability
domains, structured runtime context, isolated Sessions, and auditable evidence
for memory, workflow, and sleep-time improvement.
## Design Goals
Daat Locus is built for work that improves through repeated practice:
maintaining projects over time, handling recurring task classes, remembering
practical experience, and turning that experience into auditable runtime assets.
The main design goals are:
1. **Tools produce external effects**
Natural-language output provides explanations and records. Event completion,
file edits, terminal commands, browser interaction, code edits, plan updates,
primitive binding, and other effects happen through explicit tools.
2. **State is explicit**
The runtime stores events, pending work, app state, memory, plans, workflow
bindings, session metadata, dashboard state, and delivery state. Code stores
or renders mechanical state directly so model attention stays on semantic
judgment.
3. **Capabilities stay in their domains**
Browser, Terminal, and Coding are separate stateful capability domains. Their
tools are namespaced and operate on explicit identifiers. The model calls
each tool directly through its domain namespace.
4. **Mechanical work belongs to code**
Queue enumeration, deduplication, freshness checks, delivery bookkeeping,
schema validation, and evidence recording belong in code. The model spends
attention on semantic judgment.
5. **Experience becomes auditable assets**
Memory keeps continuity, but reusable procedures live in SOP primitive specs.
Runtime errors and workflow run evidence feed separate sleep-time improvement
paths.
6. **Sessions are isolated runtimes**
The public daemon is a Manager. Each Session process owns one runtime and is
reached only through private local IPC from the Manager.
## Runtime Loop
The current high-level flow is:
1. A client or transport sends input to the Manager daemon.
2. The Manager chooses or creates the target Session and routes the input over
private local IPC.
3. The Session registers an event or app notice and enqueues `PendingWork`.
4. The runtime claims one work item.
5. Newly claimed input and primitive routing are injected once as AfterClaim
Context.
6. Before every model turn, current execution state is injected as PreTurn
Context.
7. The model makes semantic judgments and calls explicit tools.
8. Tools mutate state, apps, files, processes, events, plans, or workflow
bindings.
9. Claimed work finishes through the appropriate completion tool.
10. The runtime records evidence needed by dashboard history, memory, workflow
runs, and sleep-time improvement.
```mermaid
flowchart LR
Client[WebUI / TUI / CLI / Telegram]
Manager[Manager daemon<br/>public API and routing]
Session[Session process<br/>one runtime]
Pending[PendingWork]
After[AfterClaim Context]
Pre[PreTurn Context]
Model[Model judgment]
Tools[Explicit tools]
State[Events / apps / plan / memory / workflows]
Sleep[Sleep improvement]
Client --> Manager --> Session --> Pending --> After --> Pre --> Model --> Tools
Tools --> State
State --> Pre
Tools --> Pending
State --> Sleep
Sleep --> State
```
The important invariant is that tool results and persisted state are first-class
sources of truth alongside model judgment. They decide whether an action
actually happened.
## Runtime Context Model
Runtime context is split by lifetime in the current implementation.
### AfterClaim Context
AfterClaim Context is injected after work is claimed. It is one-shot context for
that claimed work:
- claimed events and claimed app notices;
- source metadata needed to handle them;
- workflow primitive routing: the full primitive id vocabulary plus expanded
summaries for top relevant primitives.
It is one-shot claimed-work context. Event input lives here as part of the
claimed input record.
### PreTurn Context
PreTurn Context is injected before each model turn. It contains current
execution state that can change after tools run:
- sensory information such as current time and machine status;
- project instruction context when a coding project is in scope;
- the current plan;
- the currently bound primitive or temporary primitive composition.
App state is read on demand through the generated `appid__get_state` tool for
Browser, Terminal, or Coding.
### Capability Docs Are Separate
Keep app usage docs, app how-to-use docs, project instructions, event completion
rules, and workflow routing as separate instruction layers with their own
responsibilities.
## Core Runtime Objects
### Event
An `Event` is a structured external fact already received by the system. Current
Session code stores Telegram input and terminal/client user input as event
payloads. It represents work that needs semantic judgment and an explicit
disposition. Chat windows, selected conversations, and app cursors belong to
client or app state surfaces.
A claimed event ends through `finish_and_send`. `resolved` and `failed` require
a `reply_message` with content; `dismissed` is the silent completion path. Reply
delivery and event resolution happen through explicit completion tools.
### PendingWork
`PendingWork` is the scheduling unit for the next runtime turn. Current variants
are event work and app notice work. Events have priority over app notices.
The queue remains a scheduling layer that claims, releases, consumes, and
requeues work. Semantic judgment remains with the model and explicit tools.
### Plan
`Plan` is the short-term execution plan for the current task. Durable backlogs
and knowledge bases live in separate storage. An active plan with steps must have
exactly one `in_progress` step; completed plans are cleared after completion.
### Memory
Memory provides continuity and long-term recall. Runtime state and tool results
hold immediate facts for events, delivery, app state, and workflow binding.
### Workflow
`Workflow` is the binding and evolution layer for reusable SOP primitives.
Daat Locus separates three layers:
- `PrimitiveSpec`: a persisted primitive specification asset.
- `WorkflowBinding`: the current task's binding to one primitive or a temporary
composition of existing primitives.
- `PrimitiveRunRecord`: execution evidence recorded by runtime code at work
completion boundaries.
A temporary composition remains runtime state. Persisted primitive specs change
through explicit primitive editing or workflow evolution paths.
Builtin primitives live in repository `workflows/*.md` and are compiled by
`build.rs`. Evolvable workspace primitives live under
`~/daat-locus-workspace/workflows`.
## App Model
An `App` is a stateful capability domain with its own tools, state, lifecycle,
usage guidance, and operation guidance.
The current built-in Apps are:
- **Browser**: persistent page sessions, loading, semantic page snapshots,
element refs, navigation, and page interaction.
- **Terminal**: persistent command sessions, unread output, stdin continuation,
process lifecycle, and working directories.
- **Coding**: project-aware source operations backed by scope-engine, including
semantic search, hash-anchored reads and edits, and propagation review.
### App Tool Exposure
An App is a direct namespaced tool domain. Runtime tool construction exposes
every installed App's valid tool specs directly under the App namespace, plus a
generated state tool:
```text
browser__get_state
browser__browser_open_page
terminal__get_state
terminal__terminal_exec
coding__get_state
coding__open_project
coding__search_code
```
The App still owns its state and lifecycle internally. Tool ownership is visible
in the tool name, and operations use explicit identifiers and visible runtime
selection inputs.
### State, Usage, And How-To-Use
Every App exposes three separate layers:
- `state`: current structured facts, returned by `appid__get_state` and rendered
in app-status surfaces;
- `usage`: when the capability domain is worth using;
- `how_to_use`: how to operate the App's tools safely.
Keep these layers separate: state reports current facts, usage describes
applicability, and how-to-use text explains safe operation.
### Static File Tools Are Runtime Tools
`read_file` and `edit_file` are ordinary runtime tools. They handle explicit
path/range reads and hash-anchored edits for Markdown, TOML, YAML, JSON, shell
scripts, generated files, and paths outside SCOPE.
When a Coding project is open, source files owned by SCOPE require
`coding__edit_code` so parse validation and propagation review can run.
### Telegram Is A Transport
Telegram is a transport and event source. The Manager polls or receives
Telegram input, resolves access and default-session mapping, routes normal
messages to a Session, drains Session outboxes, and records delivery results.
The model receives the structured facts and event id from runtime, judges the
event, and completes it with `finish_and_send`.
### Workspace Apps
Third-party workspace Apps are source-first assets under:
```text
~/daat-locus-workspace/apps/<app_id_snake_case>/
app.toml
runtime/app.lua
prompt/usage.md
prompt/how_to_use.md
```
The host loads one Lua 5.4 module from `runtime/app.lua` through `mlua`. The
current Lua surface uses one module instance with hooks such as `config(ctx)`,
`init(ctx, state)`, `render_state(ctx, state)`, `list_tools(ctx, state)`,
`call_tool(ctx, state, name, args)`, and `poll_notices(ctx, state)`.
Workspace app prompts describe the App capability. Reusable task SOPs live in
workflow primitive specs.
## Tool And Action Boundaries
### Prefer Explicit Identifiers
Tool calls should bind to concrete identifiers or freshness guards:
- event completion binds to the claimed event;
- Browser calls bind to `page_id` and, for interactions, `element_ref`;
- Terminal continuation binds to `session_id`;
- Coding reads and edits bind to `path + line#hash`;
- session APIs bind to opaque `session_id` values;
- primitive binding uses primitive ids or a temporary composition id.
Explicit identifiers make stale-state mistakes auditable.
### Coding And File Editing Boundary
Coding uses one visible source-location vocabulary: `path + line#hash`.
- `coding__search_code` returns matched source lines with path-scoped anchors.
- `coding__read_code` reads a path plus anchor in `around` or `full` mode.
- `coding__edit_code` applies structured hash-anchored edits and returns
propagation results.
- `coding__next_review` exposes pending impact review events after edits.
Explicit path/range reads belong to `read_file`; `read_code` handles path plus
anchor. Configuration, generated, and outside-SCOPE edits belong to `edit_file`;
SCOPE source edits belong to `edit_code`.
### Model-Facing Schema Dialect
Runtime tools, App tools, and structured model outputs use a conservative JSON
Schema dialect. Schemas are root objects, object properties are required and
closed with `additionalProperties: false`, optional values are nullable required
fields, and correctness comes from generated and validated schemas at the
provider boundary.
The normal Rust entry point is `#[model_schema]` plus `model_schema_for::<T>()`.
Dynamic workspace app schemas are validated when loaded.
## Multi-Session Architecture
Daat Locus is a client-server multi-session system.
```text
WebUI / TUI / CLI / Telegram control
-> Manager daemon public API
-> Session process over private local IPC
```
Clients connect only to the Manager daemon. Session processes are private
runtime workers; the Manager is the public client target.
### Manager Responsibilities
The Manager owns:
- public HTTP/WebSocket endpoints and embedded WebUI serving;
- daemon authentication and token validation;
- session registry and lifecycle;
- spawning, stopping, restarting, deleting, and health-checking sessions;
- routing `/send`, dashboard requests, command requests, and Telegram input;
- Telegram ACL, default-session mapping, outbox delivery, and Telegram-only
session control commands;
- dashboard snapshot/history/stream proxying from target Sessions.
The Manager stays at public API, auth, routing, lifecycle, and compact status
summary boundaries. Runtime `Context` creation, model loop execution, and
per-session memory/event/app/plan ownership belong to Session processes.
### Session Responsibilities
Each Session process owns exactly one runtime:
- one `Context`;
- one `EventStore` and `PendingWorkQueue`;
- one conversation and memory state;
- one `Plan`;
- one `AppManager` and app instance set;
- one dashboard state stream;
- one model loop.
A Session exposes private IPC handlers to the Manager. Public HTTP serving,
global session registry loading, multi-session management, and Telegram polling
belong to the Manager.
### Session Registry And Code Mode
The Manager persists session metadata, including an opaque `session_id`, scope,
process status, IPC metadata, optional project directory, title, and timestamps.
Public session lists expose only user-facing identity, title, scope, and basic
summary fields; IPC tokens and process internals remain Manager-private.
`daat-locus run` works with general sessions. `daat-locus code <project-dir>`
canonicalizes the project directory and shows only project-scoped sessions for
that path. Creating a code session creates a new opaque `session_id`; a project
directory can have multiple code sessions.
### Manager-Session IPC
Manager and Session communicate with `interprocess` Tokio local sockets. The
protocol uses framed JSON envelopes with protocol version, request id, session
id, IPC token, and request body. Requests include status, user input submission,
dashboard snapshot/history/stream, dashboard commands/actions, Telegram event
queueing, Telegram outbox draining, delivery recording, requeueing, and
shutdown.
This IPC is a local implementation boundary for Manager/Session coordination.
### Telegram Routing
Approved Telegram chats are mapped by the Manager to a default Session. If a
chat lacks a valid mapping, the first ordinary message creates a new general
Session and stores the mapping. Telegram-only session commands such as
`/session_list`, `/session_new`, `/session_attach`, and `/session_delete` are
handled by the Manager before Session event registration. Ordinary chat messages
are routed to Session event stores as runtime events.
## Dashboard And Interactive Clients
`DashboardState` is the shared cross-client session/runtime snapshot produced by
the Session and consumed by TUI, WebUI, and other clients. It includes activity
cells, live activity, runtime status, plan summaries, app status output, skills,
Telegram access requests, token usage, and context/optimization summaries.
TUI local interaction state belongs to `TuiViewState`: command input, slash
completion, panels, scroll offsets, local feedback, expanded display choices,
history paging state, and render caches. Multiple TUI clients can show the same
`DashboardState` with different `TuiViewState` values.
The TUI architecture is:
```text
DashboardState + TuiViewState
-> input_controller reducer
-> optional DashboardCommandRunner effect
-> FrameRequester schedule
-> pure full-frame render
```
`FrameRequester` is the draw scheduler. The TUI uses full-frame renders,
coalesced draw requests, and animation scheduling through `FrameRequester`.
Slash commands are top-level product entry points. Commands such as `/skills`,
`/telegram`, `/debug`, `/app-status`, and `/status` should open panels or one
obvious action. Large typed CLI trees stay in internal, remote-control, or test
surfaces.
WebUI session rendering reads structured `DashboardState`, `WebActivityItem`,
and `ActivityCell` data directly while mirroring the TUI session activity
hierarchy.
## Sleep And Self-Improvement
Sleep is evidence-driven improvement with two independent paths:
- **Runtime Error Correction** consumes code-detected runtime/protocol error
cases and produces small global runtime contract corrections.
- **Workflow Improvement** consumes workflow-bound primitive run records and
patches or merges workspace primitive specs.
Keep these paths separate: runtime protocol errors feed contract corrections;
workflow quality evidence feeds workflow primitive patch/merge decisions.
## Persistence Boundaries
Protected runtime state includes configuration, daemon auth tokens, Telegram
ACL/default-session mapping, session registry, events, pending work, runtime
conversation and memory, plans, dashboard history, app-local state, and sleep
artifacts.
Editable workspace assets include project files, workspace app source packages,
and workspace primitive specs. Builtin primitive specs are repository assets
compiled into the binary and are read-only at runtime.
This boundary separates runtime-owned state from project-file edits while still
allowing agent-maintained workspace assets to evolve through controlled
processes.
## Current Architecture Shape
### Work Queue Runtime
Daat Locus can expose chat-like interfaces, while its core is pending work,
structured context, explicit tools, persisted state, and evidence.
### Domain-Owned Tools
Tools are exposed by domain ownership. App tool names show their owner namespace,
and stateful domains expose `get_state` with explicit identifiers.
### Source-First Workspace Apps
Workspace Apps are source-first, local, auditable capability domains. Workflow
primitive specs carry self-optimizing task procedures.
### Evidence-Driven Improvement
Self-improvement requires evidence, an ownership layer, persistent artifacts,
and auditable changes.
## Summary
Daat Locus can be summarized by a few current invariants:
- external effects flow through explicit tools and completion actions;
- Apps are stateful capability domains with direct namespaced tools;
- Events and PendingWork are separate from Apps;
- runtime context is split into AfterClaim and PreTurn layers;
- Manager is the only public server, and Sessions are private runtime workers;
- workflows are reusable SOP primitives and runtime compositions;
- sleep consumes explicit evidence through separate runtime-error and workflow
improvement paths.
The goal is a local agent runtime that can act, verify, remember, and improve
while remaining auditable and shaped by human judgment.