activate_onboarding_plan
ChatGPTActivate the first training plan the athlete confirmed through continue_onboarding. Takes no arguments: the plan comes from the confirmation ARC recorded, and it is refused if the athlete has not confirmed or if their preferences changed since. Activates at most once — calling again reports the plan already active. Not for plans built any other way; use activate_plan_template for the Plan Library.
activate_plan_template
ChatGPTActivate a Training Plan from the library as the active plan. Use after the athlete confirms the selected plan and any preview warnings/diff; confirmed=true is required and the saved active plan is returned. The plan is returned tiered like get_plan: every week as a spine row, workouts only for the week containing today and the next (clamped to the block), current_week_id named.
analyze_past_run
ChatGPTUse when the athlete asks to analyze, evaluate, review, or match a run from an earlier day — yesterday, a named date, or "last Tuesday" — not today; for today use analyze_today_run, which takes no date. Pass the day as date (YYYY-MM-DD in the athlete's own timezone), up to 30 days back; omit date only when the athlete named no day, and the server then searches the 7 days before today and resolves only when exactly one run falls in them. The server refreshes from a usable upstream provider when one is available, otherwise reads runs already stored in ARC, so a run the athlete's provider holds is found without asking them to describe it. If multiple runs are returned, ask which one and repeat with candidate_activity_id. The result names the day span searched in window, so say which day the run is from. The result leads with evaluation: when evaluation.basis is planned_workout, judge the session against that workout's steps and their targets (evaluation.workout.engine.segments) — not against the mile/km split table, which is supporting context only; when basis is scheduled_race, judge it as a race — against its steps (evaluation.workout) when the race carries them, otherwise against its target; only when basis is splits (nothing matched) is the split analysis the verdict. When the athlete wrote their own note on the run, athlete_note carries it: their own account in their words (how it felt, conditions, a niggle). Weigh it in the review and do not ask again for what it already says; never present it as your feedback — the athlete edits it in the ARC web app and no tool writes it. Analysis alone persists nothing: after presenting it, proactively offer to save the review with save_past_run_review.
analyze_today_run
ChatGPTUse when the athlete asks to analyze, evaluate, or review a run they did today. The server refreshes from a usable upstream provider when one is available, otherwise reads runs already stored in ARC, and computes today from the Athlete Profile timezone; never calculate or pass a date. If multiple runs are returned, ask which one and repeat with candidate_activity_id. If it returns no_activity and the athlete may mean a run from an earlier day, call analyze_past_run with that day rather than asking them to describe the run. The result leads with evaluation: when evaluation.basis is planned_workout, judge the session against that workout's steps and their targets (evaluation.workout.engine.segments) — not against the mile/km split table, which is supporting context only; when basis is scheduled_race, judge it as a race — against its steps (evaluation.workout) when the race carries them, otherwise against its target; only when basis is splits (nothing matched) is the split analysis the verdict. When the athlete wrote their own note on the run, athlete_note carries it: their own account in their words (how it felt, conditions, a niggle). Weigh it in the review and do not ask again for what it already says; never present it as your feedback — the athlete edits it in the ARC web app and no tool writes it. Analysis alone persists nothing: after presenting it, proactively offer to save the review with save_today_run_review so the feedback and any score are recorded.
author_planned_workout
ChatGPTAuthor a brand-new planned workout onto a date in the Training Plan — either a running session the template didn't include, or a non-running Strength, Cross-Training, or Mobility day. EVERY RUNNING SESSION MUST CARRY STRUCTURE. ARC builds a plain easy or long run for you from distance_m or duration_sec; for anything else pass steps, which can describe any session. It will not guess a shape it was not given — a quality day with only a description is refused rather than saved as prose, because a run with nothing to run shows nothing in the plan, sends nothing to the watch, and cannot be scored. Non-running days are the opposite and are marked, not prescribed: they carry no structured steps and add zero running mileage, so put the actual session in description. Name paces and zones, not watts: the athlete's Workout Target Preference decides whether the step is prescribed in pace (the default) or in watts, and ARC states the other currency alongside either way. Pin watts only when the athlete asked for those exact numbers. Enforces max 2 workouts per day. If there is no active plan, one is created automatically for the athlete's Training Focus (no template needed). Into a generated plan, the date must fall inside an existing plan week. NOT FOR THE LIBRARY: this puts a session on a DATE. If the athlete asked to save or create a workout for their library / their workouts, to reuse later, or without naming a day, use save_workout_pattern instead — then come back here with pattern_id to place it. Passing pattern_id here places one they already saved.
calculate_power_zones
ChatGPTEstimate five editable Power Zones from Critical Power watts: Z1 65-80%, Z2 80-90%, Z3 90-100%, Z4 100-115%, Z5 115-130%. Does not save them; call set_power_zones after review/edit. Only for an athlete who trains with a running power meter and has a measured Critical Power — never derive one from pace; pace remains the default target and needs no zones.
calculate_run_fitness
ChatGPTCompute Run Fitness score (returned as run_fitness_score) and training pace zones, from EITHER a timed effort (distance_meters + time_seconds) OR, when the athlete has no timed effort at all, an easy-run pace held for ≥20 min (easy_pace_sec_per_km). This is the ONLY way to obtain a Run Fitness score — never derive one by hand. Take whatever evidence the athlete can give: a recent official race is the most accurate input — recent matters, because Run Fitness is current fitness and a race too old to describe it should give way to a current effort — but a time trial, a hard training run, or a run read off a screenshot is accepted and is far better than no score, because plan creation is hard-blocked without one. Anything other than an official race comes back marked provisional. The result carries an evaluation block — run_fitness_score, run_fitness_source, run_fitness_evidence — to pass straight to patch_athlete_profile, so the score is saved with the evidence behind it rather than as a bare number. The timed-effort inputs (distance_meters + time_seconds) take precedence when both they and easy_pace_sec_per_km are given.
cancel_onboarding
ChatGPTStop the athlete's guided onboarding. Drops the pending question; every recorded fact (focus, profile, preferences, saved runs) stays, and a later continue_onboarding resumes from what is already true. Use only when the athlete says they want to stop.
close_training_block
ChatGPTCompute final execution metrics for a Training Block and persist it as closed.
confirm_regenerate
ChatGPTPersist the latest Plan Preview (re-generated server-side) as the new active plan. Completed weeks are kept and only the weeks ahead are rebuilt. Weeks ahead are rebuilt from the template, so any hand-authored session in them is replaced — call regenerate_plan first and check authored_at_risk, which names them. If the proposal switched plan level, that level is saved to the athlete's Plan Preferences so it sticks. The plan is returned tiered like get_plan: every week as a spine row, workouts only for the week containing today and the next (clamped to the block), current_week_id named.
continue_onboarding
ChatGPTAdvance the athlete's guided onboarding one step. Call with no arguments to learn where onboarding stands (it starts one if needed): the result names the current step, what ARC already knows, and either a question to relay to the athlete or the tools that do this step's work. To answer a question, call again with request_id and expected_version exactly as the question carried them, plus values keyed by the question's field keys. ARC decides the order of steps from the athlete's records — a step already satisfied elsewhere is passed, and an active plan ends onboarding — so never re-ask what the result says is known. Use this instead of running an interview of your own whenever a session-start result says onboarding is in progress.
delete_activity
ChatGPTSoft-delete an activity (hide from listings; recoverable later).
delete_coach_assessment
ChatGPTPERMANENTLY delete one of the athlete's Coach Assessments. Use it only when the athlete asks — typically because it turned out to be wrong, e.g. built on a duplicate run. It does not come back and no copy is kept. Never use it to update an assessment: a changed verdict is a new save_coach_assessment beside the old one. Say which assessment you are about to delete before you do it.
delete_planned_workout
ChatGPTDelete one planned workout from the Training Plan by id — the undo for author_planned_workout, and the way to drop a template day the athlete isn't doing. The week's mileage is recomputed. Does not delete any completed Activity that matched it; a workout already pushed to the athlete's watch is not un-scheduled there.
delete_race
ChatGPTRemove a race from the athlete's list, e.g. a duplicate; an upcoming one leaves the plan too. The goal race cannot be deleted; change the Training Focus instead. This is a soft-delete — the record is hidden and will no longer appear in list_races or race history, but is not permanently erased. Do NOT use this to edit a race — use patch_race for that. Requires a race_id from list_races. Destructive from the athlete's perspective.
delete_workout_pattern
ChatGPTPERMANENTLY remove one of the athlete's own saved workouts from their library. Use it when they say a saved session is junk, a duplicate, or something they will never do again — the undo for save_workout_pattern. This does not come back. If they only want it out of the way, or sound at all unsure, set status 'retired' with save_workout_pattern instead: that hides it from browse and from new placements and can be undone by setting the status back. Say which one you are about to do before you do it. Reaches the athlete's OWN library only. ARC's shared workouts are read-only to them and are refused here — retiring one of those is an admin action in the app. Sessions already on the plan are untouched: placing a workout copies its steps onto the day, so the day keeps everything it had. Nothing about the athlete's history or their plan changes.
generate_plan
ChatGPTGenerate a fresh plan from the active Training Focus and the athlete's saved Plan Preferences (which pick the library template and knobs), and persist it as the active plan. Requires a Run Fitness score on the Athlete Profile and saved Plan Preferences; if either is missing the tool returns an actionable error. The schedule is anchored to the Monday of start_date's week and schedules nothing before start_date itself; omit start_date to begin the upcoming Monday. A past start_date is treated as today. The plan is returned tiered like get_plan: every week as a spine row, workouts only for the week containing today and the next (clamped to the block), current_week_id named.
get_activity_analysis
ChatGPTEvaluate a historical or explicitly selected activity id. The result leads with evaluation: when evaluation.basis is planned_workout, judge the session against that workout's steps and their targets (evaluation.workout.engine.segments) — not against the mile/km split primitives, which are supporting context only; when basis is scheduled_race, judge it as a race — against its steps (evaluation.workout) when the race carries them, otherwise against its target; only when basis is splits (nothing matched) are the split primitives the verdict. For a run the athlete says happened today, use analyze_today_run, and for one from an earlier day within the last 30 days, analyze_past_run, so the day is resolved server-side from a fresh usable provider response or, when no provider is usable, from activities already stored in ARC. Raw provider samples are never returned or persisted.
get_activity_detail
ChatGPTReturn locally stored detail for one activity, including ARC-owned evidence and feedback. When the athlete wrote their own note on the run, athlete_note carries it: it is the athlete's own account in their words (how it felt, conditions, a niggle) — weigh it in your read of the run, and never present it as your feedback; no tool writes it, the athlete edits it in the ARC web app. The result carries evaluation — what the session is judged against: when evaluation.basis is planned_workout, evaluate the run against that workout's steps and targets (evaluation.workout.engine.segments), not against the mile/km splits, which are supporting context; only when basis is splits (nothing matched) are the splits the verdict. For a non-running activity the result carries a cardio_load attribution (its duration contribution and a counted/not-counted reason) — relay it rather than inventing a score. For entitled private Strava prototype users, append compact transient provider detail from the seven-day private cache without returning raw stream samples. Accepts a local cached activity UUID.
get_athlete_profile
ChatGPTLoad the athlete's training context (running history, altitude, Run Fitness score, training constraints, coach notes, and their saved Plan Preferences) at the start of every session before giving advice. Also the tool to answer "what are my preferences/plan settings?". Read-only. Plan Preferences are what the athlete requested, not what their plan runs — say so if the two differ, and read the active plan (get_plan) for what they are actually training on. Returns the profile object, or {setup_required: true} if no profile exists yet — when setup_required is true, the result text explains how to onboard the athlete; offer onboarding, but if the athlete declines, coach from context gathered during the session.
get_coach_assessment
ChatGPTRead one saved Coach Assessment in full: the summary verdict, the report behind it, the evidence as the coach reported it, the Training Focus it was measured against (null means none was set), the period it weighed, the activities it cited (available false means that activity has since been deleted), and its outlook when it had one — trend, section statuses, and the race marks and odds or Run Fitness outlook, all the coach's own numbers at the time (race.curve is ARC's drawing of them). It is a dated record, not current truth: its evidence was never recomputed, and training since then may have changed the picture. Read the latest one before changing the athlete's plan, weigh it, and say so if it is out of date.
get_coaching_doc
ChatGPTRead one chapter of ARC's authored coaching method. Call it for every topic a result lists under guidance_topics — before designing, explaining, or adjusting a plan, and before answering an athlete's request to change one — because the chapter overrides general training knowledge. Each chapter is short (a few KB): what to do, what never to do, and how to say it. A chapter already read this session does not need reading again. Returns the chapter text with its topic and description.
get_day_review
ChatGPTPlan-vs-actual snapshot for one calendar date. Returns the planned workout(s) for that day, any cached activities that started on the same date, and a completion entry per planned workout. Read completion, not note, to say what is finished: each entry carries the workout id and a status of completed (an activity fulfilled it, with the activity ids), completed_marked (the athlete marked it complete without a recorded activity — no measured actuals back it), missed, upcoming (today and the future are never missed), or rest. Sessions on one day finish independently, so a day can hold both a completed and a missed workout; note is a derived human line that reads like '1 of 2 completed — CG Core completed; easy 5 mi missed' on such a day, never a whole-day verdict. Includes prior coach feedback notes.
get_focus
ChatGPTReturn the active Training Focus — what the athlete is training toward. Its kind is one of: race (a goal race, with a distance and possibly a date), distance (a distance goal with no race on the calendar), or fitness (general fitness, with neither). A focus stored before kinds existed reads as race.
get_help
ChatGPTRead AgentRunCoach's product documentation. Use when an athlete asks what AgentRunCoach can do, how a feature works, or what to try next. Omit topic for the documentation index and athlete-worded examples, then call again with an exact topic for the full guide. Answer from these docs rather than reconstructing capability from tool names.
get_plan
ChatGPTReturn the active plan for the current focus. A week's training is the union of TWO arrays: workouts (training sessions) and scheduled_races (the goal race and any tune-ups). A race day carries an entry in scheduled_races and NO entry in workouts, so reading workouts alone shows race day as empty and makes race week look far shorter than it is — a week's target_miles counts both, and workout_miles + race_miles says how. Use scheduled_races[].id wherever a scheduled_race_id or race_id is required: get_race reads one, patch_race edits it, delete_race removes it, save_race enters a new one. The plan is tiered: every week of the block is present with its dates, phase, target_miles (and its workout_miles/race_miles split), scheduled_races, workout_count and quality_session_count, so the whole block's shape is always in view — but only two weeks carry their workouts: the week containing today (current_week_id) and the next, or the first two before the block starts and the last two after it ends. A week without a workouts key and workouts_omitted=true has workout_count sessions that were not loaded; detail_available=true means get_week_review with that week's id returns them now. A week without a workouts key and workout_count=0 has no training sessions; it has nothing scheduled only if scheduled_races is also empty — race week often holds the race and little else. Within a detailed week each workout omits its Structured Workout steps and is marked has_structure/step_count; fetch one workout's steps with get_planned_workout.
get_planned_workout
ChatGPTFetch one Planned Workout by id including its full Structured Workout steps (warmup / repeat / interval / recovery / cooldown with pace or power targets). The bulk plan views (get_plan, get_week_review, get_day_review, …) omit these steps to stay under the response size limit and flag each workout with has_structure/step_count; call this to load the steps for one workout when you need them.
get_power_zones
ChatGPTReturn the athlete's current five Power Zones from the Athlete Profile. Use before generating power-targeted workouts. Power is opt-in: pace stays the default target until the athlete has zones and sets workout_target_preference to power, so a pace athlete with no zones is the normal case, not a gap to fill.
get_profile
ChatGPTIdentify the ARC account represented by this authenticated ChatGPT connection. Returns a stable account ID and optional display email; it does not read training data.
get_race
ChatGPTGet one of the athlete's races by id, upcoming or past. For a race that has happened, watch is the run that was the race and its time: stored when a run was linked or a review recorded it, otherwise the day's longest run (stored false). A watch time is not the result; official_time_sec is, when set. Say which one you quote.
get_race_trends
ChatGPTReturn race trend points with pace and Run Fitness, optionally filtered by distance, tag, course, or location.
get_training_paces
ChatGPTReturn the athlete's Pace Profile: the named paces and five Training Zones (sec/km) at their stored Run Fitness, with any pace they have pinned applied and, when they have Power Zones, the watt band on every zone and on any pace they have pinned watts to — so pace and power read from one response. Call it with no argument for the athlete's own paces. Pass run_fitness_score only to project a hypothetical score ("what would I run at sea level"); a projection keeps the zone watts but carries no pinned paces or watts, since those are evidence at the athlete's real fitness. The race_equivalents are predicted from Run Fitness, never from a pinned pace: where a pace the athlete has pinned implies a different time at that distance, the entry also carries pinned_time_sec, and pinned_pace_source where that pin records its evidence, so you can say what disagrees with the prediction rather than silently preferring one.
get_week_review
ChatGPTPlan-vs-actual for a whole plan week. Returns weekly mileage rollup, adherence, quality-completion count, and a day-by-day breakdown. Each day carries a completion entry per planned workout: read completion, not note, to say what is finished. A status is completed (an activity fulfilled it, with the activity ids), completed_marked (the athlete marked it complete without a recorded activity — no measured actuals back it), missed, upcoming (today and the future are never missed), or rest. Sessions on one day finish independently, so a day can hold both a completed and a missed workout; note is a derived human line, never a whole-day verdict. adherence_pct is measured against planned_miles_to_date — planned volume for elapsed days only — so a mid-week review reads sensibly. When planned_miles_to_date is 0 (nothing has elapsed yet) adherence_pct is null: there is nothing to judge, so never report it as 0%. A race in this week appears in scheduled_races, NOT under any day's planned list — target_miles counts both, and workout_miles/race_miles state the split, so totalling the days alone falls short by the race distance. Best one-shot tool for 'how did week N go?' coaching questions.
get_workout_pattern
ChatGPTRead one saved running session in full, including every step. Use it to show the athlete what a Pattern actually asks for before placing it, or as the starting point for a variation you then save back with save_workout_pattern.
list_activity_feedback
ChatGPTList prior coaching notes saved against an activity, newest first. Call this before generating fresh feedback on the same activity (or a similar one in a series) so you don't repeat prior advice. Returns one lane only.
list_cached_activities
ChatGPTRead-only list of activities already stored in ARC. It does not fetch anything new, so a run the athlete's connected provider holds may not be here yet: to review a specific run from today or the last 30 days, use analyze_today_run or analyze_past_run for its day instead — they refresh from the provider first. Use this list to browse ARC's record or to find an older run by id. Call it BEFORE asking the athlete to describe or re-supply history ARC may already hold. What comes back is ARC's record, not the athlete's training: if it is empty, or thinner than what the athlete describes, do not conclude they have not been running — a stored provider connection is no guarantee that ARC holds their history, and the absence of one is no guarantee that there is nothing to collect. For a specific recent run, look it up for its day with analyze_today_run or analyze_past_run first; if it is still missing, ask them for a screenshot of a recent run from any fitness app — that is the most useful thing they can give you — and take a plain description if they have no screenshot. Save either with record_activity_evidence. from/to together must span at most 400 days.
list_coach_assessments
ChatGPTList the athlete's saved Coach Assessments, newest first. Returns an index — id, title, the summary verdict, when it was saved, the period it weighed, the Training Focus it was measured against (null when they had none), and the headline of its outlook when it had one (trend direction, chance of the target time, the Stretch, Toss-up and Likely times — or the projected range on assessments saved before those existed — and the Run Fitness outlook) — not the reports; open one with get_coach_assessment. Read the headlines before writing a new outlook's trend: they are your earlier numbers to compare against. Read this history before starting a new plan, and when the athlete asks how their training has gone over time. One page at a time: when next_cursor is present there are more, so do not describe this page as their whole history — pass it back as cursor to read on.
list_duplicate_activities
ChatGPTDetect near-duplicate activities in the cache (same start ±5min, distance within 2%).
list_plan_templates
ChatGPTList ARC's Training Plan library (ready-made, distance-specific plans) with style, load, and comparison metrics.
list_race_tags
ChatGPTList race tags already stored locally.
list_races
ChatGPTList the athlete's races, newest first: races already run, with their results, and upcoming races they have entered (no time yet). prescribed says whether a race is on the plan; outcome says how a past race ended when someone recorded it. Local-only: does not call any upstream provider.
list_training_blocks
ChatGPTList prior Training Blocks with planned metrics, execution metrics, and ARC optimization insights.
list_workout_patterns
ChatGPTList the reusable running sessions available to this athlete: the ones they saved themselves, plus the published shared set. Ordered in three groups — the athlete's starred workouts first, then their own, then ARC's shared ones — each newest first. Returns an index: id, name, type, step count, not the steps themselves; call get_workout_pattern for what a session actually asks for. Use it before writing a session from scratch — they may already have the one they want — and when swapping a planned day for something they like. One page at a time. When the result carries a next_cursor there are more workouts than were returned, so do not tell the athlete this is everything they have — pass that value back as cursor to read on. Set favorites true to read only what they have starred, which is the right call when they ask for a workout they like rather than for the whole library.
mark_planned_workout_complete
ChatGPTRecord that the athlete performed a non-running planned workout — Strength, Cross-Training, or Mobility — that ARC has no recorded activity for, or withdraw that record with completed=false. Only these mark-only days qualify: they carry no distance or pace prescription, so marking one loses nothing. Running sessions are refused, because marking carries no distance and the run would read as done while contributing zero miles against its prescription — log the run with record_activity_evidence instead. Only today or an earlier date can be marked. A workout ARC can already see was completed by an activity is refused too: the activity is the better evidence and already completes it. Marking contributes no mileage, adherence, Cardio Load, or execution score; it records that the session happened.
move_planned_workout
ChatGPTMove a planned workout to another current or future date in the active plan, including across week boundaries (for example Sunday to Monday). Preserves the workout and its structure, enforces max 2 workouts per day and both weeks' mileage budgets, and refuses past dates.
patch_athlete_profile
ChatGPTPersist updates to the Athlete Profile. Call after gathering new context — after the onboarding interview, after a race is logged (compute the score with calculate_run_fitness first, then pass its evaluation block here), or when the athlete volunteers a training constraint such as an injury to work around. All fields are optional; only provided fields are updated. ARC is not a medical tool: never solicit or record a diagnosis, a medication, or a medical history, and when a symptom needs a clinician say so instead of planning around it.
patch_plan_week
ChatGPTPatch a plan week. Set phase/notes to correct the periodization label or add coaching notes. Set target_miles to replan (relayout) the week to a new weekly mileage: already-run days are kept, days from today on are rebuilt using the plan's knobs, the week budget (<= 105% of peak) is enforced, and the change is recorded as an adaptation event. Past weeks cannot be relaid.
patch_planned_workout
ChatGPTPatch one planned workout's kind, type, terrain, distance, duration, name, or notes. Changing what a running session ASKS FOR must leave it with structure: this tool has no reps/interval_meters/work_block_minutes shorthand, so turning a day into intervals, hills or a threshold session means passing steps. Distance or duration alone is enough only for a plain easy or long run, which ARC rebuilds itself. A running session's title and description are RENDERED FROM ITS STEPS and are refused here — name the session with session_name, put coaching words in notes, and change what it asks for with steps. Title and description are accepted on a Strength, Cross-Training or Mobility day, which has no steps to render them from.
patch_race
ChatGPTEdit fields on one of the athlete's races — e.g. correct a finish time, date, distance, name, or location, set its target, record how it ended, link or relink the run that was the race, or take an upcoming race off the plan. Every field except prescribed stays editable after race day. Moving an upcoming race or changing its distance changes the plan days it holds and is refused when that pushes a week past its mileage budget. Requires a race_id from list_races or get_plan's scheduled_races. All fields are optional; only the fields you provide are changed, and passing an empty string to a text field (e.g. notes) clears it. An upcoming goal race's name, date, distance and target are edited through set_focus. To remove a race entirely use delete_race; to enter a new race use save_race.
patch_workout_step
ChatGPTEdit ONE step of a planned workout in place: its length, a repeat count, or what it targets. To rewrite the session's whole structure use patch_planned_workout with steps[] instead. The pace_zone argument names the intensity; the service applies pace or power primary targets from the active plan. Select any nested step with step_path, or use the legacy step_order/step_type and optional child selectors. The workout's title and description re-render from the steps this edits, so they never need updating alongside it. A patch changes the plan only; pushing it to the athlete's watch is a separate step.
preview_plan_template
ChatGPTPreview a Training Plan from the library against the current focus. Does not persist or activate the plan, and saves no Plan Preferences — only activate_plan_template does. Returns the proposed plan, requires_override_confirmation, replaces_active_plan, and a diff against the plan it would replace — read metrics, coach adjustments and override warnings from proposed.planned_metrics / proposed.adjustment_reasons / proposed.override_reasons. Summarize warnings before asking the athlete to confirm activation. races lists the athlete's races this plan would pick up; one with over_budget pushes its week past the mileage limit and confirming takes it off the plan (it stays in their races) — tell the athlete before they confirm. The proposal is tiered like get_plan: every proposed week is listed with its dates, phase, target_miles, races and workout_count, and only two weeks carry their workouts — the week containing today and the next, or the first two before the block starts and the last two after it ends. Other proposed weeks say workouts_omitted=true and detail_available=false — a proposal is not saved, so get_week_review cannot read it; those sessions become readable once the proposal is confirmed.
reanchor_plan
ChatGPTRe-fit the active Training Plan to the Training Focus's current race date, lengthening or shortening the block. Weeks the athlete has already completed are kept untouched; only the weeks still ahead are rebuilt, so hand-tuned history and completed work survive. Use this when get_plan reports reanchor_needed: it is the tool that answers a moved race date, and it needs no Plan Preferences change to do so. regenerate_plan is the tool for a changed request — it re-fits the same plan to the athlete's current Plan Preferences and keeps completed weeks and the plan's history the same way. Confirm with the athlete before calling: this reshapes their upcoming training. The plan is returned tiered like get_plan: every week as a spine row, workouts only for the week containing today and the next (clamped to the block), current_week_id named.
record_activity_evidence
ChatGPTPersist a completed activity ARC does not already hold in full, from a screenshot the athlete shared in this conversation or from what they told you ("8 miles in about 62 minutes yesterday"). Usually a run, but any session works — a duration-only climb or strength session omits distance_m rather than sending a placeholder. This is the provider-free route into the durable record and it works at any time — during onboarding, and afterwards whenever a run fails to reach ARC. For a run from today or the last 30 days, first look it up for its day with analyze_today_run or analyze_past_run — they refresh from the athlete's connected provider, so a run the provider holds is found without being typed in; otherwise read what ARC already has with list_cached_activities first. Ask the athlete for permission and wait for an explicit yes before calling this. Record ONLY values visible in the screenshot or stated by the athlete: leave every other field out rather than estimating it, and never invent splits or samples. Every value must come from this conversation — never from your own memory, from another athlete's history, or from a plausible guess. Do not offer the athlete a specific race, date, or finishing time to confirm: a named plausible option is very hard to decline, and once confirmed it is indistinguishable from something they actually remembered. Ask open questions instead. ARC does the matching: omit activity_id and it either enriches the activity it matches or creates a new one, so do not reason about duplicates yourself. Evidence fills empty fields only — anything the provider already recorded is kept and any disagreement comes back in conflicts rather than overwriting. Screenshot bytes are never stored. The saved activity is durable and reads back through list_cached_activities for later review and plan work.
regenerate_plan
ChatGPTCompute a proposed plan + diff vs the active plan, from the athlete's saved Plan Preferences. Does NOT persist; call confirm_regenerate to apply. The result carries the proposal and a diff, never the plan being replaced — replaces_active_plan says whether there is one. Takes no arguments — to change the plan's shape (peak weekly miles, run days), patch the athlete's Plan Preferences first with patch_athlete_profile, then regenerate. A requested peak is honored; if it is more than the athlete's current plan level can shape, the proposal switches to the plan level at the SAME race distance that is built for it, and proposed.adjustment_reasons says so — relay that to the athlete before confirming. races lists the athlete's races this plan would pick up; one with over_budget pushes its week past the mileage limit and confirming takes it off the plan (it stays in their races) — tell the athlete before they confirm. The proposal is tiered like get_plan: every proposed week is listed with its dates, phase, target_miles, races and workout_count, and only two weeks carry their workouts — the week containing today and the next, or the first two before the block starts and the last two after it ends. Other proposed weeks say workouts_omitted=true and detail_available=false — a proposal is not saved, so get_week_review cannot read it; those sessions become readable once the proposal is confirmed.
rename_race_tag
ChatGPTRename a race tag locally. If the new tag already exists, race links are merged into it.
restore_activity
ChatGPTRestore a soft-deleted activity to local listings.
save_activity_feedback
ChatGPTPersist a coaching note against a historical or explicitly selected activity. For a run the athlete says happened today, use analyze_today_run followed by save_today_run_review so the server resolves athlete-local today; for one from an earlier day they name within the last 30 days, analyze_past_run followed by save_past_run_review. Write a concrete, short note focused on what you observed and what it means for training.
save_coach_assessment
ChatGPTSave a Coach Assessment: your dated judgement of a stretch of the athlete's training — how they are tracking toward their focus, a race debrief, readiness to return from injury, a block wrap-up. Not for a single run: that is save_today_run_review or save_activity_feedback. Once you have given the athlete the assessment and the conversation has reached a verdict, OFFER to save it and wait for an explicit yes. They may want to push back or add context first, and the save should read to them as a confirmation, not a side effect. A saved assessment is never edited. If your verdict changes later, save a new one beside it; the athlete reads them in order as the story of their training. An athlete keeps at most 2 assessments saved in any 24 hours, so save the verdict that matters, not every interim read. Before offering to save, check created_at in list_coach_assessments: if 2 were saved in the last 24 hours, tell the athlete when saving will next be possible instead of offering now. ARC records the athlete's Training Focus as it stands right now alongside the assessment, so do not restate it as evidence. ARC stores your evidence exactly as you write it and never recomputes or checks it, so report only figures you read from ARC's tools in this conversation. Saving changes nothing about the plan: if the assessment recommends a change, make it with the plan tools, with the athlete's agreement. Give every assessment an outlook unless you genuinely have no forward view: with a race Focus, outlook.race with your marks (and goal_chance when there is a target time); without one, outlook.fitness if you expect Run Fitness to move; and a trend whenever the athlete has earlier assessments. Put the numbers in the outlook, not only in the prose, and tables (weekly volume, key sessions) in the report as Markdown tables.
save_past_run_review
ChatGPTPersist the complete coaching review after analyze_past_run, passing the same date. The server resolves that day's run again — refreshing from a usable upstream provider when one is available, otherwise reading ARC's stored runs — owns plan/race matching, scoring, and feedback-lane selection, and makes exact retries idempotent. Nothing earlier is lost: feedback is added beside earlier notes, and a coach_score is added beside earlier coach scores, the latest counting. Pass the resolved activity id back as candidate_activity_id so it is revalidated. After it returns, confirm the outcome to the athlete plainly from scoring: when scored is true, state the execution score; when scored is false, tell them the review was saved and relay no_score_reason rather than leaving the missing score unexplained.
save_race
ChatGPTEnter one of the athlete's races, at whatever stage it is at: an upcoming race they will run, a race they have run with its result, or a run that was a race. The race date and a finish time decide which. Without a time, a date today or ahead enters an upcoming race: it is saved as one of the athlete's races, outlives any plan, and any Training Plan whose dates cover it shows it — the race takes its day, the day's planned workouts are hidden while it holds it, and it counts toward that week's mileage; the result says whether the active plan holds it, and when it does not, tell the athlete so — a later plan covering the date picks it up. With a finish time, a date today or earlier records the result (a date after today is refused: nothing has been run yet). When the athlete already entered that race (the same date and distance — a tune-up or their goal race), its result is filled in rather than a second race logged, the result says so, and the details the race already had are kept; a different time on a race that has one is refused — correct a result with patch_race. A result for a race nobody entered is history: it is listed and counts in trends but is never on a plan, even on its own day. With activity_id the result is taken from that stored run (its date, distance and time unless given), and the run is linked. Refused when another race on a plan already holds an upcoming date, or when it would push that week past its mileage budget. The goal race comes from the Training Focus; set it with set_focus. Source a finish time from the athlete directly, or read it from a screenshot of their results screen or timing app (which shows name, bib, splits, finish time). Do not web-fetch a public results page to look up a bib — most timing platforms (RunSignup, ChronoTrack, RaceResult) and event results sites like BolderBoulder render results client-side in JavaScript, so the fetched HTML will not contain the result and the lookup fails silently. After recording a result without a run: call search_race_activity_candidates with the YYYY-MM-DD race_date to find the matching run and patch_race to link it, then get_race_trends to show the athlete's race progression.
save_today_run_review
ChatGPTPersist the complete coaching review after analyze_today_run. The server resolves today's run again — refreshing from a usable upstream provider when one is available, otherwise reading ARC's stored runs — owns plan/race matching, scoring, and feedback-lane selection, and makes exact retries idempotent. Nothing earlier is lost: feedback is added beside earlier notes, and a coach_score is added beside earlier coach scores, the latest counting. Pass the resolved activity id back as candidate_activity_id so it is revalidated. After it returns, confirm the outcome to the athlete plainly from scoring: when scored is true, state the execution score; when scored is false, tell them the review was saved and relay no_score_reason (for example, the run was not matched to a planned workout, so there is no score) rather than leaving the missing score unexplained.
save_workout_pattern
ChatGPTSAVE a running session for reuse WITHOUT putting it on a date. Use this — not author_planned_workout — whenever the athlete asks to "create a workout for my library", "save this workout", "add one to my workouts", "keep this for later", or otherwise talks about building a session they want to use again. Those words mean the library; author_planned_workout means a specific day. If they say both ("save this and put it on Thursday"), save it here first, then place it with author_planned_workout's pattern_id. It lands in the athlete's own Workouts library, so they can drop it onto a plan day later instead of writing it out again. Build the session with steps, exactly as author_planned_workout takes them — a Pattern IS a step tree, just not bound to a date yet. Targets stay unresolved: name a pace or a zone and it resolves against whatever the athlete's Run Fitness is on the day they use it, which is what makes one Pattern usable all block. You may pin an explicit band here — this is the athlete's own library and nobody else reads it — but prefer a name or target_pace_sec_per_km unless they asked for those exact numbers, because a pinned band freezes against fitness that moves. Watts follow the athlete's Workout Target Preference when the Pattern is placed: pace is the default, and a power athlete with Power Zones gets the same session in watts with the pace alongside, so name the pace here rather than converting. Structured quality only: intervals, threshold blocks, race-pace work, hill sets, a strides finisher. A plain easy or long run is refused — ARC generates those, and there is no shape in one worth saving. Pass pattern_id to update one they already have.
score_workout_execution
ChatGPTCompute and persist the deterministic Execution Score for a historical or explicitly selected activity against its planned workout. For a run the athlete says happened today, use analyze_today_run followed by save_today_run_review; for one from an earlier day they name, analyze_past_run followed by save_past_run_review. Pass planned_workout_id to score a historical activity against a workout it is not already linked to; the score is stored, the link is not.
search_race_activity_candidates
ChatGPTSearch locally cached activities that match a race by date and distance. Local-only: does not call the upstream provider. Two separate workflows: (1) after save_race recorded a result without a run — link the candidate with patch_race (race_id plus activity_id); (2) standalone — identify the run first, then save_race with its activity_id. Do not mix them: a race already recorded takes the run through patch_race, not a second save_race, which would fill the same race in again.
set_execution_score
ChatGPTOverride the Execution Score for a historical or explicitly selected activity. The override is added to the run's history of coach scores: earlier coach scores and the deterministic engine score are kept, the latest override is the score shown, and repeating the latest override changes nothing. For a run the athlete says happened today, use analyze_today_run followed by save_today_run_review; for one from an earlier day they name, analyze_past_run followed by save_past_run_review. For a Scheduled Race, pass scheduled_race_id to attach an agent-only score; for a Planned Workout, run score_workout_execution first.
set_focus
ChatGPTCreate or replace the active Training Focus — what the athlete is training toward. Three kinds: a goal race, a distance goal with no race on the calendar, or general fitness. This replaces the focus outright: every field omitted is cleared, and nothing carries over from the focus it replaces, so send what describes the target now rather than replaying an earlier get_focus. The Focus is the target only: Run Fitness lives on the Athlete Profile (set via patch_athlete_profile after calculate_run_fitness) and plan-shaping knobs (peak miles, run days, taper, long-run day) are Plan Preferences passed when generating or activating a plan. A goal race with a date is one of the athlete's races (race_id on the result; read it with get_race). When the Focus stops pointing at a race the athlete had entered, that race is kept but taken off the plan, and goal_race_note says so — relay it.
set_power_zones
ChatGPTSave the athlete's current five Power Zones on the Athlete Profile. Use manually entered/Stryd-exported watt ranges or reviewed calculate_power_zones output. Saving zones does not make power the athlete's target: pace stays the default until they set workout_target_preference to power, and until then the zones ride alongside every pace prescription as the watt equivalent.
set_workout_pattern_favorite
ChatGPTMark or unmark one of the athlete's workouts as a favorite. Favorites rank first everywhere sessions are listed or offered, so this is how the athlete tells ARC which sessions they actually want to see again — set it when they say a session went well or ask for more like it.
submit_checkin
ChatGPTRecord a weekly check-in: energy 1–10, injury flag, hours available, free-text notes. Feeds the next re-plan. The injury flag is a planning signal, not a diagnosis — ARC is not a medical tool, so plan around what hurts and refer a symptom that needs a clinician rather than assessing it.
submit_ticket
ChatGPTFile a feature request or bug report on the ARC feedback board. Opens in the 'open' state with your auto-vote; the team triages it from there.
swap_planned_workouts
ChatGPTSwap the dates of two planned workouts anywhere in the active plan, including across future week boundaries. Past-dated workouts remain locked.
tag_race
ChatGPTAdd comma-separated tags to a locally recorded race.