← Home

Guide

How to use the coach, how it is built, and how to run it yourself. The coach is grounded in a science-based fitness and nutrition curriculum. Search or filter by who you are.

For users

What Fit T. Cent 3.0 (Centenarian Coach) is

A multi-agent health coach. You ask one question; a supervisor decides which specialists to consult, each specialist searches its own knowledge base, and a synthesizer weaves their findings into one answer with citations.

The coach is grounded in a science-based fitness, nutrition, and corrective-exercise curriculum. Answers cite real passages from those source materials rather than relying on generic model knowledge.

For users

The four specialists

A question is routed to one, several, or all four specialists, depending on what it touches:

  • Nutrition: diet, macros, protein, calories, supplements, eating patterns, fasting.
  • Workout: strength training, cardio, exercise programming, progression, periodization.
  • Recovery: sleep, HRV, rest days, stress, and readiness.
  • Corrective Exercise: movement assessment, postural imbalances, mobility, flexibility, SMR / foam rolling, and region-specific corrective strategies.

For users

How to ask a good question

Plain language works. Cross-domain questions are where the multi-agent design earns its keep, because the supervisor can fan out to several specialists and the synthesizer connects their advice.

  • "How much protein should a 70-year-old eat to preserve muscle?" routes to Nutrition.
  • "I slept five hours; should I still train legs today?" routes to Workout plus Recovery.
  • "My knees cave in when I squat. How do I fix it?" routes to Corrective Exercise.
  • "I want to build muscle: how should I combine eating, training, and recovery?" can pull all four.

For users

Reading the answer

Each run shows the supervisor's routing rationale, which specialists were consulted (with timings), and the synthesized answer. Citations are grouped per specialist and toggled open under the answer, so you can see the source label behind each claim.

When LangSmith tracing is enabled, the run also surfaces a trace id so the full agent run can be inspected.

For users

Browsing past sessions

The history page lists recent coaching sessions, newest first, with a live fuzzy search over the question text and answer. Select one to see how it was routed and what each specialist found.

Coaching history

For users

Access

This is a single-admin demo: only the owner's email can sign in and run the coach. Anyone else can join a waitlist from the sign-in page. This guide, however, is fully public.

How it's built

Three LangGraph patterns

The repo is a teaching example of three patterns that show up in most production agent systems:

  • Supervisor routing: a typed, structured routing decision (via Zod withStructuredOutput) before any specialist runs.
  • Per-agent retrieval: each specialist owns an isolated pgvector namespace, so nutrition never sees workout documents.
  • State passing across nested subgraphs: a shared CoachState where each specialist writes only its own slot.

How it's built

The graph

supervisor -> fan-out to the chosen specialists (run in parallel) -> synthesize -> final answer. Each specialist is itself a compiled subgraph: retrieve -> assess -> (tools) -> compose. Specialists cannot read each other's findings; only the synthesizer sees them all.

How it's built

Tech stack

  • Next.js 16 (App Router) + TypeScript strict.
  • LangGraph 1.x for the supervisor + specialist subgraphs.
  • Drizzle ORM over Neon Postgres with the pgvector extension.
  • Auth.js v5 (email magic link), single-admin gated.
  • Seven switchable LLM providers; Gemini or Ollama for embeddings.
  • NDJSON streaming from a Next route handler; Vitest for tests + evals.

How it's built

Engineering decisions worth noting

  • Provider schema-subset mismatch: a Zod .positive() compiled to JSON Schema's exclusiveMinimum, which Gemini's structured-output subset rejects. Swapped for an inclusive .min(1).
  • Gemini embedding quota walls (100/min, ~1000/day on free tier) made large corpora impractical, so the embedding backend is swappable to a local Ollama model with no rate limit.
  • PDF text occasionally carries NUL bytes that Postgres text columns reject; the seed sanitizes C0 control characters.
  • Meet-in-the-middle seeding: a doc_index column lets two machines split one namespace and each resume independently.
  • Runtime model config: provider and per-role models are editable from /admin with no redeploy.

How it's built

The five-lesson curriculum

Run it yourself

Setup

Clone, install, configure, and migrate. pnpm 11 requires approving the postinstall scripts (esbuild, sharp, msw, unrs-resolver); that approval already ships in package.json.

git clone https://github.com/dapperAuteur/centenarian-coach-multiagent.git
cd centenarian-coach-multiagent
pnpm install
cp .env.example .env.local   # fill in keys + STORAGE_DATABASE_URL
pnpm db:migrate              # applies schema incl. coach_kb + doc_index

Run it yourself

Bring your own corpus

The repo ships kb-fixtures/ empty. You supply the knowledge base: either hand-written { source, content } JSON files, or PDFs you ingest. The author's instance is grounded in a science-based curriculum of fitness, nutrition, and corrective-exercise source PDFs.

Because source materials may be copyrighted (licensed for personal study), they live in a gitignored kb-fixtures/private/ directory and are never committed. The app is single-admin, so that content stays private to the operator's database.

