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)
- Pull last night's Fitbit data — sleep score, HRV, resting HR
- Auto-assess sleep pillar
- 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?"
- Log responses to InfluxDB (
accountability measurement)
Evening run (8:30 PM)
- Pull day's activity data — AZM, steps, exercise sessions
- Auto-confirm CrossFit pillar
- Prompt for meditation and food close-out
- Compute daily score (0–5 pillars met)
- Update rolling compliance averages (7-day, 30-day)
- 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
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
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 athttp://192.168.77.125:3000· bens_agents chat integrationThe Five Pillars
InfluxDB Data Layer
health/influx_client.pyThin wrapper around
influxdb-client-python:Key Flux Queries
Sleep score for last night:
Active Zone Minutes (CrossFit proxy):
Resting HR + HRV (stress / recovery signal):
Agent Architecture
health/accountability_agent.pyMorning run (7:00 AM)
accountabilitymeasurement)Evening run (8:30 PM)
Escalation Model
Escalation driven by rolling 7-day compliance rate per pillar, tracked independently.
Tone Examples — Sleep pillar
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)
Grafana panel: compliance heatmap + streak tracker per pillar.
Integration with Jenna (bens_agents)
check_health_accountability()added tochat_tools.pyImplementation Checklist
list_measurementsquery)INFLUX_TOKENin.env/ NAS secretshealth/influx_client.pywith typed query helpers per pillarhealth/accountability_agent.pywith morning + evening flowsaccountabilityscores back to InfluxDBcheck_health_accountability()tool tochat_tools.pyOpen Questions
.envor Grafana data source config)fitbitor something else?Reference video: https://www.youtube.com/watch?v=VGY_XMXMSZc