AI Guides

How to Build an AI Running Coach with Garmin

Mika Reyes
Mika Reyes

Co-founder at King’s Cross Labs · ex-LinkedIn PM & Forbes 30 Under 30

Heads up: This guide is a step more technical than most on this site. You will connect data sources (Strava, Oura, later Garmin), paste longer build prompts into an AI agent, and open a couple of files in your browser to check the result. You do not need to be an engineer. If connecting MCP tools is brand new, start with Health Coach and How to Setup Claude, then come back. If that sounds fine, keep going. The prompts do the heavy lifting; your job is to fill in the brackets and approve each step.

You do not need to fire a real running coach. But if you do not have the budget for one, you can build an AI running coach that connects to Strava, Garmin, and Oura and trains you for a marathon around your actual fitness, sleep, and life chaos. I built mine with Codex (any MCP-capable agent works), went from zero running to 24 miles a week and counting, and now every workout shows up on my Garmin with the exact pace and distance to hit.

Why this matters

This is the marathon-specific sequel to my Health Coach setup. That guide gets Strava, Oura, and recovery data into your AI. This one turns that data into a training system you can live inside: a Hansons calendar you can actually read, a weather panel so you know when to run, and a safe Garmin workflow that pushes today’s workout to your watch.

A human coach still wins for form, accountability, and cheering you on at mile 20. This is the best starting place when you are ambition-maxxing health without a five-figure coaching bill.

Key insight: The win is not “AI wrote a training plan.” It is that the plan lives next to your real runs, your recovery, and your watch, then rebuilds when life (or wildfire smoke) ruins a week.

What you need before you start

  • An AI agent that can use MCP tools (MCP = a plug-in style connection so the AI can talk to apps like Strava). I used Codex; Claude Desktop / Claude Code work too.
  • Strava and Oura already connected (Health Coach walks through that)
  • A Garmin Connect account if you want workouts on your watch (can wait until Part 3)
  • A race date and a training method (I used an 18-week Hansons beginner plan for an October marathon)

How this guide works: you build in three parts. After each part, you check the result before moving on. Every major part has a copy-paste prompt. Fill in the [brackets], paste it into your agent, and only say “yes, continue” when the check passes. If a prompt mentions a file type you do not recognize, you still do not need to edit it by hand. Ask the agent to open or explain it.

What does an AI running coach actually do?

Mine does five jobs most generic PDF plans skip:

  1. Builds the full calendar from your race date and method.
  2. Pulls real runs from Strava (and later Garmin) so it plans around your fitness, not a blank template.
  3. Checks Oura so easier days show up when sleep or cycle recovery say so.
  4. Rebuilds from today through race day when you miss days (history stays frozen).
  5. Pushes each day’s run to Garmin so the watch calls pace and distance while you run.

What are you actually building?

Ignore the scary filenames for a second. You are building five simple pieces that work together:

  1. The official schedule (a .json plan file) — what the computer treats as truth when talking to Garmin.
  2. The calendar page (an .html file) — what you look at in a browser, plus weather later.
  3. The translator — turns workout text into Garmin watch steps and a preview you read before anything goes live.
  4. The receipt book — remembers what was already sent to Garmin so you do not double-book.
  5. House rules for the agent — short notes so future chats follow the same safety habits.

Folder layout (what good looks like)

Ask your agent to create a small project folder with files like these. You do not need to hand-write them; the prompts below ask for them. Think of this as a packing list, not homework.

Use this generic layout (swap in your race year and a short race slug):

MARATHON_PLAN.md                               # what the workouts mean + pace rules
marathons/AGENTS.md                            # safety rules for this folder
skills/marathon-training/SKILL.md              # detailed repeatable workflow (path may vary by tool)
marathons/[year]/[race-slug].plan.json         # official schedule
marathons/[year]/[race-slug].html              # calendar page you open in a browser
marathons/[year]/[race-slug].garmin-sync.json  # Garmin receipts
scripts/garmin/compile-marathon-plan.ts        # translator / preview tool
marathons/[year]/generated/                    # preview files the translator writes

