diff --git a/AGENTS.md b/AGENTS.md index 4876a33..8e030eb 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -54,6 +54,11 @@ See `docs/ask-contract.md`. The Hub never learns a project's data model. 10. A data project answers `/ask` read-only. Never change state on a query. 11. High-consequence control does not route through the Hub. The admin app calls the service directly. +12. Route with the capability list, `routing.md`, and the LLM. Ask the user when + unsure. Never route a control action. +13. Log every request. Append only. Cap the size. No secrets, no full personal + data. +14. There is one identity: Sam. Keep the `asker` field for a future second person. ## Build order diff --git a/docs/ask-contract.md b/docs/ask-contract.md index 3afdba6..3f1b3da 100644 --- a/docs/ask-contract.md +++ b/docs/ask-contract.md @@ -23,13 +23,25 @@ own interface, or through an approval flow. Never through `/ask`. ## Endpoint -Every data project exposes two endpoints on its own port: +Every data project exposes three endpoints on its own port: ``` GET /health -> {"ok": true} +GET /capabilities -> the topics this project can answer POST /ask -> answer a question about this project's data ``` +## Capabilities (for routing) + +The Hub reads this list to choose a project. + +```json +{ "project": "email_agent", "topics": ["email", "inbox", "mail"], "people": ["sam"] } +``` + +Keep the topic list short and plain. The Hub uses these topics plus `routing.md`. +Do not put private data in this list. + ### Request ```json @@ -74,7 +86,7 @@ Never guess. Never invent. Say `reason` instead. ## Rules for the project -1. **Read only.** `/ask` never writes anything. +1. **Read only.** `/ask` never writes anything. `/capabilities` never writes. 2. **Answer for one person at most.** Check `asker` may see `person`. 3. **One short sentence.** No lists unless asked. 4. **Fast.** Answer in under 3 seconds, or return `answer: null`. diff --git a/docs/outline/01-system-overview.md b/docs/outline/01-system-overview.md index 0a524db..08357b3 100644 --- a/docs/outline/01-system-overview.md +++ b/docs/outline/01-system-overview.md @@ -64,6 +64,18 @@ interface. Each works without the Hub. A high-consequence control does not route through the Hub. +## Routing + +The Hub picks a project with three things: a capability list from each project, a +human-editable `routing.md`, and an LLM. The LLM returns one of four answers: +route, fanout, clarify, or no_match. When it is unsure, it asks the user a short +question. It never routes a control action. + +## Observability + +The Hub writes one append-only log. It records the request, the route, the project +asked, and the latency. The log is capped. It holds no secrets. + ## Reply Shapes The Hub returns one reply. The reply can hold text, spoken audio (TTS), Artemis diff --git a/hub_brief.md b/hub_brief.md index 7996b0f..e3cdc3d 100644 --- a/hub_brief.md +++ b/hub_brief.md @@ -108,6 +108,37 @@ 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 @@ -159,8 +190,10 @@ Each project is a **peer**. These are talk directions, not ownership. - **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. -- **Identity is not solved yet.** Voice has no identity. Personal data (inbox, - school, screen time) needs it. See open items. +- **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. --- @@ -185,14 +218,27 @@ Each project is a **peer**. These are talk directions, not ownership. ## What is still open -1. **Identity.** How does the Hub know who is speaking? Voice has none. This is - the top gap, because personal data now flows. -2. **Routing.** How does the Hub pick the project to ask? A small capability - registry, or an LLM choice. -3. **Overlap.** "What do I have on today?" may match several projects. Ask one, - or ask all and merge? -4. **Approval service.** One shared mechanism, or one per project? -5. **Service tokens.** One bearer token per project, stored in `environment.d`. -6. **Job contract.** Exact fields for a Paperclip job (title, brief, project, agent). -7. **Artemis voice.** Stream or file. When does phone TTS get used? -8. **Paperclip layout.** One company or several. Which projects. +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.