Files
central_ai_llm_master/docs/outline/04-agent-runbook.md
Sam Rolfe bf80efa25d AUD-49: build the Hub skeleton (hear-route-answer)
- Three inbound routes from docs/hub-api.md: POST /ask, POST /approve, GET /health.
- Five-step pipeline in src/hub, with packages hear, understand, check, route, answer.
- Routing through OmniRoute with the capability list and routing.md. The
  never-route control check runs before any LLM call.
- One real destination: Jervis house TTS, started out of band.
- Fake /ask project (src/tests/fakeproject) for the round-trip test.
- Append-only, size-capped request log. Bearer auth, source match, rate limit.
- Tests: all packages pass, including the fake /ask round trip. Race clean.
- Dockerfile and compose updated to mount routing.md and secrets, log on tmpfs.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-10 17:38:48 +11:00

5.9 KiB

Central AI Hub — AI Agent Runbook

Writing Style: ASD-STE100 Simplified Technical English (ste-writing).

Phase 1 — Prove the Paperclip Round Trip

This phase has no Hub code. It proves the missing link: a job that leaves and a result that returns.

Steps

  1. Create a Paperclip agent API key for this project. DONE.
    • Paperclip board: http://192.168.20.13:3100.
    • Agent: Hub, id 108c6220-c9e1-4b62-9e0a-6a763e0d28fd.
    • Key name: hub-service.
    • The key is stored in /home/sam/.config/environment.d/10-secrets.conf as PAPERCLIP_API_KEY. Never commit it.
    • Verification: GET /api/agents/me with the key returns 200 and the name Hub.
    • Note: POST /api/agents/{id}/keys is board-only. A run JWT gets 403 Board access required. Mint keys with the local board key.
  2. File one job with the round-trip script. The script uses the issue-create endpoint: POST /api/companies/{companyId}/issues.
    • The old POST /api/issues route does not exist. It returns 404.
    • Company id: d4921013-e5da-4d88-8016-57d5746e2d03.
    • Script: scripts/paperclip-roundtrip.sh.
  3. Confirm the job appears in the Paperclip board. DONE.
    • The first job is AUD-55, id d58891ce-9934-4710-9bba-d37974251ed9.
  4. Wait for the agent to close the job. DONE.
    • AUD-55 closed as done at 2026-10-10T06:21:03Z.
    • The agent comment on AUD-55: "The Hub round trip works."
  5. Send the result to Jervis POST /announce so the house speaks it. DONE.
    • See the announce call and the response below.
  6. Record the result in this file. DONE.

Commands

# File one job with the script. It reads PAPERCLIP_API_KEY from the
# environment, then from ~/.config/environment.d/10-secrets.conf.
scripts/paperclip-roundtrip.sh \
  --title "Hub round-trip job: confirm the return path" \
  --description "Prove the outbound Paperclip path." \
  --assignee 403de1f7-645c-4d35-bc7e-19b01d77bacc \
  --priority high \
  --project 7ae791bb-8d9a-462f-99bf-013421d20623

# Speak the result.
curl -sS -X POST http://192.168.20.13:8501/announce \
  -H "Content-Type: application/json" \
  -d '{"text":"The Hub round trip works."}'

Recorded Result — 2026-10-10

The round trip works. This table holds the proof.

Item Value
Key source PAPERCLIP_API_KEY in /home/sam/.config/environment.d/10-secrets.conf
Key name hub-service
Agent Hub, id 108c6220-c9e1-4b62-9e0a-6a763e0d28fd
Job identifier AUD-55, id d58891ce-9934-4710-9bba-d37974251ed9
Job result "The Hub round trip works."
Job final status done, at 2026-10-10T06:21:03Z
Announce call POST http://192.168.20.13:8501/announce
Announce response HTTP 200, text "The Hub round trip works."

The script wrote this line to .state/paperclip-roundtrip-issues.log:

2026-10-10T06:20:48Z	d58891ce-9934-4710-9bba-d37974251ed9	AUD-55

Note: Jervis has no playback-telemetry endpoint. Thus the HTTP 200 code and the spoken reply are the strongest available proof of the announce. The announce ran one time.

Definition of Done

  • The job appears in Paperclip. DONE.
  • The job closes. DONE.
  • The house speaks the result. DONE.
  • This file records the result. DONE.

Phase 2 — Hub Skeleton (AUD-49)

This phase builds the Hub itself. The shape is frozen in docs/hub-api.md. The code layout is in docs/outline/03-code-map.md.

What was built

  • POST /ask, POST /approve, and GET /health.
  • The five steps: hear → understand → check → route → answer.
  • Routing through the LLM at OmniRoute, with the capability topics and routing.md.
  • The never-route check runs before the LLM. A control action never reaches a model.
  • One real destination: the house speakers (Jervis /announce).
  • A fake /ask project for tests and manual runs.

Test command

docker run --rm -v "$PWD/src":/src -w /src golang:1.25-alpine go test ./...

Result on 2026-10-10: all packages pass, including the fake /ask round trip.

Live round trip

The Hub ran on port 18788 with HUB_PROJECTS="compass_nhs=http://127.0.0.1:9199" and the fake project on 9199. The real OmniRoute LLM chose the project. Jervis spoke the reply on the house speakers.

Request:

{
  "text": "what does Harry have on today?",
  "asker": "sam",
  "source": "esp32",
  "device": "kitchen-esp32",
  "request_id": "01AUD49PROOF"
}

Response:

{
  "status": "ok",
  "request_id": "01AUD49PROOF",
  "answer": "Harry has maths and a music lesson today.",
  "shape": "speech",
  "speech": {"text": "Harry has maths and a music lesson today.", "target": "house"},
  "route": {"kind": "project", "project": "compass_nhs"}
}

Hub stdout (evidence):

router: model=gpt-4o-mini status=200 elapsed=1.554598547s
speakers: announced 41 chars

The routing LLM answered in 1.5 s (inside the 3 s cap). The house announcement ran out of band and Jervis returned HTTP 200. Jervis has no playback telemetry, so the HTTP 200 and the spoken reply are the strongest available proof.

Control action proof

"cut the kids internet" returned status: "refused", route.kind: "refused", route.reason: "high_consequence_control". No LLM call ran for that request. The unit test TestControlActionNeverReachesLLM asserts the zero call count.

Deploy note

The docker-compose.yml mounts routing.md and the secrets file read-only, and uses a /tmp tmpfs for the log. To deploy: build the image, then restart the container. A HUB_TOKEN_* key per client must exist in the secrets file first.

After Phase 1

Follow the build order in AGENTS.md. Do not start a destination before the round trip works.

Health Checks

curl -s http://192.168.20.13:3100/health        # Paperclip
curl -s http://192.168.20.13:8501/health        # Jervis
curl -s -o /dev/null -w '%{http_code}\n' http://192.168.20.30:8123/   # HA