Examples of [race-slug]: nyc-marathon, chicago-2026, berlin, local-fall-marathon. Keep it short, lowercase, and hyphenated.

Example from my setup (Rockaway Beach marathon):

MARATHON_PLAN.md
marathons/AGENTS.md
skills/marathon-training/SKILL.md
marathons/2026/rockaway-beach.plan.json
marathons/2026/rockaway-beach.html
marathons/2026/rockaway-beach.garmin-sync.json
scripts/garmin/compile-marathon-plan.ts
marathons/2026/generated/

Your files will look the same, just with your year and race name instead of 2026/rockaway-beach.

Who is in charge of what

Memorize this once, in plain English:

  • The official schedule file decides what can go to Garmin.
  • The methodology note (MARATHON_PLAN.md) decides what workouts mean and which paces to use.
  • The calendar page is for you. Changing the schedule file does not auto-update the page unless you ask for that.
  • The receipt book only stores “we successfully put this on Garmin,” not “I finished the run.”
  • If two files disagree, the agent should show you the conflict, not silently pick a winner.

If the agent ever “remembers” an old Week 2 shortcut that does not match your schedule file, trust the schedule file.

Part 1: Build the training plan and calendar page

What you are making

A short “how we train” note, the official schedule file, and one calendar page you can open in Chrome or Safari. No website hosting required. Ask the agent where the .html file landed, then open it (double-click, or right-click → Open With → Browser).

On a big screen: race name, date, and short plan blurb on the left; full Monday–Sunday calendar on the right. Past days fade. Long workouts break into warmup / intervals / cooldown lines so quality days are easy to scan.

📸 Screenshot placeholder: Desktop calendar page with race intro on the left and the 18-week grid on the right. Alt: AI running coach HTML training calendar showing Rockaway Beach marathon weeks, daily mileage, and workout labels.

📸 Screenshot placeholder: One calendar day card next to the matching JSON day. Alt: Marathon plan JSON day record beside the HTML calendar card for the same date.

How to use the Part 1 prompt

  1. Open your agent in the project folder where you want these files.
  2. Confirm Strava and Oura MCP tools are connected (ask: “Can you see my recent Strava runs and Oura readiness?”).
  3. Copy the prompt below. Replace every [bracket].
  4. Paste it as one message. Do not also ask for weather or Garmin in the same turn.
  5. When it finishes, open the HTML file in your browser and skim week 1.
  6. Only move to Part 2 when week 1 looks realistic for your current fitness.
Build the plan layer of my marathon training workspace.

Context: Strava and Oura are already connected via MCP. Use them. Do not ask me to set those up again. Do not add a weather API or Garmin scheduling in this turn.

## Athlete + race inputs
- Race: [name], date: [YYYY-MM-DD], timezone: [e.g. America/New_York], distance: marathon
- Method: 18-week Hansons beginner (or [your method])
- Paces (edit to yours):
  - Goal marathon pace: [e.g. 10:13/mi]
  - Strength / MP-10s: [e.g. 10:03/mi]
  - 5K–10K intervals: [e.g. 8:52–9:13/mi]
  - Easy, long, warmup, cooldown, recovery: no forced pace target

## Deliverables
1. MARATHON_PLAN.md — Hansons principles used here, workout title grammar, pace policy, and the rule that missed runs are NOT automatically stacked onto later days
2. marathons/[year]/[race-slug].plan.json — canonical machine-readable schedule
3. marathons/[year]/[race-slug].html — standalone calendar page I can open in a browser
4. marathons/AGENTS.md — short safety stub (JSON governs Garmin; HTML is display copy; no stale week shortcuts)
5. A short assumptions note: what Strava/Oura told you about my fitness and how that shaped weeks 1–3

