Using IA/ChatGPT to write intervals.icu workouts

Give it the prompt, then paste a workout in any format that is understandable. For instance this is an image captured from whatsonzwift site.

And the output in this case for me (I also gave it an FTP value) was:

Warmup

  • 10m ramp 75-187W

Main Set

  • 30s 250W 95rpm
  • 30s 125W 85rpm
  • 30s 275W 100rpm
  • 30s 125W 85rpm
  • 30s 300W 105rpm
  • 30s 125W 85rpm
  • 3m 125W 85rpm
  • 10m 250W 90rpm
  • 4m 138W 85rpm

3x

  • 3m ramp 228-243W 85rpm

  • 3m ramp 243-258W 80rpm

  • 3m ramp 258-273W 75rpm

  • 4m 138W 85rpm

  • 2m 250W 90rpm

  • 1m 250W 70rpm

  • 2m 250W 90rpm

  • 1m 250W 70rpm

  • 4m 250W 100rpm

Cooldown

  • 7m ramp 163-113W

which has a mistake, the 3x, but other thant that looks good.

I used Ariel’s prompt as inspiration to create my own GPT: Coach GPT for Intervals.icu.
The idea is to use this GPT to generate training plans that you can upload directly to Intervals.icu via the API. I’ve built it using Ariel’s text as a base, combined with my ATP and 4DP profile.

I’d love for someone to give it a try and share feedback with me. Let me know how it works for your training schedules and if there’s anything I can improve! You can use the prompt to create plans and integrate them via the API. Thanks in advance! :blush:

7 Likes

Thanks for creating this! I’ve given it about 6 different attempts and everything looks great until it goes to create the JSON for Intervals.icu.

I can only get about a week of workouts planned, and then it lists the races I told it about. I’ve even tried not prompting it with my races, solely just my goals, and it only gives me about 5 workouts for the next week’ish.

Whatever I do, I can’t get a year worth of workouts planned around my races. But like I’d said, before we get to that point everything looks great in the propts and what it says it is going to do.

Let me know if I can replicate this for you and share a chat from ChatGPT.

1 Like

“Why won’t ChatGPT give me a full year’s workout plan in JSON?”
Well, let’s ask ChatGPT!

ChatGPT:

“I’ve got the memory of a goldfish once I hit my token limit. One minute, I’m heroically mapping out your entire year of workouts, and the next minute, I’m only describing your first week. It’s not that I don’t want to keep going—it’s just that my ‘brain’ gets ‘full’ and can’t store (or spit out) the extra details!”

Why does this happen?

  • When generating detailed JSON, each field (date, activity, duration, intensity, etc.) soaks up a lot of tokens. Before you know it, you’ve hit the model’s text limit, and the rest of your workouts never see the light of day.
  • Think of it like trying to write a whole novel in a single tweet—you’re bound to run out of space.

What’s the workaround?

  • Break it down: Plan your training for the whole year, but only ask ChatGPT to generate JSON in smaller pieces—like every 3 weeks.
  • Adapt to real life: You can then add any last-minute changes (family weekends, city trips, holidays, business trips, etc.) into your next 3-week plan. That way, if you end up in a hotel with only a treadmill, ChatGPT can suggest workouts that don’t require a bike.

So, even though it’s annoying not to get a full year’s worth of JSON right away, there’s a silver lining: you’ll have more accurate, up-to-date training schedules every time you check in.

1 Like

Thanks so you mean GPT will remember your whole year plan that you’ve asked him to create and then any day any time you can ask changes for let’s say next week or the current day and he will adapt? Like you would chat with a real coach then? :wink: On my side I still like to have visibility on the next months and if possible whole year because I’m planning holidays, A/B/C races, etc.

Yes, GPT can remember your whole year plan! I told it about my A/B/C races, planned holidays, no weekend training (3 little kids!), and my weaknesses that need extra focus. It then created a full annual plan with base, build, taper phases, and so on.

I can ask for an overview at any time, and it delivers instantly. Every three weeks, I request a new plan, share updates (e.g., “Thursday evening is solo with the kids, so indoor bike instead of running”), and it adjusts accordingly. I even request the plan in JSON format to upload directly to Intervals.icu.

It feels a lot like chatting with a real coach, except that a real coach could plan further ahead directly in Intervals.icu! That said, you can still generate and upload plans month by month or week by week to maintain visibility over your whole year.

The only limitation is the token limit of ChatGPT, but that’s manageable if you break the planning into smaller chunks. :blush:

1 Like

This looks awesome - Ive just used the prompt to build an 8 week ftp plan - I wonder what feedback this gpt gives me for each work out

I tried using ChatGPT (and 2 others) to suggest what days I should do weights if I was running on specific days. All 3 gave the same answer, with good reasoning.

