Umamy
Track your hiring pipeline
- Category
- HR & Recruiting
- Primary Subcategory
- Applicant Tracking & Recruiting Workflow
Integration details
Description
Query your Umamy recruitment pipeline directly in ChatGPT. List active hunts, look up candidates and their fit scores, read full LinkedIn message threads, access team notes, and pull pipeline analytics across your workspace. Umamy is a recruitment platform for enterprise hiring teams that helps you source, score, and engage candidates at scale. Use this app to triage your daily pipeline, brief yourself before a candidate call, draft follow-ups based on past message history, and generate weekly recaps — without leaving ChatGPT.
- Integration type
- Plugin
- Verification status
- Not applicable
- Platform
- ChatGPT
- Primary Subcategory
- Applicant Tracking & Recruiting Workflow
- Secondary Subcategories
- None listed
- Brand
- Umamy
- Access
- Account required
- First tracked
- 2026-06-06
- Tool count
- 36
- Geography
- US
The Primary Subcategory used for this profile’s headline score.
Other Subcategories where the Integration is listed.
Get alerts for Umamy
Get updates when Umamy’s Discoverability Score or category rank changes.
ChatGPT Plugin Discovery Score
ChatGPT Plugin discovery is coming soon
ChatGPT can surface a Plugin when it matches a user's request.Your Plugin Discovery Score measures how often yours appears.
No spam. Unsubscribe any time.
What discovery looks like

