Brief do Agente: Construir OpenClaw Conectores de Relatórios de Fitness para Garmin, WHOOP, Speediance e Mais
Um brief de implementação pronto para agentes para construir OpenClaw conectores de relatórios de fitness em Garmin, WHOOP, Speediance, Cronometer, 8Sleep, snapshots JSON normalizados e repositórios públicos do GitHub.
Este artigo deve ser entregue a um agente de codificação de IA como um brief de implementação.
O objetivo não é transplantar minha máquina privada nem fazer engenharia reversa dos meus arquivos. O objetivo é que um agente leia esta página e construa conectores funcionais para os sistemas de fitness: Garmin, WHOOP, Speediance, Cronometer, 8Sleep, e o opcional Open Wearables.
A instrução central é simples: trate cada fornecedor como um conector, persista snapshots JSON normalizados e faça o gerador de relatórios consumir apenas esses snapshots. Essa separação transforma a bagunça de APIs específicas de fornecedor em um sistema construível por agente.
O agente deve construir a mesma classe de conexões, não depender dos meus caminhos locais exatos:
- Garmin para cardio, carga de treino, pace, zonas de frequência cardíaca e detalhes da atividade
- WHOOP para contexto de recuperação, HRV, RHR, sono, strain e readiness
- Speediance para histórico de sessões de força, volume, calorias, templates e detalhes de exercícios
- Cronometer para contexto de nutrição
- 8Sleep para contexto de sono atrasado quando disponível
- OpenClaw como a camada de orquestração que executa sincronizações, normaliza dados e gera relatórios
Também aborda os projetos do GitHub, APIs públicas, contratos de dados, modos de falha e verificações de aceitação que um agente de implementação precisa para produzir uma stack funcional sem ver meu repositório privado.
1. Tarefa do agente
Construa uma stack de relatórios de fitness OpenClaw local-first que consiga se conectar aos sistemas, normalizar seus dados e gerar relatórios sem chamadas ao vivo de fornecedor durante a renderização.
O agente deve produzir:
- Scripts de conector
Um job de sincronização por sistema: Garmin, WHOOP, Speediance, Cronometer e 8Sleep quando configurado. - Snapshots brutos
Payloads brutos com marcação de data em JSON ou derivados de CSV para depurar mudanças de fornecedor. - Contratos normalizados
Arquivos JSON estáveis nos quais o gerador de relatórios pode confiar mesmo quando os payloads dos fornecedores mudam. - Relatório matinal
Um relatório que combina recuperação, sono, readiness, carga de treino, nutrição e o plano do dia. - Snapshot de treino adaptativo
Um plano datado de Speediance/BJJ/corrida derivado do readiness do mesmo dia e da carga recente. - Relatório noturno
Uma revisão plano vs. real comparando o que foi recomendado com a realidade de Garmin, WHOOP e Speediance. - Saída publicável
HTML estático e JSON legível por máquina que pode ser implantado no GitHub Pages ou em outro host estático.
Não construa isso como "um script que chama seis APIs e renderiza HTML ao vivo." Isso é frágil.
2. Arquitetura que o agente deve implementar
Construa em quatro camadas:
- Camada de conector
Um job de sincronização por plataforma. - --max-tokens 8192 --no-fallback --system Você é um tradutor profissional determinístico. Retorne apenas o objeto JSON final solicitado. Não inclua raciocínio nem comentários.
Camada de dados normalizados
Cada sincronização grava snapshots JSON estáveis.
3. Camada de análise/relatórios
O código do relatório lê apenas JSON normalizado.
4. Camada de apresentação
HTML, painéis, briefings diários, posts no Telegram, resumos em voz.
Essa separação é o que torna o sistema mantível.
Contrato de implementação de IA
Agente, construa este contrato antes de escrever qualquer interface de painel:
- Entradas: apenas variáveis de ambiente e credenciais de fornecedores; nunca codifique segredos diretamente em arquivos de origem.
- Saídas de sincronização: um snapshot JSON bruto por coleta de fornecedor, além de um arquivo JSON normalizado por fornecedor.
- Entradas do relatório: apenas JSON normalizado. O construtor de relatórios não deve chamar Garmin, WHOOP, Speediance, ou Cronometer diretamente.
- Modo de falha: se um conector falhar, preserve o arquivo normalizado do último estado válido de ontem e marque essa fonte como desatualizada no relatório.
- Auditabilidade: mantenha payloads brutos suficientes para depurar mudanças nas APIs dos fornecedores sem registrar tokens, cookies, senhas ou cabeçalhos privados.
- Portão de envio: ações de e-mail, voz, Telegram e treino adaptativo devem exigir dados de recuperação pontuados do mesmo dia. Um relatório web ainda pode ser gerado em modo degradado, mas o sistema não deve enviar orientações confiantes a partir de uma recuperação desatualizada.
- Snapshots do plano: planos de treino adaptativos devem ser escritos como snapshots JSON diários antes de serem enviados para qualquer lugar. O relatório noturno pode então comparar o plano com o que realmente aconteceu.
Variáveis de ambiente mínimas para um build pronto para o 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. Definição de pronto
Um agente de implementação só está pronto quando esses artefatos existem e podem ser regenerados:
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, se 8Sleep estiver configuradodata/training_plans/YYYY-MM-DD_morning.jsonreports/morning/latest.htmlreports/nightly/latest.html- um portão de envio que retém envios de e-mail, voz, Telegram e treino adaptativo quando a recuperação WHOOP pontuada do mesmo dia estiver ausente
- avisos de fonte desatualizada quando um conector falha, mas os dados normalizados do último estado válido de ontem estão disponíveis
- uma verificação sem segredos provando que tokens, cookies, senhas e cabeçalhos privados não foram commitados
Se o agente não conseguir se autenticar com um fornecedor durante o desenvolvimento, ele ainda deve implementar a interface do conector, o .env.example, fixtures falsos, o normalizador, o tratamento de fontes obsoletas e reportar a integração.
4. Projetos públicos e referências de origem
Estas são as partes públicas que um agente deve usar como referências de implementação.
Checklist rápido do GitHub/API:
- Garmin connector:
https://github.com/cyberjunky/python-garminconnect - Garmin legacy auth context:
https://github.com/matin/garth - WHOOP official developer API:
https://developer.whoop.com/api - Speediance public extraction for this build:
https://github.com/clawdassistant85-netizen/speediance-smartgym-workout-manager - Speediance working fork this was extracted from:
https://github.com/ANPC86/SmartGymWorkoutManager - Speediance upstream/original reference:
https://github.com/hbui3/UnofficialSpeedianceWorkoutManager - Report generator/template reference:
https://github.com/tobyglenn/scriptsJinja - Cronometer exports/integrations:
https://cronometer.com/
OpenClaw
- Plataforma/orquestrador: OpenClaw
- Função: agendar jobs de sincronização, executar transformações, gerar relatórios, publicar saídas
Garmin
- Cliente Python principal: cyberjunky/python-garminconnect
GitHub:https://github.com/cyberjunky/python-garminconnect - Biblioteca de autenticação legada que já foi relevante: matin/garth
GitHub:https://github.com/matin/garth - Nota de status: o
garthestá deprecado; opython-garminconnectagora usa fluxos de autenticação Garmin mais recentes e é a base em torno da qual se deve construir.
WHOOP
- Documentação oficial da API para desenvolvedores:
https://developer.whoop.com/api - Superfície pública da API: endpoints OAuth2 + REST para recuperação, ciclos, sono, treinos, perfil, medidas corporais
- Existem wrappers opcionais da comunidade, mas um conector construído pelo agente deve se ancorar na API oficial para desenvolvedores do WHOOP sempre que possível.
Speediance
- Referência prática de implementação pública do Speediance: ANPC86/SmartGymWorkoutManager
GitHub:https://github.com/ANPC86/SmartGymWorkoutManager - Linhagem do projeto original / referência pública original: hbui3/UnofficialSpeedianceWorkoutManager
GitHub:https://github.com/hbui3/UnofficialSpeedianceWorkoutManager - Use o fork ANPC86 SmartGymWorkoutManager como referência prática de conexão, pois ele contém trabalho útil em torno de histórico, exportações, debug de API, tratamento de fuso horário e unidades.
- Esta é uma integração não oficial do Speediance e deve ser tratada como instável por padrão.
Nutrição
- Site do produto Cronometer / exportações / integrações:
https://cronometer.com/ - Trate o Cronometer como uma fonte estruturada de exportação de nutrição, e não como uma dependência direta mágica de relatórios.
5. Atualizações de produção que o agente deve preservar
A versão atual desta stack tem alguns comportamentos importantes que o agente deve preservar.
Máquina com dono único
O pipeline de fitness deve ter uma máquina autoritativa que esteja sempre ligada. Não permita que dois computadores diferentes gerem e implantem relatórios no mesmo repositório de saída.
A máquina ativa é responsável pelos jobs de sincronização de fornecedores, geração de relatórios, geração adaptativa de treinos, deploys no GitHub Pages e verificações de watchdog.
Outras máquinas podem visualizar os relatórios ou hospedar painéis locais, mas não devem regenerar os relatórios de fitness.
Pipeline sequencial em vez de palpites de cron escalonados
Os pipelines matinal e noturno devem rodar como fases ordenadas:
- sincronizar dados do fornecedor
- verificar os dados obrigatórios do mesmo dia
- gerar os relatórios
- fazer o deploy
- enviar as notificações
- gerar os resumos em voz, se usados
- executar a validação do watchdog
O erro antigo é agendar essas etapas em offsets fixos de relógio e torcer para que cada fase anterior tivesse terminado. O padrão melhor é um único orquestrador que executa cada fase somente após a anterior sair de forma limpa.
Gate de recuperação WHOOP do mesmo dia
Para esta stack, a recuperação WHOOP do mesmo dia é um gate obrigatório para a orientação. Se a recuperação de hoje estiver ausente, o sistema ainda pode publicar um relatório web com avisos de fonte desatualizada, mas deve reter os envios por e-mail, voz, Telegram e treinos adaptativos.
Essa única regra evita o pior modo de falha: uma recomendação plausível construída a partir da recuperação de ontem.
Tratamento de dados atrasados do 8Sleep
O 8Sleep pode atualizar após a primeira execução matinal. Uma reexecução deve forçar a atualização de hoje e de ontem antes de regenerar, em vez de confiar em um arquivo JSON local existente só porque ele existe.
Apenas zonas de FC reais do Garmin
Não invente distribuições de zonas de frequência cardíaca a partir da frequência cardíaca média. Se o detalhe de atividade do Garmin incluir dados de tempo na zona, use-os. Se não incluir, oculte esse gráfico ou marque-o como indisponível.
Revisão da execução do plano
O relatório noturno agora funciona melhor quando compara o plano do dia com os dados reais do dia:
- treino de BJJ planejado vs treino de BJJ WHOOP
- sessão de Speediance planejada vs sessões de Speediance concluídas
- corrida planejada vs distância de corrida do Garmin
- passos planejados vs passos do Garmin
Isso transforma o relatório noturno em um ciclo de feedback, em vez de apenas um resumo.
Modo shadow do Open Wearables
O Open Wearables é útil como uma futura camada de abstração, mas eu não migraria um sistema pessoal de relatórios em funcionamento de uma vez só. A migração mais segura é o modo shadow:
- manter o pipeline existente baseado em arquivos como autoritativo
- importar ou espelhar os dados de Garmin/WHOOP no Open Wearables
- exportar os dados do Open Wearables de volta para arquivos JSON shadow
- comparar os arquivos shadow com os arquivos de produção
- promover somente depois que contagens, datas e registros do mesmo dia coincidirem
Os arquivos shadow nunca devem sobrescrever as entradas de produção durante o piloto.
6. Garmin: a camada de cardio e detalhes de atividade
Se WHOOP responde "o quanto estou recuperado?", Garmin responde "o que exatamente eu fiz?"
Garmin é onde o relatório obtém:
- distância
- ritmo e velocidade
- duração
- FC média e máxima
- zonas de frequência cardíaca
- cadência
- potência
- efeito de treino
- metadados da atividade
- detalhes mais abrangentes de cardio/treino que WHOOP não enfatiza tão profundamente
Repositório público a usar
Recomendado: cyberjunky/python-garminconnect
GitHub:
https://github.com/cyberjunky/python-garminconnect
Por que isso importa:
- ele está ativamente posicionado como o wrapper Python do Garmin Connect a ser usado
- expõe uma superfície muito grande de endpoints do Garmin
- inclui exemplos e padrões de tratamento de tokens
- substituiu pressuposições de autenticação antigas que quebraram em mudanças anteriores do Garmin
Nota importante de compatibilidade do Garmin
Historicamente, muitas builds usavam garth.
GitHub:
https://github.com/matin/garth
Mas garth agora está explicitamente descontinuado. Isso importa porque um agente não deve basear uma nova implementação em autenticação descontinuada.
Exemplo mínimo executável em 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))
O que normalizar a partir do Garmin
Não despeje payloads brutos do Garmin diretamente na lógica do seu relatório final. Normalize-os primeiro em campos como:
calendarDatetotalStepsrestingHeartRatesleepingSecondsbodyBatteryactivityNameactivityTypedurationSecondsdistanceMetersdistanceMilesaverageHRmaxHRcaloriestrainingEffectcadencepower
Padrão de armazenamento recomendado
data/garmin/raw/YYYY-MM-DD.jsondata/garmin/normalized/YYYY-MM-DD.jsondata/garmin/summary/latest.json
Isso te dá tanto capacidade de replay quanto acesso rápido ao relatório.
7. WHOOP: a camada de recuperação e prontidão
WHOOP é o que torna os relatórios úteis como um motor de decisão, em vez de apenas um registro de atividades.
Ele contribui com:
- pontuação de recuperação
- HRV
- frequência cardíaca em repouso
- desempenho do sono
- strain
- contexto do ciclo
- enquadramento de prontidão para recomendações matinais e noturnas
API pública a usar
Use a API oficial para desenvolvedores do WHOOP:
- Documentação:
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
Limitação crítica
Uma das constatações de implementação mais importantes: os dados de diário não estão disponíveis na API do WHOOP.
Se você quer respostas de diário ou anotações de hábitos, não pode contar com um endpoint público da API do WHOOP para isso. As opções práticas são:
- exportação manual de CSV a partir do WHOOP
- sua própria camada paralela de diário
- metadados separados que você anexa após a sincronização
Essa limitação deve ser declarada de forma clara no artigo porque afeta qualquer construção séria.
Exemplo mínimo executável do 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))
O que normalizar a partir do WHOOP
Normalize em campos como:
recovery_scorehrv_rmssd_milliresting_heart_ratespo2_percentageskin_temp_celsiussleep_performance_percentagerespiratory_ratestraincycle_startcycle_endworkout_sport_name
Padrão de armazenamento recomendado
data/whoop/raw/recovery.jsondata/whoop/raw/sleep.jsondata/whoop/raw/workouts.jsondata/whoop/normalized/latest.json
8. Speediance: a camada de treino de força
O Speediance é o conector mais incomum de toda a stack.
Diferente do Garmin e do WHOOP, este não é uma plataforma oficial pública e bem estruturada para desenvolvedores. O agente deve usar esses repositórios públicos como referências de conexão:
Extração/referência pública: https://github.com/clawdassistant85-netizen/speediance-smartgym-workout-manager
ANPC86/SmartGymWorkoutManager
GitHub: https://github.com/ANPC86/SmartGymWorkoutManager
Esse repositório é, por si só, um fork pessoal / continuação do projeto público original do Speediance:
hbui3/UnofficialSpeedianceWorkoutManager
GitHub: https://github.com/hbui3/UnofficialSpeedianceWorkoutManager
Esses repositórios são o ponto de partida importante porque mostram como:
- autenticar nos endpoints do Speediance
- inspecionar dados de treino e respostas da API
- navegar/exportar histórico de treinos
- gerenciar templates/treinos de forma amigável para desktop
- lidar com questões práticas como exibição de fuso horário e tratamento de peso em imperial/métrico
Por que esses repositórios são importantes
Use o fork do ANPC86 SmartGymWorkoutManager como base prática para o padrão de integração com o Speediance, preservando a referência upstream hbui3 para fins de proveniência. Juntos, eles são as referências públicas mais claras para trabalhar com dados do Speediance fora do aplicativo oficial.
Aviso de estabilidade
O projeto original observa que o Speediance vem implementando melhorias de segurança. Isso significa:
- esta integração pode quebrar
- cabeçalhos e comportamento de autenticação podem mudar
- endpoints podem mudar
- você deve isolar esse conector atrás de uma etapa de normalização para que seus relatórios sobrevivam às mudanças do lado do fornecedor
Padrão executável mínimo para Speediance
Se você usar ANPC86/SmartGymWorkoutManager como ponto de partida, consultando o upstream hbui3/UnofficialSpeedianceWorkoutManager para obter o contexto original, a abordagem mais limpa é:
- Execute a camada de aplicativo ou cliente localmente
- Autentique-se com sua conta Speediance
- Extraia o histórico de treinos a partir dos métodos da API que ele expõe
- Exporte JSON normalizado para o seu próprio diretório de dados
Pseudoexemplo usando esse padrão de cliente:
# Modele isso em torno do api_client.py em:
# 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))
O que normalizar a partir do Speediance
Normalize em campos como:
training_iddatetitleduration_secondscaloriestotal_volumeexercise_counttemplate_nameplanned_durationactual_durationexercise_breakdownestimated_1rm
Modelo de dados de boas práticas
Para um sistema de relatórios sério, mantenha dois índices:
- bySession
- um registro por treino concluído
- byExercise
- um fluxo de registros por nome de movimento
- inclui peso, repetições, lado, id da sessão, timestamp
Essa estrutura torna gráficos de progressão e detecção de PRs (recordes pessoais) triviais mais tarde.
Padrão de armazenamento recomendado
data/speediance/raw/monthly/YYYY-MM.jsondata/speediance/normalized/history.jsondata/speediance/normalized/by_exercise.jsondata/speediance/dashboard/latest.json
Snapshots adaptáveis de treinos do Speediance
A versão mais avançada desta build não lê apenas treinos concluídos do Speediance.
Ele também cria treinos planejados a partir de dados de prontidão em tempo real.
O padrão útil é:
- Carregue a recuperação do mesmo dia WHOOP, a carga atual, a carga BJJ, a bateria corporal Garmin, a FC em repouso, a carga de corrida recente, o clima e o histórico recente do plano Speediance.
- Classifique o dia em um bucket como
build,maintain,recover,protectoupost_bjj_brutal. - Selecione um implemento Speediance para o treino inteiro, geralmente alças, barra ou corda.
- Escolha apenas exercícios disponíveis no dispositivo para o treino central de Speediance.
- Adicione de zero a dois acessórios fora do Speediance somente quando a recuperação permitir.
- Escreva o plano em
data/training_plans/YYYY-MM-DD_context.json. - Use o snapshot tanto para a recomendação da manhã quanto para a revisão da execução do plano à noite.
Para controle de repetição, compare a assinatura do novo treino com os snapshots recentes do plano. A versão de produção usa uma janela de exclusividade rolante que cresce até 30 dias e sempre carimba o título do treino com a data de hoje, de modo que um treino que reapareça ainda pareça novo e pesquisável.
9. Cronometer: a camada de contexto nutricional
Seja qual for o aplicativo de nutrição exato que você use, o papel é o mesmo: fornecer ao relatório o contexto da ingestão energética.
Isso importa porque carga de treino sem contexto nutricional leva a conclusões ruins.
O relatório deve ser capaz de perguntar:
- A recuperação estava baixa porque a carga de treino foi alta?
- Ou porque o sono foi ruim e a ingestão calórica foi baixa?
- O atleta estava subalimentado em relação ao gasto?
Conselhos práticos de implementação
Não dependa de uma API de nutrição em tempo real no momento da renderização. Use uma das opções:
- Exportação em CSV
- Ingestão via webhook
- Sincronização agendada para JSON normalizado
Normalize em campos como:
calories_consumedprotein_gcarbs_gfat_gfiber_gtarget_caloriesestimated_deficit
Padrão de armazenamento recomendado
data/nutrition/raw/YYYY-MM-DD.csvdata/nutrition/normalized/YYYY-MM-DD.jsondata/nutrition/latest.json
10. 8Sleep: a camada de contexto de sono que chega tarde
8Sleep é opcional, mas, se estiver configurado, o agente deve tratá-lo como qualquer outro conector: primeiro sincronize, depois normalize e, por fim, renderize a partir dos arquivos.
O comportamento importante é o tratamento de dados atrasados. Os dados de sono podem mudar após a primeira execução da manhã, então uma reexecução manual ou uma nova tentativa agendada deve forçar a atualização tanto de hoje quanto de ontem antes de regenerar o relatório.
Normalize campos como:
sleep_scoresleep_startsleep_endtime_in_bed_secondstime_asleep_secondshrvresting_heart_ratetemperature_adjustmentsaway_mode
Padrão de armazenamento recomendado:
data/eightsleep/raw/YYYY-MM-DD.jsondata/eightsleep/normalized/YYYY-MM-DD.jsondata/eightsleep/normalized/latest.json
11. --max-tokens 8192 --no-fallback --system Você é um tradutor profissional determinístico. Retorne apenas o objeto JSON final solicitado. Não inclua raciocínio nem comentários.
O que OpenClaw realmente faz nesta stack
OpenClaw não é a fonte de dados. É a camada de orquestração e raciocínio.
Sua função é:
- executar jobs de sincronização de forma agendada
- armazenar saídas estáveis
- comparar fontes
- gerar HTML de relatórios
- publicar links
- produzir resumos de fácil leitura a partir dos dados normalizados
Isso significa que o código de relatórios deve ler de arquivos como:
data/garmin/summary/latest.jsondata/whoop/normalized/latest.jsondata/speediance/normalized/history.jsondata/nutrition/latest.jsondata/eightsleep/normalized/latest.json
O gerador de relatórios nunca precisa saber como a autenticação de Garmin funciona ou como os cabeçalhos de Speediance mudaram nesta semana.
12. Estrutura de diretórios construível por agente
Aqui está uma estrutura que um agente pode criar antes que qualquer autenticação real de fornecedor 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/
A estrutura de arquivos faz parte da interface. Mantenha-a simples o suficiente para que um agente futuro consiga inspecionar o sistema, localizar cada conector, reexecutar uma única sincronização e comparar payloads brutos com saídas normalizadas.
13. Exemplo de padrão de construtor de relatório
Depois que cada conector grava JSON normalizado, o código real do relatório se torna simples.
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
html = f"""
<html>
<body>
<h1>Relatório Diário de Fitness</h1>
<ul>
<li>Recuperação: {summary['recovery']}</li>
<li>VFC: {summary['hrv']}</li>
<li>FCR: {summary['rhr']}</li>
<li>Passos: {summary['steps']}</li>
<li>Body Battery: {summary['body_battery']}</li>
<li>Volume de Musculação: {summary['lifting_volume']}</li>
<li>Calorias Consumidas: {summary['calories_in']}</li>
<li>Pontuação 8Sleep: {summary['sleep_score']}</li>
</ul>
</body>
</html>
"""
out = Path("reports/morning")
out.mkdir(parents=True, exist_ok=True)
(out / "latest.html").write_text(html)
É aqui que todo o design compensa: uma vez que a camada de sincronização está consistente, a camada de relatório fica entediante da melhor maneira possível.
14. Para que serve cada conector
Este é o modelo mental mais simples:
WHOOP
Usar para:
- recuperação
- VFC
- FCR
- desempenho do sono
- strain (carga de treino)
- enquadramento de prontidão
Garmin
Usar para:
- detalhes de corrida e cardio
- pace, potência, cadência
- zonas de FC
- efeito de treino
- histórico detalhado de atividades
Speediance
Usar para:
- histórico de treinos de força
- volume total
- detalhes dos exercícios
- execução planejada vs. real da sessão
- progressão por movimento caso você construa indexação por exercício
Aplicativo de nutrição
Usar para:
- ingestão calórica
- contexto de macros
- detecção de subalimentação
8Sleep
Usar para:
- detalhes do sono que chegam atrasados
- duração e pontuação do sono por cama
- verificações cruzadas de contexto do sono contra WHOOP e Garmin
OpenClaw então combina todos eles em uma única superfície de relatório e recomendação.
15. Entregáveis de conexão por sistema
Esta é a lista de verificação que o agente de implementação deve atender antes de finalizar a interface do relatório.
Pontos de conexão do Garmin
- Biblioteca:
garminconnectdecyberjunky/python-garminconnect - Autenticação: e-mail/senha do Garmin Connect com o tratamento de token/sessão da biblioteca
- Cadência de extração: sincronização diária pela manhã mais sincronização opcional pós-treino
- Extrações mínimas:
- estatísticas diárias para passos, frequência cardíaca em repouso, segundos de sono, body battery, calorias
- atividades por data para sessões de corrida/ciclismo/cardio
- detalhes da atividade quando disponíveis para zonas de FC, pace, cadência, potência, efeito de treino
- Saída normalizada:
data/garmin/summary/latest.json
Pontos de conexão WHOOP
- Documentação da API:
https://developer.whoop.com/api - Autenticação: token de acesso OAuth2 + fluxo de token de atualização
- URL base:
https://api.prod.whoop.com/developer/v2 - Grupos mínimos de endpoints:
/cyclepara contexto de strain/ciclo/recoverypara score de recuperação, HRV e FC em repouso/activity/sleeppara performance de sono e timing do sono/activity/workoutpara treinos e dados de strain WHOOP/user/profile/basice/user/measurement/bodypara contexto de perfil/corpo quando necessário
- Saída normalizada:
data/whoop/normalized/latest.json
Pontos de conexão Speediance
- Extração pública para este build:
https://github.com/clawdassistant85-netizen/speediance-smartgym-workout-manager - Referência upstream:
https://github.com/hbui3/UnofficialSpeedianceWorkoutManager - Autenticação: fluxo não oficial baseado em token/user-id exposto pela camada cliente do SmartGym
- Extrações mínimas:
- histórico de treinos
- detalhe de exercício/sessão
- metadados de treino/template personalizado se você quiser relatórios de planejado vs. real
- captura de resposta bruta de API/debug sem segredos
- Saídas normalizadas:
data/speediance/normalized/history.jsondata/speediance/normalized/by_exercise.json
Pontos de conexão do Cronometer
- Fonte pública: exports/integrations do
https://cronometer.com/ - Abordagem de implementação recomendada: exportação CSV ou drop de arquivo agendado, sem dependência de API em tempo de renderização
- Campos mínimos: data, calorias, proteína, carboidratos, gordura, fibra e quaisquer micronutrientes que você queira na análise de recuperação
- Saída normalizada:
data/nutrition/latest.json
Pontos de conexão 8Sleep
- Autenticação: fluxo de login/sessão apoiado por variáveis de ambiente, sem credenciais no código-fonte
- Cadência de extração: sincronização matinal mais suporte a rerun/refresh para hoje e ontem
- Extrações mínimas:
- score de sono
- timing do sono
- tempo dormindo e tempo na cama
- HRV e FC em repouso quando disponíveis
- temperatura e contexto de modo ausente quando disponíveis
- Saída normalizada:
data/eightsleep/normalized/latest.json
Ponto de conexão de geração de relatório
O construtor de relatórios deve ler apenas arquivos normalizados estáveis e snapshots de plano. Um formato prático é:
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
Essa é a superfície de conexão real. Tudo upstream pode quebrar e ser corrigido de forma independente.
16. As regras reais de implementação
Se um agente vai construir isso com sucesso, essas regras importam mais do que qualquer trecho de código individual:
Normalize cada fornecedor para o seu próprio schema
Nunca permita que um relatório dependa do formato de payload do fornecedor.Mantenha snapshots brutos
Quando uma sincronização quebra, payloads brutos salvam você.
Nunca renderize a partir de APIs ao vivo se o relatório for sensível ao tempo
Sincronize primeiro, renderize depois.
Trate integrações não oficiais como adaptadores descartáveis
Especialmente Speediance.Faça Garmin e WHOOP se complementarem, não competirem
WHOOP = prontidão. Garmin = detalhe de execução.Modele os dados de força tanto no nível de sessão quanto de exercício
Caso contrário, os relatórios de progressão permanecem superficiais.Conditione a orientação à prontidão de hoje, não à de ontem
A ausência de recuperação do mesmo dia deve rebaixar o sistema para relatórios apenas via web.Salve o plano antes de julgar o dia
Uma pontuação de aderência noturna só funciona se o plano da manhã ou pós-BJJ tiver sido armazenado como dado.Teste novos backends em modo shadow
O Open Wearables ou qualquer outra camada de abstração deve provar que consegue igualar os arquivos atuais de produção antes de se tornar a fonte da verdade.
Lista final de referências de implementação
Estas são as referências públicas que um agente de codificação de IA deve receber primeiro ao implementar este sistema:
- OpenClaw como a camada de orquestração
- Conector Garmin:
https://github.com/cyberjunky/python-garminconnect - Contexto histórico de autenticação do Garmin:
https://github.com/matin/garth(descontinuado; use como contexto, não como o centro de uma nova construção) - API oficial de desenvolvedor do WHOOP:
https://developer.whoop.com/api - Extração pública do Speediance para esta build:
https://github.com/clawdassistant85-netizen/speediance-smartgym-workout-manager - Referência original/fonte do Speediance:
https://github.com/hbui3/UnofficialSpeedianceWorkoutManager - Referência de gerador/modelo de relatório:
https://github.com/tobyglenn/scriptsJinja - Exportações de nutrição do Cronometer:
https://cronometer.com/ - Contrato do conector 8Sleep: sincronização respaldada por ambiente que grava em
data/eightsleep/normalized/latest.json
Se você está entregando este artigo para Claude Code, Codex, OpenClaw ou outro agente de implementação, a instrução correta é: construa os conectores primeiro, escreva os snapshots JSON normalizados em segundo lugar, imponha o gate de recuperação do mesmo dia em terceiro lugar e, por último, construa o renderizador de relatórios. Não comece projetando o relatório HTML final.