## JSON plan requirements
- Include: schema version, stable id, race block (name, ISO date, timezone, distance), units (miles in the plan; meters later for Garmin), Garmin defaults, pace labels, and weeks[]
- Each day needs: stable id (like rb26-w01-mon), ISO date, weekday, kind, title, distance, original distance text, and whether Garmin scheduling is enabled or skipped
- Seven ordered days every week; every calendar day filled (run or rest)
- Workout titles must use a grammar a compiler can parse, for example:
  - 1M Warm Up; 5 Mile Tempo @ Goal MP; 1M Cool Down
  - 1.5M Warm Up; 12 x 400m @ 5k-10k Pace w. 400m jog rest; 1.5M Cool Down
  - 1.5M Warm Up; 6 x Mile @ MP - 10s w. 400m jog rest; 1.5M Cool Down

## HTML page requirements
- One self-contained file: no React, no build tool, no database
- Desktop: two columns. Left = race name, date, short description, empty weather placeholder. Right = Mon–Sun calendar that can scroll
- Embed the plan in the page as week objects with day tuples: [isoDate, weekday, workoutTitle, milesText, kind]
- On load, render week rows and day cards. Turn semicolons in titles into line breaks. Color tags for workout / long run / rest / race
- Fade dates before today. On phones/tablets, allow horizontal scrolling. Add simple print styles
- Use normal semantic HTML (sections, articles, labels) so it stays readable

## How to use Strava + Oura while building
- Pull recent Strava volume, frequency, longest run, and typical easy pace
- Shape weeks 1–3 to my current fitness (do not jump to peak mileage if my volume is low)
- Use Oura readiness, sleep, and cycle signals to place quality days realistically
- Summarize those assumptions in the note so I can sanity-check them

## Hansons principles to encode
- Frequent running and cumulative fatigue
- Tuesday quality work (speed early, strength later in the plan)
- Thursday goal-marathon-pace work where the schedule calls for it
- Controlled Sunday long runs (generally peaking around 16 miles unless my longest recent run makes that unsafe)
- Rest / cross-train days called out explicitly

Part 1 check: open the calendar page. Does every week have seven days? Does week 1 look realistic for how much you run now? Then ask the agent: “Does the official schedule file match the calendar page for one sample week? Fix anything that does not.”

Part 2: Add the weather panel

What you are making

A small hourly forecast under the race intro on the same calendar page. Mine pulls free weather for Central Park, shows roughly 7am–9pm, fades hours that already passed, and highlights comfortable run windows (mild temps, no rain or storms). You do not need an API key or account. If weather fails, the calendar should still work.

📸 Screenshot placeholder: Weather panel with hourly rows and one highlighted “good running” hour. Alt: Open-Meteo hourly weather panel on AI running coach page highlighting comfortable run hours.

How to use the Part 2 prompt

  1. Stay in the same project folder with the HTML from Part 1 open in chat context (or point the agent at the file path).
  2. Paste the prompt below after filling in your coordinates and timezone.
  3. Refresh the HTML in your browser.
  4. Confirm hours appear, or that you see “Weather timeline unavailable” without a broken page.
Continue from the existing HTML calendar page. Do not rebuild the training plan or rewrite the JSON from scratch.

Add a live weather panel with these requirements:

- Place it under the race intro. Initial text: “Loading weather…”
- Fixed location coordinates: [lat, lon] (example Central Park: 40.7829, -73.9654). Do NOT use browser geolocation.
- Call the free Open-Meteo API for hourly temperature (°C), WMO weather code, and precipitation probability
- Compute the current date and hour in timezone [e.g. America/New_York] using Intl.DateTimeFormat formatToParts, even if I open the page from another timezone
- Keep only hours from 07:00 through 21:00 for that timezone’s current date
- Map weather codes to simple emoji groups (clear, cloud, fog, drizzle, rain, snow, thunderstorm)
- Round temperatures; show rain % only when above 0; use compact 12-hour time labels
- Dim past hours
- Highlight ideal future hours when temperature is 18–26°C and the weather code is not wet/stormy
- On any failure (network, empty data, parse error): show “Weather timeline unavailable.” The calendar must still work
- No API key, no server, no cache, no retry spam, no service worker

Out of scope this turn: Garmin compiler, sync file, and scheduling.

