Imported from aymuos15/anima (
AGENTS.md). Install upstream withnpx skills add aymuos15/anima. Copyright stays with the author.
AGENTS.md
Everything needed to run and change this project locally. Read this before touching code. Local-only: do not deploy. Use only gpt-5.6-luna with low reasoning through Codex OAuth; no Gemini or API-key fallback.
What this is
An NHS App style patient view (public/index.html) over a synthetic NHS neighbourhood simulator, with an AI care team agent that reads the patient's records and proposes actions the patient approves. A staff operations console (public/admin.html) sits beside it. All data is synthetic.
Local: http://127.0.0.1:8790/ (patient app) and http://127.0.0.1:8790/admin (console).
Layout
| Path | What |
|---|---|
public/ |
Static frontend. index.html patient app, admin.html console, pathway.css. No build step, plain HTML and JS. |
agent/server.ts |
HTTP API and local static server. One file, string-matched routes. |
agent/pathway.ts |
Deterministic pathway builder: reads every site for a patient, infers stage, blockers, medicines, letters, repeats. |
agent/agents.ts |
The two ADK agents (patient, admin) and their system prompts. |
agent/tools/ |
ADK tools. read.ts read-only, write.ts actions that pause for approval, admin.ts console tools. |
agent/sim.ts |
Simulator client. |
agent/app.ts |
ADK app and session store selection. |
agent/data/ |
cohort.json (generated by npm run build:data) and examples.json (hand-curated patient stories). Bundled into the function. |
agent/test/ |
Smoke test against the live simulator. |
netlify/functions/api.mjs |
Netlify function entry. Starts the Node server on a loopback port and proxies /api/* to it. |
scripts/codex-proxy.ts |
Developer-only proxy to use a Codex CLI login as an OpenAI endpoint. Never deployed. |
docs/ |
Architecture notes and the curated pathway examples. |
Run locally
Requires Node 22 (.nvmrc).
npm install
# simulator key: create or join a world, copy apiKey into agent/key-agent.txt
curl -s https://sim.animahacks.com/api/keys -H 'Content-Type: application/json' -d '{"teamName":"my-team"}'
# Sign in to Codex CLI first. Starts or reuses the local OAuth proxy automatically.
npm run dev
Open http://127.0.0.1:8790/ (press Continue, Ctrl+K switches patient) or http://127.0.0.1:8790/admin.
Sessions go to agent/sessions.db locally. ADK_STORE=memory skips the file. HTML is read per request, so frontend edits need only a refresh. Backend edits need a restart.
Environment variables
| Variable | Where | Meaning |
|---|---|---|
SIM_KEY |
Netlify (secret). Local: agent/key-agent.txt instead |
Simulator API key |
CODEX_PROXY_PORT |
Local | Default 8788. Proxy uses the Codex CLI OAuth login. Model fixed to gpt-5.6-luna, reasoning low. Provider/model/API-key environment overrides are not used. |
DATABASE_URL |
Netlify (secret) | Postgres connection string for sessions. Must be the Supabase pooler host (see Deploy). Unset locally. |
ADK_STORE |
Optional | memory to disable persistent sessions |
PORT |
Local only | Default 8790 |
Never commit keys. key.txt, agent/key-agent.txt, .env* are ignored.
Checks
npm run typecheck # tsc, also runs in the Netlify build
npm test # builds five featured pathways against the live simulator
npm run build # typecheck + bundle the function into netlify/functions-dist
Historical deployment notes (inactive — do not deploy)
Netlify serves public/ from its CDN and runs agent/server.ts inside one function for /api/*. Supabase Postgres holds chat sessions. The ADK store creates its own tables on first use, so there are no migrations.
Why the function is pre-bundled: Netlify's own bundlers cannot handle the ADK package. Its tracer crashes on the ADK's ESM build and its CommonJS path pulls in playwright. So npm run build:fn bundles everything with esbuild into one ESM file and netlify.toml uses node_bundler = "none". Browser-related packages are marked external because the ADK only loads them lazily for browser tools we do not use.
Steps on a new machine:
npm i -g netlify-cli supabaseand log in to both.netlify linkto the site,supabase link --project-ref <ref>.- Historical deployment required simulator, model and database credentials. The current local OAuth configuration is not deployable.
DATABASE_URLmust use the session pooler, port 5432, because Netlify functions have no IPv6 and the directdb.<ref>.supabase.cohost is IPv6-only:postgresql://postgres.<ref>:<db-password>@aws-1-eu-west-1.pooler.supabase.com:5432/postgres?sslmode=requireThe password is set in the Supabase dashboard under Database settings. netlify deploy --prodfrom the repo root, or pushmainif the site is connected to GitHub.- Check:
curl https://<site>/api/patients/SIM-000009/pathwayreturns JSON, then a chat turn:curl -X POST https://<site>/api/chat -H 'content-type: application/json' -d '{"patientId":"SIM-000009","input":{"message":"start"}}'A response with"status":"error"carries the underlying message inerror.
Known limits: a chat turn takes 5 to 20 seconds and is not streamed. The pathway cache is per function instance, so cold starts are slow. Netlify's function timeout may need raising on the account if turns exceed it.
Simulator API
- Base
https://sim.animahacks.com,Authorization: Bearer <key>. OpenAPI at/api/openapi.json, handbook at/docs/handbook.json. - Sites:
gp,hospital,pharmacy,community,diagnostics,wearables,referrals. One fixed neighbourhood per world. GET /api/sites/{site}/patients?q=(30 per page).GET /api/sites/{site}/view?patient=SIM-000001&limit=500.POST /api/sites/{site}/actions.POST /api/clock {"paused":true,"advanceMinutes":N}.POST /api/keys {"teamName"}creates or joins a world. Same name, same world. New name for a clean run.- Actions need a UUID
clientRequestId. Versioned updates sendexpectedVersion. Capacity exhaustion and stale versions return 409. Staff-management actions are locked for our key. - There is no pathway concept in the API.
agent/pathway.tsderives it: records are mapped to stages by kind, sorted by date, and open or rejected records become blockers. The patient app relabels the five stages as Referred, Booked, Preparation, Procedure, Post-op care.
Conventions
- Read-only by default. Every write tool and
advance_clockyields for approval before touching the simulator. - Never invent records. Agent prompts live in
agent/agents.ts. - Mohammed's Preparation checklist is curated in
agent/preparation.tsand shared through the pathway response with the UI and agent. It is demo data, not simulator orders/results. - Featured demo patients are listed in
agent/tools/admin.tsand repeated in the two HTML files. Keep them in sync. - Rebuild cohort statistics with
SIM_KEY=... npm run build:datawhen the world changes materially.