Architecture
Data & Control Flow
How a message, a tool call, and a long-running agent run move through CoreLayer.
This page traces the three flows that matter: a chat turn, a tool call inside that turn, and a dispatched run that outlives the turn.
Chat turn
1. User sends a message from the chat panel
2. Frontend → Tauri IPC → daemon HTTP
POST /api/conversations/:id/messages/stream (or POST /api/chat/stream)
3. Agent runtime assembles context:
- conversation history (per conversation, branch-aware)
- long-term memory retrieved from the memory runtime
- the core tool set, plus any on-demand tools the router selects
4. Model Gateway resolves the active provider/model and opens a streaming call
(Vercel AI SDK v6; step control happens inside prepareStep)
5. Each step can:
- emit text → streamed to the UI
- request a tool call → step 3 of the tool-call flow below
6. Loop breakers and step budget decide whether the turn continues or stops
7. Completion policy + quality gates decide whether the result is acceptable
8. Final message is persisted and the SSE stream closesTool call
Tool call requested by the model
→ Tool Registry resolves the tool (native / MCP / skill)
→ Permission Guard classifies risk (declared at registration, not inferred)
→ Policy decision:
auto → execute
notify → execute, surface a notification
confirm → create an approval request, suspend the run, resume on decision
deny → block, record the decision
→ Execute
→ Write audit entry (actor, action, risk, decision, result)
→ Return the tool result to the modelApprovals are persisted, not held in memory: a pending approval survives a daemon restart and is resumed by the resume service after the user decides.
Dispatched run
User goal / delegated task
→ run dispatcher validates bounds (delegation may only narrow)
→ queue entry takes a slot (concurrency is bounded per resource class)
→ coding runtime creates a git worktree
→ executor adapter spawns the child agent (ACP)
→ capability probe: ready / needs_auth / unreachable
→ child streams events → event mapper → event log
→ diff + artifacts are captured into the run record
→ quality gates / adversarial judge (if enabled)
→ completion policy: pass → delivered branch; fail → failed with a reasonEvery transition writes an agent_run event, which is why GET /api/runs/:id/events can reconstruct a run after the fact and why a run can be cancelled or retried by id.
MCP connection
1. Daemon loads server definitions from mcp-servers.json
2. Spawns the child process (stdio) or connects over HTTP/SSE
3. Performs the MCP initialize handshake
4. Reads the tool list and registers each tool with its risk policy
5. Tools become available to the router and to the model
6. On disconnect, the server is marked disconnected and can be restartedStorage writes
Route or runtime → repository (SQLite / Supabase / PostgreSQL)
→ schema validation
→ write
→ (if event) also appended to the event logStorage mode is read at startup from storage.json (local, cloud, postgres). See Storage.
Voice turn
Wake word → microphone opens → ASR streams partial + final transcripts
→ final transcript enters the chat pipeline exactly like typed text
→ response streams; TTS speaks completed sentences
→ barge-in: speaking during playback interrupts audio and returns to ASRNext Steps
- System Overview — topology
- Executor Governance — what happens inside a dispatched run
- Reliability Evaluation — how run quality is measured