- Five HUB_TOKEN_* keys added to the host secrets file (mode 600, backup kept). - docker compose up -d --build recreated the hub container on :8788 with the AUD-49 image (central-ai-hub:local, sha256:f6b773c8a33a), user 1000:100. - Verified: /health ok with omniroute ok, control action refused, bad token 401, container healthy. Co-Authored-By: Paperclip <noreply@paperclip.ing>
Central AI Hub
One small service that every way in reaches every ability through. Built once, shared by the phone app, the house voice, chat, and the admin app.
Demonstrated Skills & Tech Stack
- Core Technologies: Go 1.25 service · HTTP JSON API · MQTT · LLM intent routing · OmniRoute gateway · Docker
- Entry routes:
POST /ask·POST /approve·GET /health(frozen indocs/hub-api.md) - Key Tools: Jervis (voice) · Home Assistant · Paperclip · Artemis · internet use control · Apprise / NTFY · OmniRoute
- Engineering Capabilities: service design · intent routing · authorization and approval flows · event-driven integration · deterministic safety for high-consequence actions
Quick Start
Run the Hub
# Build and run the container (Docker host 192.168.20.13).
docker compose up -d --build
# Liveness (no token).
curl -s http://192.168.20.13:8788/health
# Ask a question (source esp32 speaks the reply on the house speakers).
curl -s -X POST http://192.168.20.13:8788/ask \
-H "Authorization: Bearer $HUB_TOKEN_ESP32" \
-H "Content-Type: application/json" \
-d '{"text":"what does Harry have on today?","asker":"sam","source":"esp32"}'
The Hub reads HUB_TOKEN_*, OMNIROUTE_API_KEY, and the project tokens from
~/.config/environment.d/10-secrets.conf (mounted read-only, never committed).
Add the five Hub client tokens with the idempotent script
scripts/provision-hub-tokens.sh; it keeps mode 600 and never prints a value.
A new token needs Sam's OK (AGENTS.md "ask first: credentials").
Test without a network
scripts/hub-test.sh
The fake /ask project in src/tests/fakeproject/ proves the round trip.
Phase 1 — prove the Paperclip round trip
# 1. Create an agent API key in Paperclip.
# 2. Export it for the test only.
export PAPERCLIP_API_KEY=<redacted>
# 3. File one job.
scripts/paperclip-roundtrip.sh --title "round-trip test"
Full steps: docs/outline/04-agent-runbook.md.
System Architecture
flowchart LR
subgraph IN["Ways in"]
PHONE["Phone app<br/>wake word + voice"]
ADMIN["Admin app<br/>restricted actions"]
ESP["ESP32 voice<br/>Hey Jervis"]
DSH["dsh chat"]
CONSOLE["Console portal"]
end
HUB{{"HUB<br/>hear - understand - check - route - answer"}}
subgraph OUT["Peers and services<br/>(the Hub is not a destination)"]
HA["Home Assistant"]
SPK["Speakers<br/>Jervis TTS"]
NET["Internet control<br/>parental limits"]
ART["Artemis<br/>phone screen"]
PC["Paperclip<br/>work bench"]
WEB["Web search"]
APP["Apprise / NTFY"]
end
PHONE --> HUB
ESP --> HUB
DSH --> HUB
CONSOLE --> HUB
ADMIN --> HUB
HUB --> HA
HUB --> SPK
HUB --> ART
HUB --> WEB
HUB --> APP
HUB -- "ask only (query)" --> NET
HUB -- "slow job (approved)" --> PC
ADMIN -- "control + tap to approve" --> NET
PC -. result .-> HUB
Interactive architecture map: maps.lab.audasmedia.com.au/central_ai_llm_master
Usage & Configuration
- Model calls go through OmniRoute at
http://192.168.20.13:20129/v1. - Secrets come from
~/.config/environment.d/10-secrets.conf. - Paperclip is at
http://192.168.20.13:3100. An API key is required. - Home Assistant is at
http://192.168.20.30:8123. - Jervis (voice) is at
http://192.168.20.13:8501. - Hub is at
http://192.168.20.13:8788(local Docker container).
The design brief is hub_brief.md. Project instructions are AGENTS.md.
The interface between the Hub and every data project is docs/ask-contract.md.
The frozen inbound API (ways in to the Hub) is docs/hub-api.md.
Every other project is a peer, not a sub-project. A high-consequence control
(for example, cutting the kids' internet) does not route through the Hub.