Architecture
FRIDAY runs a modular plugin architecture with a capability registry, a v2 turn-orchestration pipeline, and a three-tier memory system. Every turn — voice or text — flows through one pipeline.
The turn lifecycle
A turn enters as voice or text and is handled by the TurnOrchestrator, which owns the lifecycle. It builds a context bundle (persona + session summary + memory recall), runs the router, executes the chosen capability, styles the response through the active persona, speaks it, and curates the turn into memory.
voice / text in
│
STTEngine ──► TurnOrchestrator (v2, core/planning/)
│
_build_context_bundle() (persona + session summary + recall)
│
PlannerEngine.plan() ◄── the 6-layer router
│
ToolPlan (mode: tool | planner | chat | reply)
│
OrderedToolExecutor ⇄ TaskGraphExecutor (parallel, opt-in)
│
CapabilityExecutor ──► capability handler (28 plugin modules)
│
ResponseFinalizer ──► persona styling ──► TTS / GUI / channel
│
MemoryCuratorAgent.curate() (writes the turn to stores + Chroma)TurnOrchestrator owns the lifecycle, PlannerEngine owns route selection, and CapabilityExecutor enforces the lock gate and online-consent gate before any handler runs.The routing pipeline
PlannerEngine.plan() walks an ordered chain and returns at the first layer that produces a plan. Each layer is more expensive than the last, so common phrasings never pay for the LLM. This is the heart of what makes FRIDAY work on small local models — covered in depth in How routing works.
L1 IntentRecognizer deterministic regex parsers (first-match wins) conf 1.0
L2 RouteScorer alias / pattern / context-term score (min 80)
L2a Learned dispatch a phrasing confirmed promote_after times
L2b LexicalRouter rapidfuzz token_set_ratio (catches STT / typos)
L3 EmbeddingRouter cosine over capability embeddings (+ confirm band)
L4 QwenPlanner local 4B planner (LLM tool / plan synthesis)
L5 llm_chat conversational fallbackWorkflow state machine
Anything that can't resolve in one turn runs as a workflow through WorkflowOrchestrator. A workflow persists its state so the next turn resumes mid-flow. Three reusable, composable mechanisms — all pure session-state + regex, gated by config — cover the common multi-turn shapes:
- ConfirmationGuard — “shall I go ahead?” before a destructive action (lock screen, delete goal, forget memory…).
- DisambiguationGuard — “which one did you mean?” when a request resolves to more than one candidate (file search, app launch, document query).
- Slot-fill templates — declarative YAML driven by
SlotFillerwith cheapest-first precedence: caller-known → extractor → LLM → default.
Three-tier memory
FRIDAY keeps memory across turns and sessions, all on local disk, written by a single curator:
Persistence — domain stores
Storage is decomposed into six domain stores under core/stores/, each owning its own tables and migration SQL. A transitional ContextStore facade delegates to them. Write-ownership is strict (each store writes only its own tables); reads may cross stores via raw SQL on the shared data/friday.db (WAL mode).
Cross-platform model
One codebase, two first-class platforms. Platform-specific behaviour is guarded throughout:
docs/ARCHITECTURE.md) and a pre-built knowledge graph of the codebase with god-nodes and community detection.