Skip to main content
Glama

Server Details

AI-native training platform for cyclists and runners: calendar, rides, readiness, sourced science.

Ownership verified
Status
Healthy
Uptime
99.2% over 22 days
OAuth
Works in Glama
Last Tested
Transport
Streamable HTTP · MCP 2025-11-25
URL

TDQS

A4.1/5.0

Scored across 63 tools

Disambiguation4/5

The descriptions are unusually explicit about boundaries: add_fact vs confirm_fact vs update_fact, copy_week vs copy_workouts vs plan_workouts, and the read family (get_plan/get_plan_workout/get_catalog_workout) each state when to use which. A few genuine overlaps remain — get_today duplicates the date already returned by get_context, get_context partly subsumes get_plan/list_activities/get_readiness_today/list_facts, and get_records/estimate_thresholds/get_metric_history all touch threshold data — so an agent can still misselect among the omnibus and granular readers.

Naming Consistency5/5

Uniform snake_case verb_noun throughout: add_/confirm_/update_/retire_fact, get_/list_/log_/set_/search_/estimate_/copy_/remove_from_plan, etc. No camelCase, no mixed verb styles, and the noun consistently names the target resource.

Tool Count2/5

63 tools is far beyond the practical ceiling even for a broad coaching platform, forcing an agent to reason over a very large schema on nearly every turn. The scope is genuinely wide (plan, activities, readiness, facts, strength, events, knowledge base, metrics), so each tool roughly earns a niche, but redundancy such as get_today vs get_context shows the surface could be consolidated considerably.

Completeness4/5

Lifecycle coverage is exceptional: full plan CRUD (plan_workouts, update_plan_workout, remove_from_plan, copy_week/copy_workouts), activity reading/editing/notes/tags/RPE/lactate, readiness read+log+baseline, facts add/update/confirm/retire/list, events create/update/delete/notes/course, profile read/update, catalog and knowledge search/read, and strength log/progression/notes. Minor gaps remain (no activity deletion, no explicit library-workout management, no fact hard-delete — deliberately, since retire_fact covers it), all workaroundable.

Available Tools

65 tools
add_checklistAInspect

Put a CHECKLIST on a calendar day, or ADD ITEMS to the one already there — a day note whose items the athlete ticks off in the calendar, desktop and phone. Use it when they want a list to work through, not advice to read: a race kit, the evening before a test or a race, a travel bag. Title + items; a list with the same title on that day is EXTENDED (ticks kept, duplicates skipped). Items are concrete things to do or take, a few words each — not advice, not training (that is plan_workouts). One day per call; it does not repeat. Saved on return, no card. Read it back in the day's notes: "[x] …" is ticked, "[ ] …" still open — say what is left instead of asking. You cannot tick for them.

ParametersJSON Schema
NameRequiredDescriptionDefault
dateYes
colorNonew list only, and only if they told you what the colour means
itemsYesplain text, no bullets or boxes
titleYesthe list's name, e.g. "Race kit"

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only say readOnlyHint=false and destructiveHint=false. The description adds rich behavioral detail: same-title extension (ticks kept, duplicates skipped), single-day, no repeat, saved on return with no card, and the read-back format. It also discloses that the agent cannot tick items for the athlete. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is longer than minimal, but every sentence adds distinct information: purpose, use cases, extension, constraints, persistence, read-back, and boundaries. It leads with the core action and flows logically, though it could be trimmed slightly without losing value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a write tool with no output schema and modest annotations, the description covers what an agent needs: inputs (date, title, items), behavior (extend vs new), side effects (saved, no card), and how to verify/read back results. It also distinguishes from plan_workouts, so the agent is fully equipped to invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 75%, so the baseline is near 3. The description adds meaning beyond the schema for title (same title/day extends the list) and items (concrete, few words, not advice/training). It does not add color semantics, but the schema already documents color's conditional use.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb-resource pair: 'Put a CHECKLIST on a calendar day, or ADD ITEMS to the one already there.' It also distinguishes from siblings by explicitly naming plan_workouts for training and contrasting 'not advice to read.' The single-day, no-repeat statement further separates it from recurring or copying tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit 'Use it when they want a list to work through, not advice to read' with concrete examples (race kit, evening before a test/race, travel bag). It names the alternative for training (plan_workouts), states the extension behavior, and the 'cannot tick for them' boundary, so agents know when to invoke and what to avoid.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

add_factAInspect

Record ONE thing you now know about the athlete, with how long it is true. This is the assistant's memory: it is NOT a copy of the snapshot and NOT a training log. Three tests, all must pass — (1) it is not already handed to you every turn (age, weight, hours, available days, thresholds, zones, race dates, the plan, load, readiness, response_profile), (2) no tool computes it (get_metric_history, get_records, get_activity), (3) it outlives this session — the verdict on one workout goes on that workout with set_activity_notes.

AREA decides what survives when context is tight: "health" and "constraint" are never cut, "pattern" is the only capped area. Nuance goes in tags, which are free.

CONSTRAINTS include a fixed commitment on a day the profile calls free, another coach's remit, an injury to plan around, and EQUIPMENT — tagged equipment, recorded as what they actually own in their words, with a horizon like anything else (a gym membership is an until, a turbo in the hallway is often a season).

HORIZON is required and there is no "unknown": if you cannot say how long it holds, ASK before writing. "stands" = until they say otherwise. "until" + dueDate = it ends (a race, an arrangement); when the date passes the fact stops applying and its opposite does NOT start applying. "recheck" + dueDate = it does not become false, it becomes untrustworthy (a threshold, a blood value, weekly hours). "season" + seasonFrom/seasonTo = true only part of the year (months, may wrap: 11-03 is November to March). "pattern" = an observation; set confirmations as you see it again.

dueAction is the line between a date that becomes a CALENDAR item and a date that is merely a question. Set it only when the due date carries something the athlete DOES ("сдать ферритин", "перемерить порог 30-мин тестом") — that is proposed as a calendar entry on the date itself. Leave it empty for "ask whether this still holds": no calendar clutter for a conversation.

Silent when the athlete just told you the fact. A CARD when it carries a dueAction (it will put something in their calendar), when it is a pattern (that is your inference about them, not their words), or when it replaces a fact already on their page.

ONE IDEA, ONE LINE. If a live fact of the same area already says something like this, the call is HELD and you get those facts back with their ids: answer with new:true (genuinely different — both stay, and a different day, date, trip or measurement IS different however alike the wording), replaces:<id> (this supersedes it — the old one is retired as this is written), or confirms:<id> (literally the same thing — that fact is bumped and your line is discarded). Every fact in your snapshot already ends with its #id, so a pattern you see again is confirm_fact on that id, not a second add_fact.

ParametersJSON Schema
NameRequiredDescriptionDefault
newNotrue = write it beside the similar facts add_fact showed you, because it is a different thing
areaYes
tagsNo
textYesthe fact itself, in the athlete's language, one thing only
sourceYesathlete = they said it; assistant = you inferred it
dueDateNorequired for until / recheck
horizonYes
confirmsNoid of a live fact that already says this — it is bumped instead, nothing new is written (only after add_fact held your call and showed it)
dueLabelNowhat it is tied to, e.g. '10 км'
replacesNoid of a live fact this one supersedes — retired as this is written; a card
seasonToNo
dueActionNowhat the athlete DOES on that date; set it and it becomes a calendar item
seasonFromNo
confirmationsNopatterns only — how many times you have seen it

TDQS

A4.1/5.0
Behavior1/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations declare destructiveHint=false, meaning the tool performs only additive updates, but the description explicitly says `replaces:<id>` retires an existing fact as this one is written. That is a non-additive state change to existing data and contradicts the annotation. The rich behavioral detail about held calls, cards, and horizons cannot overcome the contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with purpose and organized into sections for area, constraints, horizon, dueAction, and duplicate handling. It is very long, but the length is largely justified by the tool's 14-parameter complexity and the absence of an output schema. Some repetition and all-caps rule statements could be tightened.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity, 14 parameters, and no output schema, the description covers the full lifecycle: when to write, what not to write, horizon semantics, area behavior, card versus silent behavior, and how held calls return similar fact ids. Nothing critical for correct invocation appears to be missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 14 parameters and only 64% schema description coverage, the description adds substantial meaning beyond the schema. It explains horizon values (stands, until, recheck, season, pattern), dueDate requirements, dueAction versus mere questioning, tags, area survival rules, and the new/replaces/confirms semantics. This compensates well for the schema's coverage gaps.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Record ONE thing you now know about the athlete, with how long it is true.' It immediately distinguishes this memory tool from the snapshot and training log, and later names sibling tools such as set_activity_notes and confirm_fact. An agent can tell what this tool is for without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is richly specified: three tests must all pass before writing, computed values should use get_metric_history/get_records/get_activity, and workout verdicts belong in set_activity_notes. The description also explains when to be silent versus when to produce a card, and how to respond when a call is held with similar facts. This is explicit when-to-use, when-not-to-use, and alternative routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

close_commitmentAInspect

Judge one of your own earlier instructions once the day it applied to has passed and the session is in the data: kept, missed, or dropped (you changed your mind, or it stopped being relevant). Say what actually happened in one line. An instruction nobody ever checks teaches the athlete that none of them matter — this is how you close that loop.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesthe commitment id, shown in brackets in the snapshot
statusYes
verdictYesone line, in the athlete's language: what actually happened

TDQS

A4.1/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already convey that this is not a read-only operation and is not flagged destructive. The description adds useful behavioral context about the evaluation lifecycle and the meaning of 'dropped', but it does not explain side effects such as whether a commitment can be reopened or whether the status becomes permanently closed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The core usage is front-loaded and clearly structured. The final motivational sentence about closing the loop is somewhat extra, but it reinforces why the tool exists without making the description bloated.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple three-parameter tool, the description covers what, when, and why. It explains the timing prerequisite, the status options, and the required verdict format. No output schema exists, but return-value documentation is not necessary for this kind of action.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 67%, and the description adds meaning beyond the schema: it defines the three statuses, clarifies that 'dropped' includes changed-mind or no-longer-relevant, and reinforces the one-line verdict requirement in the athlete's language. The id parameter is already well described in the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description says exactly what the tool does: evaluate one of the agent's own earlier instruction/commitment once its day has passed, and record whether it was kept, missed, or dropped. This is a specific verb plus resource that clearly separates it from list/get tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives a concrete condition for when to use the tool: only after the applicable day has passed and the session data is available. It does not explicitly name alternative tools or say when not to use it, but the timing rule is clear and actionable.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

confirm_factAInspect

You saw a pattern happen again. Bumps its confirmations and stamps today, which is what makes it outrank weaker patterns when context is tight — and what stops it decaying out of the snapshot after six months unobserved. Silent, no card: counting an observation is not a claim about the athlete. Use it instead of writing the same pattern twice.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYes
noteNooptional: what you saw this time, appended to the fact

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description reveals concrete behavioral effects: confirmations are incremented, today's date is stamped, ranking is increased, decay after six months is prevented, and the operation is silent with no card. This goes well beyond the sparse annotations (readOnlyHint, openWorldHint, destructiveHint) and no output schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences with no filler; the trigger is front-loaded and each clause earns its place by explaining a behavioral consequence. The ranking/decay aside is dense but directly relevant to why confirmation matters.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter confirmation tool with no output schema, the description fully covers the situation, side effects, and semantic boundary. The only small gap is that it never states what the function returns, but this is low-stakes for a tool described as 'silent'.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Only 50% of the parameters have schema descriptions, and the description does not directly explain the id parameter beyond implying it identifies the pattern/fact. The note parameter is already well described in the schema ('what you saw this time, appended to the fact'), so the description adds no additional parameter value.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with the exact trigger, 'You saw a pattern happen again,' and states the core action: record a repeat observation by bumping confirmations and stamping today. It distinguishes confirm_fact from add_fact/update_fact by explicitly telling the agent to use it instead of writing the same pattern twice.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives a when-to-use condition (a pattern is observed again) and an explicit alternative ('instead of writing the same pattern twice'), routing the agent away from creating duplicate facts. The additional note that confirmation is not a claim about the athlete provides a clear exclusion for what the tool is not for.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

copy_weekAInspect

Copy a whole training week onto other weeks, weekday by weekday — Monday's work lands on Monday. from and each entry in to may be ANY date inside the week you mean; the week is taken from it. Day notes travel too, but only onto days that have none. This is the tool for «повтори прошлую неделю», for repeating a base week before it steps up, and for laying the same block out three times — it is one call instead of a dozen plan_workouts items, and it reproduces the week exactly. It ADDS to the target weeks: days that already hold work keep it, so a week you mean to REPLACE has to be emptied first with remove_from_plan, day by day, which the athlete will see you do.

ParametersJSON Schema
NameRequiredDescriptionDefault
toYesany date inside each week to copy TO
whyNoONE line, in the athlete's language: WHY this change — the reason from the conversation ("travel Thu-Fri, long ride moved to Sat", "deload after 3 build weeks"). The athlete's other assistant surface reads it later; without it, it sees only that the plan changed. No health details beyond what the plan needs.
fromYesany date inside the week to copy FROM
withDayNotesNocarry the source week's day notes as well (default true; they only land on days that have no note)

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only say it is not read-only and not destructive; the description adds the crucial trait that it ADDS rather than replaces (days with existing work keep it), that day notes travel only onto empty days, and that replacing requires an explicit prior removal the athlete will see. This is significant behavioral context beyond structured fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core action in the first sentence, then layers usage and the add-not-replace caveat in a deliberate order. Slightly long, but every sentence carries information an agent needs; nothing is redundant.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 4-parameter mutation tool with no output schema, the description supplies the safety-critical caveats (additive behavior, note-transfer rules, replace requires emptying first) that an agent needs to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all four parameters, including the date-in-week and withDayNotes semantics. The description reinforces the 'any date inside the week' behavior and weekday mapping but does not cover the `why` parameter or add much beyond the schema. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource — copy a whole training week onto other weeks — and immediately names the mapping semantics (weekday by weekday). It clearly distinguishes itself from siblings like plan_workouts and copy_workouts by positioning itself as the atomic one-call alternative.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly gives when-to-use scenarios in the athlete's own language, and — critically — states when NOT to use it for replacement, naming remove_from_plan as the required alternative. This is textbook when/when-not/alternative guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

copy_workoutsAInspect

Copy planned work from one day to other days — the athlete's own Copy/Paste, as a tool. Pass iid to copy ONE scheduled session (from get_plan), or omit it to copy everything planned on that day. Reach for this instead of re-writing the session with plan_workouts whenever they want the SAME thing again — a repeated Tuesday, last week's long ride, the gym session that worked: it carries the exact structure, the note, the context tags and the key star, and it invents nothing. The copies are independent entries — editing one later changes nothing else, and no series links them. A copy ADDS to the target day; to replace what is there, call remove_from_plan for that day first and say so.

ParametersJSON Schema
NameRequiredDescriptionDefault
toYesthe day(s) to copy TO
iidNocopy just this one workout (iid from get_plan); omit to copy the whole day
whyNoONE line, in the athlete's language: WHY this change — the reason from the conversation ("travel Thu-Fri, long ride moved to Sat", "deload after 3 build weeks"). The athlete's other assistant surface reads it later; without it, it sees only that the plan changed. No health details beyond what the plan needs.
fromYesthe day to copy FROM

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With annotations only covering the safety profile, the description supplies the crucial operational semantics: copies are independent entries, no series links them, and a copy ADDS to the target day rather than replacing it. It also notes what is carried over (structure, note, tags, key star) and that nothing is invented.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action and the iid behavior, then the usage guidance, then the add-not-replace caveat. It is dense with em-dashes and examples, so it runs slightly long, but every sentence carries actionable information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with no output schema and annotations that only declare the safety profile, the description covers the add-vs-replace behavior, copy independence, what is preserved, and when to choose this over plan_workouts. An agent has everything needed to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the schema already documents iid, from, to, and why. The description reinforces the key iid distinction (pass it for ONE session from get_plan, omit to copy the whole day), adding a little framing beyond the schema but no new format or syntax detail.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource (copy planned work from one day to other days) and immediately frames it as the athlete's own Copy/Paste. It differentiates from siblings by naming plan_workouts and remove_from_plan as the alternatives for different intentions.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says to reach for this instead of re-writing with plan_workouts when the athlete wants the SAME thing again, and gives the replace-vs-add rule (call remove_from_plan first). Concrete scenarios (repeated Tuesday, last week's long ride, gym session) make the selection condition unambiguous.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

create_eventAInspect

Create an event the athlete is preparing for (race, key ride, FTP test) on their Blocks calendar. Use when the athlete describes one in chat. Requires name + date (YYYY-MM-DD). Optional: description, location, map/event-page URLs, logistics notes, prep (coach) notes, priority, target and local start time (picks the forecast hours). The GPX route is added by the athlete in the app. Event-day weather is fetched automatically when within ~16 days. Returns the new event id (pass it to set_event_notes to add detailed prep).

ParametersJSON Schema
NameRequiredDescriptionDefault
dateYes
nameYesevent name, e.g. 'Gravel Fondo 120'
notesNoathlete logistics (parking, number pickup…)
mapUrlNo
targetNotheir aim, e.g. 'sub-40'
eventUrlNoofficial race / registration page
priorityNoA = season goal, B/C = on the way, '' clears
startTimeNolocal start time HH:MM
coachNotesNoprep notes (fueling, pacing, taper)
descriptionNo
locationTextNotown / venue — also used to fetch weather

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false, destructiveHint=false, and openWorldHint=false, so the safety profile is already covered. The description adds real behavioral context beyond that: automatic weather fetch within ~16 days, the returned event id, and that '' clears priority.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose, then required params, then optional fields and side effects. Dense but each clause carries information; only mildly long.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 11-param mutation tool with no output schema, the description covers the essential behaviors (required fields, return value, weather side effect, downstream handoff). It stops short of documenting every optional URL param, but nothing critical for correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 73%, and the description compensates by specifying the date format (YYYY-MM-DD), that startTime 'picks the forecast hours', and by grouping the optional fields (logistics notes, prep notes, priority, target). This adds meaning beyond the bare schema, especially for the undocumented 'date' and 'description' properties.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Create an event the athlete is preparing for') and enumerates concrete examples (race, key ride, FTP test) plus the target system (Blocks calendar). This clearly distinguishes it from siblings like update_event, delete_event, and list_events.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit trigger ('Use when the athlete describes one in chat') and routes the agent onward to set_event_notes for detailed prep, and clarifies the GPX route is added in the app rather than here. It doesn't contrast against update_event for pre-existing events, but the trigger condition is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

delete_eventA
Destructive
Inspect

