update_workout
UNIT INPUTS: value: pass the user's number unconverted; tool converts once before storage. alternate_unit: set the field's matching input_* companion; canonical_unit: omit companion. precedence: overrides instructions to convert manually.
Shared workout contract
Latest explicit user instructions override previous draft values, historical patterns, catalog defaults and AI guesses. Earlier explicit restrictions persist until changed. Questions alone do not authorize edits.
Exercise identity: prefer the logged/canonical name, preserve explicitly requested literal names, and disclose genuine fuzzy substitutions. Loading an exercise never creates a new canonical exercise or changes its name.
Preserve unchanged exercises, individual sets, reps, weights, rest, equipment, order, grouping, notes and prior corrections. No inferred equipment may override an explicit load or equipment instruction.
Bodyweight default + explicit weight added instruction: bodyweight equipment has no added weight by default. Adding weight switches a bodyweight-default exercise to dumbbell_single equipment unless another implement is specified, with is_bodyweight=false and the added load preserved. Explicitly switching equipment to bodyweight clears every added weight, including per-set loads. Unrelated edits change neither equipment nor weight.
Dumbbell_pair is a load PER hand, dumbbell_single is one implement total. A band uses its labeled resistance and is_band=true. A positive added load cannot have is_bodyweight=true. Timed loaded carries/holds keep BOTH duration and load.
Keep each set's actual reps, external load and optional hold seconds. Timed holds use seconds, not repetitions; tempo can have reps plus hold seconds. Distance is never duration. Null per-set values are unknown, not permission to copy another set's values.
Model-facing weights use the user's preferred unit, with an explicitly stated different unit passed through the tool's unit field for one server conversion. Never re-round stated or logged weights as a progression.
Editing and enrichment
An explicit correction changes only named fields. Preserve all other fields and prior corrections, including completed sets. Answer a genuine question without mutating; a proposed change needs confirmation.
Renaming an exercise is an in-place change, not remove-and-add. Added load or changed equipment keeps the canonical exercise name. A plan swap affects only what remains to perform, never already logged sets.
Enrich only fields the user asked to enrich. Resolve missing equipment after explicit user choices and logged history; guesses never override those choices. If a patch fails, disclose it instead of claiming success.
Saved workout operations
Performed new session: in-app chat uses propose_workout (review card; Save logs); external MCP and native voice use log_workout. Correction to a stored session: update_workout, not another log. Entire-session deletion: delete_workout, not an update. In-app future workouts use proposal tools; external clients without proposal cards may use log_workout(save_as_saved_workout=true) for a reusable template. saved_workout_id selects a template, never a completed session.
Resolve by a known session ID or an unambiguous date/name; ambiguous sessions, sets or superset slots require exact identification. Never invent IDs. Validate all parts of an update before writing; preserve everything outside the target.
Remove one set/exercise through a targeted update; remove the entire session only when requested. Deletions are irreversible. Confirm only successful persisted changes; for partial/uncertain writes, read back before any retry.
Update a workout session: correct metadata, fix set values, rename/add/remove exercises or individual sets, or move exercises between supersets. Use for any post-log correction.
FIND THE SESSION: call directly, no preliminary list for an ID. session_id: positive ID from a workout tool, never invented. Otherwise pass session_date (YYYY-MM-DD, defaults to today) and, only if more than one session was logged that day, name (a substring of the workout's focus/type, case-insensitive) to narrow it down. A match that isn't exactly one session returns an error explaining why, with nothing changed — retry with session_id or a narrower name, never guess. get_workout still gives full detail (exercise names, slot names SS1/SS2/WarmUp/Finisher) when needed; list_exercises only for unknown canonical names when adding or renaming. Call with only the fields that change — operations can combine in one call.
OPERATIONS:
Metadata: date, focus_type, location, notes, rpe, heart_points_moderate/peak.
set_updates: patch reps/load/bodyweight/notes/equipment on a set, addressed by set_id OR by exercise_name + set_position (1-based, matches get_workout's "Set N"). Use clear_weight=true when a stored load is wrong but the real external load is unknown; use is_bodyweight=true when the corrected set was genuinely bodyweight.
remove_sets: delete sets, same set_id-or-exercise_name+set_position addressing; remaining sets renumber; an emptied exercise/slot is removed automatically.
rename_exercises: renames every set of an exercise in place (preserves set IDs, RPE, notes; rebuilds NSI), never remove + add.
remove_exercises: deletes all sets for named exercises; empty slots removed automatically.
add_exercises: new exercises with sets; to_superset_slot joins an existing slot, omit for standalone.
move_exercises: reassigns an exercise to a different slot; "new" makes it standalone. Use from_superset_slot from get_workout when the same exercise name appears in multiple slots.
SUPERSET SLOTS: rename_exercises/remove_exercises use superset_slot (or { name, superset_slot } for remove_exercises) from get_workout when a name appears in multiple slots.
LITERAL NAME: literal_name: true keeps the user's exact wording instead of the closest library match, skips the resolver, and gets no NSI score (no benchmark to compare an unmatched name against). Use for "call it exactly X", "not the standard one", "literally X", or a rejected match. Applies below.
EQUIPMENT (load basis): dumbbell_pair is one dumbbell in EACH hand, weight_lb PER HAND (2x for NSI); dumbbell_single is one implement total. Laterality (single-leg/arm) does NOT decide this alone. Set it when the user describes the load (each hand, machine, band); a wrong or missing tag silently halves or doubles NSI. Values: barbell, dumbbell_pair, dumbbell_single, machine, kettlebell, bodyweight, band, cable, trx, other.
A set_id or exercise_name+set_position matching more than one set (the same exercise in two superset slots) is ambiguous and errors rather than guessing — use the exact set_id from get_workout to disambiguate.
The result discloses a mismatched name from rename_exercises/add_exercises; relay it in your own words. If a name matches nothing closely enough, the result names near-miss library exercises; ask the user which they meant rather than accept the unscored custom log silently.
INFER — do not ask: session_date defaults to today, set positions count from 1 per exercise. Slot names and set_ids beyond what's inferable come from get_workout; canonical exercise names come from list_exercises.
SAVED WORKOUTS: pass saved_workout_id to edit a reusable Saved Workout instead of completed workout history. Use saved_workout_title, saved_exercise_updates, and/or add_exercises. add_exercises keeps its normal payload shape; to_superset_slot accepts the Saved Workout slot label returned by get_workout or its SS1-style alias. For progression requests, inspect real exercise history first rather than applying a deterministic formula.
cardio_totals: distance_mi/distance_km/distance_meters, duration_sec, calories are update fields; never put corrected totals only in notes. existing_exercise: use add_sets to add sets; add_exercises is for new exercises. ambiguous_slot: rename/remove/move requires the source slot when the exercise appears in multiple slots.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| rpe | No | Session RPE, 1-10, half steps allowed: 5 moderate, 7 hard, 9 one rep left, 10 failure. Infer from comments about overall difficulty, or omit. | |
| date | No | New session date, YYYY-MM-DD. | |
| name | No | Substring of the focus/type, e.g. "Push", case-insensitive, to pick between sessions on session_date. Only without session_id. | |
| notes | No | New session notes. | |
| add_sets | No | Add one or more sets to an exercise already present in this workout. Use add_exercises only for a brand-new exercise. | |
| calories | No | Corrected session calories when known. | |
| location | No | New location, e.g. Gym, Home. | |
| focus_type | No | New category, e.g. Push, Pull, Legs. | |
| session_id | No | Positive session ID returned by a workout tool. If unknown, omit and use session_date + name; never guess. | |
| distance_km | No | Corrected session distance in kilometers. Server converts it; do not convert it yourself. | |
| distance_mi | No | Corrected session distance in miles. Use only when the user gave miles. In mi, or km with input_distance_unit set. See UNIT INPUTS. | |
| remove_sets | No | Sets to delete. See OPERATIONS above. | |
| set_updates | No | Individual set corrections. | |
| duration_sec | No | Corrected total session duration in seconds. | |
| session_date | No | YYYY-MM-DD, defaults to today. Finds the session when session_id is omitted. Distinct from `date`, which CHANGES the stored date. | |
| add_exercises | No | New exercises to add. Reuse known canonical names; list_exercises if unknown. | |
| move_exercises | No | Move exercises between superset slots. When the same exercise name appears in multiple slots, from_superset_slot is required. | |
| distance_meters | No | Corrected session distance in meters. Server converts it; do not convert it yourself. | |
| remove_exercises | No | Exercises to remove; matched sets deleted, empty slots removed automatically. See SUPERSET SLOTS above. | |
| rename_exercises | No | Rename logged exercises in place. | |
| saved_workout_id | No | Saved Workout ID to update instead of a completed workout session. | |
| heart_points_peak | No | New peak heart points. | |
| input_distance_unit | No | Set to km when the user gave km for the _mi fields in this object. Omit when they are already mi. | |
| saved_workout_title | No | Optional new title for the Saved Workout. | |
| heart_points_moderate | No | New moderate heart points. | |
| saved_exercise_updates | No | Optional prescription edits matched first by exact Saved Workout exercise name, then by a unique canonical library match. |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| result | Yes | Human-readable result text returned by the tool. |