accept_candidate
ChatGPTAccept a candidate from the role's feed: adds them to the project, syncs to the ATS, and (when the role has auto-contact on) queues them for outreach. Get candidate_id from get_candidate_feed.
create_role
ChatGPTSource candidates for a job by creating a Noon role. Noon searches candidate databases, ranks matches against the role, and, when the user has connected sender accounts and turned on outreach, sends personalized email and LinkedIn outreach. Use it when the user asks Noon to source or recruit for a job (including from a JD URL). Returns the role ID and a portal URL where the user can review sourced candidates. AFTER creating, poll get_candidate_feed until candidates appear and present them — do not stop at "role created". BEFORE creating, gather the role's core targeting — titles/seniority, location(s) and whether remote is OK, years-of-experience range, must-have criteria, and target companies (or an explicit decision to source broadly). If the user has not provided these and they are not clear from the JD, ASK first rather than creating an under-specified role that sources too broadly. Propose values you can infer from the JD and confirm them; only ask about what is genuinely missing. Pass what you gather as titles, location, yoe, non_negotiables, nice_to_haves, and target_companies.
explain_candidate
ChatGPTThe recruiter-facing AI evaluation summary (why a candidate was accepted or rejected) by candidate_id. Returns only the sanitized text shown in the product — internal scoring, rubrics, and prompts are never exposed. Get candidate_id from find_candidates. Get role_id from list_roles.
find_candidates
ChatGPTList individual candidates for a role, filtered by name (partial), current company, decision (reviewed | accepted | rejected | added; default reviewed), and company_fit_rating (0=best fit … 4=worst). Returns name, title, company, fit, and a rejection reason when decision="rejected". Keyset-paginated: pass the returned next_cursor as "after". Use for "find <person>", "who from <company> got rejected", "show the accepted candidates", or to gather a cohort to compare. Get role_id from list_roles.
get_candidate
ChatGPTFull profile for one candidate (current company, title, location, years of experience, work history, education, skills, company fit) by candidate_id. Get candidate_id from find_candidates. Get role_id from list_roles.
get_candidate_feed
ChatGPTView the candidate feed for a role: the candidates Noon has sourced and surfaced — name, current position, location, YOE, match score, and Noon's reasoning. Use this to review candidates before accepting/rejecting them with accept_candidate / reject_candidate, and poll it after create_role until candidates appear.
get_outbound_sequence
ChatGPTRead a role's current outreach sequence: the ordered steps (LinkedIn connection invite, InMail, emails) with their wait times and message copy, plus the connection-accepted trigger messages. Call this before update_outbound_sequence when editing an existing sequence.
get_role_state
ChatGPTA diagnostic snapshot of one role's sourcing: whether it is currently running, its configuration (enabled / calibrating / paused at the sourcing cap / disabled), the sourcing cap, the must-have criteria, which evaluation relaxations are active, the search settings (titles, locations, experience, location radius, company restrictions), and how many candidates the search has reviewed so far. Call this FIRST for any question about how a role's search is doing, why it is/isn't producing candidates, or before proposing changes. reviewed_total counts candidates the search considered — not candidates delivered to the recruiter (funnel: reviewed -> accepted/rejected -> added to project). Get role_id from list_roles.
get_slack_referrals
ChatGPTWhere Slack referral asks ("Ask in Slack": Noon asks the teammates who know a candidate on LinkedIn to refer them) stand, for one role or (without role_id) every role at the company. Returns counts per stage — waiting_to_post (queued; waiting_by_reason says why: weekly limit, work hours, nobody in Slack), asked_no_pick_yet, no_pick_after_follow_ups, picked_outreach_pending, done, closed — and one row per ask (newest first; optional stage filter) with the candidate, who was asked and by whom, the pick and who made it, the latest update, the standout flag, and for a waiting ask when Noon expects to post it; company-wide rows also name their role. Use for referral summaries ("how many candidates are queued for Slack", "which picks still need outreach"). Only for companies with the Noon Referrals Slack app. Get role_id from list_roles.
give_feed_feedback
ChatGPTGive feedback about the candidate feed as a whole ("too many consultants", "I want more fintech backgrounds", "everyone is too senior"). Noon turns it into a concrete search criterion using the same path as the in-product feed editor, applies it to the role, re-scores the CURRENT feed against it, and shapes future sourcing — candidates that no longer fit are dropped on the next pass, and feedback that reverses a past rejection can bring those candidates back. Use this to steer the search as a whole; to action one specific person use reject_candidate instead.
list_rejection_reasons
ChatGPTList the rules a role has learned from past rejection reasons and feed feedback (the portal's past-rejections panel), most impactful first: the recruiter's words, the criterion Noon derived, and how many candidates each one rejected. Call this before unlearn_rejection_reason or edit_rejection_reason to get the reason_id. Entries of kind "must_have" are the role's own criteria; drop those with give_feed_feedback instead.
list_roles
ChatGPTList the active Noon roles for your company (most recent first). Use this to find the role_id for get_outbound_sequence / update_outbound_sequence when the role was created outside this conversation.
pool_diagnostics
ChatGPTDiagnose whether a small/slow pool is caused by the SEARCH filters or by post-search EVALUATION. Runs loosened search probes (looser titles, wider location, wider experience, broader company targeting, looser must-haves) and reports how many candidates each would add (strongest_levers), alongside the accepted/rejected/added funnel, active relaxations, recent automatic search adjustments, and the top rejection bottlenecks. Use for "why is the pool small", "are filters too tight", "why did this relax", "what should we loosen". Get role_id from list_roles.
query_events
ChatGPTAggregate a role's sourcing pipeline for investigation. group_by="event" gives the funnel counts (reviewed, accepted, rejected, added to project); group_by="day"|"week"|"month" gives a time series of activity (pass events=["suggested"] to chart when candidates were reviewed); group_by="company" ranks the source companies of the reviewed candidate pool; group_by="rejection_reason" gives rejection categories (Company, Seniority, Location, Education, Skills, Experience, Criteria, …). For outreach, events=["contacted"] counts candidates whose first message was actually sent, dated by that send (group_by="day" gives daily contacted); replies are interested / not_interested / invite_accepted. Optional since/until are ISO timestamps. Compose several calls to investigate — e.g. get_role_state first, then group_by="event" for the funnel, then group_by="rejection_reason" to see what is filtering people out. Get role_id from list_roles.
reject_candidate
ChatGPTReject a candidate from the role's feed. Pass a reason whenever the user gives one (e.g. "too junior", "only worked at consultancies") — Noon turns it into a concrete screening criterion, applies it to the role's criteria the same way an in-product rejection does, and re-scores the CURRENT feed against it so other candidates with the same problem are dropped instead of coming back. Omit reason for a simple pass, which removes the candidate and teaches the role nothing.
rejection_analysis
ChatGPTWhat is constraining a role's search: rejection reasons by category, PLUS the sole-blocker criteria — for each must-have, how many candidates fail ONLY that one (sole_blocker ≈ how many otherwise-qualified people you would recover by relaxing it). This is the highest-signal tool for "how do we widen the pool without dropping quality". Optionally scope to one company (e.g. "why were the Stripe people rejected?") via company or company_id. Get role_id from list_roles.
search_trace
ChatGPTA recruiter-safe causal timeline of recent sourcing runs: search-setting changes, automatic broadening (e.g. experience range), candidate-pool checks with counts, and post-search evaluation bottlenecks — in chronological order. Use for "what happened", "why did the search broaden/relax", "why did YOE/title/location/company targeting change", or "why did sourcing stall". Get role_id from list_roles.
undo_rejection
ChatGPTUndo the rejection of one candidate ("bring Jane back, that rejection was a mistake"): the candidate is re-evaluated and returns to the feed if they still fit, and anything their rejection reason taught the role is unlearned. Get candidate_id from find_candidates (decision="rejected") or the reject_candidate call.
update_outbound_sequence
ChatGPTWrite the outreach sequence for a role — replaces ALL existing steps, so pass the complete sequence (fetch it first with get_outbound_sequence when editing). Steps run in order: the first sends when outreach starts, each later step waits wait_days after the previous one. Message placeholders that auto-fill per candidate: {first_name}, {last_name}, {company}, {ai_intro} (an AI-personalized intro line — use it on the first InMail and the first email, since candidates often miss InMail but still see email). A typical sequence: connection invite → InMail 2 days later → 2-3 email follow-ups. Omit connection_accepted to keep the role's existing connection-accepted trigger; pass null to disable it.