So far so good, so I asked ChatGPT to plan the weights workouts within some specific parameters. This looked really good and organised, aligning with a lot of what I know already. That is until I sat down and looked in detail at the exercises and found it had suggested a Plank with Band Pull Apart that I’ve never heard of.

So I asked for more details

That had me scratching my head, because it didn’t seem physically possible. You’d end up balancing all your weight on your legs only while in a plank position? I queried this, and it was rather defensive and took several goes before it sort of admitted it was wrong. Maybe it’s learning from the non-apology culture out there:

It also made some a basic mistake on another exercise. Given that it’s just trying to predict what character to write next you can see how it gets it wrong, writing inside rather than outside on an exercise, because the previous word is often followed by either of them.

So my learning is it can have some interesting ideas, but you’ve got to be careful about blindly following it’s advice. Its worth having a bit of an understanding in the first place

1 Like

I’m creating my new ATP with AI for next outdoor season and I had something similar (I don’t remember with which LLM) happened to me. AI suggested me a “dead bug” exercise that I’ve never hear so I asked more informations and the response was not the real exercise I found on youtube.

What I really like about new version of AI (DeepSeek and the “think before” of ChatGPT) are the “reasoning” models. it’s interesting to read and see how it “think” before the reply and help to spot something strange.

this should be printed in big font in all AI homepages…

Except ChatGPT, has anyone tried other AI models for running training plans? Just wondering if ChatGPT is the “best one” :wink:

This is a great tool - thanks! I’ve created a training plan and saved it as a JSON format but I’m struggling to find how to import the training plan into my Intervals.icu library. Could you possibly help instruct me how?

1 Like

Interested about the same. I’d like to use GPT to create a macro cycle of running workouts for example a block of 3 weeks and then import it into Intervals. If someone could make a short video to go through the steps this would be helpful.

to send the “AI plan” to your calendar:

  1. make sure the json is correct, I had to ask AI to fix it a couple of times.
    sould be an array similar to this:
[
       {
           "start_date_local": "2025-03-04T09:00:00",
           "category": "WORKOUT",
           "type": "Ride",
           "name": "Sweet Spot Intervals",
           "description": "Warmup\n- 10m 50%-65% 90rpm\n\nMain Set\n- 3x 12m 88%-92% 85rpm\n- 5m Z2 85rpm\n\nCooldown\n- 10m 50%-40% 80rpm"
       },
               {
           "start_date_local": "2025-03-07T09:00:00",
           "category": "WORKOUT",
           "type": "Ride",
           "name": "Recovery Spin",
           "description": "Warmup\n- 10m ramp 50%-65% 85rpm\n\nMain Set\n- 45m Z1-Z2 90rpm\n\nCooldown\n- 10m 50%-40% 80rpm"
       },
       {
           "start_date_local": "2025-03-09T09:00:00",
           "category": "WORKOUT",
           "type": "Ride",
           "name": "Endurance Ride",
           "description": "Warmup\n- 10m ramp 50%-70% 85rpm\n\nMain Set\n- 1.5h Z2 90rpm\n\nCooldown\n- 10m 50%-40% 80rpm"
       }
   ]
  1. download and install Postman
  2. left panel, “My Workspace”, create a new Collection (+ button)
  3. select your new collection and in the authorization tab select “Basic auth”, then insert “API_KEY” as username and your api key (found in your intervals.icu setting page)
  4. in this newly create collection add a new Request
    URL: https://intervals.icu/api/v1/athlete/0/events/bulk
    change type (left to URL) to POST
    in the “Body” section select Raw and paste your json
  5. Click “Send”

do a test with couple of workouts otherwise if something is wrong manually delete all the calendar entries could take some times

If you want to do more things or need more explanations with API and to check for JSON format:

1 Like

I just tried it and it works fine, thank you very much.

Wouldn’t it be possible to do some type of import directly in JSON to the library and not to the calendar?

you should be able with one of these endpoints

same procedure as before, slightly different JSON, see documentation

for example

 {
    "day": 5,
    "folder_id": "xxxxx",
    "category": "WORKOUT",
    "type": "Ride",
    "name": "VO2 Max",
    "description": "Warmup\n- 15m 55-75% 90-100rpm\n\nMain Set\n6x\n- 3m 126% (340W) 95-105rpm\n- 3m <55% 80-90rpm\n\n- 24m 55-75% 85-95rpm\n\nCooldown\n- 15m <55% 80-90rpm"
  },

folder_id is folder/plan ID.
day is the day of the plan (starting from 0), you can also use the actual date instead of “day” like in the example above

You can see folder/plan ID in the upper right corner of the edit folder/plan modal window

1 Like

Been using this for a couple of weeks.

