Noggin — Design Document
Purpose and principles
Noggin is a single-user personal agent engine: a small, portable “brain” you own outright, and a thin web “mouthpiece” you talk to it with. You create persona agents, called voices, for the topics that matter to you (career adviser, travel agent, reading coach), each with its own memory, and you choose where the brain runs according to what you want to spend.
Principles
- Sovereignty. The brain is one folder in open formats (SQLite, YAML, Markdown). It can be copied, moved, backed up or deleted, and nothing about you exists anywhere else.
- Single user. One person, one brain (or several), one pairing. No tenancy, no vendor in the loop of a conversation. Amended 2026-10-17: the transport vendor (Cloudflare) carries conversations and can technically read them in transit unless the owner turns on end-to-end encryption; no vendor stores or acts on them.
- Local by default, cloud by consent. Each voice declares its privacy level; the engine can only choose models within what the voice permits.
- Portable. One container image or binary runs the same on a laptop, a Raspberry Pi, a cheap VPS or a GPU host. Moving platform is a copy, not a migration.
- Thin mouthpiece. The client holds no state or intelligence; it renders and captures.
- Visible cost. Every outbound call is logged with model, tokens and cost, so the owner always knows what left the machine and what it cost.
- Human acts, brain prepares. The brain never submits, posts, pays or sends; the owner presses every final button.
Naming
The platform is Noggin; the site and umbrella brand is all my noggins; the app is talkto.allmynoggins.com (wordmark talkto.allmynoggins; the earlier name Talk2UrNoggin is retired); persona agents are voices, and a voice bundled with its memory and feedback is technically a personality.
| Thing | Name | Used for |
|---|---|---|
| Platform / brain | Noggin | Product name, brain binary and image (noggin) |
| Site and brand | all my noggins | allmynoggins.com |
| App | talkto.allmynoggins.com | The chat and talk PWA; favicon and PWA icon use the Talk mark |
| Tagline | “Talk to your noggin” | Marketing |
| Persona agent | voice | A career adviser, travel agent, etc. |
| The owned data folder | your noggin | The noggin/ directory that is exported and moved |
Checks before committing
- Search UK IPO and EUIPO trademark registers for “Noggin” in software classes (9 and 42); a children’s TV brand already uses the word
- Domains: one domain, allmynoggins.com; the app at talkto.allmynoggins.com; personal consoles at
<slug>.allmynoggins.com
Architecture overview
Two parts: the mouthpiece renders and captures; the brain owns every decision, every byte of state and every outbound call. A console at the owner’s subdomain points the app at the right brain and then drops out of the path.
(Diagram in the Claude Doc: console → mouthpiece ↔ brain; inside the brain the router and cost optimiser with voices, memory and feedback as two-way inputs, local and cloud engines, speech engines, the runs.db audit band; cloud providers outside, reached only from the brain.)
The mouthpiece only ever speaks to its paired brain over one authenticated API. The router chooses a model for each request within the voice’s privacy rules, and the connectors are the single point where anything leaves the machine.
The Noggin (brain)
Services in one process, all behind one API, all reading and writing the noggin/ folder.
| Service | Responsibility | How it works in v1 |
|---|---|---|
| Router and cost optimiser | Picks the model and speech backends for each request and records what it cost | Inputs: voice policy, memory, feedback, host capability. Decision order: privacy gate (hard), drop what the host cannot run, quality floor for the request class, cheapest remaining by estimated tokens. Rules in rules.yaml; learned weights recorded, acted on in stage 2 |
| Local LLM engines | Run models on the host | One adapter interface generate(messages, params) → stream. Ollama first. Detected at startup; absent on hosts without the RAM |
| Cloud LLM connectors | Call external providers on the voice’s behalf | Same adapter interface. Anthropic plus one OpenAI-compatible adapter (Groq, Together, OpenAI). Keys stored encrypted in the brain. Redaction pass for asks voices |
| Voice registry | Holds persona definitions | One Markdown file per voice with YAML front-matter. Created from the mouthpiece, the designer, or by hand |
| Memory | Remembers across sessions, scoped per voice | SQLite plus sqlite-vec in memory.db. Three tiers: session history, voice memory, shared memory. Also holds the prompt library |
| Feedback | Turns ratings into better behaviour | Thumbs up/down plus optional note on every response; a note can be promoted straight into voice memory as a correction; ratings feed per-voice learned weights |
| Scheduler | Timed jobs | schedule entries in a voice’s front-matter run in-process with the same router, privacy gate and audit |
| Audit | Records every outbound call before it is sent | runs.db, append-only |
Request flow
- Mouthpiece sends a message for a session.
- Brain loads the voice, its memory scope and recent history.
- Router scores the request and picks a model the voice allows.
- Adapter streams the response back; tokens and cost are logged as a
ModelRun. - Owner rates the response; feedback updates memory and learned weights.
Feedback into the router, and the session adviser. Feedback is the router’s learning signal, and the same data lets the router advise the owner before a session starts. Stage 1 (v1): recorded, not acted on. Stage 2: once a voice has enough ratings for a class (about 20), the router replaces the static quality floor with the learned score; learned weights live in memory.db, are visible in the app and can be reset. Session adviser: when the owner opens a voice, the mouthpiece shows a three-way choice, Performance (fastest, usually local), Quality (best-rated for this voice, often cloud) or Cost (cheapest not rated down), with expected cost per reply and typical latency from this owner’s own history. The choice sets a bias for the session, never overrides the privacy gate, and is remembered per voice. This learning stays entirely inside the owner’s noggin.
Is the router intelligent? Not in v1: it is a deterministic rules engine so every choice is explainable. Stage 2 makes it adaptive through the owner’s ratings. A v2 option is an intelligent classifier: a small local model (2–4B) reads each prompt and tags its request class before the rules run; off by default, never bypasses the privacy gate.
Scheduler (timed jobs, in v1). A voice may carry schedule entries (cron, prompt). The brain runs them in-process with the same router, privacy gate and audit as a live message, writes the result into the voice’s session, and the mouthpiece shows it on next open with a badge. Jobs only run while the brain is up; on the free tier they fire at the next start if missed. Jobs that would need a cloud call from an asks voice are held until the owner next opens the voice and confirms. No job can read beyond its voice’s memory scope.
Personalities and noggins
Two units, at two levels:
- A personality is what the owner talks to: one voice file (persona and policy), its memory scope, its prompt library, and its feedback record with any learned weights. These always travel together. In the app and on the site a personality is still called a voice.
- A noggin is what runs: one folder on one host holding any number of personalities, plus the shared parts they all use: the router and cost optimiser, the local engines, the cloud connectors, the audit log and the scheduler.
(Diagram in the Claude Doc: three personalities inside Noggin A sharing one router and one engine layer; Noggin B on a Mac mini and Noggin C on a VPS fully independent.)
Consequences
- Personalities inside a noggin are isolated by memory scope but share the router’s decisions and learned cost history.
- Separate noggins are fully independent: different hosts, different privacy postures, different providers. They never communicate.
- Export works at both levels: a whole noggin, or one personality as its own folder that can be imported into another noggin.
- Most owners need one noggin with several personalities. A second noggin is for a different place or a different privacy posture, not for a different topic.
talkto.allmynoggins.com (mouthpiece)
A stateless client: three screens, no local intelligence, everything read from and written to the brain.
| Screen | What the owner does | What the brain provides |
|---|---|---|
| Pick a voice | Chooses a persona, creates a new one with a short form or the designer, sees cost this month per voice, sees brain availability | GET /voices, POST /voices, cost summary from runs.db |
| Chat | Types a message, picks a saved prompt, sees the streamed reply, rates it, sees which model answered and what it cost; a session adviser card on open | POST /sessions/{id}/messages (streamed), GET /prompts, POST /feedback, GET /voices/{id}/advice |
| Talk | Holds to speak; device or brain-side speech-to-text, reply read aloud | Same chat pipeline plus the audio channel |
Rules
- Pairing is the only setup: enter a one-time code or follow a console link; the client stores a token and the brain’s address.
- No settings live on the client. Changing a voice, a key or a privacy level is a brain operation surfaced in the UI.
- Version 1 is a React web app (installable PWA, served at talkto.allmynoggins.com). No native iOS or Android build in v1; an Expo wrapper can reuse the same React components later if hands-free talk or store presence requires it.
- Least possible footprint. The mouthpiece stores exactly two things on the device: the pairing token and the brain’s address, both erased by Forget pairing. No message history, memory, voice files, audio, drafts or preferences are cached; the app shell is the only thing the service worker keeps, so it can open offline and show Noggin offline.
Personas (voices)
A voice is one human-editable Markdown file: YAML front-matter for policy, body text for the system prompt. See the architecture specification for the full schema.
Privacy levels
| Level | Meaning | Where it can run |
|---|---|---|
local (Local only) | Nothing leaves the host; cloud connectors are refused for this voice | Hosts with a local engine only; elsewhere the voice reports it cannot run |
asks (Asks before sharing) | Cloud allowed after the redaction pass, and the owner confirms once per session before the first cloud call | Any host |
web (Uses the web) | Cloud allowed with the full prompt | Any host |
Memory scopes: each voice reads and writes only its own scope; a shared scope holds what every voice should know (name, location, time zone, language); sharing a fact across scopes is an explicit action in the UI, never automatic.
Prompt library: saved starters per voice, each with a usage count and feedback score, stored as Markdown files beside the voice so they travel with it.
Creating a voice: a short form (name, purpose, privacy level, what it should remember), or the designer interview. The brain writes the file; the owner can open and edit it any time.
Speech (Talk)
Speech is handled exactly like the LLM layer: two adapter interfaces in the brain (transcribe, speak) with pluggable backends, chosen per voice under the same privacy rules. ElevenLabs is one option, never a dependency.
| Role | On device (free, private) | Open source on the brain | Cloud (best quality, paid) |
|---|---|---|---|
| STT | iOS and Android built-in recognition | Whisper via whisper.cpp | ElevenLabs Scribe, Deepgram Nova |
| TTS | iOS and Android built-in voices | Kokoro (82M parameters, CPU or Pi), Chatterbox (MIT licence, more RAM), Piper (very small hosts) | ElevenLabs, OpenAI TTS, Cartesia, Deepgram Aura |
How Talk flows: the phone captures audio; device STT by default, or brain-side Whisper (the default for local voices where the host can run it, since device recognition on iOS is processed by Apple); text goes to the brain through the normal messages endpoint; the brain streams the reply text and the TTS adapter converts it sentence by sentence on a second channel; if the chosen backend is unavailable, the brain falls back to the phone’s built-in voice and says so. Speech calls are logged to runs.db like LLM calls. A local voice can never be transcribed or read aloud by a cloud service.
Defaults by hosting tier: free or Pi: device STT, Kokoro or Piper TTS; cheap VPS: device STT, cloud TTS of choice; mid or GPU: Whisper and Kokoro locally, as shared services where several noggins share a GPU host, cloud only for voices that allow it.
Data model
Seven core entities, all in SQLite except voices and prompts, which stay as files: Voice (voices/<slug>.md), Prompt (voices/<slug>/prompts/*.md), Session, Message, Memory (scope, kind, content, embedding), ModelRun / SpeechRun / ToolRun (runs.db), Feedback. Keeping runs.db separate means the audit of what left the machine can be exported or inspected on its own.
API between mouthpiece and brain
One HTTPS API with bearer-token auth and SSE for streaming, versioned under /v1/; the full contract is in the architecture specification.
Portability and hosting
The brain ships as one container image (and a plain binary); all state is the mounted noggin/ folder, so moving host is copy, start, re-pair.
Hosting tiers (the cost dial)
| Tier | Where | Approx. cost | What changes |
|---|---|---|---|
| Free | Own laptop, Mac mini, Raspberry Pi | £0 | Local models available; reachable only while on; its Cloudflare Tunnel address reaches it from the phone’s browser |
| Cheap | Small VPS (1–2 GB RAM) | £0–5 / month | Always on; cloud connectors do the work |
| Mid | 8–16 GB VPS or Mac mini | £15–60 / month | Small local models run; local voices work remotely |
| GPU | 16–24 GB VRAM dedicated bare metal | ~£120–200 / month | 8B–14B models responsive for several concurrent visitors; Whisper and Kokoro as shared services; the founder’s gpu-1 (RTX 5060 Ti 16 GB) is this tier |
The router reads /health at startup and adapts; a local voice on a cloud-only host says it cannot run.
Transport: noggin export writes an encrypted archive; start the image on the new host and noggin import; the mouthpiece re-pairs. A cost screen shows current monthly spend before a move.
Portability rules: no managed-cloud dependencies (SQLite, filesystem, one process); ARM64 and x86-64; networking held in one exposure setting (tunnel by default, served by a cloudflared sidecar beside the brain at <name>.allmynoggins.net; or lan, public); one config.yaml with environment overrides.
Console and accounts
Each person claims one subdomain, <slug>.allmynoggins.com, which serves their console: a static web app that knows where their noggins are and opens the app at talkto.allmynoggins.com for any of them. The subdomain is the person; a person may own several noggins. The console only ever holds pointers to brains, never their contents.
Three actions
| Action | What happens | What the console stores |
|---|---|---|
| Access my mouthpiece | Pick a noggin; the browser pairs with it directly and the chat and talk UI loads | Nothing: traffic goes browser to brain |
| Manage my noggins | List each brain with name, host, status, monthly cost and last export; pause, export, move or delete | Name, address, hosting tier, status |
| Create a new noggin | Starter templates and a brain profile, then either Run it myself (generates an install package) or Host it for me (hidden until a compute provider is enabled in Ops) | A pointer; for hosted brains, the billing record |
Sign-in methods. Passkeys, and single sign-on through OpenID Connect with Google and Apple (others can follow). SSO only proves it is the same person to the console and never reaches a brain; the console stores only the provider’s subject id and the email. An account can add a passkey and remove the provider later. The sign-in page says plainly that the provider learns you use the console, not what is in your brain.
Creating a noggin: starter templates. Starter voices (career adviser, travel agent, reading coach, house and garden, study tutor), brain profiles (Private first, Balanced, Best quality) that pre-fill the router rules and default models, and host presets. Templates are plain files in the repo under templates/.
Install packages. The goal is a frictionless self-run noggin: one action to install, nothing to configure at Cloudflare, pairing by QR code, and one action each to repair, update, back up, move or leave (rules in the architecture specification, Owner experience for self-run noggins). Run it myself does not show commands; it generates a downloadable install package for the chosen target. Every package has the same shape (install.sh or install.ps1, docker-compose.yml, noggin.env with a single-use pairing token, config.yaml, README.md) and is built from the same templates, so a laptop and a cloud VM run byte-identical brains.
| Target | Exposure | What the package adds |
|---|---|---|
| Laptop (macOS, Windows, Linux) | Cloudflare Tunnel (sidecar) | Docker Desktop link, Ollama installed natively, a note on sleep and “offline since” |
| VPS the owner already has | Cloudflare Tunnel (sidecar) | ufw with nothing inbound, cloudflared service with the tunnel token, native Ollama, model chosen from stated RAM, name and port offset so several noggins can share one server |
| New cloud VM at a provider | Cloudflare Tunnel | A cloud-init user-data file that performs the whole install unattended on first boot |
The package holds the pairing token and the noggin’s tunnel token, and no other secret. The README carries the ownership statement. The installer is idempotent.
Availability of a self-run brain. Every brain sends a heartbeat to the console every 60 seconds (opt-out available), carrying only the brain id, version and host capability. The console shows each noggin as online, offline since a time, or unavailable here; the mouthpiece shows the same state in its header and mic button.
Reachability. Wildcard DNS and a wildcard certificate make a new subdomain instant; nothing is created per user. Self-run brains are reached through their own Cloudflare Tunnel sidecar at <name>.allmynoggins.net; hosted ones at a provider address. The console hands the browser a short-lived token to pair, then drops out of the path.
Rules that keep the promise honest: the console never proxies chat traffic; it cannot read a brain’s folder; deleting an account deletes pointers and hosted containers, with an export offered first; a self-run brain works without the console at all.
Noggin designer
designmynoggin.allmynoggins.com is a guided interface for making personalities well: it interviews the owner, proposes a voice file, memory seeds and starter prompts, lets them edit, and hands the result to a noggin. It stores nothing.
| Mode | Model | Who pays | When |
|---|---|---|---|
| Through the owner’s noggin | Whatever the owner’s router chooses, under a built-in designer voice | Owner | Default once a brain is paired |
| Platform-provided | A small, cheap frontier model on the platform’s key, hard-capped per session | Platform, as a trial cost | For someone with no brain yet; session not stored, result only downloaded |
| Fine-tuned designer model | An open-weights 3–8B model fine-tuned on published voice files and interviews | Nobody at run time; ships with the brain | Later |
Rules: the designer never keeps the interview or the result; platform mode is rate-limited and archives carry made_with; fine-tuning data is only published templates and consented interviews; the same flow is reachable in the app under New voice → Design it with me.
System architecture
Figure: docs/architecture.svg, the three layers decided on 2026-10-24 (the platform on Cloudflare, managed compute on noggin hosts, self-run noggins); see the architecture specification, Three layers, for the full description.
- The top band is the allmynoggins platform: the parts operated by the company rather than by any owner. It holds accounts, subdomains, pointers to brains, hosting tiers, templates and settings. It never holds a message, a memory, a voice file or a key.
- Ops is staff-only. Sign-in requires a passkey registered to an address at allmynoggins.com or allmynoggins.net; no other email domain and no consumer SSO. Ops reaches hosted brains only through provider adapters, and only for lifecycle (create, pause, destroy).
- Provider adapters are configuration. None is enabled at launch, so every brain is self-run; enabling one in Ops switches on Host it for me.
- Each person has one console subdomain and any number of brains. The app talks to a brain directly; the console drops out after pairing.
- Cloud model and speech providers are reached only from a brain, only where a voice’s privacy level allows, with the call logged before it is sent.
Ops console (site administration)
ops.allmynoggins.com is the platform owner’s own console for running the service. It can never see inside a brain; it administers the pointers, the plumbing and the money.
| Area | Capability |
|---|---|
| Hosting providers | Register and enable cloud providers as configuration: a provider adapter (Fly.io, Hetzner, IONOS Cloud, others) with credentials, regions and tiers. Until one is enabled, Host it for me is hidden |
| Tiers and pricing | Define hosting tiers and which are visible |
| Accounts | Search accounts; see pointers, status, hosted instances and spend; suspend or delete on a valid legal notice, with export offered first |
| Hosted fleet | Every hosted brain with provider, region, status, heartbeat, cost; pause, restart, migrate |
| Templates | Publish and version starter voices, brain profiles and host presets |
| Service settings | Edge and DNS provider (Cloudflare for v1), email provider, feature flags, maintenance notice, legal text versions |
| Audit | Every ops action logged with who, what and when |
| Health | Console API, database, each provider’s API, heartbeat lag |
Rules: ops accounts only for addresses at allmynoggins.com or allmynoggins.net, passkeys only, no consumer SSO; two people minimum before any destructive action on a user’s noggin; ops has no route to a brain’s folder or API; provider adapters share one interface so switching a cloud is configuration plus an adapter; Cloudflare is the edge and DNS provider for v1, the compute provider is left open.
Outbound actions
Principle: the brain never acts on the world. Only the owner does. A voice may find, make and prepare; the final step of anything that leaves the noggin — posting, sending, paying, booking, cancelling — is always a human click. This is a permanent design rule.
| Tier | What a voice can do | Where the result goes | Who acts | When |
|---|---|---|---|---|
| Read | Web search, fetch a page, read the owner’s calendar or inbox, check a price | Into the reply | Brain, within the voice’s privacy level | v1 |
| Produce | Generate an image, comic strip, video, document or audio | Stored in the voice’s folder; exported and deleted with the voice | Brain; cloud generators gated by asks | v1.5, images first |
| Draft | Prepare the action completely: the post with image and caption, the filled booking page, the written email | A ready-to-go draft with a single Post, Send or Open button | Brain prepares, owner clicks | v1.5 |
| Act | — | — | Owner only, always. No code path submits, posts, pays or sends | Never automated |
Example: a social media voice. It drafts the week’s posts and lays them out as cards; each card’s Post button opens the platform’s own composer pre-filled for the owner to press publish. It can be scheduled to prepare drafts every Monday; it can never be scheduled to publish them.
Rules: the privacy gate applies to tools exactly as to models; produced files and drafts record the model, prompt and cost that made them; per-voice monthly spend caps are required before any media connector ships; a draft prepared immediately after reading external content is flagged before the button; no stored platform credentials in the brain for posting or paying; every tool call is logged in runs.db before it runs.
Ownership, deletion and liability
Sovereignty cuts both ways: the owner holds everything, and the owner answers for everything.
What the brain keeps, and how to delete it: conversation history, voice memory, feedback and outcomes in memory.db, the audit of calls in runs.db. The owner can delete any of it at any time: a message, a session, a memory item, a whole voice with its scope, the audit log, or the entire noggin. Deletion removes rows and embeddings. Hosted brains are no exception: the volume is destroyed when the noggin is deleted.
Liability and accountability: whatever a voice generates, and whatever the owner collects into a noggin, is the owner’s content. If it is illegal, defamatory, infringing or otherwise unlawful where the owner lives, the owner is personally liable for it; the platform does not review, moderate or have access to it. The owner is responsible for the keys they configure, the provider terms they accept, the models they run, and their own backups.
Where the disclaimer appears: once at account creation and at first brain creation, as a short plain-English acceptance: “This noggin is yours. You can delete anything in it at any time. You are personally responsible for everything it stores or produces.”; in the app’s settings beside the deletion controls; in the console’s Manage screen beside Delete; in the export archive’s and every install package’s README.
Caveat for hosted brains: the platform runs the container, so obligations around illegal material on its infrastructure (notice-and-takedown, lawful requests) still apply. Hosted terms must say the platform will suspend or delete a hosted noggin on a valid legal notice, and this section should be reviewed by a solicitor before the hosted tier opens.
Security and sovereignty controls
- Pairing, not accounts, for brains. The brain prints a one-time code or accepts a console pairing token; tokens can be listed and revoked from the brain.
- Encryption at rest for
memory.db,runs.dband provider keys with a key derived from the owner’s passphrase; the export archive uses the same passphrase. - Transport: TLS always, through a per-noggin Cloudflare Tunnel with no inbound port on the host, so phones need only a browser; the brain refuses everything without its bearer token. Cloudflare terminates TLS at its edge and so could technically read traffic in transit; the owner accepts this by default, and can turn on end-to-end encryption (milestone 05b) so message content crosses Cloudflare only as ciphertext.
- Egress control: the connectors and read tools are the only code paths allowed outbound, and every call is written to
runs.dbbefore it is sent. - Redaction pass before a
asksvoice sends anything out. - Memory inspection: the owner can list, search and delete anything a voice remembers.
- Leave with everything: export is always available and the archive is plain SQLite, YAML and Markdown once decrypted.
Decisions and v1 scope
V1 proves the loop: pair a phone, create a voice, chat and talk, see the cost, rate the reply, move the brain to another host.
In v1: pick a voice, chat and talk screens as a React PWA; voice files with local, asks, web and scoped memory; rule-based router with memory and feedback as inputs, cost logging and a monthly cost view; session adviser; starter templates and install packages; brain availability in console and app; Ollama locally with a 3–4B default model and an 8B upgrade, plus Anthropic and one OpenAI-compatible connector; feedback with promote-to-memory; scheduler; export, import and re-pair.
Left out of v1: Produce and Draft tools; voices talking to each other; learned router weights acted on (stage 2) and the intelligent classifier (v2); native iOS and Android builds; GPU hosting tiers; hosted brains until a provider is enabled.
Decided: React web app; Python brain; CPU-first hardware; scheduler in v1; asks once per session; brain-side Whisper offered; sqlite-vec in memory.db; Anthropic plus one OpenAI-compatible adapter at launch; Cloudflare as edge and DNS; compute provider deferred to Ops; ops sign-in domain-locked; the brain never acts; mouthpiece stores only token and address.