Part 2 check: refresh the page once. Do you see hourly weather, or a calm “Weather timeline unavailable” message? Either is fine. The calendar should still look correct.

Part 3: Translate workouts and send them to Garmin

This is the only part where the agent can change something outside your laptop. Go slow. Preview first. Small date ranges only (today, this week, or next week). Never dump all 18 weeks onto Garmin in one go.

What you are making

  1. A compiler script that reads the JSON plan and writes:
    • a human-readable preview (Markdown), and
    • a Garmin-ready schedule file (JSON)
  2. A sync receipt file that records successful sends
  3. A connected Garmin MCP so the agent can read activities and upload/schedule workouts. Use taxuspt/garmin_mcp (setup steps below).
  4. Stronger AGENTS.md / skill rules so future chats keep the same safety habits (same idea as building a custom skill or any other AI coach)

Plain-English version of the compiler

Your calendar might say:

1.5M Warm Up; 12 x 400m @ 5k-10k Pace w. 400m jog rest; 1.5M Cool Down

Garmin needs that broken into watch steps with distances and paces. The compiler:

  • converts miles to meters
  • turns easy/long runs into one distance step with no forced pace
  • turns structured titles into warmup → repeats or tempo → recovery → cooldown
  • applies your pace labels from MARATHON_PLAN.md
  • skips rest/race days when Garmin scheduling is disabled
  • fingerprints each workout so it can tell “never sent,” “already sent and unchanged,” or “changed since last send → stop and ask me”

Those four states matter:

Preview saysWhat it meansWhat you do
skipNot a Garmin dayNothing
would upload and scheduleNewReview, then approve
unchanged, already syncedSame as last timeLeave it
changed, requires reviewLocal plan changed after an earlier syncPause. Choose leave Garmin alone, add a new version, or fix by hand

📸 Screenshot placeholder: Dry-run preview listing actions for each date. Alt: Garmin marathon plan compiler dry-run showing upload, skip, and review states.

How to connect Garmin MCP

Use the open-source Garmin MCP Server. Full docs live in that repo; here is the non-technical path that works for Codex, Claude Desktop, and other MCP clients.

What you need first

  • A Garmin Connect account
  • uv installed (gives you the uvx command). If you are not sure, ask your agent: “Help me install uv on my Mac.”
  • Python 3.12+ (uv can pull this for you when you run the auth command)

Step 1: Log into Garmin once in your terminal (do this before adding MCP config)

Open Terminal and run:

uvx --python 3.12 --from git+https://github.com/taxuspt/garmin_mcp garmin-mcp-auth

It will ask for your Garmin email, password, and MFA code if you use one. Tokens save to ~/.garminconnect (usually good for about six months). Prefer this over putting your password in any config file.

Never paste your Garmin password into the AI chat. Tell the agent never to print secrets.

Step 2: Add the server to your AI client (no password in the config)

Codex (I used this): add to ~/.codex/config.toml, then restart Codex:

[mcp_servers.garmin]
command = "uvx"
args = [
  "--python",
  "3.12",
  "--from",
  "git+https://github.com/taxuspt/garmin_mcp",
  "garmin-mcp"
]

Claude Desktop: edit ~/Library/Application Support/Claude/claude_desktop_config.json on Mac (or %APPDATA%\Claude\claude_desktop_config.json on Windows), merge this into your existing mcpServers block, then fully quit and reopen Claude:

{
  "mcpServers": {
    "garmin": {
      "command": "uvx",
      "args": [
        "--python",
        "3.12",
        "--from",
        "git+https://github.com/Taxuspt/garmin_mcp",
        "garmin-mcp"
      ]
    }
  }
}

If Claude cannot find uvx, run which uvx in Terminal and put that full path in "command" instead of "uvx".

Easier Claude Desktop option: download garmin-mcp.dxt from the Garmin MCP Releases page, then drag it into Claude or install via Settings → Extensions. You still need Step 1 (garmin-mcp-auth) once so data can load.

Or let the agent do the wiring: paste this after you finish Step 1:

Install the Garmin MCP server from https://github.com/taxuspt/garmin_mcp, confirm garmin-mcp-auth already saved tokens to ~/.garminconnect, and add it to my MCP configuration without storing my Garmin email or password.

Step 3: Confirm it works

Ask: “List my Garmin MCP tools, then show my most recent running activities.” You want activity lookup plus workout upload/schedule tools (this server also has high-level helpers like upload_workout, schedule_workout, and schedule_week).

Garmin does not publish a perfect public API for all of this. Community tools can break after Garmin changes things. If MCP is down, stop at local previews. Do not force a live write. When tokens expire, re-run the garmin-mcp-auth command from Step 1.

How to use Part 3a (preview only)

  1. Pick a tiny range, like this Monday through Sunday.
  2. Paste the prompt. Replace dates and paths.
  3. Read the Markdown dry-run. Confirm rest days are skipped and every run you expect is present.
  4. If anything says “changed, requires review,” stop and decide before Part 3b.
Garmin MCP may be connected, but do NOT schedule anything yet.

Build or use a compiler (TypeScript is fine) at scripts/garmin/compile-marathon-plan.ts that:

- Reads the canonical JSON plan as source of truth
- Optionally reads the existing garmin-sync receipt file
- Requires a --from and --to date range
- Translates workout titles using MARATHON_PLAN.md pace policy and the title grammar
- Converts miles to meters with 1609.344
- Easy/long runs → one distance step with no.target
- Structured titles → warmup, tempo or repeat group, recovery, cooldown
- Hashes each {date, workout} so we can compare against sync receipts
- Classifies each day as: skip | would_upload_and_schedule | unchanged_already_synced | changed_requires_review
- Writes:
  1) a human Markdown dry-run under marathons/[year]/generated/
  2) a schedule JSON with calendar_date + inline workout_data for MCP

Run a dry-run for --from [YYYY-MM-DD] --to [YYYY-MM-DD].

Then stop and summarize for me:
- date range
- how many runnable days
- how many skipped
- counts for each action type
- any changed_requires_review rows
- proof that every included date is inside the requested range

Wait for my approval before calling upload_workout, schedule_workout, or schedule_week.

If you are comfortable running a command yourself, the shape looks like this (your agent can run it for you):

node scripts/garmin/compile-marathon-plan.ts \
  --from YYYY-MM-DD --to YYYY-MM-DD \
  --out marathons/2026/generated/plan-FROM_TO.garmin-schedule.json \
  --dry-run-out marathons/2026/generated/plan-FROM_TO.garmin-dry-run.md

Useful before any live write: ask the agent, “Double-check the preview only covers my chosen dates, and that rest days are skipped.” You should be able to read the answer in plain English.

How to use Part 3b (schedule after you approve)

Only run this after you have read the dry-run and are happy with it. With garmin_mcp, the live write usually means upload_workout (or a builder) then schedule_workout / schedule_week.

I approved this dry-run: [path to the Markdown or JSON preview].
Date range: [YYYY-MM-DD] → [YYYY-MM-DD].
Garmin MCP: https://github.com/taxuspt/garmin_mcp

Follow this exact sequence:
1. Inspect what is already on Garmin for that date range (workouts / calendar tools available on the MCP)
2. Compare Garmin vs the dry-run vs the sync receipt file. Surface duplicates or conflicts. Do not silently overwrite.
3. Upload and schedule only the approved days using upload_workout + schedule_workout (or schedule_week for a small batch). Prefer the generated workout payloads from the dry-run, not random old library IDs, unless the dry-run explicitly reused an ID.
4. Check each item’s result. Batches can partly fail.
5. For successes, append receipts keyed by plan-day id with: date, workout hash, workout_id, scheduled_workout_id when available, sync_mode, and an ISO timestamp
6. Re-check Garmin for that date range to verify
7. Report results as: scheduled / skipped / already present / changed-blocked / failed

Hard rules:
- No password printing
- No full-plan dump beyond this approved range
- No unschedule or delete calls in this turn
- Anything marked changed_requires_review stays blocked until I choose: leave Garmin unchanged, add a new version, or reconcile manually

