jobwatch
jobwatch is a local-first job-search MCP server that watches company job boards, ranks new roles against your resume, and helps manage applications and interview prep.
Find, list, add, remove, and suggest company job boards to watch.
Fetch new postings and return a ranked digest, optionally fit-scored against your resume.
Track jobs and applications through stages, notes, next steps, follow-ups, duplicates, and closed postings.
Import job-alert emails and read application-status emails with proposed updates.
Save and retrieve application packages and reuse past form answers.
Prepare for interviews with prep sheets, drafted answers from your stories, role questions, and skill-gap analysis.
Compare offers using compensation, company health, career value, fit, and contacts.
Track referral contacts and parse LinkedIn profile text you provide.
Add jobs found elsewhere, including via application links, for consolidated tracking.
Reads public Greenhouse job boards to discover and track new job postings at watched companies, including pay ranges and posting details.
jobwatch
Watch the job boards of the companies you care about and get a short, ranked digest of new roles that match you, optionally fit-scored against your resume. jobwatch finds and ranks. It never applies for you.
If jobwatch helps your search, a ⭐ on GitHub is how I know: jobwatch sends nothing home, so stars are the only count of who uses it. If it landed you an interview, a $1 coffee says so too.

With sound (1½ minutes, made from made-up data):
https://github.com/user-attachments/assets/71b048d0-d372-42fd-a247-c4a59c3ffd71
Tutorials
Seven short videos, two minutes or less each, made from made-up data. GitHub's video links last five minutes, so if one stops after a second or two, reload the page and play it again.
Getting started: install, jobwatch ui, the four onboarding steps, Today.
https://github.com/user-attachments/assets/f95f85df-406f-4ede-b84c-59569d1a586a
Your daily routine: today's picks, a job's details, the queue, "I applied", Applications, the prep sheet.
https://github.com/user-attachments/assets/8653c4ca-a79d-4135-9be1-51ba3c9fccf6
Where the AI runs: the Claude API, Antigravity or this Mac; the fallback chain; what leaves your computer.
https://github.com/user-attachments/assets/40e6f2cb-c201-4da9-ba21-77bdacc464b8
Applying: the queue, jobs found elsewhere, job-alert emails, status emails, companies to watch.
https://github.com/user-attachments/assets/9d021676-85da-4ce1-8d42-f3808b4ae03b
Tracking applications: stages and follow-ups, applications that go quiet, the calendar feed, Interviews.
https://github.com/user-attachments/assets/e2e43a54-83d2-4154-9229-a063fafefe44
Interview prep: prep sheets, answers drafted from your stories, a mock interview, a drill video.
https://github.com/user-attachments/assets/c8ac1030-700f-4cdd-823d-4b92cd411bf3
Comps and who you know: pay, career value and company health side by side; the people you know there.
https://github.com/user-attachments/assets/42eb0edb-945e-4caf-95c0-3eeae6fdada6
Related MCP server: mcp-autopilot-jobhunt
Get started
pipx install jobwatch # or: pip install jobwatch
jobwatch uiA page opens on your computer and walks you through four short steps: about you and your resume, the jobs you
want, the companies to watch, and (optionally) fit scores and job-alert emails. Then press Check for new
jobs. Install the page as an app from Chrome's address bar to keep it in its own window, or run
jobwatch service install to have it always running on a Mac.
Extras: jobwatch[score] (fit scores with the Claude API), jobwatch[local] (fit scores on-device, Apple
Silicon), jobwatch[mcp] (an MCP server for Claude and other assistants), jobwatch[video] (drill videos for
interview prep). Prefer a terminal? jobwatch init, jobwatch find "Globex", then jobwatch run daily.
More on the page and the command line →
What it does
Watches company boards | Greenhouse, Lever, Ashby, Workable, Workday, Eightfold, Oracle, SmartRecruiters, Rippling, iCIMS, Jobvite, Avature, Google, Amazon and HN's Who is hiring. Fresh roles, real pay ranges, robots.txt respected. Why boards · the watchlist |
Scores fit | Your resume against each posting: must-haves met, gaps, a score out of 100. On the Claude API, Antigravity, or this Mac. Fit scores |
Keeps a short queue | Today's picks, a queue to apply from, job-alert emails and status emails read for you, reposts caught. Applying |
Tracks applications | Every stage, the next step, follow-ups for the ones gone quiet, a calendar feed. Tracking |
Preps interviews | A prep sheet per interview, answers drafted from your own stories, a mock interview, a drill video. Interview prep |
Compares offers | Pay, career value and company health side by side. Comps |
Shows who you know | Your LinkedIn connections at each company, the people you actually talk to first. Who you know |
Answers questions | A chat about today's jobs and each posting, and the skills your matches keep asking for. Chat · Skills |
Works with assistants | An MCP server and an agent skill, so Claude can run your search with you. MCP server |
Everything stays on your computer. The only exception is a model you choose for fit scores and chat: the Claude API or Antigravity get the posting and your resume (and, for drafted interview answers, your stories); on-device models send nothing anywhere.
Why it doesn't auto-apply
Tools that auto-apply to hundreds of jobs make the process worse for everyone and rarely work for the person using them:
Recruiters recognize mass applications.
Some companies cap how many roles one person can apply to.
Application forms ask legal questions (work authorization, export control, signatures) that you answer yourself.
jobwatch's job is to make sure you never miss a role worth applying to, and to spend your time on those. Getting more interviews has what moves an application from the pile to a recruiter's call.
The guide
Everything else, from every watchlist setting to the drill video, is in the guide. Development covers running the tests and making a release. MIT licensed.
Available Tools
30 toolsadd_applicationA
Add a job jobwatch didn't find (a referral, a recruiter, LinkedIn...), so everything is in one place: an application (only after the person has applied themselves), or status queued for one they're considering. A url to one job on Greenhouse, Lever, Ashby, Workable, Workday, Rippling, Google Careers (a .../jobs/results/ link), amazon.jobs (a .../jobs/ link), Oracle Recruiting Cloud (an ...oraclecloud.com/.../sites//job/ link), SmartRecruiters (a jobs.smartrecruiters.com// link), an Avature portal (a .../JobDetail// link) or iCIMS (a .../jobs///job link) or Jobvite (a jobs.jobvite.com//job/ link) is read in full (company and title may be left out). A LinkedIn job link is never read (LinkedIn's robots.txt disallows it): give company and title with it (and text to score it), and it's tracked on the company's own board when the same job is found there. Otherwise give company and title, and text (the posting, pasted) so it can be scored. For a job jobwatch already tracks (it came from get_digest or get_job), use mark_job instead; for the jobs in job-alert emails, import_job_alerts. When it's (maybe) the same opening as one already applied to, queued or skipped, the reply ends with that warning: tell the person.
| Name | Required | Description | Default |
|---|---|---|---|
| url | No | A link to the job: Greenhouse, Lever, Ashby, Workable, Workday, Rippling, Google Careers, amazon.jobs, Oracle Recruiting Cloud, SmartRecruiters, Avature, iCIMS, Jobvite or LinkedIn are read in full; any other link is just kept. | |
| note | No | A note: who referred them, how they found it... | |
| text | No | The posting's text, pasted, when the link can't be read, so it can be scored and prepped. | |
| title | No | The job title; may be left out when url is a job link it can read. | |
| status | No | applied (the default; only once the person has applied themselves), queued for one they're considering, or a later stage such as interviewing. | applied |
| company | No | The company; may be left out when url is a job link it can read. | |
| follow_up | No | A day: YYYY-MM-DD, or +N for N days from today. An empty string clears it. | |
| next_step | No | What happens next ("hiring manager call Friday"). | |
| applied_on | No | The day applied (YYYY-MM-DD), if not today. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations by disclosing that certain ATS links are parsed in full while LinkedIn is never fetched (robots.txt), that company/title may be omitted when a readable link is supplied, and that the reply ends with a duplicate warning that should be relayed to the user. This is exactly the operational 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core purpose, but the long parenthetical enumerating ATS URL shapes duplicates the url parameter description and makes the prose dense and hard to scan. Some of that detail could be trimmed without losing routing value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 9 optional params, an output schema, and annotations, the description covers the decision points (which source, which sibling, duplicate handling, LinkedIn limitation) an agent needs. Minor gap: it doesn't say what the returned warning or created application looks like, though the output schema likely handles that.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3, but the description adds cross-parameter dependencies the schema does not spell out: company and title are optional only when the URL is a readable job link, and text is needed otherwise so the posting can be scored. The link-format parentheticals largely restate the url schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource with scope: 'Add a job jobwatch didn't find (a referral, a recruiter, LinkedIn...)', and immediately contrasts with jobs jobwatch already tracks. An agent can distinguish this from mark_job and import_job_alerts from the description alone.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes: 'For a job jobwatch already tracks (it came from get_digest or get_job), use mark_job instead; for the jobs in job-alert emails, import_job_alerts.' It also clarifies the status semantics (applied only after the person applied). Alternatives and conditions are named, not implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
add_boardAIdempotent
Add a company's board to the watchlist, so fetch_jobs checks it from now on. Find the entry with find_board first and check its sample titles: a guessed board name can belong to another company (list_suggested_boards gives entries for companies whose jobs keep coming in from alerts or HN). Adding one that's already there only updates its name and careers link. For Google, leave name empty: each role keeps its own employer (Google, YouTube, DeepMind). Creates the watchlist when there is none yet. The watchlist is rewritten (a copy of the old one is kept as .bak; comments in a hand-written file are not kept).
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | The company's name as it should show, when the board's own name isn't it (e.g. a Workday tenant id). | |
| entry | Yes | The board as source:board, the way find_board and list_boards give it (e.g. greenhouse:stripe). | |
| careers | No | The company's own careers site (https://...), for a board whose hosted job pages are offline (fetch_jobs warns about those): its jobs then link there. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover the safety profile (idempotent, non-destructive), and the description adds substantial context beyond them: the watchlist file is rewritten, an old copy is kept as .bak, hand-written comments are lost, and the watchlist is created if absent. That is exactly the side-effect disclosure an agent needs before mutating a file.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is front-loaded in the first clause, and every following sentence carries a distinct rule or edge case. It is dense and slightly parenthetical-heavy, but no sentence is filler given the tool's real complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 3-parameter write tool with no output schema, it covers the full lifecycle: precondition lookup, dedupe behavior, the special-case parameter value, file-creation, and the destructive aspect of the rewrite. Nothing material to correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3; the description earns extra by adding behavioral meaning to 'name' (leave it empty for Google because each role keeps its own employer) and by linking 'entry' to how find_board/list_boards present it. The 'careers' parameter is left to the schema alone.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource+consequence: 'Add a company's board to the watchlist, so fetch_jobs checks it from now on.' That downstream effect cleanly distinguishes it from read-side siblings like list_boards and find_board.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the agent: find the entry with find_board first and inspect sample titles, with a stated failure mode (a guessed board name can belong to another company) and a pointer to list_suggested_boards for alert/HN-sourced candidates. Duplicate handling and the Google no-name case are both covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
check_postingsAIdempotent
Check that the postings of queued jobs and open applications still take applications, and record the ones that closed or came back. result is open, closed, reopened, or unknown (check it yourself); an open job's detail may say its board's hosted pages are offline and where to apply instead. Run it before working through list_queued_jobs, so time isn't spent on closed postings.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare openWorldHint=true, idempotentHint=true, and readOnlyHint=false, so the agent knows this touches an external system and mutates recorded state. The description adds real context beyond that: it records closed/reopened postings, returns open/closed/reopened/unknown, warns that 'unknown' must be checked manually, and notes an open job may be offline with a redirect. These details are not present in the annotations and materially help interpretation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with the core action and result, with the usage guidance placed last. It is dense and uses semicolons for clauses, which is slightly less scannable than ideal, but every sentence carries information and there is no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With zero parameters, an output schema already present, and annotations covering the safety/network profile, the description supplies the remaining crucial context: what it does, which result values appear, and when to run it relative to list_queued_jobs. It is essentially complete for this tool's complexity, with only minor room to clarify the re-check behavior for 'unknown' results.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the description carries no parameter-semantics burden and the baseline of 4 applies. There is nothing malformed or misleading about the parameter story.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific action on a specific resource: checking whether postings of queued jobs and open applications still accept applications, and recording closed/reopened ones. It also implicitly separates itself from list_queued_jobs by defining the validation role rather than the listing role. The verb 'check' is slightly generic, so it stops short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit sequencing guidance: 'Run it before working through list_queued_jobs, so time isn't spent on closed postings,' which tells the agent when this tool belongs in a workflow and names the sibling it precedes. It lacks an explicit when-not-to-use or a fully enumerated set of alternatives, 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.
dismiss_suggested_boardAIdempotent
Stop suggesting a company in list_suggested_boards, when the person doesn't want to watch it. Its jobs stay tracked. To watch one instead, use add_board with its add_board arguments.
| Name | Required | Description | Default |
|---|---|---|---|
| company | Yes | The company as list_suggested_boards names it (any case; Inc, LLC and the like aside), or its board. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare this as a non-read-only, non-destructive, idempotent write, so the safety profile is covered. The description adds a genuinely useful side-effect note ('Its jobs stay tracked'), clarifying that jobs are not removed when the suggestion is dismissed. It stops short of disclosing the response shape, though an output schema exists.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences, front-loading the core action and side effect before the routing hint. The trailing phrase 'with its add_board arguments' is slightly redundant and awkwardly worded, costing a point.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values need not be described, and annotations plus the schema carry the param and safety detail. The description completes the picture with routing and side-effect context; only the exact effect on the suggestion list versus the board itself is left implicit.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with a single required parameter, and the schema already spells out case-insensitivity, name-vs-board acceptance, and suffix handling. The description's reference to 'a company in list_suggested_boards' echoes rather than extends that. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Stop suggesting') and resource ('a company in list_suggested_boards'), tying the action directly to the sibling list whose results it affects. An agent can distinguish it from add_board, remove_board, and the other board tools without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives the triggering condition ('when the person doesn't want to watch it') and names the opposite-path alternative ('To watch one instead, use add_board'). The when-to-use and the when-to-use-something-else are both explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fetch_jobsAIdempotent
Check every board in the watchlist and record new roles. Returns counts, each board that failed to load (skipped; the rest are still recorded), and warnings: a board whose hosted job pages are offline while its jobs are still listed, which needs the company's careers site (add_board with careers). Run it before get_digest, which lists the new roles themselves.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnlyHint=false, idempotentHint=true, destructiveHint=false, openWorldHint=true), and the description adds genuine behavior beyond them: partial-failure semantics (failed boards are skipped while the rest are still recorded) and the meaning of the offline-board warning. This failure-mode disclosure is exactly the extra context annotations cannot carry.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action and every clause carries information (counts, failures, warnings, sequencing). It is dense and parenthetical-heavy, which slightly hurts readability, but nothing is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Because an output schema exists, return values need not be spelled out, yet the description covers side effects, partial-failure handling, warning meaning, and the downstream call. Complete enough for an agent to invoke correctly; idempotency behavior could be made more explicit but is not essential.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the schema needs no supplementation and the baseline is 4. The description correctly avoids inventing parameter talk where none exists.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource and scope: 'Check every board in the watchlist and record new roles.' It explicitly distinguishes itself from the sibling get_digest ('which lists the new roles themselves'), so an agent can separate the two without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear sequencing ('Run it before get_digest') and names the correct alternative for the offline-board warning case (add_board with careers). It does not state when not to run it, but the ordering and follow-up conditions are explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_boardARead-onlyIdempotent
Find a company's job board by name or by a job/careers link. Returns entries for the watchlist. A guessed board name can belong to another company: check the sample titles before adding one. Google (with YouTube and DeepMind) is one board, google:google (its US roles; google:google/any for all). So is Amazon (with AWS), amazon:amazon (its US roles; amazon:amazon/any for all). A Workday, Oracle Recruiting Cloud or Jibe board that isn't found by name is found from a link to a job on it. An Avature careers portal is host/portal (avature:careers.initech.example/careers); a name finds one only at name.avature.net/careers, so give a job link from any other. An iCIMS careers site is icims: (careers-.icims.com), or the whole host for another (icims:jobs-acme.icims.com); a name finds one at careers-.icims.com. A Jobvite careers site is jobvite: (jobs.jobvite.com/); a name finds one there. Hacker News' "Who is hiring?" thread is one board, hn:whoishiring (hn:whoishiring/N: the last N months'), found by "Hacker News" or the news.ycombinator.com/submitted?id=whoishiring link. Use it before add_board; to track one job from its link, use add_application instead.
| Name | Required | Description | Default |
|---|---|---|---|
| company | Yes | A company name ("Stripe"), or a link to one of its job postings or its careers page. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare this is a read-only, idempotent, open-world lookup, and the description adds substantial behavioral context: guessed names can belong to another company, sample titles should be checked, and several provider families require a job link rather than a name. These matching quirks go well beyond the annotations without contradicting them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long, but the density is justified by the many provider-specific lookup rules and examples. It is front-loaded with the core purpose and caution, though the provider details could be more scannable if structured as bullets.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description need not explain return values, and it covers the complex matching behaviors an agent needs before calling the tool. The annotations and schema are supplemented rather than repeated.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema documents the single company parameter at 100% coverage, but the description adds meaningful accepted forms and provider-specific syntax, such as avature:host/portal/careers, icims:<company>, jobvite:<company>, and hn:whoishiring. It tells the agent when a company name will work and when a link is required.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: find a company's job board by name or job/careers link, and says it returns watchlist entries. It also distinguishes this lookup from add_board and add_application, so an agent can route correctly among siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly says to use this before add_board, and to use add_application instead when tracking one job from its link. It further gives concrete when-to-use-link guidance for Workday, Oracle Recruiting Cloud, Jibe, Avature, iCIMS, and Jobvite boards.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_duplicatesARead-onlyIdempotent
Jobs tracked twice: pairs of tracked jobs, open or closed, where the person queued, applied to or skipped one and the other is the same opening (strong: a shared req or posting id, from a title, note, posting text or link; why says which, "reposted as req ..." for a repost) or maybe the same (why "same title": check it's a different opening). The same opening first, applications first. Each: why, strong, and both jobs (key, company, title, status, date, closed), the one acted on first. Read-only: the person decides what to skip (mark_job). For one job, get_job's duplicate_of says the same.
| Name | Required | Description | Default |
|---|---|---|---|
| strong_only | No | Only pairs that share a req or posting id (the same opening), not the same title alone. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is covered. The description adds useful context beyond that — that resolving duplicates is the person's call via mark_job, and that get_job surfaces duplicate_of for one job — but says little about ordering guarantees or output volume beyond the field list.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is a single run-on paragraph mixing the definition, the strong/maybe distinction, output shape, and sibling references. Content is relevant but not front-loaded or structured, making it 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.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be spelled out, yet the description still sketches the per-pair payload (why, strong, both jobs with key/company/title/status/date/closed). Combined with the strong/maybe distinction and the mark_job handoff, an agent has what it needs to call this correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3, but the description meaningfully elaborates the single parameter by defining what 'strong' means (a shared req or posting id) versus 'same title alone', which is exactly what strong_only filters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific outcome: pairs of tracked jobs that are the same opening, with a distinction between 'strong' (shared req/posting id) and 'maybe' (same title) matches. It is distinguishable from siblings like get_job or check_postings, though it opens with a dense clause rather than a crisp verb+resource statement.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied rather than spelled out: it notes 'the person decides what to skip (mark_job)' and that get_job's duplicate_of covers a single job, which hints at when to use this vs get_job. But there is no explicit when-to-use/when-not statement or prerequisites for invoking it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_past_answersARead-onlyIdempotent
Form answers the person gave on earlier applications (kept by save_application_package), newest application first: key, company, title, applied, question and answer; without a query each question once, with asked (how many applications had it). Use it before filling a form, to reuse what was answered to "reason for leaving", "notice period" or "salary" instead of writing it again; for everything sent with one application use get_application_package.
| Name | Required | Description | Default |
|---|---|---|---|
| query | No | Words of the question to look for ("notice period", "reason leaving"): every word must be in the question, any case. Empty lists each distinct question once, with its latest answer. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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 genuine context beyond that: results are newest-application-first, sourced from save_application_package, and without a query the tool collapses to one row per distinct question with an 'asked' count. It says nothing about result caps or pagination, which is the only gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with what the tool returns before the routing advice, and every clause carries information. The semicolon-chained sentence is dense and takes a second pass to parse, which keeps it from a 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With one optional parameter, an output schema, and rich annotations, the description covers provenance, ordering, dedupe behavior, and the sibling alternative. An agent has enough to call it correctly; only edge cases like result limits are unaddressed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds matching semantics beyond the schema: all query words must appear in the question, matching is case-insensitive, and the empty-query behavior returns one row per distinct question with its latest answer.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: retrieves form answers the person gave on earlier applications, and enumerates the returned fields (key, company, title, applied, question, answer). It also explicitly distinguishes itself from get_application_package, which covers everything sent with a single application.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit when-to-use trigger ('before filling a form') with concrete examples of the questions to reuse ('reason for leaving', 'notice period', 'salary'), and routes the agent to the alternative sibling (get_application_package) for the other case.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_application_packageARead-onlyIdempotent
What was sent with an application: files kept (with their folder), form answers, note, and the day the posting was saved as it read then (posting.md in the folder). Use it to check exactly what was sent; for a full prep sheet use get_interview_prep, and for the posting and fit use get_job.
| Name | Required | Description | Default |
|---|---|---|---|
| key | Yes | The job: its key as other tools return it (source:board:posting id, e.g. greenhouse:acme:4012345), just the posting id, or the company's name when that names one job (the one queued or applied to there). When it matches several, the error lists their keys. |
TDQS
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 genuine behavioral context beyond that: the returned posting is a frozen snapshot ('as it read then'), which tells the agent this is not live data and that a file artifact (posting.md) exists. It does not describe the multi-match error path, though the schema does.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the payload contents followed by the routing guidance, with no filler. The first sentence is a dense list, but every element is load-bearing.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With one well-documented parameter, no output schema, and full annotation coverage, the description supplies precisely what is missing: the shape of the return payload and the frozen-snapshot semantics. Nothing an agent needs to call it correctly is absent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the single 'key' parameter is documented in detail there (formats, fallback to company name, multi-match behavior). The description adds no parameter-level meaning, so the baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description enumerates exactly what the tool returns (files with their folder, form answers, note, the frozen posting.md) and frames it as the application package snapshot. It explicitly differentiates itself from get_interview_prep and get_job, so an agent can pick it without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Use it to check exactly what was sent' states the positive trigger, and the two named alternatives each come with their own condition ('full prep sheet' -> get_interview_prep, 'posting and fit' -> get_job). This is explicit when/when-not/alternative routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_companyARead-onlyIdempotent
Everything tracked at one company, whatever the status of its jobs (new, queued, applied, screening, interviewing, offer, rejected, withdrawn, skipped) and open or closed. company, counts (jobs by status), and jobs: each with key, title, status, posted, applied_at, closed, next_step, follow_up, due, note, package (what was saved: files, answers, note) and duplicate_of (see get_job); contacts: people the user knows there, with find_referral, a LinkedIn search for someone who could introduce them; watch: whether the company's board is on the watchlist and, when it isn't, add_board (the entry and name to pass add_board) and command. Closed postings never acted on are only counted (closed_unacted), so are open ones not acted on that the filters leave out (left_out, with left_out_by: filter -> count) unless every_role, and the other open ones not acted on are listed up to 25 (more_open). also names other companies the name matched. Returns an error when none matches. Use it when the person names a company and you don't know which stage it's at; for one job's full text, fit and prep use get_job, for every application list_applications, and for all jobs of one status list_jobs.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | A company's name ("Acme Robotics"), part of it ("acme"), or its domain ("acme.com"); case, punctuation and suffixes such as Inc don't matter. | |
| every_role | No | Also list the open roles the filters leave out (other cities, low pay...). Default: the watchlist's display.company setting (matches: only the roles Today's filters pass). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only/idempotent/non-destructive, but the description adds substantive behavior beyond them: an error when nothing matches, name-matching against other companies, a 25-item cap with a more_open remainder, closed_unacted counting, and left_out_by filter attribution. These are exactly the edge cases an agent must anticipate 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose and routing are front-loaded in the first clause and the closing sentence, and nearly every fragment carries information. However, the middle is a dense telegraphic run-on ('left_out, with left_out_by: filter -> count', 'watch: ... and command') that is 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.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema and no nested objects, the description carries the full burden of explaining return shape and does so field by field (counts, jobs fields, contacts, watch/add_board, truncation buckets). 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.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents name and every_role. The description reinforces every_role's consequence (left_out/left_out_by appear unless every_role) but adds no syntax or format detail beyond the schema — the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a specific resource and scope: 'Everything tracked at one company' across all job statuses and open/closed, then enumerates the returned sections (counts, jobs, contacts, watch). It explicitly distinguishes itself from get_job, list_applications and list_jobs, so an agent can route correctly without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit trigger ('when the person names a company and you don't know which stage it's at') plus three named alternatives with their selecting conditions (get_job for one job's full text/fit/prep, list_applications for every application, list_jobs for one status). 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.
get_compsARead-onlyIdempotent
Open applications side by side, to compare offers and processes: for each, its stage, applied day, next step and follow-up, pay as posted, places, fit score (must-haves met, top gaps), people the person knows there, and the compensation details they were told (base, bonus, equity, sign-on, asked, offered, note; set them with set_comp), and the company's health (set it with set_company_health; stale when older than 90 days: research it again). best says which opportunity is highest in posted pay, base, offered and fit. suggestion ranks them by rules (career value from the company's kind and the job's role, pay against the person's target, fit, how far along, company health) with the weights, each part's score and input, and a reason: explain it, and say what is missing (no health kept, no kind or role, no pay known) rather than guessing. Use it when the person asks how their opportunities compare; for one application's status use list_applications.
| Name | Required | Description | Default |
|---|---|---|---|
| keys | No | Compare just these jobs (each as in get_job's key), whatever their stage. Overrides stages. | |
| stages | No | Which stages to compare; default screening, interviewing and offer. Add applied for the ones still waiting. | |
| companies | No | Add these companies' health as columns of their own, even ones with no job tracked (Levels.fyi-style company comparison). Overrides stages. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the read-only, idempotent, closed-world profile, and the description builds on that with real behavioral context: a 90-day freshness rule, a directive to report missing inputs rather than guess, and the semantics of the derived 'best' and 'suggestion' fields (weights, per-part scores, reasons). It duplicates a bit of the schema's default/precedence behavior, and never says how many items are compared or what the response looks like structurally.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The lead clause is well front-loaded, but the body is a single sprawling run-on sentence whose long parenthetical chains (comp fields, ranking inputs) are hard to parse, and the crucial 'when to use' guidance is buried at the end.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description must carry the return-value burden, and it does: it names the compared fields, the 'best' ranking basis, and the 'suggestion' breakdown including weights, sub-scores and reasons. What's missing is scale/limits (how many opportunities are included, whether nulls produce empty columns) for a tool whose output shape is otherwise undocumented.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and each of keys/stages/companies already carries a precise description including the 'overrides stages' precedence, so the schema does the heavy lifting. The description adds no parameter-level detail beyond that (no format for keys, no cap on list size), so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb and resource — 'Open applications side by side, to compare offers and processes' — then enumerates exactly what is compared (stage, applied day, next step, pay, fit score, contacts, comp, company health). It explicitly contrasts itself with list_applications, so an agent can separate it from sibling read tools without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
States the triggering condition ('Use it when the person asks how their opportunities compare') and names the alternative for the adjacent case ('for one application's status use list_applications'). It also routes related writes to set_comp and set_company_health, and says to re-research health older than 90 days rather than reporting stale data.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_digestA
New jobs that pass the watchlist's filters, best first (fit score when scored, then keyword relevance), with people the user knows at each company. Call fetch_jobs first to pick up today's postings. This is for finding jobs to consider; for jobs already queued use list_queued_jobs, and for applications use list_applications. total is how many matched before the limit (jobs left out stay new for the next digest). not_scored, when set, says why a job is never fit-scored (a Hacker News post listing several roles). pace, unless the user turned it off: applications sent today against how many they aim for a day (daily) and the most (max); once met, suggest the rest wait for tomorrow, but never refuse to help.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | The most jobs to return, best first. Default: the watchlist's display.today (10 unless set; 25 when it's 0, for every match). | |
| score_top | No | How many of the most relevant unscored jobs to fit-score against the resume with shortlist-ai first. 0 (the default) skips scoring; each job takes minutes on the local backend, so keep it small. | |
| mark_shown | No | Mark the returned jobs as shown, so the next digest leaves them out. False to peek without changing anything. | |
| include_seen | No | Also include jobs already shown in an earlier digest, not just new ones. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare non-read-only, open-world, non-idempotent, non-destructive; the description is consistent with these and adds substantive behavior beyond them: jobs left out stay new for the next digest, total counts matches before the limit, not_scored explains why a job is never scored, and the pace object's daily/max semantics. It does not state permissions or a return shape explicitly, but the behavioral context is strong.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Information-dense and front-loaded with the return/ordering rule, then routing, then edge cases. Every clause carries weight, though the pace sentence is long and slightly buries the practical takeaway.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description must carry return semantics, and it does: total, not_scored, and pace are all explained. For a filtered, side-effecting digest tool with annotations covering the safety profile, this is nearly complete; only explicit auth/permission context is absent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents all four parameters, including defaults, the display.today rule for limit, and the per-job scoring cost for score_top. The description only gestures at the limit ('matched before the limit') and adds no parameter syntax beyond what the schema provides, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource (a digest of new jobs that pass the watchlist's filters) and its ordering rule (fit score, then keyword relevance). It explicitly distinguishes itself from list_queued_jobs and list_applications, so an agent can route correctly without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use ('finding jobs to consider'), a prerequisite ('call fetch_jobs first to pick up today's postings'), and named alternatives for adjacent intents (list_queued_jobs, list_applications). It also encodes the pace rule, including the 'never refuse to help' guardrail.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_interview_prepARead-onlyIdempotent
A prep sheet for a recruiter call or interview: stage and next step, each requirement and responsibility in the posting next to the closest resume line (quoted, never written), gaps to be honest about, what was sent, questions to expect and to ask, and the posting. For an application added by hand, the posting is found on a watched board by its requisition id. markdown is the sheet ready to read. Also: brief, the company as the posting and the person's own notes tell it (about: the posting's lines; facts; notes; contacts: people they know there; source), nothing looked up elsewhere, so say it's from the posting; pay, the posted range (posted, posted_min, posted_max), the person's target (target, and target_max when it's a range) and how it sits against the range (target_note); and role_questions, questions for this role written from the posting's asks (questions_note says where they came from; empty: expect's generic questions stand). The person's private pay floor is never returned here (pay.floor_withheld says one is set): don't ask for it or guess it. With draft_answers, drafted holds the drafted questions and draft_note how they were made, or why there are none. practised holds the answers the person kept from mock interviews (jobwatch ask --job KEY --mock): question, answer as they said it, and improved, the tightened version built from their own words and stories. Present a drafted answer as the person's only where it cites their stories. story_gaps lists what a story would help with (ask, why): asks with nothing close on the resume, drafted questions with no story yet, missing must-haves; to fill one, interview the person and keep what they confirm with save_story. Use it before a call; get_job and get_application_package give the raw pieces.
| Name | Required | Description | Default |
|---|---|---|---|
| key | Yes | The job: its key as other tools return it (source:board:posting id, e.g. greenhouse:acme:4012345), just the posting id, or the company's name when that names one job (the one queued or applied to there). When it matches several, the error lists their keys. | |
| draft_answers | No | Also have jobwatch's own model (the chat's backend) draft 6-10 questions likely for this role, each with the ask it probes and an answer outline built only from the person's story file and resume, citing the story ids used; one with no story says so (no_story) with an honest angle. Invented story ids and numbers are taken out before they're returned. Slow the first time, then kept. With the claude backend the posting, resume and stories go to Anthropic. False is rule-based and instant. | |
| role_questions | No | Also have jobwatch's own model (the chat's backend) write questions for this role from the posting's asks (role_questions), without answers. Only the posting goes to the model, and to Anthropic with the claude backend. Slow the first time, then kept; questions saved earlier are always returned. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive, closed-world), and the description layers on substantial extra behavior: the private pay floor is deliberately never returned (pay.floor_withheld), resume lines are quoted and never written, invented story ids/numbers are stripped before return, and the model-backed modes send posting/resume/stories to Anthropic under the claude backend and are cached after a slow first call.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose is front-loaded in the first sentence, but the body collapses into megasentences and fragment lists joined by colons and semicolons, making it taxing to parse. Nearly every clause carries information, so there is little true filler, but the structure is poor for an agent skimming for a decision.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description must carry the return shape itself, and it does: it covers the sheet contents, brief, pay (posted/target/target_note), role_questions, drafted answers, practised answers, and story_gaps with the follow-up tool (save_story). A complex multi-mode tool is described completely enough to invoke correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description goes beyond the schema by describing what each optional flag produces: draft_answers yields drafted/draft_note or an explanation for none, practised returns kept mock answers with an improved version, and role_questions falls back to generic expect questions when empty. It clarifies output semantics of the flags rather than just restating them.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening clause states a specific verb+resource (a prep sheet for a recruiter call or interview) and then enumerates exactly what the sheet contains. It also explicitly distinguishes itself from siblings by noting that get_job and get_application_package give the raw pieces this tool assembles.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
"Use it before a call; get_job and get_application_package give the raw pieces" gives a clear use moment and names the alternatives for a different need. It falls short of 5 because it never states when this tool is unnecessary or the prerequisite state of the job (e.g. applied vs queued), leaving some routing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_jobARead-onlyIdempotent
Everything about one job, by key or posting id: the full posting text, pay, tracking (status, note, next step, follow-up), its fit score against the resume (score, must-haves met, gaps, and requirements: each requirement with its verdict, met/partial/not_met, and the resume's words backing it; scores saved before jobwatch kept these have none), people the user knows there plus a LinkedIn search for a referral, skills it asks for that the resume doesn't show, what was sent with the application, and candidate_home: the company's page where the person signs in to see the application's status (Workday only; each company has its own account). link_note, when set, says the board's hosted job pages are offline and where to apply instead (url is then the company's careers site, when the watchlist gives one). With no fit score, unscored_reason says why ({code, text}: no_text means it needs its posting, a link via mark_job(url=) or the text pasted; queued means it's in the page's background scorer's line; many_roles, a post listing several roles, is never scored). duplicate_of is the job already applied to, queued or skipped that this one is (maybe) the same opening as: key, title, status, date, why, strong (a shared req or posting id; false: the same title only, so check it's a different opening), reposted, and text, the warning to heed; null when there's none. Check it before drafting a referral request or an application. Use it to tailor a resume or decide whether to apply; for only what was sent use get_application_package, and for a call or interview use get_interview_prep.
| Name | Required | Description | Default |
|---|---|---|---|
| key | Yes | The job: its key as other tools return it (source:board:posting id, e.g. greenhouse:acme:4012345), just the posting id, or the company's name when that names one job (the one queued or applied to there). When it matches several, the error lists their keys. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive, closed-world), but the description adds real behavior not visible there: the duplicate_of warning and its 'strong vs same-title-only' caveat, unscored_reason codes, link_note meaning that board pages are offline, and candidate_home being Workday-only with per-company accounts. That is genuine context beyond the annotations, though it reads more as return-field documentation than tool behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The leading clause is well front-loaded, but the remainder is one dense run-on of nested parentheticals with no paragraphing or list structure. The length is defensible because there is no output schema to carry the field semantics, but the wall-of-text delivery makes it hard to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the full burden of explaining what comes back, and it does so exhaustively: fit score, requirements verdicts, tracking fields, duplicate_of, unscored_reason, candidate_home. An agent knows exactly what to expect from a call.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the single 'key' parameter is fully documented in the schema, including the source:board:posting-id format and the multi-match error behavior. The description only restates 'by key or posting id', adding no syntax or format detail beyond what the schema provides, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource+scope: 'Everything about one job, by key or posting id.' It then explicitly distinguishes itself from the two closest siblings (get_application_package for what was sent, get_interview_prep for a call or interview), so an agent can pick it apart without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete when-to-use guidance ('Check it before drafting a referral request or an application. Use it to tailor a resume or decide whether to apply') and names the alternatives with their selecting conditions. 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.
import_job_alertsAIdempotent
Track the jobs in job-alert emails (LinkedIn, Built In, Indeed; other senders with a generic reader). Search the person's mail for them first, e.g. from:jobalerts-noreply@linkedin.com, from:builtin.com, from:jobalert.indeed.com, and pass each message in; jobwatch never needs a mail password. Links lose their tracking parameters. Each job whose title, place and pay pass the watchlist's filters is looked for on the company's own board (a link to a supported board is read from there); job sites' pages are read only when their robots.txt allows (LinkedIn's and Indeed's don't, so the email's details are used). Jobs already tracked are left alone (known); new ones show up in get_digest, with via saying where they came from. Returns counts and each job: key, result (new, known, duplicate: twice in these emails), how (board, posting, page or email), filtered (why the filters leave it out of the digest, or null) and duplicate_of (the job applied to, queued or skipped that it's maybe the same opening as, as get_job gives it, or null). For emails about the person's applications (confirmations, rejections, interviews), use read_status_emails.
| Name | Required | Description | Default |
|---|---|---|---|
| emails | Yes | The alert emails, one string each: the raw message (RFC822, as a mail connector's raw format gives it, base64url-encoded as from Gmail's API is fine too; best, since it names the sender) or just its HTML or plain-text body. | |
| dry_run | No | Say what would be tracked, and record nothing. | |
| follow_links | No | Look for each job that passes the filters on the company's own board, and read links robots.txt allows. False tracks each job as the email has it, with no requests. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Far exceeds what the annotations convey: it discloses that no mail password is needed, that tracking parameters are stripped, that robots.txt governs page reads (with the concrete LinkedIn/Indeed exception), the dedup rule ('jobs already tracked are left alone'), and where new jobs surface (get_digest, with 'via'). This is rich behavioral context consistent with the idempotentHint and non-destructive write profile.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is front-loaded and the trailing detail (robots.txt, results, alternative tool) is genuinely useful rather than filler. However, it is a dense run-on with heavy parenthetical nesting and no paragraph breaks, which hurts scannability.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the burden of explaining returns and does so thoroughly (counts, plus key/result/how/filtered/duplicate_of per job) and covers the destination tool for further action (get_digest). Nothing an agent needs to invoke and interpret this tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the three parameters (emails, dry_run, follow_links) are already well documented. The description reinforces the effect of follow_links ('Links lose their tracking parameters', board lookup behavior) but adds little parameter-level meaning beyond what the schema states, so the baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Track the jobs in job-alert emails') and enumerates the sources supported (LinkedIn, Built In, Indeed, generic reader). It explicitly distinguishes itself from the sibling read_status_emails, which handles application emails, so an agent can route correctly without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete when-to-use guidance with example mail search queries (from:jobalerts-noreply@linkedin.com, etc.) and instructs to pass each message in. It also names the alternative tool for a different email class ('For emails about the person's applications... use read_status_emails'), satisfying explicit when/when-not/alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_applicationsARead-onlyIdempotent
Every application (applied or a later stage) and where it stands, follow-ups due soonest first; candidate_home is the company's page for checking its status, when it has one (Workday). Use it to see what needs a follow-up; for jobs not applied to yet use list_queued_jobs, and for any status use list_jobs. quiet is set on an application with no stage change or note for weeks (the watchlist's quiet: days per stage): days, since, posting_open, long (quiet so long that it sorts below the fresher ones), move (nudge: a short check-in to the recruiter or a contact, or close: likely closed, ask the person whether to mark it rejected or withdrawn; never change it on your own), advice, and contacts the person knows there.
| Name | Required | Description | Default |
|---|---|---|---|
| due_only | No | Only those whose follow-up day has come. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent), yet the description adds real behavioral context: results sort follow-ups due soonest first, candidate_home only exists for some companies (Workday), and the 'move' field must never be changed by the agent ('never change it on your own'). That constraint materially changes agent behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose and routing, which is good, but the back half sprawls into an inline glossary of output fields (quiet, days, since, posting_open, long, move, advice, contacts) in a single run-on paragraph. An output schema exists, so some of that enumeration is redundant bulk.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter read tool with an output schema, the description is more than sufficient — it covers routing, sort order, and a behavioral constraint. It over-delivers by explaining return fields that the output schema already carries, which is waste rather than a gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% for the single due_only parameter, so the schema fully documents it and the baseline is 3. The description hints at the due-filtering concept ('follow-ups due soonest first') but adds no syntax or default detail beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource with scope: 'Every application (applied or a later stage) and where it stands.' It explicitly distinguishes itself from list_queued_jobs and list_jobs, so an agent can route without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use ('see what needs a follow-up') plus two named alternatives with their selection conditions: list_queued_jobs for not-yet-applied jobs, list_jobs for any status. Nothing left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_boardsARead-onlyIdempotent
The boards on the watchlist (entry, display name, careers: the board's own page, careers_link: the company's own careers site when the watchlist gives one) and where the watchlist file is. Use it to see what fetch_jobs checks; add_board and remove_board change it.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint=false, so the safety profile is covered. The description adds value beyond them by disclosing the shape of what comes back (board entry, display name, careers, careers_link) and the fact that a watchlist file backs this data — information 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
One dense sentence that front-loads the core purpose, with the parenthetical field glossary and the alternative-tool note following. The nested parenthetical is slightly clunky, but every clause carries information and nothing is redundant.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema and no parameters, the description carries the return-value burden and does describe the notable fields plus the watchlist file location. It leaves ordering, count, or file-format details unspecified, but that is minor for a zero-argument read of a small local list.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is nothing for the description to disambiguate and the baseline of 4 applies. The schema is an empty object with full coverage, and no parameter-level detail is needed or missing.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (list the boards on the watchlist) and then enumerates the returned fields — entry, display name, careers page, careers_link. It also explicitly separates itself from add_board, remove_board and fetch_jobs, so an agent can pick it without opening any other schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
"Use it to see what fetch_jobs checks; add_board and remove_board change it" gives a clear use context and routes mutations to the sibling tools. It stops short of an explicit when-not or a statement of prerequisites, but the alternative is named and the selection condition is implied strongly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_jobsARead-onlyIdempotent
Tracked jobs with their tracking fields, newest first, including closed postings. A plain list by status (e.g. every skipped job); for ranked new jobs use get_digest, for the next to apply to list_queued_jobs, and for follow-ups list_applications.
| Name | Required | Description | Default |
|---|---|---|---|
| status | No | Only jobs with this status; omit for all. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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 genuine behavioral context with 'newest first' ordering and the fact that closed postings are included, which is non-obvious for a job list. Pagination/limits are not addressed, but an output schema exists to carry return-shape details.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, zero filler; the core behavior (untracked plain listing) is front-loaded before the disambiguation list. Every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With annotations covering safety, a 100%-covered single enum parameter, an output schema handling return values, and clear sibling routing, 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.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the sole status parameter is fully described with its enum in the schema, so the baseline is 3. The description adds meaning by illustrating the filter's intent ('a plain list by status, e.g. every skipped job'), clarifying that it is an unranked equality filter rather than a relevance query.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('tracked jobs'), plus scope qualifiers: newest-first ordering, inclusion of closed postings, and 'tracking fields'. It actively distinguishes itself from sibling list tools rather than restating the name.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly names three alternatives (get_digest, list_queued_jobs, list_applications) with the condition that selects each, and adds a plain-list use case ('every skipped job'). An agent can route without opening any schema.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_queued_jobsARead-onlyIdempotent
Jobs queued to apply to, oldest first, with fit scores, notes, people the user knows there (ask them for a referral before applying) and warnings to check first (pay, place, flagged text). The first warning, and duplicate_of, say when it's (maybe) the same opening as one already applied to, queued or skipped: read them before asking anyone for a referral. Use it to pick the next application; jobs get here through mark_job with status queued. For applications already sent use list_applications.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent and non-destructive, so safety is covered; the description adds ordering ('oldest first') and, more valuably, the meaning of the first warning and duplicate_of as a duplicate-opening signal. It does not mention pagination or limits on the queued list, so it stops short of full behavioral disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The key routing information is front-loaded and every sentence carries content, but it is a single dense paragraph mixing return-field inventory, referral workflow advice and sibling routing. Slightly sprawling for a no-argument list tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description need not enumerate return fields, yet it still supplies the interpretive semantics an agent needs (warnings, duplicate_of) plus routing to list_applications. 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.
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 correctly avoids inventing any argument semantics. Nothing further is required here.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a concrete resource and scope ('Jobs queued to apply to, oldest first') and explicitly contrasts itself with list_applications for applications already sent. An agent can distinguish it from list_jobs and list_applications without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It states the decision context ('Use it to pick the next application'), how jobs arrive here ('jobs get here through mark_job with status queued'), and names the alternative for the other case ('For applications already sent use list_applications'). Both when-to-use and when-to-use-something-else are covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_skill_gapsARead-onlyIdempotent
Skills today's matching jobs and the person's applications ask for, most in demand first, each with on_resume, how many jobs mention it, how many scored jobs list it as a missing must-have, and ways to learn it: curated courses and certifications (official pages, each with a rough time and whether it fits the timeline) and searches on Coursera, LinkedIn Learning, edX and nearby colleges. Also fit-score gaps no course closes (clearance, citizenship, degree, travel). Recommend only from these links; never suggest claiming a skill the resume doesn't show. For one job's gaps use get_job; to prepare for a call use get_interview_prep.
| Name | Required | Description | Default |
|---|---|---|---|
| timeline | No | How soon the person wants to close a gap: week, month, quarter or any. Omit for the watchlist's learning.timeline. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish readOnly/idempotent/non-destructive, so the bar is lower, and the description adds real value: it discloses the return shape (counts, on_resume flags, missing must-haves, fit-score gaps no course closes) and an agent-facing behavioral rule about not recommending unsupported skills. It does not cover pagination or result-size limits, which keeps it short of a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The opening is well front-loaded with what the tool returns, but the middle is a sprawling run-on with nested parentheticals enumerating output fields and every learning platform (Coursera, LinkedIn Learning, edX, nearby colleges). The detail is defensible given there is no output schema, but the structure is dense enough that an agent must parse several clauses to find the routing guidance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description correctly carries the burden of describing the return payload and does so thoroughly, and read-only annotations cover the safety profile. What remains thin is the timeline parameter's behavior when omitted (it defers to the watchlist's learning.timeline without explaining the effect).
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There is a single optional parameter whose enum and default are fully documented in the schema (100% coverage), so the schema does the heavy lifting. The description only indirectly references it ('whether it fits the timeline') without adding format or defaulting behavior beyond what the schema already states; baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a precise verb+resource (list skill gaps across the person's matching jobs and applications) and immediately specifies the ordering ('most in demand first') and the per-skill payload (on_resume, job counts, missing must-haves, learning links). It explicitly separates itself from get_job and get_interview_prep, so an agent can route correctly without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It states the scope (all matching jobs and applications, aggregated) and names two concrete alternatives with the condition that selects each: 'For one job's gaps use get_job; to prepare for a call use get_interview_prep.' It also states a hard usage constraint ('Recommend only from these links; never suggest claiming a skill the resume doesn't show').
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_suggested_boardsAIdempotent
Companies to watch: those whose jobs came in from job-alert emails (import_job_alerts), add_application or posts in HN's Who is hiring thread (fetch_jobs, when it's watched) while their board isn't on the watchlist, ranked by how many of their jobs pass the watchlist's filters, recent ones counting more. Each: company, matching_jobs, last_seen, board (source:board, or null), board_found (posting: one of its jobs is on that board, or its HN post links to it; name: found under its name, so check with find_board's sample titles that it's theirs), careers, sample_titles, and add_board: the arguments to pass to add_board to watch it (null when no board was found: find_board with a link to its careers page may find one). dismiss_suggested_board stops suggesting one. rescan picks up HN posts kept before (see its description). Suggest; let the person decide which to add.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | The most companies to return, best first. Omit for the watchlist's suggestions.limit (10 unless set). | |
| rescan | No | First note the companies of the HN posts already kept (still open) that pass the filters: after the filters change, or for posts fetched before they were noted. Reads nothing from the web; safe to repeat. | |
| look_up_boards | No | Look for the board of each listed company that hasn't been looked for yet, the way find_board does (once per company; what's found is kept). False makes no requests. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
This is where the description earns its keep: readOnlyHint=false would otherwise be confusing for a 'list' tool, and the text explains why by disclosing that look_up_boards makes web requests once per company and keeps what it finds, while rescan 'reads nothing from the web; safe to repeat.' That goes meaningfully beyond the annotation flags and identifies the network/persistence behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is one very long run-on paragraph with deeply nested parentheticals, and the essential action is not front-loaded — the first sentence mixes purpose, data sources, ranking logic, and caveats before the agent learns what the tool returns. It also spends much of its length re-describing return fields that the output schema already defines.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity (multi-source suggestions plus a web-lookup side effect) and the presence of an output schema, the description supplies enough operational context to call it correctly and interpret results, including the board_found provenance and the pre-built add_board arguments. The only real gap is that result fields are re-explained rather than relying on the output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already carries limit, rescan, and look_up_boards semantics in detail; the description mostly defers back to it ('see its description'). The narrative adds context for why rescan exists (filters changed, or posts fetched before they were noted), but the baseline 3 applies when the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The name plus the opening enumeration of what each suggestion contains makes it clear this tool lists candidate companies to watch, and it names the relevant siblings (import_job_alerts, add_application, fetch_jobs, find_board, add_board, dismiss_suggested_board) so an agent can place it in the workflow. It never states the action in a clean verb+object form, but the resource and scope are unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The closing line 'Suggest; let the person decide which to add' and the routing to dismiss_suggested_board for removal, rescan for picking up previously kept HN posts, and find_board when no board was found give a clear sense of when to reach for this tool and what to do next. There is no explicit exclusion versus list_boards, but the sourcing condition (job-alert emails, add_application, watched HN threads) is a practical filter condition.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mark_jobADestructiveIdempotent
Record a job's status: new, shown, queued (to apply to next), applied, screening, interviewing, offer, rejected, withdrawn or skipped (omit status to keep it and only update the rest). key is the job's key, its posting id, or its company's name when that names one job (the one queued or applied to there); when it names several, nothing changes and the error lists them. Use applied only after the person has submitted the application themselves. add_note adds a dated line to the note, keeping what's there: prefer it for news ("recruiter replied: onsite only"); note replaces the whole note. next_step says what happens next ("recruiter screen Tuesday"); follow_up is the day to act (YYYY-MM-DD or +N days); applied_on is the day applied, if not today. url sets the link of a job added by hand (its posting, or the company's careers site once the posting is gone); when the job has no posting text and the link is to one job on a supported board, the posting is read from it (text, pay, places), so it can be scored. text sets its posting's text, pasted (found later, or from a copy once the posting is gone), so it can be scored and prepped. An empty string clears a field. For a job jobwatch doesn't track yet, use add_application. Queuing a job that's (maybe) the same opening as one applied to or queued still queues it, and the reply ends with the warning: tell the person.
| Name | Required | Description | Default |
|---|---|---|---|
| key | Yes | The job: its key as other tools return it (source:board:posting id, e.g. greenhouse:acme:4012345), just the posting id, or the company's name when that names one job (the one queued or applied to there). When it matches several, the error lists their keys. | |
| url | No | The link of a job added by hand: its posting, or the company's careers site once the posting is gone. | |
| note | No | Replaces the whole note. Prefer add_note for news. | |
| text | No | The posting's text, pasted (found later, or a copy once the posting is gone), so it can be scored and prepped. | |
| status | No | The new status; omit to keep it and only update the rest. applied only after the person has submitted the application themselves. | |
| add_note | No | A line to add to the note, dated today, keeping what's there ("recruiter replied: onsite only"). | |
| follow_up | No | A day: YYYY-MM-DD, or +N for N days from today. An empty string clears it. | |
| next_step | No | What happens next ("recruiter screen Tuesday"). An empty string clears it. | |
| applied_on | No | The day applied (YYYY-MM-DD), if not today. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag this as a destructive, non-read-only, open-world mutation, but the description adds concrete effect semantics: 'note replaces the whole note', 'An empty string clears a field', the no-op-plus-listing error when key is ambiguous, and the side effect that supplying url/text enables scoring. It does not mention permissions, rate limits, or what the reply payload contains, so it stops short of a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose and status list are front-loaded in the first clause, and nearly every clause carries a distinct rule, so the density is largely earned. The long semicolon-chained sentences and parentheticals make it harder to scan than it needs to be, and the closing 'tell the person' instruction is awkwardly grafted on.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 9-parameter mutation tool with an output schema, the description covers status semantics, all field behaviors, clearing rules, ambiguity/error handling, and the sibling alternative. Return values needn't be explained since an output schema exists, and 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.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, and the description does add real meaning beyond it: accepted key forms and ambiguity resolution, the 'empty string clears' convention, follow_up's +N format, applied_on defaulting to today, and the downstream consequence of url/text (posting read and scoreable). It is close to exhaustive but still leaves the note vs add_note precedence implicit.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Record a job's status') and enumerates the full status vocabulary, so the agent knows exactly what domain this mutates. It also explicitly distinguishes itself from the sibling add_application ('For a job jobwatch doesn't track yet, use add_application'), which is unusually strong sibling differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use and when-not rules: 'Use applied only after the person has submitted the application themselves', 'prefer it [add_note] for news', and the redirect to add_application for untracked jobs. It also covers an ambiguous case (queuing a duplicate opening still queues it and surfaces a warning), leaving little to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
rate_contactADestructiveIdempotent
Record what the person says about someone they know at a company: use (a good person to ask for a referral: listed first wherever contacts are), skip (never suggest them, e.g. never answers messages) or clear (forget it), with an optional short note that is shown with their name. Call it when the person tells you whom to ask or not to ask; it only changes how contacts are ordered and listed. Returns the connection (name, company, position, verdict, note). Errors when no connection (or more than one) has that name: then use their profile link.
| Name | Required | Description | Default |
|---|---|---|---|
| who | Yes | The connection's full name ("Ana Li") or LinkedIn profile link (linkedin.com/in/...). | |
| note | No | A few words to show beside their name, e.g. "doesn't check LinkedIn; reach on WhatsApp". | |
| verdict | Yes | use: ask them first; skip: never suggest them; clear: back to the usual order. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare a non-read-only, destructive, idempotent write, and the description adds value beyond them: the mutation is scoped to contact ordering/listing, the return payload is spelled out (name, company, position, verdict, note) despite no output schema, and the ambiguity error is disclosed. Minor gap: it does not say whether 'clear' also discards an existing note, which matters given destructiveHint=true.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The verb and resource are front-loaded in the first clause and every sentence carries information (verdict meanings, trigger, scope, return, error). It is dense and parenthetical-heavy ('(a good person to ask for a referral: listed first wherever contacts are)'), which costs some readability but not correctness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 3-parameter tool with an enum and no output schema, the description covers trigger, effects, return shape, and the error case. The only real hole is what happens to an existing note when verdict is 'clear', which an agent could get wrong without a trial call.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, but the description still adds meaning: 'use' is explained as 'listed first wherever contacts are', 'clear' as returning to 'the usual order', and the note as 'shown with their name'. It also restates the who identifier and the name-disambiguation failure that the schema only hints at.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a concrete verb+resource pair ('Record what the person says about someone they know at a company') and then enumerates the three verdict values and their effects. No sibling tool deals with contact ranking, and the phrase 'it only changes how contacts are ordered and listed' pins down the scope of effect precisely.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Call it when the person tells you whom to ask or not to ask' is an explicit trigger, and the note that it 'only changes how contacts are ordered and listed' bounds what the tool should be used for. The error path ('Errors when no connection (or more than one) has that name: then use their profile link') gives a concrete fallback, though no explicit when-not-to-call case is stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_profileARead-onlyIdempotent
Who an interviewer or contact is: their roles, from the text of their LinkedIn experience page, for interview prep. Each: title, company, start, end ("Present" if current), duration, location, workplace (Hybrid, Remote or On-site) and bullets (the description). The page's sidebars and footer are dropped. This only parses text it is given: jobwatch never reads linkedin.com (its robots.txt disallows it), so get the page text through the person's own browser. Returns an error when no roles are found.
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes | The page text of someone's LinkedIn experience page (linkedin.com/in/<name>/details/experience/), as the person's own browser shows it: copied, or from a browser tool's page text. Not a link. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (read-only, idempotent, non-destructive, closed-world), and the description adds real behavioral detail beyond them: sidebars and footer are dropped from the parse, and an error is returned when no roles are found. That error-path disclosure is exactly the kind of context annotations cannot express.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose and the field list are front-loaded, followed by the scoping constraint and error behavior. The dense run-on with parentheticals ('(Hybrid, Remote or On-site)', '(the description)') is slightly heavy but every clause carries information an agent needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
A single required parameter with full schema documentation, an output schema covering the return shape, plus description-level disclosure of trimming, the no-network constraint, and the no-roles error. 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.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema's parameter description already specifies the source page and that a link is unacceptable, so the description need not compensate. It reinforces the source ('text of their LinkedIn experience page') and lists the parsed fields, but adds no format or syntax guidance beyond the schema. Baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: extract roles (title, company, dates, location, bullets) from a person's LinkedIn experience page text, for interview prep. The follow-up sentence 'This only parses text it is given' resolves the misleading name 'read_profile' by making clear no external fetch occurs, distinguishing it from fetch-style siblings like fetch_jobs or check_postings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear operating context: use for interview prep on an interviewer or contact, and obtain the page text via the person's own browser because jobwatch never reads linkedin.com. It does not explicitly name a sibling alternative or state when-not to use it beyond the browser-sourcing constraint, 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.
read_status_emailsARead-onlyIdempotent
Read emails about the person's applications (a "thank you for applying" confirmation, a rejection, an interview invitation or scheduling link, a take-home assignment, an offer, a recruiter's reply) and PROPOSE what changes; nothing is recorded. Search the person's mail first (e.g. their applications' companies, or "thank you for applying", "your application", "interview"), and pass each message in; jobwatch never needs a mail password. Present the proposals to the person and only call mark_job for the ones they confirm, with the proposal's mark_job arguments (status, add_note, next_step, follow_up). Returns proposals (key, company, title, current_status, suggested_status (null: only a note), kind, note, next_step, email (date, sender, subject), confidence, why, mark_job), unmatched (emails about no tracked application, with the company guessed: offer to add it with add_application, or say it's an application it can't tell apart), nothing_new (emails that add nothing: already recorded or already past that stage) and other (the count of emails that aren't about an application). A status only moves forward: a late confirmation for an application already interviewing is not a proposal. For job-alert emails use import_job_alerts.
| Name | Required | Description | Default |
|---|---|---|---|
| emails | Yes | The emails about applications, one string each: the raw message (RFC822, as a mail connector's raw format gives it, base64url-encoded as from Gmail's API is fine too; best, since it names the sender and date) or just its HTML or plain-text body. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnly/idempotent/non-destructive, and the description adds genuinely new context: nothing is recorded, no mail password is needed, and statuses only move forward (a late confirmation for an already-interviewing application is not a proposal). It also discloses the return buckets, which the absent output schema does not.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose and the core propose-don't-record behavior, and the dense parentheticals each carry real information (return buckets, kind examples). It is long, but the length is justified by the missing output schema; minor tightening is possible.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex classification tool with no output schema, the description fully specifies the return structure (proposals, unmatched, nothing_new, other) plus the follow-up action, so an agent has everything needed to call it and act on the result.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema already documents the single 'emails' parameter including accepted formats (RFC822, base64url, HTML/plain body). The description only adds the workflow instruction to search mail first and pass each message in, which is context rather than additional parameter semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (read) and resource (emails about applications), and enumerates the email kinds it handles (confirmation, rejection, interview invite, offer, recruiter reply). It also names a sibling it is not (import_job_alerts) so the agent can disambiguate without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit workflow (search mail first, pass each message in), an explicit handoff condition (present proposals, only call mark_job for confirmed ones with the proposal's arguments), and an explicit exclusion (job-alert emails go to import_job_alerts). When/when-not/alternative are all covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
remove_boardADestructiveIdempotent
Take a board off the watchlist, so fetch_jobs stops checking it. Jobs and applications already recorded from it are kept. The watchlist is rewritten, with a copy of the old one kept as .bak.
| Name | Required | Description | Default |
|---|---|---|---|
| entry | Yes | The board as source:board, the way find_board and list_boards give it (e.g. greenhouse:stripe). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=true, but the description adds genuinely non-derivable behavior: previously recorded jobs/applications survive, the watchlist file is rewritten, and the old copy is preserved as .bak. That .bak detail is exactly the reassurance an agent needs before a destructive call. It lacks auth/prerequisite notes and error behavior, keeping it out of 5 territory.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the action and its effect, then the retention and backup guarantees. No filler and nothing repeated from the schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-param destructive mutation with no output schema, the description covers what changes, what is preserved, and what is backed up. The remaining gap is only the return/confirmation behavior and failure modes, which are minor here.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the single `entry` parameter is fully documented in the schema with format and example ('greenhouse:stripe'). The description adds no further parameter detail, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb+resource ('Take a board off the watchlist') with the downstream effect named ('so fetch_jobs stops checking it'). It is clearly the inverse of the sibling add_board, so an agent can distinguish them at a glance.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The effect statement ('fetch_jobs stops checking it') implies when to reach for it versus add_board/fetch_jobs, and it clarifies the data-retention condition. It stops short of an explicit when-not (e.g., what to do if the entry is absent) or naming an 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.
save_application_packageADestructive
Keep what was sent with an application, as copies: files (local paths to the resume PDF, cover letter... exactly as uploaded), answers (the form's questions and the answers given, [{question, answer}]; replaces any saved before) and note (a cover letter or message pasted into the form). Call it once the person has submitted, with what they actually sent; get_application_package reads it back.
| Name | Required | Description | Default |
|---|---|---|---|
| key | Yes | The job: its key as other tools return it (source:board:posting id, e.g. greenhouse:acme:4012345), just the posting id, or the company's name when that names one job (the one queued or applied to there). When it matches several, the error lists their keys. | |
| note | No | A cover letter or message pasted into the form. | |
| files | No | Local paths to the files exactly as uploaded (resume PDF, cover letter...). Copies are kept. | |
| answers | No | The form's questions and the answers given, as [{"question": ..., "answer": ...}]. Replaces any saved before. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, idempotentHint=false and readOnlyHint=false. The description adds useful context beyond them: files are kept 'as copies' (not moved), and answers 'replace any saved before', clarifying partial-overwrite semantics. It does not cover auth or error behavior, but the added nuance is real.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is a single dense sentence with parenthetical glosses for each parameter, front-loading the purpose before the usage instruction. The nested parentheses make it slightly awkward, but every clause carries information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive save tool with no output schema, the description covers what is stored, when to call it, and how to read it back. It omits what the call returns (e.g. a confirmation or the saved key), which would round it out, but nothing critical is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all four parameters well. The description largely restates the same parameter meanings ('exactly as uploaded', 'replaces any saved before'), adding little beyond what the schema already provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: keeping copies of what was sent with an application (files, answers, note). It explicitly contrasts with the read counterpart, get_application_package, so an agent can distinguish it from its closest sibling without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives a clear timing condition ('Call it once the person has submitted, with what they actually sent') and names the read alternative ('get_application_package reads it back'). It does not spell out when not to call it (e.g. before submission is complete), but the context is strong.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
save_storyA
Add a story to the person's story file (the watchlist's stories:, or stories.yaml beside it, which the watchlist then names), for drafted interview answers and mock interviews. Use it after interviewing the person about one of get_interview_prep's story_gaps: ask one question at a time; if you offer typical details to jog their memory, say they're common patterns, not their case; keep their real role (took part is not led); keep internal system names, people's names and countries out. Only what they confirmed goes in did, hard and result; the rest goes in avoid. Show them the story and save it only after they say yes. Returns the story as saved, the file and how many stories it has.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | A short name drafted answers cite it by: lowercase letters, digits and dashes (alert-dedupe). A taken one gets -2, -3... | |
| did | Yes | Two or three sentences, in the person's first person, using only what they told you. | |
| hard | Yes | Two or three sentences, in the person's first person, using only what they told you. | |
| avoid | No | Details that came up but the person didn't confirm, or asked to keep out (a tool they weren't sure of, a place). Drafted answers and mock answers that say one are taken out. | |
| title | Yes | A few words: what it was. | |
| result | Yes | Two or three sentences, in the person's first person, using only what they told you. | |
| skills | No | Tools and skills it shows, as the person named them. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare a non-read-only, non-destructive, non-idempotent write, so the safety profile is carried structurally. The description adds genuine value beyond that: the concrete persistence target (stories: section or stories.yaml), the confirmation gate before saving, content-safety constraints (no internal system names, people, countries), and the return payload. It stops short of stating what happens on an overwrite or whether an existing story is replaced.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose is front-loaded in the first clause, which is good, but the single dense paragraph bundles destination, workflow, content policy and return value, with semicolon-chained instructions that are easy to lose. Nearly every sentence earns its place, yet the packaging is heavier than the payload requires.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description usefully discloses what comes back (the story as saved, the file, and the story count). Combined with the storage location and the confirmation requirement, an agent has enough to call it correctly; only the overwrite/collision behavior for an existing story is left implicit.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so every parameter including id, did, hard, result, avoid and skills is already documented in the schema itself. The description's one added rule — only confirmed material goes in did/hard/result and the rest goes in avoid — is meaningful routing logic, but it largely restates what the avoid field description already says.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Add a story to the person's story file') and names the exact destination (the watchlist's stories: or stories.yaml beside it). It also scopes the content domain to drafted interview answers and mock interviews, which separates it cleanly from sibling tools like get_interview_prep and save_application_package.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit trigger ('Use it after interviewing the person about one of get_interview_prep's story_gaps') and names the upstream sibling that produces the gap list. It also states the interaction protocol (one question at a time, label typical details as common patterns, confirm before saving), so when-to-use and how-to-use are both answered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_compADestructiveIdempotent
Keep what a recruiter told the person about pay for a job, so get_comps can put it next to the others, and what the job is for their career (role, career_note). Only the fields given change; an empty string clears one. Write amounts the way they were said ("165-195K", "$215,000"): the first amount found is read to mark the highest. Returns what is kept for the job.
| Name | Required | Description | Default |
|---|---|---|---|
| key | Yes | The job: its key as other tools return it (source:board:posting id, e.g. greenhouse:acme:4012345), just the posting id, or the company's name when that names one job (the one queued or applied to there). When it matches several, the error lists their keys. | |
| base | No | The base salary (range) the recruiter gave, as said: "165-195K". An empty string clears it. | |
| note | No | A few words ("195K most likely their max"). Replaces the old note. Empty clears it. | |
| role | No | What the job is, for its career value: product (builds the company's own product), customer (forward-deployed, solutions, customer-facing engineering) or internal (builds internal tools or platforms for the business). Empty clears it. | |
| asked | No | What the person asked for ("210-230K"). Empty clears it. | |
| bonus | No | Bonus, as said ("10% target"). Empty clears it. | |
| equity | No | Equity, as said ("40K RSUs over 4 years"). Empty clears it. | |
| signon | No | Sign-on bonus, as said. Empty clears it. | |
| offered | No | What they offered. Empty clears it. | |
| career_note | No | A few words on its career value ("observability product, staff IC"). Empty clears it. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds real behavioral detail beyond the annotations: partial-update semantics ("Only the fields given change"), the empty-string-clear rule that explains destructiveHint, and the parsing rule that the first amount found is read to mark the highest. It does not mention permissions or how ambiguous keys resolve, but that is covered in 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose, but the sentences are long and colloquial ("Keep what a recruiter told the person"), and the trailing "Returns what is kept for the job" is vague and arguably wasted. The core content is right, the phrasing is not tight.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 10-parameter destructive write with 100% schema coverage, the description covers mutation semantics, clearing behavior and amount parsing. It is thin only on the return value (no output schema exists, so a one-line summary is acceptable) and on error handling, which the key parameter's schema already describes.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3; the description goes further by stating the amount-format expectation ("Write amounts the way they were said, '165-195K'") and the 'first amount found' interpretation rule, which the schema doesn't spell out. It also flags that role and career_note are the career-value fields.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: it stores what a recruiter said about pay for a job, plus career role/notes for that job. It names the sibling consumer (get_comps), which makes the read/write split clear. The only weakness is the folksy phrasing ("Keep what a recruiter told the person") that a non-native agent may parse slowly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by 'what a recruiter told the person about pay' and by naming get_comps as the downstream reader, so the agent can infer this is the recording step. There is no explicit 'use when' trigger and no statement of when to prefer another tool (e.g. get_comps, get_job) or what to do if the job is unknown.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_company_healthADestructiveIdempotent
Keep what is known of a company's health, per company, for get_comps to show and weigh. Search the web yourself (jobwatch fetches none of these sites) and record what you found with its source links and the day; say so when you could not find something, and leave that field out rather than guessing. Only the fields given change; an empty string clears one. Returns what is kept, with how old it is.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | No | What kind of company: tech (software, security or AI product company), consulting, or enterprise (a non-tech business whose IT builds for itself: bank, insurer, real-estate finance). The career part of get_comps reads it. Empty clears it. | |
| risk | No | A short risk note; any text counts against the company. | |
| as_of | No | The day the facts were read, YYYY-MM-DD; today when left out. Older than 90 days shows as stale. | |
| stage | No | Stage and last round, as found ("Series B, $50M, 2025"). | |
| raised | No | Total raised ("$80M"). Under $20M for a private company counts as thin funding. | |
| rating | No | Employee rating ("4.1 Glassdoor"). | |
| company | Yes | The company's name, or the key of one of its jobs. | |
| layoffs | No | Recent layoffs, with when ("10% in March 2026"), or "none" when you found none. | |
| listing | No | public or private. An empty string clears it. | |
| revenue | No | Revenue or growth, if known. | |
| sources | No | The links these came from, separated by spaces. | |
| headcount | No | Headcount trend ("growing", "shrinking"). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare destructiveHint=true and idempotentHint=true, and the description explains exactly why: "Only the fields given change; an empty string clears one" — the precise destruction mechanism an agent must know. It also discloses the return shape ("Returns what is kept, with how old it is") and that no fetching happens server-side, context 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose and consumer lead the sentence, followed by sourcing rules, then update semantics and return format — a sensible order with no filler. It is dense but each clause (sources, day, don't guess, empty clears) carries distinct instruction.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 12-parameter mutation with no output schema, the description covers the essential unknowns: sourcing responsibility, staleness via the recorded day, clearing semantics, and what comes back. Only minor things (e.g., behavior on an unknown company) are left to the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3; the description still adds set-level semantics the schema does not: partial-update behavior, empty-string-as-clear, and the instruction to omit unknown fields rather than guess. That meaningfully changes how an agent populates the 12 optional fields.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
"Keep what is known of a company's health, per company, for get_comps to show and weigh" names the verb (record/keep), the resource (company health facts), the scope (per company), and the consumer (get_comps). This clearly separates it from siblings like set_comp (compensation) and get_company (read-side), so an agent can pick it without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete operational guidance: "Search the web yourself (jobwatch fetches none of these sites)", supply source links and the day, and "say so when you could not find something, and leave that field out rather than guessing." It lacks an explicit contrast with set_comp/get_company, but the when-and-how is unambiguous.
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.
8 tool updates
v0.6.0- Changed
add_application1 field changed- changed
Input schema / properties / url / descriptionPrevious value: -"A link to the job: Greenhouse, Lever, Ashby, Workable, Workday, Rippling, Google Careers, amazon.jobs, Oracle Recruiting Cloud, SmartRecruiters, Avature, iCIMS or LinkedIn are read in full; any other link is just kept."New value: +"A link to the job: Greenhouse, Lever, Ashby, Workable, Workday, Rippling, Google Careers, amazon.jobs, Oracle Recruiting Cloud, SmartRecruiters, Avature, iCIMS, Jobvite or LinkedIn are read in full; any other link is just kept."
- Added
find_past_answers - Changed
get_company1 field changed- added
Input schema / properties / every_roleAdded value: +{ + "default": false, + "description": "Also list the open roles the filters leave out (other cities, low pay...). Default: the watchlist's display.company setting (matches: only the roles Today's filters pass).", + "title": "Every Role", + "type": "boolean" +}
- Added
get_comps - Added
rate_contact - Added
read_profile - Added
set_comp - Added
set_company_health
11 tool updates
v0.5.0- Changed
add_application1 field changed- changed
Input schema / properties / url / descriptionPrevious value: -"A link to the job: Greenhouse, Lever, Ashby, Workable, Workday, Rippling or LinkedIn are read in full; any other link is just kept."New value: +"A link to the job: Greenhouse, Lever, Ashby, Workable, Workday, Rippling, Google Careers, amazon.jobs, Oracle Recruiting Cloud, SmartRecruiters, Avature, iCIMS or LinkedIn are read in full; any other link is just kept."
- Changed
add_board1 field changed- added
Input schema / properties / careersAdded value: +{ + "default": "", + "description": "The company's own careers site (https://...), for a board whose hosted job pages are offline (fetch_jobs warns about those): its jobs then link there.", + "title": "Careers", + "type": "string" +}
- Added
dismiss_suggested_board - Added
find_duplicates - Added
get_company - Changed
get_digest5 fields changed- added
Input schema / properties / limit / anyOfAdded value: +[ + { + "minimum": 1, + "type": "integer" + }, + { + "type": "null" + } +] - changed
Input schema / properties / limit / defaultPrevious value: -25New value: +null - changed
Input schema / properties / limit / descriptionPrevious value: -"The most jobs to return, best first."New value: +"The most jobs to return, best first. Default: the watchlist's display.today (10 unless set; 25 when it's 0, for every match)." - removed
Input schema / properties / limit / minimumRemoved value: -1 - removed
Input schema / properties / limit / typeRemoved value: -"integer"
- Changed
get_interview_prep2 fields changed- added
Input schema / properties / draft_answersAdded value: +{ + "default": false, + "description": "Also have jobwatch's own model (the chat's backend) draft 6-10 questions likely for this role, each with the ask it probes and an answer outline built only from the person's story file and resume, citing the story ids used; one with no story says so (no_story) with an honest angle. Invented story ids and numbers are taken out before they're returned. Slow the first time, then kept. With the claude backend the posting, resume and stories go to Anthropic. False is rule-based and instant.", + "title": "Draft Answers", + "type": "boolean" +} - added
Input schema / properties / role_questionsAdded value: +{ + "default": false, + "description": "Also have jobwatch's own model (the chat's backend) write questions for this role from the posting's asks (role_questions), without answers. Only the posting goes to the model, and to Anthropic with the claude backend. Slow the first time, then kept; questions saved earlier are always returned.", + "title": "Role Questions", + "type": "boolean" +}
- Added
import_job_alerts - Added
list_suggested_boards - Added
read_status_emails - Added
save_story
17 tool updates
v0.3.0- Added
add_board - Removed
application_package - Removed
applications - Removed
apply_queue - Removed
digest - Added
get_application_package - Added
get_digest - Added
get_interview_prep - Added
get_job - Removed
interview_prep - Removed
job_details - Added
list_applications - Added
list_boards - Added
list_queued_jobs - Added
list_skill_gaps - Added
remove_board - Removed
skill_gaps
11 tool updates
v0.2.3- Changed
add_application9 fields changed- added
Input schema / properties / applied_on / descriptionAdded value: +"The day applied (YYYY-MM-DD), if not today." - added
Input schema / properties / company / descriptionAdded value: +"The company; may be left out when url is a job link it can read." - added
Input schema / properties / follow_up / descriptionAdded value: +"A day: YYYY-MM-DD, or +N for N days from today. An empty string clears it." - added
Input schema / properties / next_step / descriptionAdded value: +"What happens next (\"hiring manager call Friday\")." - added
Input schema / properties / note / descriptionAdded value: +"A note: who referred them, how they found it..." - added
Input schema / properties / status / descriptionAdded value: +"applied (the default; only once the person has applied themselves), queued for one they're considering, or a later stage such as interviewing." - added
Input schema / properties / text / descriptionAdded value: +"The posting's text, pasted, when the link can't be read, so it can be scored and prepped." - added
Input schema / properties / title / descriptionAdded value: +"The job title; may be left out when url is a job link it can read." - added
Input schema / properties / url / descriptionAdded value: +"A link to the job: Greenhouse, Lever, Ashby, Workable, Workday, Rippling or LinkedIn are read in full; any other link is just kept."
- Changed
application_package1 field changed- added
Input schema / properties / key / descriptionAdded value: +"The job: its key as other tools return it (source:board:posting id, e.g. greenhouse:acme:4012345), just the posting id, or the company's name when that names one job (the one queued or applied to there). When it matches several, the error lists their keys."
- Changed
applications1 field changed- added
Input schema / properties / due_only / descriptionAdded value: +"Only those whose follow-up day has come."
- Changed
digest6 fields changed- added
Input schema / properties / include_seen / descriptionAdded value: +"Also include jobs already shown in an earlier digest, not just new ones." - added
Input schema / properties / limit / descriptionAdded value: +"The most jobs to return, best first." - added
Input schema / properties / limit / minimumAdded value: +1 - added
Input schema / properties / mark_shown / descriptionAdded value: +"Mark the returned jobs as shown, so the next digest leaves them out. False to peek without changing anything." - added
Input schema / properties / score_top / descriptionAdded value: +"How many of the most relevant unscored jobs to fit-score against the resume with shortlist-ai first. 0 (the default) skips scoring; each job takes minutes on the local backend, so keep it small." - added
Input schema / properties / score_top / minimumAdded value: +0
- Changed
find_board1 field changed- added
Input schema / properties / company / descriptionAdded value: +"A company name (\"Stripe\"), or a link to one of its job postings or its careers page."
- Changed
interview_prep1 field changed- added
Input schema / properties / key / descriptionAdded value: +"The job: its key as other tools return it (source:board:posting id, e.g. greenhouse:acme:4012345), just the posting id, or the company's name when that names one job (the one queued or applied to there). When it matches several, the error lists their keys."
- Changed
job_details1 field changed- added
Input schema / properties / key / descriptionAdded value: +"The job: its key as other tools return it (source:board:posting id, e.g. greenhouse:acme:4012345), just the posting id, or the company's name when that names one job (the one queued or applied to there). When it matches several, the error lists their keys."
- Changed
list_jobs2 fields changed- changed
Input schema / properties / status / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "type": "null" - } -]New value: +[ + { + "enum": [ + "new", + "shown", + "queued", + "applied", + "screening", + "interviewing", + "offer", + "rejected", + "withdrawn", + "skipped" + ], + "type": "string" + }, + { + "type": "null" + } +] - added
Input schema / properties / status / descriptionAdded value: +"Only jobs with this status; omit for all."
- Changed
mark_job10 fields changed- added
Input schema / properties / add_note / descriptionAdded value: +"A line to add to the note, dated today, keeping what's there (\"recruiter replied: onsite only\")." - added
Input schema / properties / applied_on / descriptionAdded value: +"The day applied (YYYY-MM-DD), if not today." - added
Input schema / properties / follow_up / descriptionAdded value: +"A day: YYYY-MM-DD, or +N for N days from today. An empty string clears it." - added
Input schema / properties / key / descriptionAdded value: +"The job: its key as other tools return it (source:board:posting id, e.g. greenhouse:acme:4012345), just the posting id, or the company's name when that names one job (the one queued or applied to there). When it matches several, the error lists their keys." - added
Input schema / properties / next_step / descriptionAdded value: +"What happens next (\"recruiter screen Tuesday\"). An empty string clears it." - added
Input schema / properties / note / descriptionAdded value: +"Replaces the whole note. Prefer add_note for news." - changed
Input schema / properties / status / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "type": "null" - } -]New value: +[ + { + "enum": [ + "new", + "shown", + "queued", + "applied", + "screening", + "interviewing", + "offer", + "rejected", + "withdrawn", + "skipped" + ], + "type": "string" + }, + { + "type": "null" + } +] - added
Input schema / properties / status / descriptionAdded value: +"The new status; omit to keep it and only update the rest. applied only after the person has submitted the application themselves." - added
Input schema / properties / text / descriptionAdded value: +"The posting's text, pasted (found later, or a copy once the posting is gone), so it can be scored and prepped." - added
Input schema / properties / url / descriptionAdded value: +"The link of a job added by hand: its posting, or the company's careers site once the posting is gone."
- Changed
save_application_package4 fields changed- added
Input schema / properties / answers / descriptionAdded value: +"The form's questions and the answers given, as [{\"question\": ..., \"answer\": ...}]. Replaces any saved before." - added
Input schema / properties / files / descriptionAdded value: +"Local paths to the files exactly as uploaded (resume PDF, cover letter...). Copies are kept." - added
Input schema / properties / key / descriptionAdded value: +"The job: its key as other tools return it (source:board:posting id, e.g. greenhouse:acme:4012345), just the posting id, or the company's name when that names one job (the one queued or applied to there). When it matches several, the error lists their keys." - added
Input schema / properties / note / descriptionAdded value: +"A cover letter or message pasted into the form."
- Changed
skill_gaps2 fields changed- changed
Input schema / properties / timeline / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "type": "null" - } -]New value: +[ + { + "enum": [ + "week", + "month", + "quarter", + "any" + ], + "type": "string" + }, + { + "type": "null" + } +] - added
Input schema / properties / timeline / descriptionAdded value: +"How soon the person wants to close a gap: week, month, quarter or any. Omit for the watchlist's learning.timeline."
14 tool updates
v0.1.0- First observed
add_application - First observed
application_package - First observed
applications - First observed
apply_queue - First observed
check_postings - First observed
digest - First observed
fetch_jobs - First observed
find_board - First observed
interview_prep - First observed
job_details - First observed
list_jobs - First observed
mark_job - First observed
save_application_package - First observed
skill_gaps
TDQS
Scored across 30 tools
Most tools have clearly distinct purposes, and the descriptions explicitly cross-reference adjacent tools such as mark_job vs add_application and get_digest vs list_queued_jobs. There is still some boundary overlap among retrieval/listing tools (get_job, get_company, list_jobs, list_applications, list_queued_jobs, get_digest), though the descriptions generally resolve it.
Names are consistently snake_case and overwhelmingly follow a verb_noun pattern: list_boards, add_board, remove_board, get_job, mark_job, save_story, etc. Minor abbreviations like set_comp and get_comps are used consistently and do not disrupt predictability.
With 30 tools, the surface exceeds the threshold where a tool set becomes heavy for an agent to select from reliably, even for a broad job-search assistant domain. Several clusters (jobs, applications, emails, prep, boards, skills) could be consolidated or grouped to reduce cognitive load.
The surface covers a remarkably broad lifecycle: board discovery, job fetching/importing, application tracking, email status proposals, interview prep, compensation comparison, contacts, stories, and skill gaps. Minor gaps remain around explicit configuration of watchlist filters/resume, and management operations such as listing or deleting saved stories, but most workflows are covered.
Maintenance
Related MCP Connectors
- SalvoOAuthcom.sendsalvo
Job applications done for you: check applications and interviews, get prep, apply to a job by URL.
Analyze job listings against your resume, track applications, and generate cover letters.
Search ~1.4M open jobs from 24k company career boards: Greenhouse, Lever, Ashby, Workday and more
Open jobs from any company's careers site by name or domain, plus a search across 2.5M+ roles
Related MCP Servers
- AlicenseBqualityDmaintenanceProvides tools to search & auto-apply to jobs directly on company websites, generate custom resumes, get contacts of recruiters and referrals and track applications easily3526 npm26MIT
- AlicenseAqualityAmaintenanceScans 130+ company careers pages and scores every role against your resume with an LLM (0–100), surfacing top matches. Drafts tailored cover letters and resume bullets for any job on demand, and exports scan results to CSV.348 PyPI217MIT
- AlicenseNot gradedqualityCmaintenanceEnables users to upload a resume to build a profile, discover jobs from company websites and official ATS boards, receive scheduled recommendations, and swipe to manage interest and application status. Runs self-hosted on Cloudflare with private resume storage and no OpenAI API key required.MIT
- AlicenseNot gradedqualityAmaintenanceEnables AI agents to discover postings from watched company boards ranked by keyword fit, tailor and fact-check resumes against a source-cited profile, render ATS-readable PDFs, submit applications through the user's own browser, and track replies and follow-ups. All ranking, claim checking and email classification run as plain code, so LLM tokens are spent only on writing.1Apache 2.0