Run it yourself

Ingesting PDFs

kb:ingest extracts text from the PDF directories you configure via the INGEST_*_DIRS env vars in .env.local (one or more directories per namespace: INGEST_NUTRITION_DIRS -> nutrition_kb, INGEST_WORKOUT_DIRS -> workout_kb, INGEST_CORRECTIVE_DIRS -> corrective_kb, INGEST_RECOVERY_DIRS -> recovery_kb), chunks it, and writes kb-fixtures/private/<namespace>.json. Keeping the paths in .env.local keeps your personal directories out of the repo.

pnpm kb:ingest --dry-run   # preview classification, write nothing
pnpm kb:ingest             # write the per-namespace JSON
pnpm kb:ingest --append    # add only new files to existing JSON

Run it yourself

Embedding and inserting (seed)

kb:seed embeds each chunk and inserts it into the coach_kb table. It resumes automatically via doc_index, so a quota wall or a dead battery never forces a restart. Range flags split one namespace across two machines (meet-in-the-middle).

pnpm kb:seed                       # all namespaces, resume where left off
pnpm kb:seed workout_kb            # one namespace
pnpm kb:seed --fresh               # wipe + re-seed
pnpm kb:seed workout_kb --start=0 --end=5000   # machine A
pnpm kb:seed workout_kb --start=5000 --end=10233  # machine B

Run it yourself

Choosing the embedding backend

COACH_EMBED_PROVIDER in .env.local selects how chunks (and live queries) are embedded. Both backends are 768-dim. Switching backends requires a full re-seed, because vectors from different models live in different spaces and cannot be mixed in a namespace.

  • gemini (default): cloud, free tier capped at 100 requests/min and ~1000/day; set EMBED_RPM higher on a paid tier.
  • ollama: local, free, no rate limit. Defaults to nomic-embed-text; tune OLLAMA_EMBED_BATCH for your CPU.

Run it yourself

Choosing the chat LLM

The /admin dashboard configures the chat models at runtime, no redeploy. Changes apply to the next coach run.

  • Seven providers. Free: Ollama (local), Cerebras, OpenRouter, Mistral, Together AI. Paid: Anthropic Claude, Google Gemini.
  • Per-role model selection: supervisor (routing), composer (specialist findings), synthesizer (final answer).
  • Generation defaults: temperature (0 to 2) and max tokens.
  • LangSmith tracing toggle (needs a LANGSMITH_API_KEY to actually trace).
  • A COACH_LLM_PROVIDER env var, when set, overrides the dashboard provider (keeps evals pinned to one provider).
Open the admin dashboard

Run it yourself

Clearing the knowledge base

kb:clear deletes coach_kb rows. Useful when retiring old fixtures or switching embedding backends before a fresh seed.

pnpm kb:clear --all                # wipe everything
pnpm kb:clear nutrition_kb workout_kb   # specific namespaces

Run it yourself

Adding content: a fresh install vs. existing data

A fresh install, or a brand-new namespace: point the env var at your source directory, ingest, then seed the whole namespace.

# .env.local: INGEST_WORKOUT_DIRS="/path/to/your/pdfs"
pnpm kb:ingest             # writes kb-fixtures/private/workout_kb.json
pnpm kb:seed workout_kb    # embeds + inserts the whole namespace

Adding to a namespace that already has data: drop the new PDFs into that namespace's directory, append (existing rows stay put), then seed (resume embeds only the appended tail).

pnpm kb:ingest --append    # adds only new files to the JSON tail
pnpm kb:seed workout_kb    # resume embeds only the new rows

Append matches already-ingested files by their source label, so it is safe to re-run. Do not use a plain kb:ingest (without --append) to add content: it rebuilds the JSON from scratch and can shift positions, desyncing it from rows already embedded.

Run it yourself

Adding or removing a specialist

A specialist is a knowledge-base namespace plus a small subgraph. The Corrective Exercise specialist was added exactly this way. Adding one touches a handful of files:

  • src/state.ts: add the name to the Agent union and a slot in FindingsMap.
  • src/agents/supervisor/routing.schema.ts: add it to AgentEnum; supervisor.node.ts: describe its domain in the routing prompt.
  • src/agents/<name>/: retrieval.ts (its own <name>_kb namespace), prompts.ts, and subgraph.ts (retrieve then compose, plus tools if it needs any).
  • src/graph.ts: register the node, add it to the fan-out targets and the SPECIALISTS list, and add an edge from it to synthesize.
  • src/synthesizer/synthesize.ts: include it in the findings loop.
  • src/app/coach/page.tsx: add it to IMPLEMENTED and the intro copy.
  • Content: add an INGEST_<NAME>_DIRS row to scripts/ingest-kb.mjs, set that env var, then run kb:ingest and kb:seed <name>_kb.

Removing a specialist is the reverse: delete its agent directory, drop it from the Agent union, routing schema, graph, synthesizer, and UI, and clear its rows with pnpm kb:clear <name>_kb.