Having continuous issues when importing - the workouts continue to import as “swim” instead of ride even with the type set as “Ride”. The zones also import as HR instead of power, but I think this relates to the swim type more so than anything else.

Importing through Powershell (per Github) which works, but I don’t know if this is what is actually causing the issue.

Any recommendations to fix this? I have tried with AI to get it right, but still not working.

An example of my json file:

"date": "2025-03-11",
  "category": "workout",
  "type": "ride",
  "name": "Sweet Spot Intervals",
  "steps": [
    {"duration": "10m", "zone": "Z2", "description": "Warm-up"},
    {"duration": "12m", "zone": "Z3-Z4", "description": "Sweet Spot Interval 1"},
    {"duration": "4m", "zone": "Z1", "description": "Recovery"},
    {"duration": "12m", "zone": "Z3-Z4", "description": "Sweet Spot Interval 2"},
    {"duration": "4m", "zone": "Z1", "description": "Recovery"},
    {"duration": "12m", "zone": "Z3-Z4", "description": "Sweet Spot Interval 3"},
    {"duration": "5m", "zone": "Z1", "description": "Cool-down"}

Hello, I am the same as you, I find it very interesting but the tool is not correct enough for my use, since like you, I also train for power, it would be interesting if I could do it by power zones or better yet, for a % of the FTP value.

Regarding this type of issue, I have already made a request to the creator through Github. Here my petition: Support workouts based on % FTP · Issue #5 · h3xh0und/intervals.icu-api · GitHub

Regarding the second section you mention, swimming, the problem is not the generation of your code but the code of the import tool, I was fighting and I found the reason, let me show you:

        formatted_data.append({
            "start_date_local": training["date"] + "T00:00:00",
            "category": "WORKOUT",
            "name": training["name"],
            "description": "\n".join(description_lines).strip(),
            "type": "Ride" if "Bike" in training["name"] else "Run" if "Run" in training["name"] else "Swim",
            "moving_time": sum(
                convert_duration(step["duration"]) for step in expanded_steps
            ),
            "steps": expanded_steps

“type”: “Ride” if “Bike” in training[“name”] else “Run” if “Run” in training[“name”] else “Swim

What this code does is that when you run the script, if the activity has the word ‘Bike’ as part of the training then it will be training of type ‘Bike’; if you have the word ‘Run’ as part of the training then it will be ‘Run’ type training; If it does not meet any of the other conditions then it will always be of type ‘swimming’.

This is how it is implemented in the code, so regardless of the format and type of your JSON, when you run that script and upload it to your Intervals.icu it will change it.

For the latter, regarding the type of training there is no major problem than editing the code, even if you are not familiar with the code (I am not) it is as simple as changing that part and making it always ‘Bike’.

For the power part, I have not been able to modify the code, I have been testing but without success… let’s see if the creator of the project or someone with knowledge can help us.

1 Like

I temporarily fixed this based on the code by simply include ‘bike’ in the title of the workouts - told GPT to do this and it imported correctly.

However I had the same issue with Zones (HR instead of Power) as what you did. Will see if I can find a fix for that by changing the fields in the JSON.

Will revert back if I do.

1 Like

I found the ‘issue’. :slight_smile: In the config section of the script the ‘$zoneType’ field forces all to go to HR based workouts. I have no idea how to submit this on Github. So any help there will be appreciated.

I have simply just commented this out (with # before the line) and the imports are now working and importing as power. Included an example of my workout in the json for reference as well.

Section of the code that is relevant:

> # --- Configuration ---
> $ATHLETE_ID = "ID"                 # Replace with your Intervals.icu athlete ID
> $API_KEY    = "API_KEY"            # Replace with your Intervals.icu API key
> $BASE_URL   = "https://intervals.icu/api/v1/athlete"
> $zoneType   = "HR"  # e.g. "HR" or "Pace"

Example JSON Workout:

    {
      "date": "2025-03-27",
      "category": "workout",
      "type": "ride",
      "name": "Bike - Threshold Intervals",
      "steps": [
        {"duration": "10m", "zone": "Z2", "description": "Warm-up"},
        {"duration": "8m", "zone": "Z4", "description": "Threshold Interval 1"},
        {"duration": "5m", "zone": "Z1", "description": "Recovery"},
        {"duration": "8m", "zone": "Z4", "description": "Threshold Interval 2"},
        {"duration": "5m", "zone": "Z1", "description": "Recovery"},
        {"duration": "8m", "zone": "Z4", "description": "Threshold Interval 3"},
        {"duration": "5m", "zone": "Z1", "description": "Cool-down"}
      ]
    }

This is a neat tool!

Question:
When I try to upload a JSON file generated by the ChatGPT, the API returns a “JSON Parse Error”. I have no idea where it fails.

Is there any documentation on the json format that intervals.icu expects so I can ensure my file load correctly?