Stop Overtraining: Build a Bio-Hacker Agent with LangGraph and WHOOP
Source: Dev.to
We’ve all been there. You have a “Heavy Leg Day” blocked on your calendar, but you wake up feeling like a truck hit you. Your Heart Rate Variability (HRV) is in the gutter and your recovery score is a measly 14 %. Traditionally you’d either push through (risking injury) or manually move things around.
But we are developers. We don’t do things manually.
In this tutorial we’ll build a Bio‑Hacker Agent – an autonomous system that:
- Monitors your biometrics via the WHOOP API.
- When recovery metrics drop below a threshold, it rewrites your Google Calendar and suggests a personalized, low‑intensity nutrition plan.
By the end you’ll understand how to bridge wearable IoT data and actionable AI decision‑making using a state‑of‑the‑art stack:
- Python 3.10+
- LangGraph (state‑machine orchestration)
- Pydantic‑AI (schema‑driven LLM output)
- Google Calendar API
- WHOOP Recovery API
Data Flow Overview
graph TD
A[Start: Daily Sync] --> B[Fetch WHOOP Recovery Data]
B --> C{Is HRV/Recovery Low?}
C -- "No (Green Zone)" --> D[Keep Existing Schedule]
C -- "Yes (Red/Yellow Zone)" --> E[Agent: Initiate Pivot]
E --> F[Google Calendar API: Reschedule Workout]
E --> G[Pydantic AI: Generate Anti‑Inflammatory Recipe]
F --> H[Notify User via Slack/Push]
G --> H
D --> I[End]
H --> I
Prerequisites
| Item | Why you need it |
|---|---|
| WHOOP Developer Account | Access the Recovery API |
| Google Cloud Console (Calendar API enabled) | Update calendar events programmatically |
| Python 3.10+ | Modern language features |
langgraph, pydantic-ai, google-api-python-client | Core libraries for the agent |
1️⃣ Define the Agent’s “Brain” with Pydantic
from pydantic import BaseModel, Field
from typing import List, Optional
class RecoveryAction(BaseModel):
"""Schema for the agent’s decision output."""
is_pivot_needed: bool = Field(
description="True if HRV is below 50 % of the 7‑day average"
)
new_workout_type: Optional[str] = Field(
description="Recommended activity (e.g., Yoga, Zone 2 Walk)"
)
reasoning: str = Field(
description="Explanation for the change based on metrics"
)
suggested_calories: int = Field(
description="Adjusted calorie target for low‑intensity day"
)
2️⃣ Build the Decision Graph with LangGraph
from langgraph.graph import StateGraph, END
from typing import TypedDict, List
# ----------------------------------------------------------------------
# State definition (typed dict for static checking)
# ----------------------------------------------------------------------
class AgentState(TypedDict):
hrv_score: int
recovery_percent: int
calendar_events: List[str]
action_plan: RecoveryAction
# ----------------------------------------------------------------------
# Node: fetch biometrics from WHOOP (simulated here)
# ----------------------------------------------------------------------
def check_biometrics(state: AgentState):
# Real implementation would call WHOOP API
# Simulating a “Red Recovery” day:
return {"hrv_score": 35, "recovery_percent": 22}
# ----------------------------------------------------------------------
# Node: analyze metrics and decide whether to pivot
# ----------------------------------------------------------------------
def analyze_and_pivot(state: AgentState):
# LLM (e.g., GPT‑4o) would normally generate this decision
if state["recovery_percent"] < 30:
# Example pivot decision
return {
"is_pivot_needed": True,
"new_workout_type": "Yoga",
"reasoning": "HRV below threshold; recommend low‑intensity activity.",
"suggested_calories": 1800,
}
else:
return {
"is_pivot_needed": False,
"new_workout_type": None,
"reasoning": "Metrics within normal range.",
"suggested_calories": 2500,
}
# ----------------------------------------------------------------------
# Assemble the graph
# ----------------------------------------------------------------------
graph = StateGraph(AgentState)
graph.add_node("fetch", check_biometrics)
graph.add_node("decide", analyze_and_pivot)
graph.set_entry_point("fetch")
graph.add_edge("fetch", "decide")
graph.add_edge("decide", END)
app = graph.compile()
Production tip: Handle OAuth token refresh, error retries, and respect user privacy (HIPAA if you store PHI).
4️⃣ Generate a Recovery‑Focused Meal Plan
def generate_recipe(action: RecoveryAction):
prompt = (
f"Create a meal plan for {action.suggested_calories} calories "
f"focused on anti‑inflammatory ingredients for someone with low HRV."
)
# Call your LLM provider here (OpenAI, Anthropic, etc.)
# response = client.chat.completions.create(...)
print("Recipe generated for recovery day!")
5️⃣ Next Steps & Extensions
- Slack / Push notifications – alert the moment you wake up.
- MyFitnessPal integration – auto‑log macro targets.
- Sleep‑data analysis – incorporate WHOOP sleep stages for richer decisions.
Further Reading
For deeper dives into production‑grade health‑tech agents, see the WellAlly Blog – they cover architectural blueprints used by top‑tier longevity startups.
Happy hacking, and may your recovery be ever optimal!
Drop a comment below or share your own bio‑hacking scripts! And don’t forget to visit wellally.tech/blog for more insights into the future of AI‑driven wellness.