Delete an event from the athlete's calendar (it was cancelled or added by mistake). This removes the event AND its prep notes permanently — prefer update_event when only details changed.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYes

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark the tool as destructive, but the description adds valuable detail beyond the annotation by revealing exactly what gets destroyed: the event AND its prep notes, and that removal is permanent. It does not contradict the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences with no filler. The core action is front-loaded, followed by the critical permanence warning and routing guidance, making every sentence earn its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter destructive tool, the description covers what is deleted, that prep notes are removed, that deletion is permanent, and when to use update_event instead. No output schema exists, and the description sufficiently covers what an agent needs to invoke the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema only provides a bare string 'id' with 0% description coverage. The description implies that id refers to the event being deleted from the athlete's calendar, which adds some meaning, but it does not explicitly state the source or format of the id or how it relates to list_events. This is acceptable for a single obvious parameter but not fully specified.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Delete') and resource ('event from the athlete's calendar'), and it distinguishes itself from update_event by noting when deletion is appropriate versus when updates should be preferred. This is not a tautology and clearly separates the tool from its siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly gives the conditions for use ('cancelled or added by mistake') and names the alternative ('prefer update_event when only details changed'). This gives an agent clear routing guidance without needing to infer usage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

edit_activityA
Destructive
Inspect

Correct one completed activity when the recording got it wrong — its MEASURED numbers (jammed GPS, a dropped sensor, a computer left running) or the DAY it was filed on. Four modes, and picking the right one is the whole job: • extend — part of the session DIDN'T RECORD and the athlete says it was like the rest ('первые полчаса не записались, ехал так же'). Pass the new TOTAL movingTime in seconds. Volume scales, intensity is kept, and the personal bests stand. Pass distance too if they know the real total (their usual loop); otherwise it follows the duration. • correct — a recorded number is FALSE ('Страва посчитала 42 км, а я пробежал 10'). Pass the corrected absolute values. Correcting the distance REMOVES this session's distance records — they were computed from the wrong track and the true splits can't be recovered — so tell the athlete that before they apply. • move — the recording's CLOCK was wrong, not its numbers: the device filed the session on the wrong day or hour ('записалась на 22 сентября, а ехал сегодня'). Pass date, and time only if the start time was wrong too. Nothing measured changes and syncs won't move it back; Strava and intervals.icu keep their own date — say so. • revert — undo earlier corrections, a move included, and put the provider's original back ('верни как было'). No values needed. All values are absolute NEW totals (seconds, metres), never deltas. You do NOT compute the consequences: the server recomputes TSS, IF, work and time-in-zone and the confirmation card shows every before→after. Ask for whatever you're missing rather than guessing a number — and get_activity first, so you are correcting the real values. Once corrected, the session is the athlete's: syncs from Strava/intervals stop overwriting its measured fields, and it counts as corrected in the week, the load history and the Records tab.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYes
askYesWhat the athlete asked for, in THEIR words and language — stored with the edit and shown in the app as the reason this session is marked edited.
dateNo`move`: the real day, YYYY-MM-DD.
modeYes
timeNo`move`: the real start, HH:MM (24h); omit to keep the recorded time.
distanceNoNew total distance in METRES.
elevationNoNew total elevation gain in metres.
movingTimeNoNew TOTAL moving time in seconds (not a delta).
elapsedTimeNoNew total elapsed/wall-clock seconds. Usually omit — it follows movingTime.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare destructiveHint=true and readOnlyHint=false, and the description goes well beyond that: correcting distance REMOVES distance records with no recovery, syncs stop overwriting corrected fields, revert restores the provider original, and consequences are recomputed server-side and shown before→after. This is unusually rich behavioral disclosure.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The structure is excellent — mode list front-loaded, each bullet self-contained — but the text is long and repeats some schema facts (units, 'not a delta'), and the quoted examples add bulk. Every sentence still earns its place, so only a small deduction.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 9-parameter mutation tool with no output schema, the description covers prerequisites (get_activity first), per-mode parameter requirements, downstream effects (TSS/IF/records recomputation, sync behavior) and the confirmation card. Nothing an agent needs to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 78%, so the schema already documents most fields, but the description adds real semantics: values are absolute NEW totals, never deltas; extend requires total movingTime with distance optional and duration-derived; move takes date and only conditionally time. It maps each mode to the parameters it needs.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb and resource — correcting one completed activity — and immediately scopes it to measured numbers or the filing day. It cleanly separates itself from siblings like rename_activity, set_activity_notes and tag_activity by stating what 'correct' means here.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It enumerates all four modes and gives the exact situation that selects each, with athlete-voice examples ('первые полчаса не записались') and the explicit instruction to call get_activity first. Alternatives and preconditions are stated, not implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

estimate_cdaA
Read-only
Inspect

Estimate the athlete's EFFECTIVE drag area (CdA, m²) from their own outdoor rides with power: flat, steady 45-90 s windows solved for air drag, median per ride, then over rides. Returns the estimate with its spread and how many rides fed it. Wind is unknown and group riding lowers it (race/group/indoor-tagged rides are excluded), so it is an estimate, not a measurement — say so. To use it for a race, propose setting it on the event (update_event cda) and only set it after the athlete agrees.

ParametersJSON Schema
NameRequiredDescriptionDefault
daysNolook back this many days; default 120

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, but the description adds substantive caveats beyond them: wind is unknown, group riding biases the value low, tagged rides are excluded, and the output is explicitly an estimate rather than a measurement. It also states the return content (estimate, spread, ride count), covering the missing output schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose and method are front-loaded and every clause carries information. It is a dense single paragraph, so a sentence break between method, caveats, and race usage would improve scanability, but nothing is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description fully specifies what comes back (estimate plus spread plus number of rides). It also covers the statistical approach, the caveats, and the required follow-up workflow, so an agent has everything needed to call and act on it.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There is a single optional parameter with 100% schema coverage, including its bounds and default (120 days), so the schema already carries the meaning. The description adds nothing about the lookback window, which is acceptable given full coverage but leaves no extra value.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource (estimate the athlete's effective drag area, CdA in m²) and explains the derivation, distinguishing it clearly from siblings like estimate_thresholds. An agent can tell exactly what this produces without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit downstream guidance: to use the result for a race, propose setting it on the event via update_event cda and only after the athlete agrees. It also names the data conditions that select this tool (athlete's own outdoor rides with power) and exclusions (race/group/indoor-tagged rides).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

estimate_thresholdsA
Read-only
Inspect

Estimate the athlete's cycling FTP, LTHR and max HR from their ACTUAL synced rides over a window (default 90 days), by building the mean-maximal power curve from stored ride streams and fitting a Critical Power model on it. Returns recommended values, a CP range with the efforts behind it, W', a power-law fade estimate, and confidence with reasons — plus hrZones: whether the profile's HEART-RATE zones match the heart rate this athlete actually rides at the tops of their power zones, with bounds to propose when they do not. The check to run when heart rate sits under or over its zone on rides that felt right, or when they ask whether their heart-rate zones are correct. CYCLING ONLY — running threshold pace is NOT supported here, so for a runner use a recent race result or a 30-min field test instead. Asked to recompute an anchor from recent riding, call this and answer from what it returns: that request is what the tool is for, not a reason to send them to a test. The result carries a howToRead block — the estimates are FLOORS and confidence gates whether you may propose an update, so read it before you quote a single number.

ParametersJSON Schema
NameRequiredDescriptionDefault
daysNolookback window, default 90
sportNodefault cycling; running returns guidance, not numbers

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint/safe, so the bar is for added context, and this delivers: it discloses the return shape (recommended, CP range, W', fade estimate, confidence with reasons, hrZones with bounds), and critically warns that estimates are FLOORS and that confidence gates whether an update may be proposed, plus that a howToRead block must be read first.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Long but front-loaded: the purpose and method come first, then usage, then scope, then a return-contract warning. Since there is no output schema, much of the length is load-bearing, though some density (CP range, W', fade, hrZones, howToRead all in one paragraph) could be trimmed.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description fully carries the return-value burden by enumerating the fields and the howToRead/confidence contract, and it closes the scope gap for running. An agent has everything needed to call it and to interpret and report the result.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents both parameters including the 'running returns guidance, not numbers' enum behavior and the default window. The description reinforces the 90-day default and cycling scope but adds no syntax or semantics beyond the schema, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource with method detail: estimates FTP/LTHR/max HR from ACTUAL synced rides via a mean-maximal power curve and Critical Power fit. It distinguishes itself from siblings by naming the scope (CYCLING ONLY) and explicitly ruling out running threshold pace, which separates it from estimate_cda and running-oriented tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit triggering conditions ('when heart rate sits under or over its zone on rides that felt right', 'when they ask whether their heart-rate zones are correct') and an anti-pattern correction ('that request is what the tool is for, not a reason to send them to a test'). It also names the correct alternative for out-of-scope cases (a recent race result or 30-min field test for runners).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_activityA
Read-only
Inspect

Read ONE completed activity in full detail: all stats (NP, IF, TSS, avg/max power & HR, cadence, elevation, kJ, sRPE/load), heart-rate drift at the same power (cycling only), under one of two names: decouplingPct with decouplingBasis for ONE sustained effort (Pw:Hr across its halves), or hr_drift_across_reps for a session with reps (effort 1 vs the last at the same watts — a direction, not a verdict: the <5% line belongs to decouplingPct and does not transfer). When neither is present, decouplingNote says why. work_reps lists each sustained rep in order with the power it was ridden at and its heart rate as hr (mean), hrStart, hrEnd and hrMax — this is the athlete's own heart-rate graph as numbers, so read it instead of asking them for a screenshot of one. Read the SHAPE, not the mean: a rep that climbs and settles and one that climbs and keeps climbing average the same, as do a rep the athlete eased off and one he did not. Rising hrEnd at unchanged watts across reps is drift; flat is an aerobically clean session whatever any percentage says. Also returned: the interval structure, the device LAP structure if the file had laps, and both notes (note = the athlete's, coachNote = your earlier read). WHICH structure to read the session by is stated by structure_read_by: when the athlete has set this session to Laps on the card, structure/blocks ARE the file's laps and the detection travels alongside as structure_auto_detected — read the version they are looking at and don't re-cut the session into intervals they rejected. Otherwise it is our detection, as structure_detected/blocks_detected, with any laps as structure_laps — and when both are present, NEVER report a prescribed element as not done, cut short, or skipped on the strength of its absence from the detection alone: the detection reads the trace and can miss real work, while the laps are the athlete's own thumb on the button, so check both and grade on the laps when they disagree. Each detected block carries its own CADENCE and TERRAIN — 92rpm and -62m/11.4km mean the block lost 62 m over 11.4 km, i.e. a descent. Read them before attributing a power drop to fatigue: falling watts at a high cadence on a losing gradient is a rider out of gears, not a tiring one, and terrain is shown only where the net change exceeds 10 m. Use the id from list_activities. This is how you analyze how a session was actually executed (interval powers, rep consistency) before writing a coach read or adjusting the plan. Returns BOTH zone splits when the file supports them: time_in_zone_min is the stored measure and time_in_zone_basis names which quantity it is (%FTP, %threshold pace, or %maxHR) — read it before comparing this session's zone minutes with another's, because the same key is not the same quantity across activities. Two more preconditions travel with their numbers: tss_basis says whether a run's rTSS was grade-adjusted or read off raw pace (no altitude in the file), and np_caveat appears when the ride is too short for a 30-second rolling average to be stable. hr_time_in_zone_min is the heart-rate split, which the stored column never holds for a run — use it to tell a real physiological excursion from pace running ahead of a stale threshold mark. Its ref field names the maxHR the percentages are taken from; when that says it is a default rather than the athlete's measured maximum, say so instead of quoting the zones as precise. description is what the athlete (or the app that recorded the session) wrote on Strava / intervals.icu — on a gym session pushed from an app like Motra it holds every exercise, set, rep and weight, and since such a file carries neither power nor distance it is not a remark ABOUT the session, it IS the session: read it as the content and grade against it. list_activities flags its presence as hasDescription.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYes

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare a safe read, yet the description discloses rich behavior: how structure_read_by changes which structure to trust, the rule to grade on laps when laps and detection disagree, decoupling naming and its <5% line, cadence/terrain attribution, tss_basis and np_caveat preconditions, and zone-basis caveats. This is far beyond what annotations provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core purpose, and most sentences carry substantive field semantics, but the body is an extremely dense run-on that packs many concepts into single sentences. Useful content is present, yet the sprawl works against quick scanning and some clause repetition could be trimmed.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description assumes the full burden of explaining the return shape and does so exhaustively — stats, decoupling fields, work_reps sub-fields, structure variants, zone splits with basis and ref, and the description field. Nothing needed to interpret the response is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0% and the single id param is undocumented in the schema, but the description states where the id comes from ('Use the id from list_activities'), supplying the missing semantics. It adds no further constraints on the value, so it is strong but not exhaustive.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Read ONE completed activity in full detail') and enumerates the returned content (stats, HR drift, work_reps, interval/lap structure, notes, zone splits). It clearly distinguishes the single-activity read from list_activities and get_activity_series.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear context for use ('how you analyze how a session was actually executed ... before writing a coach read or adjusting the plan') and routes the agent to list_activities for the id. It does not explicitly delimit when to prefer get_activity_series over this tool, so it stops short of full when/when-not guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_activity_seriesA
Read-only
Inspect

The ride's own CHART as a table: time-bucketed average power, heart rate, cadence and altitude across a completed activity, as CSV. This is what the app draws in the activity card, in numbers. Call it when a summary is not enough and you need to SEE the session — where heart rate crossed a level, whether it plateaued inside a rep or kept climbing, what a valley actually looked like, where the terrain turned. Buckets are chosen so any ride comes back near 150 rows. To ZOOM into one rep or one climb, pass fromSec/toSec (seconds on the moving clock — the same clock as a block's start in get_activity and a lactate sample's t) with a small bucketSec; a fine bucket over the whole ride is widened to fit ~300 rows and the header says so. Prefer this over asking the athlete for a screenshot of their own graph: they are reading the same data you can, less precisely.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesactivity id from list_activities
toSecNoend of the window, seconds on the moving clock
fromSecNostart of the window, seconds on the moving clock
bucketSecNoseconds per row; omit to fit the ride to ~150 rows

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, so no contradiction. The description adds rich behavioral detail beyond annotations: default bucket selection yields ~150 rows, fine buckets over the whole ride are widened to ~300 rows and the header notes it, and the 'moving clock' semantics tie to get_activity blocks and lactate sample t. It also states the output is CSV, which is not in the schema. This fully discloses expected behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but every sentence earns its place. It opens with the core purpose, then usage rationale, then parameter semantics, then a practical anti-pattern. It is front-loaded and well-organized, with no filler or redundant statements. Length is justified by the complexity of the zoom behavior.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only data-retrieval tool with 4 parameters (1 required) and no output schema, the description is complete. It explains the return format (CSV), the columns, default row counts, the zoom mechanism, and the clock reference. It also covers when to use it and how it differs from related tools. Nothing an agent needs to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Although schema description coverage is 100%, the description adds substantial meaning beyond the schema. It explains that fromSec/toSec use the same clock as a block's start and a lactate sample's t, and that bucketSec interacts with them to zoom into a rep or climb. It also explains the default row-count behavior and the widening fallback. These semantics are not in the schema and are essential for correct parameter usage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a precise verb-resource pair: returns the activity's own chart as a time-bucketed CSV of average power, heart rate, cadence, and altitude. It distinguishes itself from siblings by explicitly positioning it as the 'SEE the session' tool versus a summary, and even contrasts it with get_activity by referencing the same clock. An agent can tell exactly what this does and how it differs from get_activity or other data tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit when-to-use guidance: 'Call it when a summary is not enough and you need to SEE the session.' It also gives a concrete anti-pattern: 'Prefer this over asking the athlete for a screenshot.' For zooming, it explains exactly when to pass fromSec/toSec with a small bucketSec. This is model-level guidance with clear alternatives and conditions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_athlete_fileA
Read-only
Inspect

Everything you know about this athlete, rendered as one document — the same content the athlete reads on their Profile page under "What I know about you". Kept for readers that want it in one piece; list_facts is the structured form and the one to use when you need ids, states or a single area. The grade block (sport / level / populations) is machine-read and scopes every knowledge-base search.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, so no repetition is needed; the description adds that the document mirrors the athlete's Profile page and that the grade block is machine-read and scopes every knowledge-base search. This goes beyond the annotation's binary safety flags and clarifies content semantics.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, each with a distinct purpose: state the output, position it against `list_facts`, and flag the machine-read grade block. No wasted words, and the main function is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a no-parameter, read-only tool, the description covers its purpose, relationship to the structured alternative, and a key behavioral detail (grade-block scoping). The absence of an explicit output format is a minor gap, but the term 'document' and the reference to the Profile page convey the essential return nature.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so the baseline for this dimension is 4; the description adds no parameter-specific meaning because none exist, but clarifies that the `grade` block (sport/level/populations) is machine-readable, which is output context rather than parameter semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States the tool's function as rendering everything known about an athlete as a single document, and explicitly contrasts it with `list_facts`, distinguishing the two. The mention of the grade block scoping knowledge-base searches adds precision.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Directly instructs when to use this tool ('Kept for readers that want it in one piece') and names `list_facts` as the alternative for structured needs (ids, states, single area). It also warns that the grade block scopes knowledge-base search, helping an agent decide based on query intent.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_athlete_profileA
Read-only
Inspect

Read the athlete's profile: FTP, threshold pace, max/threshold HR, the resolved zone model, AND the athlete block (age, sex, height, weight, W/kg, weekly training hours, available weekdays, experience level) — use those to right-size volume, ramps and fuelling. effective shows the bounds the app actually uses (auto presets resolved) plus absolute watt/pace/HR targets per zone and the athlete block; raw is the stored profile incl. the auto/manual flags you'd pass to update_athlete_profile.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint/destructiveHint=false/openWorldHint=false, so the safety bar is low. The description goes further by disclosing the two views (`effective` = resolved bounds the app actually uses, `raw` = stored profile with auto/manual flags), which is behavior no annotation conveys.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the resource and its fields, then the two view modes. It is dense and slightly packed into two long clauses, but every sentence carries information and nothing is redundant with the annotations.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema and no parameters, the description must carry the full return-value burden — and it does, enumerating the athlete block fields, the zone targets, and the difference between effective and raw output. An agent knows what it will receive and how to use it.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Zero input parameters, so the baseline is 4 and the description does not need to explain inputs. Its `effective`/`raw` discussion refers to output views rather than selectable parameters, so it adds no parameter semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ("Read the athlete's profile") and enumerates the exact contents (FTP, threshold pace, HR bounds, zone model, athlete block). It also distinguishes itself from the sibling mutation tool by naming update_athlete_profile as the consumer of the raw/profile flags.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives a clear downstream use ("right-size volume, ramps and fuelling") and routes the raw flags toward update_athlete_profile. There is no explicit when-not or alternative sibling for the same data, so it stops short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_catalog_workoutA
Read-only
Inspect

Read the full block structure of one workout by id — catalog, collection or the athlete's own library (to inspect before scheduling or adapting).

ParametersJSON Schema
NameRequiredDescriptionDefault
idYes

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and destructiveHint, so safety is covered. The description adds meaningful behavioral context by specifying it returns the 'full block structure' and the source domains, which goes beyond the schema and annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single, front-loaded sentence with no filler. The action, resource, scope, and purpose are all packed efficiently.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter read tool with annotations covering safety, the description is sufficient. It explains what it returns (block structure), the scope, and the intended use. Without an output schema, mentioning the block structure is enough guidance, though it could specify format.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With schema coverage at 0%, the description must compensate. It identifies the parameter as 'by id' but does not elaborate on the id type or format. However, the single parameter is simple and the tool name clarifies it is a workout id, making this adequate for the minimal schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb (read), the resource (workout by id), and explicitly scopes to catalog, collection, or the athlete's own library. It also conveys the purpose ('to inspect before scheduling or adapting'), which distinguishes it from plan-specific retrievals like get_plan_workout.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It provides a concrete use case ('inspect before scheduling or adapting') but does not name alternatives or explicitly state when not to use it. The scope (catalog/collection/library) implies it's not for plan workouts, but that differentiation is not stated directly.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_contextA
Read-only
Inspect

THE WHOLE PICTURE IN ONE CALL — start a conversation with this. Returns the athlete's date and weekday (so you do not also need get_today), then everything the Blocks app itself puts in front of its own assistant on every turn: the plan from yesterday to +7 days with a done / NOT-done verdict ALREADY COMPUTED per planned session, today's readiness with its baselines and confounders, thresholds and the resolved zone tops (watts, pace and bpm, so you never compute one), recent activities with the athlete's own notes, 14 days of planned-vs-done, 12 weeks of weekly load, upcoming events, what their own twelve weeks say about how they respond, the facts they have recorded, what either assistant changed in their plan lately and why (recent_plan_changes), and their last few exchanges with the in-app Blocks assistant — continue from those instead of starting over. Pass question — the athlete's own words, in any language — and the knowledge base is ALSO searched for you before you answer, so the evidence is in your hands without you having to guess the right query; it does not answer the question, it only decides what to retrieve, and without question nothing is searched. WHEN TO CALL: as the first tool call of a conversation, and again only after a long gap or when the athlete says something has changed since (a ride synced, a check-in logged, a threshold set). A second call in the same conversation almost always returns what you are already holding — use get_plan, list_activities, get_readiness_today, list_facts or search_knowledge for the one thing it did not cover. Read-only: it writes nothing.

ParametersJSON Schema
NameRequiredDescriptionDefault
questionNowhat the athlete just asked, in their own words, in any language — used ONLY to search the knowledge base for you. Omit it and no search runs.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the read-only safety profile, yet the description adds substantial behavioral detail: it enumerates exactly what is returned (date/weekday, plan with precomputed done/NOT-done verdicts, readiness, thresholds, activities with notes, 14-day comparison, 12-week load, upcoming events, response profile, facts, recent plan changes, and Blocks assistant exchanges). It also explains the side effect of the `question` parameter—that it triggers a knowledge base search but does not answer the question—and confirms 'Read-only: it writes nothing,' which is consistent with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long and dense, but it is front-loaded with the core purpose and uses clear section markers ('WHEN TO CALL') to aid scanning. For a tool that returns so many different data points, most sentences earn their place, though some list items could be tightened. It is appropriately sized for the complexity, with no major structural flaws.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity, the lack of an output schema, and the rich but safety-focused annotations, the description covers everything an agent needs: when to call, what data is returned, how the optional `question` behaves, and which siblings to use for focused retrieval. Nothing essential is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% for the single `question` parameter, so the schema already documents its format and basic effect. The description adds meaning beyond the schema by clarifying that the search is for evidence retrieval only and that 'it does not answer the question, it only decides what to retrieve,' which helps an agent understand the parameter's purpose. Minor additional value, but not enough to reach 5 given the schema already carries the essential details.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource (get_context) and immediately defines its scope as 'THE WHOLE PICTURE IN ONE CALL'. It distinguishes itself from siblings by naming get_today, get_plan, list_activities, get_readiness_today, list_facts, and search_knowledge as more targeted alternatives, so an agent can tell exactly when this tool is the right pick.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says to call it as the first tool of a conversation, and again only after a long gap or when the athlete reports a change. It also warns that a second call in the same conversation 'almost always returns what you are already holding' and directs the agent to specific alternatives for uncovered data. This is a complete when/when-not/alternatives guide.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_event_courseA
Read-only
Inspect

