{"id":34674967,"url":"https://github.com/ald0405/whoop-data","last_synced_at":"2026-04-01T22:25:15.699Z","repository":{"id":223141138,"uuid":"759419009","full_name":"ald0405/whoop-data","owner":"ald0405","description":"Use AI to explore your health data","archived":false,"fork":false,"pushed_at":"2026-03-23T11:07:52.000Z","size":3271,"stargazers_count":10,"open_issues_count":1,"forks_count":3,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-03-24T05:10:55.865Z","etag":null,"topics":["ai-agents","iot","langgraph","python","python3","wearable","wearable-devices","wearable-sensors","whoop","whoop-api"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ald0405.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-02-18T14:47:34.000Z","updated_at":"2026-03-23T11:07:55.000Z","dependencies_parsed_at":"2024-02-18T15:45:45.373Z","dependency_job_id":"1305f016-cc87-46f9-95a2-54e05720c812","html_url":"https://github.com/ald0405/whoop-data","commit_stats":null,"previous_names":["ald0405/whoop-data"],"tags_count":27,"template":false,"template_full_name":null,"purl":"pkg:github/ald0405/whoop-data","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ald0405%2Fwhoop-data","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ald0405%2Fwhoop-data/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ald0405%2Fwhoop-data/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ald0405%2Fwhoop-data/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ald0405","download_url":"https://codeload.github.com/ald0405/whoop-data/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ald0405%2Fwhoop-data/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31292639,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T21:15:39.731Z","status":"ssl_error","status_checked_at":"2026-04-01T21:15:34.046Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-agents","iot","langgraph","python","python3","wearable","wearable-devices","wearable-sensors","whoop","whoop-api"],"created_at":"2025-12-24T20:22:19.594Z","updated_at":"2026-04-01T22:25:15.685Z","avatar_url":"https://github.com/ald0405.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# WHOOP Health Data Platform\n\n[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)\n[![UV](https://img.shields.io/badge/package%20manager-UV-orange.svg)](https://github.com/astral-sh/uv)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![gitcgr](https://gitcgr.com/badge/ald0405/whoop-data.svg)](https://gitcgr.com/ald0405/whoop-data)\n\n![WHOOP Health Data Platform product snapshot](docs/assets/readme-hero.png)\n\nThis project turns fragmented personal health data into a decision-support product. It combines WHOOP and Withings data with analytics, API surfaces, and a chat layer so the user can move from “what happened?” to “what should I do next?” across training, recovery, sleep, and broader day-of planning.\n\n## Why this project matters\n\nThe product goal is not just to collect biometrics. It is to make personal health data more actionable by:\n\n- translating raw records into interpretable trends and coaching-style outputs\n- connecting multiple systems into one consistent experience layer\n- making the same underlying data accessible through API, dashboard, and conversational UX\n- supporting better day-of decisions around training load, recovery, and activity planning\n\n## Product outcomes\n\n- **Single source of truth** for recovery, sleep, workouts, body composition, and related context\n- **Faster interpretation** via dashboards, derived insights, and scenario-oriented analytics\n- **More accessible exploration** through a chat interface for natural-language questions\n- **More usable health decisions** by framing outputs around actions, not just raw measurements\n\n## What it does\n\n- **Data Integration** -- ETL pipelines for WHOOP (recovery, sleep, workouts, cycles) and Withings (weight, body composition, heart rate)\n- **REST API** -- FastAPI backend with interactive Swagger docs\n- **Analytics Pipeline** -- Trend analysis, correlation analysis, and multiple linear regression models for recovery and HRV\n- **Chat Agent** -- LangGraph-based agent for natural language queries against your health data\n- **Dashboard** -- Web UI with charts, MLR coefficient tables, partial correlation charts, and correlation heatmaps\n- **Telegram Bot** -- Optional Telegram transport for the shared agent conversation boundary\n\n## Experience at a glance\n\n- **Dashboard** for quick review of trends and supporting visualizations\n- **API** for structured access to raw and interpreted outputs\n- **Chat** for question-driven exploration such as:\n  - “Show me my tennis workouts from 2025”\n  - “What’s my weight trend over the last 30 days?”\n  - “How has my recovery been this month?”\n\n## Public Surface Model\n\n- **`data`** -- Raw health records, context resources, and provider status under `/api/v1/data/*`\n- **`insights`** -- Derived dashboards, analytics, scenarios, plans, and reports under `/api/v1/insights/*`\n- **`agent`** -- Conversational/coaching requests under `/api/v1/agent/*`\n- **`web`** -- Human-facing pages at `/dashboard`, `/analytics`, and `/report`\n\nNew integrations should target the canonical namespaces above. Legacy aliases still exist in a few places as temporary compatibility adapters during the migration.\n\nWHOOP developer integrations in this repository target the WHOOP **v2** API. The app's own route versioning under `/api/v1/*` is internal product/API namespacing and is separate from the upstream WHOOP developer API version.\n\n## Quick Start\n\n### 1. Install UV and dependencies\n\n```bash\ncurl -LsSf https://astral.sh/uv/install.sh | sh\nuv sync\n```\n\n### 2. Set up environment variables\n\nCreate a `.env` file with your API credentials:\n\n```bash\nWHOOP_CLIENT_ID=your_whoop_client_id\nWHOOP_CLIENT_SECRET=your_whoop_client_secret\nWITHINGS_CLIENT_ID=your_withings_client_id\nWITHINGS_CLIENT_SECRET=your_withings_client_secret\nWITHINGS_CALLBACK_URL=http://localhost:8766/callback\nOPENAI_API_KEY=your_openai_api_key\n```\n\nSupervisor/sub-agent model behaviour (model, temperature, retries, reasoning effort) is configured in `whoopdata/agent/settings.py` via `LLM_CONFIG` as the single source of truth.\n\nWHOOP uses OAuth 2.0 browser authentication. When first running ingestion, you may be redirected to complete the authorization-code flow in the browser.\n\n### 2a. Optional but recommended: shared Postgres for agent memory\n\nIf you want Telegram, API, chat UI, and LangSmith UI to share the same conversational and long-term memory, run a local Postgres instance on the Mac mini and add this to `.env`:\n\n```bash\nAGENT_POSTGRES_URL=postgresql://postgres:postgres@localhost:5432/whoop_agent?sslmode=disable\nAGENT_PERSISTENCE_AUTO_SETUP=true\n```\n\nWith `AGENT_POSTGRES_URL` set, the agent will use Postgres-backed checkpointing and long-term memory storage. If it is not set, the agent falls back to in-memory persistence for development/tests.\n\nExample local startup with Docker:\n\n```bash\ndocker run --name whoop-agent-postgres \\\n  -e POSTGRES_USER=postgres \\\n  -e POSTGRES_PASSWORD=postgres \\\n  -e POSTGRES_DB=whoop_agent \\\n  -p 5432:5432 \\\n  -d postgres:16\n```\n\nOr use the built-in helper:\n\n```bash\nmake postgres-up\n```\n\nOr with Homebrew services:\n\n```bash\nbrew install postgresql@16\nbrew services start postgresql@16\ncreatedb whoop_agent\n```\n\n### 3. Ingest data\n\n```bash\nmake etl\n# or, for a full historical backfill:\nmake etl-full\n```\n\nThese are the canonical ingestion commands. `make run` is still available as a convenience launcher, but it mixes ETL and server startup in one interactive flow.\n\n### 4. Start the API\n\n```bash\nmake server\n```\n\nThe API server exposes the canonical `data`, `insights`, and `agent` surfaces.\n\n### 5. Run analytics (optional)\n\n```bash\nmake analytics\n```\n\nUse this when you want to materialize analytics and insight outputs ahead of time.\n\n### 6. Start the chat interface (optional)\n\n```bash\nmake chat\n```\n\nChat UI runs at `http://localhost:7860`.\n\n### 7. Start LangGraph dev tooling (optional, development-only)\n\n```bash\nmake langgraph-dev\n```\n\nThis is for development and debugging workflows. It is not a separate product surface and should not be treated as the public agent API.\n\n### 8. Access the API\n\n- **Swagger UI**: `http://localhost:8000/docs`\n- **ReDoc**: `http://localhost:8000/redoc`\n- **OpenAPI tags**: `data`, `insights`, and `agent`\n\n## Shared memory testing flow\n\nOnce `AGENT_POSTGRES_URL` is configured, you can test durable shared memory end-to-end like this:\n\n1. Start the API:\n\n```bash\nmake server\n```\n\n2. Start a client surface such as Telegram or chat UI:\n\n```bash\nmake telegram-bot\n# or\nmake chat\n```\n\n3. In a coaching conversation, tell the agent something durable such as:\n   - “Remember that I’m training for a half marathon in October.”\n   - “Remember that I prefer blunt feedback.”\n\n4. In a later message or from another client surface, ask something that should use that memory:\n   - “What should I focus on this week?”\n   - “What do you remember about my current goal?”\n\n5. Restart the app process and repeat the follow-up question. With Postgres configured, the memory and thread state should survive the restart.\n\nFor API testing, you can also hit the agent routes directly:\n\n```bash\ncurl -X POST http://localhost:8000/api/v1/agent/messages \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"message\": \"Remember that I am training for Hyrox in September.\",\n    \"user_id\": \"manual-test-user\"\n  }'\n```\n\nThen ask a follow-up with the same `user_id`:\n\n```bash\ncurl -X POST http://localhost:8000/api/v1/agent/messages \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"message\": \"What should my training priority be?\",\n    \"user_id\": \"manual-test-user\"\n  }'\n```\n\n## Canonical Run Modes\n\n### Primary Commands\n\n- `make etl` -- Canonical incremental ingestion command\n- `make etl-full` -- Canonical full-history ingestion command\n- `make server` -- Canonical FastAPI server for the `data`, `insights`, and `agent` surfaces\n- `make chat` -- Canonical Gradio chat UI backed by the shared conversation boundary\n- `make telegram-bot` -- Telegram bot transport backed by the shared conversation boundary\n- `make analytics` -- Canonical analytics materialization command\n- `make langgraph-dev` -- Development-only LangGraph tooling\n- `uv run whoop-withings-auth` -- Canonical Withings re-auth utility\n\n### Convenience Launchers\n\n- `make run` / `uv run whoop-start` -- Interactive launcher that combines ETL and server flows\n- `make dev-all` -- Combined FastAPI + LangGraph dev helper\n\nUse the primary commands for docs, automation, and repeatable workflows. Treat the convenience launchers as shortcuts rather than the canonical product entrypoints.\n\n## Telegram bot setup\n\nThe LangChain Telegram page linked in some examples is a document loader for ingesting Telegram data; it is not the transport used to expose this agent over Telegram. In this repository, Telegram is an optional adapter over the same shared conversation boundary used by the API and Gradio chat UI.\n\n### Required configuration\n\nAdd the Telegram bot token to `.env`:\n\n```bash\nTELEGRAM_BOT_TOKEN=your_botfather_token_here\n```\n\nThe bot token is a secret. Do not paste it into chat, logs, screenshots, or source control. If it is ever exposed, rotate it in `@BotFather` and update `.env`.\n\n### First-run ID capture\n\nStart the API and the Telegram bot:\n\n```bash\nmake server\nmake telegram-bot\n```\n\nMessage the bot in a private Telegram chat, then use `/whoami` to see your Telegram `user_id` and `chat_id`. In a 1:1 bot chat these values may be identical — that is normal. After that, restrict the bot to your account by setting:\n\n```bash\nTELEGRAM_ALLOWED_USER_IDS=123456789\nTELEGRAM_ALLOWED_CHAT_IDS=123456789\n```\n\nRestart the bot after updating `.env` so the allowlists take effect.\n\n### Runtime model\n\nTelegram runs as a separate transport process over the shared conversation boundary:\n\n```bash\nmake server\nmake telegram-bot\n```\n\n`make dev-all` starts FastAPI and LangGraph dev tooling, but it does not start the Telegram bot.\n\nFor an always-on local setup on macOS, use the persistent service helpers instead:\n\n```bash\nmake services-up\nmake services-test\n```\n\nThat installs `launchd` jobs for the API server, Telegram bot, the scheduled morning summary push, the proactive window evaluator, and the weakness reminder evaluator. Remove them with:\n\n```bash\nmake services-down\n```\n\n### Current Telegram behavior\n\n- Supports `/start` and `/whoami`\n- Supports normal text chat with the shared health-data agent\n- Reuses conversation context per Telegram chat\n- Supports proactive pushes into the same shared Telegram conversation thread via `/api/v1/agent/telegram/push`\n- Rejects non-private chats\n- Uses Telegram-only HTML formatting for better rendering without changing Studio/API output\n- Sends agent-generated image artifacts back to Telegram when available\n- **Voice messages**: Send a voice note and the bot transcribes it (Whisper), processes it through the agent, and replies with both a voice note (TTS) and text\n- **Photo messages**: Send a photo (with optional caption) and the bot interprets it using the vision-capable model in the context of your health data\n\nCurrent limitations:\n\n- The bot must be restarted after changing Telegram token or allowlist settings\n- Voice replies use OpenAI TTS which has a ~2000 token input limit; very long responses fall back to text only\n\nThe Telegram adapter can silently ignore unauthorized users once the allowlists are set. Rotate any token that was ever pasted into chat, logs, or source control before relying on the bot.\n\n### Proactive Telegram smoke test\n\nYou can send yourself a proactive Telegram message that goes through the shared conversation service:\n\n```bash\nuv run -m scripts.telegram_hello --prompt \"set me up for the day\"\n```\n\nOr route the same flow through the running API server:\n\n```bash\nuv run -m scripts.telegram_hello --api --prompt \"set me up for the day\"\n```\n\n### Weakness reminder preview\nYou can send yourself a manual preview of the annual-review weakness reminder without consuming the once-per-workday scheduled send:\n\n```bash\nuv run python scripts/telegram_weakness_preview.py\n```\n\nOptionally preview a specific top-level bullet from `weakness.md`:\n\n```bash\nuv run python scripts/telegram_weakness_preview.py --point-number 2\n```\n\nIf you prefer richer Telegram formatting (bold/italics/bullets), you can request HTML formatting for the preview:\n\n```bash\nuv run python scripts/telegram_weakness_preview.py --point-number 2 --format html\n```\n\nTo enable HTML formatting for all proactive pushes by default, set `TELEGRAM_PROACTIVE_FORMAT=html` in `.env`.\nTo rename the coach in proactive prompts, set `COACH_NAME` in `.env`.\n\n## Rollout Verification Checklist\n\n1. Run the focused validation slices for the migration work before cutting over.\n2. Start the API with `make server` and confirm `/docs` shows the `data`, `insights`, and `agent` OpenAPI tags.\n3. Smoke the canonical public flows:\n   - `GET /api/v1/data/recovery`\n   - `GET /api/v1/insights/dashboard/daily`\n   - `POST /api/v1/agent/conversations`\n   - `POST /api/v1/agent/messages`\n4. Smoke representative compatibility adapters such as `/workouts/latest`, `/recovery/latest`, `/dashboard/daily`, and `/api/daily-plan`, and confirm the `Deprecation`, `Sunset`, and `X-Canonical-Route` headers advertise the canonical replacement.\n5. Launch `make chat`, send an initial message, then send a follow-up message and confirm the conversation resumes cleanly instead of starting a new thread.\n6. Keep `make langgraph-dev` scoped to development/debugging workflows rather than rollout verification of the public product surface.\n\n## Repo notes for reviewers\n\n- The root now prioritizes core product files and entrypoints.\n- Supporting guides live under `docs/` to keep the submission easier to scan.\n- Local runtime artifacts such as tokens, logs, caches, virtual environments, and local databases are gitignored and not part of the deliverable.\n\n## Make Commands\n\n```text\nSetup:\n  make install        Install production dependencies\n  make dev            Install with dev dependencies\n  make sync           Sync/update dependencies\n\nRun:\n  make run            Convenience launcher (interactive ETL + server menu)\n  make server         Primary FastAPI server command\n  make etl            Primary ETL pipeline (incremental)\n  make etl-full       Primary ETL pipeline (full load)\n  make chat           Primary chat interface command\n  make telegram-bot   Telegram bot adapter command\n  make analytics      Primary analytics pipeline command\n  make langgraph-dev  Development-only LangGraph dev server\n  make dev-all        Convenience FastAPI + LangGraph dev launcher\n  make proactive-now  Run the proactive window evaluator immediately\n  make weakness-now   Run the weakness reminder evaluator immediately\n  make weakness-preview Send a manual weakness reminder preview to Telegram\n\nDevelopment:\n  make test           Run tests with pytest\n  make test-cov       Run tests with coverage report\n  make format         Format code with black\n  make lint           Lint with ruff (including docstrings) and flake8\n  make typecheck      Type check with mypy\n  make verify         Run system verification\n\nMaintenance:\n  make clean          Clean cache files and build artifacts\n  make clean-all      Clean everything including .venv\n```\n\n## Troubleshooting\n\n- **WHOOP 401 errors** -- Delete `.whoop_tokens.json` and re-authenticate\n- **Withings re-auth** -- Run `uv run whoop-withings-auth`\n- **Telegram token rejected** -- Re-copy the current token from `@BotFather`, make sure `.env` contains the full token with no quotes or truncation, then restart `make telegram-bot`\n- **`/whoami` or formatting errors in Telegram** -- Restart the bot after pulling the latest code; Telegram formatting is handled adapter-side and should not affect Studio/API output\n- **Telegram access control not working** -- Confirm `TELEGRAM_ALLOWED_USER_IDS` and `TELEGRAM_ALLOWED_CHAT_IDS` are set in `.env`, then restart the bot\n- **Looking for the right API?** -- Use `/api/v1/data/*` for raw records, `/api/v1/insights/*` for interpreted outputs, and `/api/v1/agent/*` for conversational requests\n- **Need detailed implementation notes?** -- Start in [`docs/README.md`](docs/README.md)\n\n## Documentation\n\nDocumentation is organized in [`docs/`](docs/README.md):\n\n- [`docs/technical/`](docs/technical/) -- API changes, migration notes, troubleshooting, implementation detail\n- [`docs/features/`](docs/features/) -- Feature specs and product behavior\n- [`docs/guides/`](docs/guides/) -- Testing, plotting, and contribution workflow guides\n\n## Acknowledgements\n\nThe multiple linear regression module was inspired by [idossha/whoop-insights](https://github.com/idossha/whoop-insights/blob/main/src/whoop_sync/mlr.py).\n\n## License\n\nMIT License. See [LICENSE](LICENSE) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fald0405%2Fwhoop-data","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fald0405%2Fwhoop-data","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fald0405%2Fwhoop-data/lists"}