Governed runtime + skills for a multi-domain personal health agent (recovery, running, sleep, stress, strength, nutrition).
Project description
Health Agent Infra
A governed local agent runtime for personal health data. Claude Code + Garmin today; MCP-portable and multi-source on the roadmap.
A Claude Code agent reads your own health data, emits per-domain proposals bounded by codified rules, and commits auditable recommendations you review the next day. Every decision is logged to a local SQLite database on your machine; nothing leaves your device.
For technical users comfortable with a CLI who use Claude Code and want agent recommendations they can audit, reproduce, and keep local.
- Local-first. State lives in a SQLite file under your home directory. No cloud, no account, no remote telemetry.
- Governed, not generative. Python owns mechanical decisions (classification bands, policy rules, transactional commits); markdown skills own rationale and uncertainty. Skills never change an action; code never writes prose.
- Agent-operable by contract. Every CLI subcommand carries
machine-readable contract metadata (mutation class, idempotency, exit
codes) that an agent reads via
hai capabilities --json. An authoritativeintent-routerskill maps natural-language intent to deterministic workflows; every X-rule firing carries a stable slug plus a sentence-form explanation the agent can narrate verbatim. - Auditable by construction. Pulls, proposals, rule firings, synthesis,
and final recommendations all land in typed tables. Inspect anytime with
hai today(end-user prose),hai explain --operator(dense audit report),hai doctor,hai stats. Prefer these over reading the SQLite file directly — they reconcile supersede chains and hide schema churn, which plain SQL won't.
Install
pipx install health-agent-infra # or: pip install -e .
hai init --with-auth --with-first-pull # scaffolds state + config + skills,
# prompts for Garmin credentials,
# backfills the last 7 days
hai daily # tomorrow morning: pull → clean → propose → synthesize → commit
hai today # read today's plan in plain language
hai stats # local funnel: syncs, recent runs, daily streak
Prefer the non-interactive path? Run hai init on its own, then hai auth garmin separately. hai init is idempotent and safe to re-run. Full CLI
surface in
reporting/docs/agent_cli_contract.md.
macOS Keychain note. hai auth garmin and hai auth intervals-icu
store credentials in the OS keyring. On macOS, the first time
hai pull --live reads those credentials the system prompts you to
allow access. Click Always Allow — otherwise every subsequent
pull re-prompts and scripted runs (including hai daily) will hang
waiting for a keyboard. The corresponding success messages from
hai auth print a one-line stderr hint as a reminder.
Reading your plan
hai today is the non-agent-mediated user surface — it reads the
canonical plan for a date (resolving supersede chains automatically)
and renders prose in the voice the reporting skill specifies:
top-matter → 2–4 sentence summary → six per-domain sections → footer
pointing at the next review.
hai today # today, markdown on TTY / plain elsewhere
hai today --as-of 2026-04-23 # specific date
hai today --domain recovery # narrow to one domain
hai today --format json # machine-readable (same shape, no prose)
Defer domains (insufficient signal) surface a domain-specific
follow-up question and an unblock hint naming the hai intake …
command that would give tomorrow's plan the signal it needs — see
reporting/plans/v0_1_4/D3_user_surface.md
for the voice contract.
For debug-level audit dumps, use hai explain --operator (dense
field-by-field text) or hai explain (JSON). Both consume the same
explain bundle hai today reads — they just render it differently.
Recording your day
After tomorrow's hai daily schedules a review event for each rec,
log how yesterday went:
hai review record --outcome-json <path> \
--base-dir <base_dir> \
--db-path <state.db>
hai review summary --base-dir <base_dir> [--domain recovery]
Outcomes are append-only and auto-re-link when a plan has been
superseded — if you recorded an outcome against the morning plan but
re-authored the day after lunch, hai review record routes the
outcome to the canonical leaf's matching-domain rec. See the
review-protocol skill for the full payload shape.
Manual intake surfaces (stress score, gym sessions, nutrition macros,
readiness self-reports) all live under hai intake <domain>; they
persist to their per-domain raw tables so the next hai daily picks
them up automatically.
Six domains in v1
recovery · running · sleep · stress · strength · nutrition
Each domain ships its own schemas, classification bands, policy rules, and a
readiness skill, and is wired into the synthesis X-rule catalogue that
reconciles across domains. Nutrition is macros-only in v1 — see
reporting/docs/non_goals.md.
Local-first runtime at a glance
pull / intake → projectors → accepted_*_state_daily tables
│
▼
hai state snapshot --as-of <date>
│
▼
domain skills emit DomainProposal × 6
│ hai propose
▼
proposal_log
│
▼
Phase A X-rules (X1–X7) → runtime applies mutations to drafts
│
▼
daily-plan-synthesis skill overlays rationale
│
▼
Phase B X-rules (X9) → action_detail adjustments
│
▼
ATOMIC COMMIT: daily_plan + x_rule_firings
+ planned_recommendation (pre-X-rule aggregate)
+ N recommendation_log (adapted)
│
▼
hai today (read) / hai review record (write)
- Local state memory —
accepted_*_state_dailytables store the canonical per-domain day-level state the runtime reasons over. - Decision memory —
proposal_log(per-domain planned intent),planned_recommendation(aggregate pre-X-rule plan),daily_plan+x_rule_firing+recommendation_log(aggregate adapted plan) preserve the full audit chain: what was originally planned, how X-rules mutated it, and what was finally committed. - Outcome memory —
review_eventandreview_outcomerecord how the plan went, so the history of decisions and outcomes stays on-device. - Agent contract surface —
hai capabilities --jsonemits a machine-readable manifest of every subcommand; the markdown mirror lives atreporting/docs/agent_cli_contract.md. Theintent-routerskill is authoritative for NL → CLI mapping against that contract.
See reporting/docs/architecture.md for
the full pipeline and the code-vs-skill boundary.
Roadmap
- Runtime portability via MCP. Expose the agent-safe CLI surface as an MCP server so any agentic runtime (Claude Code, Codex, others) can drive it. Today the project is Claude Code–native; the CLI contract is already annotated agent-safe vs. interactive, which maps cleanly onto MCP tool schemas.
- Multi-source wearables. Apple Health, Oura, Whoop. The adapter
protocol (
core/pull/protocol.py) is already source-agnostic; the per-domain evidence contract needs to broaden before additional sources land. Community adapters welcome — seereporting/docs/how_to_add_a_pull_adapter.md. - Skill-narration eval harness. Live-mode pilot shipped (Phase E +
M8 Phase 4); broader scenario coverage still to come. See
safety/evals/skill_harness_blocker.md.
What this is not
- Not a medical device, not hosted, not multi-user, not an ML loop. See
reporting/docs/non_goals.md. - Not meal-level nutrition in v1 — macros only.
- Not an MCP server yet (see Roadmap).
- Not an MCP-wrapper-integrated or skill-harness-eval-complete release yet.
Dig deeper
- Positioning & role map —
reporting/docs/personal_health_agent_positioning.md - Query taxonomy —
reporting/docs/query_taxonomy.md - Memory model —
reporting/docs/memory_model.md - Architecture overview —
reporting/docs/architecture.md - Explainability surface (three-state audit) —
reporting/docs/explainability.md - Agent CLI contract (generated manifest) —
reporting/docs/agent_cli_contract.md - X-rule catalogue + sentence explanations —
reporting/docs/x_rules.md - Non-goals (scope discipline) —
reporting/docs/non_goals.md - State schema —
reporting/docs/state_model_v1.md - 10-minute reading tour —
reporting/docs/tour.md - Extension path — pull adapter —
reporting/docs/how_to_add_a_pull_adapter.md - Extension path — new domain —
reporting/docs/how_to_add_a_domain.md - Agent-operable runtime plan (M8 cycle) —
reporting/plans/agent_operable_runtime_plan.md - Eval capture —
reporting/artifacts/flagship_loop_proof/2026-04-18-multi-domain-evals/
CLI surface
# Evidence + intake
hai pull [--live] --date <d> # Garmin CSV / live pull
hai clean --evidence-json <p> # raw → CleanedEvidence + RawSummary
hai intake gym|exercise|nutrition|stress|note|readiness ...
# State
hai state init | migrate | read | snapshot | reproject
# Per-domain debug: use `hai state snapshot --evidence-json <p>` —
# emits classified_state + policy_result for every domain in one call.
# Agent flow (use `hai daily` for the whole loop)
hai daily # morning orchestrator (pull→clean→reproject→propose→synthesize)
hai propose --domain <d> --proposal-json <p>
hai synthesize --as-of <d> --user-id <u>
# Persistence + review
hai review schedule | record | summary [--domain <d>]
# Agent contract + audit
hai capabilities [--markdown] # JSON manifest (or regenerate the contract doc)
hai explain --for-date <d> --user-id <u> # three-state audit: planned → adapted → performed
hai memory set | list | archive # explicit user memory (goals, preferences, constraints)
# Ops
hai init [--with-auth] [--with-first-pull] # first-run wizard (idempotent)
hai doctor [--json] # runtime health + per-source freshness
hai stats [--json] # local funnel (sync + command history, daily streak)
# Auth + config + helpers
hai auth garmin | status
hai config init | show
hai exercise search --query <free-text>
# Evals
hai eval run --domain <d> | --synthesis [--json]
hai setup-skills # copy packaged skills into ~/.claude/skills/
Repo layout
For a one-page orientation of every top-level entry (active vs historical vs
generated) see REPO_MAP.md. The package itself:
src/health_agent_infra/
├── cli.py # hai dispatcher
├── core/
│ ├── schemas.py validate.py config.py
│ ├── synthesis.py synthesis_policy.py
│ ├── writeback/ state/ clean/ pull/ review/
│ ├── memory/ explain/ research/
│ └── intake/
├── domains/
│ ├── recovery/ running/ sleep/ stress/ strength/ nutrition/
│ └── each: schemas.py classify.py policy.py [+ signals/intake]
├── skills/
│ ├── recovery-readiness/ running-readiness/ sleep-quality/
│ ├── stress-regulation/ strength-readiness/ nutrition-alignment/
│ ├── daily-plan-synthesis/ intent-router/ expert-explainer/
│ └── strength-intake/ merge-human-inputs/ review-protocol/
│ reporting/ safety/
├── evals/ # packaged eval runner + scenarios
└── data/garmin/export/ # committed CSV fixture
reporting/ # see reporting/README.md
├── docs/ # architecture, x_rules, non_goals, ...
├── artifacts/flagship_loop_proof/ # eval runner captures
├── plans/ # post-v0.1 roadmap + historical phase docs
└── experiments/ # frozen Phase 0.5 / 2.5 prototypes
safety/ # see safety/README.md
├── tests/ # 1489 unit + contract + integration
├── evals/ # eval-doc reference + skill-harness pilot
└── scripts/ # legacy pre-rebuild demo shim
What's proven
- Six domains end-to-end: classify → policy → skill proposal → synthesis → review.
- Ten X-rule evaluators across two phases with atomic transactional commits,
each firing carrying a stable slug and a one-sentence
human_explanationagents can narrate verbatim. - Three-state audit chain:
proposal_log→planned_recommendation(aggregate pre-X-rule intent, migration 011) →daily_plan+recommendation_log→review_outcome.hai explainrenders all three states from persisted rows alone. - Agent CLI contract: every subcommand annotated with mutation class,
idempotency, JSON output, exit codes, agent-safe flag; machine-readable
manifest at
hai capabilities --json; markdown mirror atreporting/docs/agent_cli_contract.md. Every handler on the stable exit-code taxonomy. - Authoritative
intent-routerskill consumes the manifest as the NL → CLI mapping surface; deliberately scoped so mutation commands are previewed before they run. - Skill-harness pilot: 7 frozen recovery scenarios, 6 with hand-authored
reference transcripts scoring 2.0/2.0 on the token-presence rubric;
live-mode backend opt-in via
HAI_SKILL_HARNESS_LIVE=1. - Local onboarding + engagement telemetry (migration 012
runtime_event_log) surfaced viahai stats. No data leaves the device. - Garmin live pull via OS keyring (
hai auth garmin+hai pull --live). - Idempotent synthesis with optional
--supersedeversioning. - 28 eval scenarios (18 domain + 10 synthesis) — all deterministic axes green.
- 1489 tests covering every band, every R-rule, every X-rule, atomic transaction semantics, proposal/synthesis invariants, skill-boundary contracts, capabilities-manifest coverage + determinism, planned-ledger round-trip, three-state explain render, and the new runtime_event_log + hai stats paths.
Contributing
See CONTRIBUTING.md.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file health_agent_infra-0.1.4.tar.gz.
File metadata
- Download URL: health_agent_infra-0.1.4.tar.gz
- Upload date:
- Size: 340.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1ef8c77fc457408e4295c059de26c05cb37829e75d0fd94e6b09d9d3f8515e18
|
|
| MD5 |
dab5780a71e7476aa73ec1b00bc04bbb
|
|
| BLAKE2b-256 |
fc74e11a05a14a04f83b8214e65589ceb554fda6817dd49f4460b1a992e74e9a
|
File details
Details for the file health_agent_infra-0.1.4-py3-none-any.whl.
File metadata
- Download URL: health_agent_infra-0.1.4-py3-none-any.whl
- Upload date:
- Size: 419.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bd916117e68bdbfa443074e55e1eaa8edefe438446f71c02a56124cf4773deee
|
|
| MD5 |
4911504e10530fb5bbfe420f2bd38f38
|
|
| BLAKE2b-256 |
aa9a07dd656ae436a6e39d75855e3b84407b0a3d4fc56c3a8fd2f55e7108aec8
|