Competing in ChatGPT Interview Intelligence & Candidate Sourcing
View Category36 tools agents can invoke
**Purpose:** Bulk-add the entities on a saved criteria list (included/excluded companies or universities) into a hunt's matching criterion field. **NOT for:** Generic criteria writes (`update_hunt_criteria`). Only for the four list-backed fields below. **Returns:** `{ added: number, total_entities: number, field_slug, sync: { ok, error? } }`. Like `update_hunt_criteria`, the route auto-syncs to AWS after a successful write — no separate `sync_hunt_draft` needed before `get_hunt_candidate_count`. **When to use:** "Use my standard 'top SaaS companies' list" — pair with `list_personas` / list browsing tools to surface saved lists.
apply_hunt_criteria_list
**Purpose:** Create a new DRAFT hunt by copying an existing one's criteria, scorecard, outreach configuration, sourcing settings, and language. The new hunt is owned by the caller and starts empty (no candidates / messages / notes). **NOT for:** Editing an existing hunt (configuration changes happen in the Umamy dashboard). Not for creating a hunt from scratch (use the dashboard's setup wizard). Candidates, messages, notes, the linked LinkedIn account, and ATS connection are NEVER copied — those are reassigned manually on the new hunt. **Returns:** The newly created hunt — `{ id, name, status, role_name, created_at, updated_at }`. `status` is always `"draft"` regardless of the source hunt's status. **When to use:** - "Spin up a copy of the Senior Engineer hunt for the EU team" - "Duplicate hunt X but skip the outreach templates" - "Clone this hunt as a new draft so I can iterate on it" **Workflow:** list_organizations → list_hunts(org_id) → duplicate_hunt(org_id, source_hunt_id, name). **Defaults:** All `copy_*` flags default to `true` when omitted; pass `false` to skip a section. `add_me_as_owner` defaults to `true` and is a no-op if the caller is already an owner of the source hunt.
duplicate_hunt
**Purpose:** Propose 2–3 wordings for one new scorecard criterion that the user can pick from. **NOT for:** Replacing the whole scorecard (`regenerate_hunt_scorecard`). Not for persisting — it returns suggestions; call `update_hunt_scorecard` to commit a chosen one. **Returns:** A small array of candidate criterion drafts. **Workflow:** Server-side already follows `get_authoring_guide("scorecard_criterion")` rules. If the user is asking *you* to draft the wording before committing, fetch the guide first for the same rules. **When to use:** "Add a criterion about X" — gather options, let the user choose, then call `update_hunt_scorecard` with the chosen wording + a sensible rank.
generate_scorecard_criterion
**Purpose:** Fetch the in-house authoring rules + canonical variable list for one kind of artifact you're about to write (outreach message, connection note, scorecard criterion, requirements filter, sourcing setup). The same rules drive Umamy's built-in AI generators — calling this keeps your output consistent with what the user already sees elsewhere in the product. **NOT for:** Reading the hunt's *values* (use `get_hunt_criteria` / `get_hunt_scorecard` / `get_hunt_configuration`). This tool returns *editorial guidance*, not data. **Returns:** `{ kind, guide: string }` — a markdown blob to follow when drafting. For message-template kinds the markdown includes a table of the only allowed `{{ placeholders }}`; using anything else will be rejected by the write tool. **When to use:** Before any of these writes, especially the first time per conversation. Cheap to call. - Before `set_hunt_message_sequence` (intro / follow-ups / approve / reject) → `kind: "outreach_message"`. - Before `set_hunt_message_sequence` with `connection_note_template` → `kind: "connection_note"` (smaller placeholder set, 200-char limit). - Before `update_hunt_scorecard` / `generate_scorecard_criterion` / `regenerate_hunt_scorecard` → `kind: "scorecard_criterion"`. - Before `update_hunt_criteria` / `apply_hunt_criteria_list` → `kind: "filters"`. - Before `set_hunt_sourcing` → `kind: "sourcing"`.
get_authoring_guide
**Purpose:** Full record for one candidate — profile (name, headline, experience, education), connection status, scorecard answers, score, and the entire message thread. **NOT for:** Just the messages (use get_candidate_messages — same data, leaner payload). Not for notes (use get_candidate_notes). **Returns:** A single candidate object including `messages` array. Use this when you want everything in one go. **When to use:** User asks "tell me about candidate X", "show me [name]'s profile", "what does the team know about this candidate?". **Required:** Both `organization_id` AND `hunt_id` — candidates are keyed by (candidate_id, hunt_id) on the backend; the same person may appear in multiple hunts as separate records. Get `hunt_id` from list_candidates (each candidate is tagged with the hunt it belongs to). **Workflow:** list_organizations → list_candidates(org_id) → get_candidate(org_id, hunt_id, candidate_id)
get_candidate
**Purpose:** The full LinkedIn message thread with one candidate — every message sent and received, with sender, body, timestamp, and delivery status. **NOT for:** Internal team notes about the candidate (use get_candidate_notes). Not for the profile / scorecard (use get_candidate). **Returns:** Array of messages. Outdated/superseded messages (status `MESSAGE_OUTDATED`) are filtered out. **When to use:** User asks "what did we say to candidate X?", "did [name] reply?", "show me the conversation with this person". **Required:** `organization_id` AND `hunt_id`. If the user just gives you a candidate name, find them with list_candidates first to grab the `hunt_id` tag. **Workflow:** list_organizations → list_candidates(org_id) → get_candidate_messages(org_id, hunt_id, candidate_id)
get_candidate_messages
**Purpose:** Internal notes left by team members on a candidate (free-text, ordered chronologically). Notes are NOT visible to the candidate — they're private commentary among the hiring team. **NOT for:** LinkedIn messages with the candidate (use get_candidate_messages). Notes and messages are completely separate systems. **Returns:** Array of `{ id, hunt_id, candidate_id, content, author_id, created_at }`, oldest first. **When to use:** User asks "what notes have we left on X?", "what did the team think of this candidate?", "any feedback on [name]?". **Note on hunt_id:** Optional. If the same person is in multiple hunts, omitting hunt_id returns notes across all of them within the org; pass hunt_id to scope to one. Org-wide authorization is always enforced. **Workflow:** list_organizations → list_candidates(org_id) → get_candidate_notes(org_id, candidate_id, [hunt_id])
get_candidate_notes
**Purpose:** Full record for one hunt — name, status, criteria, owner, timestamps, high-level config flags. **NOT for:** Pipeline funnel numbers (use get_hunt_metrics_distribution with metric=pipeline_status). Not for the scorecard / outreach config (use get_hunt_configuration). Not for candidates (use list_candidates with hunt_id). **Returns:** A single hunt object. **When to use:** User asks "tell me about hunt X", "what's the status of the Senior Engineer role?". Or you have a hunt_id from list_hunts and need its details. **Workflow:** list_organizations → list_hunts(org_id) → get_hunt(org_id, hunt_id)
get_hunt
**Purpose:** Get the estimated candidate pool size for the hunt's current criteria — the feedback signal used to suggest loosening (count = 0) or tightening (count in the thousands) filters. **NOT for:** Actually listing those candidates (use `preview_hunt_candidates` for a sample, or `list_candidates` after launch). **Returns:** `{ count: number }` — a quick estimate from the search backend. Requires the hunt to have a `backend_job_id`; if you get a "must sync first" error, call `sync_hunt_draft` and retry. **When to use:** After every meaningful criteria edit during requirements setup, so the user sees the pool changing in real time. **Workflow:** `update_hunt_criteria` → `sync_hunt_draft` (if not synced) → `get_hunt_candidate_count`.
get_hunt_candidate_count
**Purpose:** Inspect how a hunt is *configured* — the scoring rubric (scorecard), outreach message templates, and automation rules. **NOT for:** Pipeline numbers (use get_hunt_metrics_distribution with metric=pipeline_status). Not for the candidate list. Not for editing — this is read-only; configuration changes happen in the Umamy dashboard. **Returns:** Nested object with `scorecard` (criteria + weights), `outreach` (message templates / sequences), and `automation` (auto-actions on connection events). **When to use:** User asks "how is hunt X scoring candidates?", "what messages are being sent on the Senior Engineer hunt?", "show me the outreach setup", or wants to debug why candidates are scored a certain way. **Workflow:** list_organizations → list_hunts(org_id) → get_hunt_configuration(org_id, hunt_id)
get_hunt_configuration
**Purpose:** Read all candidate-filter fields on a hunt — the rows on `hunt_criteria` joined with their field templates so you know the slug, the human name, the type (text / select / multiselect / tags / entity-search / location / structured_object), whether it's required, current value, and option set for select fields. **NOT for:** The scoring rubric (use `get_hunt_scorecard`). Not for the outreach config or sourcing settings (use `get_hunt_configuration`). Not for resolving raw text into entity IDs — use `search_hunt_entities` for that. **Returns:** `{ criteria: [{ field_slug, field_name, field_type, is_required, field_value?, field_value_string_array?, field_value_search_criteria_array?, field_value_location?, helper_text, theme, display_order, entity_search_type }] }` — ordered by `display_order`. Reading the right value column for the field's type is your job (text→field_value, select/multiselect/tags→field_value_string_array, entity-search→field_value_search_criteria_array, location→field_value_location, structured_object→field_value as JSON string). **When to use:** - Starting a hunt-setup conversation — first call after getting the hunt id. - "What's left to fill in?" — work the `is_required`-and-empty rows first. - Before writing values via `update_hunt_criteria` — to know which columns + slug to send. **Workflow:** `get_hunt` → `get_hunt_criteria` → `update_hunt_criteria` (loop with `search_hunt_entities` / `search_hunt_locations` for entity/location fields).
get_hunt_criteria
**Purpose:** Bucket distribution for one hunt-analytics metric. Powers histograms (score, years-of-experience), pie charts (sentiment, tags), and the kanban-style pipeline funnel. Forwards to AWS gateway /metrics_distribution. **NOT for:** "Over time" trends (use get_hunt_metrics_timeseries). Not for fetching individual candidates (use list_candidates). **Returns:** `{ ok, metric, date_range, buckets: [{ range, total, per_job }], jobs, meta: { total_candidates, total_jobs, returned_jobs } }`. Each `bucket` is a category; `per_job` breaks the count down by hunt. **Available metrics:** - `pipeline_status` — candidate funnel (INGESTION → CONNECTION_SENT → CONNECTED → CANDIDATE_APPROVED → REJECTED_MERGED…). **Use this for "candidates by status" / "what's the funnel" questions.** - `score` — fit-score distribution in 10 buckets (0-10, 11-20, …, 91-100) - `yoe` — years-of-experience distribution (<1y, 1-2y, 3-5y, 6-10y, 10+y) - `sentiment` — POSITIVE / NEGATIVE / NEUTRAL counts of candidate replies - `tags` — tag counts (sorted descending; respects `top_n`) **When to use:** - "What's the funnel on hunt X?", "score distribution across my org", "sentiment of replies on the Senior Engineer hunt", "top tags on candidates" **Workflow:** - *Org-wide distribution:* list_organizations → get_hunt_metrics_distribution(org_id, metric) - *Per-hunt funnel:* list_organizations → list_hunts(org_id) → get_hunt_metrics_distribution(org_id, "pipeline_status", hunt_id) - *Cross-org:* list_organizations → loop through every id, calling this tool per org → combine yourself **`top_n`:** Only meaningful for `tags` and across-hunt distributions where there are many jobs — caps the per_job breakdown and merges the rest into `_other`.
get_hunt_metrics_distribution
**Purpose:** Time-series counter for one hunt-analytics metric over time. Powers trend charts ("messages sent per week", "connections accepted over the last 30 days"). Forwards to AWS gateway /metrics_timeseries. **NOT for:** Bucket distributions like score histograms or pipeline funnels (use get_hunt_metrics_distribution). Not for organization-level metrics like team members or billing. **Returns:** `{ ok, metric, date_range: { from, to }, interval, total, series: [{ period, total, ...per_job }], series_keys }`. Each `series` entry is a time bucket; `per_job` keys break the count down by hunt. **Available metrics:** - `candidates_sourced` — new candidates added to the funnel (INSERT events) - `candidates_enriched` — candidates that passed enrichment - `connections_sent` — LinkedIn connection requests sent - `connections_accepted` — connection requests accepted by the candidate - `messages_sent` — outbound messages sent to candidates - `messages_received` — inbound replies from candidates - `positive_responses` — replies with POSITIVE sentiment - `negative_responses` — replies with NEGATIVE sentiment - `neutral_responses` — replies with NEUTRAL sentiment - `candidates_shortlisted` — candidates moved to CANDIDATE_APPROVED - `candidates_rejected` — CONNECTION_REJECTED_*, CANDIDATE_REJECTED - `candidates_not_interested` — CANDIDATE_NOT_INTERESTED* **When to use:** - "How many connections were sent this week?", "trend of replies over the last month", "show messages sent per day on hunt X" - Any "over time" question **Workflow:** - *Org-wide trend:* list_organizations → get_hunt_metrics_timeseries(org_id, metric) - *Per-hunt trend:* list_organizations → list_hunts(org_id) → get_hunt_metrics_timeseries(org_id, metric, hunt_id) - *Cross-org trend:* list_organizations → loop through every id, calling this tool per org → combine yourself (note: response shapes don't merge cleanly; per-org summaries are usually what users want) **Date filters:** `date_from` / `date_to` accept ISO 8601 (`2026-04-01`) or relative (`-30d`, `-1y`). `interval` is `day | week | month` and defaults sensibly based on range. **Computed rates:** Rates like "connection acceptance rate" are not stored — derive them by calling two timeseries (`connections_accepted` and `connections_sent`) and dividing.
get_hunt_metrics_timeseries
**Purpose:** Read the evaluation scorecard for a hunt — the list of `{ id, text, is_mandatory, rank }` items each candidate will be scored against. **NOT for:** Candidate-filter criteria (`get_hunt_criteria`). Not for individual candidate scores (use the candidate tools). **Returns:** `{ criteria: [{ id, text, is_mandatory, rank }] }` — empty list if no scorecard has been built yet. **When to use:** Before `update_hunt_scorecard` (read-modify-write), or to check whether the scorecard meets the "≥3 items" bar before treating the scorecard step as done. **Workflow:** `get_hunt_criteria` (hiring brief) → `get_hunt_scorecard` → `update_hunt_scorecard` (or `regenerate_hunt_scorecard` / `generate_scorecard_criterion` for AI-assisted drafting).
get_hunt_scorecard
**Purpose:** Backend-computed "what's left to set up" checklist for one hunt. Mirrors the hunt-edit stepper and returns only the items that are relevant (LinkedIn / message-sequence items appear only for outbound hunts; the ATS item appears only when the org has an active ATS connection). Each item is server-evaluated as `complete` from the authoritative state (Supabase `hunt_criteria` / `hunts.persona_id` + AWS `Job` sourcing / scorecard / outreach / ATS). **NOT for:** How the hunt is configured today (use `get_hunt_configuration` — that returns the actual scorecard rubric, outreach templates, automation rules). Not for editing — this is read-only; the matching write tools (`set_hunt_sourcing`, `update_hunt_criteria`, `update_hunt_scorecard`, `set_hunt_persona`, `set_hunt_message_sequence`, `set_hunt_ats_routing`) live in the hunt-setup toolset. Not for pipeline funnel numbers (use `get_hunt_metrics_distribution`). **Returns:** `{ items: [{ key, step: "sourcing"|"requirements"|"scorecard"|"outreach", order, description, instructions, complete }], finished }`. `key` is the stable item identifier (`setup_sourcing`, `clarify_key_requirements`, `establish_scorecard`, `connect_linkedin_account`, `setup_message_sequence`, `connect_ats`) — clients use it to localize `description`. `order` is contiguous after irrelevant items are filtered out. `instructions` is server-owned English guidance for the AI on how to complete that item (it points at the matching `get_authoring_guide(kind)` + the write tool to use); translate when you speak to the user, per the "match the user's language" rule. `finished` is true only when every returned item is complete. **When to use:** - User asks "what's left to set up hunt X?", "is hunt X ready to launch?", "why can't I launch?", "what's the next step on the SDR hunt?" - Start of a hunt-setup conversation, to plan the walkthrough - Before claiming a hunt is ready to launch — never say it's ready unless `finished === true` **Workflow:** `get_hunt_setup_checklist(org_id, hunt_id)` → for each `complete: false` item in `order`, follow its `instructions` (which calls out `get_authoring_guide(kind)` + the right write tool) → re-call `get_hunt_setup_checklist` after meaningful writes to surface progress.
get_hunt_setup_checklist
**Purpose:** Hunt totals by lifecycle status — `{ total_hunts, live_hunts, draft_hunts, paused_hunts, completed_hunts }`. Counts hunts themselves, not candidates inside them. **NOT for:** Per-hunt candidate funnel numbers (use get_hunt_metrics_distribution with metric=pipeline_status). Not for activity analytics like connections_sent or messages_received (use get_hunt_metrics_timeseries). **Returns:** `{ total_hunts, live_hunts, draft_hunts, paused_hunts, completed_hunts }` for one org. **When to use:** User asks "how many hunts do I have?", "how many active campaigns?", "give me an overview of my workspace". **Workflow:** list_organizations → get_organization_metrics(org_id) **Cross-org:** Always returns counts for one org. To answer "how many hunts across all my orgs?", loop: list_organizations → for each id, get_organization_metrics(id) → sum yourself.
get_organization_metrics
**Purpose:** List the org's active ATS connections (Workable, Greenhouse, Lever, Ashby, …). Use this to decide whether the "Connect ATS" item on the setup checklist is relevant and which connection to map to the hunt. **NOT for:** Connecting a new ATS — that's a browser OAuth flow handled by the in-app `AtsConnectionModal` (surfaced via the local "Connect ATS" chat button). **Returns:** `{ ats_connections: [...] }` — pick `ats_connection_pk` to then call `list_ats_jobs`, then map via `update_hunt_configuration`. **When to use:** Anywhere ATS is in scope — before mapping the hunt to an ATS job, before suggesting the user connect a new ATS.
list_ats_connections
**Purpose:** List jobs available on one ATS connection so the assistant can pick the right `ats_job_id` to map to the hunt. **NOT for:** Listing connections (`list_ats_connections` first). Not for writing the mapping — pair with `update_hunt_configuration` (`ats_connection_pk` + `ats_job_id`). **Returns:** `{ ats_jobs: [...] }`. **When to use:** Right before `update_hunt_configuration` in inbound-with-ATS or send-approved-to-ATS flows.
list_ats_jobs
**Purpose:** List candidates (profiles surfaced into a hunt's pipeline) for one organization. Each candidate has a profile, connection status, score, and message thread. **NOT for:** Listing hunts (use list_hunts). Not for a single candidate's full record (use get_candidate). Not for messages or notes (use list_messages / list_notes or the candidate-scoped variants). **Returns:** Array of candidate objects with profile fields, `connection_status`, score, scorecard answers, message thread, and a `hunt_id` tag (so you can resolve back to the hunt for follow-up calls). **When to use:** - User asks "show me candidates", "who's connected on hunt X?", "list everyone who replied" - Need to find a candidate_id before drilling into get_candidate / get_candidate_messages / get_candidate_notes **Workflow:** list_organizations → list_candidates(org_id, [hunt_id], [status]) → get_candidate(org_id, hunt_id, candidate_id) / get_candidate_messages(...) / get_candidate_notes(...) **Filters:** - `hunt_id` — scope to a single hunt's pipeline - `status` — filter by connection status (e.g. CONNECTED, PENDING, REPLIED, REJECTED) **Pagination:** Set `limit` (and pass `cursor` from a previous response's `next_cursor`) to page through one hunt's candidates — only works when `hunt_id` is set. Without `hunt_id` the v1 endpoint fans out across every hunt in the org and returns a single merged page; use `limit` to cap. **Cross-org:** Always returns candidates for one org. To search across orgs, loop: list_organizations → for each id, list_candidates(id) → combine yourself.
list_candidates
**Purpose:** List hunts (recruitment campaigns) for one organization. A hunt is a single open role being filled — it has a name, target candidate criteria, an outreach configuration, and a candidate pipeline. **NOT for:** Listing candidates (use list_candidates). Not for hunt analytics like funnel counts or activity over time (use get_hunt_metrics_distribution / get_hunt_metrics_timeseries). **Returns:** Array of hunts with `id`, `name`, `status` (DRAFT/LIVE/PAUSED/COMPLETED), creation timestamps. Use `id` with the per-hunt tools below. **When to use:** - User asks "show my hunts", "what roles am I hunting for?", "list active campaigns" - Need a hunt id before drilling into candidates or analytics for a specific role **Workflow:** list_organizations → list_hunts(org_id) → get_hunt / get_hunt_configuration / list_candidates(hunt_id) / get_hunt_metrics_* **Cross-org:** Always returns hunts for one org. To list across all orgs, loop: list_organizations → for each id, call list_hunts(id) in parallel → merge yourself.
list_hunts
**Purpose:** Flat list of LinkedIn messages across one organization — useful for activity reports, "what got sent today?", or recent reply scans without pulling full candidate objects. **NOT for:** A single candidate's thread (use get_candidate_messages — same data, indexed under one person). Not for internal notes (use list_notes). **Returns:** Flat array of messages, each tagged with its `hunt_id` (so you can resolve back to the hunt). Outdated messages are filtered out. **When to use:** User asks "how many messages went out this week?", "show me recent replies", "list outbound messages on hunt X". **Workflow:** list_organizations → list_messages(org_id, [hunt_id], [candidate_id], [status]) **Filters:** - `hunt_id` — scope to one hunt - `candidate_id` — scope to one candidate (REQUIRES `hunt_id`) - `status` — e.g. MESSAGE_SENT, MESSAGE_RECEIVED **Cross-org:** Always returns messages for one org. To scan across orgs, loop: list_organizations → for each id, list_messages(id) → combine yourself.
list_messages
**Purpose:** Flat list of internal team notes across one organization. Useful for activity scans like "what did the team comment on this week?". **NOT for:** Notes on a single candidate (use get_candidate_notes — same data, scoped). Not for LinkedIn messages (use list_messages). **Returns:** Flat array of notes ordered most-recent first, each with `hunt_id`, `candidate_id`, `content`, `author_id`, `created_at`. **When to use:** User asks "show me recent team notes", "what comments has the team left on this hunt?", "list notes across my org". **Workflow:** list_organizations → list_notes(org_id, [hunt_id], [candidate_id]) **Filters:** `hunt_id` and/or `candidate_id` to scope. **Cross-org:** Always returns notes for one org. To scan across orgs, loop: list_organizations → for each id, list_notes(id) → combine yourself.
list_notes
**Purpose:** List every Umamy organization (workspace) the signed-in user is a member of. **This is your entry point** — almost every other tool needs an `organization_id`, and this is how you discover them. **NOT for:** Listing hunts inside an org (use list_hunts). Not for fetching teammates, billing, or org settings. **Returns:** Array of `{ id, name, role }`. Pass the `id` as `organization_id` to other tools. **When to use:** - First call in almost any conversation that touches Umamy data — you can't address most resources without an org id - User asks "what organizations / companies do I have access to?" - Disambiguating which org owns a hunt or candidate before drilling deeper **Workflow patterns:** - *Single-org:* list_organizations → pick one id → call list_hunts / list_candidates / get_hunt_metrics_* with that id - *Cross-org analysis:* list_organizations → loop through every id, calling tools per org in parallel, combine results yourself - *Drill into a hunt:* list_organizations → list_hunts(org_id) → get_hunt(org_id, hunt_id) - *Drill into a candidate:* list_organizations → list_candidates(org_id) → get_candidate(org_id, candidate's hunt_id, candidate_id) **Why no automatic fan-out:** Different tools have different response shapes; cross-org merging is the model's job, not the server's. Looping is explicit, parallelisable, and shows your work.
list_organizations
**Purpose:** List the organization's outreach personas — each ties a connected LinkedIn account to a tone-of-voice config that hunts can reuse for outbound messaging. **NOT for:** Connecting a new LinkedIn account — that's a browser OAuth flow handled by the in-app `LinkedInConnectionDialog` (the chat surfaces a "Connect LinkedIn" button locally; no MCP tool drives it). **Returns:** `{ personas: [...] }` — pick a `persona_id` to associate with the hunt's outreach via the outreach UI (the assistant can navigate the user to the outreach step and recommend one of these). **When to use:** "Which LinkedIn accounts can this hunt send from?" / before suggesting the user assign a persona during outreach setup.
list_personas
**Purpose:** Fetch a small sample of candidates that match the hunt's current criteria, to sanity-check the filters before launching. Read-only — these are not yet in the hunt's pipeline. **NOT for:** Hard counts (use `get_hunt_candidate_count`). Not for the live candidate pipeline (`list_candidates`). **Returns:** `{ candidates: [...] }` — a handful of profiles the search backend would surface today. **When to use:** "Show me what you'd find with these filters" / "are these the right kind of people?" — typically right before transitioning from requirements to scorecard. **Workflow:** Requires a `backend_job_id` like `get_hunt_candidate_count` — call `sync_hunt_draft` first if you've never synced.
preview_hunt_candidates
**Purpose:** Replace the entire scorecard with an AI-generated set grounded in the hunt's hiring brief. **NOT for:** Tweaking one criterion (`generate_scorecard_criterion`). Not for committing manual edits (`update_hunt_scorecard`). **Returns:** `{ data: { criteria: [...] } }` — the new persisted scorecard. **Workflow:** The server-side generator already follows `get_authoring_guide("scorecard_criterion")` rules — no need to fetch the guide before this tool. Fetch it only if you're planning to manually edit the result via `update_hunt_scorecard` afterwards. **When to use:** First-time scorecard creation, or when the brief changed materially.
regenerate_hunt_scorecard
**Purpose:** Resolve a free-text query into the structured LinkedIn entities required by hunt filters — companies, schools, locations, job titles, job functions, industries. Returns real entity records with the IDs the criteria fields need; never invent these IDs yourself. **NOT for:** Reading a hunt's current values (`get_hunt_criteria`). Not for writing filters — pair this with `update_hunt_criteria` to apply the chosen results. **Returns:** `{ results: [{ id, name, logo? }] }` (companies/schools/job-functions/industries) or `{ results: [{ country, region?, city? }] }` (locations) — depending on `type`. Always present the names to the user and let them confirm before writing. **When to use:** - Whenever the user mentions a company / university / city / industry to include or exclude. - Building include/exclude company lists from a brand ("competitors of Salesforce" → multiple parallel searches). **Workflow:** `search_hunt_entities` → confirm with user via `suggest_actions` (in the in-app chat) → `update_hunt_criteria` with the returned IDs.
search_hunt_entities
**Purpose:** Write the "ATS Sync" card on the Outreach step — what happens to candidates we approve once an ATS is connected. Whether to push them to the ATS at all, which stage they land in, which existing applicant stages we should *ignore* (don't message them), and whether we should skip anyone already in the recruiter's pipeline. **NOT for:** Mapping the hunt to a specific ATS job — that's an inbound-sourcing concern (`set_hunt_sourcing(ats_connection_pk, ats_job_id)`). Not for outreach messages or automation flags. **Returns:** `{ success: true, data: <full config> }`. **When to use:** Only relevant when the org has an active ATS connection AND the hunt is mapped to a job in it (`list_ats_connections` non-empty, `get_hunt_configuration.ats_connection_pk` set). Otherwise direct the user to connect/map first.
set_hunt_ats_routing
**Purpose:** Write the "Message Automation" card on the Outreach step — how aggressively Umamy sends without a human in the loop: connection-request approval mode, auto-send-on-accept, auto-send-everything, and the score threshold for auto-approval. **NOT for:** The actual message templates (`set_hunt_message_sequence`). Not for sender identity (`set_hunt_sender_identity`). Not for ATS routing (`set_hunt_ats_routing`). **Returns:** `{ success: true, data: <full config> }`. **Field notes:** - `automation_type` — gates how connection requests get approved: - `VALIDATE_ALL_CONNECTIONS` — every request needs a human OK. - `AUTO_APPROVE_ALL_CONNECTIONS` — send all of them automatically. - `AUTO_APPROVE_UMAMY_ANALYSIS` — Umamy decides per-candidate based on the scorecard. - `auto_send_first_message_on_accept` — once the connection is accepted, fire the intro automatically. - `auto_send_all_messages` — full hands-off mode for the whole sequence. - `auto_approve_threshold` — fit-score cutoff (0–100) above which candidates are auto-approved when `automation_type = AUTO_APPROVE_UMAMY_ANALYSIS`. Higher = stricter. **When to use:** "Run this on autopilot", "lower the auto-approve bar to 70", "I want to validate every connection myself".
set_hunt_message_automation
**Purpose:** Write the actual *messages* in the outreach flow — connection request note, intro message, follow-ups, and the approve/reject reply templates. Mirrors the "Message Sequence" cards in the Outreach step. **NOT for:** The automation behaviour around these messages (use `set_hunt_message_automation` for `automation_type` / auto-send flags / auto-approve threshold). Not for sender identity (`set_hunt_sender_identity`). Not for ATS routing (`set_hunt_ats_routing`). **Returns:** `{ success: true, data: <full config> }`. **Field notes:** - `initial_message_template` — the intro. Putting `[ ]` placeholders in it opts into LLM personalisation at send time (the backend routes it to `*_with_llm` automatically). - `reminder_outreach_templates_with_llm` — array of follow-ups, in order. Replaces the existing list (pass the full set you want, not a delta). - `min_days_before_follow_up` — cadence between messages in business days. - `connection_note_template` — short text on the connection request itself (≤ 200 chars on standard accounts, ≤ 300 on premium). - `approve_candidate_template_with_llm` / `reject_candidate_template_with_llm` — reply sent when the recruiter approves / rejects a candidate. **Validation:** Every template field is checked against the canonical placeholder list — any `{{ ... }}` not in the allowed set rejects the whole write with a hint. Bracket form `[ ... ]` is unrestricted (those are LLM-personalised at send time). **Workflow:** Call `get_authoring_guide("outreach_message")` (and, when writing the connection note, `get_authoring_guide("connection_note")`) before drafting — it lists the allowed placeholders and tone rules. Then `set_hunt_message_sequence(...)`. **When to use:** Anything that's "rewrite the intro", "set the follow-ups", "shorten the connection note", "change the reject message".
set_hunt_message_sequence
**Purpose:** Assign (or clear) the outbound LinkedIn persona on a hunt — the LinkedIn account the engine will send connection requests / messages from. Writes `hunts.persona_id` AND triggers an AWS-side hunt sync so the engine picks up the new sender identity in one call. **NOT for:** Creating a new persona or connecting a new LinkedIn account — that's a UI-only OAuth flow (surface `request_linkedin_connect` in the in-app chat to start it). Not for the outreach `language` / `booking_link` (use `set_hunt_sender_identity`). Not for the inbound-only configuration's `inbound_persona_id` on the configuration object (that's set by `set_hunt_sourcing`). **Returns:** `{ success: true, hunt: { id, persona_id }, sync: { ok, error? } }`. `sync.ok: false` is non-fatal — the supabase write succeeded but the engine doesn't see the change yet (usually because the hunt has no `backend_job_id` yet, i.e. the user has never synced). Tell the user and retry `sync_hunt_draft` after the first sync lands. **When to use:** - "Use [Jean] for this hunt" (after `list_personas` returned at least one). - "Switch this hunt to send from my hiring manager's account." - "Clear the persona on this hunt — I'm flipping it to inbound-only." (Pass `persona_id: null`.) **Workflow:** `list_personas` (to fetch the org's available personas + their LinkedIn account state) → confirm the user's pick via `suggest_actions` in the in-app chat → `set_hunt_persona` → `navigate_to_step("outreach")` so the user can see the picker reflect the change.
set_hunt_persona
**Purpose:** Set the "Sender Identity" card values on the Outreach step — the outreach `language` (`en` or `fr`) and the default `booking_link` (Calendly / Cal.com / etc.) the assistant should weave into messages. **NOT for:** Assigning the outbound LinkedIn persona / account — use `set_hunt_persona` for that (it writes `hunts.persona_id` and re-syncs the engine in one shot). If no persona exists yet for the org, surface `request_linkedin_connect` first. Also not for the message templates themselves (use `set_hunt_message_sequence`). **Returns:** `{ success: true, data: <full config> }`. **When to use:** - "We're sending in French" → flip `language`. - "Use this Calendly link for all hunts on this role" → set `booking_link`.
set_hunt_sender_identity
**Purpose:** Flip the hunt's sourcing mode (inbound / outbound / both) and, for inbound, point it at the right source — an ATS connection + job, a LinkedIn job posting, or a LinkedIn Recruiter hiring project. Partial: only the fields you pass are written. **NOT for:** Outreach content / automation / ATS routing settings (use the `set_hunt_message_*` / `set_hunt_ats_routing` tools). Not for connecting a brand-new ATS or LinkedIn account — those are OAuth flows handled in-app; the chat surfaces the connect buttons via the local `request_*_connect` tools. **Returns:** `{ success: true, data: <full config> }` — the persisted snapshot after the update. **When to use:** - "Make this hunt outbound only" / "switch to inbound + outbound". - "Hook the inbound pipeline up to my Greenhouse 'Senior Engineer' job". - "Use my LinkedIn job posting / hiring project for inbound". **Workflow:** `get_authoring_guide("sourcing")` (mode-picking + inbound-source rules) → `get_hunt_configuration` (see current state) → `set_hunt_sourcing(...)` → `navigate_to_step("sourcing")` (so the user sees the picker reflect the change) → `sync_hunt_draft` (so counts/previews pick up the new settings). **Pairings to keep in mind:** - `sourcing_settings.inbound_enabled = true` ⇒ also set one of the inbound sources below. - `linkedin_job_posting_id` and `linkedin_hiring_project_id` are mutually exclusive — passing one clears the other on the route. - `ats_connection_pk` + `ats_job_id` go together; you can list them via `list_ats_connections` / `list_ats_jobs` first.
set_hunt_sourcing
**Purpose:** Push the hunt's current criteria + config to the AWS engine so candidate-count / preview tools work, and so the configuration changes take effect — WITHOUT launching the hunt. Always sends `status: "draft"`; the route refuses any other status from this tool. **NOT for:** Launching the hunt live — that stays a deliberate human action in-app (`POST /hunts/:id/sync` with `status: "live"` is intentionally not exposed). Not for changing criteria values (`update_hunt_criteria`) — sync ships whatever's already on the row. **Returns:** The hunt's updated record, including a freshly-populated `backend_job_id` if this is the first sync. **When to use:** - First time after the user has provided enough criteria to query — unlocks `get_hunt_candidate_count` / `preview_hunt_candidates`. - After non-trivial criteria or config edits, before re-running counts. **Side effects:** Idempotent; safe to call repeatedly.
sync_hunt_draft
**Purpose:** Set values on one or more existing `hunt_criteria` rows by `field_slug`. Each update names ONE slug and AT MOST ONE value column appropriate to that field's type. Partial: untouched columns are left alone. **NOT for:** Adding/removing criterion templates (those are seeded at hunt creation). Not for writing the scorecard (`update_hunt_scorecard`). Not for the outreach / sourcing config (`update_hunt_configuration`). Not for entity-search values you haven't resolved — call `search_hunt_entities` first to get real IDs. **Returns:** `{ updated: [field_slug, …], skipped: [{ field_slug, reason }, …], sync: { ok, error? } }`. The route auto-syncs to AWS after a successful write, so `get_hunt_candidate_count` works immediately afterwards — no need to call `sync_hunt_draft` separately for criteria edits. Validation against `criteria_field_templates` happens at sync time: a bad value surfaces as `sync.ok: false` with the engine's error message. **Which column to send for which field type** (read these off `get_hunt_criteria` first): - text → `field_value` (string) - select / multiselect / tags → `field_value_string_array` (array of option values) - entity-search (companies, schools, …) → `field_value_search_criteria_array` (`[{ id, name, logo? }]`) - location → `field_value_location` (`[{ country, region?, city? }]`) - structured_object (degree-timing-filter, …) → `field_value` as a JSON string **When to use:** Every time the user gives a piece of the hiring brief that maps to a known criterion slug. **Workflow:** `get_authoring_guide("filters")` (editorial rules — order, loosen/tighten levers, what not to filter on) → `get_hunt_criteria` (slugs + types) → `search_hunt_entities` if needed → `update_hunt_criteria` (auto-syncs) → `get_hunt_candidate_count`.
update_hunt_criteria
**Purpose:** Replace the hunt's scorecard with a new set of criteria — each `{ id, text, is_mandatory, rank }`. This is a full replace, so include every criterion you want to keep (read first via `get_hunt_scorecard`). **NOT for:** Drafting from scratch — use `regenerate_hunt_scorecard` (whole thing) or `generate_scorecard_criterion` (one at a time). Not for evaluating candidates against the scorecard. **Returns:** `{ data: { criteria: [...] } }` — the persisted set. **When to use:** After the user confirms a draft, or to apply ranking / pinning edits. **Workflow:** `get_authoring_guide("scorecard_criterion")` (signal-based phrasing rules, char limits, examples) → `get_hunt_scorecard` → modify → `update_hunt_scorecard`. Aim for ≥ 3 criteria grounded in the hiring brief.
update_hunt_scorecard
How do I improve a ChatGPT Plugin's discoverability?
The levers are the listing surface agents actually read: names, descriptions, keywords, tool metadata, and registry health. Which lever matters depends on where discovery breaks, which is what continuous measurement shows.
What are Umamy alternatives on ChatGPT?
As of 2026-09-28, Umamy competes with BrightHire, Clera, DiSCPROFiL, Interview Feedback Extractor, JobMojito, Juicebox, Metaview, SeekOut, Talentin AI, Tenzo AI MCP, Testlify, Vettara in ChatGPT Interview Intelligence & Candidate Sourcing, ranked by public Discoverability Score.
Where is this profile measured?
This profile uses the geography attached to the latest public registry snapshot: US. Locale tags are intentionally omitted.