Read an event's race course the way the event card's Course tab does, computed in code against the athlete's FTP, weight and the event's CdA: finish time (solo physics), NP/TSS, power plan per climb (watts, W/kg, minutes, seconds saved by +10 W), climbs and descents with category, surface split (OSM), race-hour wind from the forecast, and derived key moments (hardest/last climb, technical descent, crosswind, feeds). Use it for 'разбери трассу', pacing a race, which climb decides it. Use ITS numbers — do not redo the physics. Needs the event id from list_events and a GPX on the event.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYes
ifTargetNorace intensity (IF) to plan at; default 0.80

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds real behavioral context: the result is computed in code from the athlete's FTP, weight and the event's CdA, and it requires an existing GPX on the event. It does not, however, mention rate limits or handling of missing GPX/FTP.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action, then the output enumeration and prerequisites. The long output list is on the verbose side but earns its place since there is no output schema to document the return values. No filler sentences.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only tool with no output schema, the description usefully enumerates the return contents and states the prerequisites (event id, GPX on event). Annotations cover the safety profile. It is close to complete, though it does not say what happens when the GPX is absent or the event is a non-race.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 50%: ifTarget is documented in the schema (IF, 0.55–1, default 0.80) but the required id is not. The description partially compensates by stating the id comes from list_events, but adds nothing about ifTarget and gives no format detail for id, so this sits at the baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Read) and resource (an event's race course), and enumerates the concrete outputs it produces (finish time, NP/TSS, power plan per climb, surface split, key moments). No sibling tool does anything comparable, so an agent can distinguish it immediately.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit use cases ('разбери трассу', pacing a race, which climb decides it) and a prerequisite (needs the event id from list_events and a GPX on the event). It also cautions 'use ITS numbers — do not redo the physics', but names no alternative tool or when-not-to-use condition, so it stops short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_fatigue_tests
Read-only
Inspect

The athlete's SFT (fatigue test) log — the fixed load in the warm-up (profile fatigueTest / fatigueTestRun): the tests the app found in their rides and runs plus the ones written by hand (log_sft_answers). Per test: load, last-minute HR vs their baseline, HR drop after, their answers, check-in. Lower HR also means FATIGUE when it felt harder — follow howToRead. With no test set up (or suggest:true) it proposes the protocol's load. sport picks bike or run; weeks looks back (default 12).

ParametersJSON Schema
NameRequiredDescriptionDefault
secNotest duration for the suggestion, default 180
sportNowhich test — the bike one (watts) or the running one (pace, treadmill or flat loop). Omit for every test they have set up.
weeksNolookback, default 12
suggestNotrue = work out the test's watts from their own riding (also done automatically when no test is set up). Use for 'what watts should my test be' or a new season.
get_interval_progression
Read-only
Inspect

The same rep family across sessions — the interval ledger. Families are what an athlete would say: 3′ @ threshold, 30″ @ vo2, 20′ @ threshold (a sustained effort is a set of one), read by DURATION for rides and runs alike so a planned 1 km rep and its execution land in one family. Per session, newest first: reps × the watts they were ridden at (or pace where the file had metres) and the % of threshold at import (of max HR in a family "… by HR": never set against watts or pace), heart rate over the first rep against the last (HR a→b — the drift, from the stream), the sRPE they gave the session, the lactate they logged, and what they wrote. THIS IS WHERE A TARGET COMES FROM: before writing watts, a pace or a % into a rep session, read interval_progression in the snapshot (the families the week ahead needs, the last three each) or this for the longer arc and every family. The same watts at a lower sRPE is the athlete getting fitter (heart rate counts only on reps of 4+ min at or below threshold; bike threshold reps: 8+ min); more watts at sRPE 9 is not a step up. Arithmetic over stored structure, nothing to cite. family is a substring of the label ("3′", "threshold"); zone filters; weeks looks back (default 12, max 52).

ParametersJSON Schema
NameRequiredDescriptionDefault
zoneNo
weeksNolookback, default 12
familyNosubstring of a family label, e.g. "3′" or "1′30″ @ vo2"
sessionsNosessions per family, default 8
get_knowledgeA
Read-only
Inspect

Read an entry by refId (REF-001 / SYNTH-04). Default returns a COMPACT DIGEST (key findings + practical application + limitations) — usually all you need beyond the search card. Pass section for one specific part (e.g. 'Protocol', 'Mechanism', 'Cross-References') when you need depth. Prefer answering from the search card first; only call this when the card is insufficient. Cite refId + level, and the DOI only if the reader asks for the source itself or can click it; weight advice by evidence level.

ParametersJSON Schema
NameRequiredDescriptionDefault
refIdYese.g. REF-001 or SYNTH-04
sectionNoreturn only this ### sub-section, e.g. 'Practical Application'

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds valuable behavioral context beyond that: the default returns a COMPACT DIGEST with key findings, practical application, and limitations, and section returns one sub-section. It also discloses citation behavior, which helps the agent use results correctly.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but every sentence earns its place: it states the action, the default return format, the optional parameter behavior, and when not to call. The key guidance is front-loaded in the first sentence.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With only two simple parameters, read-only annotations, and no output schema, the description covers everything an agent needs: the refId format, the default digest contents, the section option, and the calling policy relative to search. There are no significant missing behavioral details.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents refId and section. The description adds value by explaining the default vs. section tradeoff and providing concrete refId and section examples, making the conditional meaning of the parameters clearer than the schema alone.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Read an entry by refId'. It clearly distinguishes itself from knowledge search by saying 'Prefer answering from the search card first; only call this when the card is insufficient.' The REF-001 / SYNTH-04 examples make the target resource concrete.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit when-to-use guidance is present: use the search card first, call this only when the card is insufficient. It also explains when to pass `section` for depth versus relying on the default digest. This fully routes an agent between the default and parameterized behavior.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_load_summaryA
Read-only
Inspect

sRPE training load (Foster AU = sRPE × minutes) summed per day and per ISO week for a date range, from activities that have sRPE logged. Complements TSS: use it to reason about total load including non-metered sports, monotony and ramp.

ParametersJSON Schema
NameRequiredDescriptionDefault
toYes
fromYes

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark the tool as read-only and non-destructive. The description adds meaningful behavioral context: only activities with sRPE logged are included, and results are aggregated per day and ISO week. It does not describe empty-result behavior or output format, but this is minor for a read-only summary tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two concise sentences, with the formula and aggregation logic front-loaded and the use case in the second sentence. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description sufficiently explains the computation, data source, aggregation granularity, and intended use. It would be more complete with a brief note on what the returned summary contains, but the current description is adequate for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It adds the 'date range' meaning for from/to and the ISO-week aggregation granularity, but it does not clarify inclusivity, boundary handling, or other parameter semantics beyond what the property names and regex already imply.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states that the tool computes sRPE training load (Foster AU = sRPE × minutes) summed per day and per ISO week over a date range, using only activities with sRPE logged. It does not explicitly name a sibling tool to differentiate from, but the 'Complements TSS' note helps position it relative to TSS-based load reasoning.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'Complements TSS: use it to reason about total load including non-metered sports, monotony and ramp' gives explicit when-to-use guidance. It lacks an explicit exclusion or named alternative tool, so it stops short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_metric_history
Read-only
Inspect

The HISTORY of a measured number — FTP, threshold pace, LTHR, max HR, weight, body fat, VO2max, MAP, LT1/LT2, lactate, ferritin, haemoglobin, RHR, HRV. The profile carries the CURRENT value and only that (it is overwritten in place), so this is the only way to answer "is it moving": weight trend, FTP across a season, LT2 between two lab tests, a falling ferritin. Rows carry source — profile | lab | field-test | estimate | self-report — and a lab number and a field estimate are NOT the same measurement twice: say which you are comparing. Deliberately not in the turn snapshot; call it when the question is about a trend, not about today.

ParametersJSON Schema
NameRequiredDescriptionDefault
toNoYYYY-MM-DD, inclusive
fromNoYYYY-MM-DD, inclusive
kindsNolimit to these kinds; omit for all
limitNomax rows, newest first (default 200)
get_plan
Read-only
Inspect

Read what is already scheduled on the athlete's calendar in a date range (so you don't double-book and can balance weekly load). Returns days — only days that hold a session or a note — each with its planned workouts (iid, title, sport, zone, duration + TSS; a gym session carries its content instead, a swim its metres; goal — the one line under its name saying why it exists; any note; fuel — the carbohydrate the athlete sees on the session's card, computed by the app; target — what a ride or run is held to on the device, power/pace/hr/rpe, targetDefault when that is their profile's and not the session's own; judge_by where the signal it is judged in differs, none = nothing readable: no number) and the day's own notes, plus monthlyTss (planned TSS per calendar month). Both dates are optional and inclusive; an omitted one is unbounded, so a call with neither returns the whole calendar, past and future. key:true marks a KEY session — the one the week is built around, declared in advance (see plan_workouts). Pass structure:true to also get each workout's full interval structure (compact, e.g. "6' @55% + 3×(12' @90% / 4' @55%)"); for raw blocks of ONE entry use get_plan_workout.

ParametersJSON Schema
NameRequiredDescriptionDefault
endDateNolast day, inclusive; omit for no upper bound
startDateNofirst day, inclusive; omit for no lower bound
structureNoinclude each workout's compact interval structure
get_plan_workout
Read-only
Inspect

Read ONE scheduled workout in full detail: compact interval structure, raw blocks (zones, %intensities, durations, labels, cadence), totals, notes, target (what it is held to on the device; targetDefault = their profile's), control (the signal to judge it in — see control_signal) and fuel — the carbohydrate the athlete sees on the card: grams for the WHOLE session (the app's formula from the base's per-duration rows, raised when hard work follows, or your own number if you set one) and, when the next hard session is close, what to eat straight after. Use the iid from get_plan / the athlete snapshot. This is how you inspect exactly what the athlete is supposed to do before advising on or editing a session.

ParametersJSON Schema
NameRequiredDescriptionDefault
iidYes
dateYes
get_progressionA
Read-only
Inspect

Whether the athlete's BLOCK is progressing or repeating, per quality family (tempo/threshold/vo2/sprint), read off their own calendar: the shape prescribed each week, the working minutes behind it, and whether any axis moved — duration, density or intensity. Names the case where only the target climbed on an unchanged shape, which looks like progress and is not. Arithmetic over the plan, so nothing here needs a citation. It reads the prescription AND what was executed (time at the family's zone or harder, from the synced activities), and reports the two separately — including the case where the plan grew and the work did not arrive, and the case where the athlete is outrunning a flat plan. Silent below three weeks of history, and easy families are deliberately never reported (repeating the same endurance ride weekly is correct training).

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, so the tool is clearly a safe read. The description adds substantial behavioral detail beyond annotations: it computes arithmetic over the plan (no citations), reads both plan and executed activities, reports them separately, is silent under three weeks, and deliberately omits easy families (repeating endurance is correct). These are non-obvious behaviors essential for correct interpretation and are not present in the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense and multi-sentence, but every sentence carries unique information: core purpose, per-family scope, plan-vs-execution split, edge cases (target-only climb, plan grew but work didn't, athlete outrunning plan), and limitations (silence below 3 weeks, no easy families). It is front-loaded with the primary purpose. It could be slightly tighter, but the complexity justifies the length.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a sophisticated analysis tool with no output schema, the description is exceptionally complete. It covers what it evaluates (block progression per family), what data it reads (prescription and executed time), how it reports (two separate views), edge cases (plan grew, athlete outrunning flat plan), and limitations (silent below 3 weeks, excludes easy families). An agent has everything needed to decide when to call it and to interpret its results.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema is empty (0 parameters, 100% coverage), so there are no formal parameters to document. The description compensates by clarifying the implicit inputs: the athlete's calendar, the weekly prescribed shape, working minutes, synced activities, and the plan. This adds meaning beyond the empty schema by telling the agent what data sources the tool relies on, which is exactly what a parameterless tool needs.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific, non-tautological purpose: determining whether an athlete's block is progressing or repeating across quality families (tempo/threshold/vo2/sprint). It distinguishes this tool from siblings like get_interval_progression and get_strength_progression by scope (block-level, per quality family) and by separating plan vs. executed work. No other sibling covers this exact combination.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies clear usage context: you ask this tool when you need block-level progression analysis per quality family, reading both prescription and executed time. It also notes an explicit condition (silent below three weeks of history). However, it does not explicitly name alternatives or state when not to use it (e.g., for single workouts or strength). This is close to a 5 but lacks explicit exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_readinessA
Read-only
Inspect

Raw readiness entries for a date range (subjective + confounders + manual objective values per day), plus per-metric aggregates anchored at the range end. Use for trend review ('how has the athlete slept the last two weeks?'), before/after a training block, or to check what history exists before backfilling with log_readiness.

ParametersJSON Schema
NameRequiredDescriptionDefault
toYes
fromYes

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, covering the safety profile. The description adds useful behavioral context: it specifies the content (subjective + confounders + manual objective values) and that aggregates are anchored at the range end. It does not mention response format or size limits, but it adds value beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences with no fluff. The first sentence states exactly what the tool returns, and the second gives the primary use cases. It is front-loaded and every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only tool with two date parameters, the description sufficiently explains the output (raw entries plus aggregates) and gives usage context. It could clarify whether both endpoints are inclusive, but given the simple parameter set and no output schema, it is adequately complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema has zero descriptions for the two parameters. The description only refers to 'a date range' without explaining inclusivity, timezone, or defaults. It does not compensate for the lack of schema coverage, leaving parameters semantically under-specified.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool returns raw readiness entries and per-metric aggregates for a date range. It explicitly distinguishes from siblings by naming the use cases 'trend review', 'before/after a training block', and mentions log_readiness for backfilling, which differentiates it from get_readiness_today and get_readiness_baseline.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit usage scenarios: trend review, before/after a training block, and checking history before backfilling. It names log_readiness as the tool to use for backfilling, providing guidance on when not to use this tool. However, it does not explicitly exclude other siblings like get_readiness_today, though the context implies historical vs. current.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_readiness_baselineA
Read-only
Inspect

The athlete's current per-metric baselines (7d/28d mean, 28d SD, rolling-3d, sample size) — their personal 'normal' for every readiness metric. Compare today's values against THESE, never against population absolutes.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate read-only and non-destructive behavior, so the bar for additional disclosure is lower. The description adds valuable context by specifying exactly what the baseline contains (7d/28d mean, 28d SD, rolling-3d, sample size), which helps the agent interpret results. It does not describe output structure or potential edge cases, but for a zero-parameter read-only tool this is sufficient.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences with no filler. The first sentence front-loads the core factual definition of the baseline, and the second sentence adds a practical usage note. Every phrase earns its place, and the formatting is easy to scan.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter, read-only tool with clear annotations, the description provides enough context for an agent to call and interpret the tool correctly. It defines the data contents and the intended comparison target. No output schema exists, but the description enumerates the key return fields, so no critical information is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There are no parameters, and schema coverage is 100%, so nothing needs to be documented about inputs. The baseline score for zero-parameter tools is 4, and the description does not need to compensate for parameter ambiguity. No further parameter semantics are required.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly identifies the resource: the athlete's current per-metric readiness baselines, including specific summary statistics like 7d/28d mean, 28d SD, and sample size. It communicates that this is the athlete's 'personal normal,' which is a clear and meaningful purpose. However, it does not explicitly name or contrast sibling tools like get_readiness_today or get_readiness, so sibling differentiation is only implicit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear usage context: compare today's readiness values against these baselines and never against population absolutes. This gives the agent actionable guidance on how to use the returned data. It does not explicitly name alternative tools or state when not to use this tool, but the population-vs-personal contrast effectively steers usage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_readiness_today
Read-only
Inspect

The athlete's readiness picture for one morning: today's entry (subjective 1-5, 5 = best on every item; PRS 0-10; confounder flags; any manual objective values) PLUS per-metric aggregates from their own history — baseline7d, baseline28d (personal normal), sd28d, zToday, rolling3d, deltaVsBaseline, n28 (datapoints in the window). Blocks computes NO verdict. House line, the one the check-in shows the athlete: a subjective item, PRS, RHR, HRV or total sleep is off their normal at |zToday| ≥ 0.9 with n28 ≥ 7 (fewer: no normal yet); house rule: a 1-5 item is read from its habitual answer h = round(baseline28d): one morning also needs |today − h| > 1. One morning is a reading; a shift that persists (persist3d, set only then: rolling3d past the same line, 2+ of the last 3 mornings all on that side — of h, on a 1-5 item) is what moves a plan. Sleep stages are no baseline signal. Weigh confounders first. date defaults to the athlete's today.

ParametersJSON Schema
NameRequiredDescriptionDefault
dateNoathlete-local YYYY-MM-DD; defaults to the athlete's today
get_recordsA
Read-only
Inspect

The athlete's BESTS, for one sport, in two windows at once: the last 90 days and all time. Cycling returns best average watts over 18 windows (5s…3h); running returns the fastest time over 12 distances (400m…50km) with the pace. Each row names the session it came from, and a 90-day row is marked either as still being the all-time best or with how far short it fell — that gap is the honest read on current form, far better than an absolute number. Use it to anchor threshold estimates in real efforts, to spot a decayed top end (short windows down, long ones intact), to size interval targets off what the athlete has actually held, and to tell a genuine PR from a good day. Bests come from the full-resolution stream at import, so they match what the athlete's head unit reported. pending > 0 means some older sessions haven't been scored yet (they get scored a few per sync) — say so rather than calling a number final. ALSO RETURNS THE THREE READINGS THE RECORDS PAGE SHOWS THE ATHLETE, off these same peaks, so you and the page can never quote different numbers: threshold (cp lo-hi + the anchor efforts), battery (W') and fade (the power law) — the three the athlete sees side by side on that page. The result carries the same howToRead block as estimate_thresholds; follow it.

ParametersJSON Schema
NameRequiredDescriptionDefault
sportYeswhich sport's records

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare this as a safe read, but the description goes well beyond them: data provenance (bests derived from the full-resolution import stream, matching the head unit), the meaning of the `pending` counter and how to phrase results that aren't final, and the fact that it also returns the threshold/battery/fade readings shown on the athlete's Records page.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The core purpose and the two-window mechanics are front-loaded, and each paragraph carries distinct information. It is longer than needed in places (e.g., the aside about never quoting different numbers than the page), which slightly dilutes scannability but does not bury the key points.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, so the description carries the full burden of describing return values, and it does: row contents, session provenance, the 90-day gap marker, the threshold/battery/fade readings, and the pending state. Nothing essential for calling or interpreting the result is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There is only one parameter, and the 100%-covered enum schema already documents it. The description adds real meaning by explaining what each enum branch yields (cycling: best average watts over 18 windows; running: fastest time over 12 distances with pace), though it does not add any parameter syntax beyond that.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource and the exact scope: the athlete's bests for one sport across the last-90-day and all-time windows, with per-sport peak definitions (18 power windows vs 12 run distances). It is clearly distinguishable from siblings like estimate_thresholds or get_metric_history without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives concrete when-to-use scenarios (anchor threshold estimates, spot a decayed top end, size interval targets, distinguish a true PR from a good day) and explains how to read the 90-day-vs-all-time gap. It also flags the `pending` > 0 caveat and routes the agent to the shared `howToRead` block used by estimate_thresholds.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_response_profileA
Read-only
Inspect

How THIS athlete actually responds, computed from their own last 12 weeks: whether quality sessions land where they are aimed, whether their sRPE separates hard days from easy ones, whether low morning readiness has actually predicted a poor session, and which weekday the plan leaks on. Arithmetic over their own history — no literature, so nothing here needs a citation and nothing can be out of scope. Silent where the sample is too small; an empty answer means there is genuinely nothing to say yet.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already establish read-only, non-destructive, closed-world behavior, and the description adds substantial behavioral detail beyond that: the 12-week computation window, the specific analyses performed, the decision to stay silent on small samples, and the meaning of an empty answer. This gives the agent a clear model of what the tool will and will not do.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three sentences, front-loads the core purpose, and each clause adds meaningful information: computation source, evaluated patterns, scope boundary, and empty-result semantics. No filler or repetition is present.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a parameterless read-only tool, this is complete. It gives the computation window, the exact patterns being evaluated, the source data boundary ('no literature'), and a clear interpretation of empty output. Nothing needed to invoke or trust the tool is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters and schema description coverage is 100%, so there is no parameter burden for the description to carry. The baseline of 4 applies because nothing is underdocumented.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific resource—this athlete's response profile—and explains exactly what it computes: whether quality sessions land as aimed, whether sRPE separates hard/easy days, whether low readiness predicts poor sessions, and which weekday leaks occur. This clearly distinguishes it from sibling read tools like get_readiness or get_load_summary.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It clearly frames when this tool is appropriate: when you need evidence specific to this athlete from their own last 12 weeks, as opposed to literature or generalized knowledge. It also tells the agent that an empty answer means there is genuinely no usable sample yet. It does not explicitly name alternatives or exclusions, so it stops short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_strength_logA
Read-only
Inspect

What the athlete actually DID in a planned gym session — set by set — and what they changed in the plan before starting it. A strength session has no TSS and no duration, so this is the only record of how it went: sets done against sets prescribed, load and reps per set, the RPE they were actually taken at, and the athlete's reason when something diverged. TWO LAYERS, and they answer different questions: amended before the session is a DECISION taken in advance (by the athlete, or by you — the line says which), while a set line is what the body did on the day. An athlete who drops the load every Monday morning and one who fails the last set every Monday need opposite advice. Read this before prescribing the next gym session, and before judging whether the last one was completed — the calendar alone cannot tell you.

ParametersJSON Schema
NameRequiredDescriptionDefault
toNo
fromNo

TDQS

A4.1/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the readOnly and non-destructive annotations, the description explains the two layers of data: amendments made before the session versus actual set-by-set execution. It also documents important behavioral context: no TSS, no duration, actual RPE, load/reps, and the athlete's reason for divergence. This gives the agent a strong mental model of what the tool returns.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but dense, with the core purpose front-loaded and no fluff. Some sentences around 'opposite advice' and 'the calendar alone cannot tell you' are explanatory rather than strictly necessary, but they reinforce usage rather than waste space.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The semantic content is thoroughly covered, especially the distinction between amended decisions and executed sets. However, the description does not address date-range behavior, return format, or empty results. Since there is no output schema, a bit more detail about what the agent receives would make this fully complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema has 0% description coverage and the tool description never mentions the to/from date-range parameters. The parameter names and date pattern provide some self-evident meaning, but the description does not compensate for the missing schema semantics, so an agent gets no guidance about how the date range filters the log.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a concrete resource: what the athlete actually did in a planned gym session, set by set, plus what they changed in the plan before starting. It clearly explains why this tool exists and distinguishes it from calendar or plan data by noting that strength sessions have no TSS or duration.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly tells the agent when to use this tool: before prescribing the next gym session and before judging whether the last one was completed. It also warns that the calendar alone cannot answer those questions. It does not name sibling alternatives explicitly, but it provides clear context and the different questions each data layer answers.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_strength_progression
Read-only
Inspect

The lift history, one exercise across sessions: all logged exercises or the one you name (substring of their own names — "присед" finds both squats), newest first: heaviest set done (kg×reps; s or m for timed/distance; bw = bodyweight), sets done/planned, RPE vs target, the plan where it differed, what they wrote. Each line carries the days since the previous session, the header how long ago the last one was and how often in 4/12 wk; 14+ days is marked BREAK — the next load is then a return, not a step up. A WEIGHT COMES FROM HERE: read it before writing a kg (the snapshot's strength_progression has the last three for exercises in view; this has a year). Names that may be one movement close the list: ask, then link_exercises. Arithmetic over the log, nothing to cite.

ParametersJSON Schema
NameRequiredDescriptionDefault
exerciseNofilter to exercises whose name contains this (case-insensitive, the athlete's own names)
sessionsNosessions per exercise, default 8
get_today
Read-only
Inspect

Today's date on the athlete's Blocks account, in their own time zone: ISO date, weekday, and ISO week. Call this to anchor any relative reasoning — 'today', 'tomorrow', 'this week', 'the weekend', 'in 3 days' — and to pass the correct date to other tools. zone names the time zone the date is in; when it says UTC their zone is unknown — if it may already be a different calendar day for them, say so and confirm rather than assume.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

list_activitiesA
Read-only
Inspect

List the athlete's recent COMPLETED activities (actual rides/runs/etc. synced from every connected provider — Strava, intervals.icu and the rest — deduplicated at sync) with id, date, sport, name, duration, distance, TSS, IF, NP, avg/max power & HR, kJ, elevation, meaningful-effort count (sustained work efforts, not raw segments), and any existing notes. Use this to find an activity id before writing a summary with set_activity_notes, and to base that summary on the real numbers. Defaults to the 30 most RECENT activities — a row count, not a date window, so for a three-a-week athlete that is ten weeks and for a daily one it is a month. Whenever the answer depends on how much time a stretch covers — a ramp, a stall, consistency, a block review — pass explicit from/to and read the dates you get back. On a row, coachNote is the VERDICT line of your own earlier review of that session (an excerpt — coachNoteChars is the full length; get_activity returns it whole) and note is the athlete's words, cut at 300 characters.

ParametersJSON Schema
NameRequiredDescriptionDefault
toNo
fromNo
limitNo

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only cover the safety profile (readOnly, non-destructive, closed-world), and the description adds substantial behavior beyond that: results are synced-provider data deduplicated at sync, the default limit is a row count rather than a date window, and row fields are truncated (coachNote is an excerpt with coachNoteChars giving full length, note is cut at 300 chars). This is exactly the extra context annotations cannot carry.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose and return fields, then usage rules, then row-level caveats — a logical order with no filler sentences. It is dense and long, with several nested parentheticals, so it is efficient but not maximally tight.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema and 0% schema coverage, the description carries the full burden and does so: it documents returned fields, default window behavior, and the truncation semantics of coachNote/note. Nothing an agent needs to call this correctly or interpret the response is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate, and it does for all three: limit semantics (30 most recent, a row count whose real span varies by athlete frequency) and from/to usage (pass explicitly for any time-coverage question). It adds meaning the bare schema lacks, though it never restates the from/to date format, relying on the schema pattern for that.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (List) and resource (athlete's recent COMPLETED activities) and enumerates the returned fields (id, date, sport, duration, TSS, IF, NP, power/HR, etc.). It also distinguishes itself from get_activity by noting that get_activity returns coachNote whole, so an agent can separate the two without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use ('find an activity id before writing a summary with set_activity_notes'), names the sibling that returns the full coachNote, and adds a concrete rule: pass explicit from/to whenever the answer depends on how much time a stretch covers. Conditions and alternatives are spelled out rather than inferred.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_commitmentsA
Read-only
Inspect

Everything you have already asked THIS athlete to do that is still open — your own instructions from earlier turns, with ids. The open ones already ride in the snapshot; call this to see closed ones too, or to check what you told them about a specific date before you say it again.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
statusNodefault open

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=true and destructiveHint=false, so safety is covered. The description adds that open commitments already ride in the snapshot, implying the tool can return closed ones. It doesn't contradict annotations and gives useful scoping context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences: the first states the core purpose, the second adds context about the snapshot, and the third gives usage guidance. No redundant words, and key information is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read-only listing tool with two optional parameters, the description covers scope and usage well. It mentions returning ids and filtering by status, but it doesn't describe pagination or the exact return structure (no output schema exists). Still, the essential information for calling the tool correctly is present.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 50% (status has a description, limit does not). The tool description mentions status usage indirectly ('to see closed ones') but completely ignores the 'limit' parameter. Given the low coverage, the description should compensate, but it fails to explain limit's purpose or behavior.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool lists commitments (instructions given to this athlete) with ids, and specifies the scope as 'your own instructions from earlier turns.' It distinguishes from siblings like close_commitment by focusing on listing rather than modifying.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides context for when to call: 'to see closed ones too, or to check what you told them about a specific date before you say it again.' This implies when to use it over relying on the snapshot, though it doesn't explicitly name alternatives or exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_eventsA
Read-only
Inspect

List the athlete's events (races, key rides, FTP tests, camps they're preparing for) with id, date, name, location, map + event-page URLs, route distance/elevation, the athlete's logistics notes, and the current coach notes. Use this to find an event id before writing fueling/pacing guidance with set_event_notes. Defaults to upcoming events.

ParametersJSON Schema
NameRequiredDescriptionDefault
includePastNoalso return events whose date has passed

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds useful context: the types of events included, the default to upcoming events, and the exact fields returned. It does not contradict annotations and provides value beyond them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, each purposeful: the first lists content, the second gives usage, the third states the default. No fluff or repetition. Information is front-loaded and easy to parse.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With only one optional parameter and no output schema, the description fully covers what an agent needs: the fields returned, the use case, and the default behavior. Nothing critical is missing for a read-only list tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the schema describes includePast as 'also return events whose date has passed.' The description adds the default value ('Defaults to upcoming events'), which clarifies the parameter's behavior without redundancy. This exceeds the baseline for full schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it lists the athlete's events with specific types (races, key rides, FTP tests, camps) and enumerates the fields returned (id, date, name, location, URLs, route stats, notes). This is a specific verb+resource and distinguishes it from sibling tools like list_activities or create_event.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly says 'Use this to find an event id before writing fueling/pacing guidance with set_event_notes,' giving a clear when-to-use context. It also mentions the default behavior of upcoming events. It does not explicitly name alternatives or exclusions, but the purpose is distinct enough that this is a minor gap.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_factsA
Read-only
Inspect

Everything you know about this athlete, as separate facts with how long each is true. The ACTIVE ones already ride in every turn's snapshot — call this when you need the rest: what has lapsed, what is asleep out of season, retired history, or a specific area in full. Each fact carries state: live (applies now) · lapsed (an until whose date has passed — it stops applying, and its OPPOSITE does not start applying: ask before taking the freed space) · stale (a recheck come due, or a pattern nobody has seen in half a year — still the best we have, no longer trustworthy) · asleep (a seasonal rule outside its window: the plan simply stops obeying it, this is not a question) · retired (someone decided it was done).

ParametersJSON Schema
NameRequiredDescriptionDefault
tagNofree tag, e.g. 'knee' or 'winter'
areaNoone area only
stateNodefault: everything except retired

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only indicate readOnly and non-destructive hints. The description goes far beyond by defining the five states (live, lapsed, stale, asleep, retired) and their implications, including cautions about lapsed facts ('ask before taking the freed space') and the status of stale facts. This is rich behavioral context not visible in schema or annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but front-loaded with the core purpose and when-to-use guidance in the first two sentences. The state breakdown follows logically and every clause adds value—no filler. Despite length, it earns its space by clarifying a complex state model.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers usage, state semantics, and differentiation from the snapshot. It does not explicitly describe the response format (e.g., array of fact objects), but given that the tool is a listing endpoint and the description references facts carrying a 'state', it is reasonably complete for a read-only operation. A minor gap is the absence of explicit return shape, but not critical.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, giving baseline 3. However, the description adds nuanced meaning to the 'state' parameter by explaining each state's semantics and the default behavior (everything except retired). It does not add extra meaning for 'tag' or 'area' beyond schema descriptions, but the state definitions are a meaningful augmentation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clearly states the tool lists all facts about the athlete, specifically distinguishing active facts (already in snapshots) from inactive ones (lapsed, asleep, retired). This differentiates it from any sibling that returns the current snapshot, and the verb 'call this' implies a listing action.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly directs when to use: 'call this when you need the rest' and enumerates the specific cases (lapsed, asleep out of season, retired history, or a specific area in full). Also implicitly says not to use it for active facts since they are already in the snapshot, providing clear contextual guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_sectionsA
Read-only
Inspect

List all knowledge-base sections with entry counts (the topic map).

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is established. The description adds the useful behavioral detail that the result includes entry counts and frames the tool as a topic map, but it does not describe return structure or pagination. This is acceptable but not rich.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The entire description is one front-loaded sentence with no filler. It states the action, the resource, and the key output characteristic efficiently.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple parameterless list tool with read-only annotations, the description conveys enough to be called correctly: no inputs, sections are returned, and entry counts are included. The lack of an output schema is partially mitigated by the explicit mention of entry counts, though exact response formatting is unspecified.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters and the schema description coverage is 100%, so there is no parameter information the description needs to supply. The baseline for a parameterless tool applies here.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('List') and resource ('knowledge-base sections') and adds the distinguishing output detail 'with entry counts (the topic map)'. It is clearly scoped and can be differentiated from siblings like list_facts or search_knowledge.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The purpose is specific enough that an agent can infer when to use it: when needing an overview of knowledge-base sections and their sizes. However, there is no explicit guidance on when not to use it or which siblings to prefer, leaving some inference required.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

log_lactateAInspect

Record the athlete's blood-lactate samples on a completed activity (their own meter readings — e.g. "lactate was 3.4 after the second rep"). Each sample: t = seconds into the session on the MOVING clock (estimate from the interval structure if the athlete says "after rep 2"), mmol = the reading. Appends to existing samples by default; replace:true overwrites the whole set. The samples appear as markers on the activity chart, and get_activity returns them for your session analysis. Store raw values only — put your interpretation in set_activity_notes, not here.

ParametersJSON Schema
NameRequiredDescriptionDefault
replaceNo
samplesYes
activity_idYes

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations (readOnlyHint=false), the description discloses that samples are appended by default, replace:true overwrites the entire set, and samples become visible as markers retrievable via get_activity. This gives the agent a concrete model of side effects and resulting state.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose is front-loaded and every sentence carries distinct functional information: scope, parameter semantics, append/overwrite behavior, and downstream effects. It is dense but not bloated; no filler or restatement of schema constraints.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 3-parameter logging tool with no output schema, it covers input semantics, mode of operation, downstream retrieval, and scope limitations. An agent can confidently construct a correct call without needing additional tools; activity_id is self-explanatory.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema has no property descriptions (0% coverage), so the description carries full weight. It defines t as seconds on the MOVING clock with estimation guidance, mmol as the reading, and explains the replace flag's default behavior. This is meaningful semantic coverage for all three parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb ('Record') and a precise resource ('athlete's blood-lactate samples on a completed activity'), reinforced with a concrete example. It clearly distinguishes log_lactate from sibling log_* tools by naming blood-lactate as the metric and 'completed activity' as the target.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit context: use on completed activities, append by default vs replace:true, and a clear when-not instruction ('put your interpretation in set_activity_notes, not here'). It does not explicitly contrast with log_metric or log_session_rpe, but the boundary is clear enough for correct selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

log_metricInspect

Record a MEASUREMENT with its date — a lab test (LT1, LT2, MAP, VO2max, a lactate draw), a blood panel (ferritin, haemoglobin), a weigh-in, a field-test result. One call takes several rows, so a whole lab report lands as one card. This is history, not the profile: it does NOT change what the app plans against — if the test says the threshold moved, propose update_athlete_profile as well and say so. An FTP row DOES change how PAST rides are scored: every power ride from its date to the next FTP row is re-read against it (IF, TSS, zones), and the change shows on the calendar — so when they tell you what their FTP was back then, log it on THAT date (source self-report). Date the MEASUREMENT, never today-because-that-is-when-they-told-you. note is where the test came from ("Trisystems СПб, step test to exhaustion"), never an interpretation of the athlete.

ParametersJSON Schema
NameRequiredDescriptionDefault
itemsYes
log_readinessAInspect

Record the athlete's daily readiness — one entry per date, idempotent MERGE-upsert: only the fields you send are updated, existing fields survive. Accepts a BATCH (up to 90 items) so you can backfill history from an export (e.g. months of HRV/RHR/sleep) in a few calls. Subjective core (McLean 1-5, 5=best: fatigue, sleep_quality, soreness, stress, mood) + prs (0-10) is the primary signal; objective fields (rhr bpm, hrv_rmssd ms, sleep_total_min, deep_sleep_min) are optional manual values from the athlete's wearable. Confounder flags (late_meal, alcohol, hookah, smoking, life_stress, illness, injury, poor_sleep_external, travel, underfuelled, long_day, heat, meds) record WHY a day might look off. Record them as ticked; never fold a confounder into the numbers themselves. Values are range-checked (e.g. rhr 25-110) so a typo can't poison the baselines.

ParametersJSON Schema
NameRequiredDescriptionDefault
itemsYes

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations, it discloses idempotent MERGE semantics ('only the fields you send are updated, existing fields survive'), value range-checking to prevent typos from poisoning baselines, and the rule that confounders should be ticked rather than folded into numbers. These are non-obvious behaviors that materially affect how an agent should construct calls.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but dense, with every sentence earning its place. The most important behavior — daily-readiness MERGE-upsert idempotency — is front-loaded, and supporting detail on batch backfill and field interpretation is organized logically without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex write tool with many optional fields and no output schema, the description covers idempotency, field groups, ranges, batch limits, and the confounder-handling rule. An agent has enough information to construct valid calls and make correct decisions about which values belong where.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description fully compensates by explaining the semantic groups inside items: the subjective McLean 1-5 core, optional wearable-derived objective fields, and confounder flags. It also highlights batch size (up to 90) and gives example ranges, adding substantial meaning beyond the raw property names.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific action and resource: 'Record the athlete's daily readiness'. It adds decisive behavioral detail — 'one entry per date, idempotent MERGE-upsert' — and clearly distinguishes the tool from read-side siblings like get_readiness and get_readiness_today.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states the primary use case (daily readiness logging) and explicitly mentions a batch backfill scenario from exported HRV/RHR/sleep data. It does not explicitly name excluded alternatives or contrast with log_metric/log_session_rpe, but the readiness-specific framing makes selection unambiguous in most contexts.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

log_rpe_marksAInspect

Write the athlete's EFFORT MARKS on a completed activity: RPE 1-10 at a moment of the session ("the second rep was a 7, not a 9", "I tapped 9 by mistake on the test, it was a 6"). Each mark: t = seconds into the session on the MOVING clock (the clock of get_activity's blocks and effort_marks), v = RPE, step = what it was ("Threshold 2/4", optional). get_activity returns the current marks as effort_marks. Pass the WHOLE corrected set with replace:true to change or remove a mark; without replace the marks are added. The athlete can also add, drag and edit them themselves in the activity card's RPE tab. Not the session RPE (that is log_session_rpe) and not the fatigue test's answers (log_sft_answers). Saves on return.

ParametersJSON Schema
NameRequiredDescriptionDefault
marksYes
replaceNo
activity_idYes

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare the write/no-open-world profile; the description goes well beyond them by disclosing that replace:true must carry the WHOLE corrected set to change or remove a mark, that otherwise marks are appended, that the athlete can edit the same marks in the RPE tab, and that changes persist ('Saves on return'). Minor tension with destructiveHint=false exists since replace can remove a mark, but the removal is small and reversible, not truly destructive.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action, and every clause carries information (clock semantics, replace rule, sibling disambiguation, persistence). It is dense and runs long with several parenthetical quotes, which costs a little readability, but nothing is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with no output schema and no annotations beyond the safety profile, this covers the necessary ground: input clock conventions, the add-vs-replace choice, sibling routing, and return behavior ('Saves on return'). Nothing an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries the full burden and does: t is defined as seconds on the MOVING clock (aligned to get_activity's blocks/effort_marks), v is the RPE, step is the context label, and replace's whole-set semantics are spelled out. This is meaning the schema's bare types cannot convey.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Specific verb (Write) plus precise resource (EFFORT MARKS for an activity), and it explicitly distinguishes itself from the two nearest siblings, log_session_rpe and log_sft_answers. An agent can tell exactly what this does without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

States when to use it, names the alternatives it is NOT ('Not the session RPE (that is log_session_rpe) and not the fatigue test's answers (log_sft_answers)'), and gives the replace:true vs default add semantics as an explicit decision rule.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

log_session_rpeAInspect

Attach the athlete's session RPE (Borg CR-10, 0-10, ~30 min post-session) to a completed activity from list_activities. Blocks computes load_au = sRPE × duration_min (Foster). Works for ANY sport including gym/tennis where there's no power meter — it's the universal load currency alongside TSS.

ParametersJSON Schema
NameRequiredDescriptionDefault
srpeYes
activity_idYes

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnlyHint=false and destructiveHint=false. The description adds that Blocks computes load_au = sRPE × duration_min and that the activity must be completed, which is meaningful behavioral context beyond the annotations. It does not discuss idempotency or overwrite behavior, but given annotation coverage this is adequate.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences with no filler. The first sentence front-loads the action and target; the second adds the computation formula and universality context. Slightly dense but every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple two-parameter tool with no output schema, the description covers the essential calling context: what to provide, where the activity comes from, and the system's resulting computation. It does not describe return values or error cases, but that is not expected given the low complexity and annotation coverage.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description fully compensates: it explains srpe is Borg CR-10 (0-10) and should be recorded ~30 min post-session, and that activity_id refers to a completed activity from list_activities. This adds real meaning to otherwise bare schema fields.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Attach'), a resource ('session RPE'), and a target ('completed activity from list_activities'), and it gives the Borg CR-10 scale and the computed load_au formula. This clearly separates it from generic log_metric or log_lactate siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly says the activity must come from list_activities and be completed, and notes the ~30 min post-session timing. It also frames when to use it (any sport without a power meter, as universal load currency alongside TSS), though it does not directly name alternative tools or state exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

log_sft_answersInspect

Write to the athlete's fatigue-test (SFT) log, read by get_fatigue_tests: their answers, merged with what is there. When the app did not find the test (treadmill, another device), pass hr as they read it — it is recorded by hand and wins over the file's. Name the session by activity_id, or date + sport. Saves on return, no card.

ParametersJSON Schema
NameRequiredDescriptionDefault
hrNolast-minute HR
hrrNoHR drop in the minute after
rpeNohow hard the test felt
dateNo
noteNo
sportNo
activity_idNo
minutesLeftNominutes more they could have held it
plan_workoutsInspect

Add one or more workouts to the athlete's training calendar (the days appear in Blocks). WORKFLOW per day: prefer an existing workout and pass its id as workoutId — from the catalog map already in your context if you have one, otherwise via search_catalog. Only when nothing suitable exists, pass a custom workout (validated server-side; also saved to the athlete's library). Optionally attach a short note per item, and set key:true on the one or two sessions the week is built around (you may set at most 2 per week yourself — the athlete has no such limit — declare them FIRST and fill the rest of the week around them, which is also the order a week is planned in). Batch the whole block (e.g. 3 weeks) in one call — at most about four weeks per call: the 40-item cap is a ceiling, not a target, and a call too long to finish is cut by the length limit and saves nothing. For a longer horizon place the first block, say the rest goes in block by block, and repeat weeks with copy_week. Returns per-item result with the new iid, duration and TSS.

ParametersJSON Schema
NameRequiredDescriptionDefault
whyNoONE line, in the athlete's language: WHY this change — the reason from the conversation ("travel Thu-Fri, long ride moved to Sat", "deload after 3 build weeks"). The athlete's other assistant surface reads it later; without it, it sees only that the plan changed. No health details beyond what the plan needs.
itemsYesone entry per scheduled workout
remove_from_planA
Destructive
Inspect

Remove planned work from the calendar: one scheduled workout on date (by iid from get_plan), or every planned workout on that day when iid is omitted. Touches planned entries only — completed activities and the day's notes stay. There is no undo: putting a session back is plan_workouts or copy_workouts. Returns how many entries were removed, or says nothing was planned that day.

ParametersJSON Schema
NameRequiredDescriptionDefault
iidNoone workout's iid; omit to clear every planned workout that day
whyNoONE line, in the athlete's language: WHY this change — the reason from the conversation ("travel Thu-Fri, long ride moved to Sat", "deload after 3 build weeks"). The athlete's other assistant surface reads it later; without it, it sees only that the plan changed. No health details beyond what the plan needs.
dateYesthe day to remove from

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the destructiveHint=true annotation, it discloses exactly what survives ('completed activities and the day's notes stay'), warns there is no undo, and describes the return value ('how many entries were removed, or nothing was planned'). This is meaningful behavioral context the annotations do not carry.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, all front-loaded with the highest-value information first (what it does, what it leaves alone, the irreversibility). No filler or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Even without an output schema, the description covers return behavior, destruction scope, irreversibility, and the re-add path. Everything an agent needs to invoke this mutation safely is present.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds real value by telling the agent where `iid` comes from (get_plan) and restating the omit-to-clear semantics. It does not expand on the `why` parameter, which is already documented in the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('remove') and resource ('planned work from the calendar'), then precisely distinguishes the two operating modes: one workout by `iid` versus every workout when `iid` is omitted. It also carves out scope against siblings by declaring 'touches planned entries only,' separating it from activity/note tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear conditions for the two modes (single vs whole-day) and names the re-add path (get_plan for iid; plan_workouts/copy_workouts to restore). It does not explicitly compare against near-neighbors like update_plan_workout or delete_event, so it stops short of full when-not guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

rename_activityA
Destructive
Inspect

Give one completed activity the athlete's own title, e.g. 'FTP test' or 'Гонка Царь Грейдер'. Pass an empty string to clear it and fall back to the name the provider gave. This does NOT touch the source: the provider's own name is kept separately and rewritten on every sync, so a rename here survives Sync now. Use it when the athlete asks for a rename, or tells you what a generically named session ('Ride') actually was; a session you merely read as something else keeps its name.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYes
titleYes

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Adds genuine behavior beyond the annotations: the provider's native name is kept separately and rewritten on every sync, so the rename survives 'Sync now', and an empty string reverts to it. It also scopes the mutation ('does NOT touch the source'), which usefully clarifies why destructiveHint=true is limited to the local title. It stops short of stating what happens if the activity id is unknown or if an existing custom title is overwritten.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the action, then the empty-string behavior, then the sync semantics, then the usage trigger. Dense and largely waste-free, though the trailing 'a session you merely read as something else keeps its name' is a second pass at the same exclusion already implied earlier.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter mutation with annotations covering safety and no output schema, the description supplies the non-obvious context an agent needs (sync survival, provider-name preservation, clearing semantics, usage trigger). The only real gap is that the 'id' parameter's expected value/reference is left entirely to inference.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must carry both parameters. It handles 'title' well (empty string clears, examples given, and the schema supplies maxLength), but 'id' is never explained beyond being required, leaving half the surface undocumented.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource (give one completed activity the athlete's own title) with a concrete example, and implicitly distinguishes itself from sibling mutators like set_activity_notes, edit_activity and tag_activity by confining the action to the title field. An agent can tell what it does without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly names the trigger conditions ('when the athlete asks for a rename, or tells you what a generically named session actually was') and an exclusion ('a session you merely read as something else keeps its name'). This is exactly the when/when-not routing an agent needs versus get_activity or edit_activity.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

retire_factA
Destructive
Inspect

This is no longer true, or never was. Always a card: retiring is how the athlete's own words leave their page, and they get to see it go. The fact is kept and marked retired rather than deleted — a retired fact is out of your context and still visible to them, because "we stopped believing it" is not "it never happened". A LAPSED fact is NOT automatically retired: its date passing means you no longer know, so ask first.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYes
reasonYesone line: why it is no longer true

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the destructiveHint annotation, the description discloses the key behavioral nuance: the fact is kept and marked retired rather than deleted, it leaves the agent's context, and it remains visible to the athlete. The lapsed-fact distinction adds important behavioral context that annotations alone do not provide, and nothing contradicts the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded with the core condition, but the phrase 'Always a card' is unexplained domain jargon that may confuse an agent. Overall, every sentence contributes meaning, though the conceptual framing is denser than strictly necessary.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter state-change tool with no output schema, the description explains the lasting effect, athlete visibility, and the lapsed exception. It does not describe the expected response or error handling, but those are partially covered by annotations and the simplicity of the call.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 50%, so reason has a description but id does not. The description reinforces what a valid reason means by defining 'no longer true, or never was' and contrasting it with lapsed, but it adds no direct guidance on how to format or obtain id. This is adequate for a simple two-parameter tool, but not rich.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly identifies the operation as retiring a fact: removing an athlete's statement from the active context while marking it as no longer believed. It distinguishes this from deletion and from lapsed facts, so an agent can differentiate retire_fact from update_fact and confirm_fact without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit when-to-use conditions: retire a fact when it is no longer true or never was. It also gives an explicit when-not-to-use condition: a LAPSED fact is not automatically retired, and the agent should ask first. This is clear usage guidance even without naming sibling tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_catalogA
Read-only
Inspect

Search workouts: the Blocks catalog, coach collections AND the athlete's own saved workouts (source: mine). Reuse an existing workout before inventing one — this is how you find it by keyword, by a rep interior, or among the athlete's own saved workouts, which are deliberately not in the catalog map. Filter by sport, target zone, and a duration window; returns id, title, zone, duration, TSS, IF, source. Pass a returned id to plan_workouts as workoutId.

ParametersJSON Schema
NameRequiredDescriptionDefault
zoneNodesired headline zone
limitNomax results (default 12)
queryNokeywords, e.g. 'sweet spot over-unders'
sportNo
durationMaxMinNomaximum duration, minutes
durationMinMinNominimum duration, minutes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, so the safety profile is covered. The description adds contextual behavior beyond that: it explains that the athlete's saved workouts are deliberately not in the catalog map and enumerates the returned fields (id, title, zone, duration, TSS, IF, source).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, front-loaded with scope and followed by usage guidance and output details. The middle sentence is a bit long and repeats the point about saved workouts, but every sentence contributes useful information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only search tool, the description covers the search scope, when to use it, filtering options, return fields, and downstream integration via plan_workouts. There is no output schema, but the return fields are explicitly listed. No critical calling detail is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 83%, so the baseline is 3. The description maps 'sport, target zone, and a duration window' to the relevant schema parameters, but adds little beyond what the schema already states for those fields. Query and limit are not described in prose, though the schema covers them well.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb ('Search') and names three distinct resources: the Blocks catalog, coach collections, and the athlete's saved workouts. It distinguishes itself from siblings by noting the 'mine' source and by saying returned ids can be passed to plan_workouts.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly tells the agent to reuse an existing workout before inventing one, and positions this tool as the mechanism for that lookup. It gives concrete search angles (keyword, rep interior, saved workouts) but does not name alternative search tools or state exclusion conditions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_knowledgeA
Read-only
Inspect

Search the curated endurance-science knowledge base (studies + syntheses on physiology, training, nutrition, recovery, heat, women's health, strength, masters, injury, etc.). Returns ranked COMPACT CARDS — each is refId · title · evidence level · athlete Tier · sport · DOI · ▶ actionable bottom-line, plus finding (what the study measured) and, on a framework, decision (its rule) — usually enough to answer AND cite directly. Call get_knowledge(refId) only when you need the full protocol/mechanism/limitations of a specific entry (optionally get_knowledge(refId, section) for just one part). Cite an entry by refId + level; give the DOI only when the reader asks for the source itself, or when you are writing somewhere they can click it.

ParametersJSON Schema
NameRequiredDescriptionDefault
tagNorestrict to a tag, e.g. 'vo2max'
limitNomax results (default 8, max 20 — a longer list is not more evidence)
queryYeskeywords, e.g. 'heat acclimation plasma volume' or 'fuel a long ride'
sportNorestrict to a sport, e.g. 'running', 'tennis', 'climbing'
sectionNorestrict to a section name
minLevelNominimum evidence level

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already establish readOnly/non-destructive, and the description goes well beyond them by disclosing the actual return shape (compact cards with refId, title, evidence level, tier, sport, DOI, actionable bottom-line, finding, and decision on frameworks) and how complete that payload typically is for answering and citing. This is behaviorally rich for a read tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose and return format, and every clause carries information (return fields, escalation trigger, citation rules). It is dense rather than bloated, though the citation-etiquette sentences push it toward the long side for a search tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description carries the burden of explaining return values and does so concretely, including which fields appear on ordinary entries versus frameworks. Combined with the sibling escalation path, an agent has everything needed to call this correctly and interpret results.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3; the schema already documents tag, limit, query, sport, section, and minLevel with examples. The description adds little parameter-level meaning beyond noting the refId/section pattern for the sibling tool, so it does not exceed the schema baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Search) and resource (curated endurance-science knowledge base) plus the domain scope, and distinguishes itself from the sibling get_knowledge by contrast ('Call get_knowledge(refId) only when...'). An agent can tell this is the discovery/ranking entry point versus the single-entry detail tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes between this tool and get_knowledge with a stated condition ('only when you need the full protocol/mechanism/limitations'), and gives follow-on guidance on citing (refId + level, DOI only when the reader asks). When-to-use and when-to-escalate are both covered.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_activity_notesA
Destructive
Inspect

Write a coach summary / opinion on one completed activity — the athlete sees it in the activity card in Blocks (labelled “Coach read”). Pass the activity id from list_activities. By default it REPLACES the coach note; pass append:true to add. Optionally set a post-session grade (A..E) for how the session was EXECUTED vs the plan — it shows as a colored badge on the ride card (A=nailed it, B=solid/minor deviations, C=partial/mixed, D=undercooked/well off target, E=missed/abandoned; a smart bail on a genuine bad day is NOT automatically E — grade the execution + judgement, not the athlete). Ground the read in the real numbers (duration, TSS, IF, NP, HR, zones, intervals from list_activities/get_activity), the athlete profile and the knowledge base — concrete and useful, not generic praise. Markdown renders in the app — keep it airy: a few short ## sub-headings with normal-weight prose (or short - bullets), **bold** only on a key number or the verdict, and don't restate the ride name or the grade (they're shown separately above the note and as a badge). Separate from the athlete's own note.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYes
gradeNo
notesYes
appendNo

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations flag destructiveHint=true, and the description goes further by disclosing that the default behavior REPLACES the coach note and that append:true is required to add instead. It also reveals the grade badge behavior, markdown rendering, and separation from the athlete's own note – all valuable context beyond the raw annotation flags. No contradiction exists between the description and readOnlyHint=false/destructiveHint=true.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but front-loaded: the one-line purpose comes first, followed by id source, append semantics, grade, content grounding, and markdown rules in a logical order. Every sentence carries a functional requirement, but the lengthy grade scale and formatting guidance prevent a perfect conciseness score.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 4-parameter write tool with no output schema, the description covers every angle an agent needs: input derivation, mutation behavior, optional parameters, content quality bar, rendering rules, and separation from other note types. No critical operational detail is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description fully compensates: id is tied to list_activities, notes receive content and style guidance, append is explained as the additive alternative to replacement, and grade carries a detailed A–E scale with execution-based interpretation. This is far more than the schema's type/enum declarations provide.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence names the exact action ('Write a coach summary / opinion'), the target resource ('one completed activity'), and where the result appears ('activity card in Blocks, labelled Coach read'). It also differentiates from sibling note tools by emphasizing it is a coach note separate from the athlete's own note and tied to a completed activity, not a planned workout or day.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear operational context: pass the activity `id` from list_activities, default replaces the note, append:true adds, and grade is optional. It does not explicitly name sibling tools or state when not to use this tool, but the 'completed activity' criterion sufficiently routes away from set_workout_note, set_day_note, and set_event_notes.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_day_noteA
Destructive
Inspect

ADD a SHORT note to a calendar day — a few words capturing the key thought (e.g. "easy week, watch sleep"), NOT an essay. A day holds SEVERAL notes; this appends one and never touches the athlete's own notes on that day. Max 1000 chars, but keep yours brief; the athlete uses the long form for their own impressions of the day. For a LIST they will tick off (race kit, the evening before a test) use add_checklist, not this. Pass an empty string to clear ALL notes on that day. Optional colour tags the note — the athlete assigns the meaning of each colour themselves, so only set it when they've told you what a colour means, or reuse a colour already on that day.

ParametersJSON Schema
NameRequiredDescriptionDefault
dateYes
noteYes
colorNooptional colour tag; omit to leave the note uncoloured

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds valuable behavioral context beyond the annotations: it clarifies append semantics (appends one note, never touches the athlete's own notes), and it explicitly warns that an empty string clears ALL notes on that day. This meaningfully expands on the destructiveHint annotation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense and uses strong front-loading ('ADD a SHORT note'), and every sentence carries useful information. It is slightly verbose in places (e.g., the long-form remark about the athlete's own impressions), but overall an efficient use of words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the simple three-parameter schema, no output schema, and the presence of a destructive annotation, the description covers the essentials: what to write, how much, what happens on empty, color usage, and the relevant alternative tool. Minor gaps like return value or success indication are not needed for basic invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With only 33% schema description coverage, the description compensates thoroughly. It explains the note parameter's purpose, length expectations, and the empty-string clearing behavior; it also details the optional color parameter's semantics and the condition for using it. This goes far beyond the schema's minimal details.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states a specific verb ('ADD') and resource ('calendar day'), with an explicit scope ('a few words capturing the key thought, NOT an essay'). It distinguishes itself from sibling tools by emphasizing the day context and directly naming add_checklist as the alternative for checklists.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit when-to-use guidance (short note to a day), what to avoid (essays), and names a specific alternative tool (add_checklist) for list-type content. It also tells agents when to use colour tags, including the rule to only set a colour when the athlete has assigned its meaning.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_event_notesA
Destructive
Inspect

Write the EXTENDED prep notes on one event (fueling, hydration, pacing, taper, kit, strategy). This fills the event's coach-notes section in Blocks. Pass the event id from list_events. By default it REPLACES the coach notes; pass append:true to add to them. Base fueling/pacing on the route distance/elevation + the athlete profile + the knowledge base, and keep it concrete (carbs g/h, fluid, sodium, caffeine timing, power targets). Markdown is fine.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYes
notesYes
appendNo

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description explicitly states that it REPLACES the coach notes by default and provides the append:true option to add instead, which aligns with the destructiveHint annotation. It also mentions that it fills the event's coach-notes section, giving a clear side-effect. This goes beyond the annotation by explaining how to control the destructive behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and well-structured, with each sentence adding valuable information: purpose, id source, replace/append behavior, content guidance, and markdown support. There is no redundancy or filler; it is appropriately sized for the tool's complexity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description is complete for an agent to call the tool correctly. It covers the effect (fills coach-notes), the required id, the append behavior, and the content expectations. Since there is no output schema, it doesn't need to describe return values. It also gives practical advice on content quality, making it comprehensive.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema coverage, the description must compensate, and it does. It explains the 'id' (from list_events), the 'append' parameter (append:true), and gives detailed guidance on the 'notes' parameter content (concrete specifics, markdown, and examples like carbs g/h, fluid, etc.). This adds meaning well beyond the bare schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: to write extended prep notes on a single event, specifying the resource (event) and the content (fueling, hydration, pacing, taper, kit, strategy). It differentiates from sibling note tools like set_activity_notes by explicitly targeting events and mentioning the coach-notes section. The action is unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear context: the event id should come from list_events, and the default behavior replaces notes unless append:true is passed. However, it doesn't explicitly compare with alternatives or state when not to use it (e.g., for activities). The instruction to use the event id implies the prerequisite, but a direct contrast with sibling note tools would make it fully explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_strength_notesA
Destructive
Inspect

Write your read of one LOGGED gym session and grade it — the athlete sees both on the session card, where a ride carries its coach read and badge. A gym session usually has no activity row, so set_activity_notes cannot reach it. Name it by date (plus title when two were logged that day); REPLACES the read unless append:true. grade A..E is how it was EXECUTED against the plan — A every set as prescribed, B minor drift, C partly off, D well off, E missed or abandoned; dropping the load on a bad day and finishing is judgement, not an E. Grade the execution, never the athlete. Read get_strength_log and get_strength_progression first — a read that could have been written without opening the log is not worth its cost. Markdown renders; don't restate the title or the grade. On an Analyze-button turn the app saves your REPLY as the read — don't call this there.

ParametersJSON Schema
NameRequiredDescriptionDefault
dateYes
gradeNo
notesYes
titleNo
appendNo

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations: it discloses that the call REPLACES the existing read unless append:true, exactly matching destructiveHint=true, and describes the write target (session card with coach read and badge) and rendering behavior (markdown renders). The grade rubric also documents judgment nuance (dropping load and finishing is not an E), which is behavioral context annotations cannot express.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads purpose, destination, and the sibling distinction before diving into grade detail. Every sentence earns its place, but the whole thing is one dense block with rubric and edge-case guidance interleaved, which slightly impairs scannability.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a write tool with no output schema, the definition supplies everything an agent needs: what is written, where it appears, replacement vs append behavior, parameter meaning, prerequisites, grade semantics, and the Analyze-turn exclusion. No meaningful gap remains.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema coverage, the description fully compensates: it defines date and title-as-disambiguator, explains append:true semantics, and gives a complete A..E grade rubric including edge-case interpretation. Notes content and markdown rendering are also covered, so every parameter's meaning is clear from the description alone.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: "Write your read of one LOGGED gym session and grade it," and identifies where the output lands (session card). It explicitly distinguishes itself from set_activity_notes by explaining that a gym session usually has no activity row, so an agent can route correctly without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit when-to-use (naming a session by date, plus title when two were logged), when-not-to-use (on an Analyze-button turn the app saves the reply, so don't call this), a prerequisite (read get_strength_log and get_strength_progression first), and the sibling it replaces (set_activity_notes unreachable for gym sessions). Nothing is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_workout_note
Destructive
Inspect

Write the note on one scheduled workout (iid from get_plan / plan_workouts) — the session's brief the athlete reads on its card: how to ride it, fuelling, constraints (e.g. "key session, commit" or "legs flat — cut a set"). Up to 500 chars, keep it tight; what belongs to this session goes HERE, not into a day note. Empty string clears it.

ParametersJSON Schema
NameRequiredDescriptionDefault
iidYes
dateYes
noteYes
tag_activityAInspect

Set CONTEXT tags on one completed activity (full-array write; empty array clears). Tags describe how the session should be READ, not what it contained: workout (a plain training session — read it against the plan), heat (hot conditions — HR inflated, output depressed, expected), altitude (ridden high — hypoxic shift, lower power is normal), indoor (turbo trainer, treadmill or a virtual platform — still air means HR climbs through the session at unchanged power, so drift is expected and is not a fitness signal; speed, distance and pace are the platform's invention, so judge power, HR and RPE and never km or min/km, and never compare them with outdoor numbers), race (max effort by design — grade vs the race goal, not the plan), test (FTP/lactate/field test — peak efforts deliberate; consider estimate_thresholds after), group (group ride — surging, structure deviations expected), commute (transport volume, not training intent). Use when the athlete tells you the context ('вчера была жара', 'это была гонка') or when you infer it and they confirm. Immediate write — the tag chips appear on the activity card.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYes
tagsYes

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses important behavior beyond annotations: 'full-array write; empty array clears' and 'Immediate write — the tag chips appear on the activity card.' It also explains the semantic implications of each tag. Annotations only state readOnlyHint=false, destructiveHint=false, so the description adds meaningful operational detail without contradicting them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long, but it is front-loaded with the core behavior and then structured as a compact list of tag definitions. Each tag explanation earns its place because it directly affects how the agent should tag and interpret activities. It could be slightly more concise, but there is no fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with no output schema and minimal annotations, the description is exceptionally complete. It covers purpose, usage triggers, write behavior, parameter semantics, and all enum values with domain-specific interpretation guidance. An agent has enough information to invoke the tool correctly without needing additional context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries full responsibility for parameter meaning. It thoroughly explains the tags array semantics, including full-array overwrite and empty-array clearing, and gives detailed meaning for every enum value. The id parameter is not explicitly described, but it is clearly implied by 'one completed activity' and the overall context.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Set CONTEXT tags on one completed activity'. It also explains the full-array write semantics and explicitly distinguishes tags as describing how the session should be read, not what it contained. This clearly separates the tool from siblings like set_activity_notes or edit_activity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit usage triggers: 'Use when the athlete tells you the context... or when you infer it and they confirm.' It also provides example phrases the athlete might use. It does not name alternative tools for exclusion, but the guidance is concrete enough for an agent to decide when to invoke it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

update_athlete_fileA
Destructive
Inspect

Set the athlete's GRADE — the machine-read classification that scopes every knowledge-base search: - sport: <primary>[, others], - level: recreational|trained|competitive|elite, - populations: <any of female-health, masters, youth, para — or —>. That is ALL this tool writes now.

Everything the assistant remembers about the athlete moved to separate facts on 2026-08-24 (add_fact / update_fact / confirm_fact / retire_fact), because a fact needs a horizon and free prose cannot carry one: three cancelled-race sections went on steering plans for a month. Grade is the exception on purpose — a classification has no expiry date, so it is the one thing left here.

ParametersJSON Schema
NameRequiredDescriptionDefault
modeNoreplace (default) = these lines become the whole Grade; append = add them under the existing Grade
contentYesthe Grade lines
sectionNoGrade only — everything else is add_fact

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and readOnlyHint=false, so the safety profile is covered. The description adds useful context beyond that: Grade has no expiry date, it is the only surviving free-text field, and the migration date that moved everything else to facts. It does not explicitly restate that the default mode overwrites prior Grade, but the schema's mode description carries that.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action and the format template, then the rationale. The 'three cancelled-race sections' anecdote is mild editorializing, but it justifies the architectural split in one clause and is not wasted space.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-section mutation tool with no output schema and full annotation coverage, the description covers what is written, in what format, and what has moved elsewhere. A brief note on what the write returns or how it affects subsequent knowledge-base searches would close the last gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, and the description exceeds it by documenting the actual line syntax allowed in `content` (sport/level/populations with valid enum values), which the schema only calls 'the Grade lines'. The mode semantics are left to the schema, which handles them adequately.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a precise verb+resource (set the athlete's Grade section of the athlete file) and specifies the exact content format with enum values for level and populations. It also explicitly scopes itself: 'That is ALL this tool writes now,' separating it cleanly from the fact tools in the sibling list.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Names the alternatives explicitly (add_fact / update_fact / confirm_fact / retire_fact) and gives the condition that selects them ('a fact needs a horizon'). It also explains why Grade is the deliberate exception, so an agent knows both when to use this tool and when not to.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

update_athlete_profile
Destructive
Inspect

Edit the athlete's profile — FTP (watts), running threshold pace, max/threshold HR, power/pace/HR zone boundaries, AND the about-you fields (birthdate, sex, heightCm, weightKg, weeklyHours, availableDays 0=Mon..6=Sun, experience). Every field is OPTIONAL: pass only what changes; everything else is preserved (safe partial update). Confirm new numbers with the athlete before writing (a changed FTP/weight moves every target). To set custom zones pass a sport's zoneBounds (5 strictly-ascending upper bounds) — that flips it to Manual; pass autoZones:true to revert. Same for hrZoneBounds/autoHrZones. Setting birthdate refreshes the age-based HRmax estimate unless maxHr was set manually — writing a sport's maxHr marks it manual, and autoMaxHr:true hands it back to the estimate. Server-validated; rejects an invalid edit instead of writing a broken profile. Only touches the profile, never the calendar or library. Read with get_athlete_profile first.

ParametersJSON Schema
NameRequiredDescriptionDefault
ftpNocycling FTP, watts
runNorunning thresholds + zones
sexNo
sftNothe athlete's CYCLING submaximal fatigue test (SFT): the fixed load they hold in the warm-up, which get_fatigue_tests then finds in every ride. null = stop tracking. The standard protocol (Science to Sport, what intervals.icu detects) is about 110% of FTP for 3 min (sec 180) — get_fatigue_tests proposes it — agree it with them, and do not change it mid-season — a new value starts a new baseline.
bikeNocycling thresholds + zones
sftRunNothe athlete's RUNNING fatigue test: about 105% of threshold speed for 3 min (sec 180), frozen for the season, on a treadmill or a flat loop, then a minute of walking — get_fatigue_tests sport:"running" proposes it. null = stop tracking.
controlNowhat they TRAIN BY per sport (Profile "You train by"): the signal you judge and speak in — not the watch's default (running hr also sets runByHr); null = back to what their files show. Only when they say so.
cssPaceNoSWIM threshold — critical swim speed, seconds per 100 m. Confirm it with the athlete before writing: without it swims carry no load, and with a wrong one every swim in their history is mis-scored. From a 400 m + 200 m time trial: (400-200)/(t400-t200) m/s.
runByHrNotrue = runs default to HR targets on the watch (= control.running "hr")
thrPaceNorunning threshold pace, seconds per km
dayCheckNoa subscriber's "Day check" (Profile → Assistant): the assistant's own short look at today or tomorrow when the gym log or check-in gives a reason — false turns it off. Only when they ask.
heightCmNo
weightKgNokg — enables W/kg and body-mass fuelling
autoMaxHrNotrue = go back to the age-based HRmax estimate. Writing a sport's maxHr flips this to manual on its own.
birthdateNoYYYY-MM-DD (age is derived); setting it refreshes the age-based HRmax estimate unless maxHr was set manually (maxHrAuto:false — read it back in get_athlete_profile)
experienceNotraining age → ramp aggressiveness
powerMeterNofalse = no power meter: ride targets show as HR + RPE; prescribe by HR and feel
weeklyHoursNotypical training hours/week
availableDaysNoweekdays free to train, 0=Mon..6=Sun
suggestReviewsNopost-session reviews (Profile → Assistant). For a Blocks Unlimited subscriber this is "Automatic reviews": Blocks reviews a finished training session on its own (20 min+, up to 2 a day, none at night) — false turns that off. For everyone else it is the offer of a review after a key session. Only when they ask.
update_eventA
Destructive
Inspect

Edit an existing event's fields (name, date, start time, description, location, URLs, logistics notes) — every field optional, only what you pass changes. Use when the race date shifts, the venue changes, or details firm up. Weather re-resolves automatically when date or location changes. For the coach-notes section use set_event_notes; for prep content changes don't touch this.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYes
cdaNothe rider's CdA for this race, m² (e.g. from estimate_cda, after the athlete agrees); 0 clears to the 0.32 default
dateNo
nameNo
notesNoathlete logistics; empty string clears
mapUrlNo
targetNotheir aim; '' clears
eventUrlNo
priorityNoA = season goal, B/C = on the way, '' clears
startTimeNolocal start 'HH:MM'; '' clears
descriptionNo
locationTextNo

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and readOnlyHint=false, so safety is partly covered. The description adds genuine behavioral context beyond the schema: partial-update semantics ('only what you pass changes') and an important side effect ('Weather re-resolves automatically when date or location changes'). It does not state permission requirements or whether prior values are recoverable, so not a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three dense sentences, front-loaded with the core action and field list, followed by usage triggers, a side-effect note, and sibling routing. No filler, and the most important scoping information comes first.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 12-param mutation tool with no output schema, the description covers action, patch semantics, side effects, and sibling routing, which is most of what an agent needs. Minor gaps remain on permission/auth requirements and the full clearing semantics that live only in the schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 42% across 12 parameters, so the description should compensate more. It lists field groups and contributes the useful patch-semantics note ('every field optional, only what you pass changes'), but clear-to-default behaviors (e.g. cda=0, target '' clears) are documented in the schema rather than the description, leaving gaps.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Edit') and resource ('an existing event's fields') and enumerates the editable fields, so an agent immediately knows scope. It also differentiates the tool from siblings by naming set_event_notes for coach notes and warning off prep-content edits.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives concrete triggering conditions ('when the race date shifts, the venue changes, or details firm up') and explicit exclusions ('for the coach-notes section use set_event_notes; for prep content changes don't touch this'). Both when-to-use and when-not-to-use are covered with named alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

update_factA
Destructive
Inspect

Change ONE fact — its text, its horizon, its date, its tags. Use it when the athlete corrects something or when a horizon is answered ("tennis holds through the winter" → move the recheck). A card, because this edits something already on their Profile page and often something they wrote — except rewriting their existing "Language:" fact when they ask to switch language, which saves on return. To only bump a pattern's strength use confirm_fact, which is silent.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYes
areaNo
tagsNo
textNo
dueDateNo
horizonNo
dueLabelNo
seasonToNo
dueActionNo
seasonFromNo

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already carry destructiveHint=true and readOnlyHint=false, so the description doesn't need to restate the mutation. It adds context that this edits existing Profile content and calls out a special Language-fact case that 'saves on return,' but it does not disclose response behavior or whether changes are reversible.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The core action is front-loaded and each sentence adds usage value. The phrase 'A card, because...' and 'saves on return' are slightly jargon-y and could confuse an agent without product context, but overall the description is appropriately sized.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive 10-parameter tool with no output schema, the description covers the main use cases and the key alternative. It is not complete enough for confident use of the more specialized params (area, season fields, dueAction/dueLabel) or to know what a successful update returns.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It names text, horizon, date, and tags, and the horizon-answered example gives useful meaning to recheck-style updates. However, it omits area, dueAction, dueLabel, seasonFrom, and seasonTo, and doesn't clarify that id is the only required field with the rest being optional partial-update fields.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Change ONE fact') and names the editable parts: text, horizon, date, tags. It differentiates from confirm_fact by contrasting silent pattern-strength bumps with this editing action, so an agent can distinguish it from siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly gives trigger conditions: when an athlete corrects something or when a horizon is answered, including a concrete example. It also names confirm_fact as the alternative when only pattern strength needs bumping, giving clear routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

update_plan_workout
Destructive
Inspect

Edit ONE scheduled workout in place (keeps its identity on the calendar, and its day unless moveTo moves it): replace its interval blocks (bike/run) or strength items (gym), and/or title and/or note, and/or the session's carbohydrate (fuelG). Use for structural coaching edits — a better warm-up, changed rep count, adjusted intensities — instead of remove+re-add. Read it first with get_plan_workout. blocks/strength fully REPLACE the old content (same format as plan_workouts custom workouts; validated server-side).

ParametersJSON Schema
NameRequiredDescriptionDefault
iidYes
keyNomark/unmark as the week's KEY session (see plan_workouts). You may set a limited number per week yourself; past that the rest of the edit still lands, without the star, and the result says so — a call that ONLY sets the star is refused and you ask the athlete instead. The cap is on you, not on them. Clearing one is never refused.
whyNoONE line, in the athlete's language: WHY this change — the reason from the conversation ("travel Thu-Fri, long ride moved to Sat", "deload after 3 build weeks"). The athlete's other assistant surface reads it later; without it, it sees only that the plan changed. No health details beyond what the plan needs.
dateYes
goalNothe QUALITY this session trains — why it is in the plan — a short phrase leading with the quality (as in plan_workouts); empty string hands it back to the catalog workout's own line (or none)
noteNoshort note; empty string clears it
timeNoHH:MM start of day; empty string clears
fuelGNocarbohydrate in GRAMS for the WHOLE session, overruling the app's own number for this one entry — a race rehearsal, a gut being trained up, an athlete who knows what they tolerate. The athlete sees one total, never a rate, so state it as a total. At most 120 g per hour of the session; 0 = water only; null hands it back to the formula. Leave it alone unless you have a reason the formula cannot see.
sportNofix a bike↔run mix-up on an entry that is already on the calendar, keeping its position, blocks and note. Only these two: their blocks are the same numbers read against a different threshold, while every other sport keeps a different payload entirely. Passing the entry's own sport changes nothing; any other pair is refused.
titleNo
blocksNobike/run/swim: full replacement interval structure (a swim in metres, as in plan_workouts)
moveToNoanother day to move it to, everything on it kept — a move is this one call, never copy + remove
targetNoride power|hr|rpe, run pace|hr|rpe
contextNofull-array replacement of this entry's context tags (the tag list and what each one means are in tag_activity's description — one glossary, not a second copy); empty array clears
sessionNosport 'other' only: full replacement duration + intended effort
strengthNostrength only: full replacement exercises/supersets
update_plan_workouts
Destructive
Inspect

The same kind of edit on MANY scheduled workouts — ONE card instead of one per session; use it for an edit covering more than three sessions. Each edits item is date + iid + the fields that change, each meaning what it means in update_plan_workout. Structure, gym content, sport and the key star: update_plan_workout, one by one. An edit the single tool would refuse is an invalid line on the card; the rest land.

ParametersJSON Schema
NameRequiredDescriptionDefault
whyNoONE line, in the athlete's language: WHY this change — the reason from the conversation ("travel Thu-Fri, long ride moved to Sat", "deload after 3 build weeks"). The athlete's other assistant surface reads it later; without it, it sees only that the plan changed. No health details beyond what the plan needs.
editsYes

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 1 tool update
    • Changedupdate_plan_workout1 field changed
      • addedInput schema / properties / moveTo
        Added value: +{
        +  "description": "another day to move it to, everything on it kept — a move is this one call, never copy + remove",
        +  "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
        +  "type": "string"
        +}
  2. 2 tool updates
    • Changedget_metric_history1 field changed
      • changedInput schema / properties / kinds / items / enum
        Previous value: -[
        -  "ftp",
        -  "thrPace",
        -  "lthrBike",
        -  "lthrRun",
        -  "maxHrBike",
        -  "maxHrRun",
        -  "weightKg",
        -  "vo2max",
        -  "map",
        -  "lt1",
        -  "lt2",
        -  "lactate",
        -  "ferritin",
        -  "hb",
        -  "rhr",
        -  "hrv",
        -  "cssPace",
        -  "runCp"
        -]New value: +[
        +  "ftp",
        +  "thrPace",
        +  "lthrBike",
        +  "lthrRun",
        +  "maxHrBike",
        +  "maxHrRun",
        +  "weightKg",
        +  "vo2max",
        +  "map",
        +  "lt1",
        +  "lt2",
        +  "lactate",
        +  "ferritin",
        +  "hb",
        +  "rhr",
        +  "hrv",
        +  "cssPace",
        +  "runCp",
        +  "bodyFatPct"
        +]
    • Changedlog_metric2 fields changed
      • changedInput schema / properties / items / items / properties / kind / enum
        Previous value: -[
        -  "ftp",
        -  "thrPace",
        -  "lthrBike",
        -  "lthrRun",
        -  "maxHrBike",
        -  "maxHrRun",
        -  "weightKg",
        -  "vo2max",
        -  "map",
        -  "lt1",
        -  "lt2",
        -  "lactate",
        -  "ferritin",
        -  "hb",
        -  "rhr",
        -  "hrv",
        -  "cssPace",
        -  "runCp"
        -]New value: +[
        +  "ftp",
        +  "thrPace",
        +  "lthrBike",
        +  "lthrRun",
        +  "maxHrBike",
        +  "maxHrRun",
        +  "weightKg",
        +  "vo2max",
        +  "map",
        +  "lt1",
        +  "lt2",
        +  "lactate",
        +  "ferritin",
        +  "hb",
        +  "rhr",
        +  "hrv",
        +  "cssPace",
        +  "runCp",
        +  "bodyFatPct"
        +]
      • changedInput schema / properties / items / items / properties / value / description
        Previous value: -"the number, in the kind's own unit (w, sec_per_km, bpm, kg, ml_kg_min, mmol_l, ng_ml, g_l, ms)"New value: +"the number, in the kind's own unit (w, sec_per_km, bpm, kg, pct, ml_kg_min, mmol_l, ng_ml, g_l, ms)"
  3. 1 tool update
    • Changedupdate_athlete_profile1 field changed
      • addedInput schema / properties / dayCheck
        Added value: +{
        +  "description": "a subscriber's \"Day check\" (Profile → Assistant): the assistant's own short look at today or tomorrow when the gym log or check-in gives a reason — false turns it off. Only when they ask.",
        +  "type": "boolean"
        +}
  4. 2 tool updates
    • Changedplan_workouts1 field changed
      • changedInput schema / properties / items / items / properties / workout / properties / blocks / items / anyOf
        Previous value: -[
        -  {
        -    "properties": {
        -      "children": {
        -        "items": {
        -          "properties": {
        -            "cad": {
        -              "description": "target cadence rpm",
        -              "maximum": 9007199254740991,
        -              "minimum": -9007199254740991,
        -              "type": "integer"
        -            },
        -            "dist": {
        -              "description": "RUNNING and SWIMMING: measure this rep by distance in metres (2000 for 2 km on the road, 100 for a pool rep) instead of time; time is derived from the target pace. For SWIMMING this is the normal case — a set is written in metres, never in minutes. Give either dur or dist, not both.",
        -              "maximum": 50000,
        -              "minimum": 25,
        -              "type": "integer"
        -            },
        -            "dur": {
        -              "description": "seconds (omit when using dist)",
        -              "exclusiveMinimum": 0,
        -              "maximum": 9007199254740991,
        -              "type": "integer"
        -            },
        -            "gear": {
        -              "description": "SWIMMING: paddles | buoy | fins | board | snorkel",
        -              "items": {
        -                "enum": [
        -                  "paddles",
        -                  "buoy",
        -                  "fins",
        -                  "board",
        -                  "snorkel"
        -                ],
        -                "type": "string"
        -              },
        -              "maxItems": 3,
        -              "type": "array"
        -            },
        -            "label": {
        -              "maxLength": 80,
        -              "type": "string"
        -            },
        -            "maxHr": {
        -              "description": "heart-rate ceiling, bpm: over it the trainer autopilot takes watts off",
        -              "maximum": 220,
        -              "minimum": 80,
        -              "type": "integer"
        -            },
        -            "maxRpe": {
        -              "description": "RPE ceiling (1-10): a rating over it, asked or tapped mid-step, takes watts off this step",
        -              "maximum": 10,
        -              "minimum": 1,
        -              "type": "integer"
        -            },
        -            "maxW": {
        -              "description": "CYCLING: the most watts ERG may hold on this step (a ceiling, e.g. 190 on an easy ride). Put limits HERE, not in the label or note — the trainer autopilot reads this field",
        -              "maximum": 2000,
        -              "minimum": 50,
        -              "type": "integer"
        -            },
        -            "mode": {
        -              "description": "SWIMMING: swim (default) | kick | pull | drill",
        -              "enum": [
        -                "swim",
        -                "kick",
        -                "pull",
        -                "drill"
        -              ],
        -              "type": "string"
        -            },
        -            "open": {
        -              "description": "a maximal effort (test, all-out) — no target on the device; power stays as the expected level",
        -              "type": "boolean"
        -            },
        -            "power": {
        -              "description": "%FTP (cycling) or %threshold pace (running) or %CSS (swimming — 100 = their CSS pace, below 100 = slower/easier, e.g. 92 for an aerobic set)",
        -              "maximum": 200,
        -              "minimum": 30,
        -              "type": "number"
        -            },
        -            "sft": {
        -              "description": "true = the athlete's SFT: load and length come from their profile at export; follow it with 60 s easy",
        -              "type": "boolean"
        -            },
        -            "stroke": {
        -              "description": "SWIMMING: free (default) | back | breast | fly | im | choice",
        -              "enum": [
        -                "free",
        -                "back",
        -                "breast",
        -                "fly",
        -                "im",
        -                "choice"
        -              ],
        -              "type": "string"
        -            },
        -            "target": {
        -              "description": "this step's own device target, over the session's",
        -              "enum": [
        -                "power",
        -                "pace",
        -                "hr",
        -                "rpe"
        -              ],
        -              "type": "string"
        -            },
        -            "untilLap": {
        -              "description": "the step ends when the athlete presses Lap",
        -              "type": "boolean"
        -            },
        -            "zone": {
        -              "enum": [
        -                "recovery",
        -                "endurance",
        -                "tempo",
        -                "threshold",
        -                "vo2",
        -                "sprint"
        -              ],
        -              "type": "string"
        -            }
        -          },
        -          "required": [
        -            "zone",
        -            "power"
        -          ],
        -          "type": "object"
        -        },
        -        "minItems": 1,
        -        "type": "array"
        -      },
        -      "reps": {
        -        "maximum": 30,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "sendoff": {
        -        "description": "SWIMMING: the send-off in seconds — the whole cycle, swim PLUS rest (\"10×100 on 1:40\" = 100). Rest is what is left of it. Use this OR a rest step inside the set, never both: they are two different sessions, and on a send-off swimming faster buys rest instead of ending the interval sooner.",
        -        "maximum": 1800,
        -        "minimum": 10,
        -        "type": "integer"
        -      },
        -      "type": {
        -        "const": "repeat",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "reps",
        -      "children"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "properties": {
        -      "cad": {
        -        "description": "target cadence rpm",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dist": {
        -        "description": "RUNNING and SWIMMING: measure this rep by distance in metres (2000 for 2 km on the road, 100 for a pool rep) instead of time; time is derived from the target pace. For SWIMMING this is the normal case — a set is written in metres, never in minutes. Give either dur or dist, not both.",
        -        "maximum": 50000,
        -        "minimum": 25,
        -        "type": "integer"
        -      },
        -      "dur": {
        -        "description": "seconds (omit when using dist)",
        -        "exclusiveMinimum": 0,
        -        "maximum": 9007199254740991,
        -        "type": "integer"
        -      },
        -      "gear": {
        -        "description": "SWIMMING: paddles | buoy | fins | board | snorkel",
        -        "items": {
        -          "enum": [
        -            "paddles",
        -            "buoy",
        -            "fins",
        -            "board",
        -            "snorkel"
        -          ],
        -          "type": "string"
        -        },
        -        "maxItems": 3,
        -        "type": "array"
        -      },
        -      "label": {
        -        "maxLength": 80,
        -        "type": "string"
        -      },
        -      "maxHr": {
        -        "description": "heart-rate ceiling, bpm: over it the trainer autopilot takes watts off",
        -        "maximum": 220,
        -        "minimum": 80,
        -        "type": "integer"
        -      },
        -      "maxRpe": {
        -        "description": "RPE ceiling (1-10): a rating over it, asked or tapped mid-step, takes watts off this step",
        -        "maximum": 10,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "maxW": {
        -        "description": "CYCLING: the most watts ERG may hold on this step (a ceiling, e.g. 190 on an easy ride). Put limits HERE, not in the label or note — the trainer autopilot reads this field",
        -        "maximum": 2000,
        -        "minimum": 50,
        -        "type": "integer"
        -      },
        -      "mode": {
        -        "description": "SWIMMING: swim (default) | kick | pull | drill",
        -        "enum": [
        -          "swim",
        -          "kick",
        -          "pull",
        -          "drill"
        -        ],
        -        "type": "string"
        -      },
        -      "open": {
        -        "description": "a maximal effort (test, all-out) — no target on the device; power stays as the expected level",
        -        "type": "boolean"
        -      },
        -      "power": {
        -        "description": "%FTP (cycling) or %threshold pace (running) or %CSS (swimming — 100 = their CSS pace, below 100 = slower/easier, e.g. 92 for an aerobic set)",
        -        "maximum": 200,
        -        "minimum": 30,
        -        "type": "number"
        -      },
        -      "sft": {
        -        "description": "true = the athlete's SFT: load and length come from their profile at export; follow it with 60 s easy",
        -        "type": "boolean"
        -      },
        -      "stroke": {
        -        "description": "SWIMMING: free (default) | back | breast | fly | im | choice",
        -        "enum": [
        -          "free",
        -          "back",
        -          "breast",
        -          "fly",
        -          "im",
        -          "choice"
        -        ],
        -        "type": "string"
        -      },
        -      "target": {
        -        "description": "this step's own device target, over the session's",
        -        "enum": [
        -          "power",
        -          "pace",
        -          "hr",
        -          "rpe"
        -        ],
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "steady",
        -        "type": "string"
        -      },
        -      "untilLap": {
        -        "description": "the step ends when the athlete presses Lap",
        -        "type": "boolean"
        -      },
        -      "zone": {
        -        "enum": [
        -          "recovery",
        -          "endurance",
        -          "tempo",
        -          "threshold",
        -          "vo2",
        -          "sprint"
        -        ],
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "zone",
        -      "power"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "properties": {
        +      "children": {
        +        "items": {
        +          "properties": {
        +            "cad": {
        +              "description": "target cadence rpm",
        +              "maximum": 9007199254740991,
        +              "minimum": -9007199254740991,
        +              "type": "integer"
        +            },
        +            "dist": {
        +              "description": "RUNNING and SWIMMING: measure this rep by distance in metres (2000 for 2 km on the road, 100 for a pool rep) instead of time; time is derived from the target pace. For SWIMMING this is the normal case — a set is written in metres, never in minutes. Give either dur or dist, not both.",
        +              "maximum": 50000,
        +              "minimum": 25,
        +              "type": "integer"
        +            },
        +            "dur": {
        +              "description": "seconds (omit when using dist)",
        +              "exclusiveMinimum": 0,
        +              "maximum": 9007199254740991,
        +              "type": "integer"
        +            },
        +            "gear": {
        +              "description": "SWIMMING: paddles | buoy | fins | board | snorkel",
        +              "items": {
        +                "enum": [
        +                  "paddles",
        +                  "buoy",
        +                  "fins",
        +                  "board",
        +                  "snorkel"
        +                ],
        +                "type": "string"
        +              },
        +              "maxItems": 3,
        +              "type": "array"
        +            },
        +            "hr": {
        +              "description": "the athlete's own HR corridor for this step, bpm (\"135-145\") — over the zone's band on the card, the watch and the autopilot; only when they named one",
        +              "properties": {
        +                "hi": {
        +                  "maximum": 220,
        +                  "minimum": 61,
        +                  "type": "integer"
        +                },
        +                "lo": {
        +                  "maximum": 219,
        +                  "minimum": 60,
        +                  "type": "integer"
        +                }
        +              },
        +              "required": [
        +                "lo",
        +                "hi"
        +              ],
        +              "type": "object"
        +            },
        +            "label": {
        +              "maxLength": 80,
        +              "type": "string"
        +            },
        +            "maxHr": {
        +              "description": "heart-rate ceiling, bpm: over it the trainer autopilot takes watts off",
        +              "maximum": 220,
        +              "minimum": 80,
        +              "type": "integer"
        +            },
        +            "maxRpe": {
        +              "description": "RPE ceiling (1-10): a rating over it, asked or tapped mid-step, takes watts off this step",
        +              "maximum": 10,
        +              "minimum": 1,
        +              "type": "integer"
        +            },
        +            "maxW": {
        +              "description": "CYCLING: the most watts ERG may hold on this step (a ceiling, e.g. 190 on an easy ride). Put limits HERE, not in the label or note — the trainer autopilot reads this field",
        +              "maximum": 2000,
        +              "minimum": 50,
        +              "type": "integer"
        +            },
        +            "mode": {
        +              "description": "SWIMMING: swim (default) | kick | pull | drill",
        +              "enum": [
        +                "swim",
        +                "kick",
        +                "pull",
        +                "drill"
        +              ],
        +              "type": "string"
        +            },
        +            "open": {
        +              "description": "a maximal effort (test, all-out) — no target on the device; power stays as the expected level",
        +              "type": "boolean"
        +            },
        +            "power": {
        +              "description": "%FTP (cycling) or %threshold pace (running) or %CSS (swimming — 100 = their CSS pace, below 100 = slower/easier, e.g. 92 for an aerobic set)",
        +              "maximum": 200,
        +              "minimum": 30,
        +              "type": "number"
        +            },
        +            "sft": {
        +              "description": "true = the athlete's SFT: load and length come from their profile at export; follow it with 60 s easy",
        +              "type": "boolean"
        +            },
        +            "stroke": {
        +              "description": "SWIMMING: free (default) | back | breast | fly | im | choice",
        +              "enum": [
        +                "free",
        +                "back",
        +                "breast",
        +                "fly",
        +                "im",
        +                "choice"
        +              ],
        +              "type": "string"
        +            },
        +            "target": {
        +              "description": "this step's own device target, over the session's",
        +              "enum": [
        +                "power",
        +                "pace",
        +                "hr",
        +                "rpe"
        +              ],
        +              "type": "string"
        +            },
        +            "untilLap": {
        +              "description": "the step ends when the athlete presses Lap",
        +              "type": "boolean"
        +            },
        +            "zone": {
        +              "enum": [
        +                "recovery",
        +                "endurance",
        +                "tempo",
        +                "threshold",
        +                "vo2",
        +                "sprint"
        +              ],
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "zone",
        +            "power"
        +          ],
        +          "type": "object"
        +        },
        +        "minItems": 1,
        +        "type": "array"
        +      },
        +      "reps": {
        +        "maximum": 30,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "sendoff": {
        +        "description": "SWIMMING: the send-off in seconds — the whole cycle, swim PLUS rest (\"10×100 on 1:40\" = 100). Rest is what is left of it. Use this OR a rest step inside the set, never both: they are two different sessions, and on a send-off swimming faster buys rest instead of ending the interval sooner.",
        +        "maximum": 1800,
        +        "minimum": 10,
        +        "type": "integer"
        +      },
        +      "type": {
        +        "const": "repeat",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "reps",
        +      "children"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "properties": {
        +      "cad": {
        +        "description": "target cadence rpm",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dist": {
        +        "description": "RUNNING and SWIMMING: measure this rep by distance in metres (2000 for 2 km on the road, 100 for a pool rep) instead of time; time is derived from the target pace. For SWIMMING this is the normal case — a set is written in metres, never in minutes. Give either dur or dist, not both.",
        +        "maximum": 50000,
        +        "minimum": 25,
        +        "type": "integer"
        +      },
        +      "dur": {
        +        "description": "seconds (omit when using dist)",
        +        "exclusiveMinimum": 0,
        +        "maximum": 9007199254740991,
        +        "type": "integer"
        +      },
        +      "gear": {
        +        "description": "SWIMMING: paddles | buoy | fins | board | snorkel",
        +        "items": {
        +          "enum": [
        +            "paddles",
        +            "buoy",
        +            "fins",
        +            "board",
        +            "snorkel"
        +          ],
        +          "type": "string"
        +        },
        +        "maxItems": 3,
        +        "type": "array"
        +      },
        +      "hr": {
        +        "description": "the athlete's own HR corridor for this step, bpm (\"135-145\") — over the zone's band on the card, the watch and the autopilot; only when they named one",
        +        "properties": {
        +          "hi": {
        +            "maximum": 220,
        +            "minimum": 61,
        +            "type": "integer"
        +          },
        +          "lo": {
        +            "maximum": 219,
        +            "minimum": 60,
        +            "type": "integer"
        +          }
        +        },
        +        "required": [
        +          "lo",
        +          "hi"
        +        ],
        +        "type": "object"
        +      },
        +      "label": {
        +        "maxLength": 80,
        +        "type": "string"
        +      },
        +      "maxHr": {
        +        "description": "heart-rate ceiling, bpm: over it the trainer autopilot takes watts off",
        +        "maximum": 220,
        +        "minimum": 80,
        +        "type": "integer"
        +      },
        +      "maxRpe": {
        +        "description": "RPE ceiling (1-10): a rating over it, asked or tapped mid-step, takes watts off this step",
        +        "maximum": 10,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "maxW": {
        +        "description": "CYCLING: the most watts ERG may hold on this step (a ceiling, e.g. 190 on an easy ride). Put limits HERE, not in the label or note — the trainer autopilot reads this field",
        +        "maximum": 2000,
        +        "minimum": 50,
        +        "type": "integer"
        +      },
        +      "mode": {
        +        "description": "SWIMMING: swim (default) | kick | pull | drill",
        +        "enum": [
        +          "swim",
        +          "kick",
        +          "pull",
        +          "drill"
        +        ],
        +        "type": "string"
        +      },
        +      "open": {
        +        "description": "a maximal effort (test, all-out) — no target on the device; power stays as the expected level",
        +        "type": "boolean"
        +      },
        +      "power": {
        +        "description": "%FTP (cycling) or %threshold pace (running) or %CSS (swimming — 100 = their CSS pace, below 100 = slower/easier, e.g. 92 for an aerobic set)",
        +        "maximum": 200,
        +        "minimum": 30,
        +        "type": "number"
        +      },
        +      "sft": {
        +        "description": "true = the athlete's SFT: load and length come from their profile at export; follow it with 60 s easy",
        +        "type": "boolean"
        +      },
        +      "stroke": {
        +        "description": "SWIMMING: free (default) | back | breast | fly | im | choice",
        +        "enum": [
        +          "free",
        +          "back",
        +          "breast",
        +          "fly",
        +          "im",
        +          "choice"
        +        ],
        +        "type": "string"
        +      },
        +      "target": {
        +        "description": "this step's own device target, over the session's",
        +        "enum": [
        +          "power",
        +          "pace",
        +          "hr",
        +          "rpe"
        +        ],
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "steady",
        +        "type": "string"
        +      },
        +      "untilLap": {
        +        "description": "the step ends when the athlete presses Lap",
        +        "type": "boolean"
        +      },
        +      "zone": {
        +        "enum": [
        +          "recovery",
        +          "endurance",
        +          "tempo",
        +          "threshold",
        +          "vo2",
        +          "sprint"
        +        ],
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "zone",
        +      "power"
        +    ],
        +    "type": "object"
        +  }
        +]
    • Changedupdate_plan_workout1 field changed
      • changedInput schema / properties / blocks / items / anyOf
        Previous value: -[
        -  {
        -    "properties": {
        -      "children": {
        -        "items": {
        -          "properties": {
        -            "cad": {
        -              "description": "target cadence rpm",
        -              "maximum": 9007199254740991,
        -              "minimum": -9007199254740991,
        -              "type": "integer"
        -            },
        -            "dist": {
        -              "description": "RUNNING and SWIMMING: measure this rep by distance in metres (2000 for 2 km on the road, 100 for a pool rep) instead of time; time is derived from the target pace. For SWIMMING this is the normal case — a set is written in metres, never in minutes. Give either dur or dist, not both.",
        -              "maximum": 50000,
        -              "minimum": 25,
        -              "type": "integer"
        -            },
        -            "dur": {
        -              "description": "seconds (omit when using dist)",
        -              "exclusiveMinimum": 0,
        -              "maximum": 9007199254740991,
        -              "type": "integer"
        -            },
        -            "gear": {
        -              "description": "SWIMMING: paddles | buoy | fins | board | snorkel",
        -              "items": {
        -                "enum": [
        -                  "paddles",
        -                  "buoy",
        -                  "fins",
        -                  "board",
        -                  "snorkel"
        -                ],
        -                "type": "string"
        -              },
        -              "maxItems": 3,
        -              "type": "array"
        -            },
        -            "label": {
        -              "maxLength": 80,
        -              "type": "string"
        -            },
        -            "maxHr": {
        -              "description": "heart-rate ceiling, bpm: over it the trainer autopilot takes watts off",
        -              "maximum": 220,
        -              "minimum": 80,
        -              "type": "integer"
        -            },
        -            "maxRpe": {
        -              "description": "RPE ceiling (1-10): a rating over it, asked or tapped mid-step, takes watts off this step",
        -              "maximum": 10,
        -              "minimum": 1,
        -              "type": "integer"
        -            },
        -            "maxW": {
        -              "description": "CYCLING: the most watts ERG may hold on this step (a ceiling, e.g. 190 on an easy ride). Put limits HERE, not in the label or note — the trainer autopilot reads this field",
        -              "maximum": 2000,
        -              "minimum": 50,
        -              "type": "integer"
        -            },
        -            "mode": {
        -              "description": "SWIMMING: swim (default) | kick | pull | drill",
        -              "enum": [
        -                "swim",
        -                "kick",
        -                "pull",
        -                "drill"
        -              ],
        -              "type": "string"
        -            },
        -            "open": {
        -              "description": "a maximal effort (test, all-out) — no target on the device; power stays as the expected level",
        -              "type": "boolean"
        -            },
        -            "power": {
        -              "description": "%FTP (cycling) or %threshold pace (running) or %CSS (swimming — 100 = their CSS pace, below 100 = slower/easier, e.g. 92 for an aerobic set)",
        -              "maximum": 200,
        -              "minimum": 30,
        -              "type": "number"
        -            },
        -            "sft": {
        -              "description": "true = the athlete's SFT: load and length come from their profile at export; follow it with 60 s easy",
        -              "type": "boolean"
        -            },
        -            "stroke": {
        -              "description": "SWIMMING: free (default) | back | breast | fly | im | choice",
        -              "enum": [
        -                "free",
        -                "back",
        -                "breast",
        -                "fly",
        -                "im",
        -                "choice"
        -              ],
        -              "type": "string"
        -            },
        -            "target": {
        -              "description": "this step's own device target, over the session's",
        -              "enum": [
        -                "power",
        -                "pace",
        -                "hr",
        -                "rpe"
        -              ],
        -              "type": "string"
        -            },
        -            "untilLap": {
        -              "description": "the step ends when the athlete presses Lap",
        -              "type": "boolean"
        -            },
        -            "zone": {
        -              "enum": [
        -                "recovery",
        -                "endurance",
        -                "tempo",
        -                "threshold",
        -                "vo2",
        -                "sprint"
        -              ],
        -              "type": "string"
        -            }
        -          },
        -          "required": [
        -            "zone",
        -            "power"
        -          ],
        -          "type": "object"
        -        },
        -        "minItems": 1,
        -        "type": "array"
        -      },
        -      "reps": {
        -        "maximum": 30,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "sendoff": {
        -        "description": "SWIMMING: the send-off in seconds — the whole cycle, swim PLUS rest (\"10×100 on 1:40\" = 100). Rest is what is left of it. Use this OR a rest step inside the set, never both: they are two different sessions, and on a send-off swimming faster buys rest instead of ending the interval sooner.",
        -        "maximum": 1800,
        -        "minimum": 10,
        -        "type": "integer"
        -      },
        -      "type": {
        -        "const": "repeat",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "reps",
        -      "children"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "properties": {
        -      "cad": {
        -        "description": "target cadence rpm",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dist": {
        -        "description": "RUNNING and SWIMMING: measure this rep by distance in metres (2000 for 2 km on the road, 100 for a pool rep) instead of time; time is derived from the target pace. For SWIMMING this is the normal case — a set is written in metres, never in minutes. Give either dur or dist, not both.",
        -        "maximum": 50000,
        -        "minimum": 25,
        -        "type": "integer"
        -      },
        -      "dur": {
        -        "description": "seconds (omit when using dist)",
        -        "exclusiveMinimum": 0,
        -        "maximum": 9007199254740991,
        -        "type": "integer"
        -      },
        -      "gear": {
        -        "description": "SWIMMING: paddles | buoy | fins | board | snorkel",
        -        "items": {
        -          "enum": [
        -            "paddles",
        -            "buoy",
        -            "fins",
        -            "board",
        -            "snorkel"
        -          ],
        -          "type": "string"
        -        },
        -        "maxItems": 3,
        -        "type": "array"
        -      },
        -      "label": {
        -        "maxLength": 80,
        -        "type": "string"
        -      },
        -      "maxHr": {
        -        "description": "heart-rate ceiling, bpm: over it the trainer autopilot takes watts off",
        -        "maximum": 220,
        -        "minimum": 80,
        -        "type": "integer"
        -      },
        -      "maxRpe": {
        -        "description": "RPE ceiling (1-10): a rating over it, asked or tapped mid-step, takes watts off this step",
        -        "maximum": 10,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "maxW": {
        -        "description": "CYCLING: the most watts ERG may hold on this step (a ceiling, e.g. 190 on an easy ride). Put limits HERE, not in the label or note — the trainer autopilot reads this field",
        -        "maximum": 2000,
        -        "minimum": 50,
        -        "type": "integer"
        -      },
        -      "mode": {
        -        "description": "SWIMMING: swim (default) | kick | pull | drill",
        -        "enum": [
        -          "swim",
        -          "kick",
        -          "pull",
        -          "drill"
        -        ],
        -        "type": "string"
        -      },
        -      "open": {
        -        "description": "a maximal effort (test, all-out) — no target on the device; power stays as the expected level",
        -        "type": "boolean"
        -      },
        -      "power": {
        -        "description": "%FTP (cycling) or %threshold pace (running) or %CSS (swimming — 100 = their CSS pace, below 100 = slower/easier, e.g. 92 for an aerobic set)",
        -        "maximum": 200,
        -        "minimum": 30,
        -        "type": "number"
        -      },
        -      "sft": {
        -        "description": "true = the athlete's SFT: load and length come from their profile at export; follow it with 60 s easy",
        -        "type": "boolean"
        -      },
        -      "stroke": {
        -        "description": "SWIMMING: free (default) | back | breast | fly | im | choice",
        -        "enum": [
        -          "free",
        -          "back",
        -          "breast",
        -          "fly",
        -          "im",
        -          "choice"
        -        ],
        -        "type": "string"
        -      },
        -      "target": {
        -        "description": "this step's own device target, over the session's",
        -        "enum": [
        -          "power",
        -          "pace",
        -          "hr",
        -          "rpe"
        -        ],
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "steady",
        -        "type": "string"
        -      },
        -      "untilLap": {
        -        "description": "the step ends when the athlete presses Lap",
        -        "type": "boolean"
        -      },
        -      "zone": {
        -        "enum": [
        -          "recovery",
        -          "endurance",
        -          "tempo",
        -          "threshold",
        -          "vo2",
        -          "sprint"
        -        ],
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "zone",
        -      "power"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "properties": {
        +      "children": {
        +        "items": {
        +          "properties": {
        +            "cad": {
        +              "description": "target cadence rpm",
        +              "maximum": 9007199254740991,
        +              "minimum": -9007199254740991,
        +              "type": "integer"
        +            },
        +            "dist": {
        +              "description": "RUNNING and SWIMMING: measure this rep by distance in metres (2000 for 2 km on the road, 100 for a pool rep) instead of time; time is derived from the target pace. For SWIMMING this is the normal case — a set is written in metres, never in minutes. Give either dur or dist, not both.",
        +              "maximum": 50000,
        +              "minimum": 25,
        +              "type": "integer"
        +            },
        +            "dur": {
        +              "description": "seconds (omit when using dist)",
        +              "exclusiveMinimum": 0,
        +              "maximum": 9007199254740991,
        +              "type": "integer"
        +            },
        +            "gear": {
        +              "description": "SWIMMING: paddles | buoy | fins | board | snorkel",
        +              "items": {
        +                "enum": [
        +                  "paddles",
        +                  "buoy",
        +                  "fins",
        +                  "board",
        +                  "snorkel"
        +                ],
        +                "type": "string"
        +              },
        +              "maxItems": 3,
        +              "type": "array"
        +            },
        +            "hr": {
        +              "description": "the athlete's own HR corridor for this step, bpm (\"135-145\") — over the zone's band on the card, the watch and the autopilot; only when they named one",
        +              "properties": {
        +                "hi": {
        +                  "maximum": 220,
        +                  "minimum": 61,
        +                  "type": "integer"
        +                },
        +                "lo": {
        +                  "maximum": 219,
        +                  "minimum": 60,
        +                  "type": "integer"
        +                }
        +              },
        +              "required": [
        +                "lo",
        +                "hi"
        +              ],
        +              "type": "object"
        +            },
        +            "label": {
        +              "maxLength": 80,
        +              "type": "string"
        +            },
        +            "maxHr": {
        +              "description": "heart-rate ceiling, bpm: over it the trainer autopilot takes watts off",
        +              "maximum": 220,
        +              "minimum": 80,
        +              "type": "integer"
        +            },
        +            "maxRpe": {
        +              "description": "RPE ceiling (1-10): a rating over it, asked or tapped mid-step, takes watts off this step",
        +              "maximum": 10,
        +              "minimum": 1,
        +              "type": "integer"
        +            },
        +            "maxW": {
        +              "description": "CYCLING: the most watts ERG may hold on this step (a ceiling, e.g. 190 on an easy ride). Put limits HERE, not in the label or note — the trainer autopilot reads this field",
        +              "maximum": 2000,
        +              "minimum": 50,
        +              "type": "integer"
        +            },
        +            "mode": {
        +              "description": "SWIMMING: swim (default) | kick | pull | drill",
        +              "enum": [
        +                "swim",
        +                "kick",
        +                "pull",
        +                "drill"
        +              ],
        +              "type": "string"
        +            },
        +            "open": {
        +              "description": "a maximal effort (test, all-out) — no target on the device; power stays as the expected level",
        +              "type": "boolean"
        +            },
        +            "power": {
        +              "description": "%FTP (cycling) or %threshold pace (running) or %CSS (swimming — 100 = their CSS pace, below 100 = slower/easier, e.g. 92 for an aerobic set)",
        +              "maximum": 200,
        +              "minimum": 30,
        +              "type": "number"
        +            },
        +            "sft": {
        +              "description": "true = the athlete's SFT: load and length come from their profile at export; follow it with 60 s easy",
        +              "type": "boolean"
        +            },
        +            "stroke": {
        +              "description": "SWIMMING: free (default) | back | breast | fly | im | choice",
        +              "enum": [
        +                "free",
        +                "back",
        +                "breast",
        +                "fly",
        +                "im",
        +                "choice"
        +              ],
        +              "type": "string"
        +            },
        +            "target": {
        +              "description": "this step's own device target, over the session's",
        +              "enum": [
        +                "power",
        +                "pace",
        +                "hr",
        +                "rpe"
        +              ],
        +              "type": "string"
        +            },
        +            "untilLap": {
        +              "description": "the step ends when the athlete presses Lap",
        +              "type": "boolean"
        +            },
        +            "zone": {
        +              "enum": [
        +                "recovery",
        +                "endurance",
        +                "tempo",
        +                "threshold",
        +                "vo2",
        +                "sprint"
        +              ],
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "zone",
        +            "power"
        +          ],
        +          "type": "object"
        +        },
        +        "minItems": 1,
        +        "type": "array"
        +      },
        +      "reps": {
        +        "maximum": 30,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "sendoff": {
        +        "description": "SWIMMING: the send-off in seconds — the whole cycle, swim PLUS rest (\"10×100 on 1:40\" = 100). Rest is what is left of it. Use this OR a rest step inside the set, never both: they are two different sessions, and on a send-off swimming faster buys rest instead of ending the interval sooner.",
        +        "maximum": 1800,
        +        "minimum": 10,
        +        "type": "integer"
        +      },
        +      "type": {
        +        "const": "repeat",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "reps",
        +      "children"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "properties": {
        +      "cad": {
        +        "description": "target cadence rpm",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dist": {
        +        "description": "RUNNING and SWIMMING: measure this rep by distance in metres (2000 for 2 km on the road, 100 for a pool rep) instead of time; time is derived from the target pace. For SWIMMING this is the normal case — a set is written in metres, never in minutes. Give either dur or dist, not both.",
        +        "maximum": 50000,
        +        "minimum": 25,
        +        "type": "integer"
        +      },
        +      "dur": {
        +        "description": "seconds (omit when using dist)",
        +        "exclusiveMinimum": 0,
        +        "maximum": 9007199254740991,
        +        "type": "integer"
        +      },
        +      "gear": {
        +        "description": "SWIMMING: paddles | buoy | fins | board | snorkel",
        +        "items": {
        +          "enum": [
        +            "paddles",
        +            "buoy",
        +            "fins",
        +            "board",
        +            "snorkel"
        +          ],
        +          "type": "string"
        +        },
        +        "maxItems": 3,
        +        "type": "array"
        +      },
        +      "hr": {
        +        "description": "the athlete's own HR corridor for this step, bpm (\"135-145\") — over the zone's band on the card, the watch and the autopilot; only when they named one",
        +        "properties": {
        +          "hi": {
        +            "maximum": 220,
        +            "minimum": 61,
        +            "type": "integer"
        +          },
        +          "lo": {
        +            "maximum": 219,
        +            "minimum": 60,
        +            "type": "integer"
        +          }
        +        },
        +        "required": [
        +          "lo",
        +          "hi"
        +        ],
        +        "type": "object"
        +      },
        +      "label": {
        +        "maxLength": 80,
        +        "type": "string"
        +      },
        +      "maxHr": {
        +        "description": "heart-rate ceiling, bpm: over it the trainer autopilot takes watts off",
        +        "maximum": 220,
        +        "minimum": 80,
        +        "type": "integer"
        +      },
        +      "maxRpe": {
        +        "description": "RPE ceiling (1-10): a rating over it, asked or tapped mid-step, takes watts off this step",
        +        "maximum": 10,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "maxW": {
        +        "description": "CYCLING: the most watts ERG may hold on this step (a ceiling, e.g. 190 on an easy ride). Put limits HERE, not in the label or note — the trainer autopilot reads this field",
        +        "maximum": 2000,
        +        "minimum": 50,
        +        "type": "integer"
        +      },
        +      "mode": {
        +        "description": "SWIMMING: swim (default) | kick | pull | drill",
        +        "enum": [
        +          "swim",
        +          "kick",
        +          "pull",
        +          "drill"
        +        ],
        +        "type": "string"
        +      },
        +      "open": {
        +        "description": "a maximal effort (test, all-out) — no target on the device; power stays as the expected level",
        +        "type": "boolean"
        +      },
        +      "power": {
        +        "description": "%FTP (cycling) or %threshold pace (running) or %CSS (swimming — 100 = their CSS pace, below 100 = slower/easier, e.g. 92 for an aerobic set)",
        +        "maximum": 200,
        +        "minimum": 30,
        +        "type": "number"
        +      },
        +      "sft": {
        +        "description": "true = the athlete's SFT: load and length come from their profile at export; follow it with 60 s easy",
        +        "type": "boolean"
        +      },
        +      "stroke": {
        +        "description": "SWIMMING: free (default) | back | breast | fly | im | choice",
        +        "enum": [
        +          "free",
        +          "back",
        +          "breast",
        +          "fly",
        +          "im",
        +          "choice"
        +        ],
        +        "type": "string"
        +      },
        +      "target": {
        +        "description": "this step's own device target, over the session's",
        +        "enum": [
        +          "power",
        +          "pace",
        +          "hr",
        +          "rpe"
        +        ],
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "steady",
        +        "type": "string"
        +      },
        +      "untilLap": {
        +        "description": "the step ends when the athlete presses Lap",
        +        "type": "boolean"
        +      },
        +      "zone": {
        +        "enum": [
        +          "recovery",
        +          "endurance",
        +          "tempo",
        +          "threshold",
        +          "vo2",
        +          "sprint"
        +        ],
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "zone",
        +      "power"
        +    ],
        +    "type": "object"
        +  }
        +]
  5. 1 tool update
    • Changedupdate_athlete_profile1 field changed
      • addedInput schema / properties / suggestReviews
        Added value: +{
        +  "description": "post-session reviews (Profile → Assistant). For a Blocks Unlimited subscriber this is \"Automatic reviews\": Blocks reviews a finished training session on its own (20 min+, up to 2 a day, none at night) — false turns that off. For everyone else it is the offer of a review after a key session. Only when they ask.",
        +  "type": "boolean"
        +}
  6. 1 tool update
    • Changedget_readiness_today1 field changed
      • changedInput schema / properties / date / description
        Previous value: -"athlete-local YYYY-MM-DD; defaults to server UTC today"New value: +"athlete-local YYYY-MM-DD; defaults to the athlete's today"
  7. 1 tool update
    • Changedupdate_athlete_profile2 fields changed
      • addedInput schema / properties / control
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "what they TRAIN BY per sport (Profile \"You train by\"): the signal you judge and speak in — not the watch's default (running hr also sets runByHr); null = back to what their files show. Only when they say so.",
        +  "properties": {
        +    "cycling": {
        +      "anyOf": [
        +        {
        +          "enum": [
        +            "power",
        +            "hr",
        +            "rpe",
        +            "breath",
        +            "lactate"
        +          ],
        +          "type": "string"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ]
        +    },
        +    "running": {
        +      "anyOf": [
        +        {
        +          "enum": [
        +            "pace",
        +            "hr",
        +            "rpe",
        +            "breath",
        +            "lactate"
        +          ],
        +          "type": "string"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ]
        +    },
        +    "swim": {
        +      "anyOf": [
        +        {
        +          "enum": [
        +            "pace",
        +            "rpe"
        +          ],
        +          "type": "string"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ]
        +    }
        +  },
        +  "type": "object"
        +}
      • changedInput schema / properties / runByHr / description
        Previous value: -"true = runs default to HR targets"New value: +"true = runs default to HR targets on the watch (= control.running \"hr\")"
  8. 2 tool updates
    • Changedplan_workouts1 field changed
      • changedInput schema / properties / items / items / properties / workout / properties / strength / items / anyOf
        Previous value: -[
        -  {
        -    "properties": {
        -      "mode": {
        -        "description": "kg = weight×reps, sec = timed hold/effort, m = distance-based",
        -        "enum": [
        -          "kg",
        -          "sec",
        -          "m"
        -        ],
        -        "type": "string"
        -      },
        -      "name": {
        -        "description": "exercise name, e.g. 'Back squat', 'Sled push'",
        -        "maxLength": 80,
        -        "type": "string"
        -      },
        -      "note": {
        -        "description": "optional cue: target HR, technique focus",
        -        "maxLength": 300,
        -        "type": "string"
        -      },
        -      "reps": {
        -        "description": "kg mode only",
        -        "maximum": 1000,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "rpe": {
        -        "description": "target RPE 1-10 — REQUIRED on kg work, because RPE is the actual prescription and the weight is at most a starting suggestion they autoregulate from",
        -        "maximum": 10,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "sets": {
        -        "maximum": 50,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "type": {
        -        "const": "ex",
        -        "type": "string"
        -      },
        -      "val": {
        -        "description": "kg → weight; sec → seconds; m → metres. FOR kg: 0 MEANS NO WEIGHT PRESCRIBED, and 0 is the right answer unless you actually know what they own (a fact tagged 'equipment', or they named a number in this conversation). Do not guess a round figure — an athlete with 9 kg dumbbells reads your invented 10 kg as an instruction they cannot follow. Write 0, prescribe the RPE, and say in your reply that they pick the weight.",
        -        "maximum": 100000,
        -        "minimum": 0,
        -        "type": "number"
        -      }
        -    },
        -    "required": [
        -      "name",
        -      "mode",
        -      "val",
        -      "sets"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "properties": {
        -      "ex": {
        -        "items": {
        -          "properties": {
        -            "mode": {
        -              "description": "kg = weight×reps, sec = timed hold/effort, m = distance-based",
        -              "enum": [
        -                "kg",
        -                "sec",
        -                "m"
        -              ],
        -              "type": "string"
        -            },
        -            "name": {
        -              "description": "exercise name, e.g. 'Back squat', 'Sled push'",
        -              "maxLength": 80,
        -              "type": "string"
        -            },
        -            "note": {
        -              "description": "optional cue: target HR, technique focus",
        -              "maxLength": 300,
        -              "type": "string"
        -            },
        -            "reps": {
        -              "description": "kg mode only",
        -              "maximum": 1000,
        -              "minimum": 1,
        -              "type": "integer"
        -            },
        -            "rpe": {
        -              "description": "target RPE 1-10 — REQUIRED on kg work, because RPE is the actual prescription and the weight is at most a starting suggestion they autoregulate from",
        -              "maximum": 10,
        -              "minimum": 1,
        -              "type": "integer"
        -            },
        -            "val": {
        -              "description": "kg → weight; sec → seconds; m → metres. FOR kg: 0 MEANS NO WEIGHT PRESCRIBED, and 0 is the right answer unless you actually know what they own (a fact tagged 'equipment', or they named a number in this conversation). Do not guess a round figure — an athlete with 9 kg dumbbells reads your invented 10 kg as an instruction they cannot follow. Write 0, prescribe the RPE, and say in your reply that they pick the weight.",
        -              "maximum": 100000,
        -              "minimum": 0,
        -              "type": "number"
        -            }
        -          },
        -          "required": [
        -            "name",
        -            "mode",
        -            "val"
        -          ],
        -          "type": "object"
        -        },
        -        "maxItems": 8,
        -        "minItems": 1,
        -        "type": "array"
        -      },
        -      "sets": {
        -        "description": "shared rounds for the whole superset",
        -        "maximum": 50,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "type": {
        -        "const": "ss",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "sets",
        -      "ex"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "properties": {
        +      "mode": {
        +        "description": "kg = weight×reps, sec = timed hold/effort, m = distance-based",
        +        "enum": [
        +          "kg",
        +          "sec",
        +          "m"
        +        ],
        +        "type": "string"
        +      },
        +      "name": {
        +        "description": "exercise name, e.g. 'Back squat', 'Sled push'",
        +        "maxLength": 80,
        +        "type": "string"
        +      },
        +      "note": {
        +        "description": "optional cue: target HR, technique focus",
        +        "maxLength": 300,
        +        "type": "string"
        +      },
        +      "reps": {
        +        "description": "kg mode only",
        +        "maximum": 1000,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "rpe": {
        +        "description": "target RPE 1-10 — REQUIRED on kg work, because RPE is the actual prescription and the weight is at most a starting suggestion they autoregulate from",
        +        "maximum": 10,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "sets": {
        +        "maximum": 50,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "type": {
        +        "const": "ex",
        +        "type": "string"
        +      },
        +      "unit": {
        +        "description": "lb = this exercise's weight is in pounds (their dumbbells or a machine in lb); omit for kg. Keep the unit the athlete logs it in",
        +        "enum": [
        +          "lb"
        +        ],
        +        "type": "string"
        +      },
        +      "val": {
        +        "description": "kg → weight; sec → seconds; m → metres. FOR kg: 0 MEANS NO WEIGHT PRESCRIBED, and 0 is the right answer unless you actually know what they own (a fact tagged 'equipment', or they named a number in this conversation). Do not guess a round figure — an athlete with 9 kg dumbbells reads your invented 10 kg as an instruction they cannot follow. Write 0, prescribe the RPE, and say in your reply that they pick the weight.",
        +        "maximum": 100000,
        +        "minimum": 0,
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "name",
        +      "mode",
        +      "val",
        +      "sets"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "properties": {
        +      "ex": {
        +        "items": {
        +          "properties": {
        +            "mode": {
        +              "description": "kg = weight×reps, sec = timed hold/effort, m = distance-based",
        +              "enum": [
        +                "kg",
        +                "sec",
        +                "m"
        +              ],
        +              "type": "string"
        +            },
        +            "name": {
        +              "description": "exercise name, e.g. 'Back squat', 'Sled push'",
        +              "maxLength": 80,
        +              "type": "string"
        +            },
        +            "note": {
        +              "description": "optional cue: target HR, technique focus",
        +              "maxLength": 300,
        +              "type": "string"
        +            },
        +            "reps": {
        +              "description": "kg mode only",
        +              "maximum": 1000,
        +              "minimum": 1,
        +              "type": "integer"
        +            },
        +            "rpe": {
        +              "description": "target RPE 1-10 — REQUIRED on kg work, because RPE is the actual prescription and the weight is at most a starting suggestion they autoregulate from",
        +              "maximum": 10,
        +              "minimum": 1,
        +              "type": "integer"
        +            },
        +            "unit": {
        +              "description": "lb = this exercise's weight is in pounds (their dumbbells or a machine in lb); omit for kg. Keep the unit the athlete logs it in",
        +              "enum": [
        +                "lb"
        +              ],
        +              "type": "string"
        +            },
        +            "val": {
        +              "description": "kg → weight; sec → seconds; m → metres. FOR kg: 0 MEANS NO WEIGHT PRESCRIBED, and 0 is the right answer unless you actually know what they own (a fact tagged 'equipment', or they named a number in this conversation). Do not guess a round figure — an athlete with 9 kg dumbbells reads your invented 10 kg as an instruction they cannot follow. Write 0, prescribe the RPE, and say in your reply that they pick the weight.",
        +              "maximum": 100000,
        +              "minimum": 0,
        +              "type": "number"
        +            }
        +          },
        +          "required": [
        +            "name",
        +            "mode",
        +            "val"
        +          ],
        +          "type": "object"
        +        },
        +        "maxItems": 8,
        +        "minItems": 1,
        +        "type": "array"
        +      },
        +      "sets": {
        +        "description": "shared rounds for the whole superset",
        +        "maximum": 50,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "type": {
        +        "const": "ss",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "sets",
        +      "ex"
        +    ],
        +    "type": "object"
        +  }
        +]
    • Changedupdate_plan_workout1 field changed
      • changedInput schema / properties / strength / items / anyOf
        Previous value: -[
        -  {
        -    "properties": {
        -      "mode": {
        -        "description": "kg = weight×reps, sec = timed hold/effort, m = distance-based",
        -        "enum": [
        -          "kg",
        -          "sec",
        -          "m"
        -        ],
        -        "type": "string"
        -      },
        -      "name": {
        -        "description": "exercise name, e.g. 'Back squat', 'Sled push'",
        -        "maxLength": 80,
        -        "type": "string"
        -      },
        -      "note": {
        -        "description": "optional cue: target HR, technique focus",
        -        "maxLength": 300,
        -        "type": "string"
        -      },
        -      "reps": {
        -        "description": "kg mode only",
        -        "maximum": 1000,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "rpe": {
        -        "description": "target RPE 1-10 — REQUIRED on kg work, because RPE is the actual prescription and the weight is at most a starting suggestion they autoregulate from",
        -        "maximum": 10,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "sets": {
        -        "maximum": 50,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "type": {
        -        "const": "ex",
        -        "type": "string"
        -      },
        -      "val": {
        -        "description": "kg → weight; sec → seconds; m → metres. FOR kg: 0 MEANS NO WEIGHT PRESCRIBED, and 0 is the right answer unless you actually know what they own (a fact tagged 'equipment', or they named a number in this conversation). Do not guess a round figure — an athlete with 9 kg dumbbells reads your invented 10 kg as an instruction they cannot follow. Write 0, prescribe the RPE, and say in your reply that they pick the weight.",
        -        "maximum": 100000,
        -        "minimum": 0,
        -        "type": "number"
        -      }
        -    },
        -    "required": [
        -      "name",
        -      "mode",
        -      "val",
        -      "sets"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "properties": {
        -      "ex": {
        -        "items": {
        -          "properties": {
        -            "mode": {
        -              "description": "kg = weight×reps, sec = timed hold/effort, m = distance-based",
        -              "enum": [
        -                "kg",
        -                "sec",
        -                "m"
        -              ],
        -              "type": "string"
        -            },
        -            "name": {
        -              "description": "exercise name, e.g. 'Back squat', 'Sled push'",
        -              "maxLength": 80,
        -              "type": "string"
        -            },
        -            "note": {
        -              "description": "optional cue: target HR, technique focus",
        -              "maxLength": 300,
        -              "type": "string"
        -            },
        -            "reps": {
        -              "description": "kg mode only",
        -              "maximum": 1000,
        -              "minimum": 1,
        -              "type": "integer"
        -            },
        -            "rpe": {
        -              "description": "target RPE 1-10 — REQUIRED on kg work, because RPE is the actual prescription and the weight is at most a starting suggestion they autoregulate from",
        -              "maximum": 10,
        -              "minimum": 1,
        -              "type": "integer"
        -            },
        -            "val": {
        -              "description": "kg → weight; sec → seconds; m → metres. FOR kg: 0 MEANS NO WEIGHT PRESCRIBED, and 0 is the right answer unless you actually know what they own (a fact tagged 'equipment', or they named a number in this conversation). Do not guess a round figure — an athlete with 9 kg dumbbells reads your invented 10 kg as an instruction they cannot follow. Write 0, prescribe the RPE, and say in your reply that they pick the weight.",
        -              "maximum": 100000,
        -              "minimum": 0,
        -              "type": "number"
        -            }
        -          },
        -          "required": [
        -            "name",
        -            "mode",
        -            "val"
        -          ],
        -          "type": "object"
        -        },
        -        "maxItems": 8,
        -        "minItems": 1,
        -        "type": "array"
        -      },
        -      "sets": {
        -        "description": "shared rounds for the whole superset",
        -        "maximum": 50,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "type": {
        -        "const": "ss",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "sets",
        -      "ex"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "properties": {
        +      "mode": {
        +        "description": "kg = weight×reps, sec = timed hold/effort, m = distance-based",
        +        "enum": [
        +          "kg",
        +          "sec",
        +          "m"
        +        ],
        +        "type": "string"
        +      },
        +      "name": {
        +        "description": "exercise name, e.g. 'Back squat', 'Sled push'",
        +        "maxLength": 80,
        +        "type": "string"
        +      },
        +      "note": {
        +        "description": "optional cue: target HR, technique focus",
        +        "maxLength": 300,
        +        "type": "string"
        +      },
        +      "reps": {
        +        "description": "kg mode only",
        +        "maximum": 1000,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "rpe": {
        +        "description": "target RPE 1-10 — REQUIRED on kg work, because RPE is the actual prescription and the weight is at most a starting suggestion they autoregulate from",
        +        "maximum": 10,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "sets": {
        +        "maximum": 50,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "type": {
        +        "const": "ex",
        +        "type": "string"
        +      },
        +      "unit": {
        +        "description": "lb = this exercise's weight is in pounds (their dumbbells or a machine in lb); omit for kg. Keep the unit the athlete logs it in",
        +        "enum": [
        +          "lb"
        +        ],
        +        "type": "string"
        +      },
        +      "val": {
        +        "description": "kg → weight; sec → seconds; m → metres. FOR kg: 0 MEANS NO WEIGHT PRESCRIBED, and 0 is the right answer unless you actually know what they own (a fact tagged 'equipment', or they named a number in this conversation). Do not guess a round figure — an athlete with 9 kg dumbbells reads your invented 10 kg as an instruction they cannot follow. Write 0, prescribe the RPE, and say in your reply that they pick the weight.",
        +        "maximum": 100000,
        +        "minimum": 0,
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "name",
        +      "mode",
        +      "val",
        +      "sets"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "properties": {
        +      "ex": {
        +        "items": {
        +          "properties": {
        +            "mode": {
        +              "description": "kg = weight×reps, sec = timed hold/effort, m = distance-based",
        +              "enum": [
        +                "kg",
        +                "sec",
        +                "m"
        +              ],
        +              "type": "string"
        +            },
        +            "name": {
        +              "description": "exercise name, e.g. 'Back squat', 'Sled push'",
        +              "maxLength": 80,
        +              "type": "string"
        +            },
        +            "note": {
        +              "description": "optional cue: target HR, technique focus",
        +              "maxLength": 300,
        +              "type": "string"
        +            },
        +            "reps": {
        +              "description": "kg mode only",
        +              "maximum": 1000,
        +              "minimum": 1,
        +              "type": "integer"
        +            },
        +            "rpe": {
        +              "description": "target RPE 1-10 — REQUIRED on kg work, because RPE is the actual prescription and the weight is at most a starting suggestion they autoregulate from",
        +              "maximum": 10,
        +              "minimum": 1,
        +              "type": "integer"
        +            },
        +            "unit": {
        +              "description": "lb = this exercise's weight is in pounds (their dumbbells or a machine in lb); omit for kg. Keep the unit the athlete logs it in",
        +              "enum": [
        +                "lb"
        +              ],
        +              "type": "string"
        +            },
        +            "val": {
        +              "description": "kg → weight; sec → seconds; m → metres. FOR kg: 0 MEANS NO WEIGHT PRESCRIBED, and 0 is the right answer unless you actually know what they own (a fact tagged 'equipment', or they named a number in this conversation). Do not guess a round figure — an athlete with 9 kg dumbbells reads your invented 10 kg as an instruction they cannot follow. Write 0, prescribe the RPE, and say in your reply that they pick the weight.",
        +              "maximum": 100000,
        +              "minimum": 0,
        +              "type": "number"
        +            }
        +          },
        +          "required": [
        +            "name",
        +            "mode",
        +            "val"
        +          ],
        +          "type": "object"
        +        },
        +        "maxItems": 8,
        +        "minItems": 1,
        +        "type": "array"
        +      },
        +      "sets": {
        +        "description": "shared rounds for the whole superset",
        +        "maximum": 50,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "type": {
        +        "const": "ss",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "sets",
        +      "ex"
        +    ],
        +    "type": "object"
        +  }
        +]
  9. 2 tool updates
    • Changedget_metric_history1 field changed
      • changedInput schema / properties / kinds / items / enum
        Previous value: -[
        -  "ftp",
        -  "thrPace",
        -  "lthrBike",
        -  "lthrRun",
        -  "maxHrBike",
        -  "maxHrRun",
        -  "weightKg",
        -  "vo2max",
        -  "map",
        -  "lt1",
        -  "lt2",
        -  "lactate",
        -  "ferritin",
        -  "hb",
        -  "rhr",
        -  "hrv"
        -]New value: +[
        +  "ftp",
        +  "thrPace",
        +  "lthrBike",
        +  "lthrRun",
        +  "maxHrBike",
        +  "maxHrRun",
        +  "weightKg",
        +  "vo2max",
        +  "map",
        +  "lt1",
        +  "lt2",
        +  "lactate",
        +  "ferritin",
        +  "hb",
        +  "rhr",
        +  "hrv",
        +  "cssPace",
        +  "runCp"
        +]
    • Changedlog_metric1 field changed
      • changedInput schema / properties / items / items / properties / kind / enum
        Previous value: -[
        -  "ftp",
        -  "thrPace",
        -  "lthrBike",
        -  "lthrRun",
        -  "maxHrBike",
        -  "maxHrRun",
        -  "weightKg",
        -  "vo2max",
        -  "map",
        -  "lt1",
        -  "lt2",
        -  "lactate",
        -  "ferritin",
        -  "hb",
        -  "rhr",
        -  "hrv"
        -]New value: +[
        +  "ftp",
        +  "thrPace",
        +  "lthrBike",
        +  "lthrRun",
        +  "maxHrBike",
        +  "maxHrRun",
        +  "weightKg",
        +  "vo2max",
        +  "map",
        +  "lt1",
        +  "lt2",
        +  "lactate",
        +  "ferritin",
        +  "hb",
        +  "rhr",
        +  "hrv",
        +  "cssPace",
        +  "runCp"
        +]
  10. 3 tool updates
    • Changedplan_workouts1 field changed
      • addedInput schema / properties / items / items / properties / time
        Added value: +{
        +  "description": "HH:MM start — set it when the day holds more than one session; the calendar orders the day by it",
        +  "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$",
        +  "type": "string"
        +}
    • Changedupdate_plan_workout1 field changed
      • addedInput schema / properties / time
        Added value: +{
        +  "description": "HH:MM start of day; empty string clears",
        +  "pattern": "^(([01]\\d|2[0-3]):[0-5]\\d)?$",
        +  "type": "string"
        +}
    • Changedupdate_plan_workouts1 field changed
      • addedInput schema / properties / edits / items / properties / time
        Added value: +{
        +  "pattern": "^(([01]\\d|2[0-3]):[0-5]\\d)?$",
        +  "type": "string"
        +}
  11. 1 tool update
    • Addedupdate_plan_workouts
  12. 2 tool updates
    • Addedlink_exercises
    • Changedlog_sft_answers7 fields changed
      • removedInput schema / properties / activity_id / description
        Removed value: -"the session that held the test (id from list_activities)"
      • removedInput schema / properties / date / description
        Removed value: -"the test's day, when there is no session id"
      • changedInput schema / properties / hr / description
        Previous value: -"last-minute heart rate, when the app did not read the test"New value: +"last-minute HR"
      • changedInput schema / properties / hrr / description
        Previous value: -"heart-rate drop in the minute after"New value: +"HR drop in the minute after"
      • changedInput schema / properties / minutesLeft / description
        Previous value: -"minutes more they could have held it; rounded to 0.5"New value: +"minutes more they could have held it"
      • changedInput schema / properties / rpe / description
        Previous value: -"how hard the test felt, 0-10"New value: +"how hard the test felt"
      • removedInput schema / properties / sport / description
        Removed value: -"with date"
  13. 3 tool updates
    • Changedplan_workouts2 fields changed
      • changedInput schema / properties / items / items / properties / note / description
        Previous value: -"optional short note (a few words)"New value: +"optional session brief — how to ride it, fuelling (tight)"
      • changedInput schema / properties / items / items / properties / note / maxLength
        Previous value: -140New value: +500
    • Changedset_workout_note1 field changed
      • changedInput schema / properties / note / maxLength
        Previous value: -140New value: +500
    • Changedupdate_plan_workout1 field changed
      • changedInput schema / properties / note / maxLength
        Previous value: -140New value: +500
  14. 1 tool update
    • Changedlog_sft_answers6 fields changed
      • addedInput schema / properties / date
        Added value: +{
        +  "description": "the test's day, when there is no session id",
        +  "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
        +  "type": "string"
        +}
      • addedInput schema / properties / hr
        Added value: +{
        +  "description": "last-minute heart rate, when the app did not read the test",
        +  "maximum": 230,
        +  "minimum": 60,
        +  "type": "integer"
        +}
      • addedInput schema / properties / hrr
        Added value: +{
        +  "description": "heart-rate drop in the minute after",
        +  "maximum": 120,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • addedInput schema / properties / note
        Added value: +{
        +  "maxLength": 300,
        +  "type": "string"
        +}
      • addedInput schema / properties / sport
        Added value: +{
        +  "description": "with date",
        +  "enum": [
        +    "cycling",
        +    "running"
        +  ],
        +  "type": "string"
        +}
      • removedInput schema / required
        Removed value: -[
        -  "activity_id"
        -]
  15. 2 tool updates
    • Changedplan_workouts1 field changed
      • changedInput schema / properties / items / items / properties / goal / description
        Previous value: -"WHY this session exists — one plain line the athlete reads right under its name (\"Raise the ceiling: repeatable efforts near VO2max.\"), not how to ride it. Give one for EVERY custom workout. A catalog workout already shows its own line, so pass this only when this placement has a reason of its own (\"Opener for Sunday's race.\")."New value: +"THE QUALITY this session trains — why it is in the plan — as a short phrase that LEADS with the quality, in the athlete's language: «Аэробная база», «МПК: поднять потолок», «Порог: гоночная мощность», «Силовая выносливость ног», «Экономичность бега», «Восстановление»; a test or race says what it is («Тест: лактатная шкала», «Гонка A»). Not the day's context (no «свежесть к Long», no pulse caps, no logistics) and not how to ride it — that is the note. Give one for EVERY custom workout; a catalog workout already shows its own, so pass this only to change it."
    • Changedupdate_plan_workout1 field changed
      • changedInput schema / properties / goal / description
        Previous value: -"WHY this session exists, one line under its name; empty string hands it back to the catalog workout's own line (or none)"New value: +"the QUALITY this session trains — why it is in the plan — a short phrase leading with the quality (as in plan_workouts); empty string hands it back to the catalog workout's own line (or none)"
  16. 2 tool updates
    • Changedplan_workouts1 field changed
      • addedInput schema / properties / items / items / properties / goal
        Added value: +{
        +  "description": "WHY this session exists — one plain line the athlete reads right under its name (\"Raise the ceiling: repeatable efforts near VO2max.\"), not how to ride it. Give one for EVERY custom workout. A catalog workout already shows its own line, so pass this only when this placement has a reason of its own (\"Opener for Sunday's race.\").",
        +  "maxLength": 140,
        +  "type": "string"
        +}
    • Changedupdate_plan_workout2 fields changed
      • addedInput schema / properties / fuelG
        Added value: +{
        +  "anyOf": [
        +    {
        +      "maximum": 2000,
        +      "minimum": 0,
        +      "type": "integer"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "description": "carbohydrate in GRAMS for the WHOLE session, overruling the app's own number for this one entry — a race rehearsal, a gut being trained up, an athlete who knows what they tolerate. The athlete sees one total, never a rate, so state it as a total. At most 120 g per hour of the session; 0 = water only; null hands it back to the formula. Leave it alone unless you have a reason the formula cannot see."
        +}
      • addedInput schema / properties / goal
        Added value: +{
        +  "description": "WHY this session exists, one line under its name; empty string hands it back to the catalog workout's own line (or none)",
        +  "maxLength": 140,
        +  "type": "string"
        +}
  17. 1 tool update
    • Addedlog_rpe_marks
  18. 1 tool update
    • Changedplan_workouts1 field changed
      • changedInput schema / properties / items / items / properties / workout / properties / strength / description
        Previous value: -"strength/gym only: exercises + supersets instead of blocks. No duration/TSS is computed for strength sessions."New value: +"strength/gym only: exercises + supersets instead of blocks. No duration/TSS is computed for strength sessions. Every exercise serves the athlete's goal — no plank/crunch \"core finishers\" for an endurance athlete unless they asked (the base shows no reliable endurance transfer)."

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    C
    maintenance
    AI-powered coaching for runners, cyclists, swimmers, and triathletes, enabling personalized workouts, training plan adaptation, performance analytics, and AI coaching via Claude, MCP clients, or HTTP.
    -
  • F
    license
    Not graded
    quality
    A
    maintenance
    Enables AI assistants to query and create workouts with structured intervals, manage calendars and events, analyze power PRs and CTL/ATL/TSB fitness trends, handle workout libraries, equipment and health metrics through natural language. Uses secure cookie-based authentication stored in the system keyring, so no API approval is required and any account can be set up in minutes.
    -
  • F
    license
    Not graded
    quality
    Not graded
    maintenance
    Connects AI assistants to fitness data from over 150 wearables including Strava, Garmin, and Fitbit through the Model Context Protocol. It provides 47 tools for sports science-based analysis, training load management, recovery tracking, and personalized nutrition planning.
    16
    -
Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources