245 lines
10 KiB
Markdown
245 lines
10 KiB
Markdown
# The Hub — a short brief
|
|
|
|
**Purpose:** tell every project where it fits and the rules it must follow.
|
|
**Written:** 2026-10-10
|
|
**Status:** agreed direction, not a build order.
|
|
|
|
---
|
|
|
|
## The idea in one line
|
|
|
|
**Share the plumbing. Keep the brains separate. Put one small hub in the middle.**
|
|
|
|
Every way in (phone, house voice, chat) reaches every ability (lights, internet,
|
|
Artemis, Paperclip) through one place — built once, not repeated.
|
|
|
|
---
|
|
|
|
## What already works (do not rebuild)
|
|
|
|
| System | What it is |
|
|
|---|---|
|
|
| **Jervis** | The house voice. ESP32 "Hey Jervis" → STT → agent → TTS → speakers. Controls HA, timers, reminders, shopping, calendar, music, weather, web search, family messages. |
|
|
| **dsh** | Per-person chat (sam / jo / harry / finn). Memory, images, video, documents. |
|
|
| **Console portal** | Logins and dashboard for the family. |
|
|
| **Front Door Cam** | Its own separate ESP32. Visitor detection, Gemini sees the person, voice asks them to speak. |
|
|
| **OmniRoute** | The model gateway. All models go through here. |
|
|
| **Home Assistant** | Devices, timers, calendar, notifications. |
|
|
| **Shared** | Apprise, Snapcast, STT/TTS, n8n, secrets in `environment.d`. |
|
|
|
|
These stay. The hub is added, not a replacement.
|
|
|
|
---
|
|
|
|
## What is new
|
|
|
|
Each of these is a **separate project**. Each has its own folder, repo, port,
|
|
interface, and build. The Hub never owns them.
|
|
|
|
- The **Hub** (this brief) — a shared way in and a router. Not a brain.
|
|
- **Email agent** — scans and logs the inbox. Answers questions. Own pipeline.
|
|
- **School (Compass / Teams)** — scans school data. Answers questions. Own pipeline.
|
|
- **Internet use control** — its own service and information portal. Enforces limits.
|
|
- **Artemis** — its own service. Operates the phone screen.
|
|
- **Kotlin phone app** — a new way in (wake word, voice).
|
|
- **Admin app + kids app** — control and confirmation, admin only.
|
|
|
|
---
|
|
|
|
## What the Hub is
|
|
|
|
One service that does five steps:
|
|
|
|
1. **Hear** — takes voice or text from any way in.
|
|
2. **Understand** — the LLM works out what was asked.
|
|
3. **Check** — is this person allowed to ask for this?
|
|
4. **Route** — sends it to the right destination.
|
|
5. **Answer** — returns a short reply in the right shape for the device.
|
|
|
|
The reply can be **text**, **spoken audio (TTS)**, **Artemis commands**, **a phone
|
|
notification**, **an email**, or a mix. TTS can play on the **house speakers** or
|
|
on the **phone**.
|
|
|
|
When a question is about another project's data, the Hub **asks that project** and
|
|
returns the answer. See `docs/ask-contract.md`.
|
|
|
|
## Three directions
|
|
|
|
Nothing here is ownership. These are directions of talk.
|
|
|
|
1. **The Hub asks a project.** "What is important in my inbox?", "What does Harry
|
|
have on today?", "How long have the kids been on screens?"
|
|
2. **A project tells the Hub.** "Overdue homework found.", "3 emails need a
|
|
decision."
|
|
3. **n8n triggers the project.** Scan the inbox. Scan the school. Enforce the
|
|
schedule.
|
|
|
|
The projects keep their own interfaces. The Hub is an **extra** way in.
|
|
|
|
### What the Hub is NOT
|
|
|
|
- **Not a central brain.** It does not hold one personality or one memory.
|
|
- **Not Paperclip.** It never waits minutes for an answer.
|
|
- **Not a destination.** It does not turn off the internet itself. It sends the
|
|
request to the service that does.
|
|
|
|
### The dividing line
|
|
|
|
One question sorts every request:
|
|
|
|
> **Does this need a decision, or does it need to happen?**
|
|
|
|
- **Happen** (fast, certain) → straight to the destination: HA, internet control,
|
|
Artemis, speakers. No LLM in the path of the action.
|
|
- **Decision** (slow, multi-step, worth recording) → Paperclip.
|
|
|
|
**Paperclip is the work bench, not the switchboard.** It is never in the path of
|
|
a fast or high-consequence command.
|
|
|
|
### Query, command, or control
|
|
|
|
| Kind | Example | Path | Confirm? |
|
|
|---|---|---|---|
|
|
| **Query** (read) | "What does Harry have on today?" | Hub → project (`/ask`) | No |
|
|
| **Command** (do it now) | "Turn on the lounge light." | Hub → Home Assistant | No |
|
|
| **Control** (high consequence) | "Cut the kids' internet." | Admin app → internet control | **Yes, on the phone** |
|
|
|
|
A query goes through the Hub. A high-consequence control does **not**. The admin
|
|
app talks to the internet control service directly. Voice may start it. Only the
|
|
admin app confirms.
|
|
|
|
### Routing
|
|
|
|
The Hub must decide which project to ask. It uses three things:
|
|
|
|
1. **A capability list.** Each project declares the topics it can answer. The Hub
|
|
collects this automatically. See `docs/ask-contract.md`.
|
|
2. **A rules file.** `routing.md` in the Hub. A human edits it. It holds the
|
|
judgment calls: topic → project, the preferred project when two overlap, and
|
|
things the Hub must never route.
|
|
3. **An LLM.** It reads the question, the capability list, and the rules file. It
|
|
returns one of four answers:
|
|
- **route** — send to one project.
|
|
- **fanout** — ask several projects, then merge ("what do I have on today?").
|
|
- **clarify** — ask the user a short question ("school or email?").
|
|
- **no_match** — say it does not know.
|
|
|
|
The rules file is **not** `AGENTS.md`. `AGENTS.md` tells coding agents how to work.
|
|
`routing.md` tells the running Hub how to choose. Keep them separate.
|
|
|
|
The Hub never routes a control action. Those go through the admin app.
|
|
|
|
### Observability
|
|
|
|
The Hub writes one append-only log. It records every request: time, source,
|
|
question, the routing answer, the project asked, the latency, and the reply shape.
|
|
|
|
- **Append only.** Never edit a line.
|
|
- **Cap the size.** Rotate at a fixed size. Keep a fixed number of days.
|
|
- **No secrets.** Never log tokens.
|
|
- **No full personal data.** Log the question and the route, not the inbox.
|
|
|
|
---
|
|
|
|
## Where each system fits
|
|
|
|
Each project is a **peer**. These are talk directions, not ownership.
|
|
|
|
| System | Relation | Talk direction |
|
|
|---|---|---|
|
|
| **Jervis** | House voice. Peer. | Becomes voice-only. Its tools move into the Hub over time. |
|
|
| **dsh** | Chat. Peer. | Calls the Hub for actions. Keeps its own chat. |
|
|
| **Console portal** | Login and dashboard. Peer. | Unchanged. May show Hub status and approvals. |
|
|
| **Front Door Cam** | Visitor intercom. Peer. | Separate. May use the Hub to speak. |
|
|
| **Email agent** | Separate pipeline. Peer. | Hub asks it (`/ask`). It tells the Hub (`/notify`). n8n scans it. |
|
|
| **School agent** | Separate pipeline. Peer. | Hub asks it (`/ask`). It tells the Hub (`/notify`). n8n scans it. |
|
|
| **Internet control** | Separate service and portal. Peer. | Hub **asks** it. **Control goes through its own apps, not the Hub.** |
|
|
| **Artemis** | Separate service. Peer. | Hub calls it to act. Nothing comes back. |
|
|
| **Paperclip** | Work bench. Peer. | The Hub files jobs and hears the answer. |
|
|
| **Phone app** | Way in. | Sends voice to the Hub. Shows replies and approvals. |
|
|
|
|
---
|
|
|
|
## Rules every project follows
|
|
|
|
1. **All models go through OmniRoute.** Never call a provider directly.
|
|
2. **All secrets come from `environment.d`.** Never hard-code.
|
|
3. **Own service, own port, own folder.** Do not merge into another project.
|
|
4. **No LLM in the path of a fast or consequential action.** Deterministic calls
|
|
for anything that turns something off.
|
|
5. **Paperclip only for slow, multi-step, recorded work.** Never make a person
|
|
wait on it.
|
|
6. **Replies return to the source, and stay short.** Speaker → one line. Phone →
|
|
notification. Chat → text. No long-winded answers.
|
|
7. **Restricted commands need tap-to-approve** on the admin app. This includes
|
|
parental controls and any job filed to Paperclip.
|
|
8. **Only the admin app can change parental controls.** Kids' apps and desktop
|
|
exes may only obey and report.
|
|
9. **New work registers with the Hub.** A capability is added once, and every way
|
|
in gets it.
|
|
10. **A data project answers `/ask` read-only.** It never changes state on a query.
|
|
11. **High-consequence control does not route through the Hub.** The admin app
|
|
calls the service directly.
|
|
|
|
---
|
|
|
|
## Safety
|
|
|
|
- **Voice is shared and unauthenticated.** Anyone in the house can speak.
|
|
- **The admin app is the only trusted door** for restricted actions.
|
|
- **A spoken keycode is not the lock.** It can be overheard and misheard. Voice
|
|
may *ask*; the admin app **confirms** with "Did you ask for this?".
|
|
- **Approval is required** for parental controls and Paperclip jobs.
|
|
- **One identity: Sam.** The Hub serves Sam only. The `/ask` contract keeps the
|
|
`asker` field, so a second person can be added later.
|
|
- **Voice is spoken aloud.** With one identity, anyone in the house could imitate
|
|
Sam. Consequential actions are protected by the admin-app tap, not by the voice.
|
|
|
|
---
|
|
|
|
## Build order
|
|
|
|
0. **Agree the `/ask` contract.** Both sides build to `docs/ask-contract.md`.
|
|
Nothing else starts until this is frozen.
|
|
1. **Thin slice, end to end.** Issue a Paperclip API key, file one job from a
|
|
script, and get the result announced back. Proves the round trip.
|
|
2. **Hub skeleton.** Hear → understand → route → answer, against a **fake**
|
|
project that speaks `/ask`. One real destination (speakers).
|
|
3. **Identity.** Decide how the Hub knows who is speaking.
|
|
4. **Approval flow.** "Did you ask for this?" on the admin app.
|
|
5. **One real data project** to the contract (email or school). Prove `/ask`.
|
|
6. **Internet control.** Separate service and portal. Control stays app-only.
|
|
7. **Artemis.** Separate service. Screen control only.
|
|
8. **Move Jervis's tools** into the Hub. Jervis becomes voice-only.
|
|
9. **Phone Kotlin app.** Wake word, voice to the Hub, replies and approvals.
|
|
10. **Remaining pipelines** connect when ready.
|
|
|
|
---
|
|
|
|
## What is still open
|
|
|
|
1. **Approval service.** One shared mechanism, or one per project? (See below.)
|
|
2. **Service tokens.** One bearer token per project, stored in `environment.d`.
|
|
3. **Job contract.** Exact fields for a Paperclip job (title, brief, project, agent).
|
|
4. **Artemis voice.** Stream or file. When does phone TTS get used?
|
|
5. **Paperclip layout.** One company or several. Which projects.
|
|
6. **Routing rules.** The first draft of `routing.md`.
|
|
|
|
### The approval question
|
|
|
|
Three things need a human "yes":
|
|
|
|
- cutting the kids' internet (admin app),
|
|
- filing a Paperclip job (Hub → Paperclip),
|
|
- a project writing to the calendar (email adds an event, school books an
|
|
interview).
|
|
|
|
Two options:
|
|
|
|
- **One shared approval.** The Hub (or a tiny approvals service) sends the request
|
|
to the admin app, you tap, it runs. One mechanism, one UI.
|
|
- **One per project.** Each project asks in its own way. Simpler now, more to
|
|
maintain later.
|
|
|
|
Recommended: **one shared approval.** The admin app already exists.
|