Stop Overtraining: Build a Bio-Hacker Agent with LangGraph and WHOOP

Published: (February 6, 2026 at 08:00 PM EST)
4 min read
Source: Dev.to

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

ItemWhy you need it
WHOOP Developer AccountAccess 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-clientCore 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.

0 views
Back to Blog

Related posts

Read more »

The Origin of the Lettuce Project

Two years ago, Jason and I started what became known as the BLT Lettuce Project with a very simple goal: make it easier for newcomers to OWASP to find their way...