Skip to main content
Glama
OpenHire — Real Job Postings, Ghost Jobs Scored

OpenHire — Real Job Postings, Ghost Jobs Scored

Watch a job intent

watch_intent

Register a standing job-search intent with filters and an anonymous fingerprint so new matching postings can be checked and pulled later.

Instructions

Register a standing intent so new matches can be pulled later.

The caller supplies an anonymous fingerprint. For a user who has none yet, pass fingerprint="new": the server picks a random one and returns it (do not invent one yourself; models write the same "random" strings in every conversation and collide). A user's saved key from before is reused as is (12+ characters; a four-character tag collides with strangers). The client owns it; the server stores but can never recover it, so persist it client-side and pass the identical one to check_watches. Only the fingerprint and non-PII filter keys are stored — never a name, email, phone or résumé. Accepted filter keys mirror search_jobs: skills (ANY-overlap), required_skills (ALL/AND — use this to keep sales / solutions-architect roles out), remote (bool), role_family (e.g. "engineering"), min_salary (int), company (one employer, resolved at registration), location (substring of the location text, alias-aware like search_jobs: 广州 also reaches 广东·天河区 rows, Beijing reaches 北京市, "remote" reaches 远程), title (list of title substrings, ANY-of, synonym-expanded for HR terms like search_jobs — the way to watch for recruiting or other roles no skill tag names), title_exclude (title words to keep out on every pull, as in search_jobs: the user who wants "no 专家 roles" gets that enforced by the watch, not by you), seniority (list of levels or the aliases "ic" / "management", as in search_jobs, so a watch for an engineer never fires on a Senior Manager; what_happens_next says when titles naming no level are left out), sector (autonomous_driving / embodied_ai / ai_infra / other, as in search_jobs: one watch for "robotics companies in Shenzhen" instead of one per employer), entry_level (true: only postings open to a new graduate, as in search_jobs), posted_within_days (only postings published in the last N days, as in search_jobs), remote_scope (worldwide / region_locked / country_locked / unknown, as in search_jobs: a seeker outside the US keeps US-only remote roles out with "worldwide"). Any other key is REFUSED (ERR_UNKNOWN_FILTER) rather than silently dropped, and a role_family outside engineering | data | product | design | marketing | sales | hr | ops | other is refused too (ERR_UNKNOWN_ROLE_FAMILY); "recruiting" and "招聘" resolve to hr.

min_salary keeps rows with NO stated pay (they cannot be ruled out); it only drops rows whose stated pay is below the floor. Pay is stated mostly where law requires it (US postings on Greenhouse/Lever/Ashby), so a watch that needs a number will lean US.

A board watch: pass board_url (a Greenhouse / Lever / Ashby / Moka / 北森 / Workable / SmartRecruiters / Workday / Rippling / Personio careers URL, as for read_board) with optional location and title and nothing else; check_watches then reads that board live on every pull and reports what appeared and what disappeared since the last pull. This is how an employer outside the index is watched. Not combinable with company, skills, remote, min_salary or role_family; a closed portal (Feishu, a job site) is refused with the reason.

Returns { watch_id, status, fingerprint, matching_now, what_happens_next, existing_watches, fingerprint_notice }. matching_now is how many postings match today (all already live, none new; null for a board watch); what_happens_next is the sentence to relay: OpenHire does not push, the user asks you to check, the first check is a baseline, a scheduled reminder is a recurring task in the assistant. existing_watches > 0 means this fingerprint was already in use; unless you registered those watches yourself with it, they are a stranger's: delete this watch and register again with fingerprint "new".

Tool call template

Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {
      "fingerprint": "<fingerprint>",
      "filters": "<filters>"
    },
    "name": "watch_intent"
  }
}

Input Schema

NameRequiredDescriptionDefault
filtersYes
fingerprintYes

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observedv0.3.2

TDQS

A4.7/5.0
Behavior4/5

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

Without output schema, the description discloses the storage contract (only fingerprint plus non-PII filter keys, never name/email/phone/résumé), the irreversibility (server can never recover the key), the refuse-rather-than-drop error policy (ERR_UNKNOWN_FILTER, ERR_UNKNOWN_ROLE_FAMILY), and the collision-detection semantics of existing_watches. The only gap against the annotations is that openWorldHint=false sits slightly awkwardly beside the live board-reading mode, though the actual fetch happens in check_watches, not here.

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

Conciseness4/5

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

Front-loaded correctly: the fingerprint set-up rule and collision warning come first, before the long filter-key catalogue. It is long, but the length is mostly load-bearing given 19 documented filter semantics at 0% schema coverage; the repeated 'as in search_jobs' cross-reference is a mild redundancy and the prose is dense but ordered.

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

Completeness5/5

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

Despite no output schema, the return object is fully enumerated with meaning for each field, including the interpretive instruction for what_happens_next and the danger signal of existing_watches > 0. For a two-parameter mutation tool with a permissive nested object, nothing an agent needs in order to call it correctly is missing.

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

Parameters5/5

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

Schema description coverage is 0% and filters is an open nested object, so the description carries the full burden — and does: it enumerates every accepted filter key with matching semantics (skills ANY-overlap vs required_skills ALL), value domains (role_family list, sector, remote_scope), aliasing behavior (广州 reaches 广东·天河区), and the min_salary quirk that rows with no stated pay survive. It also constrains the fingerprint parameter ("new", 12+ chars, never invent) that the schema types only as a bare string.

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

Purpose5/5

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

States a specific verb and resource — 'Register a standing intent so new matches can be pulled later' — and immediately positions it against check_watches ('pass the identical one to check_watches'), which is where the watch is consumed. An agent can distinguish watch_intent from check_watches and manage_watch without opening any schema.

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

Usage Guidelines5/5

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

Explicit branching guidance: use fingerprint="new" only when the user has none, never invent a random string, reuse an existing 12+ character key as-is. It defines two mutually exclusive modes (filter watch vs board watch via board_url), states the non-combinable keys for board mode, and gives a recovery rule when existing_watches > 0 (delete and re-register with "new").

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