{"slug": "my-ai-running-coach-didn-t-need-a-better-prompt-it-needed-my-training-history", "title": "My AI Running Coach Didn't Need a Better Prompt. It Needed My Training History.", "summary": "A developer built running-portal, an open-source tool that syncs workout data from the Mi Fitness app into a persistent training history and feeds structured context—current run metrics, recent runs, and recovery state—into an LLM to generate coaching assessments. The project, built with a coding agent and based on the MIT-licensed Mi-Fitness-Sync library, replaces the previous workflow of uploading screenshots to ChatGPT, which the developer found failed because a single workout lacks the trend data needed for useful advice.", "body_md": "After every run I used to open the Mi Fitness app, take a few screenshots, and upload them to ChatGPT for analysis. On paper, that was a personal coach: the watch collects the data, I show it to AI, AI tells me what to do next.\n\nIn practice it fell apart quickly, and not because of the prompt.\n\nA single workout doesn't fit on one screenshot: summary, charts, heart rate zones and other metrics all live on separate screens. Charts were the worst: a human can stitch several screens into one picture, but for the chat I was rebuilding the context from fragments every time.\n\nThe bigger problem: **one workout means almost nothing without the previous ones.** A heart rate of 168 is just a number. It is a different story if at roughly the same distance it was 158, then 164, 167, 168, 170 and 172. Useful advice needs a trend, and through screenshots I was bringing AI a small fragment of what the watch app already knew.\n\nSo the problem wasn't finding a better prompt. I needed a real channel between the watch data and the model.\n\nThis is a shortened fragment of a real coach prompt that the portal assembles after a run:\n\n```\n=== RUN ===\nDistance: 3.216 km\nHeart rate: 168 bpm\nPace: 6:04/km\nCadence: 162 spm\nLoad: 127\nRecovery: 57 h\nHeart rate zones: ... extreme 96%\n\n=== RECENT RUNS ===\n09/14: 3.271 km, HR 172, load 142\n09/12: 3.307 km, HR 170, load 139\n09/10: 3.216 km, HR 168, load 127\n...\n\n=== RESPONSE ===\n1. Assessment of the run.\n2. Risks given the current state.\n3. One specific recommendation for the next workout.\n```\n\nThe real request contains more: the current run, the history of recent workouts, and stored context about my state. I can edit the template itself from the portal's UI.\n\nThat is the whole difference from screenshots. Before, I showed AI a *picture* of the data. Now the code gathers the facts and builds the context, I set the rules and the response format, and the model interprets the context.\n\n[`running-portal`](https://github.com/hram/running-portal) syncs my running workouts from Mi Fitness, stores the history, and loads detailed data for a specific run. For me it is an ordinary training log. For the model it is a persistent source of context.\n\n```\nMi Fitness\n    ↓\nsync\n    ↓\nrunning-portal\n    ├── run history\n    ├── detailed metrics\n    ├── charts\n    ├── state / how I feel\n    └── monthly goal\n            ↓\n        AI coach\n```\n\nI did not reverse-engineer the private Mi Fitness API. The sync module is based on [Mi-Fitness-Sync by kevinkwee](https://github.com/kevinkwee/Mi-Fitness-Sync) (MIT License), which already implemented Xiaomi authorization, fetching workouts, and parsing detailed Mi Fitness data. A coding agent wrote `running-portal` and integrated that code; credit for the protocol work goes to the author of Mi-Fitness-Sync.\n\nThe integration is not pleasant: a private API and internal data formats, including separate files with detailed value series. That is one reason I treat the portal as a personal tool, not the basis for a public service.\n\nThe workout card shows me the same things that go to the model in structured form: heart rate, pace, cadence, stride length, load, recovery, heart rate zone distribution, and detailed time series.\n\n*To me, charts. To the model, raw numbers.*\n\nThe analysis shows up on the same workout card.\n\n*Assessment → risks → one specific next session.*\n\nIn this example the coach looks beyond average heart rate: most of the run happened in a high heart rate zone, it compares that with previous runs, and it suggests not increasing the load. I set a rigid response structure on purpose. I don't need sports motivation; I need an assessment, the risks, and the next workout.\n\nThis is where I stopped thinking of the prompt as magic text. The usefulness came from the context.\n\nThe portal also answers a shorter daily question: run today, run easy, or rest?\n\n*At the time of this screenshot, less than the estimated recovery time had passed since the last run.*\n\nHere I don't hand the decision fully to the model. The prompt has explicit rules: for example, if the estimated recovery time after the previous workout hasn't passed yet, that is a signal in favor of rest. High heart rate, load, and saved notes about my state are factored in separately. The portal fills in the facts automatically:\n\n```\nlast run\n+ how much time has passed\n+ last 7 runs\n+ load\n+ recovery\n+ saved context\n```\n\nThen the model writes a short explanation. Part of the guardrails is explicit, and the LLM is used where several factors need to be connected and explained in plain language.\n\nWhile getting back into regular running, I had problems with my feet, and later my knee bothered me for a long time. This is not a medical success story: AI didn't cure anything and didn't replace a doctor.\n\nIt was useful as a check on my own tendency to increase load too fast. When pain showed up in the context, the coach lowered the recommended load, suggested a pause, and advised seeing a doctor. After I bought new 361 KAIROS 2 shoes, the shoe change went into the context too, as one more factor against sharply increasing volume. With the knee, the portal kept the note in context and the model kept factoring it into later recommendations.\n\nA one-off chat easily forgets what happened two weeks ago. The portal doesn't.\n\nLater the task changed from \"don't force it\" to \"what volume should I aim for next month?\". At the start of the month, AI analyzes previous runs and proposes three goal options: conservative, recommended, and ambitious. I choose.\n\n*The model proposes scenarios and explains the recommended one; the final decision is mine.*\n\nOnce a goal is accepted, AI is barely needed. Plain portal code counts kilometers run, number of workouts, remaining distance, and whether the month is on track. Where arithmetic is enough, there should be arithmetic; the LLM shows up where history needs to be interpreted.\n\n`running-portal` is 100% implemented by coding agents from my specs, except for the Mi Fitness integration foundation mentioned above. It wasn't generated once from one big prompt. The loop was:\n\n```\nuse the portal\n      ↓\nsee what's missing\n      ↓\nformulate the task for the coding agent\n      ↓\nget the change\n      ↓\nuse the portal again\n```\n\nThe repository keeps 11 prompt artifacts from different stages: sync, frontend, the AI coach, charts, analytics, monthly goals and other improvements. I can't reconstruct every agent session behind them anymore, so I don't treat the number of files as a precise development log.\n\nWhen I started sending screenshots to ChatGPT, I thought the task was learning to ask the right way. A good question turned out to be the smallest part of the system.\n\nThe watch already collected the data, and the LLM could already reason about it. What was missing was a layer that stores the training history, surfaces the right details, adds up-to-date context, and hands it to the model in a predictable form. Close to a year after getting back into running, every workout lands in the portal, and AI works with my running history instead of a few pictures I show it after each run.\n\nThe source is on GitHub: [hram/running-portal](https://github.com/hram/running-portal). Suggestions and bug reports are welcome. The full case study, with more screenshots, is on my site: [https://hram.github.io/en/articles/running-portal/](https://hram.github.io/en/articles/running-portal/)", "url": "https://wpnews.pro/news/my-ai-running-coach-didn-t-need-a-better-prompt-it-needed-my-training-history", "canonical_source": "https://dev.to/hram/my-ai-running-coach-didnt-need-a-better-prompt-it-needed-my-training-history-22f8", "published_at": "2026-09-29 04:42:00+00:00", "updated_at": "2026-09-29 04:46:40.116357+00:00", "lang": "en", "topics": ["ai-tools", "large-language-models", "ai-products"], "entities": ["Mi Fitness", "ChatGPT", "running-portal", "Mi-Fitness-Sync", "kevinkwee", "Xiaomi"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/my-ai-running-coach-didn-t-need-a-better-prompt-it-needed-my-training-history", "markdown": "https://wpnews.pro/news/my-ai-running-coach-didn-t-need-a-better-prompt-it-needed-my-training-history.md", "text": "https://wpnews.pro/news/my-ai-running-coach-didn-t-need-a-better-prompt-it-needed-my-training-history.txt", "jsonld": "https://wpnews.pro/news/my-ai-running-coach-didn-t-need-a-better-prompt-it-needed-my-training-history.jsonld"}}