Skip to main content
Glama

Stop rewriting your resume for every job.

Maestro tailors it from your whole career history in under a minute, and every bullet is something you actually did, so you can defend it in an interview.

  • Same score, every time. The match score runs on fixed rules and a small model on your own computer, with no AI service involved. Same resume, same job, same number.

  • Every AI edit is a diff. Suggested changes arrive as a before and after. You accept or undo them one by one.

  • It fills the form and stops there. The Companion fills job applications from your saved answers and attaches your resume. It never submits. That click is yours. With full automation on, Apply can also click Next through the pages for you and stops on the review page. On known application sites it signs in, or makes the account, with the job-site login you saved.

Install in two commands, or follow the Getting Started guide if this is all new to you.

Many resume versions become one career history, then a specialist resume per role, company and country, matched to a job and ready to apply. You press Submit.

Give your AI your career

Connect Claude, Codex or the ChatGPT desktop app and your assistant gets your career history, your resumes and your jobs. Then just ask.

You ask

What happens

Extract

"Here's a posting. Should I even apply?"

It saves the job, scores your resumes against it and flags knock-outs like visa or years of experience.

Maintain

"I shipped the fraud model this quarter. Add it."

A new bullet, as a draft you approve, that every resume can use.

Maintain

"Make me a resume for fintech ML roles in the UK."

A specialist resume built from your history, targeted to that role and country.

Hunt

"Every morning, find new ML roles that fit and file the good ones."

The job-hunt skill files them to your Agent inbox. You queue or skip each one.

Hunt

"Which skills keep showing up that I don't have?"

The gaps across every job you saved, most frequent first.

Apply

"Tailor this one, walk me through the gaps, then make the PDF."

It asks about each gap instead of inventing, keeps every change as a diff you can undo and renders the PDF.

Apply

"Fill the applications I queued. Show me each one before it goes."

Nothing is submitted without your yes, unless you turn on full automation.

That is 94 tools and ready-made skills for a daily hunt, an apply run and email status: see the MCP guide.

Free and open source. Your career history lives on your laptop, not in someone else's cloud, and there is no account. Bring an OpenAI, Gemini or Claude key (scoring, PDFs and tracking work without one), get real LaTeX and Typst PDFs, and take everything with you in one career.md file.

Made for one person on one computer. There is no login, so anything that can reach the app can read and change your whole career record and your saved API keys. Out of the box it only listens on your own machine (127.0.0.1). Never expose the app to a network. The one published path is /api/sync, sealed, and only as sync setup describes. SECURITY.md has the details. Your career record stays on your computer. When you use AI features, resume and job information goes to the AI service you choose.


Related MCP server: CareerMate

Why it works this way

If your resume folder has a v2finalcopy(3) in it, this is for you. Maestro keeps one record of what you have actually done, and every resume is a view of that record. Approved bullets go into a resume word for word, and rewording one is a separate step that asks you first. When a job asks for something your resume does not show, Maestro asks you about it. If it is true, it is saved for every future application. If it is not, it stays a gap.

The score is fixed rules, so the same resume and job always get the same number. It is not an employer's score or a prediction of an interview, so use it to compare your own drafts. Saving a job and tailoring for it took about 10 seconds on Gemini and about 40 on the OpenAI default in our tests, at about $0.01 (OpenAI) or under $0.03 (Gemini) per application (the numbers).

Nothing here is rented. It is free and open source (Apache 2.0), with no account, and you pay only for the AI you use. Your career has one history. Your resume should too.

The long version, with the score, tailoring, templates and the rest of the toolkit, is in Using Maestro CS.


Quickstart

Install uv once. After that, Maestro is two commands: no Docker, no Git, no clone. uv installs Maestro as a single maestro command and fetches the Python it needs, and the package brings its own web app and its own Node. It runs on macOS, Linux and Windows (x64).

# 1. Install uv once, then open a new terminal.
curl -LsSf https://astral.sh/uv/install.sh | sh     # macOS and Linux
# On Windows, in PowerShell instead of the line above:
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
# 2. Install Maestro, then start it.
uv tool install --python 3.12 maestro-career-studio
maestro start

maestro start runs Maestro in the background and opens http://localhost:3000. Closing the terminal does not stop it. The first start downloads the small scoring model (about 100 MB, once) from Hugging Face, so allow a minute or two. If the terminal says maestro is not found, run uv tool update-shell and open a new terminal.

Best effort, not tested: Windows on ARM has no PDF-engine (typst) wheel, so install an x64 Python under emulation: uv tool install --python cpython-3.12-windows-x86_64-none maestro-career-studio. Alpine and other musl Linux are not supported by the PDF engine's wheels; use a glibc distro or Docker.

Then:

  1. Add your AI key in Settings › Basics. One key from OpenAI, Gemini or Claude is enough. Without a key, scoring, PDFs and tracking still work (what a key costs and does).

  2. Import your resumes, save a job, and tailor (step by step).

  3. Optional: maestro connect adds Maestro to Claude Desktop, Claude Code, Codex, Cursor or VS Code, and the Companion is a Chrome side panel for saving and filling job pages.

Command

What it does

maestro start

Start Maestro and open the app (--no-browser, --skip-model)

maestro stop

Stop it

maestro status

Whether it is running, its version and whether a newer one exists (--offline skips that check, --json for scripts; exit code 3 means stopped)

maestro update

Save a snapshot of your data, update, restart (-y skips the question)

maestro connect [app]

Add Maestro to Claude Desktop, Claude Code, Codex, Cursor or VS Code

maestro import-docker CHECKOUT

Move your data from a Docker install into this one, once (--dry-run shows the plan; steps)

The full command table also covers logs, open, restart, autostart, backup, uninstalling and TeX for LaTeX templates. What the command contacts, and when: PRIVACY.md.

Young, but rehearsed. The app runs daily on my machine. A fresh Docker install (clone, start, first tailored resume) has been checked end to end on a second machine, and CI installs and starts the uv package on macOS, Linux and Windows for every change. It has had little testing on machines that aren't mine. If it fails on yours, please open an issue with the log. That report is one of the most valuable contributions there is.

Alternative: run with Docker (self-hosters)

Docker stays the route for contributors and for servers. It needs Docker, Git and about a 1 GB download (roughly 3–4 GB unpacked); the prerequisites have the detail, and on Windows you run it under WSL (steps).

# 1. Download the project and create your settings file
git clone https://github.com/seinun-ai/maestro-career-studio.git
cd maestro-career-studio
cp .env.example .env

# 2. Start the app (downloads about 1 GB the first time)
docker compose up -d

Then open http://localhost:3000 and add your AI key in Settings › Basics. The first start sets up your database and adds a demo resume so you have something to look at. The rest of the Docker route is in the setup reference.

Docker and uv are separate copies. They keep separate data, and both want ports 8001 and 3000, so run one at a time. Moving from Docker to uv? Stop Docker, install Maestro as above, then run maestro import-docker CHECKOUT once (steps). It reads your Docker folder and changes nothing in it.

Working with AI assistants

Driving it from Claude, Codex, or ChatGPT (MCP)

MCP is the connector that lets an AI assistant use the app for you: read a posting, score it, work the gaps, make the PDF, all in conversation, on your computer against your data. All 94 tools are on by default, and smaller tool sets (profile, hunt, tailor, apply, track, templates) keep a chat focused. Your assistant writes the text with its own AI unless you pick Maestro's AI in Settings › Agent apps › Who writes for connected agents. On a uv install, run maestro connect; otherwise open Settings › Agent apps › Connect an agent app. Setup, example prompts, tool sets and the ready-made skills are in Using Maestro CS and the MCP guide. An always-on bot can work your search while your laptop is off.

Going all the way: agent applications

Maestro CS can take an application right up to the submit button. A job your agent finds becomes a proposal. You review proposals in the Agent inbox and queue or skip them, and an apply run works only the ones you queued. By default it waits for your yes before each submit. Full automation (off by default, in Settings › Agent apps) lets your agent submit a queued job without asking when its final review shows nothing to check, within your daily limit. Nothing is ever submitted from the web app itself, and the Companion never presses Submit. That yes is recorded by the agent, so it is an audit trail and a volume limit, not a lock that a manipulated agent can't pick: run it while you're watching. The risks, plainly: a job posting is untrusted text that can try to instruct the agent reading it, a posting the agent found is not a vetted employer, and we won't help you hide automation from bot detection. Read the full section before you turn it on.


Updating

Installed with uv? Run maestro update. It checks PyPI for a newer release, prints any breaking changes from the changelog, saves a verified snapshot of your data, stops Maestro, updates it and starts it again.

On Docker? From the folder you cloned, run ./scripts/update.sh (--check only tells you whether you're up to date). It needs bash, so on Windows run it under WSL.

Your data is not touched by an update, and deleting the project folder does delete it on the Docker route. After updating, reload the browser extension and restart your AI assistant so it sees new tools. docs/UPDATING.md has the rest: updating by hand, pinning a version, what the backup covers, rolling back, and coming from v0.3.0 or older.

Where your files live

A uv install keeps everything in one folder per user: the database, resumes, settings, backups, logs and maestro.env (your API keys and, if you need them, port overrides). Deleting the folder deletes your data.

System

Folder

macOS

~/Library/Application Support/Maestro Career Studio

Windows

%APPDATA%\Maestro Career Studio

Linux

$XDG_DATA_HOME/maestro-career-studio (default ~/.local/share/maestro-career-studio)

Finished resume PDFs are also copied to Documents/Maestro Career Studio/Applications, one folder per job (Settings › Basics › Resume PDFs).

On the Docker route everything stays inside the folder you cloned (data/, base_resumes/, applications/, settings/ and more; the full list). Your files are yours, never uploaded. Every application's PDF is saved in applications/, and career.md exports your whole career history as one Markdown file.

Troubleshooting

maestro status and maestro logs come first, and a port already in use is named in the message. maestro check prints the install's facts as JSON to paste into an issue. Ports, API keys and quota errors, "database is locked", PDFs that fail to build and an empty app after updating are covered in Troubleshooting & Common Questions.

Community, Documentation & Contributing

Contribution fast-path: docs fixes, resume/cover-letter templates and extension job-board adapters go straight to a pull request — no issue needed. Features and bigger changes: open an issue first. Every pull request gets a human reply within 48 hours and is read by a human — we don't merge AI slop.

This is an early release. If something doesn't work, please say so — a clear bug report is one of the most valuable contributions right now.

  • Project site: maestrocareerstudio.com — a five-minute tour before you install anything.

  • Getting Started: docs/GETTING_STARTED.md — install to first tailored PDF, step by step.

  • Using Maestro CS: docs/USING_MAESTRO.md — how it works, how to use it well, and the rest of the toolkit.

  • Setup reference: docs/SETUP_REFERENCE.md — the maestro command, prerequisites, API keys, local models and troubleshooting.

  • Updating: docs/UPDATING.md — updating by hand, backups, rolling back.

  • Known issues: KNOWN_ISSUES.md — what works well, what's rough, and what's a deliberate limitation.

  • Skills for your AI assistant: docs/skills/ — job hunt, apply run, mail status, referral pages, tailor run, and a skill that builds your own; the app's Automations page copies each as a prompt.

  • Contributing: CONTRIBUTING.md — development setup, tests, development mode and LLM tracing, and where help is wanted. SYSTEM.md is the architecture reference for contributors and coding agents; read the relevant part before changing behaviour. UBIQUITOUS_LANGUAGE.md is the project's vocabulary, worth ten minutes before your first contribution.

  • Changelog: CHANGELOG.md — what changed in each release; read any Breaking changes heading before updating. Maintainers: docs/RELEASING.md.

  • Security & privacy: SECURITY.md — the local-only rule and how to report a vulnerability. PRIVACY.md — what is stored, and what leaves your computer.

  • License: LICENSE — Apache License 2.0, plus NOTICE.

Privacy Policy

There is no Maestro CS server or account, and the author never receives your data. Your career record stays in files on your computer; it goes to an AI service only when you add a key and use an AI feature, and to the assistant you connect over MCP when it calls a tool. With a model on your own computer, the app sends nothing out. PRIVACY.md has the full policy: what is stored, every place data can go, retention, and how to ask a question.

Licensing

Maestro CS is free software under the Apache License 2.0.

You may use it commercially, and you don't have to publish your changes. Fork it, build it into a product, run a modified copy as a hosted service — all permitted. Apache 2.0 asks three things in return: keep the license and copyright notices, say what you changed in the files you changed, and pass along the NOTICE file with any redistribution. It also includes an explicit patent grant from every contributor, the main practical reason to prefer it over MIT or BSD.

Credits for the third-party pieces we redistribute — the LaTeX resume template, the XCharter font, the scoring model — are in THIRD_PARTY_NOTICES.md, which the license also asks you to carry forward.

No CLA. Contributions are licensed under Apache 2.0 by section 5 of the license itself; there's nothing to sign. Commercial questions: ajey@seinun.com.

Credits & Citation

Maestro Career Studio is a free, open-source project from Seinun LLC. It stands on other people's work. The full list — bundled sources, the scoring model, the PDF tools, and every dependency with its license — is in THIRD_PARTY_NOTICES.md. The ones that shape the product most:

Using Maestro CS in published work? Cite it with GitHub's "Cite this repository" button, which reads CITATION.cff.

Available Tools

94 tools
archive_base_resumeArchive Base ResumeA
Idempotent

Hide a base resume from pickers without deleting it.

Sets archived_at (reversible timestamp, not a delete). Archived bases drop
out of list_base_resumes' default view; JSON, PDF, TEX and version history
stay. Undo with unarchive_base_resume.
NameRequiredDescriptionDefault
slugYes

TDQS

A4.5/5.0
Behavior5/5

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

Goes well beyond the annotations: annotations only say readOnlyHint=false, idempotentHint=true, destructiveHint=false, while the description discloses the mechanism (sets archived_at), confirms reversibility, and enumerates exactly what is preserved (JSON, PDF, TEX, version history) and what changes (drops out of list_base_resumes' default view). No contradiction with annotations; mutation with idempotent=true is consistent with re-archiving being harmless.

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

Conciseness5/5

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

Three short sentences, front-loaded with the purpose, then mechanism, then the undo path. Every sentence carries distinct information with no repetition of the title or annotations.

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

Completeness5/5

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

For a one-parameter, non-destructive mutation with no output schema, the description covers the essential facts an agent needs: what changes, what persists, effect on other tools, and how to reverse it. Nothing material about calling it correctly is missing.

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

Parameters3/5

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

Schema description coverage is 0% and the description never mentions the slug parameter, so it adds no meaning about identifier format or where to obtain it. With only one unambiguous parameter in a family where slug is the standard key, the gap is minor, but the description does no compensating work.

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

Purpose5/5

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

States a specific verb and resource ('Hide a base resume from pickers') and immediately disambiguates from a sibling action by clarifying it is not a delete. An agent can distinguish this from update_base_resume, edit_base_resume, or a delete-style operation without opening any schema.

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

Usage Guidelines4/5

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

Gives clear context for use (removing a base from pickers while preserving it) and names the exact reversal path, unarchive_base_resume. It stops short of stating when NOT to archive (e.g., to permanently remove a base, use something else), so it is clear but not fully exclusionary.

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

attach_evidenceAttach EvidenceA

Attach an evidence image to a proposal, from exactly one of image_base64 (the image, base64, supplied inline in the call) or file_path (an image file already on this machine's disk, e.g. a browser tool's saved screenshot; its bytes are read and uploaded server-side, so they never enter the model context). Both or neither is refused, and nothing is uploaded. kind must be step | final_review | submission_receipt.

NameRequiredDescriptionDefault
kindNostep
stepYes
labelYes
file_pathNoAn absolute path to an existing PNG or JPEG on this machine, typically as a browser tool reports it (Playwright MCP saves to its --output-dir; with the standard setup that is under the repo's .playwright-mcp/ tree, e.g. /Users/<user>/Projects/maestro-career-studio/.playwright-mcp/<name>.png); a relative or ~ path is resolved against this server's working directory. When this server runs inside the backend container, a host path with a `.playwright-mcp/` segment is read from the container's mount of that tree (paths that leave the tree are refused). PNG/JPEG only, 5 MB max.
proposal_idYes
image_base64No

TDQS

A4.1/5.0
Behavior4/5

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

Annotations already declare the safety profile (not read-only, not destructive, not idempotent), and the description adds real value beyond that: file_path bytes are read and uploaded server-side so they never enter model context, invalid source combinations are refused with nothing uploaded, and file type/size limits appear in schema. It does not describe the response after a successful attach, but with annotations carrying the safety profile a 4 is appropriate.

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

Conciseness4/5

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

Three tight sentences with the main action and source constraint front-loaded, and the kind enum placed last. Dense but every sentence carries weight; only slightly more could be trimmed.

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

Completeness4/5

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

For a write tool with an output schema absent, the description covers the critical ambiguities: which source parameter to use, the refusal behavior, and the kind enum. The main remaining gap is that proposal_id, step, and label are undefined despite low schema coverage, but their names are largely self-explanatory for correct invocation.

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

Parameters3/5

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

Schema description coverage is only 17%, so the description must compensate. It does a good job on the three hardest parameters (mutual exclusivity of image_base64/file_path, the server-side read semantics of file_path, and the kind enum), but it says nothing about the three required parameters proposal_id, step, and label, leaving their meaning to inference. Partial compensation merits a 3.

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

Purpose5/5

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

The description gives a specific verb and resource ('Attach an evidence image to a proposal') and immediately enumerates the two mutually exclusive source parameters, so an agent can tell exactly what this does without opening the schema. It is clearly distinct from siblings like get_rendered_pdf_page_image or render_pdf.

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

Usage Guidelines4/5

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

It explicitly states the source contract: exactly one of image_base64 or file_path, with both/neither refused and nothing uploaded. That is strong when-to-use guidance for the ambiguous part of the call, but it never states when to attach evidence versus other siblings or any prerequisite context (e.g., proposal state).

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

close_tailoring_sessionClose Tailoring SessionA

Abandon an OPEN tailoring session without tailoring it.

`tailoring_session_id` is the id returned by create_tailoring_session. This is
the explicit exit for a "changed my mind" flow — e.g. the user walks through
some gaps, then decides to use the base resume as-is and does not run
tailor_session. Marks the session's status "abandoned" so it stops looking like
unfinished work. Errors (409) if the session isn't currently open (already
tailored, already superseded, or already abandoned).
NameRequiredDescriptionDefault
tailoring_session_idYes

TDQS

A4.9/5.0
Behavior5/5

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

Annotations give the safety profile (readOnlyHint=false, destructiveHint=false, idempotentHint=false), and the description adds real state-machine context beyond them: it marks status 'abandoned', explains the intent (stops looking like unfinished work), and lists the exact 409 failure conditions (already tailored/superseded/abandoned). This is consistent with idempotentHint=false.

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

Conciseness5/5

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

Front-loads the core action, then the scenario, then the status effect and error behavior. No redundant sentences; each line contributes distinct information.

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

Completeness5/5

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

For a single-parameter state-transition tool with no output schema, the description covers purpose, when to use, what state changes, and error conditions. 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.

Parameters4/5

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

With only one parameter and 0% schema description coverage, the description carries the burden and does so by explaining provenance: tailoring_session_id is the id returned by create_tailoring_session. It doesn't add format/syntax detail, but provenance is the meaningful gap an agent would otherwise lack.

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

Purpose5/5

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

States a specific verb (abandon/close) and resource (OPEN tailoring session) plus the key scope qualifier 'without tailoring it'. This cleanly separates it from tailor_session and create_tailoring_session, so an agent can distinguish 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.

Usage Guidelines5/5

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

Explicitly describes the 'changed my mind' scenario where the user walks through gaps then decides to use the base resume as-is and does not run tailor_session. It names the alternative (tailor_session) and the condition that selects this tool, and even documents the 409 error when the session isn't open.

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

compare_atsCompare Match ScoresA
Read-onlyIdempotent

Before/after match score comparison for an application: composite and per-layer deltas plus a per-skill diff (absent→matched, skills-list-only→dual, decayed→recent). Computes any missing phase row on demand.

NameRequiredDescriptionDefault
application_idYes

TDQS

A3.7/5.0
Behavior4/5

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

Annotations already cover the safety profile (readOnly, idempotent, non-destructive), but the description adds real behavioral context by disclosing the diff taxonomy (absent→matched, skills-list-only→dual, decayed→recent) and the lazy behavior 'computes any missing phase row on demand'. That last clause hints at an on-demand computation/persistence step that annotations alone would not reveal.

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

Conciseness4/5

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

Two tight sentences, front-loaded with the core comparison purpose and followed by the supporting detail. No filler; the second sentence about computing missing rows earns its place by adding behavior not present elsewhere.

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

Completeness4/5

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

With no output schema, the description usefully describes the return shape (composite/per-layer deltas, per-skill diff) and the on-demand computation behavior. For a one-parameter read tool the only real gaps are the absent usage guidance and parameter documentation.

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

Parameters3/5

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

Schema description coverage is 0% and the description never mentions application_id, so it does not compensate for the gap. However, the single parameter is self-documenting by name with no format or syntax nuance to explain, so the omission is low-cost.

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

Purpose4/5

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

The description states a specific verb (compare) and resource (before/after match scores) and even enumerates the output components: composite and per-layer deltas plus a per-skill diff. It is clearly distinguishable from score_ats (which produces a single score) by the 'before/after' framing, though it never names the sibling explicitly.

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

Usage Guidelines3/5

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

The 'before/after' framing implies the scenario (comparing an application's match state across phases), but there is no explicit when-to-use statement and no routing versus score_ats or explore_ats_over_time. Usage is inferable from context rather than stated.

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

create_base_resumeCreate Base ResumeC

Create a new base resume. Slug must be lowercase alphanumeric/underscores, not 'master'.

NameRequiredDescriptionDefault
dataYes
slugYes
display_nameYes

TDQS

C2.9/5.0
Behavior3/5

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

Annotations already disclose that this is a non-read-only, non-idempotent, non-destructive write, so the safety profile is covered. The description adds a real operational constraint (slug format and the reserved 'master' value) but says nothing about failure modes on duplicate slugs or what the returned object contains.

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

Conciseness4/5

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

Two short sentences, no filler, purpose stated first and the constraint second. Efficient, though extremely terse for a creation tool.

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

Completeness2/5

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

For a write tool with a nested free-form 'data' object, no output schema, and zero schema coverage, the description leaves too much unexplained — what shape 'data' takes and what a successful create returns are both unspecified.

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

Parameters2/5

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

Schema description coverage is 0% across three required parameters. The description only constrains 'slug' (lowercase alphanumeric/underscores, not 'master'), leaving 'display_name' and especially the nested 'data' object entirely undocumented in both schema and description.

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

Purpose4/5

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

States a specific verb+resource ('Create a new base resume') that is unambiguous. It does not differentiate itself from the sibling create_base_resume_from_kb, which an agent might reasonably confuse it with.

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

Usage Guidelines2/5

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

No when-to-use guidance, no prerequisites, and no mention of the alternative create_base_resume_from_kb. The agent must infer from the name alone which creation path to take.

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

create_base_resume_from_kbCreate Resume from Career KBA

Compose a new base resume from selected Career KB entities. LLM-free.

entity_ids is REQUIRED. An empty list composes nothing and 422s — that is
deliberate; omitting the argument is not allowed because it would have to
mean "the whole KB". A role_label or role_category is required (no slug
argument). role_category is strict: an unknown value 422s naming the
closest categories, no normalization. An unmatched role_label maps to
role_category "other" and slug `other`/`other_2`…; display_name never
affects the slug, which is `base.slug` in the response. Only APPROVED
points under the selected entities compose —
points from kb_ingest_resume are DRAFTS and contribute nothing until
kb_approve_points (or the user, at /career) approves them.
skills and contact arrive in full from the KB profile regardless of entity
selection (the KB has no per-entity skill data), so skills may need trimming
on the resulting base. The
whole-career summary is dropped unless include_summary, or pass a reviewed
summary. A selected job or project with no approved point is left out, and
a 422 "None of the items you picked has approved bullets." means none has any.

Response is {base, next}. next is a hint (null when suppressed or when its
settings read fails; the base is created either way, and repeating the call
mints a second slug, <slug>_2).
NameRequiredDescriptionDefault
summaryNo
entity_idsYes
role_labelNo
display_nameNo
role_categoryNo
include_summaryNo

TDQS

A4.5/5.0
Behavior5/5

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

Extensive disclosure beyond the annotations: which 422s fire and why (empty entity_ids, unknown role_category, no approved bullets), that unmatched role_label falls back to 'other'/slug other/other_2, that skills and contact always arrive in full from the KB profile and may need trimming, that the summary is dropped without include_summary, and that a job/project with no approved point is omitted. It also documents the {base, next} response and warns that repeating the call mints a second slug — consistent with idempotentHint=false.

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

Conciseness4/5

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

Front-loads the purpose and the hard requirement in the first three sentences, then spends the rest on failure modes and side effects that genuinely matter. It is dense and slightly run-on in the middle (the summary/skills paragraph), but no sentence is filler.

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

Completeness5/5

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

There is no output schema, yet the description explains the return value ({base, next}) and even the meaning of next being null. For a mutation tool with six parameters and no structured documentation, the definition supplies everything an agent needs to call it correctly and to interpret the result.

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

Parameters5/5

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

Schema coverage is 0%, yet the description covers all six parameters: entity_ids (required, non-empty semantics), role_label/role_category (mutually sufficient, strict validation), display_name (never affects the slug), summary (pass a reviewed summary), and include_summary. This compensates fully for the empty schema and adds meaning no schema field could carry.

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

Purpose4/5

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

"Compose a new base resume from selected Career KB entities. LLM-free." states a specific verb (compose), resource (base resume) and source (Career KB entities), which separates it from the sibling create_base_resume that doesn't draw on the KB. It never names that sibling explicitly, so the differentiation is implied rather than stated.

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

Usage Guidelines4/5

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

Gives clear conditions for use: entity_ids must be non-empty because empty would have to mean 'the whole KB', and one of role_label/role_category is required since there is no slug argument. It explains the approval prerequisite (points from kb_ingest_resume are drafts until kb_approve_points). It lacks an explicit 'use create_base_resume instead when...' contrast, but the operational context is unusually complete.

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

create_tailoring_sessionStart Tailoring SessionA
Destructive

Start the gap-analysis tailoring workflow for a job + base resume.

Calling again for the same job+base SUPERSEDES the open session (saved
resolutions become unreachable); list_tailoring_sessions shows existing
sessions. A failing fatal health gate on the base is a 409.

Scores the base (deterministic ATS engine, persisted as the 'before' score) and
returns a session whose gaps_json.categories list every gap in fix-cost order:
missing skills, wording mismatches, placement upgrades, stale evidence, adjacent
skills, title/structure. The intended flow is: gather the user's answer for each
gap, save them with resolve_gaps, then tailor_session. Each gap carries its
allowed actions. A missing skill MAY use add_keyword ONLY to add the keyword to
a skills category (placement_target.section="skills"): that inserts an
unverified skills-list item, never a fabricated bullet. The evidence-backed
alternatives are a user_input resolution (the user's answer to
enrichment.elicitation_question), attach_project, or skip.

use_presets=True also fills every gap the user's Quick tailor presets decide
(get_tailoring_options explains them), with no AI; undecided gaps are saved
as skip. When that fill fails, the error names the session it started.

enrich=True has Maestro's AI add display-only explanations to each gap (one
fast-model call with the user's key; no score, gap or career-history match
changes). Refused (409) when the user's writer setting (get_setup_status) says
the agent app writes: run it without enrich, the default, which calls no model.

Response is the session (filled, with use_presets) plus a `next` hint (null
when hints are off or unavailable). `base_anchors` are the base's emphasis
hints (countries, role, company, focus), not evidence; the anchor company is
the resume's own target, not necessarily this job's employer.
NameRequiredDescriptionDefault
enrichNo
job_idYes
base_resumeYes
use_presetsNoTrue: once the session is created, fill it from the user's Quick tailor presets (get_tailoring_options explains them) through resolve_gaps' honesty-gated save path, deterministically and with no AI. The presets plan only mechanical, evidence-respecting moves; the fill does not write resume text. The returned resolutions_json may already resolve every gap, including system-planned entries (payload.provenance); a gap the presets do not decide is saved as skip. A session whose answers are all skip is not an error: the presets allowed nothing for it, and resolve_gaps still saves answers on it. An unverified or absent skill enters only a skills category (add_skill_item), never as an experience or project bullet; the server does not gate edit ops the caller writes against fabricated skills, experience, metrics or dates. A stale or no-longer-open session blocks the fill (409). The `next` hint then carries the presets' standing instruction as tailor_session's user_prompt when the session has no note of its own.

TDQS

A4.8/5.0
Behavior5/5

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

Beyond the annotations, the description discloses the destructive supersede behavior for existing open sessions, the 409 fatal health gate, and the fact that saved resolutions become unreachable. It further explains enrich's model call and refusal condition based on the writer setting, use_presets' deterministic no-AI fill, and failure behavior when that fill fails.

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

Conciseness4/5

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

The description is front-loaded with the core purpose and destructive behavior, then proceeds logically through workflow, parameters, and response shape. It is long and dense with parenthetical detail, but most content is relevant for a complex tool with multiple behavioral branches.

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

Completeness5/5

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

There is no output schema, but the description explains the returned session shape, gaps_json.categories ordering, allowed actions per gap, the `next` hint, and `base_anchors` semantics. It also covers important error cases such as 409 health-gate failures, enrich refusals, and stale-session conflicts.

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

Parameters4/5

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

Schema description coverage is low at 25%, so the description must compensate. It gives rich semantics for enrich and use_presets, including side effects, refusal conditions, and preset fill behavior; however, it does not add much detail about the job_id and base_resume identifier parameters beyond their roles in the workflow.

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

Purpose5/5

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

The first sentence states a specific verb (start) and resource/workflow (gap-analysis tailoring session for a job + base resume), making the tool immediately identifiable. It also distinguishes itself from siblings by naming list_tailoring_sessions, resolve_gaps, and tailor_session in the surrounding flow.

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

Usage Guidelines5/5

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

The description explicitly describes the intended sequence: gather each gap answer, save with resolve_gaps, then call tailor_session. It also names alternatives and conditions, including using list_tailoring_sessions to inspect existing sessions, when add_keyword is allowed versus user_input/attach_project/skip, and when enrich or use_presets should be used or avoided.

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

create_template_draftCreate Template DraftA

Create a DRAFT template. engine defaults to 'latex'. Pass engine='typst' for Typst — then source is REQUIRED: raw .typ text (no Jinja, no escape filters; read via json(bytes(sys.inputs.resume)) / json(bytes(sys.inputs.fmt)); engine is immutable after creation).

Both engines consume the same resume JSON (contact, summary,
skills[].{category,items}, experience/projects/education, certifications,
extra_sections). Typst reads r.contact.name etc.; optional fields arrive
as `none` — guard with `!= none`. LaTeX uses resume.* with |latex_escape
on every value.

Typst constraints: dates arrive PRE-FORMATTED server-side (fmt.date_format
is not read). Package imports (`#import "@preview/..."` or any `@...`
import) are REJECTED (no external packages). Fonts: only
vendored XCharter plus typst's embedded defaults (e.g. Libertinus Serif);
any other family compiles WITHOUT error and silently substitutes. A template
that does not render r.extra_sections (both `entries` and `bullets` shapes)
hard-fails on resumes with custom sections; get_template('typst-classic')
shows the block.

LaTeX: omit `source` to start from the canonical starter. Given source
must be a complete compilable document (\documentclass + preamble) as
Jinja2 with blocks ((* *)), variables ((( ))), comments ((# #)). The source
is raw LaTeX: bare `&` for tabular cells, `\&` for a literal ampersand;
HTML entities such as `&amp;` are not decoded. Includable:
((* include '_header.tex.j2' *)). Spacing and look can be wired to `fmt.*`
(full knob list on get_template) instead of hard-coded values;
get_template('default') is a starting point.

validate=True test-compiles in the same call (status/last_error). A LaTeX
draft cannot validate on a backend with no TeX (list_templates →
engine_available); engine='typst' works there. Not usable until validation
succeeds. `id` is a slug: [a-z0-9_-].
NameRequiredDescriptionDefault
idYes
engineNolatex
sourceNo
validateNo
display_nameYes

TDQS

A4.7/5.0
Behavior5/5

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

Annotations only declare the safety profile (write, non-destructive, non-idempotent); the description goes far beyond: engine is immutable after creation, drafts are not usable until validation succeeds, LaTeX cannot validate on a backend without TeX, Typst rejects @-imports, unknown fonts silently substitute without error, templates that skip r.extra_sections hard-fail, and HTML entities are not decoded. These are exactly the non-obvious behaviors an agent must know before writing source.

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

Conciseness4/5

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

Front-loaded with the core action and the engine branch, then progressively details Typst constraints, LaTeX format, and validation. Dense but each sentence carries operative information. It is long for a tool description and the Typst/LaTeX blocks could be slightly tightened, so it is not a model of concision, but little is filler.

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

Completeness5/5

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

For a 5-parameter, no-output-schema mutation tool, the description covers the full call surface plus the failure modes: what source must contain per engine, what validation does and reports (status/last_error), engine availability via list_templates, and post-creation immutability. Nothing an agent needs to call it correctly is missing.

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

Parameters5/5

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

Schema description coverage is 0%, so the description carries the full burden and does: engine default and the source-required-for-typst rule, the exact required format of source per engine (raw .typ with sys.inputs access vs. complete Jinja2 LaTeX document with ((* *)), ((( ))), ((# #)) blocks), validate's test-compile semantics, and id's slug charset [a-z0-9_-]. Only display_name is left undocumented, which is self-evident.

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

Purpose5/5

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

States a specific verb + resource + lifecycle state: 'Create a DRAFT template.' Distinguishes itself from siblings by naming the read path (get_template), the enumeration tool (list_templates), and the mutation follow-up (update_template_draft implied), so an agent can place it in the template lifecycle 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.

Usage Guidelines4/5

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

Gives concrete conditional guidance: engine defaults to 'latex'; pass engine='typst' and then source becomes REQUIRED; omit source for the LaTeX canonical starter; validate=True test-compiles in the same call. It also names get_template('default') and get_template('typst-classic') as starting points. It does not explicitly route 'editing an existing draft' to update_template_draft, so it stops short of 5.

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

duplicate_base_resumeDuplicate Base ResumeC

Clone an existing base resume into a new slug.

NameRequiredDescriptionDefault
slugYes
new_slugYes
new_display_nameNo

TDQS

C2.7/5.0
Behavior2/5

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

Annotations already declare readOnlyHint=false and destructiveHint=false, so safety is partly covered. The description adds nothing beyond that: it does not say whether the copy is deep or shallow, whether source content is left untouched, or what happens if new_slug already exists (annotations mark idempotentHint=false, so a collision error is plausible but unstated).

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

Conciseness4/5

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

A single short sentence with the verb and target front-loaded and no wasted words. It is concise, though the brevity comes partly from under-specification rather than disciplined editing.

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

Completeness2/5

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

For a mutation tool with three undocumented parameters, no output schema, and only a default-valued third argument, the description omits too much: no mention of the third parameter, no collision behavior, and no indication of what the new resume inherits. An agent could call it, but with avoidable guesswork.

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

Parameters2/5

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

Schema description coverage is 0%, so the description must carry the load, but it only gestures at two of the three parameters ('existing' slug and 'new slug'). The optional new_display_name is never mentioned, nor is uniqueness/format expected for new_slug or the default display name of the clone.

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

Purpose4/5

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

States a specific verb ('Clone') and resource ('base resume') plus the outcome ('into a new slug'), so an agent knows this is a copy operation. It does not, however, distinguish itself from close siblings like create_base_resume, create_base_resume_from_kb, or kb_sync_base, which could also produce a new resume.

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

Usage Guidelines2/5

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

There is no when-to-use guidance and no mention of the alternatives that produce a new base resume (create_base_resume, create_base_resume_from_kb, kb_sync_base). The agent must infer that this tool is for copying an existing resume rather than building one from knowledge-base data.

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

edit_applicationEdit Tailored ResumeA
Destructive

INCREMENTAL FIX: apply typed edit ops on top of an existing application's CURRENT tailored resume (customized_json), preserving every prior edit.

Falls back to the base resume only when the application has no customized_json
yet (nothing to preserve). Suited to refining or retrying a tailored resume
after inspecting PDF previews — swap a bullet, tweak wording, fix one thing —
without losing the rest of what's already been tailored and without creating
duplicate applications.
Accepts the FULL op vocabulary documented on edit_base_resume — every
kind. replace_entry changes an entry's dates, title, company, project name
or tech list; add/replace/remove/move_extra_section handle the custom
Publications/Awards/Volunteer sections.

Op field names (these exact keys, no synonyms):
{"kind": "replace_bullet", "section": "experience", "index": 0,
 "bullet_index": 2, "value": "New bullet text"} — `kind` (not op/type),
`index` (not entry_index; 0-based into the FULL array incl. disabled rows),
`value` (not text).
Index is 0-based into the full customized_json array (including enabled:false),
as shown by get_application, not PDF ordinals. Response `applied[].name`
echoes the entry each op touched.
Clears pdf_path/tex_path (the old PDF is stale); render_pdf produces a new one.
NameRequiredDescriptionDefault
opsYesTyped edit ops. Each is an object with a `kind`, one of: replace_summary | toggle_entry | replace_bullet | replace_skills_group | add_skill_item | add_bullet | add_entry | replace_entry | remove_entry | remove_bullet | replace_contact | replace_certifications | add_extra_section | replace_extra_section | remove_extra_section | move_extra_section. To change a field ON an entry — dates, title, company, project name, link, tech — use replace_entry with that entry's index and the full edited entry object; it is scoped to that one entry (a whole-resume replace is the separate update_base_resume tool). See the tool description for each op's shape. add_extra_section/replace_extra_section `value` is {key,title,enabled,type:"entries"|"bullets"} plus EITHER entries:[{heading,subheading?,location?,date?,link?,enabled,bullets:[str]}] OR bullets:[str] — never both; unknown keys are rejected (400, extra="forbid"). Text the ops write is implied first person: a line with I/he/she/they or the owner's name is a 400 naming the lines, and nothing is written.
application_idYes

TDQS

A4.6/5.0
Behavior5/5

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

Annotations already declare destructive=true, readOnly=false, and idempotent=false. The description adds valuable behavior beyond that: it preserves prior edits, falls back only when customized_json is absent, clears stale pdf_path/tex_path, and says applied[].name echoes the touched entry.

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

Conciseness5/5

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

Front-loads the key framing with "INCREMENTAL FIX" and proceeds through fallback, usage, op vocabulary, exact field names, indexing, response, and file invalidation. It is dense but every sentence carries useful context for a complex 16-op tool.

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

Completeness4/5

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

Covers the core behavior, fallback, response echo, and stale-file handling well for a destructive complex tool with no output schema. It is not fully self-contained because full op shapes must be read from the sibling edit_base_resume description.

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

Parameters4/5

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

With 50% schema description coverage, the description meaningfully compensates by specifying exact op keys (`kind`, `index`, `value`) and 0-based indexing into the full array including disabled rows, not PDF ordinals. It still delegates full op shapes to edit_base_resume and does not describe application_id, though that parameter is obvious.

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

Purpose5/5

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

States a specific verb and resource: applying typed edit ops to an existing application's CURRENT tailored resume (customized_json), preserving prior edits. It distinguishes the resource from base-resume editing and from creating duplicate applications.

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

Usage Guidelines4/5

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

Explicitly says it is suited to refining or retrying a tailored resume after inspecting PDF previews, and explains the base-resume fallback when no customized_json exists. It references edit_base_resume for the op vocabulary but does not fully state when to use that sibling instead or when not to use this tool.

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

edit_base_resumeEdit Base ResumeA
Destructive

Apply typed edit ops to a base resume. replace_entry changes a field on one entry (dates, title, company, project name, link, tech) given that entry's index and the full edited entry; update_base_resume instead replaces the whole resume body (PUT). ExtraSection shape is on ops (ATS-neutral).

Indices are 0-based into the FULL array (incl. enabled:false), as returned by get_base_resume, never PDF order. Response applied echoes each op. Kinds:

  • {"kind":"replace_summary","value":str|null,"expected_content_hash"?:str}

  • {"kind":"toggle_entry","section":"experience"|"projects","index":int,"enabled":bool}

  • {"kind":"replace_bullet","section":,"index":int,"bullet_index":int,"value":str,"expected_content_hash"?:str}

  • {"kind":"replace_skills_group","category":str,"items":[str]} (case-insensitive)

  • {"kind":"add_skill_item","category":str,"item":str}

  • {"kind":"add_bullet","section":"experience"|"projects","index":int,"text":str}

  • {"kind":"add_entry","section":,"value":} (appends)

  • {"kind":"replace_entry","section":,"index":int,"value":} (one indexed entry only)

  • {"kind":"remove_entry","section":,"index":int}

  • {"kind":"remove_bullet","section":,"index":int,"bullet_index":int}

  • {"kind":"replace_contact","value":}

  • {"kind":"replace_certifications","items":[str]}

  • {"kind":"add_extra_section","value":}

  • {"kind":"replace_extra_section","section_key":str,"value":} (key may not change)

  • {"kind":"remove_extra_section","section_key":str}

  • {"kind":"move_extra_section","section_key":str,"to_index":int} =experience|projects|education (toggle_entry/add_bullet: experience|projects). section_key is ExtraSection.key. Bad index/category/key → error. Re-renders PDF. Every response carries render_error: non-null means the automatic re-render failed and the existing PDF is stale.

NameRequiredDescriptionDefault
opsYesTyped edit ops. Each is an object with a `kind`, one of: replace_summary | toggle_entry | replace_bullet | replace_skills_group | add_skill_item | add_bullet | add_entry | replace_entry | remove_entry | remove_bullet | replace_contact | replace_certifications | add_extra_section | replace_extra_section | remove_extra_section | move_extra_section. To change a field ON an entry — dates, title, company, project name, link, tech — use replace_entry with that entry's index and the full edited entry object; it is scoped to that one entry (a whole-resume replace is the separate update_base_resume tool). See the tool description for each op's shape. add_extra_section/replace_extra_section `value` is {key,title,enabled,type:"entries"|"bullets"} plus EITHER entries:[{heading,subheading?,location?,date?,link?,enabled,bullets:[str]}] OR bullets:[str] — never both; unknown keys are rejected (400, extra="forbid"). Text the ops write is implied first person: a line with I/he/she/they or the owner's name is a 400 naming the lines, and nothing is written.
slugYes

TDQS

A4.7/5.0
Behavior5/5

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

Goes well beyond the annotations by disclosing that the tool re-renders the PDF, that every response carries render_error (non-null = stale PDF), that ops write implied first-person text and otherwise 400 with nothing written, and that expected_content_hash supports concurrency checks. These are the mutation side effects an agent needs and are not in the annotations.

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

Conciseness4/5

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

Front-loads the core distinction and index convention before the op list, and the op list is dense but each line earns its place. There is mild duplication between the description's kind list and the `ops` schema description, which keeps it from being maximally tight.

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

Completeness4/5

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

With no output schema, the description still tells the agent what comes back (`applied` echo and `render_error`), and it covers validation and index semantics. The undocumented `slug` param and an incomplete picture of the full response shape are the only shortfalls.

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

Parameters4/5

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

Schema coverage is only 50%, and the description carries the burden for `ops` by enumerating every kind's shape, the <sec> enum values, the ExtraSection key/entries-or-bullets constraint, and the move_extra_section key-immutability rule. The `slug` parameter is never explained in either place, which is the remaining gap.

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

Purpose5/5

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

States a specific verb+resource ('Apply typed edit ops to a base resume') and immediately distinguishes it from the sibling update_base_resume, which replaces the whole body. An agent can tell the two apart without opening either schema.

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

Usage Guidelines5/5

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

Explicitly says to use replace_entry for field-level changes on one entry versus update_base_resume for a whole-body PUT, and states indices are 0-based into the FULL array as returned by get_base_resume, never PDF order. It also names the failure conditions (bad index/category/key → error).

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

explore_gap_frequencyRecurring Skill GapsA
Read-onlyIdempotent

Skills that recur as gaps across saved JDs (best-scoring base resume vs JD, before tailoring), ranked by how many jobs want them and their potential match score gain. This is RECURRING DEMAND, not a "you lack this" or learn-next list: a skill can recur because the evidence lives on a different base resume, is stale, or is merely mis-placed on this one. The learn-vs-move distinction is the per-skill tier on build_areas (build = no resume evidence AND nothing in the Career KB, the only genuinely learn-it rows; surface = the material exists, port or strengthen it) — get_job_search_brief carries build_areas, or GET /api/explore/build-areas. Hygiene mirror_wording gaps are excluded here: the resume already matches those at full keyword credit, so the literal JD token moves no score and is not demand. Each row also carries category_label, the plain-words form of category (e.g. "Add an example in a job or project"); the raw keys (dual_place, missing_skills) and the build_areas tier values are internal identifiers, and category_label / the tier word is their user-facing wording. Optionally filtered by role/level/type; limit caps the number of skills returned.

NameRequiredDescriptionDefault
levelNo
limitNo
role_categoryNo
employment_typeNo

TDQS

A3.9/5.0
Behavior4/5

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 adds real behavioral context beyond them: ranking semantics, exclusion of mirror_wording hygiene gaps and why (full keyword credit means no score movement), and guidance that raw keys (dual_place, missing_skills, tier values) are internal with category_label as the user-facing wording.

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

Conciseness4/5

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

The core definition is front-loaded in the first clause and the following sentences are dense with interpretation-relevant guidance rather than filler. It runs long, and the internal-identifier aside is somewhat discursive, but each part earns its place by preventing misreading of the output.

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

Completeness4/5

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

With no output schema, the description must convey the return shape, and it does: each row carries category_label and ranking by job demand plus potential match-score gain. Filtering behavior is sketched but not specified in detail, which is the main remaining gap.

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

Parameters3/5

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

Schema description coverage is 0%, so the description carries the full parameter burden. Its single line 'Optionally filtered by role/level/type; limit caps the number of skills returned' maps all four schema params to plain words, but supplies no value formats, allowed values, or defaults for level, role_category, employment_type, or limit.

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

Purpose4/5

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

States a specific resource and scope: skills recurring as gaps across saved JDs, measured on best-scoring base resume vs JD before tailoring, ranked by job count and potential match-score gain. It clearly disambiguates from a 'you lack this / learn-next' interpretation. It does not name sibling analytics tools (explore_top_skills, explore_skill_heatmap, resolve_gaps) by name, so sibling differentiation is partial.

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

Usage Guidelines4/5

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

Explains what this output represents and explicitly redirects the learn-vs-move question to another surface ('the learn-vs-move distinction is the per-skill tier on build_areas ... get_job_search_brief carries build_areas'). That is a concrete when-to-use-something-else pointer, though it never states a positive trigger condition for calling this tool.

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

export_jobsExport JobsA
Read-onlyIdempotent

Export jobs, newest first, with extracted fields and nested skills, for open-ended analysis. Paged by limit (default 10, max 50) and offset; a page shorter than limit is the last. Rows run a few thousand characters (the skills list is most of it) and omit raw_text and extracted_json, which get_job returns for one posting. since is an ISO date (YYYY-MM-DD); skill is a case-insensitive substring.

NameRequiredDescriptionDefault
levelNo
limitNo
sinceNo
skillNo
offsetNo
role_categoryNo

TDQS

A4.3/5.0
Behavior4/5

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

Annotations already declare readOnly, idempotent, non-destructive, so safety is covered. The description adds real behavioral detail beyond them: pagination semantics (page shorter than limit is the last), row size in characters, and the fact that raw_text and extracted_json are omitted. Return format is only partially covered (no output schema).

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

Conciseness4/5

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

Dense but front-loaded: purpose first, then pagination, then payload shape, then parameter formats. Every sentence carries information, though the parenthetical asides add some length without changing agent behavior.

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

Completeness4/5

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

For a 6-param read-only export with no output schema, the description supplies the pagination contract, row-size expectations, and omitted fields, which is what an agent needs to call it. The only shortfall is the undocumented level and role_category filters.

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

Parameters4/5

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

Schema coverage is 0%, so the description must carry the load. It documents limit (default 10, max 50), offset, since (ISO YYYY-MM-DD), and skill (case-insensitive substring), which is most of the parameter surface. However, the level and role_category filters are left entirely unexplained, which is a real gap for a 6-param tool.

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

Purpose5/5

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

States a specific verb and resource (export jobs), the ordering and payload shape (newest first, extracted fields, nested skills), and the intent (open-ended analysis). It explicitly distinguishes itself from get_job, which returns raw_text and extracted_json for a single posting, so an agent can route without opening the schema.

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

Usage Guidelines4/5

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

Frames the use case (open-ended analysis, bulk export) and names get_job as the single-posting alternative. It stops short of explicit exclusions against sibling list_jobs, so the when-not-to-use case is inferred rather than stated.

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

find_job_by_urlFind Job by URLA
Read-onlyIdempotent

Answer "is this posting already captured?", so an extraction can be skipped: posting-equality source_url lookup returning {found, job, application_exists, application_id}. Matching ignores query strings and fragments (?utm_*, ?gh_src=, #apply) and treats the posting's own sub-paths (/apply, /application) as the same posting, so tracking parameters need not be stripped from the input. A search-results or employer-index URL still matches nothing. found=False means the posting is new; store_extracted_jd still dedupes authoritatively via already_existed.

NameRequiredDescriptionDefault
source_urlYes

TDQS

A4.8/5.0
Behavior5/5

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

Annotations already cover the safety profile (readOnly, idempotent, non-destructive), and the description adds real behavioral detail beyond them: the matching algorithm (ignores ?utm_*/?gh_src=/#apply, treats /apply and /application as the same posting), what counts as a non-match, and the meaning of found=False. That is exactly the extra context a caller needs.

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

Conciseness4/5

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

Front-loads the purpose and return shape, then layers matching rules and the dedupe caveat. It is dense and information-rich with no wasted sentences, though the parenthetical lists make it slightly heavier to parse than necessary.

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

Completeness5/5

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

For a one-parameter lookup with no output schema, the description fully covers purpose, matching edge cases, return keys, and the relationship to the authoritative dedupe path. An agent has everything needed to call and interpret it correctly.

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

Parameters4/5

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

Schema coverage is 0% for the single source_url parameter, but the description compensates with real semantics: tracking parameters and fragments need not be stripped, and the posting's own sub-paths are normalized. It clarifies what input is acceptable rather than just naming the field.

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

Purpose5/5

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

Opens with the concrete question it answers ("is this posting already captured?") and names the resource (posting-equality source_url lookup) and the return shape. An agent can immediately tell it apart from siblings like store_extracted_jd, list_jobs, and get_job.

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

Usage Guidelines5/5

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

Explicitly frames when to use it (before an extraction, to skip work when found=True) and names the alternative that dedupes authoritatively (store_extracted_jd via already_existed). It also states the failure mode: search-results or employer-index URLs match nothing. Nothing is left to inference.

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

generate_cover_letterGenerate Cover LetterA
Destructive

Maestro's AI writes a cover letter for an application in the requested tone, with the user's API key (with none set it returns an error). This replaces the application's prior generated cover-letter entry. Refused (409) when the user's writer setting (get_setup_status) says the agent app writes; store_cover_letter stores a letter the caller wrote, with no LLM call.

NameRequiredDescriptionDefault
toneYes
application_idYes

TDQS

A4.1/5.0
Behavior5/5

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

Adds substantial traits beyond the annotations: it errors when no API key is set, it overwrites the prior generated entry (concretely defining what destructiveHint covers), and it returns 409 when the writer setting conflicts. These are exactly the preconditions an agent needs before invoking.

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

Conciseness4/5

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

Three sentences, front-loaded with the action, then prerequisites, then failure modes and the sibling contrast. Dense but every clause carries information; the parenthetical error note is slightly parenthetical-heavy but not wasteful.

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

Completeness4/5

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

No output schema exists, and the description implies a stored letter but doesn't say what the call returns (letter body, id, or entry reference). Otherwise preconditions, side effects, and refusal behavior are all covered for a two-param generation tool.

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

Parameters2/5

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

Schema coverage is 0% and both params are bare 'string' fields, yet the description only gestures at 'tone' without listing valid tones or noting format, and says nothing about application_id beyond context. With the schema doing nothing, the description needed to carry this and largely did not.

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

Purpose5/5

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

States a specific verb and resource ('writes a cover letter for an application') plus the key qualifier 'Maestro's AI', immediately separating it from store_cover_letter. An agent can tell what it produces and that generation is LLM-backed.

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

Usage Guidelines4/5

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

Names the alternative (store_cover_letter, 'no LLM call') and the condition that blocks this tool (writer setting says agent app writes, checked via get_setup_status), plus the missing-API-key prerequisite. It stops short of saying which situation positively favors this tool, but the contrast is clear enough to route correctly.

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

generate_qa_answersGenerate Screening AnswersA

Maestro's AI writes a batch of screening-question answers for an application, with the user's API key (with none set it returns an error). questions is the complete list of questions to answer in this batch. Outreach/cold messages are asked as free-form questions here (e.g. "Write a short LinkedIn DM to the hiring manager") — answers are grounded in the resume and the application's linked referral contact when one exists. Refused (409) when the user's writer setting (get_setup_status) says the agent app writes; store_qa_answers stores answers the caller wrote, with no LLM call.

NameRequiredDescriptionDefault
questionsYes
application_idYes

TDQS

A4.3/5.0
Behavior4/5

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

Adds real context beyond annotations: requires the user's API key and errors without it, grounded in the resume and linked referral contact, and 409 refusal tied to get_setup_status. Does not mention latency/cost of the LLM batch or batching limits, but covers the main behavioral traits.

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

Conciseness4/5

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

Front-loads the core purpose and parameter clarification, with backticked parameter names aiding scanability. Dense but nearly every sentence carries routing or behavioral information.

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

Completeness4/5

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

For an open-world, non-idempotent mutation with no output schema, it covers auth prerequisites, grounding sources, refusal conditions, and the sibling alternative. Little is left ambiguous, though return/format expectations are absent.

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

Parameters4/5

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

With 0% schema description coverage, the description usefully clarifies that `questions` is the complete list of questions to answer in this batch, and shows the kind of free-form prompts accepted. `application_id` is left implied as the target application.

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

Purpose5/5

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

States a specific verb+resource ('writes a batch of screening-question answers for an application') with the actor (Maestro's AI) and scope. It is clearly distinguishable from store_qa_answers, which is described as storing caller-written answers.

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

Usage Guidelines4/5

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

Explicitly names the alternative (store_qa_answers for answers the caller wrote, no LLM call) and states a when-not condition (refused 409 when the writer setting says the agent app writes). Lacks a crisp positive 'use when' statement, but the routing is clear.

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

get_applicationGet ApplicationB
Read-onlyIdempotent

Get one application's full detail: the tailored resume (customized_json) and the joined job. Use compare_ats for before/after scores.

NameRequiredDescriptionDefault
application_idYes

TDQS

B3.4/5.0
Behavior3/5

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 fully covered. The description adds the return payload (customized_json plus joined job), which is useful given no output schema, but says nothing about behavior for a missing or invalid ID or any auth requirements.

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

Conciseness5/5

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

Two short sentences, front-loaded with what is retrieved and what is returned; no filler or restatement of the name.

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

Completeness4/5

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

For a single-entity read tool with one param and no output schema, the description is nearly sufficient — it characterizes the return value and points at a related comparison tool. The only real omission is how to obtain the application_id.

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

Parameters2/5

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

Schema description coverage is 0% and the description says nothing about application_id — neither its format nor that it originates from list_applications/propose_application. With only one parameter this is a small gap, but the description contributes no parameter meaning at all.

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

Purpose4/5

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

States a specific verb and resource (get one application) and enumerates the payload: the tailored resume (customized_json) and the joined job. That payload description distinguishes it meaningfully from list_applications and from edit/update_application, though it doesn't contrast with other single-entity getters like get_proposal.

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

Usage Guidelines3/5

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

The sentence 'Use compare_ats for before/after scores' routes the agent on an adjacent need, but there is no explicit statement of when to call this tool versus get_application-adjacent siblings (get_proposal, get_final_review) or where the application_id comes from. Usage is implied rather than prescribed.

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

get_autofill_profileGet Autofill ProfileA
Read-onlyIdempotent

Read the user's application-form autofill data: profile (personal contact + address, work-authorization answers (work_auth: the job's country's, none without one; work_auth_by_country: per market key, e.g. UK; a question naming a country takes its), preferences like salary/notice/relocation, education, languages — each a language with read/speak/write level Basic/Intermediate/Fluent and separate native and fluent booleans — custom Q&A presets), plus employment blocks and skills from the selected resume when application_id or base is given. Response is labeled source: "profile" and includes canonical_identity (legal_first, legal_last, preferred) mapped only from stored autofill personal fields; it is the source of truth for form identity fields and takes precedence over ATS-parsed values. It is the feed the Chrome extension's deterministic fill uses. EEO/demographic answer values (profile.eeo) are returned ONLY when Profile standing consent is active (eeo_consent.enabled) and are stripped otherwise; when returned they are the user's stored answers, intended for Playwright/agent fill verbatim with no inference or model-authored values. eeo.veteran_status is no, yes or decline: one question, "Are you a veteran?" (a no also answers "not a protected veteran"; a yes alone never says which protected class applies, so leave a protected-class list to the user). eeo.gender is male, female, non_binary, self_describe or decline; with self_describe, eeo.gender_self_describe is the user's own words for a form's self-describe box. A form lacking a matching option is left to the user. Missing EEO values are completed by the user in Profile or in the browser; consented answers are not pasted or re-dictated through chat. A value absent here (a county) is not in the profile and is not guessable. WOTC, signatures and terms are human-only.

NameRequiredDescriptionDefault
baseNo
application_idNo

TDQS

A4.3/5.0
Behavior5/5

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

Despite annotations already covering readOnly and idempotent behavior, the description adds substantial behavioral detail: EEO values are returned only under active consent, otherwise stripped; returned EEO answers are verbatim stored answers with no inference allowed; missing values are not guessable; and canonical identity takes precedence over ATS-parsed values.

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

Conciseness3/5

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

The opening purpose is front-loaded, but the body is a dense run-on with nested parentheticals. Much of the EEO and consent detail is valuable, but the structure could be tightened or bulleted for easier parsing.

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

Completeness5/5

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

With no output schema, the description carries the full burden of explaining returned data, and it does so thoroughly: response labeling, canonical identity precedence, conditional EEO consent behavior, and edge cases such as missing values are all covered.

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

Parameters3/5

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

Schema description coverage is 0%, so the description must compensate for undocumented `base` and `application_id` parameters. It does explain that employment blocks and skills come from the selected resume when either parameter is given, but it does not define the difference between `base` and `application_id` or explain null/default behavior.

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

Purpose5/5

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

The description opens with a specific verb and resource: "Read the user's application-form autofill data." It then enumerates the profile contents and distinguishes this read operation from the sibling mutation tool `set_autofill_profile`.

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

Usage Guidelines4/5

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

It gives clear usage context: this is the feed for the Chrome extension's deterministic fill and the source of truth for form identity fields. It also states important exclusions such as WOTC, signatures, and terms being human-only, though it does not explicitly compare when to use this versus other sibling read tools.

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

get_base_resumeGet Base ResumeB
Read-onlyIdempotent

Get a base resume's full data JSON, render status, and metadata.

NameRequiredDescriptionDefault
slugYes

TDQS

B3.2/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false and openWorldHint=false, so the safety profile is fully covered by structured data. The description adds value by disclosing what the read returns (full data JSON, render status, metadata), which is useful given there is no output schema. It stops short of describing error/not-found behavior.

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

Conciseness5/5

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

A single front-loaded sentence with no filler; the payload contents are listed compactly and every clause informs the agent about the call's output.

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

Completeness4/5

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

With no output schema and only one parameter, the description does the necessary work by naming the returned artifacts. It is nearly complete for a simple read tool; only the slug semantics and failure behavior are absent.

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

Parameters2/5

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

Schema description coverage is 0% for the single 'slug' parameter, so the description carries the full burden. It implies the slug identifies the resume but never explains the slug's format, source (e.g., from list_base_resumes), or what happens on an unknown slug.

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

Purpose4/5

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

States a specific verb ('Get') and resource ('base resume') and enumerates the payload ('full data JSON, render status, and metadata'), so it is clearly distinguishable from list_base_resumes. It does not explicitly distinguish itself from retrieval-adjacent siblings like get_resume_version, but the purpose is unambiguous.

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

Usage Guidelines2/5

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

There is no statement of when to use this tool versus list_base_resumes, get_resume_version, update_base_resume, or edit_base_resume. No preconditions or exclusions are given; the agent must infer usage entirely from the name.

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

get_career_contextGet Career ContextA
Read-onlyIdempotent

Read the user's career record from the Career KB, as format="json" (the default) or format="markdown".

json: `resume`, the approved-points resume view assembled from the profile and the
non-archived entities, and `memory`, the beyond-the-resume string: identity facts and
entity notes that don't belong on a resume. `resume` carries approved points only;
`memory` also includes the profile summary and notes and the non-archived entities'
notes.

markdown: the exact portable career.md generated from the current Career KB, as
deterministic Markdown text, the file the web's career export downloads.

Intended as grounding for writing about the user's career (LinkedIn posts, outreach
drafts), optionally beside a base resume for its voice. It never invents facts,
metrics, employers, or dates; anything absent from it (and from a fetched base resume)
is not part of the user's recorded career. Neither format carries IDs; the profile
set's career history tools return the IDs needed to correct anything. Read-only.
NameRequiredDescriptionDefault
formatNojson

TDQS

A4.7/5.0
Behavior5/5

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

Annotations already declare read-only and idempotent, but the description adds substantial non-redundant behavior: what 'resume' contains (approved points only), what 'memory' adds (profile summary, notes, non-archived entity notes), that markdown output is deterministic and matches the web export, and the critical constraint that neither format carries IDs. That last point materially changes how an agent would sequence calls.

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

Conciseness4/5

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

Front-loaded with the action and the format branch, then two clearly labelled per-format paragraphs. Slightly padded at the end — the 'never invents facts, metrics, employers, or dates' sentence is a useful grounding constraint but is stated at length, and the no-IDs point is repeated from context.

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

Completeness5/5

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

There is no output schema, so the description must describe return contents — and it does for both formats, including what is excluded from 'resume'. Combined with the ID caveat and the grounding-use framing, 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.

Parameters5/5

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

Schema coverage is 0% and the enum values carry no descriptions, so the description must carry the burden — and it does. It documents both enum values, restates the default, and contrasts the two outputs semantically ('json' = assembled views, 'markdown' = exact portable career.md).

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

Purpose5/5

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

States a specific verb and resource ('Read the user's career record from the Career KB') and immediately defines what the output is in each format. It is clearly distinguishable from siblings like kb_get_entity (single entity), kb_list_points (IDs), and get_base_resume (a different artifact).

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

Usage Guidelines4/5

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

Explicitly frames intended use ('grounding for writing about the user's career... optionally beside a base resume for its voice') and routes correction work elsewhere ('the profile set's career history tools return the IDs needed to correct anything'). It stops short of naming that sibling tool or stating an explicit when-not-to-use case, so it's clear context without full exclusions.

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

get_final_reviewGet Final ReviewA
Read-onlyIdempotent

Compact final-review bundle: job summary, chosen base/match score delta, PDF readiness, QA answers, blocked/manual items, evidence manifest. approval_recorded is the user's yes on this proposal; eeo.consent_recorded is their standing EEO consent (no values). Requires an existing proposal — a 404 usually means propose_application was not called (it accepts application_id to late-link) or an application id was passed where a proposal id belongs. duplicate_submitted=true means a same-company+title proposal was already submitted (relevant to the user's approval decision). flags lists the job's recorded form answers worth a second look (record_filled_answers): question, source, answer (an EEO one carries eeo_answered instead) and each flag's reason. base_country.eligible is false when the resume being sent is set for other countries than the job's.

NameRequiredDescriptionDefault
proposal_idYes

TDQS

A4.3/5.0
Behavior5/5

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

Annotations already declare readOnly/idempotent/non-destructive, but the description adds substantial semantics beyond them: what `approval_recorded` vs `eeo.consent_recorded` mean, what `duplicate_submitted=true` implies for the approval decision, what `flags` contains (question, source, answer, reason), and when `base_country.eligible` is false. That is exactly the contextual layer structured fields don't carry.

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

Conciseness4/5

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

Front-loaded with the bundle contents before the field semantics, and every sentence adds information. Slightly dense/run-on in the error-handling portion, but no filler.

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

Completeness5/5

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

No output schema exists, so the description carries the return-shape burden — and it does, defining the bundle's fields, error meanings, and edge-case flags. Nothing an agent needs to call this correctly and interpret the result is missing.

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

Parameters4/5

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

Schema coverage is 0% for the single parameter, so the description must compensate — and it does by clarifying that proposal_id must reference an existing proposal and by warning about confusing it with an application id. It stops short of stating where to obtain a proposal id (e.g., list_proposals), so not a 5.

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

Purpose4/5

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

Opens with a specific noun bundle ('Compact final-review bundle') and enumerates its contents (job summary, match score delta, PDF readiness, QA answers, blocked/manual items, evidence manifest). An agent knows exactly what comes back. It doesn't explicitly contrast with sibling get_proposal, so sibling 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.

Usage Guidelines4/5

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

States the precondition ('Requires an existing proposal') and interprets the failure mode: a 404 usually means propose_application wasn't called (which accepts application_id to late-link) or an application id was passed instead of a proposal id. It also frames the context as feeding the user's approval decision. No explicit 'use X instead' exclusion, hence not a 5.

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

get_health_reportGet Resume Health ReportA
Read-onlyIdempotent

Fetch the most recent stored health report for a base resume or application without re-running it. kind is 'base' or 'application', key is the slug or application id. Returns {score, grade, tier, next_grade, gates, counts, findings} (fields as in run_health_check), or an error if no report exists yet (run_health_check creates one).

NameRequiredDescriptionDefault
keyYes
kindYes

TDQS

A4.3/5.0
Behavior4/5

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 behavioral context beyond that: the failure mode (error when no report exists yet) and the pointer to run_health_check as the remedy.

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

Conciseness4/5

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

Front-loaded with the core action, followed by parameter meaning and return shape in two tight sentences. The inline field list is dense but earns its place given there is no output schema.

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

Completeness4/5

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

With no output schema, the description steps in to enumerate the returned fields and the error case, which is enough to call and interpret the tool. A mention of report freshness/staleness semantics would make it complete.

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

Parameters4/5

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

Schema description coverage is 0%, so the description must carry the burden and largely does: it explains that `kind` is 'base' or 'application' and `key` is the slug or the application id. Only minor gaps remain (format of the slug/id is not spelled out).

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

Purpose5/5

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

States a specific verb (Fetch) and resource (most recent stored health report) plus the scope (base resume or application) and the key constraint ('without re-running it'). It is immediately distinguishable from the sibling run_health_check, which it names.

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

Usage Guidelines4/5

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

Clearly frames when to use it: to read an existing report rather than recompute one, and it points at run_health_check as the tool that creates a report when none exists. It stops short of an explicit 'use X when you want a fresh score' rule, but the routing is inferable.

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

get_jobGet Job DetailsB
Read-onlyIdempotent

Get a job with its most recent application. The nested job carries ownership (owned_here, owner, handover, pending_requests), identifying replicas and jobs being handed over.

NameRequiredDescriptionDefault
job_idYes

TDQS

B3/5.0
Behavior3/5

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 useful context about the payload shape (nested ownership fields: owned_here, owner, handover, pending_requests) and what those fields identify, which goes 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.

Conciseness4/5

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

Two sentences, purpose front-loaded first, return-shape detail second. Efficient and no padding, though the second sentence is dense with parenthetical field names.

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

Completeness3/5

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

No output schema exists, so the description must carry the return burden; it partially does by naming the ownership fields. But job_id semantics and the relationship to siblings (get_application) are left unstated, leaving gaps for a lookup tool.

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

Parameters2/5

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

Schema description coverage is 0% and the description adds nothing about job_id — no format, source, or how to obtain a valid id. With a single undocumented parameter, the description fails to compensate for the schema gap.

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

Purpose4/5

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

States a specific verb+resource ('Get a job') and adds scope detail ('with its most recent application'), which distinguishes it from siblings like list_jobs and get_application. It stops short of explicitly naming alternatives, but the agent can tell 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.

Usage Guidelines2/5

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

There is no guidance on when to use this versus get_application, list_jobs, or get_job_search_brief. Usage is only implied by the word 'Get' on a single job_id; no exclusions or prerequisites are stated.

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

get_job_search_briefGet Job Search BriefA
Read-onlyIdempotent

Read the server-composed job-search brief: profile constraints (location, relocation, work-auth VERBATIM plus warnings[] when values are contradictory or missing — never guessed), persona text (may be empty, in which case the analytics-derived targets are the stronger signal), active base-resume summaries, role mix, top required skills, build areas (per-skill tier plus category_label, the plain-words label for the raw category key), referral careers pages (company + careers_url + has_contact), and counts of jobs captured in the last 30 days by role category. profile.work_auth_by_country holds those yes/no answers for each market the user applies in, keyed by market ("UK", not "GB"); profile.work_auth is the home market's set, named by work_auth_market and kept for one release; unless the user lives and applies in one country, each warning names its country. last_runs maps each automation to when its newest run that did not fail finished (UTC ISO; a failed run does not count; absent when none has). roles is the role catalog as {key, label}. It is the entry point of the agentic job-search workflow (playbook: docs/agentic-job-search.md), which covers capture, scoring and proposals; applying is outside its scope. sync carries enabled and role (home, remote, or null when sync is off). applying.answer_level is the Screening answers level (facts, history, queued).

NameRequiredDescriptionDefault

No parameters

TDQS

A4.6/5.0
Behavior5/5

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

Annotations already cover read-only/idempotent safety, but the description adds substantial behavioral detail: warnings are never guessed, work-auth values are verbatim, persona may be empty, failed runs do not count toward last_runs, sync.role is null when off, and work_auth_market is kept for one release. This is exactly the extra context the annotations do not provide.

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

Conciseness4/5

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

The main purpose is front-loaded in the first clause, and every sentence describes return semantics or workflow scope. The paragraph is dense and could be easier to scan as a list, but given the absence of an output schema, the length is largely justified.

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

Completeness5/5

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

With no output schema and no parameters, the description carries the full burden of explaining what the brief contains, and it does so thoroughly: profile constraints, persona, resume summaries, role mix, skills, build areas, referrals, counts, sync state, and answer level. Safety behavior is already covered by annotations.

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

Parameters4/5

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

There are zero input parameters, so the baseline is 4. The description instead spends its space explaining return-field semantics, which is valuable but not part of the input-parameter dimension.

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

Purpose5/5

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

The description opens with a specific verb and resource ("Read the server-composed job-search brief") and enumerates the exact contents, so an agent can tell it apart from sibling tools like get_career_context or list_jobs without opening a schema. It also names its role as the entry point of the workflow.

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

Usage Guidelines4/5

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

It explicitly states when to use it — "the entry point of the agentic job-search workflow" — and defines a boundary: "applying is outside its scope." However, it does not name sibling alternatives or explicit when-not conditions beyond that boundary.

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

get_job_site_loginGet Job-Site LoginA
Idempotent

The email and password the user saved for job-site accounts, for creating an account or signing in on this proposal's application site. Available only while full automation is on and only for a queued or approved proposal; each call is recorded (never the value). The value passes through the agent's AI provider, which is why it is a password the user keeps for job sites alone. Returns {email, password}.

NameRequiredDescriptionDefault
proposal_idYes

TDQS

A4.3/5.0
Behavior4/5

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

With annotations already covering safety hints, the description adds substantial non-obvious context: every call is recorded (but never the value), the value is exposed to the agent's AI provider, and the user's password is deliberately scoped to job sites. It also pre-empts the odd readOnlyHint=false by explaining the audit side effect, so there is no contradiction. It stops short of describing failure behavior when the preconditions are unmet.

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

Conciseness4/5

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

Front-loaded with what the tool returns, followed by availability constraints, audit/privacy notes, and the return shape. Three dense sentences, all earning their place; the AI-provider sentence is slightly circuitous but adds meaningful warning value.

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

Completeness4/5

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

There is no output schema, and the description compensates by specifying the return shape {email, password}, plus availability gates and a privacy warning. Complete for invocation; only a note on what happens when the tool is unavailable or the proposal is unapproved is missing.

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

Parameters3/5

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

Schema description coverage is 0% for the single proposal_id parameter, so the description carries the burden. It only implies the parameter via 'this proposal's application site' and 'a queued or approved proposal', which conveys the concept but not the id format or source (e.g., from list_proposals). Baseline 3 for a one-param tool with a partial hint.

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

Purpose5/5

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

States a precise verb+resource: it retrieves the user's saved email and password for job-site accounts tied to a proposal's application site, and names the intended use (creating an account or signing in). No sibling tool does credential retrieval, so it is unambiguously distinct from get_proposal, get_application, and the kb_* family.

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

Usage Guidelines5/5

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

Gives explicit preconditions that act as when/when-not guidance: available only while full automation is on, and only for a queued or approved proposal. The purpose statement also names the concrete situation in which the agent should reach for it (signing in or creating an account on the application site).

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

get_proposalGet ProposalB
Read-onlyIdempotent

Get proposal detail including job facts, application summary, QA entries, and evidence manifest. Reading expires an overdue pending_review or needs_decision proposal (terminal 'expired').

NameRequiredDescriptionDefault
proposal_idYes

TDQS

B3/5.0
Behavior1/5

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

The description states that reading the resource mutates it, expiring an overdue pending_review or needs_decision proposal into a terminal 'expired' state. That is a state-changing, effectively irreversible side effect, which directly contradicts the readOnlyHint=true and destructiveHint=false annotations. This is a genuine annotation contradiction.

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

Conciseness5/5

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

Two sentences, zero filler, and the return payload is front-loaded before the critical side-effect warning. Every clause earns its place.

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

Completeness4/5

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

With no output schema, the description usefully enumerates the returned sections (job facts, application summary, QA entries, evidence manifest) and warns of the expiry transition, which is the most important thing an agent must know here. It is only incomplete in that it says nothing about the proposal_id parameter.

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

Parameters2/5

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

There is a single required parameter, proposal_id, with 0% schema description coverage, and the description never explains its meaning, format, or where to obtain it. With no annotations or schema text to lean on, the description fails to compensate for the coverage gap.

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

Purpose4/5

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

States a specific verb and resource ('Get proposal detail') and enumerates the payload it returns (job facts, application summary, QA entries, evidence manifest), which is far more useful than a tautology. It implicitly contrasts with list_proposals via 'detail', but never names that sibling explicitly, so it falls 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.

Usage Guidelines3/5

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

Usage is only implied: an agent can infer this fetches one proposal by id rather than listing them. There is no explicit when-to-use, when-not-to-use, or named alternative (e.g. list_proposals for discovery), so guidance is thin.

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

get_rendered_pdfGet Rendered PDFA
Read-onlyIdempotent

Save a rendered PDF locally and render one PNG per page without inlining images. target_type 'base_resume'(slug)/'application'(id) returns the last rendered resume PDF; 'template'(id) returns the sample preview PDF. Returns {filename, path, size_bytes, mime_type, page_count, page_images, em_dash_found, em_dash_pages, artifact_dir?}. Requires an existing render (render_pdf, or validate_template for a template preview). Paths are local to where the backend/MCP server run; browser uploads use the copy staged by prepare_application_pdf_upload. The PDF and per-page PNGs ({id}.pN.png, ~120 dpi) are written under $MAESTRO_CS_PDF_DIR (or a temp dir). This slim response never includes image base64; get_rendered_pdf_page_image returns the visual bytes of exactly one page. em_dash_found reports whether the PDF contains an em dash (U+2014), which rendered resumes in this product are required not to contain; em_dash_pages lists the page numbers. (page_count is None / page_images empty if the PDF can't be read.)

NameRequiredDescriptionDefault
target_idYes
target_typeYes

TDQS

A4.7/5.0
Behavior5/5

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

Beyond the readOnly/idempotent hints it discloses concrete behavior: it writes the PDF and per-page PNGs under $MAESTRO_CS_PDF_DIR (or a temp dir), guarantees no inlined base64, and defines how em_dash_found/em_dash_pages are computed and how page_count/page_images degrade when the PDF can't be read. This is unusually rich disclosure of side effects and edge cases.

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

Conciseness4/5

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

Front-loads the core action, then returns, then prerequisites, then environment details, so an agent can stop reading early. It is a dense block rather than bulleted and the return-shape detail is long, but nearly every sentence adds distinct, useful information.

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

Completeness5/5

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

With no output schema, the description fully enumerates the return object ({filename, path, size_bytes, mime_type, page_count, page_images, em_dash_found, em_dash_pages, artifact_dir?}), the prerequisite, the file destination, and the edge case where the PDF is unreadable. Nothing an agent needs to call and interpret this tool is missing.

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

Parameters5/5

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

Schema description coverage is 0%, so the description carries the full burden and does so well: it explains that target_type accepts 'base_resume' (slug), 'application' (id), and 'template' (id), and describes what each target returns. target_id semantics (slug vs id) are implied by the per-type parentheticals.

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

Purpose5/5

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

The description pairs a specific verb with a specific resource ('Save a rendered PDF locally and render one PNG per page') and clarifies the exact scope (the last rendered resume PDF, a template preview PDF). It is immediately distinguishable from the sibling get_rendered_pdf_page_image, which only returns one page's visual bytes.

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

Usage Guidelines4/5

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

It states the prerequisite plainly ('Requires an existing render (render_pdf, or validate_template for a template preview)') and routes the agent to the alternative tool when image bytes are needed. It doesn't spell out an explicit 'do not use when' clause, so it falls just short of the fully explicit 5.

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

get_rendered_pdf_page_imageGet PDF Page ImageA
Read-onlyIdempotent

Return one rendered PDF page as an explicit opt-in visual payload. page_number is 1-based. max_dimension_px (default 1024) is the longest side of the re-rendered PNG; larger values grow the payload, and encoded payloads over ~1MB are rejected (a smaller max_dimension_px fits). Returns target_type, target_id, page_number, page_count, filename/path/ size/mime metadata, and page_image_b64 for only the requested PNG. Out-of-range page numbers are rejected. Does not change get_rendered_pdf's pre-rendered preview PNGs.

NameRequiredDescriptionDefault
target_idYes
page_numberYes
target_typeYes
max_dimension_pxNo

TDQS

A4.3/5.0
Behavior5/5

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), and the description adds meaningful behavior the annotations cannot: payload-size rejection above ~1MB, out-of-range page rejection, 1-based numbering, and that only the requested PNG is included. These are real operational constraints an agent must plan around.

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

Conciseness4/5

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

Front-loads the core purpose before diving into parameter and return detail, and each sentence carries distinct information with no filler. It is dense but every clause earns its place; only the long parenthetical clauses make it slightly heavy.

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

Completeness4/5

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

With no output schema, the description usefully enumerates the return fields (target_type, target_id, page_number, page_count, filename/path/size/mime, page_image_b64), and constraints are covered. The gap is the unexplained target_type/target_id semantics for a tool that requires both.

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

Parameters3/5

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

Schema description coverage is 0%, so the description carries the param burden, yet it only documents two of four: page_number (1-based) and max_dimension_px (default 1024, longest side, larger grows the payload). target_type and target_id semantics, including the three enum values, are left entirely undocumented.

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

Purpose5/5

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

States a specific verb and resource ('Return one rendered PDF page') and immediately distinguishes itself from the sibling get_rendered_pdf by noting it does not change that tool's pre-rendered preview PNGs. An agent can tell what this produces without opening the schema.

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

Usage Guidelines4/5

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

The 'explicit opt-in visual payload' framing tells the agent this is the deliberate choice for pulling a single page image, and the closing sentence contrasts it with get_rendered_pdf's default previews. It establishes context and the alternative, but never states an explicit trigger condition such as 'use this when you need a page the pre-render doesn't cover.'

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

get_resume_versionGet Resume VersionA
Read-onlyIdempotent

Fetch one resume version including its snapshot and the diff vs its parent.

kind/key as on list_resume_versions: "base"+slug or "application"+id.
number is the version number from that list.
NameRequiredDescriptionDefault
keyYes
kindYes
numberYes

TDQS

A4.4/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true and destructiveHint=false, so the safety profile is covered structurally. The description adds genuine behavioral value by disclosing what is returned (snapshot plus parent diff), which is not inferable from the schema.

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

Conciseness5/5

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

Two sentences, both front-loaded with the highest-value information (what it returns, then how to source the parameters). No filler.

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

Completeness4/5

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

There is no output schema, so the description correctly takes on the job of explaining the return payload (snapshot + diff). Combined with full parameter coverage and annotation-backed safety, only minor gaps remain, such as error behavior for a nonexistent version.

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

Parameters4/5

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

Schema description coverage is 0%, so the description must carry the burden, and it does: it defines kind as 'base' vs 'application', explains key as a slug for base or an id for application, and identifies number as the version number from list_resume_versions. It compensates well, though it omits format details such as whether number is 0-indexed or 1-indexed.

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

Purpose5/5

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

States a specific verb (Fetch) and resource (one resume version), and further specifies the payload: the snapshot and the diff vs its parent. This clearly distinguishes it from the sibling list_resume_versions, which returns many versions rather than one with a diff.

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

Usage Guidelines4/5

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

The description anchors usage to list_resume_versions by telling the agent that kind/key/number come from that list, which is real workflow context. It does not, however, state when not to use this tool or name restore_resume_version as the mutation alternative.

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

get_setup_statusGet Setup StatusA
Read-onlyIdempotent

Where this user's Maestro setup stands, for an agent starting fresh. Returns ai_key (whether Maestro has its own AI key), writer (who writes for agent apps: "agent", the default, means the agent app writes, so the tools where Maestro's own AI writes the text refuse (409) and the agent writes it and saves it with the matching store or add tool; "maestro" means Maestro's AI writes it with the user's key, which needs ai_key), demo_bases (slugs of the shipped demo resume, never the user's own), next_step (the first setup step an agent can do that is not done, {step, tool_set, says}; null when none is left), tool_sets (each set's name, use_when and holds, in journey order) and steps (the full setup status: each step's done and detail, form-answer readiness, suggested bases, PDF engines). The AI key, the writer and the default resume design are set by the user in the app and are never a next step.

NameRequiredDescriptionDefault

No parameters

TDQS

A4.6/5.0
Behavior5/5

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

Goes well beyond the readOnlyHint annotations by disclosing real behavioral consequences: with writer="agent", AI-writing tools refuse with 409 and the agent must write and persist via the matching store/add tool; with writer="maestro", the user's ai_key is required. It also states that the AI key, writer, and default resume design are app-set and never appear as a next step, preventing a whole class of wasted calls.

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

Conciseness4/5

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

Front-loaded with the core purpose, then a single dense sentence enumerating returns with parenthetical explanations. Every clause carries information, but the nested parentheses and run-on structure make it harder 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.

Completeness5/5

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

There is no output schema, so the description must carry the full return contract, and it does: it names and explains ai_key, writer, demo_bases, next_step (with its {step, tool_set, says} shape and null case), tool_sets, and steps. It also explains the downstream 409 behavior an agent will hit, which is exactly the context needed for a zero-param orientation tool.

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

Parameters4/5

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

The tool takes zero parameters, so the baseline is 4. The description instead spends its space on return-value semantics (writer enum meanings, demo_bases being slugs of shipped demos, next_step being null when nothing remains), which is useful but does not add anything about parameters since there are none.

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

Purpose5/5

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

States a specific verb+resource ('where this user's Maestro setup stands') and adds the audience/trigger ('for an agent starting fresh'). The enumerated return fields (ai_key, writer, next_step, tool_sets, steps) make it clearly distinct from siblings like run_health_check or get_career_context.

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

Usage Guidelines4/5

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

The phrase 'for an agent starting fresh' plus the next_step field implicitly tells the caller this is the orientation call before doing setup work. It does not name an explicit alternative or exclusion, so it falls short of a 5, but the usage context is clear enough to route an agent correctly.

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

get_tailoring_optionsGet Tailoring OptionsA
Read-onlyIdempotent

The user's Quick tailor presets, as data an agent can explain or work around. Returns presets ([{key, on, means}]: each switch, whether it is on, and its plain meaning), instruction (an extra instruction the user gave for every tailor, may be empty) and persona (the user's own words on tone, may be empty). create_tailoring_session with use_presets follows these presets; a custom tailor walks the gaps with the user however the agent talks with them and saves the decisions with resolve_gaps. Either way the server keeps its rules: an unproven skill enters only a skills list, resume lines stay in the owner's implied first person, and saved keywords land. The presets are the user's, set in the app; no tool changes them.

NameRequiredDescriptionDefault

No parameters

TDQS

A4.1/5.0
Behavior4/5

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

Annotations already cover read-only/idempotent/non-destructive, and the description adds real context beyond that: fields may be empty, the presets are user-owned and immutable via tools, and the server enforces specific rules (unproven skills only in a skills list, resume lines in first person, saved keywords land). The rule list is partially about tailoring generally rather than this read call, so it's helpful context rather than precise return semantics.

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

Conciseness4/5

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

Front-loaded with what is returned and in what shape, which is the highest-value information. The trailing sentences about server rules and gap-walking drift into workflow guidance that is only loosely tied to a read-only getter, adding length without tightening the tool's own contract.

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

Completeness5/5

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

No output schema exists, and the description compensates by enumerating the three returned fields and their sub-shape, noting emptiness is possible, and clarifying that the agent may explain or work around the presets. Combined with annotations covering the safety profile, an agent has what it needs 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.

Parameters4/5

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

Zero parameters, so the baseline is 4; nothing to document. The description productively spends its space describing the returned structure (presets array with key/on/means, instruction, persona) instead of parameters, which is the useful detail here given there is no output schema.

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

Purpose4/5

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

States a specific verb+resource: it returns the user's Quick tailor presets as structured data (switches, on/off, plain meaning), plus the per-tailor instruction and persona text. It distinguishes itself from set_persona and the create/resolve siblings by noting the presets are user-set in the app and no tool mutates them. Slightly muddied by extending 'options' to include persona/instruction, which overlaps conceptually with set_persona.

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

Usage Guidelines4/5

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

Clearly routes the agent: use create_tailoring_session with use_presets to follow these presets, or run a custom tailor that walks gaps and saves via resolve_gaps. It explains the downstream consumption rather than an explicit 'call this first when…' rule, but the alternatives and their conditions are named.

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

get_tailoring_sessionGet Tailoring SessionA
Read-onlyIdempotent

Fetch a tailoring session to resume a half-done gap walkthrough.

`tailoring_session_id` is the id returned by create_tailoring_session. Returns
the session with its frozen gap list (gaps_json), any resolutions saved so far
(resolutions_json), and status (open/tailored). resolutions_json may already
contain SYSTEM-PLANNED auto-resolutions stamped at creation (their payload
carries `provenance`, e.g. library_auto/kb_auto/kb_profile/wording_auto —
hand-made resolutions never do): verified evidence the resolver pre-applied.
To retract one, resend its gap_id with action "skip" via resolve_gaps.
Unresolved gaps are those in gaps_json with no entry in resolutions_json;
tailor_session consumes the saved resolutions. `base_anchors` are the base's
emphasis hints (countries, role, company, focus), not evidence; the anchor
company is the resume's own target, not necessarily this job's employer.
NameRequiredDescriptionDefault
tailoring_session_idYes

TDQS

A4.3/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint and destructiveHint, so safety is covered; the description adds real signal beyond them — the frozen gap list, that resolutions_json can carry pre-stamped SYSTEM-PLANNED auto-resolutions with provenance, and that tailor_session consumes the saved resolutions. It does not need auth/rate-limit detail for a safe read.

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

Conciseness4/5

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

Purpose is front-loaded and every sentence conveys domain-specific meaning, but the paragraph is dense with jargon and packs downstream usage (retraction, tailor_session consumption, base_anchors) into a single block that is harder 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.

Completeness4/5

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

With no output schema and no annotation detail on payloads, the description compensates by explaining the returned fields (gaps_json, resolutions_json, status) and the unresolved-gap definition. It is close to complete, missing only the exact status-transition or format conventions.

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

Parameters4/5

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

Schema description coverage is 0%, so the description must carry the load for the single parameter, and it does: tailoring_session_id is explicitly defined as the id returned by create_tailoring_session. It does not state the string format, but the origin/linkage is the practically important information.

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

Purpose5/5

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

States a specific verb (fetch) and resource (tailoring session) plus intent (resume a half-done gap walkthrough). It is clearly distinguishable from create_tailoring_session, list_tailoring_sessions and close_tailoring_session among siblings.

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

Usage Guidelines4/5

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

The 'to resume a half-done gap walkthrough' framing gives clear when-to-use context, and it names the producing tool (create_tailoring_session) and the consuming tool (tailor_session), plus resolve_gaps for retraction. It does not give explicit when-NOT-to-use or exclusion guidance.

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

get_templateGet Resume TemplateA
Read-onlyIdempotent

Get a template incl. its full source (Jinja2+LaTeX for engine='latex'; raw .typ text for engine='typst') plus engine, engine_available (see list_templates), and supported_fmt_keys. A template of either engine opts into look knobs by referencing fmt.* (LaTeX via the Jinja namespace, Typst via sys.inputs.fmt; defaults reproduce Classic): font_size (11), side_margins (0.4in), top_bottom_margin (0.3in), line_spacing (1.0), section_spacing (6pt), entry_spacing (0pt), justify (false), hide_divider (false), bullet_icon ("bullet"|"dash"), header_align ("center"|"left"|"right"), skills_layout ("inline"|"bulleted"), education_order ("degree_first"|"institution_first"), date_format ("verbatim"; feeds |format_date). For engine='typst', supported_fmt_keys always includes date_format (applied server-side) even if the source never names it.

NameRequiredDescriptionDefault
template_idYes

TDQS

A3.8/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, non-destructive, so the safety profile is covered, and the description adds real domain context: the returned source differs by engine (Jinja2+LaTeX vs raw .typ), how templates opt into fmt.* knobs, the defaults, and a typst-specific quirk where date_format is always supported server-side. This is meaningful behavior beyond the annotations, though it does not discuss failure modes.

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

Conciseness3/5

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

The purpose is front-loaded in the first clause, which is good, but the body then expands into a long enumeration of fmt.* knobs and defaults that is more relevant to rendering/tailoring than to merely fetching a template. The density is high and could be trimmed or moved, making it verbose for the stated action.

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

Completeness4/5

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

With no output schema, the description correctly takes on the burden of describing return values and does so thoroughly (source, engine, engine_available, supported_fmt_keys, and the fmt namespace semantics). It is close to complete, with only error/missing-template behavior left unspecified.

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

Parameters3/5

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

The single template_id parameter has 0% schema coverage, so the description carries the burden, but it never defines the id's format or where it comes from beyond an implicit nod via '(see list_templates)'. It does add substantial context about what a template object contains, which indirectly clarifies the resource, but the parameter itself is only weakly explained.

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

Purpose5/5

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

The description names a specific verb (get) and resource (template) and enumerates exactly what is returned: full source, engine, engine_available, and supported_fmt_keys. It also distinguishes itself from list_templates by referencing it, so an agent can tell the retrieval tool apart from the listing tool without opening schemas.

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

Usage Guidelines3/5

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

The only routing cue is the parenthetical '(see list_templates)', which implies that list_templates supplies the template_id this tool consumes. There is no explicit when-to-use/when-not statement, no prerequisite about needing a valid template_id, and no mention of error behavior for a missing template.

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

judge_health_bulletsJudge Resume BulletsA

Stores evaluations of a resume's pending bullets while Maestro's own model does not judge them (no model key is set, or the agent app writes), then rebuilds its health report. kind is 'base' or 'application', key the slug or application id. classifications is the classifications list in the output shape that judging.prompt from run_health_check states, one entry per pending id. Each entry gets the checks a model's answer gets: level is one of direct, analogue, adjacent, implied, unaddressed; analogue and direct need a verbatim quote of three or more words from the bullet in evidence, else the level is stored as adjacent; a measure question survives only when its target is in the bullet's own words. An id that is not pending (already judged, or its text changed) is rejected. Judgments are stored under this client's name and count while Maestro's own model does not judge. Returns the rebuilt report (fields as in run_health_check) plus accepted [{id, level as stored}] and rejected [{id, reason}]. 409 while Maestro's own model judges: a model key is set and Maestro's AI writes for agent apps.

NameRequiredDescriptionDefault
keyYes
kindYes
classificationsYes

TDQS

A4.9/5.0
Behavior5/5

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

Beyond the annotations (which only say non-read-only, non-destructive, non-idempotent), the description discloses the acceptance rules — analogue/direct require a verbatim ≥3-word quote or the level is downgraded to adjacent, measure questions survive only if the target is in the bullet's own words — plus rejection of non-pending ids, storage under the client's name, and the 409 conflict condition.

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

Conciseness4/5

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

Every sentence earns its place and the core effect leads, but the prose is packed into long run-on sentences (the opening sentence alone carries two clauses plus a parenthetical), which makes it denser to parse than necessary.

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

Completeness5/5

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

There is no output schema, yet the description explains the return value — the rebuilt report with the same fields as run_health_check plus accepted [{id, level as stored}] and rejected [{id, reason}] — and covers error behavior, so an agent has everything needed to call it and interpret the result.

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

Parameters5/5

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

Schema description coverage is 0%, so the description must carry the load, and it does: kind is 'base' or 'application', key is the slug or application id, and classifications is the list from run_health_check's judging.prompt output shape with one entry per pending id and enumerated level values (direct, analogue, adjacent, implied, unaddressed).

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

Purpose5/5

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

It states a specific verb and resource — stores evaluations of pending resume bullets, then rebuilds the health report — and situates it against the sibling run_health_check by naming the exact condition under which the judging is delegated to the client. An agent can distinguish it from run_health_check and get_health_report 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.

Usage Guidelines5/5

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

The when-to-use condition is explicit: it applies while Maestro's own model does not judge (no model key set, or the agent app writes), and the exclusion is spelled out too — a 409 fires while Maestro's own model judges. It also points the caller at judging.prompt from run_health_check as the source of the input shape.

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

kb_add_pointsAdd Career Points as DraftsA
Idempotent

Add bullets the caller wrote to an existing Career KB entity as DRAFT points, with no LLM call (kb_capture with entity_id, minus the model that splits and places free text). Drafts appear on no resume and in no career export until approved with kb_approve_points (or at /career). The text is stored as the user's own words and facts; the server does not verify it.

Store-time rules: en and em dashes become a hyphen in a range
("2020-2023") and a comma elsewhere, and one opening a bullet is dropped.
Resume text is implied first person:
a bullet where I, he or she opens a clause, his/her/my opens one or follows
its verb ("Grew his team"), or the owner's name appears returns 400 naming
the lines and stores nothing; they/their and pronouns about other people
are stored. A bullet already on the entity in any state
(case and spacing ignored), or repeated in the call, is skipped, so a
repeated call adds nothing; a rephrasing is added as a new draft
(kb_groom_entity reports similar bullets).

Returns {entity_id, entity_title, point_ids, skipped}: the new DRAFT point
ids and the skipped texts. An unknown entity_id is a 404; kb_list_entities
returns the ids, and kb_create_entity makes a new entity.
NameRequiredDescriptionDefault
pointsYes1-50 bullets for the one entity, each at most 1000 characters.
entity_idYes

TDQS

A4.5/5.0
Behavior4/5

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

Goes well beyond the annotations: drafts are invisible to resumes/exports until approved, text is unverified, there are dash-normalization rules, a 400 for first-person phrasing with nothing stored, dedupe skipping, and a 404 for unknown entities. These are consistent with readOnlyHint=false, destructiveHint=false and idempotentHint=true (repeat calls add nothing), though idempotency could have been tied explicitly to that annotation.

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

Conciseness3/5

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

Front-loaded and information-dense with no filler, but the store-time rules paragraph is long and reads like spec text rather than selection guidance. It is defensible because these rules change what a caller should send, yet the definition could be tightened.

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

Completeness5/5

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

With no output schema, the description fully documents the return payload ({entity_id, entity_title, point_ids, skipped}) and the error modes. For a two-parameter draft-creation tool, an agent has everything needed to call it and interpret the result.

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

Parameters4/5

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

Schema coverage is only 50% and entity_id has no schema description, but the text compensates by explaining that entity_id must be an existing entity (404 otherwise) and where to get ids. For points it adds content-level validation rules (dash handling, first-person rejection, dedupe) beyond the schema's 1-50/1000-char limits.

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

Purpose5/5

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

States a specific verb and resource (add bullets to an existing Career KB entity as DRAFT points) plus the key mechanism (stored as-is, no LLM splitting). It explicitly distinguishes itself from kb_capture by noting the missing model step, so an agent can tell the two apart without opening either schema.

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

Usage Guidelines5/5

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

Names the alternatives and the conditions that select them: kb_capture when free text needs splitting, kb_approve_points (or /career) to move drafts out of draft state, kb_list_entities to resolve ids, kb_create_entity for a new entity, kb_groom_entity for near-duplicates. Usage is fully routed rather than inferred.

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

kb_approve_pointsApprove Career PointsA
Idempotent

Batch-approve Career KB points. Approved points are the only ones that appear on composed resumes and the career export; this is the single approval path available over MCP, and kb_retire_points retires points. The approval written is the user's decision about the listed points; the server does not check that the user reviewed them (a convention, not enforcement).

1-500 ids; repeats collapse to one result row. Per-id results are honest: unknown ids
return ok=false detail="not found" and the rest still proceed; a failed id fails the
same way until corrected (kb_list_points returns the current ids).

Response is {results: [{id, ok, state, detail}], next}. next is a hint
(null when suppressed or unavailable).
NameRequiredDescriptionDefault
point_idsYes

TDQS

A4.6/5.0
Behavior5/5

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

Goes well beyond the annotations (which only say non-readonly, idempotent, non-destructive): it discloses that approval is a convention not server-enforced, that repeats collapse to one row, that partial failures are per-id with the rest proceeding, and that failed ids keep failing until corrected. It also explains the response envelope and the meaning of 'next'.

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

Conciseness4/5

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

Front-loaded with purpose and scope, then constraints, then response shape — logical ordering with no filler sentences. Slightly dense and the response-shape paragraph is verbose, but every segment carries information an agent needs.

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

Completeness5/5

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

With no output schema, the description supplies the return envelope ({results:[{id, ok, state, detail}], next}) and the semantics of 'next', plus error-path behavior. For a one-parameter batch mutation tool this leaves nothing material missing.

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

Parameters4/5

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

Schema description coverage is 0%, so the description carries the burden: it gives the 1-500 range for point_ids, the deduplication behavior, and what happens with unknown ids ('ok=false detail="not found"'). It does not say where ids come from in the schema itself, though it points at kb_list_points as the source, which largely compensates.

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

Purpose5/5

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

States a specific verb and resource ('Batch-approve Career KB points') and immediately explains the downstream effect: approved points are the only ones appearing on composed resumes and the career export. It also explicitly contrasts with kb_retire_points, so an agent can separate the two KB mutation tools without opening schemas.

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

Usage Guidelines4/5

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

Says this is 'the single approval path available over MCP' and names kb_retire_points as the alternative for retirement, plus points to kb_list_points as the way to obtain current ids. Clear usage context, but there is no explicit statement of prerequisites (e.g. that points must exist first, or what to do if the user has not reviewed them beyond the convention note).

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

kb_captureCapture Career NotesA

Capture free-text career news into DRAFT points. Maestro's AI matches it to an existing entity or proposes a new one, with the user's API key (with none set it returns an error); pass entity_id to force placement. Refused (409) when the user's writer setting (get_setup_status) says the agent app writes; kb_add_points stores bullets the caller already wrote, with no LLM call. Points land as drafts for the user to approve at /career. The text is stored as the user's own words and facts; the server does not verify it.

NameRequiredDescriptionDefault
textYes
entity_idNo

TDQS

A4.8/5.0
Behavior5/5

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

Beyond the annotations (readOnlyHint=false, openWorldHint=true), it discloses the API-key requirement and its failure mode, the 409 refusal condition tied to another tool, the fact an LLM call is made and may create a new entity, that output is unapproved drafts surfaced at /career, and that content is unverified user words. That is exactly the behavior an agent needs before invoking a mutating, non-idempotent tool.

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

Conciseness4/5

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

Front-loaded with the core action and state, then prerequisites and the alternative tool. Dense with parenthetical asides ("(with none set it returns an error)", "(get_setup_status)") that add value but make it slightly cluttered; still no wasted sentence.

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

Completeness5/5

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

For a 2-parameter mutating tool with no output schema, it covers auth, error/409 behavior, draft lifecycle, where approval happens, and the sibling alternative. Nothing an agent needs 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.

Parameters4/5

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

Schema coverage is 0%, so the description must carry parameter meaning: it explains entity_id's semantics (force placement rather than letting AI match) and characterizes text as free-text news stored verbatim as the user's own words. The text parameter's expected granularity (a news item vs. a full bio) is only loosely implied, keeping it short of a 5.

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

Purpose5/5

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

"Capture free-text career news into DRAFT points" is a specific verb plus resource plus state (draft), and the description explicitly contrasts it with kb_add_points (no LLM call) and kb_edit_point/kb_approve_points territory. An agent can distinguish it from the many sibling kb_* tools without opening any schema.

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

Usage Guidelines5/5

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

It gives when-to-use (free-text capture that needs AI entity matching), when-not (use kb_add_points for bullets the caller already wrote), a pre-condition (get_setup_status writer setting, else 409), and an override path (pass entity_id to force placement). No inference is required.

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

kb_combine_pointsCombine Career PointsA
Idempotent

Fold Career KB points into one: the keeper stays the bullet, and every point in point_ids (the others, not the keeper) is retired and recorded as one of the keeper's wordings. Resumes that use any of them keep their text; combining never edits a resume. Reversible from /career (Make its own bullet). The grouping written is the user's decision about the listed points; the server does not check that the user reviewed them (a convention, not enforcement, the same gate as kb_approve_points). Same entity required (400); a retired or user_cannot_confirm keeper, a user_cannot_confirm loser, and a loser the user stopped (retired but not folded) are refused (400), and so is a keeper that is itself folded into another; a loser already folded elsewhere moves to this keeper. Returns {keeper, repointed}: the keeper with its wordings, and any combined claims the fold moved from a loser onto it. 1-50 ids.

NameRequiredDescriptionDefault
keeper_idYes
point_idsYes

TDQS

A4.6/5.0
Behavior5/5

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

Beyond the annotations it discloses the key side effect (losers retired and folded as wordings), that resumes are never edited, full reversibility, the convention-not-enforcement gate, the 400 refusal cases (cross-entity, retired/cannot-confirm keeper, user-stopped loser, already-folded keeper), the loser-moves-to-keeper rule, and the return shape. This is consistent with destructiveHint=false and idempotentHint=true.

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

Conciseness4/5

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

Purpose is front-loaded in sentence one, then behavior, reversibility, and error cases follow. The long error sentence packs several conditions together and is the densest part, but nothing is wasted.

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

Completeness5/5

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

No output schema exists, yet the description documents the return value ({keeper, repointed}), reversibility, limits, and failure modes. For a 2-param destructive-adjacent merge tool, an agent has everything needed to call it correctly and interpret the result.

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

Parameters4/5

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

With 0% schema coverage the description carries the burden: it defines keeper_id as the surviving bullet and point_ids as 'the others, not the keeper', and adds the 1-50 constraint. It could go further on ID format, but it meaningfully compensates for the empty schema.

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

Purpose5/5

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

The first sentence gives a precise verb and resource: fold Career KB points into a keeper, retire the rest as wordings. It explicitly delineates the keeper vs. point_ids roles and sets it apart from kb_retire_points and kb_merge_entities by the 'same entity required' scope.

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

Usage Guidelines4/5

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

It states the reversibility path ('/career → Make its own bullet') and frames the grouping as the user's decision with a convention gate matching kb_approve_points, giving clear context on when/how it applies. It stops short of naming a concrete alternative sibling for a different case (e.g. kb_merge_entities), so it's 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.

kb_create_entityCreate Career EntityA

Create a Career KB entity — kind is experience|project|education| certification|extra. Writes immediately and is not draft-gated: the entity, with the dates and wording supplied, is stored as the user's own career record, and no duplicate is blocked (possible_duplicates hints are returned). detail is a free-form dict (conventional keys: tech list[str]|str, link, field); kind="extra" REQUIRES section_key (lowercase slug), section_type ("entries"|"bullets"), and section_title nested inside detail — no top-level params exist. A certificate PDF still has to be uploaded from the web UI.

NameRequiredDescriptionDefault
orgNo
kindYes
notesNo
titleYes
detailNo
statusNo
end_dateNo
start_dateNo

TDQS

A4.1/5.0
Behavior5/5

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

Goes well beyond the annotations: it discloses that the write is immediate with no draft gate, that no duplicate is blocked and possible_duplicates hints come back, and that a certificate PDF cannot be created here and must be uploaded via the web UI. These are non-obvious behavioral traits that annotations (readOnlyHint=false, idempotentHint=false) alone would not convey.

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

Conciseness4/5

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

Front-loaded with the verb+resource and the kind enum, then progressively adds constraints. Dense but each clause adds a real constraint; a small amount of parenthetical nesting makes it slightly harder 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.

Completeness4/5

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

For an 8-param mutation with no output schema and 0% schema coverage, the description covers the highest-risk pieces (immediate persistence, no dedupe, kind='extra' nesting, upload limitation). The undocumented side of the parameters (status, notes, date formats) is the remaining gap.

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

Parameters3/5

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

Schema description coverage is 0%, so the description carries the burden. It does define kind's value set, the free-form detail dict conventions (tech/link/field), and the nested section_key/section_type/section_title requirement for kind='extra', but org, notes, status, start_date and end_date receive no semantic treatment at all.

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

Purpose5/5

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

States a specific verb (Create) and resource (Career KB entity) and enumerates the concrete kinds it accepts (experience|project|education|certification|extra). An agent can distinguish this from kb_edit_entity and kb_capture without opening either schema.

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

Usage Guidelines3/5

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

Usage is only implied: 'writes immediately and is not draft-gated' contrasts indirectly with the draft/approval flow behind kb_capture and kb_approve_points, but no alternative is named and no explicit when-to-use condition is given. Adequate but leaves the agent to infer the routing against siblings.

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

kb_edit_entityEdit Career EntityA
DestructiveIdempotent

Fix an entity's dates, title, org, notes or lifecycle status (ongoing|completed|archived). Omitted fields are left alone. Writes immediately with no draft gate; each supplied value replaces the stored one. Kind cannot be changed here — that is a rebuild, not a correction.

NameRequiredDescriptionDefault
orgNo
notesNo
titleNo
detailNo
statusNo
end_dateNo
entity_idYes
start_dateNo

TDQS

A4.4/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true, idempotentHint=true, readOnlyHint=false. Beyond that the description adds real behavior: 'Omitted fields are left alone' (partial-update merging), 'writes immediately with no draft gate' (no approval step, no undo window), and 'each supplied value replaces the stored one' (overwrite, not append). That is genuine added context over the annotations.

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

Conciseness5/5

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

Four short sentences, front-loaded with what the tool does, then partial-update semantics, then the immediate-write caveat, then the immutable-field limitation. No filler and nothing buried.

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

Completeness4/5

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

For a mutation tool with no output schema, the description covers the important gaps: partial update behavior, no draft gate, destructive overwrite, and the kind immutability boundary. Missing only return-value expectations, error behavior on a bad entity_id, and the 'detail' parameter's meaning.

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

Parameters4/5

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

With 0% schema description coverage the description must carry the load, and it does for most fields: it maps dates, title, org, notes, and status, and supplies the status enum (ongoing|completed|archived) that the schema itself omits. It leaves the 'detail' object parameter and the date string format unaddressed, so it is strong but not complete.

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

Purpose5/5

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

States a specific verb (Fix/Edit) and resource (entity), then enumerates the editable field set (dates, title, org, notes, lifecycle status). The 'Kind cannot be changed here — that is a rebuild, not a correction' clause separates it cleanly from the create/rebuild path without the agent 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.

Usage Guidelines4/5

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

Gives an explicit exclusion (kind changes belong elsewhere) and frames this as a correction rather than a rebuild, which routes the agent productively. It stops short of naming the alternative tool for rebuilds, so it lands below the explicit when/when-not/alternative bar of 5.

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

kb_edit_pointEdit Career PointA
DestructiveIdempotent

Reword a Career KB point or retag it. Changing the text sends the point back to DRAFT, so it leaves the composed resume and career export until it is re-approved (kb_approve_points or /career). Cannot approve, retire or delete a point. New text gets the kb_add_points rules: en and em dashes become a hyphen or a comma, and a third-person line is a 400 naming it.

NameRequiredDescriptionDefault
tagsNo
textNo
point_idYes

TDQS

A4.5/5.0
Behavior5/5

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

Adds substantial context beyond the annotations: text changes revert the point to DRAFT and drop it from the composed resume and career export until re-approved, which explains the destructiveHint. It also discloses the input-normalization rules (dashes converted, third-person lines rejected with a 400) that no structured field carries.

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

Conciseness4/5

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

Front-loaded with the action, then consequences, then exclusions, then normalization rules — a sensible ordering. It is dense and the final sentence is slightly overloaded, but every clause adds operative information.

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

Completeness4/5

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

No output schema exists, and the description covers the mutation's side effects and failure mode (400) but not what a successful call returns. For a 3-parameter destructive edit, the safety and lifecycle story is otherwise complete.

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

Parameters4/5

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

Schema coverage is 0%, so the description must compensate, and it does: 'text' carries the dash-normalization and third-person-400 rules, and 'retag it' clarifies that tags are a replaceable set. point_id is left implicit, but it is self-evident as the required key.

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

Purpose5/5

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

States a specific verb and resource: 'Reword a Career KB point or retag it', naming both editable fields. It is clearly separable from siblings like kb_add_points, kb_combine_points, and kb_retire_points.

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

Usage Guidelines4/5

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

Explicit exclusion — 'Cannot approve, retire or delete a point' — routes agents to kb_approve_points for re-approval, which is the key follow-up. It doesn't discuss when to prefer this over kb_combine_points or kb_groom_entity when restructuring content, so not quite 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.

kb_edit_profileEdit Career ProfileA
DestructiveIdempotent

Update the Career KB profile: contact block, career summary, skill groups, notes. Omitted fields are left alone; a supplied field REPLACES its stored value wholesale (current values are in get_career_context), so changing one list item means sending the full merged field. Writes immediately with no draft gate.

NameRequiredDescriptionDefault
notesNo
skillsNo
contactNo
summaryNo

TDQS

A4.1/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true and readOnlyHint=false, and the description adds real context beyond them: 'Writes immediately with no draft gate' and the wholesale-replacement semantics that justify the idempotent hint. It does not cover failure modes or validation behavior.

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

Conciseness5/5

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

Three tight sentences, front-loaded with the target and affected fields, then the critical merge semantics, then the side-effect warning. No filler.

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

Completeness4/5

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

No output schema exists, so the description carries the behavioral load, and it does so well for a zero-required-parameter mutation tool: it covers scope, merge behavior, read-before-write routing, and immediacy. Minor gaps remain around input shape hints and error handling.

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

Parameters4/5

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

Schema description coverage is 0% and all four parameters are undocumented nullables, so the description carries the burden. It compensates by mapping its four named fields to the four parameters and clarifying the replace-not-merge semantics, though it says nothing about the expected shape of the contact object or skills array.

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

Purpose4/5

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

States a specific verb ('Update') and resource ('Career KB profile') and enumerates exactly which fields it touches (contact block, summary, skill groups, notes). It is distinguishable from nearby siblings like kb_edit_point and kb_edit_entity by scope, though it never explicitly contrasts itself with them.

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

Usage Guidelines4/5

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

Gives concrete guidance on how to use it correctly: omitted fields are untouched, supplied fields are replaced wholesale, and current values live in get_career_context (a named sibling to consult first). It lacks an explicit 'use X instead when...' exclusion relative to the point/entity editors.

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

kb_get_entityGet Career EntityA
Read-onlyIdempotent

Full detail for one Career KB entity: dates, notes, its points (each with id, text and state), attached documents, and the activity timeline; also used_in_bases, the base resumes it is on (archived included, deleted excluded).

NameRequiredDescriptionDefault
entity_idYes

TDQS

A4/5.0
Behavior4/5

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

Annotations already declare read-only, idempotent, non-destructive, closed-world behavior, so the safety profile is covered. The description adds genuine value beyond that by enumerating what is returned (dates, notes, points with id/text/state, documents, activity timeline) and by disclosing the filtering nuance 'archived included, deleted excluded' for used_in_bases.

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

Conciseness5/5

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

One sentence, front-loaded with the core purpose ('Full detail for one Career KB entity'), followed by the return contents. No filler, no repetition of the title.

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

Completeness4/5

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

With no output schema, the description usefully enumerates the return payload and its filtering rules, which is exactly what an agent needs for a read-only single-entity fetch. The only gap is the unstated provenance/format of entity_id.

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

Parameters3/5

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

Schema description coverage is 0% and there is a single required entity_id, so the description must compensate. It implies the parameter selects 'one Career KB entity' but gives no format, source, or lookup guidance for the id. Baseline adequacy, no added semantics.

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

Purpose5/5

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

States a specific verb and resource ('Full detail for one Career KB entity') and the singular scoping implicitly separates it from list siblings like kb_list_entities. An agent can tell it is a detail-fetch for a single entity without opening the schema.

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

Usage Guidelines3/5

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

Usage is only implied by 'for one Career KB entity' – it presupposes a known entity_id but never states where that id comes from (e.g., kb_list_entities) or when to prefer this over kb_list_points or kb_edit_entity. No explicit exclusions or prerequisites are given.

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

kb_groom_entityFind Similar Career PointsA
Read-onlyIdempotent

Similar bullets on one Career KB entity, clustered, with a proposed keeper. Deterministic and zero LLM calls: the pinned local embedder scores every pair of the entity's active points (drafts included, retired and user_cannot_confirm excluded) and joins pairs at 0.80 cosine and above, minus pairs the user marked "Not the same" at /career. Proposes only; nothing is written. Each cluster carries score, keeper_id, members [{id, text, state, origin, provenance, usage_count, best_score}] and pairs. The keeper rule is approved over draft, then most recently updated, then longest text. compared_wording is false when the embedder could not run; clusters is then empty. Acting on a cluster is kb_combine_points (one claim in other words: the others become the keeper's wordings) or kb_retire_points (a similar but stale one).

NameRequiredDescriptionDefault
entity_idYes

TDQS

A4.5/5.0
Behavior5/5

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

Goes well beyond the readOnly/idempotent annotations: deterministic zero-LLM scoring, the 0.80 cosine threshold, exclusion of retired and user_cannot_confirm points, subtraction of user-marked 'Not the same' pairs, and the keeper precedence rule (approved > most recent > longest). It also discloses the degraded path (compared_wording=false, empty clusters) when the embedder cannot run — an important failure mode not visible in annotations.

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

Conciseness4/5

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

The core action, determinism, and propose-only nature are front-loaded, then the return shape and keeper rule follow. It is dense and leans on payload-field enumeration ('{id, text, state, origin, provenance, usage_count, best_score}') that adds bulk, but nearly every sentence carries operational information.

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

Completeness4/5

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

With no output schema, the description fully documents the cluster return shape, keeper rule, and degraded behavior — an agent can interpret results correctly. The only real gap is how to source entity_id, which is left implicit.

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

Parameters3/5

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

There is one required parameter with 0% schema description coverage, so the description must carry it. It repeatedly frames the scope as 'the entity's active points', which lets an agent infer entity_id identifies the target entity, but it never states the identifier's form or how to obtain it (e.g., via kb_list_entities).

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

Purpose5/5

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

States a specific verb and resource ('Similar bullets on one Career KB entity, clustered, with a proposed keeper') and immediately names the downstream siblings it feeds into. An agent can distinguish it from kb_combine_points, kb_retire_points, and kb_list_points without opening any schema.

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

Usage Guidelines5/5

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

Explicitly frames the tool as propose-only ('nothing is written') and routes the agent onward: kb_combine_points for one claim in other words, kb_retire_points for a similar but stale point. This is a clear when-to-use / what-to-do-next mapping against the alternatives.

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

kb_ingest_resumeImport Parsed ResumeA
Idempotent

Persist one caller-parsed resume into the Career KB. No in-house LLM.

Points land as DRAFTS and appear on no resume until approved with
kb_approve_points (or at /career), which records the user's approval.

HONESTY: `data` is stored as the user's own resume content, so a faithful
transcription is expected. The server does not detect embellishment,
rewording or invented metrics (same trust model as caller-authored tailor
ops); approved points become part of the career record.

ENTITY NAMES: matching is two-pass. Exact identity-key first (experience:
company+role+start_date; projects: name; education: institution+degree;
certs: the string), then a near-identity pass for experience/projects/certs
(token-subset; projects allow ≤2 extra tokens). Education and extra are
identity-key-only. Different spellings can merge on the second pass;
names outside its coverage still fork.

Re-running the same resume_key is a merge: no duplicate entities; a bullet
already on the entity (even retired) is not re-created. resume_key must
match ^[a-z0-9][a-z0-9_]*$.

`data` is ResumeData (only contact.name and contact.email required).
Sections: contact, summary, skills[{category, items}], experience, projects,
education, certifications[str], extra_sections. Experience:
{company, role, location?, start_date?, end_date?, bullets[str]}.
extra_sections are NOT stored in the KB (report warns); they can be added to
a base resume after it exists. skills/contact/summary go to the KB profile
(no draft state). Profile seeding is first-write-wins, so the first resume
ingested determines the profile.

Response {report, next}. report: created/matched entity ids, DRAFT point
ids, counts, warnings. next is a hint (null when suppressed/unavailable); brief=True
(multi-resume loops) suppresses it before any settings read. 422 on a
ResumeData validation failure or duplicate source key (atomic).
NameRequiredDescriptionDefault
dataYesResumeData. Only contact.name and contact.email are required. 422 if any source fails validation or on a duplicate SOURCE key (re-running the same resume_key is a merge, not an error); atomic either way: nothing persisted on a 422.
briefNo
resume_keyYes

TDQS

A4.7/5.0
Behavior5/5

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

Goes far beyond the annotations: it discloses draft state, first-write-wins profile seeding, merge-not-duplicate behavior on identical resume_key (matching idempotentHint), atomic 422 semantics, two-pass entity-name matching that can merge differently-spelled names, and that extra_sections are not persisted. This is exactly the behavioral context an agent needs before a mutating call.

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

Conciseness4/5

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

Front-loaded purpose followed by labeled blocks (HONESTY, ENTITY NAMES) makes the density navigable, and each section adds decision-relevant information. The entity-name matching paragraph is long and borders on internal mechanics, which slightly blunts conciseness, but little is pure filler.

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

Completeness5/5

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

With no output schema, the description still specifies the return shape {report, next}, what report contains, when next is null, and the 422 failure conditions. Between this, the nested ResumeData breakdown, and the annotation-delimited safety profile, nothing needed to invoke it correctly is missing.

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

Parameters5/5

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

With only 33% schema coverage, the description carries the load: it gives the resume_key regex ^[a-z0-9][a-z0-9_]*$, spells out the ResumeData shape and section list, notes only contact.name/email are required, and defines brief=True as suppressing the next hint in multi-resume loops. This meaningfully exceeds the bare schema.

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

Purpose5/5

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

States a specific verb and resource – 'Persist one caller-parsed resume into the Career KB' – and immediately disambiguates scope with 'No in-house LLM', signalling the caller owns parsing. Combined with the draft/approval lifecycle, an agent can tell this apart from kb_capture or kb_create_entity 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.

Usage Guidelines4/5

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

Gives clear lifecycle context: points land as DRAFTS and must be approved via kb_approve_points (or /career), and describes the re-run merge case. It stops short of naming when to prefer this over sibling capture tools like kb_capture, so it is clear but lacks explicit exclusions.

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

kb_list_entitiesList Career EntitiesA
Read-onlyIdempotent

List Career KB entities with their IDs (get_career_context returns prose with no IDs; this tool returns the IDs needed to edit). Optionally filter by kind (experience|project|education|certification|extra) or status (ongoing|completed|archived). Each item carries point_count, draft_count and approved_count (the bullets a resume can use; retired ones are in point_count only, except a bullet combined into another, which is counted nowhere) and used_in_bases, the base resumes it is on (archived included, deleted excluded).

NameRequiredDescriptionDefault
kindNo
statusNo

TDQS

A4.7/5.0
Behavior5/5

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

The annotations already declare readOnlyHint/idempotentHint/openWorldHint=false, and the description goes well beyond them: it explains exactly how point_count, draft_count and approved_count relate to each other, including the edge case of retired bullets and bullets combined into another being counted nowhere. It also spells out the inclusion rule for used_in_bases (archived included, deleted excluded), which is non-obvious behavior an agent could not infer.

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

Conciseness4/5

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

Purpose and the sibling distinction are front-loaded, and every sentence carries information. The dense parenthetical about bullet counting is justified but somewhat hard to parse in a single pass, which keeps it just short of a 5.

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

Completeness5/5

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

There is no output schema, so the description must describe the return shape — and it does, naming the per-item fields (point_count, draft_count, approved_count, used_in_bases) and their inclusion semantics. With only two optional filters, nothing an agent needs in order 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.

Parameters5/5

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

Schema description coverage is 0% and the schema declares both filters as unconstrained strings, so the description carries the full burden — and it does, enumerating the valid kind values (experience|project|education|certification|extra) and status values (ongoing|completed|archived). Without this text an agent would have no way to know legal filter values.

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

Purpose5/5

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

The description states a specific verb+resource ('List Career KB entities with their IDs') and immediately distinguishes the tool from its closest sibling, get_career_context, by explaining that the latter returns prose without IDs. An agent can tell exactly what it gets here without opening the schema.

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

Usage Guidelines4/5

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

It names an explicit alternative (get_career_context) and the condition that selects this tool instead ('IDs needed to edit'), which covers the main routing decision. It does not, however, position itself against other KB listing tools such as kb_list_points or kb_get_entity, so the guidance is clear but not exhaustive.

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

kb_list_pointsList Career PointsA
Read-onlyIdempotent

List Career KB points across all entities, optionally by state (draft|approved|retired), oldest first. An unfiltered call returns the first limit points (default 50, max 100); offset pages on. Each row carries id, entity_id/entity_title/entity_kind, text, state, origin, tags and dates; the per-use port history and merge provenance are omitted (kb_get_entity).

NameRequiredDescriptionDefault
limitNo
stateNo
offsetNo

TDQS

A4.3/5.0
Behavior4/5

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). The description adds real behavioral value on top: default and max page size, offset-based paging, sort order, and which fields are deliberately omitted from each row. It does not mention row-count/total behavior, so it is strong but not exhaustive.

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

Conciseness4/5

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

Three front-loaded sentences with no filler; the core action and default paging come first, and the sibling pointer closes it out. Some clauses are densely packed (field list plus omitted-field parenthetical), which costs a little readability.

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

Completeness4/5

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

With no output schema, the description usefully enumerates the returned row fields and flags what is omitted, and it covers filtering, ordering and pagination. What is missing is minor: no statement of total result count or behavior when `offset` runs past the end.

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

Parameters4/5

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

Schema description coverage is 0%, so the description carries the load and does so well: it supplies the enum values for `state` (draft|approved|retired) that the schema lacks, plus `limit` default 50 / max 100 and the paging meaning of `offset`. The only gap is that the column list ('id, entity_id/...') is output-oriented rather than parameter detail.

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

Purpose5/5

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

States a specific verb and resource ('List Career KB points across all entities'), plus the ordering ('oldest first') and the optional filter axis. An agent can distinguish it from kb_list_entities and kb_get_entity without opening either schema.

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

Usage Guidelines4/5

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

Explains the unfiltered case (returns first `limit` points) and the paging mechanism (offset), and explicitly redirects to kb_get_entity for per-use port history and merge provenance. It gives clear context but does not state when this should be preferred over the other list-type siblings.

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

kb_merge_entitiesMerge Career ItemsA
DestructiveIdempotent

Fold one Career KB item into another of the same kind, the cure for a duplicate an import split off: merge_id goes, keep_id stays. Everything on merge_id moves to keep_id: its bullets in every state (approved, drafts, retired, and the wordings folded into a bullet), its evidence documents, and its record of which resumes its bullets were copied into.

keep_id keeps its own title, dates, status and notes. A field keep_id has blank (org,
start or end date, notes) is filled from merge_id, except the end date of an ongoing item,
and a detail key keep_id lacks is taken from merge_id. Lost: merge_id's title, its status,
its creation record, and each value of it where keep_id already holds a different one.
Bullets are not de-duplicated: one both items carried is there twice afterwards
(kb_combine_points folds them into one). Resumes are not edited. There is no unmerge.
The merge written is the user's decision about the two items; the server does not check
that the user agreed (a convention, not enforcement).

Refused: the same id twice, items of different kinds, `extra` items from different
sections, and an archived keep_id (400; an archived merge_id is fine), an unknown id
(404), and a merge of the same item running at once (409). Returns keep_id's detail,
kb_get_entity's shape.
NameRequiredDescriptionDefault
keep_idYes
merge_idYes

TDQS

A4.9/5.0
Behavior5/5

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

Annotations carry destructiveHint/idempotentHint, but the description goes well beyond them: it enumerates what migrates (bullets in all states, evidence documents, resume-copy records), what is destroyed (title, status, creation record, colliding values), and says outright 'There is no unmerge'. It also discloses failure conditions with status codes (400 archived keep_id, 404 unknown id, 409 concurrent merge), which the annotations do not cover.

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

Conciseness4/5

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

The critical fact ('merge_id goes, keep_id stays') and the duplicate-cure framing are front-loaded, and the paragraphs are logically ordered: effect, field-level rules, losses, refusal codes. It is dense rather than padded, though the run-on parentheticals (bullets in every state, end-date exception) make it longer and harder to scan than an ideal version.

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

Completeness5/5

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

For a destructive two-param merge with no output schema, everything an agent needs is present: direction of the fold, field-by-field conflict resolution, irreversible losses, error conditions, and the return value ('returns keep_id's detail, kb_get_entity's shape'). Nothing material is deferred to an unstated assumption.

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

Parameters5/5

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

Schema coverage is 0%, so the description must carry the param meaning and it does: keep_id is the survivor and keeps its title/dates/status/notes while absorbing blanks and missing detail keys, merge_id is consumed and its contents moved. The blank-filling rule and the ongoing-end-date exception give semantics far beyond two bare strings.

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

Purpose5/5

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

States a precise verb and resource ('Fold one Career KB item into another of the same kind') and immediately fixes the direction with 'merge_id goes, keep_id stays'. It also names the sibling that handles a different part of the problem (kb_combine_points) and the read sibling whose shape is returned (kb_get_entity), so no ambiguity remains.

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

Usage Guidelines5/5

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

The target scenario is explicit ('the cure for a duplicate an import split off'), the alternative is named for the adjacent job ('one both items carried is there twice afterwards (kb_combine_points folds them into one)'), and the exclusions are enumerated as a refusal list. It adds an operational instruction to the agent too: the merge is the user's decision and the server does not verify consent, so the agent must confirm before calling.

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

kb_retire_pointsRetire Career PointsA
Idempotent

Batch-retire Career KB points: they stop being offered to resumes and the career export; resumes that already use them keep their text. Reversible from /career (Use again). The state written is the user's decision about the listed points; the server does not check that the user reviewed them (a convention, not enforcement, the same gate as kb_approve_points).

1-500 ids; repeats collapse to one result row. Per-id results are honest:
unknown ids return ok=false detail="not found" and the rest still proceed.
Response is {results: [{id, ok, state, detail}], next}; next is a hint
(null when suppressed or unavailable).
NameRequiredDescriptionDefault
point_idsYes

TDQS

A4.6/5.0
Behavior5/5

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

Goes well beyond the annotations: discloses that existing resumes keep their text, that the action is reversible from a specific UI location, and that review is not server-enforced. Per-id outcome semantics (unknown ids return ok=false detail="not found" and the rest still proceed) are exactly the kind of behavior an agent needs before mutating state, and the idempotent hint is consistent with "repeats collapse to one result row."

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

Conciseness4/5

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

Front-loads the effect and reversibility, then moves to limits and response shape. Dense but every clause carries information; the nested parenthetical ("a convention, not enforcement, the same gate as kb_approve_points") is slightly awkward but earns its place.

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

Completeness5/5

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

A single-parameter mutation tool with no output schema, yet the description covers the state change, reversibility, batching limits, per-id error behavior, and the response envelope including the `next` field. 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.

Parameters4/5

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

Schema coverage is 0% for the single `point_ids` array, but the description compensates with cardinality bounds (1-500), de-duplication semantics, and per-id failure behavior. It stops short of describing the id format or where ids come from (presumably kb_list_points).

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

Purpose5/5

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

States a specific verb and resource ("Batch-retire Career KB points") plus the exact effect (no longer offered to resumes and the career export, while existing resume text is preserved). This clearly separates it from siblings like kb_list_points, kb_edit_point, and kb_approve_points.

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

Usage Guidelines4/5

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

The description gives clear operating context: reversibility via /career "Use again" and the fact that the server treats review as a convention rather than enforcement, mirroring kb_approve_points. It does not, however, explicitly say when to choose this over an alternative (e.g., deleting vs retiring a point).

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

kb_sync_baseSync Resume to Career KBA
Idempotent

Sync one base resume into the Career KB.

Deterministic: zero LLM calls. New material lands as DRAFT points
(origin=base_sync) for the user to approve at /career. A bullet that
rephrases an existing point on the same item (0.80 cosine and above) is
kept as that point's wording, not added as a second point; only a new
claim lands as a draft. Never edits resumes. Safe to rerun — a second
call is a no-op when already in sync. compared_wording is false when the
embedder could not run: a rephrased bullet was then added as new rather
than kept as a wording (exact text still matches).
NameRequiredDescriptionDefault
slugYes

TDQS

A3.8/5.0
Behavior5/5

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

Goes well beyond the annotations: zero LLM calls, new material lands as DRAFT points with origin=base_sync, the 0.80 cosine dedup rule that keeps existing wording rather than adding a duplicate point, the explicit 'never edits resumes' guarantee, rerun no-op semantics, and the compared_wording=false fallback when the embedder fails. These are exactly the side effects an agent needs before calling 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.

Conciseness4/5

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

Front-loaded with the one-line purpose, then the side-effect contract in descending order of importance. The final sentence about compared_wording is dense but conveys a real edge case; no sentence is filler.

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

Completeness5/5

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

There is no output schema, and the description compensates by describing what the call produces (draft points, wording merges, compared_wording flag) and what it does not do (edit resumes, duplicate on rerun). For a one-parameter, idempotent write tool this covers everything an agent needs beyond the slug ambiguity.

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

Parameters2/5

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

Schema coverage is 0% and the single parameter 'slug' is completely undocumented in the schema. The description only implies it names 'one base resume'; it never says whether the slug is a base-resume slug or a KB entity slug, nor what format it takes. With one required identifier and no other source of truth, this gap is significant.

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

Purpose4/5

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

States a specific verb and resource: sync one base resume into the Career KB. That is clearly distinct from edit_base_resume or kb_edit_point, but the description never distinguishes it from the similarly named siblings kb_ingest_resume, kb_capture, kb_add_points or sync_now, so the agent must infer which entry point produces draft points from a base resume.

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

Usage Guidelines3/5

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

Usage is only implied by the operation itself (syncing a base resume yields drafts the user approves at /career). There is no explicit statement of when to prefer this over kb_ingest_resume or sync_now, nor any exclusion or prerequisite. The 'safe to rerun' note helps operationally but is not routing guidance.

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

list_applicationsList ApplicationsA
Read-onlyIdempotent

List your applications as a thin paginated summary array. Filter by status/role_category; page with limit/offset. Rows name their base resume (base_resume_name) and the stored score (ats_score, null when unscored). Use get_application(id) for the full record and compare_ats for scores.

NameRequiredDescriptionDefault
limitNo
offsetNo
statusNo
role_categoryNo

TDQS

A4.6/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so safety is covered. The description adds useful behavior beyond that: the output is a thin summary (not full records), ats_score is null when unscored, and paging is limit/offset based.

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

Conciseness5/5

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

Three dense sentences, front-loaded with the core purpose and result shape, followed by filtering/paging and then routing. No filler; every clause adds information.

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

Completeness4/5

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

With no output schema, the description usefully names the returned fields (base_resume_name, ats_score) and their null semantics. It is largely complete for a list tool, though valid filter values and pagination limits remain unspecified.

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

Parameters4/5

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

Schema description coverage is 0%, so the description must carry the load, and it maps each parameter to a purpose: status/role_category for filtering and limit/offset for paging. It does not, however, give valid status values or bounds for limit/offset, leaving some ambiguity.

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

Purpose5/5

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

States a specific verb and resource ('List your applications') plus the shape of the result ('thin paginated summary array'). It clearly distinguishes itself from get_application(id), which returns the full record.

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

Usage Guidelines5/5

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

Explicitly routes the agent to alternatives: use get_application(id) for the full record and compare_ats for scores. This tells an agent exactly when this tool is the right choice versus its siblings.

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

list_base_resumesList Base ResumesA
Read-onlyIdempotent

List base resumes (slug, display name, summary). By default only the ones that can be picked; include_archived=true adds the archived ones, each with its archived_at date (archiving hides a resume from scoring and the pickers without deleting it).

NameRequiredDescriptionDefault
include_archivedNo

TDQS

A4.2/5.0
Behavior4/5

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

Annotations already declare readOnly=true, idempotent, non-destructive, so the safety profile is covered. The description adds genuinely useful domain context beyond that: archiving hides a resume from scoring and pickers without deleting it, and archived entries carry archived_at. It does not mention ordering or pagination of the list.

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

Conciseness4/5

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

Front-loaded with purpose and return fields, then the filtering behavior, then a tight parenthetical defining archiving. Every sentence earns its place; the nested explanation of archiving is slightly dense but still efficient.

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

Completeness4/5

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

No output schema exists, and the description compensates by naming the returned fields including archived_at. For a one-parameter read tool this is nearly complete; only list ordering/limits are unaddressed, which is minor.

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

Parameters5/5

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

Schema coverage is 0% and the single boolean has no description in the schema, so the description must carry it. It does so fully: explains the default (only pickable), exactly what include_archived=true adds, and the extra field those entries carry.

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

Purpose4/5

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

States a specific verb and resource (list base resumes) plus the return fields (slug, display name, summary), which makes it clearly distinct from get_base_resume or list_resume_versions. It never names a sibling explicitly, so an agent must infer alternatives from the names alone.

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

Usage Guidelines4/5

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

Gives concrete guidance for the single decision point: default returns only pickable resumes, include_archived=true adds archived ones. Clear usage context, but no explicit statement of when not to use it or which sibling to reach for instead (e.g. get_base_resume for detail).

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

list_jobsList Saved JobsA
Read-onlyIdempotent

List stored jobs as a thin summary array, newest first, paged by limit (default 50, max 500) and offset; a page shorter than limit is the last. Each item is a slim projection (company, title, role_category, level, employment_type, work_mode, location, salary, work_authorization, opt_accepted, best_ats_score: the best stored base-resume score, null when unscored) of roughly 0.8k characters, with no raw_text or extracted_json; use get_job for full detail. Optionally only jobs without an application. Each job carries ownership (owned_here, owner, handover, pending_requests), identifying replicas and jobs being handed over.

NameRequiredDescriptionDefault
limitNo
offsetNo
without_applicationNo

TDQS

A4.6/5.0
Behavior5/5

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

Adds substantial context beyond the readOnly/idempotent annotations: page-termination semantics ('a page shorter than limit is the last'), item size (~0.8k chars), excluded fields (no raw_text or extracted_json), null semantics for best_ats_score when unscored, and ownership/handover flags. This is exactly what an agent needs to interpret results.

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

Conciseness4/5

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

Front-loaded with the core action and paging rule, then projection contents, then the optional filter and ownership fields. Dense but every clause carries information; the parenthetical field list is long but justified by the absent output schema.

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

Completeness5/5

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

With no output schema, the description fully specifies the returned projection fields, null semantics, and page-boundary behavior, plus ownership metadata. An agent can consume and paginate results correctly without further documentation.

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

Parameters4/5

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

Schema description coverage is 0%, so the description carries the burden and does so well: it restates limit default/max, explains offset paging behavior, and gives meaning to without_application. It stops short of documenting edge cases like out-of-range offset, but coverage is strong for three params.

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

Purpose5/5

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

Specific verb+resource with scope modifiers: 'List stored jobs as a thin summary array, newest first, paged by limit and offset.' It also explicitly distinguishes itself from the sibling get_job ('use get_job for full detail') and implicitly from export_jobs/list_applications.

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

Usage Guidelines4/5

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

Clear routing context: use this for slim summaries and get_job when full detail is needed, plus the 'only jobs without an application' filter condition. No explicit exclusions (e.g., when to prefer export_jobs), 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.

list_proposalsList Application ProposalsA
Read-onlyIdempotent

List application proposals, newest first, as {items, total}. status is one status or a comma-separated set; limit (default 20, max 50) and offset page through total. A row is a couple of thousand characters (fit and job).

status 'accepted' means the user queued the proposal for an apply run (via
the /proposals page or record_triage); 'pending_review' proposals are awaiting
the user's triage. Batch apply runs work 'accepted' proposals by convention
(the agent-apply playbook); the server also permits preparation, evidence and
consent from 'pending_review'. Each item's proposed_by names who filed it: an
MCP client's name, "you" for the web app's queue, or null. Reading expires
overdue pending_review and needs_decision proposals (terminal 'expired').
NameRequiredDescriptionDefault
limitNo
offsetNo
statusNo

TDQS

A3.7/5.0
Behavior1/5

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

The annotations declare readOnlyHint=true and idempotentHint=true, but the description states 'Reading expires overdue pending_review and needs_decision proposals (terminal "expired")' — i.e., invoking this read mutates persisted state. That is a direct contradiction of the read-only/idempotent claims and would mislead an agent about whether repeated calls can change results.

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

Conciseness4/5

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

Front-loads the essential contract (what, ordering, return shape, paging) in the first two sentences, then adds status lifecycle detail. The second paragraph is dense and references internal playbook concepts, but nearly every sentence conveys distinct, non-redundant information.

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

Completeness4/5

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

With no output schema, the description supplies the return shape ({items, total}), row size, and the proposed_by provenance values, plus full status lifecycle semantics — enough to call it correctly. It omits item field details beyond proposed_by and any error/empty-result behavior, keeping it short of complete.

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

Parameters4/5

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

Schema coverage is 0%, so the description carries the burden and does so: status is 'one status or a comma-separated set' (the schema only says string|null), limit is default 20/max 50, and offset 'pages through total'. It adds real semantics beyond the schema, though it does not cover invalid status values or behavior past the end of the list.

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

Purpose5/5

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

Opens with a specific verb+resource ('List application proposals'), states ordering ('newest first') and the exact return envelope ({items, total}), which distinguishes it immediately from get_proposal, list_applications, and list_jobs. An agent can tell what this 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.

Usage Guidelines4/5

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

Gives strong operational context: 'accepted' means queued for an apply run, 'pending_review' is awaiting triage, batch apply runs work 'accepted' by convention, and record_triage is named as the accept path. It stops short of an explicit 'use this instead of get_proposal when you need one row' statement, so it is clear context rather than full alternative routing.

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

list_qa_entriesList Application AnswersB
Read-onlyIdempotent

List an application's screening answers and cover letters, newest first: the ones the app's model generated and the ones a caller stored.

NameRequiredDescriptionDefault
application_idYes

TDQS

B3.1/5.0
Behavior3/5

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

The annotations already establish that this is a safe, idempotent read operation. The description adds useful behavior beyond that by stating the results are newest first and include both model-generated and caller-stored entries, but it omits pagination, result size, and whether full text or metadata is returned.

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

Conciseness5/5

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

The description is a single front-loaded sentence with no wasted text. It states the action and key scope details immediately.

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

Completeness3/5

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

For a simple read-only list tool, the description covers the core contents and ordering. However, with no output schema and no parameter documentation, it leaves important gaps around return shape and application_id semantics.

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

Parameters2/5

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

Schema description coverage is 0%, so the schema does little beyond naming application_id as a string. The description only implies that the parameter identifies an application; it does not explain format, source, or any constraints.

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

Purpose4/5

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

The description gives a specific verb and resource: listing an application's screening answers and cover letters. It also clarifies scope by including both generated and caller-stored entries, though it does not explicitly distinguish this tool from nearby siblings like store_qa_answers or generate_cover_letter.

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

Usage Guidelines2/5

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

There is no explicit guidance on when to use this tool versus alternatives such as get_application, list_applications, or the generate/store QA and cover-letter tools. Usage is only implied by the word 'List'.

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

list_referralsList Referral ContactsA
Read-onlyIdempotent

List referral contacts (company, careers URL, contact name, notes, applications_count).

NameRequiredDescriptionDefault

No parameters

TDQS

A3.5/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false, and openWorldHint=false, so safety and mutability are fully covered without the description. The description adds the shape of returned data (company, careers URL, contact name, notes, applications_count), which is useful since there is no output schema, but it says nothing about scope, volume, or pagination.

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

Conciseness5/5

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

A single parenthetical sentence with zero filler; the resource is front-loaded and the returned fields are compactly listed. Every token earns its place.

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

Completeness4/5

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

For a zero-parameter read tool with full annotation coverage, the description is nearly complete, and the field enumeration substitutes for the missing output schema. It could still state whether all referrals are returned or whether ordering/pagination applies.

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

Parameters4/5

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

This tool takes zero parameters, so the baseline is 4. The description correctly implies no filtering input is accepted and instead documents the output fields, adding marginal value beyond the empty schema.

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

Purpose4/5

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

States a specific verb (List) and resource (referral contacts), and enumerates the returned fields, so an agent knows exactly what this retrieves. It is distinguishable from sibling list tools like list_jobs and list_applications even without explicit sibling routing.

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

Usage Guidelines2/5

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

The description gives no indication of when to use this over alternatives, no prerequisites, and no filtering or scoping context. It is a bare statement of what the tool returns with no usage guidance at all.

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

list_resume_versionsList Resume VersionsA
Read-onlyIdempotent

List append-only resume snapshots for one target, newest last.

kind is "base" (key = base-resume slug) or "application" (key = application
id). This is NOT render_pdf's target_type vocabulary — there is no
"base_resume" kind here. Each row is a version summary (number, label,
created_at); use get_resume_version for the snapshot and diff.
NameRequiredDescriptionDefault
keyYes
kindYes

TDQS

A4.5/5.0
Behavior4/5

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

Annotations cover the safety profile (readOnly, idempotent, non-destructive), so the bar is lower. The description still adds real behavioral context: the list is append-only, ordered 'newest last', and rows are version summaries with number/label/created_at fields.

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

Conciseness5/5

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

Front-loads the core action, then parameter semantics, then alternative routing. Three tight sentences with no filler; each sentence earns its place.

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

Completeness5/5

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

No output schema exists, yet the description describes the return rows (version summary: number, label, created_at), defines both required params, and points to the companion tool. An agent has everything needed to call it correctly.

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

Parameters4/5

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

Schema description coverage is 0%, so the description carries the burden, and it does so well: it defines kind ('base' vs 'application') and the meaning of key for each ('base-resume slug' vs 'application id'). It even pre-empts confusion with render_pdf's different vocabulary.

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

Purpose5/5

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

States a specific verb and resource ('List append-only resume snapshots for one target') plus scope ('newest last'). It explicitly distinguishes itself from siblings, clarifying it is NOT render_pdf's target_type vocabulary and routing detail retrieval to get_resume_version.

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

Usage Guidelines4/5

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

Names the alternative explicitly ('use get_resume_version for the snapshot and diff'), giving clear context for when to use this lister vs. the getter. It stops short of broader when-not guidance, but the routing is unambiguous.

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

list_tailoring_sessionsList Tailoring SessionsA
Read-onlyIdempotent

List all tailoring sessions for a job, newest first.

A lost session id can be rediscovered here (create_tailoring_session would
supersede the open one). Each item is a summary (id, job_id, base_resume,
status, application_id, timestamps, gap_count, resolution_count); the gap
list and saved resolutions are on get_tailoring_session. Status is one of:
open (in-progress gap walkthrough, resumable via get_tailoring_session),
tailored (finished — tailor_session already ran), superseded (a newer
session for the same job+base replaced it), or abandoned (explicitly closed
via close_tailoring_session without tailoring).
NameRequiredDescriptionDefault
job_idYes

TDQS

A4.6/5.0
Behavior5/5

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

Annotations already cover the safety profile (readOnlyHint, idempotentHint, destructiveHint=false, openWorldHint=false), and the description still adds substantial behavior: it documents the summary-level item shape and enumerates all four status values with their meanings and the action that produces each. This is exactly the kind of state semantics structured fields cannot express.

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

Conciseness4/5

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

Front-loaded with the one-line purpose, then layered detail on rediscovery and item shape. Dense but every clause carries information; the middle sentence is a long parenthetical that could be slightly tighter but is not wasted.

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

Completeness5/5

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

With no output schema, the description carries the burden of describing the return value, and it does so completely: item fields, what is excluded (gaps and resolutions), and full status enum semantics. An agent can use the result without calling another tool first.

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

Parameters3/5

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

Schema description coverage is 0% for the single job_id parameter. The description compensates only partially by scoping the tool to 'for a job,' implying job_id is the target job identifier, but it never states the expected format or whether the job must exist. Adequate for a self-evident single key, not more.

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

Purpose5/5

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

States a specific verb and resource ('List all tailoring sessions for a job') plus the ordering ('newest first'). It is cleanly separable from the adjacent siblings get_tailoring_session, create_tailoring_session, and close_tailoring_session, which are each named and assigned distinct roles.

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

Usage Guidelines5/5

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

Gives an explicit when-to-use trigger ('A lost session id can be rediscovered here') and routes the agent to alternatives: get_tailoring_session for gap lists and resolutions, create_tailoring_session to supersede an open session, close_tailoring_session for abandonment. The division of labor between listing, reading detail, and mutating is fully spelled out.

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

list_templatesList Resume TemplatesA
Read-onlyIdempotent

List resume templates — both engines (id, display_name, status['draft'|'ready'], engine, is_default, last_error). parse_certified false = a 'ready' template that still loses word boundaries under strict extraction — see validate_template. engine_available=false marks a LaTeX template on a backend with no TeX: still pickable, renders through Typst with a render_note.

NameRequiredDescriptionDefault

No parameters

TDQS

A3.8/5.0
Behavior4/5

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

Annotations already establish readOnly/idempotent/no-destructive, so the description's real value is explaining non-obvious domain flags: parse_certified=false meaning a 'ready' template still loses word boundaries, and engine_available=false meaning a LaTeX template on a TeX-less backend still renders via Typst with a render_note. That is meaningful behavioral context beyond the annotations, though it does not cover pagination or result size.

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

Conciseness4/5

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

Front-loaded with the core action and the returned field list, then two compact parenthetical clarifications for the ambiguous flags. Dense but every clause carries information; slightly over-packed but not padded.

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

Completeness4/5

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

With no output schema, the description must carry return-value meaning, and it does so for the fields an agent would act on (status enum values, is_default, last_error, parse_certified, engine_available). It omits ordering and any note that this is a full list with no filtering, which is a minor gap.

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

Parameters4/5

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

The tool takes zero parameters, so per the rubric the baseline is 4. The description instead spends its words on returned-field semantics, which is appropriate and adds value over the empty schema.

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

Purpose4/5

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

States a specific verb+resource ('List resume templates') and immediately scopes it ('both engines'), and enumerates the shape of what comes back (id, display_name, status, engine, is_default, last_error). It does not explicitly contrast with the sibling get_template, so sibling differentiation is only partial.

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

Usage Guidelines3/5

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

Usage is implied by the listing action, and it routes one narrow case to validate_template ('parse_certified false ... see validate_template'), but there is no explicit when-to-use vs get_template or when to prefer this over create/update_template_draft. Guidance exists but is incidental rather than directive.

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

mark_submittedMark Application SubmittedA
Destructive

Flip an approved proposal to submitted (terminal; links the application to applied). Requires submission_receipt evidence, or user_attested=True, which records the user's own statement that they submitted it (or that a submission_uncertain proposal went through, e.g. a confirmation email or portal check) as an attested consent event with their words in note. user_attested substitutes for receipt evidence and the server does not verify it; it is the user's attestation, not the caller's. In full automation mode, channel auto records the agent's own word that the application went through, with note naming what confirmed it (the confirmation page or a confirmation email); no receipt is needed, and it is accepted only while full automation is on.

NameRequiredDescriptionDefault
noteNo
channelNochat
proposal_idYes
user_attestedNo

TDQS

A4.5/5.0
Behavior5/5

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

Goes well beyond the annotations (destructiveHint=true, readOnlyHint=false, idempotentHint=false) by disclosing the terminal nature of the transition, the evidence requirement, that user_attested is the user's attestation rather than the caller's and is not server-verified, and that channel='auto' is accepted only while full automation is on. This is exactly the kind of auth/verification/mode behavior 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.

Conciseness4/5

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

Front-loads the core action and terminal scope before the evidence rules, and every sentence carries information. The middle passage on user_attested is dense and slightly repetitive ('the user's attestation, not the caller's'), but not wasteful.

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

Completeness4/5

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

For a no-output-schema mutation tool, the description covers the state change, evidence/attestation requirements, verification posture, and automation-mode gating. It does not spell out what the response returns or precisely how the application link is applied, a minor gap.

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

Parameters4/5

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

With 0% schema coverage the description must carry the load, and it does: it explains user_attested's meaning and substitution role, note's content ('their words' / 'naming what confirmed it'), and channel='auto' semantics. proposal_id is only implied as 'an approved proposal', leaving one small gap.

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

Purpose5/5

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

States a specific verb and resource ('flip an approved proposal to submitted'), plus the consequential scope detail that it is terminal and links the application to applied. An agent can distinguish this state-transition from siblings like propose_application, record_decision, or resume_proposal 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.

Usage Guidelines4/5

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

Clearly states the conditions under which the tool may be invoked: a submission_receipt must exist, or user_attested=True, or the auto channel while full automation is on. It does not name explicit alternatives (e.g., use record_decision to approve first), so it is strong context without full routing guidance.

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

prepare_application_pdf_uploadStage PDF for UploadA
Idempotent

Stage a disposable copy of an application's canonical rendered PDF for direct Playwright upload: its tailored resume by default, or its cover letter (document). If the PDF has not been rendered, render it and retry once. Writes atomically under $MAESTRO_CS_UPLOAD_DIR/<application_id>/, defaulting to the repository's .playwright-mcp/uploads directory (pair Playwright --output-dir with the parent .playwright-mcp tree). Returns upload_path, an absolute path usable directly by Playwright's file chooser. The staged copy is the only location intended for browser file uploads; the canonical server artifact (under applications/artifact_dir) is preserved and is not an upload source. Also returns filename/path integrity and PDF lint metadata. This preparation tool does not authorize or submit an application.

NameRequiredDescriptionDefault
documentNo"resume" (default): the tailored resume's PDF. "cover_letter": the PDF of the cover letter stored for the application (store_cover_letter or generate_cover_letter), rendered first when it has none, staged in the same folder under its own file name, so the two copies sit side by side. With no cover letter stored the call is refused and nothing is staged.resume
application_idYes

TDQS

A4.6/5.0
Behavior4/5

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

Annotations already declare non-readOnly, idempotent, non-destructive, so the safety profile is covered; the description adds genuinely new behavior — atomic writes, render-then-retry-once, refusal when no cover letter exists, and preservation of the canonical artifact. It stops short of describing failure modes beyond the retry or the size/shape of the lint metadata, so not a full 5.

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

Conciseness4/5

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

Front-loaded with the core action and its default, then the pathing caveat, the return value, and the non-authorization disclaimer in descending order of importance. The Playwright --output-dir parenthetical is dense but functional; a slightly tighter phrasing would reach 5.

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

Completeness5/5

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

With no output schema, the description carries the return contract itself (upload_path as an absolute Playwright-usable path, plus filename/path integrity and PDF lint metadata), and it covers the env-var default location. An agent has everything needed to invoke it and consume the result without guessing.

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

Parameters4/5

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

Schema coverage is only 50%, but the description compensates for the undocumented half by explaining the default document value, the cover-letter branch, and the side-by-side staging behavior. The required application_id is left unexplained, though its meaning is evident from the path template shown in the description.

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

Purpose5/5

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

The opening clause names a specific verb and resource — stage a disposable copy of an application's canonical rendered PDF — for a named consumer (Playwright file upload), and explicitly scopes the default (tailored resume) versus the alternative (cover letter). It is clearly distinguishable from sibling render_pdf/get_rendered_pdf, which produce or fetch the canonical artifact rather than an upload-ready staging copy.

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

Usage Guidelines5/5

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

States when to use it (browser file uploads), which of the two documents to request, and the environment/path pairing needed to make the result usable. It also draws an explicit boundary: the staged copy is the only upload source, the canonical artifact under applications/artifact_dir is not, and this tool does not authorize or submit — routing the agent away from mark_submitted.

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

propose_applicationPropose ApplicationA
Idempotent

File an agent-hunted application proposal for user review.

If an open proposal already exists for the job, returns that proposal (idempotent)
instead of 409. Pass application_id after tailoring to late-link when the open
proposal is still unlinked (409 if already linked to a different application).
Refused (409) when the company is blocklisted or when THIS posting was
previously declined (declines are posting-scoped and permanent; other roles
at the same company are unaffected).
plan may include "company_note" (1-2 sentences: what the company is/does,
direct employer vs staffing, any legitimacy doubt) — the proposals page
shows it as "About the company" for triage.
NameRequiredDescriptionDefault
fitNo
planNo
job_idYes
referral_idNo
application_idNo

TDQS

A4.4/5.0
Behavior5/5

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

Beyond the annotations (readOnlyHint=false, idempotentHint=true), the description explains what idempotency concretely means (returns existing proposal instead of 409), the late-link semantics, and two distinct 409 refusal paths including that declines are posting-scoped and permanent while other roles at the same company are unaffected. This is rich behavioral detail the 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.

Conciseness4/5

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

Purpose is front-loaded in the first sentence, followed by conditional edge cases in a logical order. It is dense but each sentence (idempotency, late-link, refusal, company_note) carries distinct information, with only minor compression possible.

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

Completeness4/5

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

Given a mutation tool with no output schema, the description covers idempotency, refusal conditions, and partial parameter intent adequately. It stops short of describing the returned proposal shape or the full fit/referral semantics, but the core invocation contract is complete.

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

Parameters2/5

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

Schema description coverage is 0% across 5 parameters, so the description carries the full burden, yet it only documents application_id (late-link use) and one aspect of plan (company_note). fit, referral_id, and the rest of plan's structure are entirely unexplained, leaving an agent to guess their format and effect.

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

Purpose5/5

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

States a specific verb+resource ('File an agent-hunted application proposal for user review') that is clearly distinct from siblings like tailor_session, tailor_application, and get_proposal. An agent can tell this creates a reviewable proposal rather than performing tailoring or reading an existing one.

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

Usage Guidelines5/5

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

Explicitly routes usage: idempotent return when an open proposal exists, pass application_id 'after tailoring to late-link' when the proposal is unlinked, and 409 refusal conditions (blocklisted company, previously declined posting). This is concrete when/when-not guidance rather than implied context.

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

record_decisionRecord Proposal DecisionA

Record user decision when proposal is in needs_decision state. Resolves back to pending_review. application_id may be omitted; the backend then links the job's application on fit.chosen_base when there is one, else the job's one application (409 only when the job has no application); an automatic link sets fit.chosen_base to the linked application's resume.

NameRequiredDescriptionDefault
fitYes
proposal_idYes
application_idNo

TDQS

A3.5/5.0
Behavior4/5

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

Annotations only declare the generic profile (readOnly=false, idempotent=false, destructive=false, openWorld=false). The description goes beyond them by disclosing the post-condition state transition to pending_review, the side effect of writing fit.chosen_base, and the precise 409 failure condition when the job has no application — all behavior an agent could not derive from 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.

Conciseness3/5

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

Purpose is correctly front-loaded in the first sentence. The second sentence, however, is a run-on with nested clauses and parentheticals about linkage and the 409 case, which is information-dense but harder to parse than it needs to be.

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

Completeness3/5

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

For a mutation tool with no output schema, no annotation detail, and 0% parameter description coverage, the description supplies the state machine and the application-linking/error behavior but omits any indication of what `fit` must contain. The agent still cannot construct a valid required payload from what is given.

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

Parameters2/5

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

Schema description coverage is 0% and the required `fit` object is an open-ended additionalProperties object with no semantics given anywhere, so the core payload remains opaque. The description does explain application_id thoroughly (omitted → link job's application on fit.chosen_base, else the job's single application), which is real added value, but covers only one of three parameters.

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

Purpose4/5

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

The description states a specific verb and resource (record user decision / proposal) and anchors it to a named state machine position ('needs_decision state') with its resulting state ('pending_review'). It is clearly a decision-recording mutation, distinguishable from read-only siblings like get_proposal, though it never names the closest alternatives (request_decision, resume_proposal) to draw the boundary explicitly.

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

Usage Guidelines4/5

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

It gives a concrete precondition for use: the proposal must be in the needs_decision state. That is real when-to-use guidance, but there are no exclusions or comparisons against request_decision/resume_proposal, so the agent must infer which sibling to call when the proposal is not in that state.

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

record_filled_answersRecord Filled AnswersA

Record what was filled into this job's application form, one call per form page: each field's question, answer and source. Per question the latest call wins; the job page's What was submitted tab shows the record. An EEO answer is kept only while the user's standing EEO consent is recorded, and no MCP read returns its value. Returns {id, application_id, flag_count, flags}: each flagged field by its index in fields, with guessed_screening (a screening question answered by inference or composed prose), ticked_everything (a multi-select with every one of 3+ options ticked), differs_from_profile or eeo_without_saved_answer, each with a one-line reason. Flags warn; nothing is blocked, and get_final_review lists the job's flags again. step names the page: pass its URL path (location.pathname), the Companion's own key, so an agent row and a Companion row for one page fold together; a page number is still accepted. application_id links the record now; without it the record links, for the application of base_resume (the base resume's slug), when that application is created, marked applied or submitted.

NameRequiredDescriptionDefault
stepNo
fieldsYesThe page's fields as filled: {question, source, answer?, section?, required?, options_count?, slot?, eeo?, edited_by_you?}. answer is a string, or for a multi-select the list of ticked options with options_count, the number offered. source: profile (the autofill profile) | resume (work history or skills) | custom (a saved answer) | written (prose composed for this form) | inferred (a choice no saved fact states) | you (typed or changed by the user) | upload (a file: slot resume or cover_letter, answer the file name). slot names the profile fact, such as preferences.willing_to_relocate. eeo marks a voluntary self-identification question.
job_idYes
base_resumeNo
application_idNo

TDQS

A4.7/5.0
Behavior5/5

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

Goes well beyond the annotations: discloses latest-call-wins overwrite semantics, that EEO answers persist only while standing consent is recorded and no MCP read returns their value, the exact return shape {id, application_id, flag_count, flags}, each flag type with meaning, and that flags warn rather than block. Annotations only cover write/safety hints, so this added context is substantive.

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

Conciseness4/5

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

Dense but mostly front-loaded, starting with the action and page granularity. The application_id/base_resume linking sentence is convoluted and hard to parse, costing some clarity, but nearly every sentence conveys non-obvious behavior.

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

Completeness5/5

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

With no output schema and low schema coverage, the description compensates fully: it documents return values, flag semantics, consent-gated EEO handling, overwrite behavior, and the keying strategy for pages and applications. Nothing an agent needs to call it correctly appears missing.

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

Parameters5/5

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

With only 20% schema coverage, the description carries the load and does: `step` is explained as the page URL path (location.pathname) so agent and Companion rows fold together, while page numbers are still accepted; `application_id` vs `base_resume` linking rules are spelled out; and the `fields` payload format, source enum, and eeo/slot semantics are detailed.

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

Purpose5/5

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

Opens with a specific verb+resource: recording what was filled into a job's application form, one call per page. It is unmistakably distinct from siblings like record_triage, record_decision, or edit_application, and it states the granularity (per form page) that governs invocation.

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

Usage Guidelines4/5

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

Gives clear operational context: call once per form page, per question the latest call wins, and points at the 'What was submitted' tab and get_final_review for verification. It does not name a competing tool or an explicit when-not-to-use condition, so it stops short of a 5.

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

record_runRecord Automation RunA

Stores one finished automation run. The Automations page lists the newest run of each automation under Recent runs (its counts, digest and job links) and each card shows when its automation last ran; the Agent inbox says so when the run proposed jobs. automation is the card id (mail-status, job-hunt, referral-pages, tailor-run, apply-session) or a custom automation's own name, 40 characters at most. outcome: ok, partial (some of the work failed) or failed (none of it was done). The newest 200 runs are kept. Returns the stored run.

NameRequiredDescriptionDefault
reportNo{counts?, digest?, job_ids?}. counts: whole numbers for found, proposed, skipped, tailored, updated and needs_you; other keys are refused. digest: the run's plain-text summary, kept to its first 2000 characters; it holds counts and title-and-company lines, not email text. job_ids: the jobs the run touched, the first 50 kept; unknown job ids are dropped.
outcomeYes
automationYes

TDQS

A4.3/5.0
Behavior4/5

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

Beyond the annotations (mutation, non-idempotent, non-destructive), the description discloses real side effects: the run appears under Recent runs, updates the card's last-ran timestamp, and can surface the proposed jobs in the Agent inbox. It also states the 200-row retention cap, which annotations do not convey. Non-destructiveHint plus silent eviction of older runs is a mild tension, but it is a documented cap rather than a contradiction.

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

Conciseness4/5

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

Front-loads the core action, then spends a long clause enumerating UI surfaces (Recent runs, card timestamps, Agent inbox) that is informative but slightly sprawling. Nothing is off-topic and every sentence earns its place, though the middle sentence could be tighter.

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

Completeness4/5

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

For a 3-param write tool with no output schema, it covers the essentials: what is stored, side effects, retention, and the return ("Returns the stored run"). The report-shape details live in the schema, so the description need not repeat them; only the retention boundary and idempotency of repeated identical runs go unaddressed.

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

Parameters4/5

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

Schema description coverage is only 33%, and the description fills the biggest hole by naming the valid card ids (mail-status, job-hunt, referral-pages, tailor-run, apply-session) and the 40-character custom-name rule for `automation`. It also expands the `outcome` enum into plain meanings (ok / partial = some work failed / failed = none done), which the bare enum does not.

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

Purpose5/5

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

Opens with a specific verb+resource: "Stores one finished automation run." It immediately distinguishes this from sibling recorders (record_triage, record_decision, report_failure) by tying it to automation runs and describing where the stored run surfaces. An agent can tell what it does without opening the schema.

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

Usage Guidelines4/5

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

The "finished automation run" scoping plus the list of valid automation card ids gives clear context for when to call it, and the 200-run retention implies it is an append-style ledger. It does not, however, name an alternative or state any exclusion, so it stops short of an explicit when/when-not rule.

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

record_triageRecord Triage DecisionA
Destructive

Record the user's TRIAGE decision over one or many proposals — accept queues them for the next apply run; decline drops those unique postings (posting-scoped, never the company). The decision is the user's own, stated directly or as a selection rule they gave. One append-only consent row is written per proposal and the result is a per-id ok/error report (a mixed batch partially succeeds). Accept is NOT submit consent: the per-application approval is recorded separately by record_consent.

NameRequiredDescriptionDefault
noteNo
actionYes
reasonNo
channelNomcp
proposal_idsYes

TDQS

A4.3/5.0
Behavior5/5

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

Annotations declare destructiveHint=true and idempotentHint=false, and the description goes well beyond them: an append-only consent row is written per proposal, the result is a per-id ok/error report, mixed batches partially succeed, and decline is posting-scoped rather than company-scoped. It tells the agent exactly what gets destroyed and the partial-success semantics 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.

Conciseness4/5

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

The content is dense but front-loaded, leading with the core action before the scoping and consent caveats. It reads as a long run-on paragraph, and a tighter split would aid scanning, but every clause carries real information.

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

Completeness4/5

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

For a destructive, non-idempotent mutation with no output schema, the description supplies the return shape (per-id ok/error report), the side effect (append-only consent rows), and the boundary against record_consent — exactly the details an agent needs. Only the optional note/reason/channel parameters are left unexplained.

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

Parameters3/5

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

Schema description coverage is 0%, so the description carries the load. It ably documents the action enum (accept vs decline) and implies proposal_ids via 'one or many proposals,' but note, reason, and channel receive no explanation at all, leaving three of five parameters undocumented in either place.

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

Purpose5/5

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

It states a specific verb (record) and resource (the user's triage decision over one or many proposals) and spells out the two actions' effects: accept queues for the next apply run, decline drops those unique postings. It explicitly distances itself from the sibling record_consent, so an agent can route correctly 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.

Usage Guidelines4/5

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

The description frames when to call it — the user's own decision, stated directly or as a selection rule — and clarifies that accept is NOT submit consent, pointing to record_consent for the separate approval step. It stops short of contrasting with record_decision/request_decision, so context is clear but alternatives aren't fully enumerated.

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

render_pdfRender Resume PDFA
Idempotent

Render a PDF. target_type is 'base_resume' (target_id=slug) or 'application' (target_id=application id). Optional template_id selects a template (either engine; must be 'ready'; omit for the default). Response reports resolved_template_id / resolved_engine (the template actually used); template_fallback=true only when an explicit template_id was passed and the resolved id differs — a substitution of the persisted choice is reported by render_note, never by the flag. render_note is non-null only when the backend has no TeX and a LaTeX template was rendered through a Typst template instead; it names both. Returns the render result incl. pdf_path (an application render also has copy_path: where the user finds the PDF in their resumes folder, null when off), plus a next key: for an 'application' render this is the terminal apply-readiness hint (autofill_ready, incomplete/blocking groups, a conditional browser-handoff offer); for a 'base_resume' render it is always null — a base-resume preview isn't part of the score->tailor->render arc, so there is nothing to offer.

Without keep, template_id is a one-off and the saved design is unchanged.
With keep=true the template_id and/or formatting are saved on the resume
first, its later renders use them, and the response adds kept
{template_id, formatting}: what the resume now keeps.
NameRequiredDescriptionDefault
keepNoTrue: before rendering, the template_id and/or formatting given are saved on this base resume or tailored resume, so its later renders use them, after an edit too; template_id must name a ready template. False (default): template_id is a one-off for this render, the saved design is unchanged, and formatting is refused.
target_idYes
formattingNoLook settings to keep (keep=true), one object of the template knobs: font_size (10|11|12), side_margins and top_bottom_margin (0.3-1.0 inches), line_spacing (0.9-1.4), section_spacing (0-14 pt), entry_spacing (0-10 pt), justify and hide_divider (true|false), bullet_icon ("bullet"|"dash"), header_align ("left"|"center"|"right"), date_format ("verbatim"|"short_month"|"long_month"|"numeric"), education_order ("degree_first"|"institution_first"), skills_layout ("inline"|"bulleted"), section_order (a list of summary, experience, projects, extra_sections, skills, education, certifications; the rest follow in the template's order). It replaces the resume's saved look settings: a knob left out takes the template's default (on a tailored resume, its base resume's setting first), and {} clears them. An unknown knob or a value out of range is a 400 and nothing is kept. get_base_resume returns a base resume's saved formatting and template_id.
target_typeYes
template_idNo

TDQS

A4.6/5.0
Behavior5/5

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

Annotations declare non-readonly, non-destructive, idempotent, but the description adds substantial behavior beyond that: template_fallback only triggers on explicit template_id mismatch, render_note only on the Typst-substitution path, keep=true persists template/formatting, and the `next` key is null for base_resume renders. These are non-obvious side effects and flag semantics not derivable from annotations.

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

Conciseness4/5

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

Front-loads the render action and target_type semantics, then layers on fallback/keep details. It's dense and the `next`/render_note explanations run long, but nearly every clause carries decision-relevant information about flags the agent will encounter.

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

Completeness5/5

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

With no output schema, the description takes on return-value disclosure and does it thoroughly: resolved_template_id/resolved_engine, template_fallback, render_note, pdf_path, copy_path nullability, the `next` key's shape per target_type, and kept{template_id, formatting}. For a 5-param tool with a mutation mode, 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.

Parameters4/5

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

Schema coverage is only 40% — target_id, template_id, and target_type are undocumented in the schema — but the description compensates: target_id's meaning depends on target_type, template_id requires a ready template and defaults when omitted, and keep's persistence behavior is explained. Formatting knobs are already richly described in the schema, so the description doesn't need to repeat them.

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

Purpose5/5

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

States a specific verb+resource ('Render a PDF') and immediately disambiguates the two modes via target_type ('base_resume' (target_id=slug) or 'application' (target_id=application id)). An agent can tell exactly what this produces and how the two target kinds differ without opening the schema.

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

Usage Guidelines4/5

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

Explains the when-conditions well: template_id must be 'ready', omit for default, and keep=true vs default one-off are spelled out, plus the base_resume render is framed as a preview outside the score->tailor->render arc. It stops short of routing to siblings like get_rendered_pdf or get_rendered_pdf_page_image, so there is no explicit alternative-naming.

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

report_failureReport Application FailureA
Destructive

Report execution failure. From pending_review/accepted/approved, transitions to needs_human (resumable). reason='submission_uncertain' (for a submit click that could not be verified) moves the proposal to the terminal submission_uncertain status: resume_proposal is refused for it. The user's attestation, or the agent's (channel auto) in full automation mode, through mark_submitted moves it on.

NameRequiredDescriptionDefault
reasonYes
proposal_idYes

TDQS

A4.3/5.0
Behavior5/5

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

Annotations only declare the generic mutation profile (destructive, not read-only, not idempotent); the description goes well beyond by disclosing reversibility semantics — needs_human is resumable while submission_uncertain is terminal — and cross-tool effects (resume_proposal refused, mark_submitted advances it). This is exactly the behavioral context 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.

Conciseness4/5

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

Front-loaded with the core action and state transition, then the special-case reason, then the recovery path. Dense and mostly efficient, though the final sentence ('The user's attestation, or the agent's (channel auto) in full automation mode, through mark_submitted moves it on') is convoluted and requires re-reading.

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

Completeness4/5

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

For a mutation tool with no output schema, the description covers the critical states, transitions, and cross-tool interactions an agent needs. Minor gaps remain: behavior on invalid state transitions, and what non-'submission_uncertain' reason values do.

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

Parameters3/5

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

Schema coverage is 0%, so the description must carry parameter meaning. It adds real value for `reason` by defining the special value 'submission_uncertain' and its effect, but is silent on other accepted reason values and says nothing about `proposal_id` beyond the obvious. Partial compensation for a low-coverage schema.

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

Purpose5/5

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

States a specific verb and resource ('Report execution failure') and immediately defines the state machine it drives: from pending_review/accepted/approved to needs_human. This lets an agent distinguish it from siblings like resume_proposal and mark_submitted without opening the schema.

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

Usage Guidelines4/5

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

Gives clear preconditions (only valid from pending_review/accepted/approved) and explains the consequence of each path, including that resume_proposal is refused once the terminal submission_uncertain status is reached. It lacks an explicit 'use this instead of X when Y' framing against sibling tools, but the workflow context is strong enough to route correctly.

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

request_decisionRequest Proposal DecisionB
Idempotent

Escalate an unlinked/ambiguous proposal to needs_decision. Idempotent if already needs_decision.

NameRequiredDescriptionDefault
reasonYes
proposal_idYes

TDQS

B3.3/5.0
Behavior3/5

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

The idempotency claim duplicates idempotentHint=true from the annotations and earns no credit, but the description does add the target state (needs_decision) and the escalation semantics. It says nothing about side effects, notifications, or what the proposal looks like afterward, so it is only moderately transparent.

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

Conciseness5/5

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

Two short sentences, front-loaded with the action and target state, with zero filler. Every clause carries information.

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

Completeness3/5

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

The tool is low-complexity (two params, no output schema) and annotations already carry the safety and idempotency profile, so the description's coverage of the state transition is arguably sufficient. It still leaves both parameters undocumented, which is a real gap for a mutation tool.

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

Parameters2/5

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

Schema description coverage is 0% and both parameters are required with no schema-level documentation. The description never mentions proposal_id or reason, so it fails to compensate for the coverage gap; an agent gets no guidance on what a valid reason looks like or how the ID is scoped.

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

Purpose4/5

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

States a specific action (escalate) on a specific resource (proposal) and names the resulting state (needs_decision), which is more informative than the title. It doesn't explicitly distinguish itself from the closely related sibling record_decision, so it falls 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.

Usage Guidelines3/5

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

"Unlinked/ambiguous proposal" implies the trigger condition, giving implied usage guidance. However, it never names the alternative tools (record_decision, resume_proposal) or states when NOT to use this tool, leaving the routing decision partly to inference.

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

resolve_gapsSave Gap ResolutionsA
DestructiveIdempotent

Save gap resolutions on a tailoring session (merge by gap_id, idempotent). The batch is validated as ONE unit — one invalid item saves NOTHING (existing saved resolutions untouched).

`tailoring_session_id` is the id from create_tailoring_session. Each item
is {gap_id, action, payload}. Actions: add_keyword, user_input,
attach_project, skip, enable_entry, port_kb_point, cannot_confirm.
Payload shapes live on the `resolutions` parameter schema.

enable_entry and port_kb_point carry verified evidence and are exempt
from the add_keyword missing-skill rule (unverified additions stay in
skills). Re-sending a gap_id overwrites that gap; other saved resolutions
stay — including system-planned autos (payload.provenance; see
get_tailoring_session). May be called repeatedly; tailor_session consumes
the saved resolutions. Merge-only: omitting a gap_id never removes its saved resolution — resend
that gap_id with action "skip" to retract.

Response is the session plus a `next` hint (null when hints are off or unavailable).
NameRequiredDescriptionDefault
resolutionsYesBatch of {gap_id, action, payload}. Actions: add_keyword | user_input | attach_project | skip | enable_entry | port_kb_point | cannot_confirm. Validated as ONE unit — one invalid item saves NOTHING (existing saved resolutions untouched). Merge-by-gap_id; omit never deletes — resend skip to retract. Payloads: add_keyword needs placement_target {section, index_or_category} (+ optional wording); a MISSING skill may use add_keyword ONLY with section=skills. user_input {text}. attach_project {project_name}. enable_entry {section: experience|projects, index}. port_kb_point {kb_point_id, kb_entity_id, placement_target, wording}. skip/cannot_confirm {} (cannot_confirm also stores a durable user_cannot_confirm KB record; only legal on gaps that ask a question, i.e. where user_input is allowed).
tailoring_session_idYes

TDQS

A4.8/5.0
Behavior5/5

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

Goes well beyond the annotations (destructive=true, idempotent=true). It discloses the all-or-nothing batch validation ('one invalid item saves NOTHING'), the merge-only overwrite rule per gap_id, the exemption of enable_entry/port_kb_point from the add_keyword missing-skill rule, and that system-planned autos are preserved. Notably it reconciles the destructiveHint by clarifying that omission never deletes and retraction requires an explicit skip.

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

Conciseness4/5

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

Dense but well-organized, with the atomicity and merging rules front-loaded in the first three sentences before the finer action-level detail. A few clauses (payload provenance, evidence exemption) could be tightened, but nearly every sentence carries operational information the schema lacks.

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

Completeness5/5

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

With no output schema, the description still characterizes the response (session plus a 'next' hint, null when hints are off or unavailable). Given a two-parameter mutation tool with heavy schema detail and annotations present, the description supplies everything an agent needs to call it correctly.

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

Parameters4/5

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

The resolutions parameter is heavily documented inside the schema itself, and the description defers payload shapes there rather than duplicating them. Its added value is real: it explains tailoring_session_id's origin, the cross-item interaction rules, and the evidence exemption that the schema does not state, compensating for the 50% coverage gap.

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

Purpose5/5

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

States a specific verb+resource ('Save gap resolutions on a tailoring session') and immediately qualifies it with merge-by-gap_id and idempotent semantics. It is clearly distinct from its sibling tailor_session, which is named as the downstream consumer of what this tool saves.

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

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states prerequisites (tailoring_session_id comes from create_tailoring_session), that it may be called repeatedly, that tailor_session consumes the results, and how to retract a resolution (resend the gap_id with action 'skip'). It also names get_tailoring_session as the place to inspect provenance, giving the agent a clear alternative for the read side.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

restore_resume_versionRestore Resume VersionA
Destructive

Copy a past version's snapshot into the live resume.

Restore goes through the standard versioned write path — it is itself a
new version (history is append-only; nothing is deleted). kind/key as on
list_resume_versions: "base"+slug or "application"+id. For applications,
the old PDF is cleared; render_pdf produces a new one. A "base" restore
re-renders, so the response carries render_note (see render_pdf: non-null
only when a TeX-less backend rendered a LaTeX template through a Typst
one) and, if that render failed, render_error — the restore landed either
way, only the PDF is stale.
NameRequiredDescriptionDefault
keyYes
kindYes
numberYes

TDQS

A4.1/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only flag destructive/not-idempotent; the description goes far beyond them by disclosing that history is append-only and nothing is deleted, that restoring an application clears the old PDF, and that a base restore re-renders with render_note/render_error while the restore still lands. This is exactly the kind of operational context 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.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the purpose in the first sentence, then layers the mechanism and edge cases. Dense but nearly every sentence adds a distinct fact; the render_note aside is slightly parenthetical but still load-bearing.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description responsibly explains the return values (render_note, render_error) and the failure semantics. The only gap is the 'number' parameter, which is left for the agent to infer.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must carry the burden. It clarifies kind/key ('base'+slug or 'application'+id), which covers two of three parameters, but leaves 'number' (the version to restore) unexplained beyond the vague 'past version's snapshot.' Partial compensation warrants a baseline 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: 'Copy a past version's snapshot into the live resume.' An agent can immediately tell this apart from siblings like list_resume_versions or get_resume_version, which are reads rather than a restore.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It cross-references list_resume_versions to explain the kind/key convention, which helps the agent orient, but it never states when to prefer this over alternatives (e.g., edit_base_resume or duplicate_base_resume) or any preconditions/exclusions. Usage is implied rather than guided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

resume_proposalResume ProposalA

Return a needs_human proposal to pending_review so preparation can continue. Releases any pre-click daily-cap reservation. Refused for submission_uncertain.

NameRequiredDescriptionDefault
proposal_idYes

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false, idempotentHint=false, destructiveHint=false, so the agent knows it mutates without destroying. The description adds genuinely useful context beyond annotations: it releases a daily-cap reservation and is refused for submission_uncertain proposals. It does not explain permissions or the full effect of the state change.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three terse sentences, each earning its place: the action, the side effect, and the refusal condition. Fully front-loaded with zero filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter mutation with annotations covering the safety profile and no output schema, the state transition, side effect, and refusal condition are enough to avoid misuse. However, it omits the parameter's meaning and how to reach the needs_human state, leaving meaningful gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With one required parameter at 0% schema coverage, the description carries the burden of documenting proposal_id but never mentions it, its format, or where to obtain it. It only implicitly constrains which proposals are eligible. Baseline 3 is the best fit.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific state transition: it moves a needs_human proposal to pending_review. A reader can distinguish it from get_proposal or request_decision. However, it does not say what 'preparation' is or which sibling performs it, so scope is partly implied.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage by describing the state transition but never states when to call this versus alternatives like request_decision or record_decision. It also gives no prerequisites, only a refusal condition.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

run_health_checkRun Resume Health CheckA

Run the JD-independent resume health check on a base resume or a tailored application. kind is 'base' (then key is the base-resume slug) or 'application' (then key is the application id). Classifies every bullet on the evidence ladder, checks structure/content gates, and returns {score, grade, tier, next_grade, gates, counts, findings, judged} ranked by what each defect costs. Concrete qualitative results can earn full credit. An ask/fix finding carries question, ask_kind (measure|detail|reword), measure_target, alt_question, gain and evidence. Notes score zero: the evidence.no_numbers flag and language.* wording notes. Disputes and the word bank are web-only for now. judged is {done, pending, by}: bullets a judge has read, bullets waiting, and the judges' model ids. When Maestro's own model does not judge (no model key is set, or the user's settings say the agent app writes), no model is called: only stored judgments count (any judge, current rubric version); score, grade and next_grade are null while a scored bullet is pending, and judging is {rubric_version, pending_ids, prompt}, where prompt is the app's own evaluator prompt filled with the pending bullets; judge_health_bullets stores answers in that prompt's output shape. create_tailoring_session returns 409 when the base resume's latest, current report has an unwaived failing fatal gate; this call produces that report.

NameRequiredDescriptionDefault
keyYes
kindYes

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Given annotations only flag readOnlyHint=false / idempotentHint=false, the description adds substantial behavioral context: no model is called when the agent's own model writes, only stored judgments count, score/grade/next_grade are null while a scored bullet is pending, and the `judging` payload including the evaluator prompt is returned. It also names the finding shape (ask_kind, measure_target, evidence) and that notes score zero — none of which is recoverable from 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.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The first sentence is well front-loaded, but the remainder is a dense block that mixes return-shape enumeration, judging fallback protocol, and judge_health_bullets coupling into one paragraph without structure. Most content earns its place, yet the single unbroken run makes key conditions (the no-model path, null score rule) hard to locate quickly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description does describe the return object ({score, grade, tier, next_grade, gates, counts, findings, judged}) and the degraded `judging` shape, which is the main gap it needed to close. It omits the enumerated gate names and how findings are ordered in practice, leaving minor ambiguity about what a failing result looks like.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must carry the burden, and it does: it defines the enum values' meaning and, critically, states that `key` is interpreted differently per kind (base-resume slug vs. application id). That conditional semantics is exactly what the bare string schema cannot convey.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("Run the JD-independent resume health check") and immediately scopes it to two target types, base resume vs. tailored application. It is clearly distinguishable from siblings like get_health_report (retrieval) and judge_health_bullets (submission), and the last line clarifies that this call produces the report that create_tailoring_session gates on.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explains exactly how to select between the two modes (kind='base' → key is the slug; kind='application' → key is the application id) and describes the downstream consequence with create_tailoring_session 409 behavior. It does not explicitly contrast with get_health_report or say when re-running is warranted, so it stops short of full alternative routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

save_referralSave Referral ContactA
Destructive

Add a referral contact, or edit one when referral_id is given (list_referrals has the ids). A referral is a company the user can apply to with someone's referral: its careers page, the contact's name and notes. A new referral needs company and careers_url (an http or https address); contact_name and notes are optional, and each call without referral_id adds another referral. An edit changes only the fields passed, and company is optional there: a field left out keeps its saved value, and a field passed replaces it (referrals keep no history of earlier values). An unknown referral_id is a 404 and nothing is written. Returns the saved referral {id, company, careers_url, contact_name, notes, applications_count, created_at, updated_at}.

NameRequiredDescriptionDefault
notesNo
companyNo
careers_urlNo
referral_idNo
contact_nameNo

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond annotations: it explains why the tool is non-idempotent and destructive (each call adds a new referral; edits replace saved values and keep no history), and that a failed edit writes nothing. It also discloses the full return shape for a tool with no output schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Dense but zero waste: the create/edit switch is front-loaded, each parenthetical ('list_referrals has the ids', 'no history of earlier values') carries real signal, and the return contract closes the definition. Length is justified by the number of non-obvious semantics.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with no output schema and 0% parameter documentation, the description supplies required-vs-optional behavior per mode, replacement semantics, error behavior, and the response object. Nothing material an agent needs to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% and the schema only shows nullable, non-required params, so the description carries the burden: it explains that company/careers_url are required on create but company is optional on edit, and crucially that an omitted field keeps its value while a passed field replaces it. That is exactly the null-default semantic the schema cannot express.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Add a referral contact, or edit one when referral_id is given') and explicitly defines what a referral is (company, careers page, contact name, notes). An agent can distinguish this create-or-edit tool from list_referrals and from application-editing siblings without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use routing: omit referral_id to create (and 'each call without referral_id adds another referral'), pass referral_id to edit, and consult list_referrals for the ids. It also names the prerequisites (company and careers_url required on create) and the failure condition (unknown referral_id is a 404).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

score_atsScore Resume Against JobA

Deterministic hybrid match score (no LLM): deterministic lexical layers + anchored pinned-model semantic matching + section-level semantic_fit. Omit target to score ALL base resumes (fast).

target_type "base_resume" (target_id = slug) or "application" (target_id = id).
Same inputs always give the same score; use it to compare bases and to
verify an edit actually moved the number.

Response is {scores, recommendation, countries, next}. `scores` is the raw per-target
list: composite (0-100), per-layer subscores (incl. semantic_fit), gate
warnings, and a per-skill diagnostic table with fix_hints. `recommendation`
is a deterministic ranking of the base-resume rows (order, recommended slug,
margin, close_call, reasons, coverage_warning) — always present, cheap, and
useful during triage even with hints off. Bases set for other countries are
not scored for this job unless `include_other_countries` is true; the
`countries` block ({job_country, fallback, skipped}) names them and is
omitted when a target_id is given. `next` is an optional next-step
hint (null when suppressed or unavailable): in a set with the tailoring tools,
a gap analysis of the recommended base, filled from the saved presets or
walked by hand.

brief=True suits scoring many jobs in a triage/mass-capture loop: it
suppresses ONLY `next` (never `recommendation`) and is checked before any
settings lookup, so a twenty-posting triage loop pays no extra HTTP
round-trip for a hint nobody will read.
NameRequiredDescriptionDefault
briefNo
job_idYes
target_idNo
target_typeNo
include_other_countriesNo

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

It discloses substantial behavior beyond annotations: deterministic/no-LLM computation, full response shape ({scores, recommendation, countries, next}), what each block contains, and the precise exclusion semantics of the countries block. It also explains brief's side-effect surface (suppresses only next, skips settings lookup).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose and the key decision (target vs all) are front-loaded, but the passage is verbose—e.g., the brief justification about HTTP round-trips and settings lookup is repeated in spirit. It earns most of its length given complexity, but some sentences could be tightened.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex, 5-parameter tool with no output schema and no schema descriptions, the description fully compensates: it explains the return structure block-by-block and conditions each optional behavior. An agent has everything needed to call it and interpret the result.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema coverage, the description carries the full burden and does so: target_type's two enum values are mapped to their target_id forms (slug vs id), omitting target scores all bases, include_other_countries gates cross-country scoring, and brief's exact effect is defined. Every parameter gains meaning absent from the bare schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence names a specific verb+resource ('Deterministic hybrid match score') and enumerates the layers (lexical, semantic, semantic_fit), clearly distinguishing it from siblings like compare_ats. An agent immediately knows this produces a match score, not a comparison or edit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states concrete use cases ('compare bases', 'verify an edit actually moved the number') and the omit-target-all-resumes behavior, plus when to set brief=True for triage loops. The alternative path (score-all vs single target) is spelled out explicitly.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_autofill_profileUpdate Autofill ProfileA
DestructiveIdempotent

Save the user's application-form answers: the profile get_autofill_profile reads and the Companion fills forms from. Only the sections passed change. Inside personal, eligibility, preferences and each country's work-permit answers only the keys passed change, and a null removes one; education and languages replace the stored list whole (get_autofill_profile returns them). Each custom answer replaces the saved one with the same question (case and spacing ignored) and the same only_for and only_for_kind, or is added: for an answer held for one company or city, send its only_for and only_for_kind as get_autofill_profile shows them, or a second scoped answer is added. A saved answer is never removed here, so one the Companion learned meanwhile stays (removing one is the user's, in Profile). A work-permit answer is per country and a form question without one is asked on that form, never defaulted; setup counts the answers of each country in apply_in (set_markets). Diversity (EEO) answers have no field here: they and their consent are the user's, in Profile. An unknown section, key or market key writes nothing. Returns {profile, setup}: the saved profile without eeo, and setup status's form-answer readiness (readiness 0 to 1, groups, blocking, work_auth_by_country counts), null when that read fails.

NameRequiredDescriptionDefault
customNo
personalNo
educationNo
languagesNo
eligibilityNo
preferencesNo
work_auth_by_countryNoWork-permit answers by market key. Each country's answers merge key by key; a country set to null loses its answers; a country left out keeps them.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations (destructiveHint/idempotentHint) by spelling out merge semantics per section, that null removes a key, that education/languages replace the list whole, that saved custom answers are never removed here, and that unknown section/key/market writes nothing. Also discloses the return shape {profile, setup} and that setup is null on read failure, which no output schema covers.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core purpose and every sentence carries substantive rules, but the custom-answer rule in particular is a long nested clause that takes rereading, and the whole thing is one dense paragraph rather than grouped by section.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive, all-optional merge-write with no output schema, the description covers the merge/removal model, the custom-answer identity rule, what is deliberately out of scope, failure behavior for unknown keys, and the returned object — leaving no material gap for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 14%, so the description must compensate, and it does: it explains per-section key-level merging, null-removal, list replacement for education/languages, and the question/only_for/only_for_kind matching rule for custom answers. It stops short of naming individual fields inside personal/preferences/eligibility, which the nested $defs already document.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb and resource ('Save the user's application-form answers') and immediately ties it to the sibling read tool get_autofill_profile and to the Companion consumer, so the agent knows exactly what is being written and who reads it.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Routes the agent clearly: reads go through get_autofill_profile, removals and EEO answers are 'the user's, in Profile' and not this tool, and work-permit answers are keyed per country with market keys from apply_in. No explicit contrast against write-side siblings like record_filled_answers, so not a full 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_base_resume_identitySet Resume TargetA
Idempotent

Set what a base resume is written for. Only the fields passed change. countries (ISO codes) restricts which jobs the resume is scored and recommended for: a job in another country skips it, and a resume sent to one is flagged. role_category/role_label name the role, company and focus are free-text emphasis hints for tailoring (at most 80 characters each), and display_name renames the resume. [] clears countries and "" clears company or focus. color_hue (0-359) sets the colour the app shows beside the resume's name; it never changes the PDF. An unknown country, an over-long value or a hue outside 0-359 is a 422 that saves none of the fields. Resume content, versions and the PDF are never touched.

NameRequiredDescriptionDefault
slugYes
focusNo
companyNo
color_hueNo
countriesNo
role_labelNo
display_nameNo
role_categoryNo

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations: it discloses partial-update semantics ('only the fields passed change'), clearing conventions ([] and ""), an atomic 422 failure that 'saves none of the fields', and explicit no-side-effect guarantees for content/versions/PDF. The idempotentHint is matched and enriched by this 'only passed fields change' behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Dense but front-loaded, opening with the core purpose and partial-update rule before enumerating fields. Every clause adds real information (limits, clear sentinels, error behavior), though the field-by-field list makes it long enough to be close to overstuffed.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with no output schema and 8 undocumented parameters, the description supplies update semantics, per-field meaning, validation constraints, clearing behavior, and failure/atomicity guarantees. An agent has everything needed to call it correctly without further context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema coverage across 8 parameters, the description carries the full load and does so thoroughly: it explains countries (ISO codes and their scoring/recommendation effect), role_category/role_label, company and focus (free-text, 80-char cap), display_name, and color_hue (0-359, UI-only). It even documents clear-value sentinels and validation ranges that the bare schema omits.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: setting the targeting/identity metadata a base resume is written for. It is clearly distinguished from the many siblings that touch resume content (update_base_resume, edit_base_resume) by explicitly noting content, versions and PDF are never touched.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The intended scope is strongly implied by contrast ('Resume content, versions and the PDF are never touched'), which effectively signals this is for metadata-only changes rather than content edits. However, it never explicitly names an alternative tool or states when to prefer this over update_base_resume/edit_base_resume, leaving the routing to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_job_preferencesUpdate Job PreferencesA
DestructiveIdempotent

Save the jobs the user wants, which get_job_search_brief reads and setup counts as done once any is set. Only the fields passed change; [] clears a list and "" clears notes. favored_roles holds at most 25 roles, duplicates dropped. A role the catalog does not know (the refusal names the closest), a currency that is not ISO 4217 or more than 25 roles is a 422 that saves nothing. Returns the stored preferences, with role_categories derived from favored_roles.

NameRequiredDescriptionDefault
notesNo
remoteNo
locationsNo
min_salaryNo
favored_rolesNo
employment_typesNo
years_experienceNo

TDQS

A4.1/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well past the annotations (readOnly=false, destructive=true, idempotent=true) by disclosing partial-update semantics ('Only the fields passed change'), explicit clearing conventions ('[] clears a list and "" clears notes'), list limits and dedup, and an atomic 422 that saves nothing. It also states the return payload and the derived role_categories field.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Dense and front-loaded: purpose and downstream effect come first, then mutation semantics, then limits and failure behavior. The telegraphic phrasing ('a currency that is not ISO 4217 or more than 25 roles is a 422') is economical but takes a re-read; nothing is padded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With 7 optional parameters, no output schema, and 0% schema coverage, the description covers the tricky parts: merge-vs-clear semantics, the 25-role cap, atomic validation, and what is returned. It stops short of explaining the non-favored-role fields (remote, locations, employment_types, years_experience), which the schema only partially covers.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must carry parameter meaning, and it does so thoroughly for favored_roles, notes, and min_salary currency. remote, locations, employment_types, and years_experience get no explanation beyond the schema's enums and bounds, leaving half the parameters unaddressed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Names a specific verb and resource ('Save the jobs the user wants') and frames the tool by its downstream effect (get_job_search_brief reads it; setup completes once set). It does not differentiate itself from adjacent setters such as set_markets, set_persona, or set_autofill_profile, which share the 'set_*' shape.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives real usage context: the saved preferences feed get_job_search_brief and count as setup-done once any value is set. It never says when *not* to use it or which sibling setter to pick instead, so routing among the other configuration tools is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_marketsSet Where You Live and ApplyA
Idempotent

Save where the user lives and applies. home (a market key, "UK" not "GB") sets the date format and, while home_currency is unset, the currency pay is shown in. apply_in is every market the user applies in, each asking its own work-permit answers; [] reads as home alone, and a market dropped from it keeps its stored answers. home alone leaves apply_in as stored. home_currency is ISO 4217; "" follows home again. Only the fields passed change, all in one save: a refused field (an unknown currency) writes none of them. No field passed reads the current values. Returns {home, apply_in, home_currency (the resolved one), setup}: setup is setup status's form-answer readiness, null when that read fails.

NameRequiredDescriptionDefault
homeNo
apply_inNo
home_currencyNo

TDQS

A4.3/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations, the description discloses atomic all-or-nothing save behavior on a refused field, retention of stored answers for dropped markets, the meaning of [] for apply_in, and the no-argument read behavior. It also describes the return object and how setup can be null. This is rich behavioral context for a mutation tool and does not contradict the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core purpose and is dense with useful clauses rather than filler. It is somewhat semicolon-heavy and run-on, which slightly reduces readability, but almost every clause earns its place given the complex partial-update semantics.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a three-parameter mutation tool with no output schema, the description supplies the return shape, atomic failure behavior, partial-update semantics, and edge cases for each parameter. Nothing an agent needs in order 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.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must carry parameter meaning, and it does: home is a market key like 'UK' not 'GB' and controls date format and fallback currency; apply_in lists every applied market and [] means home alone; home_currency is ISO 4217 and an empty string follows home again. These details add real semantics beyond the enum-only schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a clear verb and resource: 'Save where the user lives and applies,' and explains that home controls date format and currency while apply_in controls application markets. It does not explicitly name or contrast sibling tools such as set_persona or set_job_preferences, so sibling differentiation is implicit rather than stated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains how the fields interact, including that passing no fields reads current values and that only passed fields change. However, it never states when to use this tool instead of related scheduler-profile or preference tools, so usage guidance is implied rather than explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_personaUpdate PersonaA
DestructiveIdempotent

Replace the user's persona: their direction, strengths and working style in their own words. Every writing prompt (tailoring, application answers, cover letters) reads it for tone and emphasis, never as a source of facts. The whole text is replaced; "" clears it, and setup counts the step done while it is not empty. The app's own persona draft needs Maestro's AI key and has no MCP tool. Returns {key, value}.

NameRequiredDescriptionDefault
textYes

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations: the whole text is replaced (matching destructiveHint), an empty string clears it, setup counts the step done while non-empty, and it returns {key, value}. The AI-key note about the app's own draft is exactly the kind of context structured fields cannot carry.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the verb+resource, then behavior, then the return shape. It is dense but nearly every clause adds operationally useful information; the Maestro AI-key aside is the one sentence that could be trimmed.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite having no output schema, the description supplies the return shape ({key, value}) and covers clear-vs-set semantics and the setup side effect. Nothing an agent needs in order to call this one-parameter mutation correctly appears to be missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0% and the single 'text' parameter is undocumented in the schema, so the description carries the load. It does so by explaining that the parameter is the full persona text, is wholly replaced rather than merged, and that "" clears it — meaningful semantics the schema lacks.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Replace the user's persona') plus what the resource contains (direction, strengths, working style in the user's own words). It also distinguishes the persona from factual sources ('never as a source of facts'), separating it from KB-oriented siblings like kb_edit_profile or kb_capture.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explains downstream usage ('every writing prompt ... reads it for tone and emphasis') and rules out treating it as a fact store, and notes the in-app persona draft has no MCP tool, implying this is the only path. It does not give explicit when-not-to-call guidance or name a sibling alternative directly.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

store_cover_letterStore Cover LetterA
DestructiveIdempotent

Store a cover letter the caller wrote for an application and render its PDF, with no LLM call (generate_cover_letter has the app's configured model write it). It replaces the application's cover letter and that letter's PDF (an application holds one); the new one shows on the job's Apply step and in list_qa_entries. The text is stored as the user's own letter; the server does not verify its facts. As with a generated letter, en and em dashes become a hyphen in a range ("2020-2023") and a comma elsewhere, and one opening a line ("— Jane") is dropped; the rest is stored as written, line breaks and paragraphs included, up to 20000 characters. The PDF puts the base resume's contact block above the letter, in the engine of the application's resume template.

Returns the stored entry {id, application_id, kind, answer, model_used,
pdf_path, render_note, render_error, created_at}; model_used names the
agent. render_error non-null means the letter is stored and its PDF could
not be made (pdf_path is null). render_note is non-null only when a TeX-less
backend rendered a LaTeX template through a Typst one.
NameRequiredDescriptionDefault
textYes
application_idYes

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the destructiveHint and idempotentHint annotations, the description explains what is replaced, that the letter is stored as the user's own text without fact verification, the dash-normalization behavior, line-break preservation, the 20000-character limit, and how the PDF is assembled. It also explains render_error and render_note, which are important behavioral details not present in annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with purpose and the key alternative, then layers on operational details. It is long and dense for a two-parameter tool, and the render_note explanation is niche, but most sentences carry useful information for a destructive replacement operation.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, so the description's return-value details are essential and present: it lists the returned entry fields and explains render_error and render_note semantics. Combined with replacement behavior, PDF rendering details, and storage constraints, it gives an agent enough context to call the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description adds substantial meaning for text: it is the caller's own letter, stored with specific normalization and a 20000-character cap, with line breaks and paragraphs preserved. It only implicitly describes application_id through the phrase 'for an application' and does not state its format or required status, though it is required in the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: store a caller-written cover letter and render its PDF. It explicitly distinguishes this from generate_cover_letter by noting that no LLM call is involved here, while generate_cover_letter uses the configured model.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It clearly establishes the use case: the caller wrote the letter, not the model. It names the alternative generate_cover_letter and explains its different behavior, and it warns that this replaces the application's existing cover letter and PDF.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

store_extracted_jdSave Extracted JobA
Idempotent

Store a job description the caller already extracted into JSON (the backend makes no LLM call).

extracted_json must match the app's JobExtraction schema: company, title,
role_category, level: "intern"|"entry"|"mid"|"senior"|"lead" (other spellings
map to these; any other level is kept in its own words), employment_type,
work_mode: "remote"|"hybrid"|"on_site" (stored as that key), city/state/country
(the job also stores country_code, the one ISO code they name),
location_raw, salary_min/max, salary_period, salary_currency (ISO 4217; a bare "$"
is no currency, so the job takes its country's, else the home one, and
salary_currency_assumed is true),
work_authorization: "sponsorship_available"|"no_sponsorship"|"citizen_or_gc_required"|"unstated",
opt_accepted: "yes"|"stem_opt_ok"|"no"|"unstated",
years_experience_min/max, skills[{skill_name, skill_category,
requirement_level: "required"|"preferred"|"mentioned"}],
responsibilities[], qualifications[]. ANY other work_authorization or
opt_accepted value silently normalizes to "unstated" with no error.
source is "user" (default) or "agent"; source="agent" marks agent-hunted jobs,
which need an open proposal before the apply helpers act on them. A job
stored with source="user" is not proposal-gated: the server skips the
open-proposal check for any non-agent source. Returns the stored job.

A posting already saved is returned unchanged with already_existed=true,
unless update=true: then this extraction corrects it and the job carries
correction. Already saved means the same raw_text (with none, the same
extraction or the same posting at source_url) or the same company and
requisition_id.
NameRequiredDescriptionDefault
sourceNouser
updateNoTrue: when the posting is already saved, this extraction replaces that job's fields and skills through the same mapping a new capture uses; the job keeps its id, status, applications, proposals, source and raw_text. It overwrites the stored extraction, which the web app can't undo. The saved job is found the way a capture finds it: resend the saved raw_text, or omit raw_text and pass its source_url (new raw_text misses the text match and creates a new job). The response's correction is {changed: the fields whose value changed, "skills" when the skill list did; scores_cleared: the job's match scores deleted because a field scoring reads changed, after which the job is scored again; rescored: true when that succeeded; rescore_failed: "bases" or the application ids it could not score, which score_ats computes later; tailored_applications: tailored resumes, left as written; open_sessions: open gap analyses, left to read as out of date, with their score link cleared; proposals_fit_stale: proposals whose stored fit predates the correction}. A job another copy of Maestro owns is refused (409). False (default): a repeat capture returns the saved job unchanged.
raw_textNo
apply_urlNoThe posting's application address when it differs from source_url (http or https). Stored with the job; find_job_by_url then finds the job by it when the address names the posting (an id in its path or query). Without update, a saved job takes it only when it has none; with update it replaces the stored one.
source_urlNo
extracted_jsonYes

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Far beyond what the annotations convey: silent normalization of unknown work_authorization/opt_accepted values to "unstated" with no error, currency-assumption flagging, duplicate-detection identity rules (raw_text, extraction, source_url, company+requisition_id), the 409 refusal, and the full correction result shape. The note that update=true overwrites an extraction the web app can't undo is disclosed even though destructiveHint=false — useful context the annotation would otherwise hide, not an outright contradiction of it.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose and the no-LLM constraint are front-loaded, and the single long sentence enumerating the JobExtraction schema is dense but each clause adds real constraint. It is a wall of text for a complex tool, so slightly short of maximum for scannability.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With six parameters, a nested free-form object, and no output schema, the description still covers return values ("Returns the stored job"), the already_existed path, and the correction payload. An agent has everything needed to call this correctly and to predict the response.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 33% and extracted_json is an untyped object with additionalProperties, so the description carries the full burden — and does, enumerating every field, every enum, and the fallback semantics of each. source, raw_text, update and source_url behavior are all explained contextually rather than restated.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence gives a specific verb and resource ("Store a job description") and rules out the wrong mental model with "the caller already extracted" and "the backend makes no LLM call". It is unambiguous what the tool does, though there is no sibling that stores jobs, so no active differentiation is required.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly states the two conditions that shape a call: source="agent" vs "user" changes whether the open-proposal gate applies, and update=true vs the default changes duplicate handling. It does not name an alternative tool for pre-save lookup (find_job_by_url) or state outright exclusions, so it stops short of full routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

store_qa_answersStore Screening AnswersA
DestructiveIdempotent

Store screening-question answers the caller wrote for an application, with no LLM call (generate_qa_answers has the app's configured model write them). One entry per question, shown in the job's Apply step history and in list_qa_entries. A question the application already holds (the same words, case and spacing ignored) has its answer replaced and the others are added, so a repeated call changes nothing. Answers are stored as plain form text, as generated ones are: markdown bold, headings, bullet markers and backticks are removed, and en and em dashes become a hyphen in a range ("2020-2023") and a comma elsewhere, line breaks kept. The text is stored as the user's own words; the server does not verify it. An answer that is empty once its formatting is removed is a 400 that stores nothing. Returns the stored entries [{id, kind, prompt, answer, model_used, created_at}]; model_used names the agent.

NameRequiredDescriptionDefault
answersYes1-50 {question, answer} pairs: question as the form asks it (at most 2000 characters), answer as it goes into the form (at most 10000).
application_idYes

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations flag destructiveHint and idempotentHint, and the description earns its keep beyond them: it explains exactly what replacement means for an existing question, that formatting (markdown bold, headings, bullets, backticks, dashes) is stripped before storage, that line breaks are kept, that content is not verified, and that an empty-after-stripping answer is a 400 that stores nothing. That is precise mutation and failure semantics, which annotations alone 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.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose and the generate_qa_answers contrast are front-loaded in the first sentence, and the remaining detail is all behaviorally load-bearing. The dash and formatting enumeration is granular enough to border on over-specification, but every sentence carries information an agent could act on.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, but the description supplies the return shape and field meanings ([{id, kind, prompt, answer, model_used, created_at}], with model_used naming the agent). Combined with the mutation, dedup, and error behavior, an agent has everything needed to call this correctly and interpret the result.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 50%, and the description compensates well for the answers array: it defines per-question entry semantics, the replace-vs-add matching rule (same words, case and spacing ignored), and the stored-text normalization, none of which is in the schema. application_id remains undocumented in both places, which keeps it from a 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a concrete verb and resource ('Store screening-question answers') and immediately contrasts with the sibling that generates them instead ('generate_qa_answers has the app's configured model write them'). An agent can distinguish this from generate_qa_answers, list_qa_entries, and record_filled_answers 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.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It names the alternative (generate_qa_answers) and the condition that picks this tool: the caller supplies the text themselves. It also states the repeat-call behavior ('a repeated call changes nothing'), which tells the agent re-invocation is safe. It stops short of an explicit 'do not use when' statement, 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.

sync_nowSync NowA
Idempotent

Run one sync round on the always-on copy. Returns its outcome (ok, transient, needs_person) and per-step counts, or a skip reason. Forces a round through the backoff window; an attempt within the last 30 seconds is skipped with 'Synced moments ago.'. Sync off returns "Sync isn't set up."; home returns "This is your laptop's copy; your bot runs the sync."

NameRequiredDescriptionDefault

No parameters

TDQS

A4.3/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Well beyond the annotations, it enumerates the outcome vocabulary (ok, transient, needs_person), per-step counts, skip reasons, and the 30-second rate-limit behavior with the exact returned string. That is exactly the behavioral detail an agent needs before invoking a mutating, open-world sync.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the action, then outcome, then edge cases; each sentence carries distinct information. The quoted literal responses are slightly verbose but they are the actual contract the caller will see, so they earn their place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no parameters and no output schema, the description carries the full burden and does so: it documents the return shape, outcome values, skip reasons, and the not-set-up/home cases. 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.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so the schema baseline is 4 and there is nothing for the description to disambiguate. No param guidance is needed or missing.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb+resource and scope: "Run one sync round on the always-on copy." That is unambiguous and clearly not the same as the KB or resume siblings. It stops short of naming any sibling as the alternative path, so it is clear but not explicitly differentiated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives concrete usage context: forcing a round through the backoff window, and the states where it is a no-op (sync off, home copy). Those effectively describe when the call is pointless. It does not, however, route the agent to a different tool for those cases.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

tailor_sessionTailor Resume SessionA
Destructive

Run the tailor pipeline for a session: saved resolutions -> edit ops -> the job's tailored application, scored and rendered.

Three ways to produce the edits:
- ops omitted: Maestro's AI writes them, only when the user's writer setting
  (get_setup_status) is Maestro's AI; otherwise refused (409).
- ops: the caller's own typed edit ops, the shapes edit_application takes
  (its ops schema lists each kind), carrying only the changed fields; no
  model call.
- no_new_text=True: no new wording and no model call, under either setting.
The ops and no_new_text parameters say which saved answers the server
applies; answers_left_to_ops lists the ones that need wording.

Caller-supplied ops are applied as authored: the server validates structure
only, so nothing gates fabricated skills, experience, metrics, or dates. A
skill the candidate cannot evidence goes only in the skills list
(add_skill_item), not in a bullet; the compare view audits any edit beyond
the saved resolutions. Resume text is implied first person: an edited line
in I/he/she voice or naming the owner is a 400 naming the lines.

Optional user_prompt adds free-form tailoring guidance. Writes the job's ONE
application from the base plus the edits: it rebuilds the draft (version
history keeps the old draft) and renders its PDF; pdf_ready is false when
that render failed. compare (before/after match score deltas) may be null
with compare_error set: the tailor still succeeded. unbacked_skills names
missing skills this tailor put on the resume that career history does not
back. kb_writeback_skips derives from each user_input resolution's STORED
placement_target from resolve_gaps, not from the ops, so ops that disagree
with the stored target produce a spurious wrong_section skip. `next` (null
when off or unavailable): render_pdf if pdf_ready is false, else apply
readiness; no_new_text's answers left come first.
NameRequiredDescriptionDefault
opsNoTyped edit ops, the shapes edit_application's ops parameter lists; omitted (and no_new_text false), Maestro's AI writes them when the user's writer setting is Maestro's AI. With ops the server itself applies only the saved enable_entry and port_kb_point answers: user_input and attach_project answers reach the resume only through these ops, and answers_left_to_ops lists them. On every path a saved add_keyword whose word (its wording, else the gap's jd_skill) is not on the result is added to the skills list, in the category it chose, else Additional Skills, never as a bullet; keywords_added lists those words.
no_new_textNoTrue: Maestro writes no new wording and calls no model, whichever writer setting the user chose. It applies only the saved answers that need none: enable_entry, port_kb_point (an approved career-history bullet) and add_keyword into the skills list (keywords_added lists the words). An add_keyword placed anywhere else needs a rewritten line: its word lands in the skills list when the resume lacks it, and otherwise the answer is listed in answers_left_to_ops beside the user_input and attach_project answers; nothing listed there reaches the resume. With non-empty ops it is a 422; when nothing can be applied without new wording it is a 400 that says so.
user_promptNo
tailoring_session_idYes

TDQS

A4.2/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Far beyond the annotations (destructive, non-idempotent, open-world), the description discloses that it rebuilds the draft while version history preserves the old one, renders the PDF and can return pdf_ready=false, and that compare may be null with compare_error set while the tailor still succeeded. It also exposes non-obvious contract details: structure-only validation of caller ops, the voice rule producing a 400 naming offending lines, the unbacked_skills audit, and the kb_writeback_skips quirk tied to resolve_gaps' stored placement_target.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose is front-loaded well, but the body is a dense sprawl of run-on sentences and nested parentheticals, mixing core routing rules with niche diagnostics like spurious wrong_section skips. Several details (kb_writeback_skips derivation, next ordering) are genuinely useful but buried where an agent skimming for 'when do I use this' will miss them.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description carries the full return-value burden and does so: pdf_ready, compare/compare_error, unbacked_skills, kb_writeback_skips, answers_left_to_ops, keywords_added, and the `next` fallback chain are all explained. For a destructive, non-idempotent pipeline tool with four parameters, an agent has everything needed to call it and interpret the result.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 50%, and the description compensates: user_prompt is explained as free-form tailoring guidance, and ops/no_new_text gain cross-parameter semantics the schema can't express (ops are applied as authored with no fabrication gate; no_new_text conflicts with non-empty ops at 422; which saved answer kinds flow through ops vs. server application). tailoring_session_id is left unexplained, but its meaning is evident from the tool name.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence states a specific verb, resource, and outcome: run the tailor pipeline for a session, producing the job's scored and rendered application from saved resolutions plus edit ops. It distinguishes itself functionally from edit_application by naming that tool's ops schema as the source of op shapes, but it never frames a clean contrast ('use this instead of edit_application when...'), so differentiation is by reference rather than explicit statement.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The three-way breakdown (ops omitted -> Maestro AI writes when get_setup_status says so, else 409; caller ops -> no model call; no_new_text -> no wording, no model call) gives explicit selection criteria and failure modes, including ops + no_new_text = 422. What's missing is guidance on when to pick this tool over sibling paths such as edit_application or edit_base_resume rather than how to pick a mode within it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

unarchive_base_resumeUnarchive Base ResumeA
Idempotent

Restore an archived base resume to list_base_resumes' default view.

Clears archived_at. The resume is again selectable; nothing else changes.
NameRequiredDescriptionDefault
slugYes

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly=false, idempotent=true, destructive=false, openWorld=false, so the bar is lower. The description still adds real behavioral detail: it clears archived_at, makes the resume selectable again, and explicitly states 'nothing else changes' — a valuable scope guarantee. It does not, however, cover error behavior (e.g. unarchiving a non-archived resume).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short, front-loaded sentences with zero waste: the action and its scope lead, followed by the concrete state change and a reassurance clause. Nothing is redundant or padded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple, single-identifier state-flip tool whose safety profile is fully covered by annotations and with no output schema to explain, the description is nearly complete. Only the meaning/format of slug and the non-archived edge case remain unstated.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The single slug parameter has 0% schema description coverage, so the description would ideally clarify it, and it does not mention slug at all. The parameter is a trivially inferable identifier, which softens the gap, but the description provides no semantic compensation for the missing schema documentation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (restore/unarchive) and resource (an archived base resume), and the inverse action clearly distinguishes it from the sibling archive_base_resume. Naming list_base_resumes' default view scopes exactly what the operation achieves.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the operation itself ('restore an archived...'), and it implies a prerequisite (the resume must be archived). However, it never states when to use this versus alternatives like restore_resume_version or update_base_resume, nor the condition under which it is the wrong tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

unwaive_health_gateRemove Health Gate WaiverA
DestructiveIdempotent

Remove a health-gate waiver and restore the gate's protection. Deletes the stored waiver for this gate (a no-op if none exists), so the gate blocks create_tailoring_session with a 409 again. The counterpart waive_health_gate records the user's decision to bypass a failing gate.

NameRequiredDescriptionDefault
keyYes
kindYes
gate_idYes

TDQS

A3.9/5.0
Behavior4/5

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 adds genuinely non-structured behavior: it deletes the stored waiver, is a no-op if none exists, and causes create_tailoring_session to return 409 again. That downstream effect is valuable context not present in the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences with no filler; the core action is front-loaded and the counterpart tool is described last as supporting context. Slightly longer than strictly necessary but every sentence contributes.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a small mutation tool with annotations covering the safety profile and no output schema, the description is mostly adequate. However, with 0% parameter coverage and an unexplained enum, an agent cannot confidently supply kind or key, leaving a real completeness gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% across three required parameters, so the description carries the full burden, yet it explains none of them. "For this gate" loosely implies gate_id, but kind (base vs application) and key are left completely undefined, and the enum's two values are nowhere explained.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("Remove a health-gate waiver") and explicitly names its counterpart tool, waive_health_gate, so an agent can distinguish the two without opening either schema. The effect (restore the gate's protection) is unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains the situation that motivates the call: it undoes a prior bypass so the gate blocks create_tailoring_session again, and it identifies waive_health_gate as the reverse operation. It stops short of explicit when-to-use/when-not wording, but the context is clear enough to select the tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

update_applicationUpdate Application TrackingA
DestructiveIdempotent

Update an application's tracking fields (status, applied_at, notes, referral_id).

Only the arguments passed are sent to the backend — the PATCH endpoint is
driven by which fields were actually set on the request, so an argument left
out leaves that field untouched. `clear` empties notes or unlinks the
referral (an explicit null on the request).

Allowed statuses: draft, applied, interviewing, offered, accepted, rejected,
withdrawn, skipped (anything else is rejected). `skipped` is the user's own
"not applying to this one". Setting status to applied, interviewing, offered
or accepted also closes any open proposal on the job, recorded as a declined
"applied manually" consent event; skipped closes it as a plain skip.

applied_at sync rule: if you change `status` without also passing `applied_at`,
the backend keeps applied_at in sync automatically — entering "applied" stamps
it with the current time (only if not already set), moving back to "draft"
clears it, and every other status (interviewing/offered/accepted/rejected/
withdrawn/skipped) preserves whatever applied_at already holds. An explicit
`applied_at` overrides that sync and must carry a UTC offset
(e.g. `2026-08-18T14:32:11+00:00`) — a naive value is a 422.

Every status change is logged with its date and who made it (this client's
name). Pass `from_email=True` when you read the change in the user's job
email (the mail-status automation): the log then says it came from mail.
NameRequiredDescriptionDefault
clearNoFields to empty: "notes" removes the notes, "referral_id" unlinks the referral contact (the referral itself is kept). A field given a value in the same call is refused, and nothing is written.
notesNo
statusNo
applied_atNo
from_emailNo
referral_idNo
application_idYes

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Far beyond what the annotations declare: it discloses the PATCH contract, the side effect that certain statuses close an open proposal with a declined 'applied manually' consent event, the applied_at sync rules per status transition, the 422 on naive datetimes, and that every change is logged with date and actor. For a destructive, non-read-only mutation this is exactly the context an agent needs before calling.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the purpose, then paragraph-per-topic (PATCH semantics, statuses, applied_at sync, logging) with no filler sentences. It is on the long side for seven parameters, but each block maps to a distinct behavior an agent would otherwise get wrong.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers the write semantics, side effects, validation errors and logging for a seven-parameter mutation with no output schema. What is missing is the shape of the response (the updated row vs. a bare acknowledgement) and any differentiation from `edit_application`.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 14% and `status` has no enum in the schema, so the description carries the load: it enumerates the eight allowed statuses, defines `skipped` in the user's terms, specifies UTC-offset formatting for `applied_at`, and explains that `clear` empties notes or unlinks the referral. That compensates for nearly every undocumented parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence gives a specific verb and resource plus the exact set of tracking fields it touches (status, applied_at, notes, referral_id). It is clearly a partial PATCH-style update rather than a creation or read. The one gap is that the sibling `edit_application` is never mentioned, so an agent cannot tell from this text why it should pick this tool over that one.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit when-semantics are given for the trickiest cases: only supplied arguments are sent, `clear` is the way to null a field, and `from_email=True` applies when the change was read in the user's job email. There is no exclusion or alternative-tool routing, and the overlap with `edit_application` goes unaddressed.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

update_base_resumeReplace Base Resume DataA
DestructiveIdempotent

Replace a base resume's data (the full ResumeData object, required). Optionally also update display_name. PUT replaces the whole resume body.

NameRequiredDescriptionDefault
dataYes
slugYes
display_nameNo

TDQS

A3.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and idempotentHint=true, but they do not say whether the write merges or overwrites. The description fills that gap: 'PUT replaces the whole resume body' plus 'the full ResumeData object, required' tells the agent anything omitted from data is lost, which is genuinely additive. It still omits auth requirements and what happens on invalid data.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, front-loaded with the core action and payload requirement; nothing padding. Minor redundancy with the title ('Replace Base Resume Data') but it earns its place by adding the PUT/replacement semantics.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive mutation with a nested unschematized payload and no output schema, the description is minimal but directionally adequate. It leaves the ResumeData structure entirely undocumented and never mentions the slug parameter or failure behavior, so an agent still has gaps before calling it safely.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must carry the load. It clarifies that data is the required full ResumeData object and that display_name is optional ('optionally also update'), but says nothing about slug and gives no shape for the nested data object.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Replace a base resume's data') and defines the primary payload as the full ResumeData object. 'PUT replaces the whole resume body' implicitly distinguishes it from partial-edit siblings such as edit_base_resume, 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.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'PUT replaces the whole resume body' implies the tool is for wholesale replacement rather than a patch, which is useful routing context. However, it never states when to choose this over edit_base_resume, set_base_resume_identity, or create_base_resume_from_kb, and lists no prerequisites.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

update_template_draftEdit Template DraftA
DestructiveIdempotent

Edit a draft template; changing the source resets it to 'draft'. Pass validate=True to save + test-compile in one call (returned status/last_error show the result); otherwise re-validate separately. The active default template cannot be edited through these tools (the backend rejects it).

NameRequiredDescriptionDefault
sourceNo
validateNo
template_idYes
display_nameNo

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnly=false, destructive=true, idempotent=true. The description adds non-obvious behavior beyond that: editing the source resets the template to 'draft', validate=True performs a save+test-compile with results surfaced via status/last_error, and the active default template is rejected by the backend. These are exactly the side effects 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.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three dense sentences, front-loading the core edit action and the source-reset caveat. The parenthetical about returned status/last_error is slightly compressed but each 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.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive mutation with no output schema, the description covers the mutation's side effects, the validation shortcut and its result fields, and a key restriction. Only the undocumented display_name/template_id parameters leave a small gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must carry the load. It explains the validate parameter's semantics and the source parameter's side effect (reset to draft), but display_name and template_id are not described at all. Partial compensation for a 0% coverage schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Edit a draft template') and immediately scopes it against siblings by noting changing the source resets status to 'draft' and that re-validation can happen separately (routing away from validate_template). An agent can distinguish this from create_template_draft and validate_template without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says when to use the one-call path ('Pass validate=True to save + test-compile in one call') versus validating separately, and states a hard when-not: the active default template cannot be edited and the backend rejects it. Both the alternative and the exclusion are named.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

validate_templateValidate TemplateA
Idempotent

Test-compile a template against a built-in sample resume. On success it becomes 'ready' (usable via render_pdf template_id) and a preview is available via get_rendered_pdf('template', id). On failure returns {ok: false, error} with the engine's compile error (Typst errors carry file:line:col). Returns {ok, error, parse_certified} — parse_certified is true when the template's compiled PDF round-trips through a strict text extractor with word boundaries intact, false when it drops text, null when not assessed. Also returns parse_report: {missing, headers_missing, extra_sections_supported, extra_sections_missing} — missing lists the exact sample phrases the PDF dropped; extra_sections_missing non-empty means the template will hard-fail rendering any resume that has custom sections.

NameRequiredDescriptionDefault
template_idYes

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations by disclosing the state transition to 'ready', the exact failure shape ({ok:false, error} with Typst file:line:col), and the semantics of parse_certified (true/false/null) and parse_report. The idempotentHint is reinforced by the deterministic test-compile behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the purpose and outcome, then layers the return-value contract. Dense but each sentence carries information; the parse_certified/parse_report details are justified since there is no output schema. Slightly long, but no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description carries the full burden of explaining return values, and it does so thoroughly for both success and failure paths, including the hard-fail warning for extra_sections_missing. An agent has everything needed to call and interpret this tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0% and the sole parameter (template_id) has no schema description. The description references template_id only indirectly through render_pdf/get_rendered_pdf usage, and never says where template_id comes from (e.g., list_templates). It adds marginal meaning but leaves the parameter under-documented.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Test-compile a template') and explains the concrete outcome: on success the template becomes 'ready' and is usable via render_pdf. An agent can immediately distinguish this from create_template_draft or render_pdf.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Clearly frames the use case as a pre-flight validation step ('On success it becomes ready... usable via render_pdf template_id'), implying it should be run before rendering. It does not name an explicit when-not-to-use or a competing alternative, but the context is unambiguous.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

waive_health_gateWaive Health GateA
Idempotent

Escape hatch for the fatal-health-gate 409 from create_tailoring_session. Waiving bypasses a safety gate, so the stored waiver records an explicit user decision: reason is the user's stated reason for bypassing the named gate. The server stores the waiver as given and does not verify who made the decision. kind is 'base' or 'application', key is the resume slug or application id. The 409 names each failing gate by its label; the gate_id to pass is that gate's gates[].id in get_health_report.

NameRequiredDescriptionDefault
keyYes
kindYes
reasonYes
gate_idYes

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare a non-read-only, non-destructive, idempotent, closed-world mutation; the description adds genuinely non-obvious context on top: that waiving bypasses a safety gate, that the server stores the waiver verbatim and does not verify who made the decision, and that the stored waiver is meant to represent an explicit user decision. It doesn't cover repeat-call behavior or the response shape, keeping it at 4 rather than 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the purpose in the first sentence, then moves to behavioral trust model and finally parameter semantics, with no filler sentences. It is dense and slightly run-on across five sentences, but each one adds information an agent needs.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 4-required-param mutation with no output schema, the description covers trigger, trust model, and all parameter meanings, and annotations carry the safety profile. Minor gaps remain around idempotent repeat behavior and what the stored waiver looks like on return.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage the description must carry all parameter meaning, and it does: kind is 'base' or 'application' (matching the enum), key is the resume slug or application id, reason is the user's stated justification, and gate_id is pinpointed as the gates[].id value from get_health_report. Every required parameter is disambiguated beyond the bare schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a precise verb+resource (waive a health gate) and anchors it to a concrete trigger: the fatal-health-gate 409 from create_tailoring_session. It also names the sibling tools it interacts with (create_tailoring_session, get_health_report), so an agent can distinguish it from nearby tools like unwaive_health_gate or run_health_check.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives a clear when-to-use condition (only as an escape hatch after create_tailoring_session returns a fatal-health-gate 409) and explains how to obtain the required gate_id from get_health_report. It never explicitly names unwaive_health_gate as the reverse operation or states when NOT to waive, so it falls just short of full routing guidance.

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.

  1. 38 tool updatesv0.12.0
    • Changedattach_evidence5 fields changed
      • addedInput schema / properties / file_path
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "An absolute path to an existing PNG or JPEG on this machine, typically as a browser tool reports it (Playwright MCP saves to its --output-dir; with the standard setup that is under the repo's .playwright-mcp/ tree, e.g. /Users/<user>/Projects/maestro-career-studio/.playwright-mcp/<name>.png); a relative or ~ path is resolved against this server's working directory. When this server runs inside the backend container, a host path with a `.playwright-mcp/` segment is read from the container's mount of that tree (paths that leave the tree are refused). PNG/JPEG only, 5 MB max.",
        +  "title": "File Path"
        +}
      • addedInput schema / properties / image_base64 / anyOf
        Added value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • addedInput schema / properties / image_base64 / default
        Added value: +null
      • removedInput schema / properties / image_base64 / type
        Removed value: -"string"
      • changedInput schema / required
        Previous value: -[
        -  "proposal_id",
        -  "step",
        -  "label",
        -  "image_base64"
        -]New value: +[
        +  "proposal_id",
        +  "step",
        +  "label"
        +]
    • Removedattach_evidence_file
    • Changedcreate_tailoring_session1 field changed
      • addedInput schema / properties / use_presets
        Added value: +{
        +  "default": false,
        +  "description": "True: once the session is created, fill it from the user's Quick tailor presets (get_tailoring_options explains them) through resolve_gaps' honesty-gated save path, deterministically and with no AI. The presets plan only mechanical, evidence-respecting moves; the fill does not write resume text. The returned resolutions_json may already resolve every gap, including system-planned entries (payload.provenance); a gap the presets do not decide is saved as skip. A session whose answers are all skip is not an error: the presets allowed nothing for it, and resolve_gaps still saves answers on it. An unverified or absent skill enters only a skills category (add_skill_item), never as an experience or project bullet; the server does not gate edit ops the caller writes against fabricated skills, experience, metrics or dates. A stale or no-longer-open session blocks the fill (409). The `next` hint then carries the presets' standing instruction as tailor_session's user_prompt when the session has no note of its own.",
        +  "title": "Use Presets",
        +  "type": "boolean"
        +}
    • Changededit_application1 field changed
      • changedInput schema / properties / ops / description
        Previous value: -"Typed edit ops. Each is an object with a `kind`, one of: replace_summary | toggle_entry | replace_bullet | replace_skills_group | add_skill_item | add_bullet | add_entry | replace_entry | remove_entry | remove_bullet | replace_contact | replace_certifications | add_extra_section | replace_extra_section | remove_extra_section | move_extra_section. To change a field ON an entry — dates, title, company, project name, link, tech — use replace_entry with that entry's index and the full edited entry object; it is scoped to that one entry (a whole-resume replace is the separate update_base_resume tool). See the tool description for each op's shape. add_extra_section/replace_extra_section `value` is {key,title,enabled,type:\"entries\"|\"bullets\"} plus EITHER entries:[{heading,subheading?,location?,date?,link?,enabled,bullets:[str]}] OR bullets:[str] — never both; unknown keys are rejected (400, extra=\"forbid\")."New value: +"Typed edit ops. Each is an object with a `kind`, one of: replace_summary | toggle_entry | replace_bullet | replace_skills_group | add_skill_item | add_bullet | add_entry | replace_entry | remove_entry | remove_bullet | replace_contact | replace_certifications | add_extra_section | replace_extra_section | remove_extra_section | move_extra_section. To change a field ON an entry — dates, title, company, project name, link, tech — use replace_entry with that entry's index and the full edited entry object; it is scoped to that one entry (a whole-resume replace is the separate update_base_resume tool). See the tool description for each op's shape. add_extra_section/replace_extra_section `value` is {key,title,enabled,type:\"entries\"|\"bullets\"} plus EITHER entries:[{heading,subheading?,location?,date?,link?,enabled,bullets:[str]}] OR bullets:[str] — never both; unknown keys are rejected (400, extra=\"forbid\"). Text the ops write is implied first person: a line with I/he/she/they or the owner's name is a 400 naming the lines, and nothing is written."
    • Changededit_base_resume1 field changed
      • changedInput schema / properties / ops / description
        Previous value: -"Typed edit ops. Each is an object with a `kind`, one of: replace_summary | toggle_entry | replace_bullet | replace_skills_group | add_skill_item | add_bullet | add_entry | replace_entry | remove_entry | remove_bullet | replace_contact | replace_certifications | add_extra_section | replace_extra_section | remove_extra_section | move_extra_section. To change a field ON an entry — dates, title, company, project name, link, tech — use replace_entry with that entry's index and the full edited entry object; it is scoped to that one entry (a whole-resume replace is the separate update_base_resume tool). See the tool description for each op's shape. add_extra_section/replace_extra_section `value` is {key,title,enabled,type:\"entries\"|\"bullets\"} plus EITHER entries:[{heading,subheading?,location?,date?,link?,enabled,bullets:[str]}] OR bullets:[str] — never both; unknown keys are rejected (400, extra=\"forbid\")."New value: +"Typed edit ops. Each is an object with a `kind`, one of: replace_summary | toggle_entry | replace_bullet | replace_skills_group | add_skill_item | add_bullet | add_entry | replace_entry | remove_entry | remove_bullet | replace_contact | replace_certifications | add_extra_section | replace_extra_section | remove_extra_section | move_extra_section. To change a field ON an entry — dates, title, company, project name, link, tech — use replace_entry with that entry's index and the full edited entry object; it is scoped to that one entry (a whole-resume replace is the separate update_base_resume tool). See the tool description for each op's shape. add_extra_section/replace_extra_section `value` is {key,title,enabled,type:\"entries\"|\"bullets\"} plus EITHER entries:[{heading,subheading?,location?,date?,link?,enabled,bullets:[str]}] OR bullets:[str] — never both; unknown keys are rejected (400, extra=\"forbid\"). Text the ops write is implied first person: a line with I/he/she/they or the owner's name is a 400 naming the lines, and nothing is written."
    • Removedexplore_ats_over_time
    • Removedexplore_fit_distribution
    • Removedexplore_role_mix_over_time
    • Removedexplore_skill_heatmap
    • Removedexplore_tailoring_lift
    • Removedexplore_top_skills
    • Addedexplore_trends
    • Changedget_career_context1 field changed
      • addedInput schema / properties / format
        Added value: +{
        +  "default": "json",
        +  "enum": [
        +    "json",
        +    "markdown"
        +  ],
        +  "title": "Format",
        +  "type": "string"
        +}
    • Removedget_career_export
    • Addedget_setup_status
    • Addedget_tailoring_options
    • Addedjudge_health_bullets
    • Addedkb_add_points
    • Changedkb_approve_points1 field changed
      • removedInput schema / properties / state
        Removed value: -{
        -  "default": "approved",
        -  "enum": [
        -    "approved",
        -    "retired"
        -  ],
        -  "title": "State",
        -  "type": "string"
        -}
    • Addedkb_combine_points
    • Addedkb_groom_entity
    • Addedkb_merge_entities
    • Addedkb_retire_points
    • Changedlist_base_resumes1 field changed
      • addedInput schema / properties / include_archived
        Added value: +{
        +  "default": false,
        +  "title": "Include Archived",
        +  "type": "boolean"
        +}
    • Changedprepare_application_pdf_upload1 field changed
      • addedInput schema / properties / document
        Added value: +{
        +  "default": "resume",
        +  "description": "\"resume\" (default): the tailored resume's PDF. \"cover_letter\": the PDF of the cover letter stored for the application (store_cover_letter or generate_cover_letter), rendered first when it has none, staged in the same folder under its own file name, so the two copies sit side by side. With no cover letter stored the call is refused and nothing is staged.",
        +  "enum": [
        +    "resume",
        +    "cover_letter"
        +  ],
        +  "title": "Document",
        +  "type": "string"
        +}
    • Removedquick_tailor
    • Changedrender_pdf2 fields changed
      • addedInput schema / properties / formatting
        Added value: +{
        +  "anyOf": [
        +    {
        +      "additionalProperties": true,
        +      "type": "object"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Look settings to keep (keep=true), one object of the template knobs: font_size (10|11|12), side_margins and top_bottom_margin (0.3-1.0 inches), line_spacing (0.9-1.4), section_spacing (0-14 pt), entry_spacing (0-10 pt), justify and hide_divider (true|false), bullet_icon (\"bullet\"|\"dash\"), header_align (\"left\"|\"center\"|\"right\"), date_format (\"verbatim\"|\"short_month\"|\"long_month\"|\"numeric\"), education_order (\"degree_first\"|\"institution_first\"), skills_layout (\"inline\"|\"bulleted\"), section_order (a list of summary, experience, projects, extra_sections, skills, education, certifications; the rest follow in the template's order). It replaces the resume's saved look settings: a knob left out takes the template's default (on a tailored resume, its base resume's setting first), and {} clears them. An unknown knob or a value out of range is a 400 and nothing is kept. get_base_resume returns a base resume's saved formatting and template_id.",
        +  "title": "Formatting"
        +}
      • addedInput schema / properties / keep
        Added value: +{
        +  "default": false,
        +  "description": "True: before rendering, the template_id and/or formatting given are saved on this base resume or tailored resume, so its later renders use them, after an edit too; template_id must name a ready template. False (default): template_id is a one-off for this render, the saved design is unchanged, and formatting is refused.",
        +  "title": "Keep",
        +  "type": "boolean"
        +}
    • Addedsave_referral
    • Addedset_autofill_profile
    • Addedset_job_preferences
    • Addedset_markets
    • Addedset_persona
    • Addedstore_cover_letter
    • Changedstore_extracted_jd2 fields changed
      • addedInput schema / properties / apply_url
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "The posting's application address when it differs from source_url (http or https). Stored with the job; find_job_by_url then finds the job by it when the address names the posting (an id in its path or query). Without update, a saved job takes it only when it has none; with update it replaces the stored one.",
        +  "title": "Apply Url"
        +}
      • addedInput schema / properties / update
        Added value: +{
        +  "default": false,
        +  "description": "True: when the posting is already saved, this extraction replaces that job's fields and skills through the same mapping a new capture uses; the job keeps its id, status, applications, proposals, source and raw_text. It overwrites the stored extraction, which the web app can't undo. The saved job is found the way a capture finds it: resend the saved raw_text, or omit raw_text and pass its source_url (new raw_text misses the text match and creates a new job). The response's correction is {changed: the fields whose value changed, \"skills\" when the skill list did; scores_cleared: the job's match scores deleted because a field scoring reads changed, after which the job is scored again; rescored: true when that succeeded; rescore_failed: \"bases\" or the application ids it could not score, which score_ats computes later; tailored_applications: tailored resumes, left as written; open_sessions: open gap analyses, left to read as out of date, with their score link cleared; proposals_fit_stale: proposals whose stored fit predates the correction}. A job another copy of Maestro owns is refused (409). False (default): a repeat capture returns the saved job unchanged.",
        +  "title": "Update",
        +  "type": "boolean"
        +}
    • Addedstore_qa_answers
    • Removedtailor_application
    • Changedtailor_session2 fields changed
      • addedInput schema / properties / no_new_text
        Added value: +{
        +  "default": false,
        +  "description": "True: Maestro writes no new wording and calls no model, whichever writer setting the user chose. It applies only the saved answers that need none: enable_entry, port_kb_point (an approved career-history bullet) and add_keyword into the skills list (keywords_added lists the words). An add_keyword placed anywhere else needs a rewritten line: its word lands in the skills list when the resume lacks it, and otherwise the answer is listed in answers_left_to_ops beside the user_input and attach_project answers; nothing listed there reaches the resume. With non-empty ops it is a 422; when nothing can be applied without new wording it is a 400 that says so.",
        +  "title": "No New Text",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / ops / description
        Added value: +"Typed edit ops, the shapes edit_application's ops parameter lists; omitted (and no_new_text false), Maestro's AI writes them when the user's writer setting is Maestro's AI. With ops the server itself applies only the saved enable_entry and port_kb_point answers: user_input and attach_project answers reach the resume only through these ops, and answers_left_to_ops lists them. On every path a saved add_keyword whose word (its wording, else the gap's jd_skill) is not on the result is added to the skills list, in the category it chose, else Additional Skills, never as a bullet; keywords_added lists those words."
    • Changedupdate_application2 fields changed
      • addedInput schema / properties / clear
        Added value: +{
        +  "anyOf": [
        +    {
        +      "items": {
        +        "enum": [
        +          "notes",
        +          "referral_id"
        +        ],
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Fields to empty: \"notes\" removes the notes, \"referral_id\" unlinks the referral contact (the referral itself is kept). A field given a value in the same call is refused, and nothing is written.",
        +  "title": "Clear"
        +}
      • addedInput schema / properties / from_email
        Added value: +{
        +  "default": false,
        +  "title": "From Email",
        +  "type": "boolean"
        +}
  2. 88 tool updatesv0.11.1
    • First observedarchive_base_resume
    • First observedattach_evidence
    • First observedattach_evidence_file
    • First observedclose_tailoring_session
    • First observedcompare_ats
    • First observedcreate_base_resume
    • First observedcreate_base_resume_from_kb
    • First observedcreate_tailoring_session
    • First observedcreate_template_draft
    • First observedduplicate_base_resume
    • First observededit_application
    • First observededit_base_resume
    • First observedexplore_ats_over_time
    • First observedexplore_fit_distribution
    • First observedexplore_gap_frequency
    • First observedexplore_role_mix_over_time
    • First observedexplore_skill_heatmap
    • First observedexplore_tailoring_lift
    • First observedexplore_top_skills
    • First observedexport_jobs
    • First observedfind_job_by_url
    • First observedgenerate_cover_letter
    • First observedgenerate_qa_answers
    • First observedget_application
    • First observedget_autofill_profile
    • First observedget_base_resume
    • First observedget_career_context
    • First observedget_career_export
    • First observedget_final_review
    • First observedget_health_report
    • First observedget_job
    • First observedget_job_search_brief
    • First observedget_job_site_login
    • First observedget_proposal
    • First observedget_rendered_pdf
    • First observedget_rendered_pdf_page_image
    • First observedget_resume_version
    • First observedget_tailoring_session
    • First observedget_template
    • First observedkb_approve_points
    • First observedkb_capture
    • First observedkb_create_entity
    • First observedkb_edit_entity
    • First observedkb_edit_point
    • First observedkb_edit_profile
    • First observedkb_get_entity
    • First observedkb_ingest_resume
    • First observedkb_list_entities
    • First observedkb_list_points
    • First observedkb_sync_base
    • First observedlist_applications
    • First observedlist_base_resumes
    • First observedlist_jobs
    • First observedlist_proposals
    • First observedlist_qa_entries
    • First observedlist_referrals
    • First observedlist_resume_versions
    • First observedlist_tailoring_sessions
    • First observedlist_templates
    • First observedmark_submitted
    • First observedprepare_application_pdf_upload
    • First observedpropose_application
    • First observedquick_tailor
    • First observedrecord_consent
    • First observedrecord_decision
    • First observedrecord_filled_answers
    • First observedrecord_run
    • First observedrecord_triage
    • First observedrender_pdf
    • First observedreport_failure
    • First observedrequest_decision
    • First observedresolve_gaps
    • First observedrestore_resume_version
    • First observedresume_proposal
    • First observedrun_health_check
    • First observedscore_ats
    • First observedset_base_resume_identity
    • First observedstore_extracted_jd
    • First observedsync_now
    • First observedtailor_application
    • First observedtailor_session
    • First observedunarchive_base_resume
    • First observedunwaive_health_gate
    • First observedupdate_application
    • First observedupdate_base_resume
    • First observedupdate_template_draft
    • First observedvalidate_template
    • First observedwaive_health_gate

TDQS

B3.4/5.0

Scored across 94 tools

Disambiguation2/5

The set contains several overlapping clusters: base-resume editing (edit_base_resume/update_base_resume/restore_resume_version), application editing (edit_application/tailor_session ops), proposal state transitions (record_triage/record_decision/request_decision/record_consent/resume_proposal), and KB ingestion (kb_capture/kb_add_points/kb_ingest_resume/kb_sync_base). Individual descriptions are detailed, but at 94 tools an agent must reason through many subtle boundaries and may misselect.

Naming Consistency4/5

Nearly all tools use snake_case verb_noun phrasing, often with clear domain prefixes such as kb_ and get_/set_/list_/record_. Minor deviations exist around the kb_ namespace and some state-machine verbs, but the conventions remain predictable.

Tool Count1/5

94 tools is an extreme count for any MCP server, even one covering a broad career workflow. The surface should be consolidated into fewer higher-level tools or split into separate servers.

Completeness4/5

The surface covers a wide lifecycle: jobs, applications, proposals, tailoring, KB, templates, rendering, health checks, referrals, autofill, and export. There are minor gaps such as explicit deletion/update paths for jobs and referrals, but core workflows are well represented.

Maintenance

ActivityActive
ResponsivenessNo recent community issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    A
    maintenance
    CareerMate is an MCP-first, local-only career management tool that stores your career data (profiles, resumes, cover letters, job postings, applications, interview prep) on your computer and exposes it through MCP tools for AI agents to read and write.
    16 npm
    2
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Enables parsing a master resume, analyzing job descriptions for ATS/match scores, generating truthful tailored resumes, tracking applications, and producing PDF reports through Claude Desktop.
    17
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables AI assistants to tailor a resume to any job description by extracting keywords, analyzing gaps and ATS compliance, managing versions, and compiling PDF/LaTeX outputs entirely locally without external API keys.
    MIT