Skip to content

Health Accountability Sub-Agent: Fitbit + InfluxDB daily check-in with escalating nudges #2

Description

@BenSpex

Overview

Build a daily accountability sub-agent that queries Ben's Fitbit data from InfluxDB, cross-references manual check-ins for pillars that can't be auto-detected, scores each day, and delivers increasingly pointed feedback the longer streaks break.

Stack: InfluxDB at http://influxdb:8086 · Grafana at http://192.168.77.125:3000 · bens_agents chat integration


The Five Pillars

Pillar Data Source Detection Method
Sleep Fitbit via InfluxDB Auto — sleep score, minutes asleep, sleep stages, HRV
CrossFit Fitbit via InfluxDB Auto — Active Zone Minutes, exercise type, duration
Ice Bath Manual Morning check-in prompt (no sensor proxy)
Meditation Manual + HRV proxy Check-in + flag if HRV trending down (stress signal)
Food Manual + meal_prep agent Check-in + cross-reference meal_prep plan

InfluxDB Data Layer

health/influx_client.py

Thin wrapper around influxdb-client-python:

from influxdb_client import InfluxDBClient

INFLUX_URL = "http://influxdb:8086"
INFLUX_TOKEN = os.getenv("INFLUX_TOKEN")  # store in .env
INFLUX_ORG = "bens_health"
INFLUX_BUCKET = "fitbit"  # confirm bucket name on first run

client = InfluxDBClient(url=INFLUX_URL, token=INFLUX_TOKEN, org=INFLUX_ORG)

Key Flux Queries

Sleep score for last night:

from(bucket: "fitbit")
  |> range(start: -24h)
  |> filter(fn: (r) => r._measurement == "sleep" and r._field == "score")
  |> last()

Active Zone Minutes (CrossFit proxy):

from(bucket: "fitbit")
  |> range(start: -24h)
  |> filter(fn: (r) => r._measurement == "activity" and r._field == "active_zone_minutes")
  |> sum()

Resting HR + HRV (stress / recovery signal):

from(bucket: "fitbit")
  |> range(start: -7d)
  |> filter(fn: (r) => r._measurement == "heart_rate"
      and (r._field == "resting_heart_rate" or r._field == "hrv"))
  |> mean()

First-run note: Run list_measurements() against the InfluxDB bucket to confirm actual measurement/field names from the Grafana data source before hardcoding.


Agent Architecture

health/accountability_agent.py

Morning run (7:00 AM)

  1. Pull last night's Fitbit data — sleep score, HRV, resting HR
  2. Auto-assess sleep pillar
  3. Send morning check-in prompt to Ben via bens_agents chat:
    • "Ice bath today? (y/n)"
    • "CrossFit on the schedule?" (auto-confirms later if AZM > 30 detected)
    • "How's food looking today?"
  4. Log responses to InfluxDB (accountability measurement)

Evening run (8:30 PM)

  1. Pull day's activity data — AZM, steps, exercise sessions
  2. Auto-confirm CrossFit pillar
  3. Prompt for meditation and food close-out
  4. Compute daily score (0–5 pillars met)
  5. Update rolling compliance averages (7-day, 30-day)
  6. Deliver verdict (see escalation model)

Escalation Model

Escalation driven by rolling 7-day compliance rate per pillar, tracked independently.

def get_tone(compliance_7d: float) -> str:
    if compliance_7d >= 0.85:   return "encouraging"
    elif compliance_7d >= 0.70: return "direct"
    elif compliance_7d >= 0.50: return "pointed"
    else:                        return "ruthless"

Tone Examples — Sleep pillar

Tone Example message
Encouraging "6h42m last night — not your best but you're tracking well overall."
Direct "Three nights under 7 hours this week. That's not a blip, it's a pattern."
Pointed "5 of 7 nights under 7 hours. Your HRV is showing it. What's actually going on?"
Ruthless "18 days. Sleep compliance is 38%. You're not tired because of work — you're tired because you keep doing this."

Each pillar escalates independently. Crush sleep but dodge ice baths and the ice bath message gets brutal while sleep stays warm.


InfluxDB Write-back (Accountability Scores)

measurement: accountability
tags:
  pillar: sleep | crossfit | ice_bath | meditation | food
fields:
  met: 0 or 1
  score_raw: float        # e.g. Fitbit sleep score 82, AZM 45
  tone_level: 0-3
  streak_missed: int
  compliance_7d: float
  compliance_30d: float

Grafana panel: compliance heatmap + streak tracker per pillar.


Integration with Jenna (bens_agents)

  • New tool: check_health_accountability() added to chat_tools.py
  • Returns: last night's sleep score, yesterday's pillar completion, outstanding check-ins
  • Jenna surfaces it in morning briefings naturally:

    "Sleep score was 74 — HRV dipped, probably the late call. Ice bath still unconfirmed."

  • If Ben's on a multi-day miss streak on any pillar, Jenna flags it unprompted

Implementation Checklist

  • Confirm InfluxDB bucket name + actual Fitbit measurement/field names (list_measurements query)
  • Set up INFLUX_TOKEN in .env / NAS secrets
  • Build health/influx_client.py with typed query helpers per pillar
  • Build health/accountability_agent.py with morning + evening flows
  • Implement escalation model + tone engine
  • Write accountability scores back to InfluxDB
  • Add check_health_accountability() tool to chat_tools.py
  • Create Grafana compliance panel (heatmap + streak tracker)
  • Schedule via bens_agents cron (7:00 AM + 8:30 PM daily)
  • Close duplicate issues on bens_agents repo (#12 and #13)

Open Questions

  • What's the InfluxDB auth token? (check NAS .env or Grafana data source config)
  • Is the bucket named fitbit or something else?
  • For ice bath + meditation check-ins: chat prompt, Telegram, or push notification?

Reference video: https://www.youtube.com/watch?v=VGY_XMXMSZc

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions