Volver a los análisis
Informes de campo24 min de lectura

Brief del agente: Crear OpenClaw conectores de informes de fitness para Garmin, WHOOP, Speediance, y más

Un brief de implementación listo para el agente para crear OpenClaw conectores de informes de fitness en Garmin, WHOOP, Speediance, Cronometer, 8Sleep, instantáneas JSON normalizadas y repositorios públicos de GitHub.

Toby 3 de mayo de 2026

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 hacer ingeniería inversa de mis archivos. El objetivo es que un agente lea esta página y construya conectores funcionales a los sistemas de fitness: Garmin, WHOOP, Speediance, Cronometer, 8Sleep, y Open Wearables de forma opcional.

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, no depender de mis rutas locales exactas:

  • Garmin para cardio, carga de entrenamiento, ritmo, zonas de frecuencia cardíaca y detalle de actividades
  • WHOOP para recuperación, HRV, RHR, sueño, strain y contexto de readiness
  • 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 la capa de orquestación que ejecuta las sincronizaciones, normaliza los datos y genera los 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 de informes de fitness OpenClaw local-first que pueda conectarse a los sistemas, normalizar sus datos y generar informes sin llamadas en vivo a los proveedores durante el renderizado.

El agente debe producir:

  1. Scripts conectores
    Un trabajo de sincronización por sistema: Garmin, WHOOP, Speediance, Cronometer y 8Sleep cuando estén configurados.
  2. Instantáneas crudas
    Payloads derivados de JSON o CSV con marca de fecha para depurar cambios en los proveedores.
  3. Contratos normalizados
    Archivos JSON estables en los que el generador de informes pueda confiar incluso cuando cambien los payloads de los proveedores.
  4. Informe matutino
    Un informe que combine recuperación, sueño, readiness, carga de entrenamiento, nutrición y el plan del día.
  5. Instantánea de entrenamiento adaptativo
    Un plan Speediance/BJJ/carrera con fecha, derivado del readiness del mismo día y la carga reciente.
  6. Informe nocturno
    Una revisión plan vs. realidad que compare lo recomendado con la realidad de Garmin, WHOOP y Speediance.
  7. Salida publicable
    HTML estático y JSON legible por máquina que se pueda desplegar en GitHub Pages u otro host estático.

No construyas esto como "un script que llama a seis API y renderiza HTML en vivo". Eso es frágil.

2. Arquitectura que el agente debe implementar

Construye en cuatro capas:

  1. Capa de conectores
    Un trabajo de sincronización por plataforma.

Capa de datos normalizados
Cada sincronización escribe instantáneas JSON estables. 3. Capa de análisis/informes
El código de informes lee únicamente JSON normalizado. 4. Capa de presentación
HTML, paneles, resúmenes diarios, publicaciones en 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 de proveedores; nunca codifiques secretos en los archivos fuente.
  • Salidas de sincronización: una instantánea JSON sin procesar por cada extracción de proveedor, más un archivo JSON normalizado por proveedor.
  • Entradas de informes: solo JSON normalizado. El generador de informes no debe llamar a Garmin, WHOOP, Speediance o Cronometer directamente.
  • Modo de fallo: si un conector falla, conserva el archivo normalizado del último estado bueno conocido de ayer 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 cabeceras privadas.
  • 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 con confianza 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 sitio. 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 termina cuando estos artefactos existen y pueden regenerarse:

  • 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, si 8Sleep está configurado
  • data/training_plans/YYYY-MM-DD_morning.json
  • reports/morning/latest.html
  • reports/nightly/latest.html
  • una puerta de envío que retenga los envíos de correo electrónico, voz, Telegram y entrenamiento adaptativo cuando falten datos de recuperación WHOOP puntuados del mismo día
  • advertencias de fuentes obsoletas cuando un conector falla pero los datos normalizados del último estado bueno conocido de ayer están disponibles
  • una comprobación de no-secretos que demuestra que los tokens, cookies, contraseñas y cabeceras privadas no se incluyeron en el repositorio

Si el agente no puede autenticarse con un proveedor durante el desarrollo, debe implementar igualmente la interfaz del conector, .env.example, fixtures falsos, normalizador, manejo de fuentes obsoletas y la integración de informes.


4. Proyectos públicos y referencias de fuentes

Estas son las piezas públicas que un agente debe usar como referencias de implementación.

Lista de comprobación rápida de GitHub/API:

  • Conector Garmin: https://github.com/cyberjunky/python-garminconnect
  • Contexto de autenticación heredado de Garmin: https://github.com/matin/garth
  • API oficial para desarrolladores de WHOOP: https://developer.whoop.com/api
  • Extracción pública de Speediance para esta compilación: https://github.com/clawdassistant85-netizen/speediance-smartgym-workout-manager
  • Fork funcional de Speediance del que se extrajo esto: https://github.com/ANPC86/SmartGymWorkoutManager
  • Referencia upstream/original de Speediance: https://github.com/hbui3/UnofficialSpeedianceWorkoutManager
  • Referencia de generador/plantilla de informe: 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 y publicar resultados

Garmin

  • Cliente Python principal: cyberjunky/python-garminconnect
    GitHub: https://github.com/cyberjunky/python-garminconnect
  • Librería de autenticación heredada que antes era importante: matin/garth
    GitHub: https://github.com/matin/garth
  • Nota de estado: garth está obsoleto; python-garminconnect ahora usa flujos de autenticación más recientes de Garmin y es la opción sobre la que se debe construir.

WHOOP

  • Documentación de la API oficial para desarrolladores: https://developer.whoop.com/api
  • Superficie de la API pública: endpoints OAuth2 + REST para recuperación, ciclos, sueño, entrenamientos, perfil y medidas corporales
  • Existen wrappers opcionales de la comunidad, pero un conector creado por el agente debe anclarse a la API oficial para desarrolladores de WHOOP siempre que sea posible.

Speediance

  • Referencia de implementación pública práctica de Speediance: ANPC86/SmartGymWorkoutManager
    GitHub: https://github.com/ANPC86/SmartGymWorkoutManager
  • Linaje del proyecto upstream / referencia pública original: hbui3/UnofficialSpeedianceWorkoutManager
    GitHub: https://github.com/hbui3/UnofficialSpeedianceWorkoutManager
  • Usar el fork de ANPC86 SmartGymWorkoutManager como referencia práctica de conexión porque contiene trabajo útil sobre historial, exportaciones, depuración de la 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 / exportaciones / integraciones de Cronometer: https://cronometer.com/
  • Tratar Cronometer como una fuente estructurada de exportación de nutrición, no como una dependencia mágica directa del informe.

5. Actualizaciones de producción que el agente debe preservar

La versión actual de este stack tiene algunos comportamientos importantes que el agente debe preservar.

Máquina de un único propietario

El pipeline de fitness debe tener una máquina autoritativa siempre encendida. No se debe permitir que dos ordenadores diferentes generen y desplieguen informes contra el mismo repositorio de salida.

La máquina activa es la responsable de las tareas de sincronización con proveedores, la generación de informes, la generación adaptativa de entrenamientos, el despliegue en GitHub Pages y las comprobaciones del watchdog.

Otras máquinas pueden consultar los informes o alojar paneles locales, pero no deben regenerar los informes de fitness.

Pipeline secuencial en lugar de conjeturas escalonadas de cron

Los pipelines matutino y nocturno deben ejecutarse como fases ordenadas:

  1. sincronizar datos de proveedores
  2. verificar los datos requeridos del día
  3. generar informes
  4. desplegar
  5. enviar notificaciones
  6. generar resúmenes de voz, si se utilizan
  7. ejecutar la validación del watchdog

El error de antes era programar esos pasos a intervalos fijos de reloj confiando en que cada fase anterior hubiera terminado. El patrón más adecuado es un único orquestador que ejecute cada fase solo después de que la anterior haya finalizado correctamente.

Barrera de recuperación WHOOP del mismo día

Para este stack, la recuperación WHOOP del día es una barrera obligatoria para el coaching. Si falta la recuperación de hoy, el sistema puede seguir publicando un informe web con avisos de fuente obsoleta, pero debe retener el envío de correos, voz, coaching por Telegram y entrenamientos adaptativos.

Esa única regla evita el peor modo de fallo: una recomendación aparentemente sólida basada en la recuperación de ayer.

Gestión 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 de ayer antes de regenerar, en lugar de fiarse de un archivo JSON local existente solo porque exista.

Solo zonas de FC reales de Garmin

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 por zona, utilízalo. Si no, oculta ese gráfico o márcalo como no disponible.

Revisión de la ejecución del plan

El informe nocturno funciona mejor cuando compara el plan del día con los datos reales del día:

  • entrenamiento BJJ planificado vs entrenamiento BJJ de WHOOP
  • sesión Speediance planificada vs sesiones Speediance completadas
  • carrera planificada vs distancia de carrera de Garmin
  • pasos planificados vs pasos de Garmin

Esto convierte el informe nocturno en un ciclo de retroalimentación en lugar de ser solo un resumen.

Modo sombra de Open Wearables

Open Wearables es útil como futura capa de abstracción, pero no migraría de golpe un sistema de informes personales que ya esté funcionando. La migración más segura es el modo sombra:

  1. mantener el pipeline basado en archivos existente como autoritativo
  2. importar o replicar los datos de Garmin/WHOOP en Open Wearables
  3. exportar los datos de Open Wearables de vuelta a archivos JSON sombra
  4. comparar los archivos sombra con los archivos de producción
  5. promover 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?»

Garmin es donde el informe obtiene:

  • distancia
  • ritmo y velocidad
  • duración
  • FC media y máxima
  • zonas de frecuencia cardiaca
  • cadencia
  • potencia
  • efecto de entrenamiento
  • metadatos de la actividad
  • detalle cardiorespiratorio y de entrenamiento más amplio que WHOOP no enfatiza con tanta riqueza

Repositorio público a usar

Recomendado: cyberjunky/python-garminconnect

GitHub: https://github.com/cyberjunky/python-garminconnect

Por qué importa:

  • está posicionado activamente como el wrapper Python de Garmin Connect que conviene usar
  • expone una superficie de endpoints de Garmin muy amplia
  • incluye ejemplos y patrones de gestión de tokens
  • sustituyó suposiciones de autenticación antiguas que se rompieron con cambios previos de Garmin

Nota importante de compatibilidad con Garmin

Históricamente, muchas builds utilizaban garth.

GitHub: https://github.com/matin/garth

Pero garth ahora está explícitamente obsoleto. Esto importa porque un agente no debería 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 crudos de Garmin directamente en la lógica de tu informe final. Normalízalos primero en campos como:

  • calendarDate
  • totalSteps
  • restingHeartRate
  • sleepingSeconds
  • bodyBattery
  • activityName
  • activityType
  • durationSeconds
  • distanceMeters
  • distanceMiles
  • averageHR
  • maxHR
  • calories
  • trainingEffect
  • cadence
  • power

Patrón de almacenamiento recomendado

  • data/garmin/raw/YYYY-MM-DD.json
  • data/garmin/normalized/YYYY-MM-DD.json
  • data/garmin/summary/latest.json

Esto te ofrece tanto reproducibilidad como acceso rápido al informe.


7. WHOOP: la capa de recuperación y disposición

WHOOP es lo que hace que los informes resulten útiles como motor de decisión en lugar de ser solo un registro de actividades.

Aporta:

  • puntuación de recuperación
  • HRV
  • frecuencia cardiaca en reposo
  • rendimiento del sueño
  • carga (strain)
  • contexto de ciclo
  • encuadre de disposición para recomendaciones matutinas y nocturnas

API pública a usar

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 respuestas del diario o anotaciones de hábitos, no puedes confiar en un endpoint público de la API de WHOOP para eso. Las opciones prácticas son:

  • exportación manual en CSV desde WHOOP
  • tu propia capa de diario paralela
  • metadatos separados que adjuntas después de la sincronización

Esa limitación debería mencionarse claramente en el artículo porque afecta a cualquier desarrollo serio.

Ejemplo ejecutable mínimo 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_score
  • hrv_rmssd_milli
  • resting_heart_rate
  • spo2_percentage
  • skin_temp_celsius
  • sleep_performance_percentage
  • respiratory_rate
  • strain
  • cycle_start
  • cycle_end
  • workout_sport_name

Patrón de almacenamiento recomendado

  • data/whoop/raw/recovery.json
  • data/whoop/raw/sleep.json
  • data/whoop/raw/workouts.json
  • data/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, esta no es una plataforma de desarrollo pública oficial y bien definida. El agente debería 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 Speediance público original:

hbui3/UnofficialSpeedianceWorkoutManager
GitHub: https://github.com/hbui3/UnofficialSpeedianceWorkoutManager

Estos repositorios son el punto de partida importante porque muestran cómo:

  • autenticar contra los endpoints de Speediance
  • inspeccionar datos de entrenamientos y respuestas de la API
  • navegar/exportar el historial de entrenamiento
  • gestionar plantillas/entrenamentos de forma amigable para escritorio
  • manejar problemas prácticos como la visualización de zonas horarias y el manejo de pesos en sistema imperial/métrico

Por qué importan estos repositorios

Utiliza el fork de ANPC86 SmartGymWorkoutManager como base práctica para el patrón de integración de 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 Speediance fuera de la aplicación oficial.

Advertencia de estabilidad

El proyecto original señala que Speediance ha estado implementando mejoras de seguridad. Eso significa que:

  • esta integración puede romperse
  • las cabeceras y el comportamiento de autenticación pueden cambiar
  • los endpoints pueden cambiar de ubicación
  • deberías 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 utilizas ANPC86/SmartGymWorkoutManager como punto de partida, consultando al mismo tiempo el upstream hbui3/UnofficialSpeedianceWorkoutManager para conocer el contexto original, el enfoque limpio es:

  1. Ejecuta su app o capa cliente en local
  2. Autentícate con tu cuenta Speediance
  3. Extrae el historial de entrenamientos de los métodos de la API que expone
  4. Exporta JSON normalizado a tu propio directorio de datos

Pseudoejemplo utilizando ese patrón de cliente:

# Adapta esto alrededor del api_client.py en:
# 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 de Speediance

Normaliza en campos como:

  • training_id
  • date
  • title
  • duration_seconds
  • calories
  • total_volume
  • exercise_count
  • template_name
  • planned_duration
  • actual_duration
  • exercise_breakdown
  • estimated_1rm

Modelo de datos de buenas prácticas

Para un sistema de informes serio, mantén dos índices:

  1. bySession
  • un registro por entrenamiento completado
  1. byExercise
  • un flujo de registros por nombre de movimiento
  • incluye peso, repeticiones, lado, id de sesión, marca temporal

Esa estructura hace que las gráficas de progresión y la detección de PR resulten triviales más adelante.

Patrón de almacenamiento recomendado

  • data/speediance/raw/monthly/YYYY-MM.json
  • data/speediance/normalized/history.json
  • data/speediance/normalized/by_exercise.json
  • data/speediance/dashboard/latest.json

Capturas adaptativas de entrenamientos Speediance

La versión más avanzada de esta compilación no solo lee los entrenamientos Speediance completados.

También crea entrenamientos planificados a partir de datos de preparación en tiempo real.

El patrón útil es:

  1. Cargar la recuperación de WHOOP del mismo día, la carga actual, la carga BJJ, la batería corporal Garmin, la FC en reposo, la carga reciente de carrera, el clima y el historial reciente del plan Speediance.
  2. Clasificar el día en una categoría como build, maintain, recover, protect o post_bjj_brutal.
  3. Seleccionar un implemento Speediance para todo el entrenamiento, normalmente asas, barra o cuerda.
  4. Elegir ejercicios en el dispositivo solo para el entrenamiento principal Speediance.
  5. Añadir de cero a dos accesorios fuera de Speediance solo cuando la recuperación lo permita.
  6. Escribir el plan en data/training_plans/YYYY-MM-DD_context.json.
  7. Usar 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 repetición, comparar la firma del nuevo entrenamiento con las instantáneas recientes del plan. La versión de producción utiliza 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 para que un entrenamiento que reaparece siga siendo actual y se pueda buscar.


9. Cronometer: la capa de contexto nutricional

Sea cual sea la aplicación de nutrición exacta que utilices, la función es la misma: proporcionar al informe contexto sobre la ingesta energética.

Esto importa porque la carga de entrenamiento sin contexto nutricional lleva 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 depender de una API de nutrición en tiempo real en el momento de renderizar. Usar una de:

  • Exportación CSV
  • Ingestión por webhook
  • Sincronización programada a JSON normalizado

Normalizar en campos como:

  • calories_consumed
  • protein_g
  • carbs_g
  • fat_g
  • fiber_g
  • target_calories
  • estimated_deficit

Patrón de almacenamiento recomendado

  • data/nutrition/raw/YYYY-MM-DD.csv
  • data/nutrition/normalized/YYYY-MM-DD.json
  • data/nutrition/latest.json

10. 8Sleep: la capa de contexto del sueño de llegada tardía

8Sleep es opcional, pero si está configurado, el agente debe tratarlo como cualquier otro conector: sincronizar primero, normalizar después, renderizar desde los archivos al final.

El comportamiento importante es el manejo de datos tardíos. Los datos del sueño pueden cambiar después de la primera ejecución matutina, por lo que una reejecución manual o un reintento programado debe forzar la actualización tanto de hoy como de ayer antes de regenerar el informe.

Normalizar campos como:

  • sleep_score
  • sleep_start
  • sleep_end
  • time_in_bed_seconds
  • time_asleep_seconds
  • hrv
  • resting_heart_rate
  • temperature_adjustments
  • away_mode

Patrón de almacenamiento recomendado:

  • data/eightsleep/raw/YYYY-MM-DD.json
  • data/eightsleep/normalized/YYYY-MM-DD.json
  • data/eightsleep/normalized/latest.json

11.

Lo que OpenClaw realmente hace en esta pila

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 una programación
  • almacenar salidas estables
  • comparar fuentes
  • generar el HTML del informe
  • publicar enlaces
  • producir resúmenes amigables para humanos a partir de los datos normalizados

Esto significa que el código de informes debe leer archivos como:

  • data/garmin/summary/latest.json
  • data/whoop/normalized/latest.json
  • data/speediance/normalized/history.json
  • data/nutrition/latest.json
  • data/eightsleep/normalized/latest.json

El generador de informes nunca debería necesitar saber cómo funciona la autenticación de Garmin ni cómo cambiaron los encabezados de Speediance esta semana.


12. Estructura de directorios construible por un agente

Esta es una estructura que un agente puede crear antes de que cualquier autenticación real de 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 es parte de la interfaz. Hazla lo suficientemente sencilla para que un agente futuro pueda inspeccionar el sistema, encontrar cada conector, volver a ejecutar una sola sincronización y comparar las cargas útiles sin procesar con las salidas normalizadas.


13. Ejemplo de patrón para el generador de informes

Una vez que cada conector escribe JSON normalizado, el código real del informe se vuelve simple.

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>Informe diario de fitness</h1>
    <ul>
      <li>Recuperación: {summary['recovery']}</li>
      <li>HRV: {summary['hrv']}</li>
      <li>RHR: {summary['rhr']}</li>
      <li>Pasos: {summary['steps']}</li>
      <li>Body Battery: {summary['body_battery']}</li>
      <li>Volumen de pesas: {summary['lifting_volume']}</li>
      <li>Calorías ingeridas: {summary['calories_in']}</li>
      <li>8Sleep Puntuación: {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 estable, la capa de informes se vuelve aburrida de la mejor manera posible.


14. Para qué sirve realmente cada conector

Este es el modelo mental más sencillo:

WHOOP

Úsalo para:

  • recuperación
  • HRV
  • RHR
  • rendimiento del sueño
  • carga
  • encuadre de la disposición

Garmin

Úsalo para:

  • detalle de carrera y cardio
  • ritmo, potencia, cadencia
  • zonas de FC
  • efecto de entrenamiento
  • historial detallado de actividades

Speediance

Úsalo para:

  • historial de entrenamientos de fuerza
  • volumen total
  • detalle del ejercicio
  • ejecución de la sesión planificada frente a la real
  • progresión a nivel de movimiento si construyes indexación por ejercicio

Aplicación 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 específicas de cada cama
  • comprobaciones cruzadas del contexto del sueño frente a WHOOP y Garmin

OpenClaw los combina todos en una única superficie de informe y recomendaciones.


15. Entregables de conexión por sistema

Esta es la lista de comprobación que el agente de implementación debe satisfacer antes de pulir la interfaz del informe.

Puntos de conexión de Garmin

  • Biblioteca: garminconnect de cyberjunky/python-garminconnect
  • Autenticación: correo electrónico/contraseña de Garmin Connect con la gestión 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,骑行/cardio
    • detalle de actividad, cuando esté disponible, para zonas de FC, ritmo, cadencia, potencia, efecto de entrenamiento
  • Salida normalizada: data/garmin/summary/latest.json

Puntos de conexión WHOOP

  • Documentación de la API: https://developer.whoop.com/api
  • Autenticación: token de acceso OAuth2 + flujo de token de actualización
  • URL base: https://api.prod.whoop.com/developer/v2
  • Grupos de endpoints mínimos:
    • /cycle para contexto de strain/ciclo
    • /recovery para puntuación de recuperación, HRV y FC en reposo
    • /activity/sleep para rendimiento del sueño y horarios de sueño
    • /activity/workout para entrenamientos y datos de strain de WHOOP
    • /user/profile/basic y /user/measurement/body para contexto de perfil/cuerpo cuando sea necesario
  • Salida normalizada: data/whoop/normalized/latest.json

Puntos de conexión Speediance

  • Extracción pública para esta build: 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 ejercicio/sesión
    • metadatos de entrenamientos/plantillas personalizados si quieres informes de planificado vs. real
    • captura de respuestas sin procesar de API/debug sin secretos
  • Salidas normalizadas:
    • data/speediance/normalized/history.json
    • data/speediance/normalized/by_exercise.json

Puntos de conexión de Cronometer

  • Fuente pública: exports/integraciones de https://cronometer.com/
  • Enfoque de implementación recomendado: exportación CSV o entrega programada de archivos, no una dependencia de API en tiempo de renderizado
  • Campos mínimos: fecha, calorías, proteínas, carbohidratos, grasas, fibra y cualquier micronutriente que desees incluir en el análisis de recuperación
  • Salida normalizada: data/nutrition/latest.json

Puntos de conexión 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
    • horarios de sueño
    • tiempo dormido y tiempo en cama
    • HRV y FC en reposo cuando estén disponibles
    • temperatura y contexto del modo ausente cuando estén disponibles
  • Salida normalizada: data/eightsleep/normalized/latest.json

Punto de conexión de generación de informes

El generador de informes solo debería leer archivos normalizados estables y snapshots 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 superficie de conexión real. Todo lo que está aguas 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 individual:

  1. Normaliza cada proveedor en tu propio esquema
    Nunca dejes que un informe dependa de la forma del payload del proveedor.

  2. Conserva instantáneas (snapshots) sin procesar
    Cuando una sincronización se rompe, los payloads sin procesar te salvan.

Nunca renderices desde APIs en vivo si el informe es sensible al tiempo
Sincroniza primero, renderiza después.

  1. Trata las integraciones no oficiales como adaptadores desechables
    Especialmente Speediance.

  2. Haz que Garmin y WHOOP se complementen, no que compitan
    WHOOP = preparación. Garmin = detalle de ejecución.

  3. 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.

  4. Condiciona el entrenamiento a la preparación de hoy, no a la de ayer
    Si falta la recuperación del mismo día, el sistema debería degradarse a informes solo web.

  5. Guarda el plan antes de juzgar el día
    Una puntuación de adherencia nocturna solo funciona si el plan de la mañana o post-BJJ se almacenó como dato.

  6. Prueba los 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 final de referencias de implementación

Estas son las referencias públicas que un agente de codificación de IA debería recibir primero al implementar este sistema:

  • OpenClaw como capa de orquestación
  • Conector de Garmin: https://github.com/cyberjunky/python-garminconnect
  • Contexto histórico de autenticación de Garmin: https://github.com/matin/garth (obsoleto; usar como contexto, no como centro de una nueva construcción)
  • API oficial para desarrolladores de WHOOP: https://developer.whoop.com/api
  • Extracción pública de Speediance para esta compilación: https://github.com/clawdassistant85-netizen/speediance-smartgym-workout-manager
  • Referencia upstream/original de Speediance: https://github.com/hbui3/UnofficialSpeedianceWorkoutManager
  • Referencia del generador/plantilla de informe: https://github.com/tobyglenn/scriptsJinja
  • Exportaciones de nutrición de Cronometer: https://cronometer.com/
  • Contrato del conector 8Sleep: sincronización respaldada por 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.

#openclaw#garmin#whoop#speediance#informes de fitness#sistemas de IA