Technology
Fast thinking, slow thinking,
and a memory that knows who's who.
An assistant in the kitchen has to feel instant and still be smart. Anamanti gets there with a team of specialised models instead of one big one, a knowledge graph instead of a chat history, and a strict rule: the cheapest way to answer a request is the one that answers it.
Responsiveness
System 1 answers first. System 2 only when it's needed.
Psychology describes two modes of thought: fast and intuitive, and slow and deliberate. Most of what people say to a kitchen assistant is the fast kind, such as “set a timer for ten minutes”, “what's the weather?” or “I'm done, thanks”, so Anamanti tries the fast routes first, in order, and stops as soon as one can answer.
Memory commands
“Remember that…”, “forget that”, “who am I?” Matched in plain code. “Who am I” is answered from your voiceprint, not a guess.
Home Assistant
“Turn off the kitchen lights.” Matched against a cached device list, then one direct call. It refuses to guess.
Camera
“Show me the front door.” The display that asked opens the live stream.
System-1
A typed classifier: it doesn't write text, it labels the request in a single pass with a confidence score. It handles timers, weather, time and date, closing screens and ending the conversation. Below a confidence of 0.85 it defers to System 2.
System 2
Memory recall from the graph, then the full language model with tools, streamed sentence by sentence into speech.
Precision over recall
A fast answer that's wrong is worse than a slow one that's right, so System-1 is tuned to defer whenever it's unsure. It hands past-tense questions (“what was the weather yesterday?”), questions about specific places and anything open-ended to System 2.
On the calibration set it scored 22 of 22 at a 0.85 threshold, with zero wrong resolutions. One global threshold was enough; no per-intent tuning was needed.
System-1 can run locally through Laya-Decision, a non-autoregressive ModernBERT classifier in Rust, or as a hosted classifier (Jev, on OpenRouter). Both use the same contract, so you can swap them from the console.

Streaming everywhere
Never wait for a whole answer.
Even when the large model is needed, nothing waits for anything else to finish.
median from the end of speech to the spoken reply when System-1 answers (fastest 417 ms).
median when the full model answers. Each sentence goes to Piper as soon as it's complete, so speech starts long before the reply is finished.
median speech-to-text time per turn, after you stop talking.
added to a turn by memory ingestion. Indexing happens in the background, after the turn.
Medians are from the last 100 turns on the live install (October 2026). Every turn logs a per-stage timeline (speech-to-text, System-1, fetch, recall, prompt, first token, first audio), shown as a waterfall in the console, so a slowdown is visible the day it appears.
Linked AI systems
Not one model. A team of them.
A single turn can involve up to eight models, each small and good at one job. Each can be swapped without touching the others, and the console labels where each one runs.
Hear the wake word
openWakeWord
An ONNX model running in Rust on the display.
DisplayDetect end of speech
Silero VAD
A small neural speech detector.
MacRecognise the speaker
ECAPA-TDNN
192-dimension voiceprints, in pure Rust.
MacTranscribe
Whisper / Scribe
Local whisper.cpp or faster-whisper, or ElevenLabs.
Mac or cloudRoute
System-1 classifier
Laya-Decision (ModernBERT) or Jev.
Mac or cloudRemember
nomic-embed-text
768-dimension embeddings via onnxruntime.
MacReason & act
Language model
Ollama, Claude or OpenAI, with tools.
Mac or cloudSpeak
Piper
Fast neural text-to-speech; 174 voices here.
MacA ninth model works in the background, after the turn: entity extraction (Claude Haiku) reads each finished turn and adds people, places and topics to the memory graph. It's the one memory step that uses a cloud model even when everything else is local, so the console says so and it has an off switch.
Graph memory
A memory shaped like a household.
A chat history can only find text that looks similar to what you just said. A household is people, places and relationships, so Anamanti's memory is a graph.
HelixDB, embedded. A graph and vector database running inside the Core process, with no server and no Docker. Its nodes are people, turns, memories and entities, and recall is a vector search followed by a hop across the graph, so “what did Sam say about the cabin?” can follow Sam → the cabin → what was said, rather than matching keywords.
Lossless by design. Every turn is appended to a plain chat log, which is the source of truth. A background process embeds it into the graph about every 30 seconds. Durable facts live in SQLite. If the embedder ever fails, recall falls back to SQLite full-text search, so a turn always gets some memories.
Local embeddings, swappable live. nomic-embed-text runs on the Mac with no key and no network. Switch to OpenAI embeddings and back from the console: each backend keeps its own index, so switching re-embeds nothing and loses nothing.
Across languages. A voiceprint describes how you sound, not which language you're speaking, so the same person should be recognised in English or Portuguese, and something said in one language should be recalled when asked in the other. We're testing exactly that with English and Brazilian Portuguese now, before adding more languages.
Scoped to the speaker. Each memory belongs to a person, the household, or an unknown voice. Things an unknown voice says are kept but never recalled for anyone until you review them, so a guest can't plant facts about you.
Illustration. Recall starts from the turns most similar to what you just said, then follows the graph to the people, places and topics around them.


The stack
Rust almost everywhere.
The Core, the display's audio engine, the phone app's networking and the shared protocol are all Rust. That gives predictable latency on the Mac, and no garbage-collector pauses on a 32-bit device with about 1 GB of RAM. Flutter draws the screens; Rust does everything time-critical.
Devices and the Core use Wyoming, the open voice protocol from the Home Assistant ecosystem, with Anamanti's own frames for screens, music, memory and push. They find each other over mDNS.
| Layer | Technology |
|---|---|
| Core | Rust · tokio · rig agent framework |
| Display | Flutter + Rust via flutter_rust_bridge v2 |
| Wake word | openWakeWord on tract-onnx |
| On-Mac inference | onnxruntime · whisper.cpp (Metal) · candle |
| Memory | HelixDB (embedded graph + vector) · SQLite |
| Transport | Wyoming over TCP · mDNS discovery |
| Audio | cpal / AAudio on device · Snapcast in the house |
| Console | Static HTML + Tailwind, compiled into the binary |