Brief del Agente: Crear conectores de informes de fitness OpenClaw para Garmin, WHOOP, Speediance y más
Un brief de implementación listo para agentes para crear conectores de informes de fitness OpenClaw en Garmin, WHOOP, Speediance, Cronometer, 8Sleep, instantáneas JSON normalizadas y repositorios públicos de GitHub.
Este artículo está pensado para entregarse a un agente de codificación de IA como un brief de implementación.
El objetivo no es clonar mi máquina privada ni aplicar ingeniería inversa a mis archivos. El objetivo es que un agente lea esta página y construya conectores funcionales con los sistemas de fitness: Garmin, WHOOP, Speediance, Cronometer, 8Sleep y, opcionalmente, Open Wearables.
La instrucción principal es sencilla: trata cada proveedor como un conector, persiste instantáneas JSON normalizadas y haz que el generador de informes consuma únicamente esas instantáneas. Esa separación convierte el caos de las API específicas de cada proveedor en un sistema que un agente puede construir.
El agente debe construir la misma clase de conexiones, sin depender de mis rutas locales exactas:
- Garmin para cardio, carga de entrenamiento, ritmo, zonas de frecuencia cardíaca y detalle de actividad
- WHOOP para recuperación, HRV, RHR, sueño, fatiga y contexto de preparación
- Speediance para el historial de sesiones de fuerza, volumen, calorías, plantillas y detalle de ejercicios
- Cronometer para el contexto de nutrición
- 8Sleep para el contexto de sueño que llega tarde, cuando esté disponible
- OpenClaw como capa de orquestación que ejecuta sincronizaciones, normaliza datos y genera informes
También cubre los proyectos de GitHub, las API públicas, los contratos de datos, los modos de fallo y las comprobaciones de aceptación que un agente de implementación necesita para producir un stack funcional sin ver mi repositorio privado.
1. Tarea del agente
Construye un stack local de generación de informes de fitness con OpenClaw que pueda conectarse a los sistemas, normalizar sus datos y generar informes sin llamadas en vivo a proveedores durante la renderización.
El agente debe producir:
- Scripts de conector
Un trabajo de sincronización por sistema: Garmin, WHOOP, Speediance, Cronometer y 8Sleep cuando estén configurados. - Instantáneas sin procesar
Cargas útiles sin procesar en JSON o derivadas de CSV con marca de fecha para depurar cambios de los proveedores. - Contratos normalizados
Archivos JSON estables en los que el generador de informes pueda confiar incluso cuando cambien las cargas de los proveedores. - Informe matutino
Un informe que combina recuperación, sueño, preparación, carga de entrenamiento, nutrición y el plan del día. - Instantánea de entrenamiento adaptable
Un plan de Speediance/BJJ/carrera fechado, derivado de la preparación del mismo día y la carga reciente. - Informe nocturno
Una revisión de plan frente a realidad que compara lo recomendado con la realidad de Garmin, WHOOP y Speediance. - Resultado publicable
HTML estático y JSON legible por máquina que pueda desplegarse en GitHub Pages u otro host estático.
No lo construyas como "un script que llama a seis API y renderiza HTML en vivo". Eso es frágil.
2. --max-tokens 8192 --no-fallback --system Eres un traductor profesional determinista. Devuelve solo el objeto JSON final solicitado. No incluyas razonamiento ni comentarios.
Arquitectura que el agente debe implementar
Constrúyelo en cuatro capas:
- Capa de conectores
Un trabajo de sincronización por plataforma. - Capa de datos normalizados
Cada sincronización escribe instantáneas JSON estables. - Capa de análisis/informes
El código de informes lee únicamente el JSON normalizado. - Capa de presentación
HTML, paneles, briefings diarios, publicaciones de Telegram, resúmenes de voz.
Esa separación es lo que hace que el sistema sea mantenible.
Contrato de implementación de IA
Agente, construye este contrato antes de escribir cualquier interfaz de panel:
- Entradas: solo variables de entorno y credenciales del proveedor; nunca codifiques secretos en los archivos fuente.
- Salidas de sincronización: una instantánea JSON sin procesar por extracción del proveedor, además de un archivo JSON normalizado por proveedor.
- Entradas del informe: solo JSON normalizado. El generador de informes no debe llamar directamente a Garmin, WHOOP, Speediance ni a Cronometer.
- Modo de fallo: si falla un conector, conserva el archivo normalizado del último estado conocido del día anterior y marca esa fuente como obsoleta en el informe.
- Auditabilidad: conserva suficientes cargas útiles sin procesar para depurar cambios en la API del proveedor sin registrar tokens, cookies, contraseñas ni encabezados privados.
- Puerta de envío: las acciones de correo electrónico, voz, Telegram y entrenamiento adaptativo deben requerir datos de recuperación puntuados del mismo día. Aún se puede generar un informe web en modo degradado, pero el sistema no debe enviar coaching confiado a partir de datos de recuperación obsoletos.
- Instantáneas del plan: los planes de entrenamiento adaptativo deben escribirse como instantáneas JSON diarias antes de enviarse a cualquier destino. El informe nocturno puede entonces comparar el plan con lo que realmente ocurrió.
Variables de entorno mínimas para una compilación lista para el agente:
GARMIN_EMAIL=
GARMIN_PASSWORD=
WHOOP_CLIENT_ID=
WHOOP_CLIENT_SECRET=
WHOOP_ACCESS_TOKEN=
WHOOP_REFRESH_TOKEN=
SPEEDIANCE_USER_ID=
SPEEDIANCE_TOKEN=
SPEEDIANCE_REGION=Global
CRONOMETER_EXPORT_PATH=
EIGHTSLEEP_EMAIL=
EIGHTSLEEP_PASSWORD=
3. Definición de terminado
Un agente de implementación solo se considera terminado cuando estos artefactos existan y puedan regenerarse:
data/garmin/summary/latest.jsondata/whoop/normalized/latest.jsondata/speediance/normalized/history.jsondata/speediance/normalized/by_exercise.jsondata/nutrition/latest.jsondata/eightsleep/normalized/latest.json, si 8Sleep está configuradodata/training_plans/YYYY-MM-DD_morning.jsonreports/morning/latest.htmlreports/nightly/latest.html- una puerta de envío que retiene los envíos de correo electrónico, voz, Telegram y entrenamientos adaptativos cuando falta la recuperación WHOOP puntuada del mismo día
- advertencias de fuente obsoleta cuando falla un conector pero se dispone de los datos normalizados válidos conocidos de último recurso del día anterior
- una comprobación de ausencia de secretos que verifica que no se han confirmado tokens, cookies, contraseñas ni cabeceras privadas
Si el agente no puede autenticarse con un proveedor durante el desarrollo, debe implementar igualmente la interfaz del conector, .env.example, fixtures falsos, el normalizador, la gestión de fuentes obsoletas y la integración con los informes.
4. Proyectos públicos y referencias de código fuente
Estas son las piezas públicas que un agente debe utilizar como referencias de implementación.
Lista rápida de verificación de GitHub/API:
- Conector Garmin:
https://github.com/cyberjunky/python-garminconnect - Contexto de autenticación legacy Garmin:
https://github.com/matin/garth - API oficial para desarrolladores WHOOP:
https://developer.whoop.com/api - Extracción pública Speediance para esta compilación:
https://github.com/clawdassistant85-netizen/speediance-smartgym-workout-manager - Fork funcional Speediance del que se extrajo esto:
https://github.com/ANPC86/SmartGymWorkoutManager - Referencia upstream/original Speediance:
https://github.com/hbui3/UnofficialSpeedianceWorkoutManager - Referencia de generador/plantilla de informes:
https://github.com/tobyglenn/scriptsJinja - Exportaciones/integraciones de Cronometer:
https://cronometer.com/
OpenClaw
- Plataforma/orquestador: OpenClaw
- Función: programar trabajos de sincronización, ejecutar transformaciones, generar informes, publicar resultados
Garmin
- Cliente principal en Python: cyberjunky/python-garminconnect
GitHub:https://github.com/cyberjunky/python-garminconnect - Biblioteca de autenticación legacy que antes era relevante: matin/garth
GitHub:https://github.com/matin/garth - Nota de estado:
garthestá obsoleto;python-garminconnectahora utiliza flujos de autenticación Garmin más recientes y es la base sobre la que construir.
WHOOP
- Documentación oficial de la API para desarrolladores:
https://developer.whoop.com/api - Superficie pública de la API: OAuth 2 + endpoints REST para recuperación, ciclos, sueño, entrenamientos, perfil y mediciones corporales
- Existen wrappers opcionales de la comunidad, pero un conector desarrollado por un agente debe anclarse a la API oficial para desarrolladores WHOOP siempre que sea posible.
Speediance
- Referencia práctica de implementación pública de Speediance: ANPC86/SmartGymWorkoutManager
GitHub:https://github.com/ANPC86/SmartGymWorkoutManager - Linaje del proyecto original / referencia pública original: hbui3/UnofficialSpeedianceWorkoutManager
GitHub:https://github.com/hbui3/UnofficialSpeedianceWorkoutManager - Usa el fork ANPC86 SmartGymWorkoutManager como referencia práctica de conexión porque contiene trabajo útil sobre historial, exportaciones, depuración de API, manejo de zonas horarias y manejo de unidades.
- Esta es una integración no oficial de Speediance y debe tratarse como inestable por defecto.
Nutrición
- Sitio del producto Cronometer / exportaciones / integraciones:
https://cronometer.com/ - Trata Cronometer como una fuente estructurada de exportación de nutrición, no como una dependencia mágica de informes directos.
5. Actualizaciones de producción que el agente debe preservar
La versión actual de esta pila tiene algunos comportamientos importantes que el agente debe preservar.
Máquina con un único propietario
La canalización de fitness debe tener una máquina autorizada que esté siempre encendida. No dejes que dos computadoras diferentes generen e implementen informes contra el mismo repositorio de salida. La máquina activa es la propietaria de los trabajos de sincronización con proveedores, la generación de informes, la generación adaptativa de entrenamientos, los despliegues a GitHub Pages y las comprobaciones del vigilante.
Otras máquinas pueden ver los informes o alojar paneles locales, pero no deben regenerar los informes de fitness.
Canalización secuencial en lugar de estimaciones escalonadas de cron
Las canalizaciones matutina y nocturna deben ejecutarse como fases ordenadas:
- sincronizar datos del proveedor
- verificar los datos requeridos del mismo día
- generar informes
- implementar
- enviar notificaciones
- generar resúmenes de voz, si se usan
- ejecutar la validación del vigilante
El error antiguo es programar esos pasos en intervalos fijos de reloj esperando que cada fase anterior haya terminado. El mejor patrón es un único orquestador que ejecute cada fase solo después de que la anterior haya finalizado correctamente.
Puerta de recuperación de WHOOP del mismo día
Para esta pila, la recuperación de WHOOP del mismo día es una puerta estricta para el coaching. Si falta la recuperación de hoy, el sistema aún puede publicar un informe web con advertencias de datos desactualizados, pero debe retener el correo electrónico, la voz, el coaching de Telegram y los envíos de entrenamiento adaptativo.
Esa única regla previene el peor modo de fallo: una recomendación plausible construida a partir de la recuperación de ayer.
Manejo de datos tardíos de 8Sleep
8Sleep puede actualizarse después de la primera ejecución matutina. Una reejecución debe forzar la actualización de hoy y ayer antes de regenerar, en lugar de confiar en un archivo JSON local existente solo porque existe.
Zonas de FC reales de Garmin solo
No inventes distribuciones de zonas de frecuencia cardíaca a partir de la frecuencia cardíaca media. Si el detalle de actividad de Garmin incluye datos de tiempo en zona, úsalo. Si no los incluye, oculta ese gráfico o márcalo como no disponible.
Revisión de la ejecución del plan
El informe nocturno ahora funciona mejor cuando compara el plan del día con los datos reales del día:
- entrenamiento BJJ planificado vs entrenamiento BJJ WHOOP
- sesión Speediance planificada vs sesiones Speediance completadas
- carrera planificada vs distancia de carrera Garmin
- pasos planificados vs pasos Garmin
Esto convierte el informe nocturno en un bucle de retroalimentación en lugar de un simple resumen.
Modo sombra de Open Wearables
Open Wearables resulta útil como futura capa de abstracción, pero no migraría un sistema de informes personales que ya funciona de golpe. La migración más segura es el modo sombra:
- mantén el pipeline basado en archivos existente como autoritativo
- importa o replica datos de Garmin/WHOOP en Open Wearables
- exporta los datos de Open Wearables de vuelta a archivos JSON sombra
- compara los archivos sombra con los archivos de producción
- promociona solo cuando coincidan los recuentos, las fechas y los registros del mismo día
Los archivos sombra nunca deben sobrescribir las entradas de producción durante la fase piloto.
6. Garmin: la capa de cardio y detalle de actividad
Si WHOOP responde a «¿cómo de recuperado estoy?», Garmin responde a «¿qué hice exactamente?».
De Garmin es de donde el informe obtiene:
- distancia
- ritmo y velocidad
- duración
- FC media y máxima
- zonas de frecuencia cardíaca
- cadencia
- potencia
- efecto del entrenamiento
- metadatos de la actividad
- un detalle más amplio de cardio y entrenamiento que WHOOP no enfatiza con tanta profundidad
Repositorio público a utilizar
Recomendado: cyberjunky/python-garminconnect
GitHub: `https://github.com/cyberjunky/python-garminconnect``
Por qué importa:
- está posicionado activamente como el wrapper Python de Garmin Connect a utilizar
- expone una superficie de endpoints de Garmin muy amplia
- incluye ejemplos y patrones de manejo de tokens
- sustituyó suposiciones de autenticación antiguas que se rompieron en cambios previos de Garmin
Nota importante de compatibilidad con Garmin
Históricamente, muchas compilaciones utilizaban garth.
GitHub: `https://github.com/matin/garth``
Pero garth ahora está explícitamente obsoleto. Esto importa porque un agente no debe basar una nueva implementación en una autenticación obsoleta.
Ejemplo mínimo ejecutable de Garmin
from garminconnect import Garmin
from datetime import date
from pathlib import Path
import json
import os
email = os.environ["GARMIN_EMAIL"]
password = os.environ["GARMIN_PASSWORD"]
client = Garmin(email=email, password=password)
client.login()
today = date.today().isoformat()
stats = client.get_stats(today)
activities = client.get_activities_by_date(today, today)
payload = {
"date": today,
"stats": stats,
"activities": activities,
}
out = Path("data/garmin/raw")
out.mkdir(parents=True, exist_ok=True)
(out / f"{today}.json").write_text(json.dumps(payload, indent=2))
Qué normalizar desde Garmin
No vuelques los payloads sin procesar de Garmin directamente en la lógica de tu informe final. Normalízalos primero en campos como:
calendarDatetotalStepsrestingHeartRatesleepingSecondsbodyBatteryactivityNameactivityTypedurationSecondsdistanceMetersdistanceMilesaverageHRmaxHRcaloriestrainingEffectcadencepower
Patrón de almacenamiento recomendado
data/garmin/raw/YYYY-MM-DD.jsondata/garmin/normalized/YYYY-MM-DD.jsondata/garmin/summary/latest.json
Esto te ofrece tanto la posibilidad de reproducir los datos como un acceso rápido para los informes.
7. WHOOP: la capa de recuperación y disposición
WHOOP es lo que hace que los informes resulten útiles como motor de decisiones en lugar de ser solo un registro de actividades.
Aporta:
- puntuación de recuperación
- HRV
- frecuencia cardíaca en reposo
- rendimiento del sueño
- carga
- contexto del ciclo
- encuadre de disposición para recomendaciones matutinas y nocturnas
API pública que se debe utilizar
Utiliza la API oficial para desarrolladores de WHOOP:
- Documentación: `https://developer.whoop.com/api``
Grupos de endpoints relevantes:
/developer/v2/cycle/developer/v2/recovery/developer/v2/activity/sleep/developer/v2/activity/workout/developer/v2/user/profile/basic/developer/v2/user/measurement/body
Limitación crítica
Uno de los hallazgos de implementación más importantes: los datos del diario no están disponibles en la API de WHOOP.
Si quieres obtener respuestas del diario o anotaciones de hábitos, no puedes depender para ello de ningún endpoint público de la API de WHOOP. Las opciones prácticas son:
- exportación manual a CSV desde WHOOP
- tu propia capa de diario paralela
- metadatos independientes que añadas tras la sincronización
Esta limitación debería mencionarse claramente en el artículo porque afecta a cualquier desarrollo serio.
Ejemplo mínimo ejecutable de WHOOP
from pathlib import Path
import json
import os
import requests
BASE = "https://api.prod.whoop.com/developer/v2"
TOKEN = os.environ["WHOOP_ACCESS_TOKEN"]
headers = {"Authorization": f"Bearer {TOKEN}"}
def get(path):
response = requests.get(f"{BASE}{path}", headers=headers, timeout=30)
response.raise_for_status()
return response.json()
payload = {
"recovery": get("/recovery"),
"sleep": get("/activity/sleep"),
"workouts": get("/activity/workout"),
}
out = Path("data/whoop/raw")
out.mkdir(parents=True, exist_ok=True)
(out / "latest.json").write_text(json.dumps(payload, indent=2))
Qué normalizar desde WHOOP
Normaliza en campos como:
recovery_scorehrv_rmssd_milliresting_heart_ratespo2_percentageskin_temp_celsiussleep_performance_percentagerespiratory_ratestraincycle_startcycle_endworkout_sport_name
Patrón de almacenamiento recomendado
data/whoop/raw/recovery.jsondata/whoop/raw/sleep.jsondata/whoop/raw/workouts.jsondata/whoop/normalized/latest.json
8. Speediance: la capa de entrenamiento de fuerza
Speediance es el conector más inusual de toda la pila.
A diferencia de Garmin y WHOOP, no se trata de una plataforma oficial pública y limpia para desarrolladores. El agente debe usar estos repositorios públicos como referencias de conexión:
Extracción/referencia pública: https://github.com/clawdassistant85-netizen/speediance-smartgym-workout-manager
ANPC86/SmartGymWorkoutManager
GitHub: https://github.com/ANPC86/SmartGymWorkoutManager
Ese repositorio es en sí mismo un fork personal / continuación del proyecto público original de Speediance:
hbui3/UnofficialSpeedianceWorkoutManager
GitHub: https://github.com/hbui3/UnofficialSpeedianceWorkoutManager
Estos repositorios son el punto de partida importante porque muestran cómo:
- autenticarse contra los endpoints de Speediance
- inspeccionar datos de entrenamientos y respuestas de la API
- explorar/exportar el historial de entrenamiento
- gestionar plantillas/entrenamientos de forma amigable para escritorio
- manejar cuestiones prácticas como la visualización de zonas horarias y el manejo de pesos en sistema imperial/métrico
Por qué importan estos repositorios
Usa el fork de ANPC86/SmartGymWorkoutManager como base práctica para el patrón de integración con Speediance, conservando al mismo tiempo la referencia upstream hbui3 para la trazabilidad. Juntos, son las referencias públicas más claras para trabajar con datos de Speediance fuera de la aplicación oficial.
Advertencia de estabilidad
El proyecto original señala que Speediance ha estado implementando mejoras de seguridad. Esto significa que:
- esta integración puede romperse
- los encabezados y el comportamiento de autenticación pueden cambiar
- los endpoints pueden moverse
- debes aislar este conector detrás de un paso de normalización para que tus informes sobrevivan a los cambios del proveedor
Patrón ejecutable mínimo para Speediance
Si usas ANPC86/SmartGymWorkoutManager como punto de partida, al tiempo que consultas el upstream hbui3/UnofficialSpeedianceWorkoutManager para obtener el contexto original, el enfoque limpio es:
- Ejecuta su app o capa cliente localmente
- Autentícate con tu cuenta de Speediance
- Extrae el historial de entrenamientos desde los métodos de la API que expone
- --max-tokens 8192 --no-fallback --system You are a deterministic professional translator. Return only the requested final JSON object. Do not include reasoning or commentary.
Exporta JSON normalizado a tu propio directorio de datos
Pseudoejemplo usando ese patrón de cliente:
# Shape this around the api_client.py in:
# https://github.com/clawdassistant85-netizen/speediance-smartgym-workout-manager
from api_client import SpeedianceClient
from datetime import date
from pathlib import Path
import json
import os
client = SpeedianceClient()
success, msg, debug = client.login(
os.environ["SPEEDIANCE_USER_ID"],
os.environ["SPEEDIANCE_TOKEN"],
)
if not success:
raise RuntimeError(msg)
start_date = os.environ.get("SPEEDIANCE_START_DATE", "2026-01-01")
end_date = date.today().isoformat()
records = client.get_training_data(start_date, end_date)
out = Path("data/speediance/raw")
out.mkdir(parents=True, exist_ok=True)
(out / "history.json").write_text(json.dumps(records, indent=2))
Qué normalizar desde Speediance
Normaliza en campos como:
training_iddatetitleduration_secondscaloriestotal_volumeexercise_counttemplate_nameplanned_durationactual_durationexercise_breakdownestimated_1rm
Modelo de datos de buenas prácticas
Para un sistema de informes serio, mantén dos índices:
- bySession
- un registro por entrenamiento completado
- byExercise
- un flujo de registros por nombre de movimiento
- incluye peso, repeticiones, lado, id de sesión, marca de tiempo
Esa estructura facilita mucho después los gráficos de progresión y la detección de PRs.
Patrón de almacenamiento recomendado
data/speediance/raw/monthly/YYYY-MM.jsondata/speediance/normalized/history.jsondata/speediance/normalized/by_exercise.jsondata/speediance/dashboard/latest.json
Instantáneas adaptativas de entrenamientos Speediance
La versión más avanzada de esta construcción no solo lee los entrenamientos Speediance completados, sino que también crea entrenamientos planificados a partir de datos de preparación en tiempo real.
El patrón útil es:
- Carga la recuperación WHOOP del mismo día, la carga actual, la carga BJJ, la batería corporal Garmin, la FC en reposo, la carga de carrera reciente, el clima y el historial reciente del plan Speediance.
- Clasifica el día en un bucket como
build,maintain,recover,protectopost_bjj_brutal. - Selecciona un implemento Speediance para todo el entrenamiento, normalmente mangos, barra o cuerda.
- Elige ejercicios en el dispositivo solo para el entrenamiento principal Speediance.
- Añade de cero a dos accesorios fuera de Speediance solo cuando la recuperación lo permita.
- Escribe el plan en
data/training_plans/YYYY-MM-DD_context.json. - Usa la instantánea tanto para la recomendación matutina como para la revisión nocturna de la ejecución del plan.
Para el control de repeticiones, compara la nueva firma del entrenamiento con las instantáneas recientes del plan. La versión de producción usa una ventana de unicidad móvil que crece hasta 30 días, y siempre marca el título del entrenamiento con la fecha de hoy, de modo que un entrenamiento que reaparece sigue siendo fresco y buscable.
9. Cronometer: la capa de contexto nutricional
Sea cual sea la aplicación de nutrición exacta que uses, la función es la misma: aportar al informe contexto sobre la ingesta energética.
Esto importa porque la carga de entrenamiento sin contexto nutricional conduce a malas conclusiones.
El informe debería poder preguntar:
- ¿La recuperación fue baja porque la carga de entrenamiento fue alta?
- ¿O porque el sueño fue pobre y la ingesta calórica fue baja?
- ¿Estuvo el atleta mal alimentado en relación con el rendimiento?
Consejos prácticos de implementación
No dependas de una API de nutrición en tiempo real en el momento de generar el informe. Usa una de estas opciones:
- exportación CSV
- ingesta mediante webhook
- sincronización programada a JSON normalizado
Normaliza en campos como:
calories_consumedprotein_gcarbs_gfat_gfiber_gtarget_caloriesestimated_deficit
Patrón de almacenamiento recomendado
data/nutrition/raw/YYYY-MM-DD.csvdata/nutrition/normalized/YYYY-MM-DD.jsondata/nutrition/latest.json
10. 8Sleep: la capa de contexto de sueño que llega tarde
8Sleep es opcional, pero si está configurado, el agente debería tratarlo como cualquier otro conector: sincronizar primero, normalizar después, y renderizar desde archivos al final.
El comportamiento importante es el manejo de datos tardíos. Los datos de sueño pueden cambiar después de la primera ejecución matutina, por lo que una reejecución manual o un reintento programado debería forzar la actualización tanto de hoy como de ayer antes de regenerar el informe.
Normaliza campos como:
sleep_scoresleep_startsleep_endtime_in_bed_secondstime_asleep_secondshrvresting_heart_ratetemperature_adjustmentsaway_mode
Patrón de almacenamiento recomendado:
data/eightsleep/raw/YYYY-MM-DD.jsondata/eightsleep/normalized/YYYY-MM-DD.jsondata/eightsleep/normalized/latest.json
11. Lo que OpenClaw realmente hace en este stack
OpenClaw no es la fuente de datos. Es la capa de orquestación y razonamiento.
Su trabajo es:
- ejecutar trabajos de sincronización según la programación
- almacenar resultados estables
- comparar fuentes
- generar el HTML del informe
- publicar enlaces
- producir resúmenes amigables para personas a partir de los datos normalizados
Esto significa que el código del informe debería leer de archivos como:
data/garmin/summary/latest.jsondata/whoop/normalized/latest.jsondata/speediance/normalized/history.jsondata/nutrition/latest.jsondata/eightsleep/normalized/latest.json
El generador de informes nunca debería necesitar saber cómo funciona la autenticación de Garmin o cómo cambiaron las cabeceras de Speediance esta semana.
12. --max-tokens 8192 --no-fallback --system Eres un traductor profesional determinista. Devuelve únicamente el objeto JSON final solicitado. No incluyas razonamiento ni comentarios.
Estructura de directorios que un agente puede crear
Esta es una estructura que un agente puede crear antes de que cualquier autenticación real con un proveedor funcione:
project/
data/
garmin/
raw/
normalized/
summary/
whoop/
raw/
normalized/
speediance/
raw/
normalized/
dashboard/
nutrition/
raw/
normalized/
eightsleep/
raw/
normalized/
training_plans/
scripts/
sync_garmin.py
sync_whoop.py
sync_speediance.py
sync_nutrition.py
sync_eightsleep.py
gate_same_day_recovery.py
build_adaptive_plan.py
build_report.py
reports/
morning/
latest.html
nightly/
latest.html
frontend/
data/
La estructura de archivos forma parte de la interfaz. Hazla lo suficientemente clara para que un futuro agente pueda inspeccionar el sistema, localizar cada conector, volver a ejecutar una sola sincronización y comparar los datos en bruto con las salidas normalizadas.
13. Ejemplo de patrón para generar informes
Una vez que cada conector escribe JSON normalizado, el código del informe propiamente dicho resulta sencillo.
import json
from pathlib import Path
base = Path("data")
garmin = json.loads((base / "garmin/summary/latest.json").read_text())
whoop = json.loads((base / "whoop/normalized/latest.json").read_text())
speediance = json.loads((base / "speediance/normalized/history.json").read_text())
nutrition = json.loads((base / "nutrition/latest.json").read_text())
eightsleep_path = base / "eightsleep/normalized/latest.json"
eightsleep = json.loads(eightsleep_path.read_text()) if eightsleep_path.exists() else {}
summary = {
"recovery": whoop.get("recovery_score"),
"hrv": whoop.get("hrv_rmssd_milli"),
"rhr": whoop.get("resting_heart_rate"),
"steps": garmin.get("totalSteps"),
"body_battery": garmin.get("bodyBattery"),
"lifting_volume": speediance.get("today", {}).get("total_volume"),
"calories_in": nutrition.get("calories_consumed"),
"sleep_score": eightsleep.get("sleep_score"),
}
html = f"""
<html>
<body>
<h1>Daily Fitness Report</h1>
<ul>
<li>Recovery: {summary['recovery']}</li>
<li>HRV: {summary['hrv']}</li>
<li>RHR: {summary['rhr']}</li>
<li>Steps: {summary['steps']}</li>
<li>Body Battery: {summary['body_battery']}</li>
<li>Lifting Volume: {summary['lifting_volume']}</li>
<li>Calories In: {summary['calories_in']}</li>
<li>8Sleep Score: {summary['sleep_score']}</li>
</ul>
</body>
</html>
"""
out = Path("reports/morning")
out.mkdir(parents=True, exist_ok=True)
(out / "latest.html").write_text(html)
Aquí es donde todo el diseño da sus frutos: una vez que la capa de sincronización es razonable, la capa de informes se vuelve aburrida del mejor modo posible.
14. Para qué sirve realmente cada conector
Este es el modelo mental más sencillo:
WHOOP
Úsalo para:
- recuperación
- VFC
- FC en reposo
- rendimiento del sueño
- esfuerzo
- encuadre de la disposición
Garmin
Úsalo para:
- detalle de carrera y cardio
- ritmo, potencia, cadencia
- zonas de FC
- efecto del entrenamiento
- historial detallado de actividades
Speediance
Úsalo para:
- historial de entrenamientos de fuerza
- volumen total
- detalle de ejercicios
- ejecución de la sesión planificada frente a la real
- progresión a nivel de movimiento si construyes indexación por ejercicio
App de nutrición
Úsala para:
- ingesta calórica
- contexto de macronutrientes
- detección de alimentación insuficiente
8Sleep
Úsalo para:
- detalle del sueño que llega tarde
- duración y puntuación del sueño por cama
- verificaciones cruzadas del contexto del sueño con WHOOP y Garmin
OpenClaw luego los combina todos en una única superficie de informe y recomendación.
15. Entregables de conexión por sistema
Esta es la lista de comprobación que el agente de implementación debe cumplir antes de pulir la interfaz del informe.
Puntos de conexión de Garmin
- Biblioteca:
garminconnectdecyberjunky/python-garminconnect - Autenticación: email/contraseña de Garmin Connect con el manejo de tokens/sesiones de la biblioteca
- Cadencia de extracción: sincronización diaria por la mañana más sincronización opcional tras el entrenamiento
- Extracciones mínimas:
- estadísticas diarias de pasos, FC en reposo, segundos de sueño, body battery, calorías
- actividades por fecha para sesiones de carrera, ciclismo o cardio
- detalle de la actividad cuando esté disponible para zonas de FC, ritmo, cadencia, potencia, efecto del entrenamiento
- Salida normalizada:
data/garmin/summary/latest.json
Puntos de conexión de WHOOP
- Documentación de la API:
https://developer.whoop.com/api - Autenticación: flujo de OAuth2 con token de acceso + token de actualización
- URL base:
https://api.prod.whoop.com/developer/v2 - Grupos mínimos de endpoints:
/cyclepara contexto de esfuerzo/ciclo/recoverypara puntuación de recuperación, VFC, FC en reposo/activity/sleeppara rendimiento del sueño y horarios de sueño/activity/workoutpara entrenamientos y datos de esfuerzo de WHOOP/user/profile/basicy/user/measurement/bodypara contexto de perfil/cuerpo cuando sea necesario
- Salida normalizada:
data/whoop/normalized/latest.json
Puntos de conexión de Speediance
- Extracción pública para esta compilación:
https://github.com/clawdassistant85-netizen/speediance-smartgym-workout-manager - Referencia upstream:
https://github.com/hbui3/UnofficialSpeedianceWorkoutManager - Autenticación: flujo no oficial basado en token/user-id expuesto por la capa cliente de SmartGym
- Extracciones mínimas:
- historial de entrenamientos
- detalle de ejercicios/sesiones
- metadatos de entrenamientos/plantillas personalizadas si quieres informes de lo planificado frente a lo real
- captura de respuestas crudas de API/depuración sin secretos
- Salidas normalizadas:
data/speediance/normalized/history.jsondata/speediance/normalized/by_exercise.json
Puntos de conexión de Cronometer
- Fuente pública:
https://cronometer.com/exports/integrations - Enfoque de implementación recomendado: exportación CSV o entrega programada de archivos, sin dependencia de API en tiempo de renderizado
- Campos mínimos: fecha, calorías, proteínas, carbohidratos, grasas, fibra y cualquier micronutriente que quieras incluir en el análisis de recuperación
- Salida normalizada:
data/nutrition/latest.json
Puntos de conexión de 8Sleep
- Autenticación: flujo de inicio de sesión/sesión respaldado por variables de entorno, sin credenciales en el código fuente
- Cadencia de extracción: sincronización matutina más soporte de reejecución/actualización para hoy y ayer
- Extracciones mínimas:
- puntuación de sueño
- horario de sueño
- tiempo dormido y tiempo en cama
- HRV y frecuencia cardíaca en reposo cuando estén disponibles
- temperatura y contexto de modo ausente cuando estén disponibles
- Salida normalizada:
data/eightsleep/normalized/latest.json
Punto de conexión para generación de informes
El generador de informes solo debería leer archivos normalizados estables y capturas de planes. Una forma práctica sería:
data/garmin/summary/latest.json
data/whoop/normalized/latest.json
data/speediance/normalized/history.json
data/speediance/normalized/by_exercise.json
data/nutrition/latest.json
data/eightsleep/normalized/latest.json
data/training_plans/YYYY-MM-DD_morning.json
data/training_plans/YYYY-MM-DD_post_bjj.json
Esa es la verdadera superficie de conexión. Todo lo que está más arriba puede romperse y arreglarse de forma independiente.
16. Las verdaderas reglas de implementación
Si un agente va a construir esto con éxito, estas reglas importan más que cualquier fragmento de código concreto:
Normaliza cada proveedor en tu propio esquema
Nunca dejes que un informe dependa de la forma del payload del proveedor.Conserva las capturas sin procesar
Cuando se rompe una sincronización, los payloads sin procesar te salvan.Nunca renderices desde APIs en vivo si el informe depende del tiempo
Primero sincroniza, después renderiza.Trata las integraciones no oficiales como adaptadores desechables
Especialmente Speediance.Haz que Garmin y WHOOP se complementen, no compitan
WHOOP = disposición. Garmin = detalle de ejecución.Modela los datos de fuerza tanto a nivel de sesión como de ejercicio
De lo contrario, el informe de progresión se queda superficial.Condiciona el coaching a la disposición de hoy, no a la de ayer
Si falta la recuperación del mismo día, el sistema debe degradarse a solo informes web.Guarda el plan antes de juzgar el día
Una puntuación de adherencia nocturna solo funciona si el plan matutino o post-BJJ se almacenó como dato.Prueba nuevos backends en modo sombra
Open Wearables o cualquier otra capa de abstracción debería demostrar que puede igualar los archivos de producción actuales antes de convertirse en la fuente de verdad.
Lista de referencia de implementación final
Estas son las referencias públicas que deben entregarse primero a un agente de codificación de IA al implementar este sistema:
- OpenClaw como capa de orquestación
- Conector Garmin: `https://github.com/cyberjunky/python-garminconnect``
- Contexto de autenticación histórico de Garmin: `https://github.com/matin/garth`` (obsoleto; usar como contexto, no como centro de una nueva implementación)
- API oficial para desarrolladores de WHOOP: `https://developer.whoop.com/api``
- Extracción pública de Speediance para esta implementación: `https://github.com/clawdassistant85-netizen/speediance-smartgym-workout-manager``
- Referencia original/fuente de Speediance: `https://github.com/hbui3/UnofficialSpeedianceWorkoutManager``
- Referencia de generador/plantilla de informes: `https://github.com/tobyglenn/scriptsJinja``
- Exportaciones de nutrición de Cronometer: `https://cronometer.com/``
- Contrato del conector 8Sleep: sincronización respaldada por el entorno que escribe
data/eightsleep/normalized/latest.json
Si vas a entregar este artículo a Claude Code, Codex, OpenClaw u otro agente de implementación, la instrucción correcta es: primero construye los conectores, segundo escribe instantáneas JSON normalizadas, tercero aplica la puerta de recuperación del mismo día, y por último construye el renderizador de informes. No empieces diseñando el informe HTML final.