📸 Screenshot placeholder: Garmin calendar or MCP list after a small approved sync. Alt: Garmin scheduled workouts confirming AI running coach sync for selected dates.

Two IDs to keep straight: a workout_id is the reusable workout template. A scheduled_workout_id is that workout sitting on a specific calendar date. When you delete, you almost always mean the scheduled calendar entry, not your whole workout library.

How to use Part 3c (after you finish a run)

“Sync today’s run” means reconcile a completed activity. It does not mean schedule a new workout.

Interpret this as activity reconciliation, not scheduling.
Garmin MCP: https://github.com/taxuspt/garmin_mcp

I finished my run on [YYYY-MM-DD].

1. Find running activities on Garmin for that date (e.g. get_activities / activity tools)
2. Match on date + the expected plan label (for example RB26 W##). If multiple activities could match, list them and ask me which one
3. If a matching completed activity exists and a pending scheduled workout is still on the calendar, show me the exact scheduled workout ID and ask before removing it
4. Never delete the completed activity
5. Do not write completed-activity fields into the scheduling receipt file

Lock the habits so future chats stay safe

Ask your agent to save short house rules for this project (a skill or AGENTS.md is fine) that always:

  • start from the marathon workflow notes
  • only touch a small date range (today / this week / next week)
  • show you a preview before any Garmin write
  • check Garmin before and after scheduling
  • never print passwords
  • only log successful sends in the receipt book
  • summarize results in plain categories (scheduled, skipped, already there, needs review, failed)
  • trust the official schedule file over any remembered week shortcut

When the plan changes: update the methodology note if needed → update the official schedule → update the calendar page when you care that they match → run a new preview → sync Garmin only after you approve. Old receipts stay put until a new approved sync succeeds.

What happens when life ruins the plan?

A couple weeks ago NYC was too smoggy from wildfire smoke to run outside, so we missed days. I told the coach what happened. It rebuilt from today through race day and left every past week alone, so I did not lose the record of what I had already done.

Hard rule for both options below: only rewrite today → race day. Past weeks on the calendar stay as history. Missed runs are not revenge-stacked onto tomorrow.

Option A: Let Strava show what really happened

Use this when your completed (or skipped) runs are already in Strava.

How to use it: paste the prompt, fill the date window, read the future-only changes, approve the schedule + calendar update, then run a fresh Part 3a preview before any Garmin sync.

We got off plan. Rebuild using real Strava data.

## Scope (non-negotiable)
- ONLY change the plan from today’s date through race day
- Do NOT edit, delete, or rewrite any historical days before today
- Keep past HTML day cards and past JSON entries as-is so progress is preserved
- After the rebuild, HTML and JSON must still match for the future portion
- Do not auto-stack missed mileage onto the next day
- Leave garmin-sync receipts untouched until I approve a new Part 3a → 3b

## Steps
1. Pull Strava activities from [start of recent window] through today
2. Compare completed runs vs what the plan prescribed; summarize missed days, partial days, extra volume, longest recent run, and current weekly mileage
3. Optionally factor Oura (sleep / readiness / cycle) if recovery should force easier near-term days
4. Propose a revised schedule from TODAY to race day that closes the gap without reckless mileage spikes and still follows Hansons principles
5. Show a clear diff of future dates only
6. Update JSON + HTML for future dates only (update MARATHON_PLAN.md only if pace or policy changed)
7. Stop before Garmin. I will run a new compiler dry-run next

Option B: You list the misses yourself

Use this when Strava does not tell the whole story (treadmill not synced, travel, smoke day, sick day) or you want to dictate the constraint.

How to use it: list the dates and reasons, paste the prompt, approve the future-only changes, then Part 3a before Garmin.

We got off plan. My miss list is the source of truth for what did not happen.

## Misses
- Dates missed or changed: [list dates + what happened]
- Anything I still completed those weeks: [optional]
- Constraint: [e.g. no outdoor runs until air quality clears / travel until DATE]

## Scope (non-negotiable)
- ONLY change the plan from today’s date through race day
- Do NOT edit, delete, or rewrite any historical days before today
- Keep past HTML day cards and past JSON entries as-is
- After the rebuild, HTML and JSON must still match for the future portion
- No revenge mileage and no auto-stack onto the next day
- No Garmin push until I approve a new Part 3a dry-run

## Steps
1. Accept my miss list (you may peek at Strava for volume sanity-check if useful)
2. Propose a revised schedule from TODAY to race day that catches me up safely under Hansons principles
3. Show a clear diff of future dates only
4. Update JSON + HTML for future dates only

Weekly loop

  1. Check today’s weather panel and Oura / recovery signal.
  2. Do the run (or honestly log why you did not).
  3. When you are off plan, run Option A or Option B.
  4. Approve any reschedule, then Part 3a → Part 3b before Garmin changes.

Key insight: Missed days are not a failure mode. They are the reason to connect real data. A static PDF cannot renegotiate the remaining weeks after smoke week. Your AI coach can, as long as it rewrites the future only and leaves your history alone.

AI coach vs human coach

Use AI for calendar building, data-aware adjustments, weather-aware planning, previews, and watch delivery. Keep a human (or a trusted running friend) for form checks, race-day nerves, and the mile-20 pep talk. If you can afford both, great. If you cannot, this system is a strong place to start while you build the habit.

I still cannot believe we are in an era where non-techies can build a custom tool for ambition-maxxing something as personal as marathon training. Start with Part 1 today. Your future race-day self will thank you.

How do you know it’s working?

You do not need to run developer commands. Trust what you can see:

  1. The calendar looks right. Open the page in your browser. Race date, weekly mileage, and today’s workout should make sense for a human athlete, not a random template.
  2. Weather is helpful or quietly absent. Hours show up, or you get a simple unavailable message. The page should not break.
  3. Previews are readable. Before anything hits Garmin, you get a plain summary of which days will upload, which will skip, and which need your decision.
  4. Garmin matches what you approved. After a small sync, open Garmin Connect (or ask the agent to list that week). The workouts on the calendar should match the preview you said yes to. Nothing extra. Nothing missing.
  5. History stays put after a rebuild. If you miss days and rebuild, past weeks still look like what you already did. Only today → race day should change.
  6. You always stay on the approve button. If the agent cannot reach Garmin, stopping with a good calendar + preview is still a win. Do not force a live write.

If any of those fail, paste the symptom back to the agent (“Week 3 Tuesday on the page does not match the schedule file”) and fix that before you move on.

Here are some related guides to check out:

  1. Health Coach
  2. How to Create an AI Coach
  3. How to Create Your Own Custom Skill
  4. How to Setup Claude
  5. What Is a Skill?

Frequently asked questions

Can I build an AI running coach if I am not technical?
Yes, with a little patience. This guide is a step more technical than most on the site, but you mostly paste prompts, fill in brackets, and review results in a browser. The careful part is Garmin sync: always read a preview and approve a small date range before anything hits your watch. If connecting Strava and Oura is new, do the Health Coach guide first, then come back.
Do I need Strava, Garmin, and Oura all at once?
You need Strava and Oura connected to build the training calendar the way this guide describes, because the plan should start from your real fitness and recovery. Garmin can wait until the calendar and weather page feel right. Add watch sync when you want each workout delivered to your wrist.
Is it safe to let AI schedule workouts on my Garmin?
It is safe if you use a narrow date range, read a compiler dry-run first, check what is already on Garmin, keep a sync receipt file, and pause when a workout changed after an earlier sync. Never give the agent automatic permission to delete or unschedule workouts without naming the exact IDs and getting your confirmation.
What is the difference between this and the Health Coach guide?
Health Coach connects Strava and Oura into a recovery dashboard that recommends how hard to train today. This guide is the marathon workspace: a Hansons calendar, a weather panel, a compiler that turns plan text into Garmin steps, and rules that rebuild only from today to race day when life happens so you do not lose historical progress.