fitatu-api
fitatu-api
An unofficial Python client for the API of Fitatu, the calorie
counter, built to be driven by AI agents and scripts. It reads and writes the food diary,
activities, body measurements and water, reads and sets goals, and reads summaries and the food
catalog.
FitatuTools turns the diary into tools a language model can call. The session handling
follows python-garminconnect: log in once,
keep one session file, let the client refresh it.
Unofficial. This project is not affiliated with or endorsed by Fitatu Sp. z o.o. The API was reverse-engineered from the Fitatu apps and can change without notice. Automated access may break Fitatu's Terms of Service; check them, and use the library only with your own account and at your own risk. The MIT licence covers this code, not the Fitatu service, its API or its data.
Install
Python 3.11 or newer; the only dependency is requests (and tzdata on Windows).
pip install fitatu-api # the library and the fitatu-api command
pip install "fitatu-api[mcp]" # plus fitatu-mcp, the MCP server
pip install "git+https://github.com/Jezue/fitatu_library" # unreleased changes from mainTo work on the library or run its tests offline, clone it instead: git clone https://github.com/Jezue/fitatu_library && cd fitatu_library && pip install -e ".[dev]".
Related MCP server: fatsecret-mcp-server
Quick start
fitatu-api login # asks for e-mail and password, writes ~/.fitatu/session.jsonSigned up with Apple or Facebook? Then the account has no password: copy the session from the
web app with fitatu-api import-session instead, as described under
Authentication & session file.
from datetime import date
from fitatu_api import FitatuApiClient
with FitatuApiClient.from_session() as client: # closes the HTTP connections at the end
user_id = client.auth.fitatu_user_id
today = date.today()
day = client.planner.get_day(user_id, today)
for meal_key, meal in day["dietPlan"].items():
for row in meal["items"]:
print(meal_key, row["name"], row["energy"], row["planDayDietItemId"])
egg = client.search_food("jajko kurze", limit=1)[0] # search rows carry the id as foodId
added = client.planner.add_product_to_day_meal(
user_id, today, meal_type="breakfast", product_id=egg["foodId"],
measure_id=egg["measure"]["measureId"], measure_quantity=2, # 2 of the hit's measure
)
print("added row", added["row_id"])How writes, row ids and removals work: docs/PLANNER.md.
To copy a catering diet's menu into the diary (safe to run again), use catering_sync.py from
the repository: Importing a catering menu.
For AI agents
FitatuTools exposes 47 tools (read the day, search food, log food, weight, water,
workouts, private recipes and products, ...) with JSON Schema inputs and read-only / destructive / idempotent annotations.
call() never raises: it returns {"ok": true, "data": ...} or {"ok": false, "error": {"error_type", "message", "retryable", "hint", ...}}, so the model can read what went wrong.
SYSTEM_PROMPT is the recommended system prompt: the rules the model needs on top of the tool
descriptions (read before writing, users' own meal names, data.ok, confirmations). The model
asks get_today for the date, in the account's time zone.
import json
import anthropic
from fitatu_api import FitatuTools
from fitatu_api.agent import READ_ONLY_TOOLS, SYSTEM_PROMPT, anthropic_tools # openai_tools() for OpenAI
client = anthropic.Anthropic()
messages = [{"role": "user", "content": "How many kcal did I eat today?"}]
# Only the read tools, as this loop runs tool calls without asking the user: call() refuses
# any other tool, which the model can still name.
with FitatuTools.from_session(tools=READ_ONLY_TOOLS) as tools:
while True:
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=16000,
system=SYSTEM_PROMPT,
tools=anthropic_tools(READ_ONLY_TOOLS),
messages=messages,
)
messages.append({"role": "assistant", "content": response.content})
if response.stop_reason != "tool_use":
break
results = [
{
"type": "tool_result",
"tool_use_id": block.id,
"content": json.dumps(tools.call(block.name, block.input)),
}
for block in response.content
if block.type == "tool_use"
]
messages.append({"role": "user", "content": results})
if response.stop_reason != "end_turn": # max_tokens or refusal: the answer is cut or missing
raise RuntimeError(f"the model stopped early: {response.stop_reason}")
print("".join(block.text for block in response.content if block.type == "text"))The write tools (log food, update, move, copy and delete rows, weight, water, workouts, private
recipes and products) need a loop
that asks the user before destructive calls; it is in
docs/AGENTS.md, with the
tool table, the calls never to expose (session tokens, catalog writes), how to make writes safe
to repeat, what to do per error_type, the OpenAI variant, long-running hosts, and how to try
the tools without an account against the offline test backend.
MCP
fitatu-mcp serves the same tools to Claude Code, Claude Desktop and other MCP hosts over
stdio, with SYSTEM_PROMPT as its instructions and three Polish slash commands
(podsumowanie_dnia, przeglad_tygodnia, zaloguj_posilek):
pipx install "fitatu-api[mcp]"
fitatu-api login
claude mcp add fitatu --scope user -- fitatu-mcp # fitatu-mcp --read-only: the read tools onlyfitatu-mcp --http serves the same tools over HTTP, with a token, for n8n, another computer or
Docker (the repository has a Dockerfile):
docs/AGENTS.md.
Without an account, fitatu-mcp --demo (or FitatuTools.demo()) serves a small made-up diary
kept in memory. For Claude Desktop, each GitHub release
has fitatu-<version>.mcpb, installed with a double click (log in with fitatu-api login first). Without installing anything, uvx --from "fitatu-api[mcp]" fitatu-mcp runs the server. It is
listed in the MCP Registry as
io.github.Jezue/fitatu-api (server.json). For Hermes Agent and other hosts that read
Agent Skills, skills/fitatu-diary/SKILL.md
tells the agent how to set the server up and use its tools well.
The host's permission prompt is the confirmation step, so keep it on for the destructive tools. Claude Desktop, uvx and what the server does: docs/AGENTS.md.
What it covers
Area | Client ( | Agent tools |
Food diary |
|
|
Activities |
|
|
Foods |
|
|
The user's own foods |
|
|
Measurements |
|
|
Water |
|
|
Summary and export |
|
|
Fasting and habits |
|
|
Goals and settings |
|
|
Catalog writes |
| none, on purpose |
FitatuLibrary, which wraps most of these as *_via_api methods that return {"status": ...}
instead of raising, is deprecated and will be removed in 1.0: for results that never raise use
FitatuTools ({"ok": true, "data": ...}), otherwise the client. Every public call with its stability is listed in
docs/API_REFERENCE.md.
Free and Premium accounts
Free account | Premium | |
Diary: read, log, update, move, copy, remove food, notes, activities, water, weight, body measurements | ✅ | ✅ |
Search, barcode, food measures, recipe search by words and | ✅ | ✅ |
Recipe search filters ( | ❌ "needs Fitatu Premium": the tools follow the app | ✅ |
Goals: read and set ( | ✅ (progress: a request per day, at most 31 days) | ✅ |
Weight and body measurement history, profile, fasting and habits (read), shopping list | ✅ | ✅ |
Top foods ( | ❌ 403: needs Fitatu Premium | ✅ |
Diary export ( | ❌ 403: "needs Fitatu Premium" | ✅ |
Protein / fat / carbohydrate day by day ( | ❌ 403 ( | ✅ |
Nearly everything works on an account without Fitatu Premium. Fitatu answers 403 without it to (checked live 2026-10-15):
summary.get_nutrient_by_day()for protein, fat and carbohydrate (energy works on any account);summary.get_top_products(), and so theget_top_foodstool;summary.export_diary(), and sofitatu-api export, which then says so in one line.
Fitatu serves the recipe search filters and premium catalog recipes to any account, but its app
keeps them for Premium, and so do the tools: they check the account's accessControl flags and
answer a forbidden error without them. The client itself does not check.
get_progress and get_report work on every account: when the macros' day-by-day route is
refused, they read each day's own summary instead (a request per day, at most 31 days), and
get_report gives top_foods null with a top_foods_note. A free account's macro goals are a
range (target_min below target_max); on a Premium account a one-day summary gave the two
equal (the day-by-day route get_progress reads there agrees, checked live). It takes a manual
goal and its own macro split too (set_targets, checked live 2026-10-15); with a split, its
macro goals are single numbers. fitatu-api doctor
says whether the account has a premium plan. See
Free and Premium accounts
in docs/AGENTS.md for the tools.
Command line
fitatu-api (also python -m fitatu_api) works on the session file, $FITATU_SESSION or
~/.fitatu/session.json:
fitatu-api login # or import-session, see Authentication & session file below
fitatu-api status # the session: file, user id, host, token expiry; sends nothing
fitatu-api doctor # checks the session, the clock and the client version with Fitatu
fitatu-api logout # deletes the session file after asking (--yes: without asking)
fitatu-api tools # the agent tools: name, read / write / destructive, what it does
fitatu-api tools --json # the same tools in the Anthropic API format, anthropic_tools()
fitatu-api call get_day '{"date": "2026-10-14"}'
fitatu-api export --from 2026-10-01 --to 2026-10-14 --format csv -o diary.csv # needs Fitatu Premiumstatus prints where the session comes from (the file and its permissions, or
$FITATU_SESSION_JSON), the user id, API host, locales, when the bearer token expires and
whether there is a refresh token, without sending anything; --check also reads the profile
once. doctor checks the setup with Fitatu, one ok / WARN / FAIL line each: the session
file's permissions, the refresh token (it refreshes the bearer once and saves it, as any
refresh does), this computer's clock against the fresh token's issue time, a profile read,
whether a premium plan runs (not until when, nor its price), and whether Fitatu's web app is still at the version the library sends (GET /upgrade-application/WEB/<version>); it exits with 1 when a check failed and prints no
token, user id or home directory, so its output can go into a bug report. logout deletes the
session file; stop fitatu-mcp and other processes that use it first, as they would write
their refreshed tokens back. Fitatu has no call the library knows of that revokes tokens.
None of these commands prints a token. fitatu-api --version prints the version.
call runs one tool through FitatuTools.call() and prints its envelope as JSON; the exit
status is 0 when ok is true and 1 when it is false. Only the read tools (READ_ONLY_TOOLS)
run unless --allow-writes is given. export saves Fitatu's diary export (csv, xls, pdf
or txt) to a new file readable only by you (0600); it does not replace an existing file
without --overwrite, and a range with nothing logged writes no file and exits with 1.
fitatu-api COMMAND --help describes each command. Logs go to stderr, from WARNING unless
fitatu-api --log-level DEBUG COMMAND or FITATU_LOG_LEVEL says otherwise (see
Privacy & logging).
Authentication & session file
fitatu-api login [--email ADDRESS] [-o PATH] [--base-url URL] (also python -m fitatu_api login) logs in, reads your profile for the account's locales and timezone, and writes the
session file. It reads FITATU_EMAIL and
FITATU_PASSWORD when they are set and prompts otherwise. Accounts without a password use
fitatu-api import-session (below).
Where.
fitatu-api login,fitatu-api import-session,FitatuApiClient.from_session(),FitatuTools.from_session()and the deprecatedFitatuLibrary.from_session()use the same file: the path you pass (-ofor the CLI), else$FITATU_SESSION, else$FITATU_SESSION_PATH, else~/.fitatu/session.json. A missing file raisesFitatuAuthErrortelling you to runfitatu-api login.What. JSON with
bearer_token,refresh_token,fitatu_user_id,base_url(the region's API host),app_locale,app_searchlocale,app_storagelocale,app_timezoneand a schema version. The client's identity (API key, app version, ...) is not stored; it comes from the library.Permissions. The file is written owner-only (0600), in a directory created 0700, through a temporary file that replaces it, so a reader never sees half a session. It holds live tokens: treat it like a password.
Tokens. Checked live on 2026-10-13: the bearer token is a JWT that lives one hour. The refresh token is an opaque string that Fitatu does not rotate:
POST /token/refreshreturns a new bearer token and the same refresh token, which keeps working, and older bearer tokens stay valid until they expire.POST /loginanswers a wrong e-mail or password with 422, notRefresh and write-back. The client refreshes the bearer token 60 seconds before it expires (from the JWT
exp) and once after a 401, one refresh at a time. The tokens are merged into the session file, so the next process starts with them; a process that shares the file picks up a pair another one saved, e.g. afterfitatu-api loginran again. Passpersist_tokens=Falseto keep the file untouched. A pair of another account (a login to another account with the same file) is not picked up: the running client keeps its own tokens and stops writing to the file, so that login stays. When a token fresh from Fitatu already looks expired, the computer's clock runs fast: the client then logs one warning and refreshes only after a 401.Logging in again. When Fitatu rejects the refresh token, calls raise
FitatuAuthError(error_typeauth). Runfitatu-api login(orimport-session) again; a running client picks the new pair up from the file the next time it needs a refresh.Accounts without a password. Accounts created with Apple or Facebook (Apple's "Hide my e-mail" addresses included) have no password for
fitatu-api login. Copy the session from the web app instead:Log in at https://www.fitatu.com/app/ with Apple or Facebook.
Open the browser's developer console on that page and run the line below. It copies only the tokens and your user id; the web app's
localStorage.useralso holds your e-mail, nickname and more.copy(JSON.stringify((u => ({token: u.token, refresh_token: u.refresh_token, id: u.id}))(JSON.parse(localStorage.user))))On macOS run
pbpaste | fitatu-api import-session. On Linux or Windows paste it into a file, runfitatu-api import-session < file(PowerShell:Get-Content file | fitatu-api import-session) and delete the file.
import-session [-o PATH] [--base-url URL]reads the JSON from stdin (a session file of this library works too), checks both tokens with Fitatu by refreshing the bearer once (so the saved one is good for an hour), reads the account's locales and timezone likeloginand writes the session file the same way. Nothing else from the input is saved. The token is a full account credential: do not paste it anywhere else.Containers and cron. Where no writable session file fits, put the session JSON itself in
FITATU_SESSION_JSON:fitatu-api login --print(orimport-session --print) prints it to stdout instead of writing a file, for a secret store.from_session()without a path takes it before any file, and keeps the tokens it refreshes in memory: Fitatu does not rotate the refresh token, so the same value works for every run until the refresh token itself expires (how long it lives is not known yet) or you log in again.Facade (deprecated).
FitatuLibrary.from_session()loads the same file and writes refreshed tokens back to it.FitatuLibrary(session_data, session_path=...)does the same for a session dict, and copies the current pair intosession_dataafter every call.From Python.
FitatuApiClient.login(email, password, token_store_path=path)logs in and merges the whole session intopath.
Regions & headers
The API host is the session's base_url, else the host of the account's storage locale:
pl_PL becomes https://pl-pl.fitatu.com/api, de_DE becomes https://de-de.fitatu.com/api.
fitatu-api login logs in on https://pl-pl.fitatu.com/api and stores the storage locale's
host; with --base-url it logs in there and stores that URL.
Group | Headers | Notes |
Required |
| The key and secret are static app values (403 without them); |
Semantic |
|
|
Identification |
| Only identify the client. The library always sends one constant web-app profile ( |
If Fitatu changes what the web app sends (its version, or the API key and secret) before a
release of the library follows, set FITATU_CLIENT_PROFILE to a JSON object with the keys of
WEB_CLIENT_PROFILE to change, e.g. FITATU_CLIENT_PROFILE='{"app_version": "4.14.0"}'. Any
other key or a value that is not plain text is refused with a FitatuValidationError
(fitatu-mcp then does not start). fitatu-api doctor says whether the version is still the
newest.
Login (POST /login with _username and _password) and refresh (POST /token/refresh with
{"refresh_token": ...}) go through the same request path and send the same headers, without
Authorization; at login the locale headers are still the pl_PL defaults. There is no
request signing, and Firebase App Check is not enforced; the library does not send it.
Credentials only go to https hosts under fitatu.com: any other base_url or absolute URL
raises FitatuValidationError before a request is made, and Authorization is only sent to
URLs under base_url or https://fitatu.com/api. Redirects are not followed: a 3xx answer is
a FitatuApiError, so a request body never goes on to another host.
Errors, retries, rate limits
The library's errors are FitatuApiError subclasses. describe_error(exc) turns any
exception into the JSON-safe dict that FitatuTools.call() (and the deprecated FitatuLibrary) return.
Exception | Raised when |
|
| An argument is invalid; nothing was sent. |
|
| The id, meal or row you named is not there: the library found that in what it read (the message lists what is there), or the server answered 404 ( |
|
| 401 after a refresh, a rejected refresh token, no session file, or a wrong e-mail or password at login (Fitatu answers 422); |
|
| 429 after retries; |
|
| No HTTP response (DNS, timeout, connection reset). |
|
| Fitatu's |
|
| The day sync answered 202 but rejected a day; |
|
| A tool for what the Fitatu app keeps for Premium, on an account without it; nothing was sent for it. |
|
| Any other HTTP error: |
|
Messages read METHOD /path -> status CODENAME: server message. In describe_error()'s message
the user id is <user> (GET /diet-plan/<user>/days -> 403), and with user_id= (which
FitatuTools.call() passes) wherever else it appears, so a result does not carry it to the
model provider. A 403 whose body is an HTML page comes from a firewall in front of the API (e.g.
Cloudflare), not from Fitatu's premium or key checks, and its hint says so. Any other exception, such as a TypeError raised inside the
library, is unexpected: a bug to report, since FitatuTools.call() checks the arguments first.
Retries: network errors, 429, 500/502/503/504 and Cloudflare's 520 to 524 are retried for GET, HEAD and OPTIONS,
and for writes marked idempotent: the day sync (all planner writes; it upserts by row id),
water.set_day, measurements.set_day, measurements.delete_day and foods.set_favorite.
Other writes (catalog writes, settings, login, refresh) are sent once. Up to
retry_max_attempts=3 attempts with exponential backoff from retry_base_delay_seconds=0.5.
A Retry-After of up to 30 seconds is honoured; a longer one is not waited for, and the error
is raised at once (FitatuRateLimitError with retry_after for a 429). During a technical
break nothing is retried or refreshed. Inside with client.time_limit(seconds): the requests
end within that time in all: a retry whose wait would leave it less than 2 seconds is not made, each request's
timeout is cut to the time left, and a request with no time left is not sent
(FitatuConnectionError). FitatuTools runs every call in one of 45 seconds (call_timeout).
Most writes make several requests, which counts when you budget against 429s: the tools read
the day before every diary write, and updates, moves, removals and activity writes read it
again afterwards to set ok. Requests per agent tool call, before retries and token refreshes:
Requests | Tools |
0 |
|
1 | the other read tools; |
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
8 |
|
1 a day |
|
Privacy & logging
The library logs through the standard logging module and configures no handlers. The
fitatu-api command and fitatu-mcp log to stderr, never stdout (which carries the command's
result, or the MCP protocol): the library from WARNING, or from the level that --log-level DEBUG|INFO|WARNING|ERROR (for fitatu-api before the command, e.g. fitatu-api --log-level DEBUG call get_today) or FITATU_LOG_LEVEL sets; other libraries from WARNING.
INFO(fitatu_api.client): auth events as JSON lines: login (user id), token refresh start, success and failure, andclear_auth, with a non-secret state snapshot (user id, locales, timezone, host, token expiry, whether tokens are present).WARNING(fitatu_api.client):fitatu.request.errorfor a request that failed for good on a network error, a 429 or a 5xx, after its retries;fitatu.auth.clock_skew(a token fresh from Fitatu looks expired, so the local clock is off; refreshing ahead of expiry stops) andfitatu.auth.store_other_account(the session file now holds another account's tokens; the client keeps its own). Fromfitatu_api.agent,fitatu_api.facadeandfitatu_api.mcp_server, a call whose result reports anunexpectederror (with the traceback), anauthor amaintenanceerror:get_day failed (auth): .... Fromfitatu_api.auth, a token store (usually the session file) that could not be read. Fromfitatu_api.mcp_serverunder--http, each request refused for its token, with the client's address (never the token); uvicorn adds its start and stop lines.DEBUG(fitatu_api.client): every request as JSON lines:fitatu.request.start(method, path, query parameters such as search phrases),fitatu.request.retrybefore each retry's wait (the failedattempt,delay_seconds, and thereason: the status or the network error's type), thenfitatu.request.okorfitatu.request.error(status,attempt,elapsed_mssince the start, and the first 300 characters of an error body; a 4xx stays at DEBUG, since the caller gets it as an exception and some, such as a 404, are expected). Fromfitatu_api.planner, one line per planner write (user id, day, meal, food id, a custom row's name and kcal); from the tool layers, every other error a result reports. Paths contain the user id and dates.
Request bodies, passwords and tokens are never logged: values under keys containing token,
secret, password or authorization are replaced with [redacted], and the auth context
keeps tokens and the API secret out of its repr. Error messages carry up to 200 characters of
the server's message; the full response body is in exc.body, which describe_error() and
the error results of FitatuTools (and the deprecated FitatuLibrary) leave out. A token that is not a valid header value (e.g. pasted with a
newline) is reported without quoting it.
Testing
pip install -e ".[dev]"
pytest -qThe suite runs offline. tests/fixtures/api_recording.json holds real API responses (scrubbed
of personal data) for the day sync, measurements, summaries, search and settings;
tests/fake_server.py is a fake backend built from them, and tests/test_recorded_contract.py
fails if the fake drifts from the recording. How the recording is made and refreshed:
tests/fixtures/README.md.
The live suite (tests/test_live_all.py) runs against a real account and writes to it:
FITATU_RUN_LIVE_TESTS=1 pytest tests/test_live_all.pyIt uses the session file that fitatu-api login wrote (or $FITATU_SESSION) and saves
refreshed tokens back to it; with $FITATU_SESSION_JSON set, that session is used instead and
refreshed tokens are not saved. Optional: FITATU_LIVE_DAY (after today; default a year from
today), FITATU_LIVE_MEAL_KEY (snack), FITATU_LIVE_PRODUCT_ID, FITATU_LIVE_RECIPE_ID,
FITATU_LIVE_MEASUREMENT_DAY (2020-01-01; skipped if it has a measurement) and
FITATU_LIVE_RUN_WRITE_ACCOUNT=1.
Each test deletes exactly the rows it added on FITATU_LIVE_DAY and fails if one is left; a
day on or before today is refused. Water and the note on that day are set back, and the weight
and measurements written on FITATU_LIVE_MEASUREMENT_DAY are deleted. -k ReadOnly runs only
the tests that read.
Logging catalog foods adds them to the account's recent foods, which is not undone. With
FITATU_LIVE_RUN_WRITE_ACCOUNT=1 the suite also changes and restores the water glass size and the
daily goals (Fitatu keeps the restored goals as a new version from today), and creates, then
deletes, a private product and two private recipes (one through the tools, logged on
FITATU_LIVE_DAY and removed) and a private product through the tools (logged on
FITATU_LIVE_DAY, changed, removed). Product and recipe deletes are soft, so like the recent
foods they are not fully undone: they stay on the account, marked deleted and hidden from your
foods and searches. The full list is in the module docstring of tests/test_live_all.py. Never point FITATU_LIVE_DAY at a day with entries you care about.
scripts/check_contract.py tells, reading only, whether the live API still answers with the
structure the recording holds: it prints route and key names, never values, and exits 1 when a
key is gone, a type changed or a route fails. The Live contract workflow runs it and the
read-only live tests every Monday with a throwaway account's session in the FITATU_SESSION_JSON
secret, and skips without it:
CONTRIBUTING.md.
scripts/eval_agent.py scores how well a Claude model uses the tools on the demo diary (29
tasks in Polish and English; needs ANTHROPIC_API_KEY and costs API usage, so CI does not run
it): docs/AGENTS.md.
Documentation
docs/AGENTS.md: tools, safe writes, error handling and the MCP server for agents.
docs/PLANNER.md: the day sync contract, ids, and the result of every diary write.
docs/API_REFERENCE.md: every public class and method with its stability.
docs/APP_4_17_1_API_CATALOG.md: every route of the Fitatu Android app 4.17.1, from a decompile.
docs/RELEASING.md: release steps for maintainers.
Bugs and questions: GitHub issues. Security problems are reported privately: SECURITY.md. Setup, checks and rules for pull requests: CONTRIBUTING.md.
License
MIT, see LICENSE. It covers this code only, not the Fitatu service, its API or the data it returns.
Available Tools
47 toolsadd_activityLog a workoutA
Log a workout from the activity catalog; returns its row_id. Fitatu stores energy_kcal as given and does not compute it (see search_activity). Each call adds an activity unless row_id is reused. data.ok says a re-read shows it.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | Day as YYYY-MM-DD; when the user says today, yesterday, this week or a weekday, call get_today and count from its date. | |
| row_id | No | Optional UUID version 1 for the new row; omit it to get a new id. Repeating the add with the same row_id and values does not log a second row: when a failed add's error has a retry_row_id, repeat it with that row_id. Never a row_id from get_day: a logged activity cannot be changed; remove it with remove_activity and add it again. | |
| minutes | Yes | Duration in minutes. | |
| activity_id | Yes | activity_id from search_activity. | |
| energy_kcal | Yes | Energy burned in kcal. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds real behavior beyond the annotations: energy_kcal is stored as given and never computed, activity rows are immutable once logged, each call adds a row unless row_id is reused, and the row_id retry flow for failed adds. The closing 'data.ok says a re-read shows it' is cryptic and underspecified, which keeps this from 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three front-loaded sentences with the action and return value first, then semantics. Mostly tight, though the final sentence is dense and hard to parse, slightly weakening readability.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description needn't spell out return values and correctly focuses on mutation semantics and idempotency. The vague reference to 'data.ok' is the only loose end for a mutation tool with four required parameters.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 meaning the schema lacks by explaining that energy_kcal is not derived and clarifying the row_id reuse/retry contract beyond what the property text already states.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Log a workout from the activity catalog') and immediately names the return value ('returns its row_id'). This clearly distinguishes it from add_food, search_activity and remove_activity 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides concrete routing context: get_today for date phrasing, search_activity for the catalog and energy semantics, and remove_activity + re-add for corrections. It never states exclusions against add_food explicitly, but the activity-vs-food boundary is self-evident from the naming and description.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
add_custom_itemLog a custom foodA
Log a food that is not in the catalog, by name and the nutrition of the whole amount eaten; returns its row_id. Each call adds a row unless row_id is reused. When the user gives only kcal, estimate protein_g, fat_g and carbohydrate_g for that food and tell the user they are estimates; an omitted one counts as 0 g.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | Day as YYYY-MM-DD; when the user says today, yesterday, this week or a weekday, call get_today and count from its date. | |
| meal | Yes | Meal slot. The keys are fixed, but users rename their meals in the app: match the user's words against get_day's meal_name and pass that meal's meal_key. Only the meals get_day lists exist. | |
| name | Yes | What it was, e.g. 'Kanapka z serem'. | |
| eaten | No | true when the user ate or drank it or just asks to log it; false (the default) only when they plan ahead. | |
| fat_g | No | Fat in grams. | |
| row_id | No | Optional UUID version 1 for the new row; omit it to get a new id. Repeating the add with the same row_id and values does not log a second row: when a failed add's error has a retry_row_id, repeat it with that row_id. Never a row_id from get_day: update_item changes a logged row's quantity and eaten; to change anything else, remove the row and add it again. | |
| protein_g | No | Protein in grams. | |
| energy_kcal | Yes | Energy in kcal. | |
| carbohydrate_g | No | Carbohydrate in grams. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover the safety profile (write, non-destructive, not idempotent), and the description adds the row-append behavior plus the keyed-retry nuance ('Each call adds a row unless row_id is reused') and the estimation duty that no structured field conveys. Return values are also handled by the output schema, so this is solid added context rather than duplication.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, front-loaded with purpose, then the append/idempotency rule, then the estimation edge case. No filler, and each clause carries actionable information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 9-parameter write tool with full schema documentation, annotations and an output schema, the description covers purpose, the row_id idempotency rule and the estimation fallback adequately. Only peripheral details (e.g., what occurs if row_id collides with another row) are unaddressed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 semantic meaning: the nutrition figures are for 'the whole amount eaten' rather than per unit, and an omitted macro explicitly counts as 0 g. That resolves an ambiguity the schema's 'Fat in grams' wording leaves open.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Log a food that is not in the catalog') and immediately scopes it against the catalog-based add_food/add_foods siblings. It also names the return value ('returns its row_id'), so an agent knows both what it does and what it gets back.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The trigger condition is explicit — use this when the food is not in the catalog — which implicitly routes catalog foods to add_food, and it gives concrete guidance for the kcal-only case. It stops short of naming the alternative tools outright.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
add_foodLog a foodA
Log a catalog food in a meal; returns its row_id. food_id and food_type come from a search_food, search_recipes, find_by_barcode, get_recent_foods, get_favorite_foods or get_my_foods hit, create_food's food_id (PRODUCT) or create_recipe's recipe_id (RECIPE). For a PRODUCT give either unit 'g' or 'ml' with quantity in grams or millilitres, or measure_id (from the hit or get_food_measures) with quantity = how many of that measure. A RECIPE is logged in portions unless measure_id names another of its measures; unit is for products only. A premium recipe needs Fitatu Premium: without it a forbidden error. A measure_id the food does not have is refused before anything is written (that check reads the food once), and the error lists its measures. Each call adds a row unless row_id is reused. The row is not read back: data.ok says the sync accepted it, so read get_day to check what was logged. The result names the measure the row was stored in (measure_id, measure_name, measure_quantity): grams of a food without a gram measure are stored as a count of another one (70 g as 2 portions of 35 g), and update_item's quantity counts that measure.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | Day as YYYY-MM-DD; when the user says today, yesterday, this week or a weekday, call get_today and count from its date. | |
| meal | Yes | Meal slot. The keys are fixed, but users rename their meals in the app: match the user's words against get_day's meal_name and pass that meal's meal_key. Only the meals get_day lists exist. | |
| unit | No | Products only: quantity is in g or ml. | |
| eaten | No | true when the user ate or drank it or just asks to log it; false (the default) only when they plan ahead. | |
| row_id | No | Optional UUID version 1 for the new row; omit it to get a new id. Repeating the add with the same row_id and values does not log a second row: when a failed add's error has a retry_row_id, repeat it with that row_id. Never a row_id from get_day: update_item changes a logged row's quantity and eaten; to change anything else, remove the row and add it again. | |
| food_id | Yes | food_id of a search_food, search_recipes, find_by_barcode, get_recent_foods, get_favorite_foods or get_my_foods hit, create_food's food_id (PRODUCT), create_recipe's recipe_id (RECIPE), or a get_day row's product_id (PRODUCT) or recipe_id (RECIPE). | |
| quantity | Yes | Grams or ml with unit, else how many of the measure. | |
| food_type | Yes | type of that search hit, or the get_day row's food_type. | |
| measure_id | No | measure_id of this food, from its search hit or get_food_measures. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only give the generic safety profile; the description supplies the non-obvious behaviors: premium recipes fail with a forbidden error, an unknown measure_id is refused before anything is written, each call adds a row unless row_id is reused, and the write is not read back (data.ok only means the sync accepted it). It also explains that grams may be stored as a count of another measure, a real data-model quirk.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Every sentence carries load for a 9-parameter tool with tricky branching, and the return value leads. It is delivered as one dense block, however, with sourcing rules, product/recipe rules and verification steps interleaved, which makes it slower to scan than it needs to be.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite an output schema existing, the description covers the gating (premium), the validation failure path, the retry path, and the post-write verification workflow. An agent has everything needed to call this correctly on the first try.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3, but the description goes well beyond it: it explains the PRODUCT-vs-RECIPE branch for unit/measure_id/quantity, where food_id and food_type originate, and the retry_row_id/idempotency-key behavior of row_id. That is substantive semantic value the schema cannot express.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource+effect: logs a catalog food into a meal and returns its row_id. It also implicitly distinguishes itself from add_custom_item (catalog food only) and from update_item (which changes a logged row). 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly names the sibling tools that produce food_id/food_type (search_food, search_recipes, find_by_barcode, get_recent_foods, get_favorite_foods, get_my_foods, create_food, create_recipe) and get_food_measures for measure_id. It also routes the agent away from the tool when changing an existing row (use update_item; otherwise remove and re-add) and tells it to verify with get_day.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
add_foodsLog several foodsA
Log several catalog foods in one meal with one write, e.g. a whole breakfast. Each item takes food_id, food_type, quantity and measure_id or unit as add_food does, and is checked the same way before anything is written (one read per item with measure_id or unit): when one is wrong, nothing is logged and the error names it as items[index]. Returns the rows (row_id, food_id, measure_id, measure_name, measure_quantity) in the order of items; they are not read back, data.ok says the sync accepted them. Each call adds rows unless row_id is reused.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | Day as YYYY-MM-DD; when the user says today, yesterday, this week or a weekday, call get_today and count from its date. | |
| meal | Yes | Meal slot. The keys are fixed, but users rename their meals in the app: match the user's words against get_day's meal_name and pass that meal's meal_key. Only the meals get_day lists exist. | |
| eaten | No | Sets every row: true (the default) when the user ate them or just asks to log them; false only when they plan ahead. | |
| items | Yes | The foods, each as add_food takes it. | |
| row_id | No | Optional UUID version 1 the rows' row_ids are derived from; omit it to get a new one. Repeating the add with the same row_id and arguments writes the same rows again instead of new ones: when a failed add's error has a retry_row_id, repeat it with that row_id. Never a row_id from get_day. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only carry the safety/idempotency flags; the description adds substantial behavior beyond them: all-or-nothing validation ('when one is wrong, nothing is logged'), one read per item, error naming as items[index], the exact return fields and ordering, that rows are not read back and data.ok is the success signal, and that repeats append unless row_id is reused. This is unusually rich disclosure for a write tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single dense paragraph, front-loaded with purpose before mechanics, and every clause carries information (atomicity, error format, return, idempotency). The parenthetical about 'one read per item' is slightly cluttered but not wasteful enough to drop the score.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, annotations covering safety, and 100% schema coverage, the description still supplies what the structured fields cannot: atomicity, error indexing, sync semantics, and idempotency via row_id. Nothing needed to call this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 value by declaring the item shape must match add_food, explaining that items validate atomically and report errors by items[index], and clarifying row_id as a reuse/idempotency key. It reinforces rather than merely restates the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb (Log), specific resource (catalog foods), and explicit scope: several items in one meal with one write. It distinguishes itself from the sibling add_food by framing itself as the batch form ('as add_food does'), so an agent can route without reading both schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The example ('a whole breakfast') and the repeated 'as add_food does' framing make it clear this is for multi-item logging, with add_food implied for singles. It stops short of an explicit rule like 'use add_food instead when logging one item,' so it is clear context but not a full when/when-not statement.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
copy_mealCopy a mealA
Copy the food rows of a meal, or only row_ids of it, to another meal and/or day in one write, e.g. 'the same breakfast as yesterday' or 'plan this lunch for tomorrow'. Products and recipes keep their measure and quantity, custom rows their name and nutrition; rows of other types are not copied and are listed in skipped. Returns the copies' row_ids (remove_items with them undoes the copy); data.ok says a re-read shows them all. Each call adds rows unless row_id is reused.
| Name | Required | Description | Default |
|---|---|---|---|
| eaten | No | Sets every copy: true when the user ate it or just asks to log it, false when they plan ahead. Omit it to keep each row's eaten. | |
| row_id | No | Optional UUID version 1 the copies' row_ids are derived from; omit it to get a new one. Repeating the copy with the same row_id and arguments writes the same rows again instead of new ones: when a failed copy's error has a retry_row_id, repeat it with that row_id. Never a row_id from get_day. | |
| row_ids | No | Only these rows of from_meal (row_ids from get_day); omit it for the whole meal. | |
| to_date | Yes | Day to copy to, as YYYY-MM-DD (from_date itself when to_meal differs); when the user says today, yesterday, this week or a weekday, call get_today and count from its date. | |
| to_meal | No | Meal to copy into (default: from_meal). Meal slot. The keys are fixed, but users rename their meals in the app: match the user's words against get_day's meal_name and pass that meal's meal_key. Only the meals get_day lists exist. | |
| from_date | Yes | Day as YYYY-MM-DD; when the user says today, yesterday, this week or a weekday, call get_today and count from its date. | |
| from_meal | Yes | Meal to copy. Meal slot. The keys are fixed, but users rename their meals in the app: match the user's words against get_day's meal_name and pass that meal's meal_key. Only the meals get_day lists exist. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only cover the safety profile (readOnlyHint=false, destructiveHint=false, idempotentHint=false, openWorldHint=false). The description goes well beyond them: what is preserved (measures/quantities for products and recipes, name/nutrition for custom rows), what is skipped and surfaced in 'skipped', the additive nature ('Each call adds rows unless row_id is reused'), the undo path via remove_items, and the row_id idempotency-key mechanism. This is rich disclosure layered on top of 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three front-loaded sentences that lead with the core action before qualifying details. Dense but mostly earned; the return-value/undo sentence is somewhat packed and overlaps with the output schema, but nothing is wasted boilerplate.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, annotations covering safety, and 100% schema coverage across 7 parameters, the description still adds the behavioral context an agent needs: copy semantics per row type, skip behavior, undo, and repeat-call semantics. Complete for this tool's complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the property descriptions are already very detailed (row_id retry semantics, meal_key matching, date counting from get_today). The prose adds little parameter-level meaning beyond what the schema states, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb and resource ('Copy the food rows of a meal... to another meal and/or day in one write') and immediately scopes it with a partial-copy variant ('or only row_ids of it'). Concrete examples ('the same breakfast as yesterday', 'plan this lunch for tomorrow') make the intent unmistakable and distinguish it from siblings like move_item, add_food, and add_foods.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives clear usage context through examples and explains the eaten flag as selecting 'log it' vs 'plan ahead', plus retry behavior when a copy fails. It stops short of explicitly naming a competing tool or a when-not-to-use condition (e.g. move_item vs copy), leaving some routing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_foodCreate a private productA
Save a product in the user's own foods from its nutrition label, e.g. a bar the catalog does not have, to log it by weight or by its servings. Only the user sees it; it never goes to the shared catalog. Values are per 100 g (100 ml with unit ml), as the label gives them: when it gives only a serving's, scale them to 100 g. Energy in kcal, not kJ. Returns food_id and measures, its measures as get_food_measures lists them (null when it could not be read back). Log it with add_food: food_id, food_type PRODUCT, and unit g (ml) with the amount, or a measure_id with the count. Each call creates another product: when one fails with anything but a validation or rate_limit error, look for it with get_my_foods before creating it again.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | The product's name, e.g. 'Baton owsiany'. | |
| unit | No | ml for a drink whose label gives values per 100 ml. | g |
| brand | No | Its brand, if the label has one. | |
| fat_g | Yes | Fat in g in 100 g (100 ml for a drink), as the label gives it. | |
| salt_g | No | Salt in g. | |
| barcode | No | The 8 to 14 digits under the bars. Only the user sees it; find_by_barcode then finds this product. | |
| fiber_g | No | Fibre in g. | |
| servings | No | Its servings, each name once, e.g. [{'name': 'bar', 'weight': 45}]; add_food then logs them by measure_id. | |
| sugars_g | No | Of which sugars, in g; at most carbohydrate_g. | |
| protein_g | Yes | Protein in g in 100 g (100 ml for a drink), as the label gives it. | |
| energy_kcal | Yes | Energy in kcal, not kJ, in 100 g (100 ml for a drink), as the label gives it. | |
| carbohydrate_g | Yes | Carbohydrate in g in 100 g (100 ml for a drink), as the label gives it. | |
| saturated_fat_g | No | Of which saturated fat, in g; at most fat_g. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover only the mutation/idempotency profile; the description adds real behavioral context beyond them: visibility scope (private, never shared), the per-100 g normalization requirement and the scaling rule when the label gives serving values, kcal-not-kJ, and the explicit warning that every call creates a new product. It also names the return payload (food_id, measures).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose and scope are front-loaded, and every sentence carries information (visibility, units, return value, logging, retry). It is dense and packs several distinct instructions into long sentences, which slightly hurts scanability but nothing is filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 13-parameter mutation tool with nested servings and an output schema, the description covers the intent, the unit/normalization convention, visibility, the downstream logging path, and failure recovery. An agent can call it correctly without further inference.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 supplies cross-parameter semantics the schema states only per-field: values are always per 100 g (100 ml with unit ml) and must be scaled when the label gives a serving's values, plus the mappings to add_food via unit vs measure_id. It stops short of describing optional fields like sugars/fiber/salt relationships.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Save a product in the user's own foods from its nutrition label') and immediately scopes it against the shared catalog ('Only the user sees it; it never goes to the shared catalog'), which separates it from catalog-facing siblings like search_food and update_food.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives the triggering situation ('a bar the catalog does not have'), the follow-up workflow (log with add_food, food_type PRODUCT, unit g/ml), and a concrete retry rule ('when one fails with anything but a validation or rate_limit error, look for it with get_my_foods before creating it again'). Alternatives and exclusions are both covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_recipeCreate a private recipeA
Save a private recipe in the user's own foods from catalog products, e.g. their usual smoothie, so it can be logged as one food. Only the user sees it; it never goes to the shared catalog. Each ingredient takes food_id, quantity and unit or measure_id as add_food does, is a PRODUCT, and is checked the same way before anything is written: when one is wrong, nothing is created and the error names it as ingredients[index]. Returns recipe_id and per_serving, its portion measure as get_food_measures lists it (weight_g, energy_kcal, protein_g, fat_g, carbohydrate_g of one serving; null when the recipe could not be read back). Log it with add_food: food_id recipe_id, food_type RECIPE, quantity the servings eaten. Each call creates another recipe: when one fails with anything but a validation, not_found or rate_limit error, look for it with get_my_foods before creating it again.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | The recipe's name, e.g. 'Owsianka z bananem'. | |
| servings | No | How many servings the ingredients make. | |
| description | No | How to make it, as the app shows it. | |
| ingredients | Yes | The products in it, each as add_food takes it. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only tell the agent this is a non-read-only, non-destructive, non-idempotent call. The description adds real behavioral detail beyond that: privacy (user-only, no shared catalog), atomic validation semantics ('when one is wrong, nothing is created and the error names it as ingredients[index]'), the return payload, and the fact that each call creates another recipe with a specific retry path.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action and privacy constraint, and nearly every clause carries information (atomicity, return shape, logging pattern, idempotent retry). It is a dense single block with some long compound sentences, which costs a little readability but no meaningful waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present the description needn't explain returns, yet it still names recipe_id and per_serving fields. Combined with full schema coverage, annotations, and explicit cross-tool workflow steps, an agent has everything needed to call this correctly on the first attempt.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is already 100%, so the baseline is 3, but the description adds genuine meaning: ingredients take 'food_id, quantity and unit or measure_id as add_food does', must be a PRODUCT, and validation errors reference ingredients[index]. It clarifies the unit-vs-measure_id relationship in prose rather than just per-field text.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Save a private recipe') plus the scope ('in the user's own foods from catalog products... never goes to the shared catalog'). This clearly separates it from create_food and update_recipe/delete_recipe without needing to open any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit usage context ('so it can be logged as one food'), tells the agent how to consume the result ('Log it with add_food: food_id recipe_id, food_type RECIPE, quantity the servings eaten'), and provides precise retry/exclusion guidance ('when one fails with anything but a validation, not_found or rate_limit error, look for it with get_my_foods before creating it again').
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_foodDelete a private productADestructiveIdempotent
Delete one of the user's own products: create_food's food_id or a get_my_foods PRODUCT hit's food_id. Any other product (a catalog one or another user's) is refused before anything is changed (that check reads it). Rows already logged with it keep their name and values. Fitatu keeps a deleted product marked deleted, out of the user's foods and searches; deleting it again gives data.ok true with already_deleted true. previous holds what create_food takes to make it again (under a new food_id).
| Name | Required | Description | Default |
|---|---|---|---|
| food_id | Yes | create_food's food_id, or a get_my_foods PRODUCT hit's food_id. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations it discloses non-obvious behavior: the ownership check runs before mutation, previously logged entries retain the name and values, deletion is a soft delete (product stays marked deleted and drops out of foods/searches), re-deletion returns already_deleted=true, and the response carries a 'previous' payload that can recreate the item. This corroborates idempotentHint/destructiveHint and adds real detail the 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is dense but front-loaded: the action and scope come first, followed by refusal behavior, soft-delete semantics, idempotency, and the recreation payload. Every sentence carries information, though the run-on clause about the parenthetical ownership check ('that check reads it') is slightly awkward.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter destructive tool with an output schema and full annotation coverage, the description supplies everything an agent needs: valid ID sources, ownership refusal, soft-delete semantics, idempotent re-call behavior, and the meaning of the returned 'previous' field. Nothing material is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so food_id's description already documents its origin. The prose reiterates the same two sources without adding format, range, or failure-mode detail beyond what the schema states, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb+resource (delete one of the user's own products) and scopes it precisely to the user's private foods, excluding catalog items and other users' products. It also grounds the food_id's provenance in two sibling tools (create_food, get_my_foods), so an agent can distinguish it from delete_recipe or update_food without inference.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives clear context and an explicit exclusion: only the user's own products may be deleted, and any catalog or other-user product is refused before any change. It also tells the agent where to get valid IDs. It stops short of routing to named alternatives (e.g. what to call instead for a recipe), so it is strong but not a full when/when-not/alternative statement.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_recipeDelete a private recipeADestructiveIdempotent
Delete one of the user's own private recipes: create_recipe's recipe_id or a get_my_foods RECIPE hit's food_id. Any other recipe (a catalog recipe, a shared one or another user's) is refused before anything is changed (that check reads the recipe). Fitatu keeps a deleted recipe marked deleted, out of the user's foods and searches; deleting it again gives data.ok true with already_deleted true.
| Name | Required | Description | Default |
|---|---|---|---|
| recipe_id | Yes | Id of a recipe the user created. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=true, but the description goes further: it discloses that the ownership check reads the recipe before mutation, that deletion is a soft delete (recipe stays marked deleted and drops out of foods and searches), and that a repeat call returns data.ok true with already_deleted true. That is meaningful behavior beyond the structured hints.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three dense sentences, front-loaded with the core action and id source, then the refusal rule, then the delete semantics. No filler and nothing repeated from the schema or annotations.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values need no explanation, yet the description still surfaces the most decision-relevant output field (already_deleted). For a single-parameter destructive tool, preconditions, side effects, and idempotency are all covered.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the single parameter is already documented, so the baseline is 3. The description earns an extra point by explaining provenance of the id value – it must come from create_recipe or a get_my_foods RECIPE hit's food_id – which the schema does not say.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (delete a private recipe) and immediately scopes it to the user's own recipes, which separates it from create_recipe, update_recipe, and delete_food. It even names where valid ids originate (create_recipe's recipe_id, get_my_foods RECIPE hits).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-not conditions: catalog, shared, and other users' recipes are refused before any change. However, it never routes the agent to a sibling for those refused cases (e.g., delete_food or preview_removal), so alternative selection is only partially covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_by_barcodeFind a product by barcodeARead-onlyIdempotent
Find the catalog product with a barcode (the EAN or UPC digits printed under the bars), or the user's own product with it (create_food's barcode). Returns it in the same shape as a search_food hit, for add_food and get_food_measures. A barcode that no product has is not_found: then search_food by the product's name.
| Name | Required | Description | Default |
|---|---|---|---|
| barcode | Yes | The 8 to 14 digits, without spaces, e.g. '5901234123457'. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, openWorld and non-destructive, so safety is covered. The description adds real behavioral context beyond them: the exact return shape ('same shape as a search_food hit') and the not_found outcome with a recovery path. Missing details such as rate limits or whether user products shadow catalog matches.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, front-loaded with the primary action and ending with the failure fallback. Every clause carries information, though the parenthetical naming of create_food and downstream tools makes it slightly dense.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need no explanation, and the description still frames the return shape for compatibility with add_food/get_food_measures. With one fully documented parameter and a stated failure mode, nothing needed for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description still adds meaning by identifying which barcode is meant (EAN/UPC digits printed under the bars) and clarifying that user-created products can carry a barcode too, which the schema does not convey.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('find the catalog product with a barcode') and disambiguates the two lookup spaces: catalog products versus the user's own products created via create_food. An agent can distinguish this from search_food 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit routing: use this when you have a barcode, and when nothing matches, fall back to search_food by product name. It also names downstream consumers (add_food, get_food_measures), so the when-to-use and when-not-to-use paths are both covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_body_measurementsRead body measurement changesARead-onlyIdempotent
Read how the user's body measurements changed over a period: per body_part (neck, chest, waist, stomach, hips, thigh, calf, biceps, fat_percentage) the first and last value of the period (start_value, end_value) and the difference. Sizes are in the user's size unit (cm unless changed in the app), fat_percentage in %. Parts with nothing logged are left out. Pass from_date and to_date to choose the period; without them the server picks it. Body weight is get_weight_history.
| Name | Required | Description | Default |
|---|---|---|---|
| to_date | No | Day as YYYY-MM-DD; when the user says today, yesterday, this week or a weekday, call get_today and count from its date. | |
| from_date | No | Day as YYYY-MM-DD; when the user says today, yesterday, this week or a weekday, call get_today and count from its date. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint and destructiveHint=false, so the safety profile is covered. The description adds genuinely useful behavior: units (cm unless changed in app, fat_percentage in %), the omission rule for parts with nothing logged, and the default-period fallback when dates are absent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four compact sentences, front-loaded with the return shape and followed by the scoping parameters and the sibling pointer. Dense and mostly waste-free, though the body-part enumeration is long and edges toward schema duplication.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return structure need not be re-explained, yet the description still supplies the unit conventions and the 'parts with nothing logged are left out' caveat that schemas typically miss. Nothing needed to call or interpret this tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 meaning beyond the schema by explaining that from_date/to_date define the period and that omitting them makes the server choose the range. That behavior is not stated anywhere in the schema property descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a precise verb+resource ('read how the user's body measurements changed over a period') and enumerates the exact body parts and returned fields (start_value, end_value, difference). It is immediately distinguishable from raw-history siblings like get_measurement_history and from get_weight_history, which it names explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear context: pass from_date/to_date to choose the period, otherwise the server picks it, and routes body weight to get_weight_history. It never explicitly contrasts with get_measurement_history (raw entries vs. period deltas), so the sibling-boundary is only partially drawn.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_dayRead a diary dayARead-onlyIdempotent
Read one diary day: per meal its meal_key (the slot other tools take), meal_name (the name the user gave it) and every logged food (row_id, food_type, product_id or recipe_id, name, measure_id, measure_name and measure_quantity, weight in g, energy in kcal, protein/fat/carbohydrate/fiber/sugars/salt in g, eaten); per-meal and day totals; and logged activities (row_id, name, energy in kcal burned); note, the user's own text for the day (null without one), and tags_ids, the ids of its note tags. What the user ate is eaten_totals (rows ticked as eaten); when it is 0 but totals is not, the rows are logged without the tick, so use totals and say so. totals counts every row, planned or eaten. Burned energy is not subtracted. Read the day first to get the row_ids that update_item, move_item and remove_items take. A PRODUCT or RECIPE row's product_id or recipe_id is the food_id that add_food takes, with its food_type, measure_id and measure_quantity as quantity.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | Day as YYYY-MM-DD; when the user says today, yesterday, this week or a weekday, call get_today and count from its date. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint and openWorldHint=false, so safety is covered. The description does add real behavior beyond that: the eaten_totals=0-but-totals-nonzero fallback, the statement that burned energy is not subtracted, and the null-without-a-note rule. However, with an output schema present it mostly describes the payload rather than the tool's operational behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the resource and purpose, and every later clause encodes a rule (field mapping, totals caveat, row_id handoff). It is efficient for the amount of information, though enumerating every returned column in a single run-on sentence partly duplicates the output schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read tool whose annotations and output schema already cover safety and return shape, the description supplies the remaining cross-tool glue: row_ids for update_item/move_item/remove_items, food_id handoff to add_food, and the totals-vs-eaten_totals rule. Nothing needed 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.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There is a single date parameter and schema description coverage is 100%, including the get_today counting rule, so the schema already carries the semantics. The description adds nothing about the date argument itself, only about the returned fields, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (read) and resource (one diary day) and immediately enumerates the scope: meals, foods, totals, activities, note and tags. It is clearly distinguishable from siblings like get_today, get_range_summary or get_report, which are day-adjacent but different aggregations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly prescribes sequencing: 'Read the day first to get the row_ids that update_item, move_item and remove_items take', and explains which field (food_id/food_type/measure_id/measure_quantity) feeds add_food. It also gives in-context guidance on choosing eaten_totals vs totals with the exact edge case that selects between them.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_fastingRead intermittent fastingARead-onlyIdempotent
Read the user's intermittent fasting (post przerywany) for a range of up to 62 days: days lists each day with fasting, its eating_periods (when the user ate, from and to as times of day) next to expected (the eating windows of the scheme); a day without fasting is not listed. scheme is the fasting scheme in the user's settings (type, e.g. 16_08_hours or 5_2_days, week_days and start_date as Fitatu gives them), null when none is set.
| Name | Required | Description | Default |
|---|---|---|---|
| to_date | Yes | Day as YYYY-MM-DD; when the user says today, yesterday, this week or a weekday, call get_today and count from its date. | |
| from_date | Yes | Day as YYYY-MM-DD; when the user says today, yesterday, this week or a weekday, call get_today and count from its date. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive and closed-world, so the safety profile is covered. The description adds genuinely non-obvious behavior: days without fasting are silently omitted, and scheme can be null. It does not discuss pagination or truncation behavior at the 62-day boundary.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the purpose and range limit before the field-by-field explanation. The middle clause is dense and parenthetical ('its eating_periods ... next to expected ...'), but every element maps to real response semantics rather than padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present the description need not re-explain return shape, yet it usefully flags the two semantic quirks an agent would otherwise misread (omitted fasting-free days, null scheme). Combined with rich annotations and fully documented parameters, an agent has everything needed to call this correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and both date parameters carry their own guidance about resolving relative dates via get_today, so the baseline is 3. The description earns above baseline by imposing the practical 62-day maximum span on from_date/to_date, a limit the schema itself does not express.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Read the user's intermittent fasting') plus the scope ('range of up to 62 days'), which cleanly separates it from the other read tools like get_day, get_range_summary, or get_habits. It also names the response entities (days, eating_periods, expected, scheme), so an agent knows exactly what it retrieves.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The range cap ('up to 62 days') is an actionable usage constraint, and the parameter descriptions route the agent to call get_today first when the user speaks in relative dates. There is no explicit when-not guidance, but no sibling covers fasting either, so the routing risk is low.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_favorite_foodsList favourite foodsBRead-onlyIdempotent
List the user's favourite products and recipes, in the same shape as search_food hits.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of hits. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, openWorldHint=false and destructiveHint=false, so the safety profile is fully covered. The description adds a genuinely useful behavioural cue — that hits are shaped like search_food results — but says nothing about ordering, pagination, or what happens when the user has no favourites.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One sentence, zero filler, and the resource and output-shape note are both front-loaded. Nothing could be removed without losing information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Output schema exists so return values need not be described, and annotations cover the safety profile. The description covers what is listed and the result shape; only the ordering/pagination behaviour and the distinction from sibling list tools are left implicit.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the single 'limit' parameter is fully documented in the schema (default 10, max 50). The description adds no further meaning 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.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List the user's favourite products and recipes') and clarifies scope as the user's favourites, which distinguishes it from generic search tools. It does not explicitly differentiate from near-neighbours like get_top_foods or get_my_foods, so it falls just short of 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No when-to-use or when-not-to-use guidance is given, and no alternatives are named. In a sibling set containing get_top_foods, get_my_foods, get_recent_foods, and search_food, an agent gets no help deciding which listing tool to call.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_food_measuresList a food's measuresARead-onlyIdempotent
List the measures a food can be logged in: measure_id, name (e.g. 'g', 'portion', 'piece'), weight_g or capacity_ml, energy_kcal and protein_g, fat_g, carbohydrate_g of one measure (a macro is null when the food's details do not give it; a product the user created with unit ml gives a serving's ml as weight_g). Pass measure_id and a quantity of that measure to add_food. A premium recipe needs Fitatu Premium: without it a forbidden error.
| Name | Required | Description | Default |
|---|---|---|---|
| food_id | Yes | food_id of a search_food, search_recipes, find_by_barcode, get_recent_foods, get_favorite_foods or get_my_foods hit, create_food's food_id (PRODUCT), create_recipe's recipe_id (RECIPE), or a get_day row's product_id (PRODUCT) or recipe_id (RECIPE). | |
| food_type | Yes | type of that search hit, or the get_day row's food_type. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/openWorld safety. The description goes beyond them by disclosing edge cases: a macro is null when details lack it, a user product with unit ml returns serving ml as weight_g, and a premium recipe returns a forbidden error without Fitatu Premium. That is real behavioral value, though it stops short of noting pagination or result sizing.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action, then adds the returned fields and the error caveat. One long parenthetical makes it dense, but every sentence carries useful information and nothing is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values need not be re-explained, yet the tool's role in the log-food flow, its edge-case semantics, and its authorization requirement are all covered. 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.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so food_id and food_type are already fully documented including the enum. The description clarifies what measure_id is (the identifier passed onward to add_food), but adds little about the tool's own two inputs. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource: 'List the measures a food can be logged in', and immediately names the fields returned. This is clearly distinguishable from siblings like search_food, get_recipe, or add_food 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives the selecting context: this is the pre-step for logging, since 'Pass measure_id and a quantity of that measure to add_food'. It does not explicitly state when-not to use it or name an alternative tool, but the workflow positioning is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_good_daysList the good daysARead-onlyIdempotent
List the days the app's summary marks as good days (Fitatu's own rule decides which), oldest first, with their count. Pass from_date and/or to_date to keep only a period; without them, every good day there is.
| Name | Required | Description | Default |
|---|---|---|---|
| to_date | No | Day as YYYY-MM-DD; when the user says today, yesterday, this week or a weekday, call get_today and count from its date. | |
| from_date | No | Day as YYYY-MM-DD; when the user says today, yesterday, this week or a weekday, call get_today and count from its date. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnlyHint, idempotentHint, destructiveHint=false), so the description only needs to add behavior beyond them. It does: result ordering ('oldest first'), the inclusion of a count per day, and the default no-filter behavior that returns the full history. It does not discuss limits or volume, but the added ordering and default-scope facts are genuinely useful.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two compact sentences, with the core purpose and ordering front-loaded and the filtering behavior second. No filler, no restatement of the title, and every clause adds information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return-value documentation is not required, and the annotations cover the safety profile. What remains slightly thin is the meaning of 'with their count' (count of what) and any volume/limit expectation for the unfiltered case, but for a simple read-only list tool the definition is nearly complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and both parameters are documented there, including the date format and the get_today cross-reference, so the schema carries the load. The description restates the filter semantics ('keep only a period; without them, every good day there is') without adding format, boundary inclusivity, or ordering-of-arguments detail beyond the schema. Baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a specific verb and resource ('List the days ... good days'), explains the domain-specific source of the classification ('the app's summary marks as good days (Fitatu's own rule decides which)'), and states the ordering. This distinguishes it from siblings like get_day, get_range_summary and get_progress without needing to open any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives clear guidance on the date parameters ('Pass from_date and/or to_date to keep only a period; without them, every good day there is'), which is effectively a usage rule for the optional filter. However it never states when to pick this tool over get_day, get_range_summary or get_progress, so the alternative selection is left implicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_habitsRead the user's habitsARead-onlyIdempotent
Read the habits the user took up in the app (e.g. drinking water every day): per habit its habit_id, name, length_days (how long it runs), days_done and checked_days (the days ticked), enrolled_date and completed. available lists the other habits the app offers (habit_id, name, length_days, premium).
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive, and closed-world, so the safety profile is covered. The description goes beyond that by explaining the shape of the response, including the notable 'available' field that returns the broader habit catalog the app offers rather than just enrolled habits, which is genuine behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence leads with the core action and then documents field meanings tersely in parentheses. There is little waste; density of field detail is justified given the lack of parameters.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With zero parameters, full annotation coverage, and an existing output schema, the description supplies more than the minimum by glossing fields and flagging the 'available' catalog. Nothing an agent needs in order 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.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline is 4. There is nothing for the description to clarify regarding inputs, and it appropriately spends its words on output structure instead.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb (Read) and resource (the user's habits) with a concrete example ('drinking water every day') and enumerates the fields returned. It is unambiguous what the tool does. It does not name a sibling to differentiate from, but no sibling tool overlaps with habits, so this is a minor omission.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the read-only listing nature of the tool, but there is no explicit when-to-use, when-not, or alternative named. An agent can infer intent, but nothing routes it away from other read tools if ambiguity arose.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_measurement_historyRead a body size historyARead-onlyIdempotent
List the logged values of one body measurement as {date, value}, newest first: value in the user's size unit (cm unless changed in the app), fat_percentage in %. Days without that measurement are left out. Pass from_date and to_date to choose the period; without to_date it stops at today, so give it for later days; without either it lists the newest entries up to limit. The first and last value of every part over a period is get_body_measurements; body weight is get_weight_history.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of entries. | |
| to_date | No | Day as YYYY-MM-DD; when the user says today, yesterday, this week or a weekday, call get_today and count from its date. | |
| body_part | Yes | The measurement, e.g. waist; fat_percentage is body fat in %. | |
| from_date | No | Day as YYYY-MM-DD; when the user says today, yesterday, this week or a weekday, call get_today and count from its date. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive, closed-world, so the safety profile is settled. The description adds real behavioral context beyond that: values are in the user's size unit (cm unless the app setting is changed), fat_percentage is in %, days with no measurement are omitted (sparse series), and results are ordered newest first. It does not mention pagination boundaries beyond the limit cap, which holds it just short of 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose and output shape are front-loaded in the first clause, and every sentence carries required information about units, omissions, or date semantics. The middle sentences are dense with semicolon-chained conditionals, which costs some readability, but there is no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need no explanation, and the annotations cover the safety profile. Combined with the unit conventions, sparse-day behavior, date defaults and sibling routing, an agent has everything needed to call this correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 schema already documents all four parameters including formats and defaults. The description goes beyond the schema by explaining the interaction between from_date, to_date and limit (default range end, fallback to newest-N when undated), which is semantics the schema alone does not convey.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List the logged values of one body measurement'), gives the return shape {date, value} and ordering (newest first). It explicitly differentiates itself from the two closest siblings, get_body_measurements and get_weight_history, so an agent can route 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit conditional behavior for from_date/to_date/limit ('without to_date it stops at today, so give it for later days; without either it lists the newest entries up to limit') and names the alternatives with the condition that selects them ('first and last value of every part over a period is get_body_measurements'). Both when-to-use and when-to-use-something-else are covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_my_foodsList the user's own foodsARead-onlyIdempotent
List the foods the user created, their own recipes (create_recipe) and products (create_food), in the same shape as search_food hits: a RECIPE hit's food_id is what update_recipe and delete_recipe take, a PRODUCT hit's what update_food and delete_food take.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of hits. | |
| phrase | No | Words of the name; omit it for all of them. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, non-destructive and closed-world, so the safety profile is covered. The description adds genuinely useful behavior beyond that: results come back in the same shape as search_food hits and food_id differs semantically per hit type, which is what determines subsequent calls.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is a single dense sentence with no filler, front-loading the scope ('foods the user created') before the ID-mapping detail. It reads as a long run-on packing several clauses, but every clause carries meaning.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return-value documentation is unnecessary; the description instead supplies the one thing the schema can't — the cross-tool ID semantics. Purpose, scope, provenance and follow-on routing are all present, leaving nothing an agent needs missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and only two parameters exist (limit, phrase), each already documented in-schema. The description contributes nothing about filtering or paging, so this sits at the baseline where structured data does all the work.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (List) and a precisely scoped resource: foods the user created, split into their own recipes and products. This clearly separates it from siblings like search_food (public catalog) and get_favorite_foods, so an agent can pick it without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description establishes the usage context (the user's own created items, with create_recipe/create_food named as provenance) and routes downstream calls by mapping food_id to update_recipe/delete_recipe vs update_food/delete_food. It does not, however, state an explicit 'use search_food instead when...' exclusion, so the boundary with the search siblings is inferred rather than declared.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_profileRead the user's profileARead-onlyIdempotent
Read what the user's goals are computed from, for advice: height_cm, weight_kg (the current weight in the profile; a weigh-in logged for today updates it), start_weight_kg and target_weight_kg, bmi (from height_cm and weight_kg), goal (lose, maintain or gain) with pace_kg_per_week, pal (the activity level: TMR = BMR x pal), sex (male, female or null), age in years, and premium: active (whether the account has Fitatu Premium) and end_date. kg and cm whatever units the user chose in the app; a value is null when the profile lacks it. The daily goals are get_targets, the weigh-ins get_weight_history.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish this is a read-only, idempotent, non-destructive, closed-world read. The description goes beyond that by disclosing return-time behavior an agent can't infer from schema/annotations: a weigh-in logged today updates weight_kg, units follow the user's app preference, missing values are null, and premium carries both an active flag and end_date. It doesn't mention auth or error behavior, but the added context is meaningful.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose is front-loaded and the sibling routing is placed cleanly at the end, which is good structure. But the bulk is one run-on sentence with dense parentheticals enumerating every field, most of which is redundant given that an output schema exists, so much of the text does not strictly earn its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter read tool with full annotations and an output schema, the description is effectively complete: it explains scope, null/unit conventions, the live-update behavior of weight_kg, and routes to sibling tools. The only shortfall is that it spends effort restating return fields the output schema already carries rather than noting anything about failure modes.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline is 4 by the rubric. The description does not (and need not) add parameter meaning; its detail is all about return fields, which belongs to the output schema rather than to parameter semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names the resource (the user's profile) and enumerates exactly what is returned, and it explicitly distinguishes itself from the neighboring get_targets and get_weight_history at the end. The leading framing ('what the user's goals are computed from, for advice') is slightly indirect about the tool's own purpose, but the field list disambiguates it fully from siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It offers a light usage hint ('for advice') and routes the agent to get_targets for daily goals and get_weight_history for weigh-ins, which is genuine sibling differentiation. However, it never states explicitly when to call get_profile versus those tools, so the guidance is implied rather than spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_progressCheck progress against goalsARead-onlyIdempotent
Progress against the user's goals, day by day, for one day or a range of up to 62 days: per day and for energy, protein, fat and carbohydrate, logged (every row, planned or eaten; null when nothing is logged that day), the goal (target in kcal for energy; target_min and target_max in g for a macro, which is on target between the two) and left (the goal minus logged, a macro's from target_max; negative when over). totals gives the whole range: logged, eaten (only rows ticked as eaten) and the goal summed over the days. Works on every account; without Fitatu Premium it reads each day on its own, so it covers at most 31 days, and each day has eaten too. Answers 'what is left today', 'did I hit protein' and how each day went; a summary of a week or month with weight and top foods, or of a longer range, is get_report (over 31 days without Fitatu Premium, get_range_summary).
| Name | Required | Description | Default |
|---|---|---|---|
| to_date | Yes | Day as YYYY-MM-DD; when the user says today, yesterday, this week or a weekday, call get_today and count from its date. | |
| from_date | Yes | Day as YYYY-MM-DD; when the user says today, yesterday, this week or a weekday, call get_today and count from its date. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent and non-destructive, so safety is covered; the description then adds real behavioral context beyond them: the 62-day ceiling, the degraded behavior without Fitatu Premium (per-day reads, max 31 days, plus an eaten value), and that rows are null when nothing is logged. These are operational constraints the agent cannot infer from 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose and scope are front-loaded, and every sentence carries information (null handling, macro target semantics, premium limits, alternatives). It is a dense single paragraph, however, and mixing return-field semantics with routing guidance makes it harder to scan than a short structured form would be.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be spelled out, yet the description still explains the non-obvious semantics (goal is kcal for energy but target_min/target_max in grams for macros; 'left' for a macro is measured from target_max and goes negative when over). Combined with the range limits and premium caveat, an agent has everything needed to call and interpret this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and both date parameters are documented there, so baseline 3 applies. The description goes beyond that by stating the meaningful bound on the pair (up to 62 days, 31 without Premium), which is genuinely parameter-relevant range semantics rather than a restatement of the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening names the exact resource and scope: goal progress per day, over one day or a range of up to 62 days. It also explicitly distinguishes itself from the two nearest siblings (get_report, get_range_summary) including the conditions under which each applies, so an agent can route 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Concrete example questions ('what is left today', 'did I hit protein') are given, plus an explicit alternative with its trigger condition: weekly/monthly summaries with weight and top foods go to get_report, and ranges over 31 days without Fitatu Premium go to get_range_summary. When-to-use and when-to-use-something-else are both covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_range_summarySummarize a date rangeARead-onlyIdempotent
Read Fitatu's own summary of a date range, as the app's Summary tab shows it: nutrition (energy in kcal; protein, fat, carbohydrate, fiber, sugars, salt in g) counts every logged row, ticked as eaten or not, like get_day's totals; eaten_nutrition the same for the rows ticked as eaten only; activity_energy is kcal burned. Both are totals over the whole range, not daily averages: divide by the number of days for one. For goals and what is left per day, use get_progress.
| Name | Required | Description | Default |
|---|---|---|---|
| to_date | Yes | Day as YYYY-MM-DD; when the user says today, yesterday, this week or a weekday, call get_today and count from its date. | |
| from_date | Yes | Day as YYYY-MM-DD; when the user says today, yesterday, this week or a weekday, call get_today and count from its date. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/idempotent annotations, it discloses the exact accounting semantics of each field: nutrition counts every logged row whether ticked eaten or not, eaten_nutrition only ticked rows, activity_energy is kcal burned. The warning that both are whole-range totals rather than daily averages is a genuinely important interpretive caveat that annotations cannot convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core purpose and every clause carries information, with no filler. It is slightly dense given the stacked parentheticals on units and the get_day comparison, but nothing is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return formatting need not be explained, yet the description still decodes the field semantics an agent needs to interpret the numbers correctly. Combined with the routing guidance to get_progress, nothing required for correct invocation or interpretation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and both date parameters are documented in-schema with the get_today referencing guidance, so the baseline is 3. The description adds range-level semantics ('totals over the whole range, not daily averages') but nothing further about the date parameters themselves.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (read Fitatu's own summary of a date range) and anchors it to the app's Summary tab so the agent knows exactly what data is returned. It explicitly distinguishes itself from get_day totals and get_progress, so it is identifiable 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Names the alternative (get_progress) and the condition that selects it: 'For goals and what is left per day, use get_progress.' It also clarifies the relationship to get_day's totals, giving the agent both when-to-use and when-not-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_recent_foodsList recently logged foodsARead-onlyIdempotent
List foods the user recently logged in a meal, most used first, in the same shape as search_food hits. Handy for 'my usual breakfast'.
| Name | Required | Description | Default |
|---|---|---|---|
| meal | Yes | Meal slot. The keys are fixed, but users rename their meals in the app: match the user's words against get_day's meal_name and pass that meal's meal_key. Only the meals get_day lists exist. | |
| limit | No | Maximum number of hits. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive, and closed-world, so safety is covered. The description adds genuinely useful behavioral context beyond that: the results are sorted 'most used first' and mirror the shape of search_food hits. It omits empty-result or pagination behavior, but coverage is strong relative to a simple 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences with zero waste; the core purpose, ordering, and result shape are front-loaded. The usage hint follows efficiently without padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values need not be described, and full schema coverage handles parameters. Annotations carry the safety profile. The description covers scope, ordering, and a use case, leaving only sibling routing unaddressed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the meal enum and limit are fully documented in the schema (including the non-trivial instruction to map user meal words against get_day's meal_name). The description adds nothing param-specific, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('List'), a precise resource ('foods the user recently logged in a meal'), plus ordering ('most used first') and result shape ('same shape as search_food hits'). An agent can distinguish this from get_favorite_foods or get_top_foods by the 'recently logged in a meal' scope, though no sibling is named explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase "Handy for 'my usual breakfast'" gives a concrete usage scenario, implying when to reach for this tool. However, it names no alternatives (get_favorite_foods, get_top_foods, get_my_foods) and states no when-not conditions, leaving routing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_recipeRead a recipeARead-onlyIdempotent
Read one recipe in full, from the catalog or the user's own: name, servings (how many servings the ingredients make), ingredients for the whole recipe (food_id, food_type, quantity, measure_id, name, measure_name and weight_g; create_recipe and update_recipe take only the first four: drop the rest), description (the steps), per_serving (its portion measure as get_food_measures lists it: weight_g, energy_kcal, protein_g, fat_g and carbohydrate_g of one serving; null when it has none), cooking_time and preparation_time in minutes as the catalog gives them, meals (the meal types it suits), tags (e.g. vegan, keto, polish), rating, premium, deleted, and own: whether it is the user's private recipe, which update_recipe and delete_recipe take. A premium recipe needs Fitatu Premium: without it a forbidden error.
| Name | Required | Description | Default |
|---|---|---|---|
| recipe_id | Yes | food_id of a RECIPE hit (search_recipes, search_food, get_my_foods, get_favorite_foods, get_recent_foods), create_recipe's recipe_id or a get_day row's recipe_id; never a product's id. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, non-destructive behavior, so the bar is lower, yet the description still adds real behavioral context: a premium recipe without Fitatu Premium yields a forbidden error, 'own' flags a private user recipe, and 'deleted'/'per_serving: null' edge states are disclosed. Return-format detail is largely redundant with the output schema, keeping it out of the top band.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The scope statement is front-loaded and there is no boilerplate, but the bulk is a long run-on enumeration of return fields (food_id, quantity, measure_id, weight_g, energy_kcal...) that an output schema already defines. That verbosity dilutes the one or two genuinely valuable caveats buried inside.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description needn't explain return values, and it still covers the key call-time concerns: which ids are valid, the Premium auth gate, and private-vs-catalog ownership. Nothing essential to a correct single fetch is missing, though the field-by-field inventory is surplus.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% for the single recipe_id parameter, so the baseline is 3; the description adds the catalog-vs-own scope but nothing about id format, origin, or failure modes beyond what the schema description already supplies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Read one recipe in full') and immediately scopes it ('from the catalog or the user's own'), which distinguishes it from search_recipes/get_my_foods list tools and from get_food_measures. An agent can identify this as the single-record recipe fetch 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied rather than stated: the description contrasts what get_recipe returns with what create_recipe and update_recipe consume, and notes the Premium precondition, but never says explicitly when to call this versus search_recipes or get_my_foods. The id-source guidance lives in the schema, not the description.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_reportWeekly or monthly reportARead-onlyIdempotent
A weekly or monthly report (or one of any range) in one call. nutrition: for energy, protein, fat and carbohydrate the range's totals, logged (every row, planned or eaten) and eaten (rows ticked as eaten), and daily: logged averaged over days_logged (the days with anything logged) next to the average daily goal (target for energy, target_min and target_max for a macro). weight: the first and last weigh-in of the range (date, value in the user's weight unit) and the change; null without one. top_foods: the 5 foods with the most energy and the 5 with the most protein, as get_top_foods gives them. Without Fitatu Premium, top_foods is null (top_foods_note says why) and the range is at most 31 days; get_range_summary gives the totals of a longer one.
| Name | Required | Description | Default |
|---|---|---|---|
| to_date | Yes | Day as YYYY-MM-DD; when the user says today, yesterday, this week or a weekday, call get_today and count from its date. | |
| from_date | Yes | Day as YYYY-MM-DD; when the user says today, yesterday, this week or a weekday, call get_today and count from its date. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safe-read profile (readOnly, idempotent, non-destructive), and the description adds genuinely new behavior: the Premium gating (top_foods becomes null, top_foods_note explains why), the 31-day free-tier range cap, and null-for-weight semantics. This is exactly the kind of access/limit 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
The opening purpose sentence is front-loaded, but the rest is a dense block that spends most of its length enumerating return values (nutrition totals, eaten vs logged, weight fields, top_foods contents) that the output schema already supplies. That return-shape detail is largely redundant and crowds out the routing/limit guidance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a report tool with a full output schema and complete annotations, the description supplies the remaining edge cases an agent needs: free-tier truncation, null top_foods, null weight, and the longer-range alternative. Nothing needed to call it correctly appears to be missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and both dates are fully documented in the schema (including the get_today counting tip), so the description adds no parameter-level meaning. Baseline 3 is appropriate when the schema carries the parameter semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb/resource ('a weekly or monthly report (or one of any range) in one call') and immediately delineates scope against siblings like get_range_summary and get_top_foods. An agent can tell exactly what it returns 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It names an explicit alternative and the condition that selects it: 'the range is at most 31 days; get_range_summary gives the totals of a longer one.' That is real routing guidance, though it is buried mid-paragraph rather than stated as front-loaded when/when-not guidance, and it does not cover the get_day/get_today boundary.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_shopping_listMake a shopping listARead-onlyIdempotent
A shopping list for a range of up to 14 days, worked out from the rows planned in the diary and not ticked as eaten. products sums them per product and measure (product_id, name, measure_name, quantity of that measure, weight_g; weight_g is null when a row does not give it), with the ingredients of each planned recipe added for its portions; recipes lists those recipes (date, meal, recipe_id, name, portions, and expanded false when its ingredients could not be read or it is a premium recipe on an account without Fitatu Premium, so they are missing from products); other_items lists custom and other rows as they are. It cannot know what the user already has at home, pack sizes or anything not planned in the diary: say so. Start at today ("this week" is today to Sunday): rows on past days not ticked as eaten were usually eaten anyway. One request per day and one per recipe.
| Name | Required | Description | Default |
|---|---|---|---|
| to_date | Yes | Day as YYYY-MM-DD; when the user says today, yesterday, this week or a weekday, call get_today and count from its date. | |
| from_date | Yes | Day as YYYY-MM-DD; when the user says today, yesterday, this week or a weekday, call get_today and count from its date. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover the safety profile (readOnly, idempotent, non-destructive), and the description adds substantial behavioral context beyond that: the 14-day cap, the 'one request per day and one per recipe' rate guidance, the unticked-row assumption, and explicit limitations (cannot know what the user has at home, pack sizes, unplanned items). This is richer than most read-only definitions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One dense run-on sentence packs the products/recipes/other_items explanation plus caveats into a wall of text, and the 'say so' instruction is grammatically stranded. It is front-loaded and information-rich, but the structure makes it hard to parse and the return-field detail is largely redundant with the output schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The output schema exists, so explaining return fields is redundant, but the description still covers the critical limitations an agent needs before calling (no pantry awareness, no pack sizes, unticked-row assumption, date-range semantics). It is complete for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and both parameters are documented there, so the baseline is 3. The description adds range semantics (up to 14 days, start at today) but no per-parameter detail beyond what the schema already provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific resource (shopping list) and the exact derivation rule (rows planned in the diary not ticked as eaten, over up to 14 days). It does not name a sibling that is similar, but the derivation is distinctive enough to separate it from get_range_summary or get_day.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear usage context: start at today, 'this week' means today to Sunday, and past unticked rows are assumed eaten. This tells the agent how to choose the date range. It does not name an alternative tool or say when not to use it, so it falls 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_targetsRead the daily goalsARead-onlyIdempotent
Read the user's daily goals for a day: energy in kcal, protein/fat/carbohydrate as grams and percent of energy, and BMR/TMR in kcal. date is the day asked for; settings_since is when these goals took effect (an earlier day is normal).
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | Day as YYYY-MM-DD; when the user says today, yesterday, this week or a weekday, call get_today and count from its date. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive, closed-world), so the bar is lower; the description goes further by explaining that goals take effect from a settings_since date and that an earlier effective date than the requested day is normal. That is genuine interpretive context that prevents the agent misreading stale-looking targets.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences, front-loaded with purpose and returned fields before the scoping notes; no filler. The settings_since clause sits in the same breath as the parameter discussion, which reads slightly ambiguous about whether it is an input or an output field.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter read tool with an output schema present, the description is essentially complete: purpose, returned fields, date scoping, and the settings_since semantics are all covered. The only soft spot is the ambiguous status of settings_since, which the output schema could have clarified.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the sole parameter's meaning, including relative-date handling, is fully spelled out in the schema, so baseline 3 applies. The description adds only 'date is the day asked for', and its mention of 'settings_since' names something that is not an input parameter (additionalProperties is false), which risks slight confusion rather than adding parameter clarity.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb+resource ('Read the user's daily goals for a day') and enumerates the returned content (energy, macro grams/percent, BMR/TMR), so the agent knows exactly what this returns. It does not explicitly point at the sibling it is not (set_targets) or distinguish itself from get_today/get_profile, so it stops short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'date is the day asked for' hints at how to source the parameter but there is no statement of when to use this tool versus set_targets, get_today, or get_profile, and no prerequisites or exclusions. The actual date-resolution guidance ('call get_today and count from its date') lives in the schema, not the description.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_todayGet today's dateARead-onlyIdempotent
Today's date in the user's time zone: date (YYYY-MM-DD), timezone and weekday. Call it when the user says today, yesterday, tomorrow, this week or a weekday, and count from it.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint=false, so the safety profile is covered. The description adds genuinely new behavioral context: the value is computed in the user's time zone, and it enumerates the returned fields, telling the agent this is a stable per-day anchor to compute relative dates from.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, zero filler, and the return shape is front-loaded before the usage trigger. Every clause carries information the agent needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description needn't explain return structure, and it still summarizes it in one clause. Zero parameters, full annotation coverage, and no missing prerequisites make this complete for a trivial read tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is nothing for the description to disambiguate. That matches the baseline of 4 for parameter-free tools.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource and pins down the exact payload: "Today's date in the user's time zone: date (YYYY-MM-DD), timezone and weekday." The word "today" and the timezone scoping distinguish it from the sibling get_day, which an agent can infer handles arbitrary dates.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly names the trigger phrases ("today, yesterday, tomorrow, this week or a weekday") and even instructs the agent to "count from it," which is actionable usage context. It does not name the alternative (get_day) for non-today dates or state any exclusions, so it falls short of a full when/when-not treatment.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_top_foodsRank foods by a nutrientARead-onlyIdempotent
The foods that gave the user the most of a nutrient over a date range, most first: name, amount (kcal for energy, g otherwise, summed over the range) and per100 (the food's own amount per 100 g; null for a custom item). A recipe may be listed as its ingredients. Answers 'where does my sugar come from'. Premium only: on an account without Fitatu Premium, Fitatu refuses it (a forbidden error); tell the user, do not retry.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of hits. | |
| to_date | Yes | Day as YYYY-MM-DD; when the user says today, yesterday, this week or a weekday, call get_today and count from its date. | |
| nutrient | No | What to rank the foods by. | energy |
| from_date | Yes | Day as YYYY-MM-DD; when the user says today, yesterday, this week or a weekday, call get_today and count from its date. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, non-destructive, but the description adds substantial non-obvious behavior: Premium gating with a 'forbidden' failure mode and an explicit do-not-retry instruction, recipe expansion into ingredients, unit conventions (kcal for energy, g otherwise, summed over the range), and null per100 for custom items. This goes well beyond what the annotations convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the result shape and a one-phrase example query, then the Premium constraint. Dense and mostly waste-free, though the first sentence's nested parentheticals (unit rules, per100 semantics) make it slightly heavy to parse for information the output schema may already carry.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers the operation, ordering, unit conventions, recipe expansion, and the Premium failure path, which is the main thing that could cause a wrong agent action. Since an output schema exists, some of the returned-field explanation is redundant, and date-parsing guidance lives in the schema rather than the description, so it is strong but not exhaustive.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, including the nutrient enum and the get_today counting hint on both date parameters, so the schema carries the parameter burden. The description adds only indirect meaning (units/summation tied to the nutrient choice) and no per-parameter syntax or constraints beyond the schema. Baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb-like operation and resource: foods ranked by nutrient intake over a date range, with ordering ('most first') and the returned fields named. It is clearly distinguishable from siblings like get_favorite_foods (favorites, not nutrient totals) and get_range_summary (aggregate totals, not per-food ranking). An agent can select it 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a concrete usage framing ('where does my sugar come from') and a hard precondition with handling instructions: Premium-only, forbidden error, tell the user, do not retry. It does not explicitly name an alternative tool to use instead when the user wants totals rather than rankings, so it stops short of full 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.
get_waterRead the water drunkARead-onlyIdempotent
Read how much water the user drank on a day (water_ml), the day's goal (target_ml) and the size of one glass in the user's settings (glass_ml); each is null when unknown.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | Day as YYYY-MM-DD; when the user says today, yesterday, this week or a weekday, call get_today and count from its date. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, non-destructive and closed-world, so safety and repeatability are covered. The description adds genuine behavioral context beyond that by disclosing null semantics for each field when unknown, which tells the agent how to interpret partial results.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single sentence that front-loads the action and resource, then parenthetically lists the returned values and the null case. Every clause earns its place with no filler or repetition of the title.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values need not be explained, yet the description still summarizes them and covers the null case; annotations cover the safety profile and the sole parameter is fully documented. The only missing element is routing guidance against overlapping read tools such as get_range_summary or get_progress.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the date parameter's format, required status, and relative-date handling are fully documented in the schema, so the baseline of 3 applies. The description names the day concept but adds no parameter-level meaning (syntax, format, edge cases) beyond what the schema already supplies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
It uses a specific verb (Read) over a specific resource (water drunk on a day) and even enumerates the three returned fields, so the function is unmistakable. It does not, however, explicitly contrast itself with the write sibling set_water or with range/summary siblings like get_range_summary, so it stops short of full sibling differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The purpose implies when to call it (fetching a single day's water), and the date parameter's schema description routes relative-date phrasing to get_today. But the description itself never states when to prefer this over set_water or over aggregate tools, nor any exclusion, so usage remains implied rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_weight_historyRead the weight historyARead-onlyIdempotent
List logged body weights as {date, value, difference, direction}, newest first: value in the user's weight unit (kg unless changed in the app), difference from the previous entry, direction the weight goal (1 gain, -1 lose, 0 keep). Pass from_date and to_date to choose the period; without them it lists the newest entries up to limit, however old (there is no default period). For the change over a long period, get_report.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of entries. | |
| to_date | No | Day as YYYY-MM-DD; when the user says today, yesterday, this week or a weekday, call get_today and count from its date. | |
| from_date | No | Day as YYYY-MM-DD; when the user says today, yesterday, this week or a weekday, call get_today and count from its date. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint=false, so the safety profile is covered. The description adds real behavioral context beyond that: newest-first ordering, the fact that a limit-only call has no default period and can return very old entries, and the meaning of the direction codes (1 gain, -1 lose, 0 keep). It doesn't discuss pagination or truncation signalling, keeping it short of 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the return shape, then the period/limit behavior, then the alternative tool, in a tight sequence with no filler. The parenthetical asides make it slightly dense, but every sentence carries information an agent needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be re-explained, yet the description still gives enough about ordering, defaults, and field meaning for correct invocation. With the low-complexity schema (3 optional params) and annotations covering safety, nothing an agent needs is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 goes further by explaining the fallback semantics of omitting from_date/to_date and how limit interacts with them ('newest entries up to limit, however old'). It also clarifies the unit context (kg unless changed in the app) and the derived fields difference/direction, which the schema does not define.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List logged body weights') and immediately enumerates the returned fields {date, value, difference, direction}, so an agent knows both the action and the shape. It differentiates itself from nearby siblings like get_measurement_history and get_report by naming get_report explicitly for the long-period case.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Spells out both branches of use: pass from_date/to_date to select a period, or omit them to get the newest entries up to limit with no default period. It also routes the agent to get_report when the question is change over a long period, which is explicit alternative-selection guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
log_measurementsLog body measurementsADestructiveIdempotent
Save body measurements for a day: sizes in the user's size unit (cm unless changed in the app), fat_percentage in %. Only the values given are replaced; the day's other measurements and its weight are kept. Body weight is log_weight. data.ok says the server accepted it.
| Name | Required | Description | Default |
|---|---|---|---|
| calf | No | Calf circumference. | |
| date | Yes | Day as YYYY-MM-DD; when the user says today, yesterday, this week or a weekday, call get_today and count from its date. | |
| hips | No | Hips circumference. | |
| neck | No | Neck circumference. | |
| chest | No | Chest circumference. | |
| thigh | No | Thigh circumference. | |
| waist | No | Waist circumference. | |
| biceps | No | Biceps circumference. | |
| stomach | No | Stomach circumference. | |
| fat_percentage | No | Body fat in %. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare the safety profile (not read-only, destructive, idempotent), and the description adds the crucial nuance the annotations cannot: 'Only the values given are replaced; the day's other measurements and its weight are kept.' It also discloses unit conventions and the data.ok response signal, so the destructiveHint is properly scoped.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four short sentences, front-loaded with the action and scope, followed by units, partial-update semantics, sibling routing, and response meaning. Every sentence carries distinct information with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 10-parameter mutation with an output schema present, the description covers what an agent needs: units, partial-replace behavior, sibling routing, and confirmation signal. Return-value details are correctly left to the output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 genuinely additive semantics absent from the schema: sizes are in the user's size unit (cm unless changed) and fat_percentage is in %. Unit interpretation is not in the property descriptions, so this raises it above baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource with scope: 'Save body measurements for a day.' It even disambiguates from the closest sibling by noting 'Body weight is log_weight', so an agent can separate measurement logging from weight logging 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear context for when this applies (logging measurements for a day) and explicitly routes weight to the alternative tool log_weight. It stops short of naming the read-side siblings (get_body_measurements, get_measurement_history) or stating exclusions, so it is clear but not a full when/when-not map.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
log_weightLog body weightADestructiveIdempotent
Save the user's body weight for a day in kg, replacing a weight already saved for that day; other body measurements of that day are kept. data.ok says the server accepted it.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | Day as YYYY-MM-DD; when the user says today, yesterday, this week or a weekday, call get_today and count from its date. | |
| weight_kg | Yes | Body weight in kg; convert pounds first (1 lb = 0.4536 kg). |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint, idempotentHint and readOnlyHint=false. The description adds genuinely useful behavioral context beyond them: the write replaces only the existing weight for that day while other body measurements are preserved, and the 'data.ok' acceptance signal clarifies what success looks like.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single tightly written sentence that front-loads the action and scope and appends the replacement rule and response signal with no wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter mutation with full schema coverage and an output schema, the description covers mutation scope, preservation of other measurements, and response semantics. The data.ok mention is slightly redundant against the output schema, but nothing an agent needs to call the tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so both parameters are fully documented in the schema (including the YYYY-MM-DD format, lb conversion, and get_today redirect). The description's 'in kg' and 'for a day' only restate the schema, adding no new semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb+resource ('Save the user's body weight for a day in kg') and clarifies the scope is a single day's weight, which distinguishes it from the sibling log_measurements. It stops short of naming that sibling explicitly, so it falls just below the top tier.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit when-to-use guidance or named alternatives are given. Usage is only implied via the 'for a day' scoping and the replacement behavior, so an agent must infer that this is the tool for logging weight versus broader measurement logging.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
move_itemMove a logged foodADestructive
Move a logged food row to another meal and/or day. The moved row gets a new row_id, returned here; the old one is gone. data.ok says a re-read confirms both.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | Day as YYYY-MM-DD; when the user says today, yesterday, this week or a weekday, call get_today and count from its date. | |
| row_id | Yes | row_id of a food row on that day, from get_day (meals[].items[].row_id). | |
| to_date | No | Day to move it to, as YYYY-MM-DD (default: the same day); when the user says today, yesterday, this week or a weekday, call get_today and count from its date. | |
| to_meal | Yes | Meal to move it to. Meal slot. The keys are fixed, but users rename their meals in the app: match the user's words against get_day's meal_name and pass that meal's meal_key. Only the meals get_day lists exist. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=false, so the safety profile is covered. The description goes further and discloses the non-obvious consequence: the moved row receives a new row_id and the old one no longer exists, plus that data.ok is a re-read confirmation. That row_id change is exactly the kind of follow-up-relevant behavior structured fields don't convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences with the core action front-loaded, followed by the two behavioral facts an agent actually needs. No filler or restatement of the title.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, and the description wisely limits itself to the one behavioral twist (new row_id, old row gone). For a destructive mutation, nothing essential about correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 date, row_id, to_date, and the meal_key matching rule thoroughly. The description adds no parameter-level detail (e.g., no mention of required vs optional or to_date defaulting), so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Move a logged food row to another meal and/or day') and clarifies that this is a relocation, not a copy, by noting the old row is gone. It never names the nearest sibling (copy_meal, update_item), so the differentiation is only implied.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'to another meal and/or day' implies the intended use case, and the schema descriptions point at get_day/get_today as upstream steps. However, there is no explicit statement of when to choose this over update_item or copy_meal, so the agent must infer.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
preview_removalPreview a removalARead-onlyIdempotent
Show what remove_items would delete, without deleting anything: would_remove lists each food row with what it is (meal, meal_name, row_id, name, food_type, food_id, measure_id, measure_name, measure_quantity, energy in kcal, protein/fat/carbohydrate in g, eaten), as remove_items' removed does; missing lists the ids that are not food rows on the day. data.ok is false when one is missing. Call it before remove_items and name the foods to the user, not their row_ids.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | Day as YYYY-MM-DD; when the user says today, yesterday, this week or a weekday, call get_today and count from its date. | |
| row_ids | Yes | row_ids from get_day. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true and destructiveHint=false, and the description reinforces the no-deletion guarantee. It adds genuinely useful behavior beyond annotations: what happens to non-food ids (they appear in 'missing') and that data.ok flips to false in that case.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core purpose and the safety guarantee in the first clause; the rest is dense but each clause carries a distinct fact (return shape, error signal, workflow ordering, output presentation rule). No filler sentences.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present the description need not enumerate return fields, yet it still explains the would_remove/missing split and the data.ok=false condition. Nothing an agent needs to invoke this correctly, or to interpret the preview, is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, and the schema already documents 'date' (including the get_today counting rule) and 'row_ids' (sourced from get_day). The description references row_ids but adds no syntax or format detail 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.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Show what remove_items would delete, without deleting anything') and explicitly contrasts itself with the sibling that performs the real deletion. An agent can distinguish preview_removal from remove_items 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit when-to-use directive ('Call it before remove_items') and a usage rule about output handling ('name the foods to the user, not their row_ids'). It names the alternative tool and the condition that selects this one.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
remove_activityRemove a workoutADestructiveIdempotent
Delete a logged activity by row_id (activities[].row_id in get_day, or from add_activity). An id that is not an activity on the day (already deleted, or a food row's row_id) gives data.ok false, reason item_not_found and a message listing the day's activities, so repeating the call is safe; the result's top-level ok only says the call ran.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | Day as YYYY-MM-DD; when the user says today, yesterday, this week or a weekday, call get_today and count from its date. | |
| row_id | Yes | row_id of an activity on that day. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: it explains the exact failure response for a stale or non-activity id (data.ok false, reason item_not_found, message listing the day's activities) and clarifies that the top-level ok only confirms the call ran. This response-field semantics is not derivable from the 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads verb and resource, then layers id source and error semantics; every clause carries information, though the second half is a long semicolon-heavy run-on that slightly taxes readability.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive mutation with an output schema and full annotation coverage, it supplies the key missing pieces (id provenance, idempotent error behavior, ok-means-ran caveat). The only omission is explicit routing to preview_removal as an alternative.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is already 100% (baseline 3), and the description adds genuine meaning by telling the agent where row_id originates (get_day or add_activity), reducing the chance of passing a food row's id.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Delete a logged activity') and pins the exact identifier source ('activities[].row_id in get_day, or from add_activity'), which cleanly separates it from sibling bulk operations like remove_items and from add_activity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear context for when it applies (you have a row_id for an activity on the day) and reassures that repeats are safe. It does not explicitly contrast with siblings such as preview_removal or remove_items, so a 4 rather than 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
remove_itemsRemove logged foodsADestructiveIdempotent
Delete logged food rows from a day by row_id (meals[].items[].row_id in get_day). removed lists each deleted row with what it was (meal, meal_name, row_id, name, food_type, food_id, measure_id, measure_name, measure_quantity, energy in kcal, protein/fat/carbohydrate in g, eaten), enough to add it again: with add_food, or with add_custom_item from its name and nutrition when food_id is null (a custom row); failed lists the rows still there. Ids that are not food rows on the day (already deleted, or an activity's row_id) are listed in missing, so repeating the call is safe. Preview a removal with preview_removal, which only reads; dry_run does the same here. data.ok is false when a row was missing or failed; the result's top-level ok only says the call ran.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | Day as YYYY-MM-DD; when the user says today, yesterday, this week or a weekday, call get_today and count from its date. | |
| dry_run | No | Only report what would be deleted; preview_removal does it without a destructive call. | |
| row_ids | Yes | row_ids from get_day. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, idempotentHint=true and readOnlyHint=false, so the safety profile is covered. The description goes further by explaining the mechanism behind idempotency (non-food/already-deleted ids land in missing), the recovery data returned, and the distinction between data.ok and the top-level ok, which is real added context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the action and row identifier in the first clause, and every sentence carries information. It is dense to the point of being run-on, and the dry_run/preview_removal point is repeated from the schema, so it is not maximally tight.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive, idempotent mutation this covers what it needs: identifier source, preview path, restoration options, failure semantics and the missing/failed/removed distinction. An output schema exists, so the return-value detail is largely redundant but harmless.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 provenance for row_ids (the exact meals[].items[].row_id path) and clarifies dry_run's relation to preview_removal beyond the schema's own wording. That is a modest but real increment over the structured fields.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (delete logged food rows from a day) and pins the identifier to its source (meals[].items[].row_id in get_day). It is clearly separable from siblings like preview_removal, add_food, update_item and remove_activity, so an agent can route 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly names preview_removal as the read-only alternative and notes dry_run does the same here, gives the recovery path (add_food for normal rows, add_custom_item when food_id is null), and warns that repeating the call is safe. This is genuine when/when-not guidance plus alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_activitySearch activitiesARead-onlyIdempotent
Search the activity (workout) catalog, e.g. 'bieganie' (running) or 'rower' (cycling). Each hit has activity_id for add_activity, name, and energy_kcal: the catalog's estimate for the effort in energy_for (e.g. '5 km w 00:30:00') for an average person. Scale it to what the user did to get the energy_kcal that add_activity needs.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of hits. | |
| phrase | Yes | Activity name, e.g. 'bieganie'. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare this a safe, idempotent, open-world read. The description goes further by disclosing the non-obvious semantics of a returned field: energy_kcal is the catalog estimate for energy_for (e.g. '5 km w 00:30:00') for an average person and must be scaled. That is real behavioral context 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with what is searched, then the return shape, then the scaling requirement. Every sentence carries information, though the middle sentence is densely packed with field semantics.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values need not be enumerated, yet the description still covers the one genuinely non-obvious piece: that energy_kcal is an average-person estimate tied to energy_for and must be scaled before add_activity. Nothing an agent needs to call and chain this tool is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so both parameters are already documented, and the description only repeats the 'bieganie' phrase example already in the schema. It adds no new syntax or interpretation for phrase or limit, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (search) and resource (activity/workout catalog) and immediately disambiguates from the food and recipe search siblings by naming the catalog and giving workout examples ('bieganie', 'rower'). An agent can tell what domain this searches 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description frames the tool within the workflow: each hit carries activity_id to feed add_activity, and the returned energy_kcal must be scaled before add_activity can use it. It gives clear context but never states when *not* to use it or names the alternative catalog-search siblings explicitly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_foodSearch the food catalogARead-onlyIdempotent
Search the Fitatu food catalog (Polish names work best). Each hit has food_id and type (PRODUCT or RECIPE) for add_food and get_food_measures, name, brand, its default measure (measure_id, name, weight_g or capacity_ml of one measure) with energy_kcal for one such measure, times_used (how often the user logged it; null when the server does not say) and favorite (whether it is one of the user's favourites). A barcode belongs in find_by_barcode. With locale, the hits come from that country's catalog (foods the user logged before show up too) and can be logged like any other.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of hits. | |
| locale | No | Another country's catalog, e.g. de_DE for a product bought in Germany; omit it for the user's own (Polish unless changed in the app). | |
| phrase | Yes | What to look for, e.g. 'jajko' or 'owsianka'. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover readOnly/idempotent/non-destructive safety, and the description goes further by disclosing the per-hit fields, that times_used is null when the server does not say, and that a locale-scoped search also surfaces previously logged foods. It does not mention pagination or result-ordering behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the core capability and the barcode routing, then enumerates return fields compactly. It is dense but nearly every clause carries information; the return-field enumeration is the only part that borders on redundant given the output schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a three-parameter read-only search with a full schema and an output schema, the description covers scope, locale behavior, sibling routing, and return semantics. 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.
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, but the description adds real meaning: 'Polish names work best' and the semantics of locale (that the returned foods can be logged like any other, and that user-logged foods appear too) go beyond the enum's field description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Search) and resource (the Fitatu food catalog) and immediately distinguishes itself from siblings by declaring that a barcode belongs in find_by_barcode. The PRODUCT/RECIPE type and food_id are named, so an agent knows exactly what class of entity is returned.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes barcode lookups to find_by_barcode and explains the locale selection condition (omit for the user's own catalog, set for another country). It does not, however, contrast with search_recipes, get_my_foods, get_recent_foods, or get_favorite_foods, which are close neighbours for the same catalog.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_recipesSearch recipe ideasARead-onlyIdempotent
Search the Fitatu recipe catalog for meal ideas, e.g. phrase 'kurczak' with max_energy_kcal 500 for a chicken dinner of at most 500 kcal, or diets ['vegan'], meal 'breakfast' and max_cooking_time 10 for a quick vegan breakfast. The filters are per portion and all apply together; all but max_energy_kcal need Fitatu Premium (without it a forbidden error: tell the user, search by phrase and max_energy_kcal instead). Each hit is shaped like a search_food hit of type RECIPE (food_id, name, energy_kcal and measure of one portion) plus cooking_time and preparation_time as the catalog gives them, rating, and premium: whether the app keeps the recipe for Fitatu Premium (get_recipe and get_food_measures read it only with Premium). get_recipe gives a hit's ingredients and steps. Log one with add_food: food_type RECIPE, quantity the portions.
| Name | Required | Description | Default |
|---|---|---|---|
| meal | No | Only recipes the catalog suggests for this meal type (dinner is obiad, supper kolacja). | |
| diets | No | Diets every hit must fit, e.g. ['vegan', 'gluten_free']. | |
| limit | No | Maximum number of hits. | |
| phrase | No | Words to look for, e.g. 'kurczak' or 'sałatka'; omit it to browse. | |
| min_protein_g | No | Only recipes with at least this many g of protein per portion. | |
| max_energy_kcal | No | Only recipes of at most this many kcal per portion. | |
| max_cooking_time | No | Only recipes with a cooking_time of at most 10 or 30 minutes, the catalog's two time filters. | |
| max_carbohydrate_g | No | Only recipes with at most this many g of carbohydrate per portion. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover readOnly/idempotent/non-destructive, and the description adds substantive behavior beyond them: Premium-only filters with a 'forbidden' error path, per-portion semantics, the exact hit payload, and the meaning of the `premium` flag including which tools it gates.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single dense paragraph that front-loads examples before constraints, and nearly every clause carries information. It is on the heavy side with multiple cross-tool references packed together, but not padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an 8-parameter optional-filter search with full schema coverage and an output schema, the description supplies everything else an agent needs: gating, error handling, filter interaction semantics, and follow-up tools.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 meaning: worked examples ('kurczak' with max_energy_kcal 500, diets ['vegan'] with meal 'breakfast'), the AND-together and per-portion semantics of the filters, and the note that max_cooking_time uses the catalog's two fixed time filters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (search the Fitatu recipe catalog) and immediately scopes it with concrete examples using actual filter values. It distinguishes itself from the food-search sibling by framing hits as 'a search_food hit of type RECIPE', 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives rich context: filters are per portion and AND together, Premium gating with a prescribed fallback ('tell the user, search by phrase and max_energy_kcal instead'), and routes to get_recipe for details and add_food for logging. It stops short of explicitly saying when to prefer search_food over this tool, so it isn't fully explicit on alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_favoriteAdd or remove a favouriteAIdempotent
Add a catalog food to the user's favourites, or remove it with favorite false. food_id and food_type come from search_food, get_recent_foods or get_favorite_foods. Repeating it is safe. The server applies it asynchronously, so get_favorite_foods may not show the change for a moment. data.ok says the server accepted it.
| Name | Required | Description | Default |
|---|---|---|---|
| food_id | Yes | food_id of a search_food, search_recipes, find_by_barcode, get_recent_foods, get_favorite_foods or get_my_foods hit, create_food's food_id (PRODUCT), create_recipe's recipe_id (RECIPE), or a get_day row's product_id (PRODUCT) or recipe_id (RECIPE). | |
| favorite | No | false to remove it from the favourites. | |
| food_type | Yes | type of that search hit, or the get_day row's food_type. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare idempotentHint=true, destructiveHint=false and readOnlyHint=false, so the safety profile is covered; the description nonetheless adds genuinely new context: the write is applied asynchronously, so get_favorite_foods may lag, and data.ok signals server acceptance. It does not mention auth/permission requirements, but the async and confirmation details are the more valuable disclosures here.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Five short sentences, purpose front-loaded, each carrying distinct information (purpose, input provenance, idempotency, async latency, confirmation signal). Only the data.ok sentence is arguably redundant given an output schema exists.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 3-parameter mutation with full schema coverage and an output schema, the description covers everything an agent needs: what it does, where inputs come from, that repeats are safe, and the asynchronous timing caveat that would otherwise cause a false 'it didn't work' conclusion.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the schema already enumerates every source of food_id/food_type in detail, including the default of favorite and the PRODUCT/RECIPE enum. The description restates provenance rather than adding syntax or edge-case meaning 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.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Add a catalog food to the user's favourites') plus the inverse operation ('remove it with favorite false'), so the tool's toggle nature is unambiguous. An agent can immediately distinguish it from the read-only sibling get_favorite_foods.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete provenance for its required inputs ('food_id and food_type come from search_food, get_recent_foods or get_favorite_foods'), which tells the agent when this tool is applicable. It does not, however, explicitly contrast itself with adjacent write tools such as add_food or add_custom_item, so routing guidance stops just short of exhaustive.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_noteWrite the day's noteADestructiveIdempotent
Replace the user's note for a diary day (get_day's note) with note; an empty note deletes it. The day's note tags are kept, and so is everything else of the day. data.previous is the note before ('' when there was none), to put it back; data.ok says a re-read shows the new note.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | Day as YYYY-MM-DD; when the user says today, yesterday, this week or a weekday, call get_today and count from its date. | |
| note | Yes | The whole new note, '' to delete it. To add to the note, send get_day's note with the addition. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: it discloses the destructive edge case ('' deletes the note), what is preserved (tags and everything else of the day), and return semantics (data.previous for undo, data.ok confirming a re-read). This is exactly the added context destructiveHint/idempotentHint cannot convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences, front-loaded with the action and the destructive case, then the preservation and return facts. Every clause carries information; nothing is padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Annotations, a full-coverage schema, and an output schema already cover safety and return shape; the description still adds the undo value (data.previous) and the verification signal (data.ok), leaving nothing an agent needs to call this correctly unspecified.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so both parameters are already documented in the schema, including the get_day/get_today usage hints. The description restates the '' -to-delete behavior and the 'get_day's note' input convention but adds no syntax or format detail beyond the schema, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource+scope: 'Replace the user's note for a diary day ... with note', and clarifies the delete semantics of an empty string. It anchors itself relative to sibling get_day, so an agent can immediately distinguish it from the read-side note tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear operational context: an empty note deletes, tags and other day data are untouched, and get_day's note is the input to extend. Schema adds the today/yesterday resolution path via get_today. No explicit when-not or named alternative, since there is no competing write-note sibling, so 4 rather than 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_targetsSet the daily goalsADestructiveIdempotent
Change the user's daily goals from today on; earlier days keep theirs. energy_kcal sets a manual calorie goal. protein_pct, fat_pct and carbohydrate_pct set the macro split as whole percent of the energy, all three summing to 100; the grams follow from the energy. With energy_kcal alone the current split stays, or 20/30/50 when the account has none (say so); the percentages alone keep the current energy, as a manual goal. automatic true goes back to the goal Fitatu calculates from the user's profile, with no energy_kcal or percentages. water_glass_ml is the glass size water is counted in (get_water's glass_ml). Returns the goals now in effect as get_targets gives them, plus automatic, glass_ml and previous: the arguments that put back what this call changed, with no water_glass_ml when there was no glass size (that cannot be put back). data.ok says Fitatu's reply shows the change.
| Name | Required | Description | Default |
|---|---|---|---|
| fat_pct | No | Fat's share of the energy goal in whole percent (not body fat). | |
| automatic | No | true: back to the goal Fitatu calculates. Only true, and not with energy_kcal or the percentages. | |
| energy_kcal | No | Daily calorie goal in kcal; makes the goal manual. Convert kJ first: 1 kcal = 4.184 kJ. | |
| protein_pct | No | Protein's share of the energy goal in whole percent; with fat_pct and carbohydrate_pct, summing to 100. | |
| water_glass_ml | No | Size of one glass in ml. | |
| carbohydrate_pct | No | Carbohydrate's share of the energy goal in whole percent. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare destructiveHint=true and idempotentHint=true, yet the description adds substantial behavior beyond them: history before today is preserved, a manual-vs-calculated mode switch, the fallback 20/30/50 split, that the returned 'previous' arguments can restore the change, and that water_glass_ml cannot be restored when none existed. It also explains what data.ok means, which no structured field conveys.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the verb and scope, and every clause carries real information about defaults, interactions, or reversibility. It is dense to the point of being a wall of semicolon-joined clauses, which slightly hurts scannability for six parameters.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutation tool with an output schema and full annotation coverage, this is complete: it explains effects on existing data, mode interactions, defaults, and how to undo the change. Nothing an agent needs to invoke it correctly appears to be missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, but the description goes well past per-field docs by defining cross-parameter semantics the schema cannot express: the three percentages must sum to 100, grams are derived from energy, and omitting a group changes what defaults apply (current split stays, or 20/30/50 when none). This is genuine added meaning, not repetition.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Change the user's daily goals') with an explicit temporal scope ('from today on; earlier days keep theirs'), which is exactly the scope detail needed to distinguish this setter from the read-only get_targets. An agent can tell what it does and what it does not touch 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear conditional guidance for each mode (energy_kcal alone, percentages alone, automatic true, water_glass_ml) including defaults when the account has no split and that automatic cannot be combined with energy_kcal or percentages. It does not explicitly frame when to call this versus e.g. get_targets, but the context is fully actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_waterSet the water drunkADestructiveIdempotent
Set the total water drunk on a day in ml. It replaces the day's total instead of adding to it: to add some, read get_water and send the sum. For glasses, multiply by get_water's glass_ml (ask the user for the size when it is null). data.ok says the server accepted it.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | Day as YYYY-MM-DD; when the user says today, yesterday, this week or a weekday, call get_today and count from its date. | |
| water_ml | Yes | Total for the day in ml. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=true, but the description adds the operative detail behind that: it overwrites the day's total rather than accumulating, which is the behavior an agent most needs. It also notes that data.ok signals server acceptance, though it leaves permission/auth context unstated.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the core semantic (set/replace) in the first clause, then handles the two edge cases compactly in the following sentences. Slightly dense with three distinct instructions packed into the second half, but no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the return-value explanation is unnecessary and the mention of data.ok is mildly redundant. Everything else an agent needs to call this correctly — replace semantics, additive workaround, unit conversion, date resolution via the schema — is covered.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so both parameters are already documented and the baseline is 3. The description adds one genuine relation beyond the schema, the glass-to-ml conversion via get_water's glass_ml, but otherwise restates that water_ml is the day's total.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource with units: 'Set the total water drunk on a day in ml.' It is immediately distinguishable from the read sibling get_water, which it explicitly references for the additive case.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when/when-not guidance: this replaces the day's total, so to add instead the agent should read get_water and send the sum. It also routes the glass-based case through get_water's glass_ml and tells the agent to ask the user when that value is null.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_foodChange a private productADestructiveIdempotent
Change one of the user's own products (create_food's food_id or a get_my_foods PRODUCT hit's food_id): any value create_food takes but unit; what is not given stays as it is, and servings replaces the list. Any other product is refused before anything is changed (that check reads it). Fitatu usually changes the product in place (replaced_food_id null), and rows already logged with it then show the new values too. It may save the change as a new product instead (seen after a rename or new servings): food_id is then the new id and replaced_food_id the old, retired one, and rows logged before keep the old values. Before changing a product the user has logged, tell them their logged rows may change. Returns measures as create_food does and previous, which update_food takes on food_id to undo the change. data.ok says the server accepted it.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | The product's name, e.g. 'Baton owsiany'. | |
| brand | No | Its brand, if the label has one. | |
| fat_g | No | Fat in g in 100 g (100 ml for a drink), as the label gives it. | |
| salt_g | No | Salt in g. | |
| barcode | No | The 8 to 14 digits under the bars. Only the user sees it; find_by_barcode then finds this product. | |
| fiber_g | No | Fibre in g. | |
| food_id | Yes | create_food's food_id, or a get_my_foods PRODUCT hit's food_id. | |
| servings | No | Every serving of it, each name once; replaces the list. | |
| sugars_g | No | Of which sugars, in g; at most carbohydrate_g. | |
| protein_g | No | Protein in g in 100 g (100 ml for a drink), as the label gives it. | |
| energy_kcal | No | Energy in kcal, not kJ, in 100 g (100 ml for a drink), as the label gives it. | |
| carbohydrate_g | No | Carbohydrate in g in 100 g (100 ml for a drink), as the label gives it. | |
| saturated_fat_g | No | Of which saturated fat, in g; at most fat_g. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the destructiveHint/idempotentHint annotations: it discloses the dual persistence model (usually in-place with replaced_food_id null, but sometimes saved as a brand-new product with the old id retired), the downstream effect on already-logged rows, the refusal-before-write guarantee, and the undo path via the returned 'previous'. This is exactly the mutation semantics an agent needs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the key eligibility constraint, and essentially every sentence carries needed information (eligibility, partial-update semantics, in-place vs new-product, undo, warning duty). The prose is dense and parenthetical-heavy, hurting readability, but little is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 13-parameter destructive mutation with an output schema present, the description covers everything an agent needs: which products qualify, partial-update behavior, the two persistence outcomes, effect on logged rows, undo, and acceptance signaling via data.ok. Return measures need not be re-explained given the output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so per-field detail is already in the schema (baseline 3). The description adds genuine cross-cutting semantics: any value create_food accepts except 'unit', unspecified fields stay as-is (partial update), and 'servings' replaces the whole list rather than merging. It also confirms food_id's accepted origin.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource (change one of the user's own products) and immediately scopes which products are eligible via create_food's food_id or a get_my_foods hit. It also clarifies which products are refused, distinguishing it from create_food and from generic product lookups 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear context: only the user's own products (from create_food or get_my_foods) are accepted, others are refused before any change, and it instructs the agent to warn the user when a logged product may shift their logged rows. It also points to update_food with the returned 'previous' to undo. It stops short of an explicit 'use update_food instead of X' routing statement against siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_itemChange a logged foodADestructive
Change a logged food row: its quantity (in the row's own measure, see measure_name and measure_quantity in get_day) and/or eaten. Nothing else can be changed: for another food, or a custom row's name or nutrition, remove the row and add it again. Activities cannot be updated: remove and add them again. data.ok says a re-read shows the change; data.previous is the row's quantity and eaten before it, to undo the change.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | Day as YYYY-MM-DD; when the user says today, yesterday, this week or a weekday, call get_today and count from its date. | |
| eaten | No | true for eaten, false for only planned. | |
| row_id | Yes | row_id of a food row on that day, from get_day (meals[].items[].row_id). | |
| quantity | No | New measure_quantity. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, idempotentHint=false, and readOnlyHint=false, but the description adds real value: it explains partial-update scope, that nothing else is changeable, and that data.previous enables undoing the change. It does not mention auth or rate limits, but the undo and re-read semantics are substantive behavioral detail 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the action and mutable fields, then follows with constraints and return semantics; every clause carries information. It is dense with run-on phrasing but not padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers the mutation's edge cases (what cannot change, alternatives), the undo path via data.previous, and re-read confirmation. With the output schema already documenting the return shape, 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.
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 meaning by tying quantity to the row's own measure and pointing to measure_name/measure_quantity in get_day. This clarifies the unit semantics beyond what the schema field text alone conveys.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (change/update) and resource (a logged food row), then enumerates exactly which fields are mutable (quantity, eaten). This distinguishes it clearly from add/remove siblings so an agent can select it without opening another schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit boundaries and alternatives: for a different food or a custom row's name/nutrition, 'remove the row and add it again,' and activities cannot be updated. It describes the workflow rather than naming sibling tools like remove_items/add_food, so it is clear context with implied alternatives rather than fully explicit routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_recipeChange a private recipeADestructiveIdempotent
Change one of the user's own private recipes (create_recipe's recipe_id or a get_my_foods RECIPE hit's food_id): its name, ingredients (the whole new list, each as create_recipe takes it and checked the same way), servings and/or description; what is not given stays as it is. Any other recipe is refused before anything is changed (that check reads the recipe). Returns per_serving as create_recipe does, and previous (name, servings, description, ingredients), which update_recipe takes to undo the change. data.ok says the server accepted it.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | The new name. | |
| servings | No | How many servings the ingredients make. | |
| recipe_id | Yes | Id of a recipe the user created. | |
| description | No | How to make it, as the app shows it. | |
| ingredients | No | Every product of the recipe, each as add_food takes it; replaces the list. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| data | No | |
| error | No | describe_error() of what went wrong; docs/AGENTS.md, Results and errors. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the destructive/idempotent annotations, it discloses partial-update semantics ('what is not given stays as it is'), the ordering guarantee that the ownership check reads the recipe and refuses before any mutation, and an undo path via the returned 'previous' object. This is meaningfully richer than what the annotations alone convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is front-loaded with the core action and every sentence carries information (partial update, refusal ordering, return values). It is dense and parenthetical-heavy, reading as one long run-on, which slightly hurts scanability.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an update tool with an output schema, the description covers ownership preconditions, partial-update behavior, and undo, which is complete enough for correct invocation. The return details are somewhat redundant given the output schema, but nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents every field; however the description adds the semantics the schema omits - that omitted fields are left unchanged and that ingredients is a full replacement list validated the same way as create_recipe. That goes beyond the baseline 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('Change one of the user's own private recipes') and enumerates exactly what can be changed (name, ingredients, servings, description). It ties the recipe_id provenance to sibling tools (create_recipe, get_my_foods), so an agent can distinguish it from create_recipe/delete_recipe 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It clearly scopes use to the user's own private recipes and states the exclusion ('Any other recipe is refused'), which tells the agent the ownership precondition. It does not explicitly name alternative tools for the non-owned or create cases, so it stops short of full when/when-not/alternative routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
47 tool updates
v0.1.0- First observed
add_activity - First observed
add_custom_item - First observed
add_food - First observed
add_foods - First observed
copy_meal - First observed
create_food - First observed
create_recipe - First observed
delete_food - First observed
delete_recipe - First observed
find_by_barcode - First observed
get_body_measurements - First observed
get_day - First observed
get_fasting - First observed
get_favorite_foods - First observed
get_food_measures - First observed
get_good_days - First observed
get_habits - First observed
get_measurement_history - First observed
get_my_foods - First observed
get_profile - First observed
get_progress - First observed
get_range_summary - First observed
get_recent_foods - First observed
get_recipe - First observed
get_report - First observed
get_shopping_list - First observed
get_targets - First observed
get_today - First observed
get_top_foods - First observed
get_water - First observed
get_weight_history - First observed
log_measurements - First observed
log_weight - First observed
move_item - First observed
preview_removal - First observed
remove_activity - First observed
remove_items - First observed
search_activity - First observed
search_food - First observed
search_recipes - First observed
set_favorite - First observed
set_note - First observed
set_targets - First observed
set_water - First observed
update_food - First observed
update_item - First observed
update_recipe
TDQS
Scored across 47 tools
Most tools target a clearly distinct resource and action (add_food vs add_foods vs add_custom_item vs add_activity, get_day vs get_progress), and the descriptions explicitly cross-reference the right sibling tool. However, the report family (get_range_summary, get_progress, get_report, get_top_foods) and the measurement family (get_weight_history, get_body_measurements, get_measurement_history) overlap enough that only the very long descriptions prevent misselection.
Every name is snake_case with a predictable verb_noun shape: get_*, add_*, update_*, remove_*, set_*, create_*, delete_*, search_*, find_*, move_*, copy_*, log_*, preview_*. No camelCase or vague verbs break the pattern.
At 47 tools this is heavy, and several reads (three summary/report tools, three measurement-history tools) add surface redundancy. It is defensible given the breadth of the Fitatu domain (diary, foods, recipes, activities, body data, water, fasting, habits, goals, notes, reports), but it sits well above the comfortable 3-15 range.
Coverage is unusually thorough: full CRUD for user foods and private recipes, add/remove for diary rows and activities, reads and writes for weight, measurements, water, targets, notes and favourites, plus search, barcode lookup, meal copy/move, shopping list and multiple report views. No obvious lifecycle gap for the stated domain.
Maintenance
Related MCP Connectors
Wger MCP — wraps wger Workout Manager REST API (free, no auth for read)
A calorie MCP that looks up calories and macros from a 4M+ food catalog, not model guesses.
MCP server for Withings health data — sleep, activity, heart, and body metrics.
USDA FoodData Central nutrient lookup, FDA recall watch, EU FMCG labelling via remote MCP
Related MCP Servers
- AlicenseAqualityDmaintenanceMCP server for managing Yazio user & nutrition data (unofficial)15369 npm65MIT
- AlicenseAqualityDmaintenanceMCP server for managing food diary, nutrition tracking, meal planning, and weight logging via the FatSecret Platform API.15MIT
- AlicenseCqualityCmaintenanceEnables programmatic access to Fitatu nutrition tracking via MCP tools for login, food search, product lookup, daily nutrition read, and adding entries.9MIT
- FlicenseNot gradedqualityCmaintenanceSyncs and retrieves daily nutrition data (meals and macros) from Fitatu via MCP tools, with SQLite caching and HTTP Streamable transport.2-