Muninn — Features & sources
The companion to Huginn's feature-and-sources page, for the other raven. Same goal: the deliberately complete, honest catalogue of what Muninn does and where each idea came from — credited in the open.
One difference is worth stating up front, because it's the honest story. Huginn was built by surveying the open-source coding-agent field and borrowing its best ideas. Muninn was built the other way round. It didn't even begin as a product — it started in early 2026 as a nameless learning exercise: a small Python tutorial to understand how agents actually work (its owner was already running an off-the-shelf agent and, true to form, wanted to own the machinery, not just operate it). Halfway through, that exercise turned out to re-derive a router-agent he'd hand-built years earlier and shelved as "too early" — and it grew, from personal need and mostly from first principles, into the household assistant Muninn is now. So this page has fewer "borrowed from project X" lines and more "built it, then found the paper that named it." Where there is a real debt — Odysseus, GPT-Researcher, the Claude-Code memory pattern, Honcho, the Ebbinghaus curve, MCP — it's called out precisely.
Conventions, same as Huginn's page:
- Borrowed — the idea came from a specific project, paper or article; the code is Muninn's own.
- Convergent — built independently, later found to match outside work (named because it's honest).
- Own — no external antecedent worth crediting.
- Integration — a self-hosted service Muninn drives, not an idea it borrowed.
The shared thesis across both ravens — the harness/loop is the differentiator, not the model — is what lets Muninn run on a local quantized model and still feel capable: the quality is in the loop, the memory and the tools, not a frontier API.
1. Shape — the sub-agent router
Single-tool main loop → ephemeral sub-agent. The conversation-facing LLM sees
exactly one tool, agent. When it needs to act, it calls agent({task}) and a
sub-agent runs in a throwaway context with the full tool surface. This keeps the main
context lean (~150 tokens of tool defs instead of ~500+), scales to many tools without
bloating every turn, and isolates tool execution from the conversation — roughly a 70%
saving on tool-definition tokens per request.
Own — a context-management design that fell out of running on local models where
every token of context costs latency.
Multi-transport core. One transport-agnostic BotCore behind a Transport trait;
Matrix (end-to-end encrypted), an HTTP voice receiver, and a web chat door all
push the same IncomingMessage. Add a surface by implementing the trait.
Own.
2. The agent loop — reliability
These are the L1/L2 fixes from the loop-engineering reading (the same article set Huginn audits against — Lanham's "three nested loops," MindStudio, LangChain's four-loop stack), mapped onto a conversational assistant.
L2 completion-verification. Before a sub-agent reports a state-changing task done, a fast-tier checker confirms the outcome actually happened (file written and non-empty? command succeeded?); a gap re-asks with the missing piece and the model keeps working. It fires only on a real mutation — a pure read ("show me the logs") skips it — so "done" is a checked fact, not a claim. This is Muninn's generalised analogue of Huginn's repro gate. Borrowed framing — MindStudio's "testable termination" / Lanham's "evaluation checkpoint"; convergent with Huginn's own repro-first gate.
Course-correct instead of kill. When the loop detector trips but rounds remain, the turn injects a "change tack" nudge and keeps its tools rather than force-ending — a recovery, not a death. Convergent — Lanham's L2 "control state, not prompts."
Empty-reply retry & deterministic routing. A garbled/empty final answer is re-asked tool-free up to four times before any canned fallback; and clear "research this" or "restart yourself" asks route deterministically to the right tool, because a local model ignores soft prompt rules. Own — hard lessons from running Qwen/Gemma locally.
3. The memory system — Muninn's heart
The reason Muninn exists: small context, good memory. A SQLite store (FTS5 +
sqlite-vec + a link graph) with an async extraction worker and a 30-minute
maintenance worker. The design is mostly its own; the specific borrowings are flagged.
Hybrid retrieval, LLM-judged. Recall is a cheap candidate generator — FTS5 + vector
search fused with reciprocal-rank fusion, plus one-hop graph augmentation. Relevance
is then judged by an LLM discriminator (the memory_slicer / profile_slicer) that
asks "is this actually useful for this message?" before injection, because cosine
similarity ranks vocabulary overlap, not aboutness.
Borrowed — this "which memories to attach" split is Claude Code's pattern (it keeps
no vector DB in its hot path); Muninn keeps embeddings for recall and bolts the LLM
gate on top.
Ebbinghaus decay. Memory strength fades on the forgetting curve
(strength · 2^(-days/14)); access resets the clock; below a floor a memory is archived,
not deleted.
Borrowed — the Ebbinghaus forgetting curve, applied directly.
Per-user profiles. Each person's top personal memories distil into a capped
"About <user>" block injected only for that sender.
Borrowed — Honcho's per-user dialectic profile idea, built "Honcho-lite."
The rest — own/convergent. Episodic summaries (group aged-out messages → LLM
summary), fact consolidation (merge Jaccard-similar memories with provenance), semantic
linking (cosine > 0.85 → graph edges), rolling conversation summaries, memory correction
(a corrects field auto-archives contradicted facts), and an opt-in nightly reflective
"dream" pass that re-reads for higher-order memories.
Own / Convergent — the shape echoes the agent-memory literature (memory stream +
reflection + decay) but was built from the household need, not ported from a paper.
4. Who, what, where — identity & access
Identity registry. One canonical user_id bridges every surface a person speaks
through — Matrix handle, voice speaker-ID label, device owner — into a single row with a
role.
Own. Device registry & presence map stable device ids → room → media player, and
track who/what is where for location-aware actions.
Own.
Role-based tool filter. Every request resolves the caller's role
(admin/adult/child/guest/unknown) and filters the sub-agent's tool surface both
in the prompt and at execution — the LLM never even sees a tool it can't use, and a
denied call is rejected again at invocation (defence in depth). Shell, email, calendar
and contacts are admin-only; children get room-limited home control; unknowns get
weather/calculate only.
Own.
Ephemeral sessions, onboarding & audit. An unknown speaker gets RAM-only state that
never touches the memory DB, a deterministic onboarding state machine (ask name → capture
→ approve), an impersonation defence (a claimed known name is acknowledged but never
trusted), and an append-only auth_events audit log — so the owner can answer "was there
a stranger in the basement at 3am?" without keeping the conversation.
Own — a privacy-first design for an always-listening household assistant.
5. The tools
Twenty-plus inner tools behind the agent router. Most are integrations — Muninn's
value there is the orchestration and safety, not the backend. The ones with a real idea
debt are flagged.
Home & household: home_query/home_action (Home Assistant conversation API),
music (full Music Assistant control — play modes, rooms, sync, taste split),
weather, photos (Immich slideshows on wall displays), camera (Frigate snapshot +
vision describe), speak/transcribe (TTS/STT).
Integration — Home Assistant, Music Assistant, Frigate, Immich, ComfyUI vision.
Generation: imagine — three image models (Krea 2 Turbo default, Flux 2 for edits,
Ideogram 4 for typography) on a local ComfyUI, async with placeholder swap.
Integration — ComfyUI; model routing is Muninn's own.
Email, calendar, contacts: IMAP/SMTP mail with correct threading and a Sent-append,
multi-account resolution, and a confirm-first extract_events appointment miner;
SQLite-truth calendar with NL date parsing, RRULE recurrence, and a reminder worker that
actually messages you; CardDAV contact lookup.
Borrowed — Odysseus (github.com/pewdiepie-archdaemon/odysseus, MIT): the email
threading / Sent-append / multi-account shape and the need_cal triage poller came
straight from its email_server.py / email_pollers.py; the calendar RRULE-expansion
and CalDAV-SSRF-guard patterns from its calendar_routes.py / caldav_sync.py.
Research: a deep-research tool with its own bounded plan → SearXNG search → fetch →
synthesize loop, returning a cited brief — with grounded planning, iterative deepening,
and per-page context compression.
Borrowed — the compression step ports GPT-Researcher's EmbeddingsFilter (chunk →
embed → keep only chunks similar to the query); the loop and SSRF guard are Muninn's own.
SearXNG is the integration.
Web, compute, FS, meta: web_search (SearXNG over Tor), youtube (yt-dlp captions →
summary), calculate/code_run (sandboxed Python), file_*/project (sandboxed FS),
shell (2-gate safety), scratchpad (per-task working memory), memory_lookup,
schedule (cron), progress.
Own / Integration.
External tools via MCP. Muninn can use tools from external Model Context Protocol
servers over stdio or streamable-HTTP (in production for muninn-fetch: page
fetch/screenshot/extract), admin-gated.
Borrowed — MCP is Anthropic's open standard.
6. Failure-learning & self-improvement
Failure-learning loop. The mirror of the memory system's success side: a run_outcomes
ledger records sub-agent runs, !failures reviews them (outcome / round-limit /
tool-failure / corrected), and !review-failures distils recurring failures into
"constraint" memories that surface back through retrieval — closing the loop (opt-in auto,
~once a day).
Borrowed/Convergent — the failure-side learning matches Self-Harness (arXiv
2606.09498) "weakness mining"; Muninn's version was built independently and aligns with
the paper.
Skill curator. Distilled procedural skills are archived when unused, low-success, or long-idle — memory that prunes itself. Own.
7. Orchestration — the L3 loop
Muninn drives Huginn. Muninn's meta-loop is the Muninn→Huginn relationship: it relays a coding task to Huginn over NATS, Huginn works headless, Muninn surfaces the structured outcome to Matrix — and the rule is faithful reporting (a downgraded "partial" must read as partial, never papered as done). Oz is the sole approver; approval lives in the run state. Borrowed framing — Lanham's L3 (orchestration/governance) from the loop-engineering reading; the relationship itself is the ravens' own design.
8. Voice & ambient presence
Wake-word-free ambient voice (speaker-ID routed), an open-house mode, and a native
TTS router that speaks straight through Home Assistant's tts.speak as a direct code
path — so audio works even when the model backend is busy or down. One verified room →
player map fixed the long-standing "TTS played in the wrong room" bug.
Own — built on the household's voice satellites + Home Assistant.
9. Safety
Two-gate shell, SSRF guards on every user/LLM-influenced URL (research, fetch, CalDAV/CardDAV — loopback/private/link-local rejected), an untrusted-content posture (content from web/Matrix/feeds/MCP is data, never instructions), and the role matrix above. Credentials live only in a gitignored local config; the memory DB and crypto store are never committed. Convergent — the untrusted-content posture is the loop-engineering reading's L1/L3 containment lesson (NCSC "confusable deputy"); the rest is first-principles.
10. Operations & observability
Cron scheduling with a reminder worker, replay capture (every exchange saved so a
prompt change can be A/B-tested against the real LLM), timing instrumentation (⏱ in
the logs), context logging, infra alerts & auto-remediation, and a one-binary deploy.
Own — the self-announcing-failures work came from a real pain (services dying silently).
Integrations Muninn builds on
Not idea-borrowings — the self-hosted stack it orchestrates: Home Assistant, Music
Assistant, Frigate, Immich, ComfyUI (Krea 2 / Flux 2 / Ideogram 4),
SearXNG, SOGo (CalDAV/CardDAV), Mailcow (IMAP/SMTP), Ollama
(nomic-embed-text), Matrix/Synapse, NATS, yt-dlp.
Sources
Ideas borrowed (code written here):
- Odysseus —
github.com/pewdiepie-archdaemon/odysseus(MIT) — email threading / Sent-append / multi-account resolution /need_caltriage poller; calendar RRULE expansion + NL parse; CalDAV one-way sync + SSRF guard - GPT-Researcher — the research tool's context-compression (
EmbeddingsFilter: chunk → embed → keep query-similar chunks) - Claude Code — the "which memories to attach" pattern: an LLM relevance gate over cheap embedding recall, no vector DB in the hot path
- Honcho — per-user dialectic "About
<user>" profiles (built "Honcho-lite") - Ebbinghaus forgetting curve — time-based memory decay with access-reset
- Model Context Protocol (MCP) — Anthropic's open standard for external tool servers
Papers:
- Self-Harness: Harnesses That Improve Themselves — arXiv 2606.09498 (failure / weakness mining; Muninn's failure-learning loop converges with it)
The loop-engineering reading (shared with Huginn — full notes in the Huginn copy):
- What Is Loop Engineering? — MindStudio (testable termination)
- The Agent Loop Decoded: Three Levels — Micheal Lanham / Oracle (the L1/L2/L3 nested-loop model; Muninn's L3 is the Muninn→Huginn orchestration)
- Building Autonomous AI Agent Loops — setkyar
- The Art of Loop Engineering — LangChain (the four-loop stack)
- Loopcraft: the Art of Stacking — Latent.Space (active memory, provider-agnostic routing)
- Loop Engineering — Addy Osmani (automations, skills, connectors, verification-split, on-disk state)
See the Huginn feature & sources page for the harness side, and the full Muninn feature inventory for the exhaustive component-by-component list.
Last reviewed: 2026-06-25. Maintained by hand — if a feature ships without landing here, that's a bug in the page.