Architecture
Single Python backend. Explicit LangGraph agent graph. Three memory layers backed by SQLite. CLI-first development.
Turn pipeline
Safety-first ordering
The crisis gate is the first node in the graph. Memory only loads on the therapeutic branch — if a message triggers a crisis response, memory retrieval is skipped entirely.
1
Command(goto=...) routes to one branch:crisis_gate_nodeEvery message — no exceptions. LLM-primary classifier with deterministic overrides and regex fallback.
crisis path
2a
crisis_response_nodePFA overlay + web-searched local hotlines
3a
crisis_log_nodeAudit trail — writes regardless of memory mode
therapeutic path
2b
load_memory_nodeHybrid RRF retrieval across 3 namespaces
3b
therapeutic_subgraphDispatcher → 1 of 7 response styles × 7 approaches
both paths converge
4
finalize_turn_nodeAppend response to transcript via operator.add reducer. No I/O — no retry.
parallel fan-out
5
extract_semantic_facts_nodeCandidate extraction → deterministic write policy
5
extract_procedural_rules_nodeStyle rules → immediate commit or session-end hold
session end/end · timeout · shutdown · voice disconnect
6
summarize_sessionEpisodic arc for cross-session continuity
7
commit_session_memoryPromote held semantic + procedural candidates
Every I/O node has RetryPolicy(max_attempts=2) as defense-in-depth.
Key decisions
| Decision | Choice | Why |
|---|---|---|
| Execution | LangGraph StateGraph | Explicit branches, deterministic ordering, checkpoint persistence |
| LLM | BaseLLMClient protocol | Provider-agnostic — Gemini + OpenAI satisfy the same interface |
| Embedding | EmbeddingProvider protocol | Gemini text-embedding-004 default; null provider for offline |
| Storage | SQLite via aiosqlite | Single-file, no server, survives restart |
| Memory | MemoryStore protocol | In-memory for incognito/tests; SQLite for persistent |
| Retrieval | Hybrid RRF | Embedding cosine + token-recall fused via Reciprocal Rank Fusion |
| Prompt sources | agent/prompts/sources/*.md files | Reviewed prompt fragments; composed at runtime |
| Context | WorkflowContext frozen dataclass | Attribute access, type-safe, immutable per turn |
| Reducers | operator.add + _merge_dicts | Transcript accumulation + parallel diagnostics |
| Observability | LangSmith + local diagnostics | LangSmith for trace-level debugging and evaluation review; in-CLI diagnostics for per-turn visibility |
| Crisis log | Always-on | Privacy asymmetry — incognito scrubs user_id but still records |
Persistence
Four SQLite databases
Each under .store/, each owning its schema independently. Paths
overridable via CLI flags. Incognito mode uses in-memory backends
for all four — nothing touches disk.
| Database | Owner | What it persists | Retention |
|---|---|---|---|
threads.sqlite3 | LangGraph checkpointer | Conversation state snapshots | Indefinite |
memory.sqlite3 | SqliteMemoryStore | Semantic facts, episodic arcs, procedural profiles | User-controlled |
crisis.sqlite3 | SqliteCrisisLogBackend | Crisis event audit trail | 90 days |
session_feedback.sqlite3 | SqliteSessionFeedbackBackend | End-of-session thumbs ratings | 180 days |
Prompt layers
Six layers composed per turn, outermost first. Click a layer to see its source.
See Prompt Assembly for the full composition logic.
Package layout
| Package | Owns |
|---|---|
agent/ | Graph entrypoint, state schema, models, runtime context |
agent/nodes/ | One file per graph node (8 nodes) |
agent/memory/ | Store protocol, embeddings, retrieval, dedup, hashing |
agent/therapeutic/ | Subgraph: dispatcher, seven response style nodes, prompts |
agent/tools/ | Web search for crisis resources |
services/llm/ | BaseLLMClient + Gemini + OpenAI clients |
opencouch_cli/ | Rich-based interactive CLI |
voice/ | OpenAI Realtime voice sessions |
api/ | FastAPI routes (chat, threads, memory) |
tests/ | 630+ pytest tests |
eval/ | 5 eval harnesses with curated datasets |
Quick links
| Topic | Page |
|---|---|
| Agent graph | Graph |
| Node catalog | Nodes |
| Tools | Tools |
| State schema | State |
| Memory | Memory |
| Crisis gate | Crisis Gate |
| Runtime | Runtime |
| Observability | Observability |
| Privacy | Privacy |