Health tracking¶
Body stats, bloodwork panels, biomarker trends, Garmin Connect daily summaries, immunization registry, and medical history. Per-user SQLite on local disk at Config.module_db_path(user, "health") (default {db_path.parent}/modules/{user}/health.db); user-facing uploads stay in the workspace on the mount. All measurements stored metric (kg, cm, °C, mmHg, bpm); the display layer converts to the user's preferred units.
Health is an on-by-default module with per-user opt-out via disabled_modules in user settings.
Features¶
Body stats — Time series for weight, blood pressure, resting HR, body fat %, body temp, respiratory rate, SpO2. Manual logging via skill CLI or auto-populated from Garmin sync. Unit-aware input (accepts lb, °F, etc. and converts at log time). BMI derived from latest weight + profile height.
Bloodwork — Panel ingestion from three sources: drag-and-drop OCR upload (PDF/image → LLM extraction with review-and-confirm), CSV bulk import, or manual entry via skill CLI. 60+ canonical biomarkers with sex-specific reference ranges, alias normalization, and auto-flagging (H/L/C). Blood-pressure and resting-HR biomarker rows fan out to the stats time series.
Biomarker trends — Per-marker trend charts with out-of-range zones shaded. LLM-generated educational explainer cards for flagged markers (never diagnoses or prescriptions — hard guardrails in the prompt). Explainers cached per-user per (name, direction).
Garmin Connect — OAuth connection via the general Settings → Connected services page. Garmin is a cross-module connected service, shared with the location track importer — connect once and both features use the same token. Sync runs on demand (the "Sync health data" button on that Garmin card, the garmin-sync skill CLI, or a user-configured CRON job), not on an automatic schedule. It pulls sleep (duration, score, stages), stress, body battery, steps, active calories, SpO2, HRV, VO2 max, and respiration. A multi-day backfill is available but not auto-triggered on connect.
Immunizations — Registry of administered vaccines with date, product, manufacturer, lot, site, route, and facility. Bundled canonical vaccine reference list with recommended schedules. Coverage tracker shows due-soon and overdue immunizations. Bulk import from MyChart/clipboard paste with dry-run preview. Static educational explainers per vaccine.
Medical history — Encounters (doctor visits, procedures, screenings, hospitalizations) and diagnoses (active, resolved, chronic) with ICD-10 codes. history-summary command generates a new-doctor packet.
A condition is linked to every appointment it was seen at, not just one: something a GP found, a specialist was referred for and a follow-up reviewed carries all three, and appears under each of them. Link and unlink from either side — an encounter's page lists its conditions, a condition lists its appointments — and unlinking keeps both records; removing the last link does not delete the condition. Links recorded before this existed are carried over on first upgrade.
Setup¶
Health requires no additional configuration — it's enabled by default for all users. To disable for a specific user, add health to their disabled_modules list in user settings or via the web UI Preferences page.
Install optional dependencies for full functionality:
OCR upload also requires pdftotext (from poppler-utils) for PDF text extraction.
Database¶
Per-user SQLite on local disk (see above). Tables:
| Table | Purpose |
|---|---|
stats |
Body stat time series (metric, value, unit, date, source) |
panels |
Bloodwork panels (drawn_at, lab, type, draft/confirmed, content_hash) |
biomarkers |
Individual biomarker results linked to panels |
biomarker_explainers |
Cached LLM explainer text per (name, direction) |
biomarker_refs |
Bundled canonical biomarker reference ranges and aliases |
immunizations |
Vaccine administration records |
immunization_refs |
Bundled canonical vaccine reference list and schedules |
encounters |
Medical encounters (visits, procedures, screenings) |
diagnoses |
Diagnoses with status (active, resolved, chronic) |
diagnosis_encounters |
Which appointments a condition was seen at (many-to-many) |
health_settings |
Key/value store for profile (DOB, height, sex) and unit display preferences |
documents |
Stored paperwork — scans, discharge summaries, vaccination cards |
document_links |
Which records a document evidences (encounter / diagnosis / immunization) |
Document bytes live at {workspace}/health/uploads/documents/{id}/{filename} — beside the panel sources, under the one path root the file-serving routes guard. A document is stored once and can be linked to several records, so a visit summary covering a diagnosis and a vaccine given at the same visit is one file, not three copies. Size is capped by [health] max_document_bytes (default 25 MiB; 0 = unlimited). A document that ends up attached to nothing is deleted 24 hours after the last thing that referenced it — long enough that detaching a file on the way to re-attaching it elsewhere is safe, short enough that an import you abandoned doesn't linger.
Garmin Connect OAuth tokens are not stored here — they live in the framework-level encrypted secrets table under service="garmin" (Fernet via ISTOTA_SECRET_KEY).
Web pages¶
| Path | Content |
|---|---|
/health/stats |
Netdata-style sparkline grid for all body stats |
/health/bloodwork |
Dates-as-rows × markers-as-columns spreadsheet with category bands |
/health/bloodwork/panel?id=… |
Panel detail with inline-edit table and source preview |
/health/bloodwork/upload |
Drag-and-drop OCR review-and-confirm |
/health/bloodwork/marker?name=… |
Trend chart, related markers, clinical description, explainer card |
/health/immunizations |
Registry table, coverage status, import controls |
/health/history/encounter?id=… |
Encounter detail — linked diagnoses, panels, and its documents |
/health/history/diagnoses |
Conditions list; a paperclip badge opens that condition's documents |
/health/immunizations/detail?id=… |
Per-record edit plus "Proof of immunization" |
/health/settings |
DOB/height/sex, display preferences (Garmin connect/sync lives on Settings → Connected services) |
Skill CLI¶
The health skill exposes istota-skill health <subcommand>. Key subcommands:
log,stats,latest— body stat CRUD and queriespanels,panel,add-panel,add-biomarker— bloodwork managementtrend,summary— biomarker analysisupload,import-csv,export-csv— bulk data operationssettings,set— profile and display preferencesencounters,add-encounter,update-encounter,delete-encounter— medical visitsdiagnoses,diagnosis,add-diagnosis,resolve-diagnosis,update-diagnosis,delete-diagnosis— conditionslink-encounter,unlink-encounter— attach a condition to an appointment it was seen at, or detach it (both records are kept)immunizations,add-immunization,update-immunization,delete-immunization— vaccine recordsvaccine-refs,coverage,explain-immunization— reference data and coverageimport-immunizations— bulk import from clipboard/pastegarmin-status,garmin-sync,garmin-disconnect— Garmin integrationdocuments,document,attach-document,detach-document— file paperwork against a record
Attaching takes a TYPE:ID token: istota-skill health attach-document --path ~/inbox/card.jpg --to immunization:5. Types are encounter, diagnosis, immunization. The agent attaches files the user supplied; deleting a document stays a web-UI action behind a confirmation, since it removes the file from every record it is attached to.
All mutating operations are deferred under sandbox (written to task_<id>_health_ops.json, replayed post-task by the scheduler).
Privacy¶
Health data is the most sensitive data in the system. The health DB is the single source of truth.
- Quantitative health data (measurements, biomarker values, lab dates, symptoms) must never be written to USER.md, the knowledge graph, dated memories, or KV.
- Biomarker values are excluded from briefings and log channels.
- Source files for uploaded labs are served only through the auth-gated
/panels/{id}/sourceroute; attached documents likewise through/documents/{id}/file. Neither is ever a public share link. Documents are always served as a download withnosniff, because one may have arrived from outside (an email attachment the agent filed). - Stable identity-level medical facts (allergies, named chronic conditions) belong in the knowledge graph; detailed records stay in the health DB.