MCP App Store
Productivity
Metaview icon

Metaview

by Metaview

Overview

Bring Metaview's hiring intelligence into Claude. Search, analyze, and extract insights from your recruiting data. Query conversations, source candidates, and start outreach. Use Claude alongside Metaview's AI agents to turn every conversation and signal into faster, better hiring decisions.

Tools

create_ai_field

ChatGPT
<usecase> Create a new AI field or update an existing one. AI fields are the primary tool for analyzing conversations at scale. Each field defines a question that is answered independently for every conversation it is applied to. This means you can extract specific data points from hundreds of conversations without hitting context window limits — each conversation is analyzed in isolation, and the structured results can then be aggregated, filtered, and grouped. WHEN TO USE: When the user wants insights across 20+ conversations, create an AI field to extract the specific data point, then use search_conversations or group_conversations to aggregate the results. This is far more effective than trying to read all transcripts. HELPING USERS APPROACH THE TASK: The tool automatically assesses and improves prompts before creating the field (unless skip_improvement=true), so you do not need to help the user craft the exact prompt — focus on helping them think through their approach: - If the user's request is broad (e.g., 'analyze the interviews'), help them identify what specific questions they want answered. What decisions are they trying to make? What patterns are they looking for? - If a single AI field won't capture what they need, suggest breaking it into 2-3 focused fields (e.g., one for candidate sentiment, one for key objections, one for salary expectations) rather than one catch-all. - Help them think about whether they need per-conversation detail (search) or an aggregate view (group by interviewer, department, etc.). IMPORTANT: Always confirm with the user before calling this tool. Describe the field you plan to create or update (name, prompt, value type) and get explicit approval. AI fields analyze every conversation they're used against, so the user should understand what will be created or modified on their behalf. </usecase> <instructions> Creating: When no field_id is provided, creates a new AI field. Before creating, the tool searches for existing fields (both system-provided and workspace-custom) that capture the same information. If a match is found, the existing field is returned instead of creating a new one. If the suggested match is not what you need, retry with skip_similarity_check=true to bypass the check and force creation. Updating: When field_id is provided, updates the existing field's name, prompt, and/or value_type. If the prompt, value_type, or name (for auto-prompted fields) changes, existing results are cleared and re-analysis is triggered on next query. AI fields are processed asynchronously. After creating or updating a field, use it in search_conversations or group_conversations to retrieve results. If results show evaluation_pending, retry after ~30 seconds. Use list_fields(search_term=...) to check for existing AI fields and prefab system fields before creating new ones — this tool also deduplicates automatically, but searching first avoids the overhead. Choosing a value_type: Fields are most useful when their values can be filtered, grouped, and sorted in reports. This means the output should be constrained to a known set of values whenever possible. - Yes/no questions → use boolean - Numeric scores or ratings → use number (e.g., 1-5 scale) - Lists of items → use list instead of comma-separated text - Categorical data → use single_line_text with the prompt constraining output to a fixed set of allowed values (e.g., "Respond with exactly one of: None, Low, Moderate, High"). Never let single_line_text produce free-form text with explanations — it should act like an enum so users can filter and group by exact values. Only use free-form text (single_line_text without constrained values, or long_text) when the answer is genuinely open-ended and cannot be represented as a number, boolean, list, or category. Args: name: Human-readable field name (e.g., "Candidate Salary Expectation"). prompt: Instructions for what to extract from transcripts (e.g., "Extract the candidate's salary expectations from the conversation"). value_type: The data type of the extracted value. One of: single_line_text, long_text, list, number, currency, date, boolean. field_id: Optional. The field ID of an existing AI field to update (e.g., "AI:<uuid>"). Omit to create a new field. skip_similarity_check: Optional. Set to true to skip the similarity check and force creation of a new field. Use this when a previous call returned already_existed: true but the suggested field does not meet your needs. Default false. skip_improvement: Optional. Set to true to skip the automatic column improvement step. By default, the tool assesses and improves the column definition (prompt, value_type) before creation. Set to true to create the field exactly as specified. Default false. Returns: field_id: The field's ID for use in other tools (e.g., "AI:<uuid>"). name: The field name. value_type: The field's value type. already_existed: Whether an existing field was returned instead of creating a new one (create only). similarity_explanation: When already_existed is true, explains why the existing field matched. updated: Whether an existing field was updated (update only). </instructions> <performance> IMPORTANT: Each AI field is analyzed per conversation. Analysis is asynchronous and takes longer with more conversations. Always apply narrow filters (date range, department, interviewer, etc.) in search_conversations or group_conversations to limit analysis to the conversations you actually need. Broad unfiltered queries will be slow and may hit evaluation limits. </performance>

create_report

ChatGPT
<usecase> Create a new report or update an existing one in the Metaview web-app. IMPORTANT: Only use this tool when the user explicitly asks to create or edit a saved report in Metaview. Do NOT use this tool for ad-hoc data analysis, answering questions, or running queries — use search_conversations, group_conversations, or get_chart_data for those. This tool persists a report that appears in the user's Reports list in the web-app. Before calling this tool, confirm with the user what they want the report to contain (name, filters, grouping, fields). Do not create reports speculatively. After creating or updating a report, share the url from the response with the user so they can open it in the web-app. </usecase> <instructions> Creating: Omit report_id. You MUST provide filters (can be an empty list for "all conversations"). Optionally set name, fields, grouping, and other configuration in the same call. Updating: Provide report_id of an existing report. Only the fields you include will be changed — omitted fields are left unchanged. Use list_fields to find valid field IDs for filters, fields, and grouping. Use list_field_values to find valid filter values. Args: report_id: ID of an existing report to update. Omit to create a new report. filters: Array of filter objects (required for create, optional for update). See search_conversations for the complete filter format reference. IMPORTANT: Date filter values must use a dict with scope and value, not a bare date string. Example: {"field_id": "default:start_time", "operation": "after", "value": {"scope": "relative", "value": -2592000}} name: Human-readable report name (e.g., "Engineering Interviews Q1"). description: Report description. group: Field ID to group conversations by (e.g., "OSPT:<uuid>"). Use list_fields to find field IDs. remove_grouping: Set to true to remove grouping from a report. Required because passing group=null is indistinguishable from omitting the parameter. field_ids: List of field IDs to show as columns (e.g., ["default:start_time", "OSPT:<uuid>"]). sort_field: Field ID to sort by. Must be one of the field_ids. sort_ascending: Sort ascending (true) or descending (false). Default true. metrics: Metrics for grouped reports. Array of objects, each with: metric_id (str), function (str: mean/median/max/min/sum), footer_aggregation_function (str), metric_arguments (dict). sort_metric: Which metric to sort groups by. Object with: metric_id (str), function (str), metric_arguments (dict). Pass null to sort by the group label. sort_metric_ascending: Sort groups ascending or descending. Default true. only_show_recorded_conversations: Include only recorded conversations. Default true. expand_rows: Expand table rows. Default false. min_group_conversation_count: Hide groups with fewer conversations than this. </instructions> <examples> Common filter examples: Last 30 days: [{"field_id": "default:start_time", "operation": "after", "value": {"scope": "relative", "value": -2592000}}] January 2024: [{"field_id": "default:start_time", "operation": "between", "value": {"scope": "absolute", "value": ["2024-01-01T00:00:00.000Z", "2024-02-01T00:00:00.000Z"]}}] Engineering department, last 90 days (get the field ID from list_fields): [{"field_id": "default:start_time", "operation": "after", "value": {"scope": "relative", "value": -7776000}}, {"field_id": "OSPT:<uuid>", "operation": "is_one_of", "value": ["Engineering"]}] My conversations (use "$self" — resolved to your participant ID automatically): [{"field_id": "default:contact", "operation": "includes_one_of", "value": ["$self"]}] My interviews as interviewer: [{"field_id": "default:interviewer", "operation": "includes_one_of", "value": ["$self"]}] Specific candidate (use contact UUID from list_field_values): [{"field_id": "default:candidate", "operation": "includes_one_of", "value": ["<candidate-contact-uuid>"]}] Specific interviewer (use contact UUID from list_field_values): [{"field_id": "default:interviewer", "operation": "includes_one_of", "value": ["<interviewer-contact-uuid>"]}] Example — create a report: create_report( name="Engineering Last 30 Days", filters=[{"field_id": "default:start_time", "operation": "after", "value": {"scope": "relative", "value": -2592000}}, {"field_id": "OSPT:<uuid>", "operation": "is_one_of", "value": ["Engineering"]}], field_ids=["default:start_time", "default:interviewer", "default:candidate"], sort_field="default:start_time", sort_ascending=false ) Example — rename a report: create_report(report_id="abc-123", name="New Report Name") </examples>

fetch_candidates

ChatGPT
<usecase> ALWAYS use this tool to look up one or more people or candidates. This is the ONLY way to retrieve candidate scorecards, ATS feedback, resume files, application history, and professional profile data. Do NOT try to scrape LinkedIn or other websites directly — this tool fetches richer data than any public page and includes internal ATS records. Look up candidates by LinkedIn URL, email, phone number, or participant ID. Returns per-candidate results with two sections each: - profile: Professional background (experience, education, skills, location, etc.). Available when a LinkedIn URL is provided or can be resolved from ATS data. - ats: Internal ATS data including: - scorecards: Interview scorecard responses (questions and answers/scores) - applications: Job applications with title, status, and stage - feedback: Interviewer feedback notes - files: Resumes and other attached documents with download URLs Only available when the candidate exists in your ATS and you have permission to access their data. Use this tool when you need to: - Look up scorecard results for one or more candidates - Get a candidate's application status or interview stage - Retrieve resume or document files for a candidate - Get a candidate's professional profile (experience, education, skills) - Check interviewer feedback on a candidate ATS data access requires one of: - You are a Metaview admin - You are an ATS admin - The candidate appeared in a conversation you have access to Accepts 1-10 candidates per call. </usecase> <instructions> Args: candidates: A list of candidate lookups. Each entry is a dict with at least one identifier: - linkedin_url: LinkedIn profile URL (e.g. "https://www.linkedin.com/in/john-doe") or bare shorthand (e.g. "john-doe"). - email: Candidate email address. - phone_number: Candidate phone number. - participant_id: Metaview participant ID for direct lookup. This is the internal ID shown in conversation data (e.g. from the default:candidate field in search_conversations results). </instructions> <response_format> {"candidates": [ { "lookup": {"email": "john@example.com"}, "profile": { "name": "John Doe", "linkedin_url": "https://www.linkedin.com/in/john-doe", "location": "San Francisco, CA", ...}, "ats": { "name": "John Doe", "applications": [{"job_title": "...", "status": "...", "stage": "..."}], "scorecards": [{"question": "...", "answer_or_score": "..."}], "feedback": ["..."], "files": [{"file_name": "resume.pdf", "download_url": "..."}]} }, { "lookup": {"linkedin_url": "https://www.linkedin.com/in/jane-smith"}, "error": "No candidate found matching the provided identifiers." } ]} </response_format> <examples> Fetch a single candidate by email: fetch_candidates(candidates=[{"email": "john@example.com"}]) Fetch multiple candidates: fetch_candidates(candidates=[ {"linkedin_url": "https://www.linkedin.com/in/john-doe"}, {"email": "jane@example.com"}, {"participant_id": "abc-123-def"}]) Fetch with multiple identifiers per candidate (for better matching): fetch_candidates(candidates=[ {"linkedin_url": "https://www.linkedin.com/in/john-doe", "email": "john@example.com"}]) </examples>

find_candidate_in_sequences

ChatGPT
<usecase> Check if a candidate is enrolled in any sequences. Look up a candidate by ID, LinkedIn URL, email address, or phone number and return all sequences they are (or were) enrolled in, including sequences created by other users. Useful before adding someone to a new sequence to avoid duplicate outreach. Provide at least one lookup parameter. If candidate_id is given, it is used directly. Otherwise, linkedin_url/email/phone_number are matched with OR logic. </usecase> <instructions> Args: candidate_id: Candidate ID for direct lookup (preferred when known). linkedin_url: LinkedIn profile URL (normalized automatically). email: Email address to match against candidate primary email or the to_email used in the sequence. phone_number: Phone number to match against candidate primary phone. </instructions> <response_format> {"candidates": [ {"candidate_id": "...", "candidate_name": "John Doe", "candidate_email": "john@example.com", "candidate_phone": "+1234567890", "candidate_linkedin_url": "https://www.linkedin.com/in/johndoe", "sequences": [ {"sequence_id": "...", "sequence_name": "Outreach v2", "status": "active", "created_at": "2024-01-10T...", "steps_sent": 2, "steps_total": 4}]}]} </response_format> <examples> Check by LinkedIn: find_candidate_in_sequences(linkedin_url="https://linkedin.com/in/johndoe") Check by email: find_candidate_in_sequences(email="john@example.com") Check by multiple identifiers: find_candidate_in_sequences(linkedin_url="...", email="john@example.com") </examples>

generate_notes

ChatGPT
<usecase> Generate (or regenerate) AI Notes for a conversation, optionally with a specific template. Use this tool to: - Trigger notes generation for a conversation that has no notes yet. - Regenerate notes using a different template (built-in or custom). - Preview how a newly created or updated template renders on a real conversation. </usecase> <instructions> Args: conversation_id: The conversation (session) ID to generate notes for. template: Optional. Built-in template options: 'question_and_answer' (Question and Answer) 'conversational' (Topic Highlights) 'recruiter_screen' (Recruiter Screen) 'generic_debrief' (Generic Debrief) 'team_role_debrief' (Team-Specific Debrief) 'technical_role_debrief' (Technical Debrief) 'intake_call' (Intake | Role Scope) 'candidate_pack' (Candidate Pack) 'coding_interview' (Coding Interview) 'system_design_interview' (System Design Interview) 'role_alignment' (Role Alignment) 'client_call' (Client Call) Use 'custom_definition' with template_definition_id for custom templates. Omit to auto-select the best template for the conversation. template_definition_id: Optional. UUID of a custom note template. Required when template='custom_definition'. Get the ID from list_note_templates or get_note_template. </instructions> <response_format>{"status": "generation_queued", "message": "..."}</response_format> <examples> Generate with auto-selected template: generate_notes(conversation_id="12345") Generate with a built-in template: generate_notes(conversation_id="12345", template="question_and_answer") Generate with a custom template: generate_notes(conversation_id="12345", template="custom_definition", template_definition_id="<uuid>") </examples>

get_chart_data

ChatGPT
<usecase> Get chart data for aggregate time-series or scatter plots. Each chart_input is processed independently. The chart type is determined automatically from the keys present: - Aggregate chart (line/bar/stacked bar): include function AND interval in the chart_input. Returns time-bucketed data points. - Values chart (scatter plot): omit function and interval. Returns one data point per conversation. IMPORTANT: Not all metrics support scatter charts. Check the metric's chart_types from list_fields. Only metrics with "scatter" in chart_types can be used as scatter plots (omitting function/interval). For example, "Conversation Count" only supports bar/line (aggregate) charts, not scatter plots. Use list_fields to discover valid metric_id values and their supported chart types and aggregation functions. </usecase> <instructions> See search_conversations for the complete filter format reference. IMPORTANT: Date filter values must use a dict with scope and value, not a bare date string. Example: {"field_id": "default:start_time", "operation": "after", "value": {"scope": "relative", "value": -2592000}} Args: chart_inputs: Array of chart specifications. Each dict must have: metric_id (str, required) — the metric to chart. Call list_fields to discover available IDs. Metric IDs start with "aggregation:" (e.g. "aggregation:session_count", "aggregation:actual_duration") or "AI:<uuid>" for AI fields. function (str) — one of: Average, Median, Count, Sum, Max, Min, Cumulative, Rolling Average. Required for aggregate charts, must be omitted for scatter charts. Must be in the metric's supported chart_functions (from list_fields). interval (str) — one of: day, week, month, quarter. Required for aggregate charts, must be omitted for scatter charts. Both function and interval must be provided together or both omitted. metric_arguments (dict, optional) — extra arguments. Check required_arguments from list_fields. For contact-scoped metrics (question_count, talk_time, minutes_late) you MUST pass {{"scope": "internal"}} or {{"scope": "external"}}. "internal" = interviewers/hiring team, "external" = non-team participants (candidates, clients, etc.). function_arguments (dict, optional) — for Rolling Average, include {"windowIntervalCount": <int>}. NOTE: For values (scatter) charts, omit function and interval. report_id: ID of a saved report. filters: Array of filter objects, each with field_id (str), operation (str), and value. only_show_recorded_conversations: When true (default), only return recorded conversations. Set to false to also include unrecorded conversations (scheduled calls that were not recorded, or upcoming conversations that haven't happened yet). group: Field ID to scope the chart to conversations that have a value for this field (e.g. "OSPT:<uuid>" limits the chart to conversations with a department set). This is a filter, NOT a breakdown — it does not split the chart by group member. To get per-group metrics, use group_conversations with metrics instead. IMPORTANT: This must be a field ID (e.g. "OSPT:<uuid>", "default:interviewer"), NOT a metric ID. Do not pass "aggregation:..." IDs here. min_count: Minimum conversations per group (when group is specified). timezone_offset_minutes: Timezone offset for date bucketing (default 0 = UTC). Only used by aggregate charts. </instructions> <response_format> {"charts": [ {"metric_id": "aggregation:session_count", "function": "Count", "interval": "week", "data": [ {"start_date": "2024-01-01", "value": 15.0, "values": [{"label": null, "value": 15}]} ]}, {"metric_id": "aggregation:actual_duration", "data": [ {"conversation_id": 12345, "date_time": "2024-01-15 10:00:00+00:00", "value": 45.2, "label": "45 min"} ]} ]} </response_format> <notes> Note: AI field values are processed asynchronously. If "ai_processing" is present in the response, some values are still being computed. Poll by retrying the same call every ~30 seconds until the data is complete. IMPORTANT: Including AI fields triggers analysis for every matching conversation that hasn't been analyzed yet. Always apply tight filters (date range, department, interviewer, etc.) to keep the set small and get results quickly. Broad unfiltered queries will be slow and may hit evaluation limits that require narrowing your search. </notes> <examples> Weekly conversation count trend (aggregate chart): get_chart_data( chart_inputs=[{"metric_id": "aggregation:session_count", "function": "Count", "interval": "week"}], filters=[{"field_id": "default:start_time", "operation": "after", "value": {"scope": "relative", "value": -7776000}}]) Scatter plot of individual interview durations (values chart): get_chart_data( chart_inputs=[{"metric_id": "aggregation:actual_duration"}], filters=[{"field_id": "default:start_time", "operation": "after", "value": {"scope": "relative", "value": -7776000}}]) </examples>

get_enrichment_status

ChatGPT
<usecase> Get the workspace's enrichment credit status, usage breakdown, and optionally list individual enrichment attempts. Always returns: - Monthly credit allowance and remaining balance - Usage breakdown by enrichment type (email vs phone) for the requested month - Active top-up credit purchases with remaining balances and expiry dates Optionally returns: - Per-user usage breakdown (include_usage_by_user=true) - Individual enrichment attempts (include_enrichment_attempts=true) </usecase> <instructions> Args: person_id: Filter usage and attempts to a specific person (admin only). Non-admins always see only their own data regardless of this parameter. month: Month to report on as YYYY-MM (e.g. "2026-01"). When provided, usage is scoped to that calendar month. When omitted, usage covers the current month to date (no end boundary). include_usage_by_user: When true, include per-user usage breakdown. Default false. include_enrichment_attempts: When true, append the list of individual enrichment attempts. Default false. enrichment_type: Filter attempts by type: "email" or "phone". Only used when include_enrichment_attempts=true. offset: Pagination offset for attempts (default 0). limit: Number of attempts per page (default 50, max 100). </instructions> <response_format> {"credits": { "monthly_limit": 500, "monthly_used": 450, "monthly_remaining": 50, "top_up_credits_available": 200, "total_available": 250, "warning_threshold_reached": false}, "usage": { "email": {"enrichments_count": 50, "credits_used": 150}, "phone": {"enrichments_count": 30, "credits_used": 300}, "total_credits_used": 450}, "usage_by_user": [{...}], "top_ups": [{...}], "enrichment_attempts": [{...}], "enrichment_attempts_total_count": 150, "enrichment_attempts_has_more": true} </response_format> <notes> credits reflects the current live balance regardless of the month parameter. usage is scoped to the requested month. All workspaces receive a base allowance of 500 credits per month. usage_by_user is only present when include_usage_by_user=true. enrichment_attempts fields are only present when include_enrichment_attempts=true. </notes> <examples> Check credit status and usage: get_enrichment_status() Usage for January 2026: get_enrichment_status(month="2026-01") Per-user breakdown: get_enrichment_status(include_usage_by_user=true) Include individual enrichment attempts: get_enrichment_status(include_enrichment_attempts=true) </examples>

get_note_template

ChatGPT
<usecase> Fetch a single AI Notes custom template with its full section configuration. Use list_note_templates first if you don't have a template ID. </usecase> <instructions> Args: template_id: Required. UUID of the template. INTERNAL ONLY — never show this id to the user; refer to templates by name. </instructions> <response_format> {"template": {"id": "...", "name": "...", "version": 3, "created_by": {"name": "Alice Smith"}, "created_at": "...", "updated_at": "...", "section_count": 2, "sections": [...]}} The id is INTERNAL ONLY — never show it to the user. </response_format>

get_sourcing_analytics

ChatGPT
<usecase> Get aggregate sourcing metrics for your workspace with flexible filtering and grouping. Use this to answer questions like: - How many searches / candidates / feedback events in a time period? - What is the acceptance rate overall, per user, or per search? - Who created the most searches or gave the most feedback? - Weekly/monthly trends of sourcing activity - How many searches are on recurring schedules or linked to sequences? - Are we using all our sourcing seats? </usecase> <instructions> PERMISSIONS: - Non-admin users: results are always scoped to their own data (searches they created, feedback they gave). The user_id parameter is ignored for non-admins. - Admin users: results cover the entire workspace. Admins can optionally pass user_id to filter to a specific team member. - seat_utilization metric: admin-only. - search_id: verified against the user's access (ownership, sharing, or admin). Args: metric (REQUIRED): What to measure. One of: acceptance_rate, accepted, candidates, candidates_without_feedback, feedback, maybe, rejected, scheduled_searches, searches, searches_with_sequences, seat_utilization time_period: Shorthand time filter. One of: last_30_days, last_7_days, last_90_days, last_month, last_quarter, last_week, this_month, this_quarter, this_week, today, yesterday start_date: ISO date (YYYY-MM-DD) for custom range start. Overrides time_period. end_date: ISO date (YYYY-MM-DD) for custom range end. group_by: Break down results. One of: day, feedback_value, mode, month, search, user, week user_id: (admin only) Filter to a specific user's data by person ID. search_id: Filter to a specific search (UUID). Must be accessible to the user. include_archived: Include archived searches (default false). limit: Max groups to return (default 20, max 100). offset: Pagination offset for grouped results (default 0). For comparisons (e.g. this month vs last month), call this tool twice with different time_period values. </instructions> <response_format>{"metric": "acceptance_rate", "value": 38.4, "groups": [{"label": "Alice Smith", "id": 123, "value": 52.1, "count": 245}], "total_groups": 45, "has_more": true, "time_range": {"start": "2026-04-01", "end": "2026-04-29"}, "filters_applied": {"time_period": "this_month"}}</response_format> <examples> Searches this month: get_sourcing_analytics(metric="searches", time_period="this_month") Weekly candidate trend: get_sourcing_analytics(metric="candidates", group_by="week", time_period="last_90_days") Acceptance rate by user: get_sourcing_analytics(metric="acceptance_rate", group_by="user", time_period="last_30_days") Check seat utilization: get_sourcing_analytics(metric="seat_utilization") </examples> <data_model> - A SEARCH is a sourcing conversation with an AI agent that finds candidates matching your requirements. Each search has a conversation thread, an ICP (Ideal Candidate Profile), and a list of surfaced candidates. Searches have a mode (SOURCE or RESEARCH) and can be active or archived. - The agent goes through phases: idle (waiting for input), busy (actively searching), waiting (needs your feedback on candidates), error (something went wrong). - CANDIDATES are people surfaced by the agent. Each has a profile summary and reasoning sections explaining why they match. - FEEDBACK is a YES, NO, or MAYBE verdict given by a user on a candidate. The acceptance rate is the percentage of YES out of total feedback. - An ICP is the Ideal Candidate Profile the agent builds from your conversation. It evolves as you provide feedback and refine requirements. - A SCHEDULED SEARCH is a search configured to run on a recurring schedule. - A SEARCH-SEQUENCE LINK connects a sourcing search to an outreach sequence, so accepted candidates flow into automated outreach. </data_model>

get_sourcing_messages

ChatGPT
<usecase> Retrieve the conversation history for a sourcing search. Returns messages between you and the sourcing agent, including text messages and structured attachments. Structured attachments (candidates, ICP, calibration, file, filter_proposal) are rendered as separate messages in the response. Use this to: - Check the agent's latest response after sending a message - Review the full conversation history - See which candidates were surfaced (candidate attachments show IDs — use list_sourcing_candidates or fetch_candidates to get full details) Poll this after sending a message. The agent phase indicates progress: - busy: Agent is still working. Poll again in a few seconds. - idle/waiting: Agent has finished and is waiting for your input. - error: Something went wrong. </usecase> <instructions> Args: search_id: The search ID to retrieve messages for. limit: Maximum number of messages to return (default 50, max 200). offset: Number of messages to skip for pagination (default 0). Messages are ordered chronologically. </instructions> <response_format>{"search_id": "550e8400-...", "phase": "idle", "messages": [{"role": "user", "content": "Find me senior backend engineers...", "timestamp": "2025-01-15T10:30:00Z", "message_type": "text"}, {"role": "assistant", "content": "Candidates presented: id1, id2, id3", "timestamp": "2025-01-15T10:32:00Z", "message_type": "candidates"}], "total_count": 12, "has_more": false, "next": "The agent is idle. Read the latest message to understand the current state..."}</response_format> <examples> Get latest messages: get_sourcing_messages(search_id="550e8400-...") Paginate: get_sourcing_messages(search_id="550e8400-...", limit=20, offset=20) </examples>

get_user_context

ChatGPT
<usecase> IMPORTANT: Call this tool FIRST, before any other tool. Returns your identity, role, and what data you can access. - workspace_name: The name of the workspace you are connected to. - participant_id: Your contact UUID. Use "$self" in filter values instead of this raw UUID — it is resolved automatically to your participant_id. - user_id: Your numeric user ID. - is_admin: Whether you have admin access. - is_paying_plan: Whether you are on a paid plan. Free users have limited access to transcripts, summaries, and AI fields. - data_access: Describes exactly which conversations you can see. Read this before drawing conclusions about completeness of query results. An ACTION is a structured prompt in tool responses when the user needs to take an action in the Metaview web app. When actions are present, present them to the user with the provided label and URL. Action types: 'upgrade' (user needs a paid plan), 'try_feature' (user should try a feature in the Metaview app for a richer experience). </usecase> <instructions>No parameters needed.</instructions> <response_format> {"organization_id": 1, "workspace_name": "Acme Corp", "user_id": 123, "participant_id": "550e8400-e29b-41d4-a716-446655440000", "is_admin": true, "is_paying_plan": true, "data_access": "You can see all conversations in the organization."} </response_format> <communication_style> As you work, briefly describe each step of your process in plain language so the user can follow along and trust that you're on the right track. For example: - "I'm looking up which departments are available so I can filter to Sales." - "Now I'm searching for all recruiter screens in the last 90 days." - "I found 43 conversations. Let me group them by interviewer to see scores for each recruiter." Keep narration concise — one or two sentences per step is enough. Do NOT expose raw IDs, tool names, or technical parameters to the user. Instead of "Calling search_conversations with field_id=OSPT:abc123", say "Searching for Engineering interviews in the last month." The user should see your reasoning and methodology, not the underlying API calls. </communication_style>

give_sourcing_feedback

ChatGPT
<usecase> Submit feedback on one or more candidates in a sourcing search. Feedback calibrates the sourcing agent — accepting or rejecting candidates helps it refine its search and find better matches. Supports bulk feedback: submit feedback for multiple candidates in a single call. Maximum 50 candidates per call. After submitting feedback, send a message using send_sourcing_message (e.g. 'Please search for more candidates based on my feedback') to trigger the agent to refine its search. The agent does NOT automatically restart. </usecase> <instructions> Args: search_id: The search containing the candidates. feedbacks: Array of feedback objects. Each must have: - candidate_id (str): The candidate ID. - accepted (str): One of YES, MAYBE, or NO. - text (str, optional): Free-text feedback explaining your decision. Feedback values: YES: Strong match, move forward. MAYBE: Possible match, keep in consideration. NO: Not a match, do not consider further. </instructions> <response_format>{"search_id": "550e8400-...", "results": [{"candidate_id": "c1a2b3d4-...", "success": true}, {"candidate_id": "invalid-id", "success": false, "error": "Candidate not found in this search"}], "next": "Feedback recorded. The sourcing agent does NOT automatically refine..."}</response_format> <examples> Accept a single candidate: give_sourcing_feedback(search_id="550e8400-...", feedbacks=[{"candidate_id": "c1a2b3d4", "accepted": "YES", "text": "Great Python experience"}]) Bulk feedback: give_sourcing_feedback(search_id="550e8400-...", feedbacks=[{"candidate_id": "c1a2b3d4", "accepted": "YES"}, {"candidate_id": "d4e5f6a7", "accepted": "NO", "text": "Missing distributed systems experience"}]) </examples>

group_conversations

ChatGPT
<usecase> Group conversations by a field and compute metrics. Groups conversations by a field (e.g., department, interviewer) and returns counts and metric values per group. Prefer this tool when the user asks for breakdowns, distributions, rankings, or "by X" questions. POWERFUL PATTERN — AI field + grouping for large-scale analysis: When the user wants to find trends or patterns across many conversations, use this workflow: 1. Create an AI field (create_ai_field) that extracts the data point of interest. 2. Group by that AI field here to see the distribution of values. Or group by another field (e.g., interviewer) and use the AI field as a metric to see averages/counts per group. This avoids reading raw transcripts and works at any scale. Use metrics to compute metrics per group (e.g., total questions, average duration). Use list_fields to discover available metrics. </usecase> <instructions> See search_conversations for the complete filter format reference. IMPORTANT: Date filter values must use a dict with scope and value, not a bare date string. Example: {"field_id": "default:start_time", "operation": "after", "value": {"scope": "relative", "value": -2592000}} Args: group_by: Field ID to group by (e.g., "OSPT:<uuid>", "default:interviewer"). Use list_fields to find attributes where can_be_grouped_by is true. report_id: ID of a saved report. filters: Array of filter objects, each with field_id (str), operation (str), and value. only_show_recorded_conversations: When true (default), only return recorded conversations. Set to false to also include unrecorded conversations (scheduled calls that were not recorded, or upcoming conversations that haven't happened yet). search_term: Filter groups by name substring. Use this when looking for a specific group instead of fetching all groups. min_conversation_count: Minimum conversations per group to include (default 0). offset: Pagination offset. limit: Groups per page (default 20). metrics: Array of metrics to compute per group. Each dict has: metric_id (str, required) — metric ID from list_fields (e.g., "aggregation:question_count"). function (str, required) — one of: mean, median, sum, max, min. metric_arguments (dict, optional) — extra arguments. Check required_arguments from list_fields to see if this metric needs specific arguments. For contact-scoped metrics (question_count, talk_time, minutes_late) you MUST pass {{"scope": "internal"}} or {{"scope": "external"}}. "internal" = interviewers/hiring team, "external" = non-team participants (candidates, clients, etc.). sort_metric: How to sort groups. A dict with: metric_id (str, required) — metric to sort by. function (str, required) — one of: mean, median, sum, max, min. metric_arguments (dict, optional) — same rules as above. If omitted, groups are sorted alphabetically by label. sort_ascending: Sort ascending (default true). </instructions> <response_format> {"groups": [ {"label": "Engineering", "value": "Engineering", "conversation_count": 42, "metric_values": {"aggregation:question_count:sum": 156.0}}, {"label": "Product", "value": "Product", "conversation_count": 28, "metric_values": {"aggregation:question_count:sum": 98.0}}], "total_groups": 5, "total_conversation_count": 100, "has_more": false, "ai_processing": {"AI:<uuid>": {"pending_count": 20, "total_count": 100}}} </response_format> <notes> Note: AI field values are processed asynchronously. If "ai_processing" is present in the response, some values are still being computed. Poll by retrying the same call every ~30 seconds until the data is complete. IMPORTANT: Including AI fields triggers analysis for every matching conversation that hasn't been analyzed yet. Always apply tight filters (date range, department, interviewer, etc.) to keep the set small and get results quickly. Broad unfiltered queries will be slow and may hit evaluation limits that require narrowing your search. IMPORTANT: When grouping by an AI field, the sum of conversation_count across all groups may be LESS than total_conversation_count while AI processing is in progress. Check ai_processing to see how many conversations are still being analyzed. Wait for pending_count to reach 0 before treating group counts as complete. Similarly, filtering by an AI field excludes conversations that have not yet been evaluated for that field. This means total_conversation_count itself may be lower than expected until AI processing finishes. </notes> <examples> Conversations by department in the last 90 days (get field ID from list_fields first): group_conversations( group_by="OSPT:<uuid>", filters=[{"field_id": "default:start_time", "operation": "after", "value": {"scope": "relative", "value": -7776000}}]) Top 10 interviewers by total question count (last 90 days): group_conversations( group_by="default:interviewer", metrics=[{"metric_id": "aggregation:question_count", "function": "sum", "metric_arguments": {"scope": "internal"}}], sort_metric={"metric_id": "aggregation:question_count", "function": "sum", "metric_arguments": {"scope": "internal"}}, sort_ascending=false, limit=10, filters=[{"field_id": "default:start_time", "operation": "after", "value": {"scope": "relative", "value": -7776000}}]) Average interview duration by department (get field ID from list_fields first): group_conversations( group_by="OSPT:<uuid>", metrics=[{"metric_id": "aggregation:actual_duration", "function": "mean"}], sort_metric={"metric_id": "aggregation:actual_duration", "function": "mean"}, sort_ascending=false) </examples>

list_field_values

ChatGPT
<usecase> Get possible values for a specific field. Use this to discover what values are available for filtering. For example, get all department names, interviewer names, or job titles. Essential for looking up person IDs needed by PERSON-type and PARTICIPANT-type filters. BEST PRACTICE: Use search_term when looking for a specific value (e.g., a person's name or a particular department). This returns fewer results and avoids unnecessary data transfer. Can be scoped to a report or filtered set of sessions to show only values that appear in the matching sessions. </usecase> <instructions> Contact lookup — choosing the right field: The same person can have MULTIPLE contact records (e.g. one as an interviewer and one as a candidate). To avoid duplicates: - Looking up an interviewer / employee? Use "default:interviewer". This returns only internal team members (has_access=True) — one result per person. - Looking up a candidate? Use "default:candidate". This returns only external participants (has_access=False). - Don't know the role? Use "default:contact", but beware it may return multiple records for the same person. Check the "is_internal" field in the response to distinguish employees from candidates. IMPORTANT: search_term supports substring matching ("Bart" matches "Bartels", "Bartosz", etc.) and regex matching (e.g. "eng.team|product" is automatically detected as a regex pattern when the term contains special characters like .+?[]|()). When multiple results are returned, disambiguate before proceeding. Prefer searching with both first and last name. See search_conversations for the complete filter format reference. IMPORTANT: Date filter values must use a dict with scope and value, not a bare date string. Example: {"field_id": "default:start_time", "operation": "after", "value": {"scope": "relative", "value": -2592000}} Args: field_id: The field ID (from list_fields, e.g., "OSPT:<uuid>", "default:interviewer"). report_id: Optional report ID to scope values to sessions in that report. filters: Optional filters to scope values. only_show_recorded_conversations: When true (default), only return recorded conversations. Set to false to also include unrecorded conversations (scheduled calls that were not recorded, or upcoming conversations that haven't happened yet). search_term: Filter values by name/label. Supports substring and regex patterns. offset: Pagination offset. limit: Number of values per page (default 50). </instructions> <response_format> For STRING-type fields, values are the actual strings: {"field_id": "OSPT:<uuid>", "values": [{"value": "Engineering", "label": "Engineering", "person": null}, {"value": "Product", "label": "Product", "person": null}], "has_more": false} For PERSON-type fields, values are integer IDs with name labels and person info: {"field_id": "default:interviewer", "values": [{"value": 123, "label": "Alice Smith", "person": {"first_name": "Alice", "last_name": "Smith", "email": "alice@example.com"}}, {"value": 456, "label": "Bob Jones", "person": {"first_name": "Bob", "last_name": "Jones", "email": "bob@example.com"}}], "has_more": true} For PARTICIPANT-type fields, values include an is_internal flag: {"field_id": "default:contact", "values": [{"value": "uuid-1", "label": "Alice Smith", "person": {"first_name": "Alice", "last_name": "Smith", "email": "alice@example.com", "is_internal": true}}, {"value": "uuid-2", "label": "Bob Jones", "person": {"first_name": "Bob", "last_name": "Jones", "email": "bob@gmail.com", "is_internal": false}}], "has_more": false} </response_format> <examples> List all departments (get the field ID from list_fields first): list_field_values(field_id="OSPT:<uuid>") Search for an interviewer by name (preferred for employees): list_field_values(field_id="default:interviewer", search_term="Alice Smith") Search for a candidate by name: list_field_values(field_id="default:candidate", search_term="Bob Jones") Values scoped to a saved report: list_field_values(field_id="OSPT:<uuid>", report_id="abc-123") </examples>

list_fields

ChatGPT
<usecase> List available fields for filtering, grouping, and columns, plus metrics. Returns two SEPARATE lists: 1. fields — filter/grouping field metadata. Field IDs look like "default:start_time", "OSPT:<uuid>", or "AI:<uuid>". Use these for filters, group_by, columns, and the group parameter in get_chart_data. 2. metrics — computed summaries you can chart or aggregate. Metric IDs look like "aggregation:session_count", "aggregation:actual_duration", or "aggregation:AI:<uuid>". Use these ONLY as metric_id in group_conversations (with metrics) and get_chart_data (chart_inputs). Do NOT mix them up: field IDs go in filters/group_by/group, metric IDs go in metric_id/chart_inputs. Each metric includes chart_types showing which chart types it supports. Only metrics with "scatter" in chart_types support scatter plots (omitting function/interval in get_chart_data). BEST PRACTICE: Use search_term to find specific fields instead of fetching all. For example, use search_term="department" to find the department field rather than retrieving the full list. </usecase> <instructions> Args: search_term: Filter fields by name (case-insensitive). Supports plain substring matching and regex patterns (e.g. "eng.*|product" is automatically detected as regex when it contains special characters). report_id: Optional report ID to scope fields to a specific report's context. </instructions> <response_format> {"fields": [ {"id": "default:start_time", "name": "Start Time", "type": "date", "description": "When the conversation started", "filterable": true, "groupable": false, "displayable": true, "filter_operations": ["before", "after", "between"], "filter_format": "value MUST be a dict with ..."}, {"id": "OSPT:a1b2c3d4-e5f6-7890-abcd-ef1234567890", "name": "Department", "type": "string", "description": null, "filterable": true, "groupable": true, "displayable": true, "filter_operations": ["is_one_of", "is_not_one_of"], "filter_format": "value: list of strings. Example: [\"Engineering\"]"}, ... ], "metrics": [ {"id": "aggregation:session_count", "name": "Conversation Count", "functions": ["max", "mean", "median", "min", "sum"], "chart_types": ["bar", "line"], "chart_functions": ["Count", "Cumulative"]}, ... ]} </response_format> <examples> Find the department field: list_fields(search_term="department") Find date-related fields: list_fields(search_term="date") All fields for a specific report: list_fields(report_id="a1b2c3d4-e5f6-7890-abcd-ef1234567890") All fields (no filter): list_fields() </examples> <data_model> - A CONVERSATION is a single recorded call (interview, demo, sync, etc.). Conversations can be RECORDED (Metaview captured and transcribed the call) or UNRECORDED (the call is on the calendar but was not recorded — e.g. the bot wasn't invited, the meeting was cancelled, or it hasn't happened yet). By default, queries only return recorded conversations. Pass only_show_recorded_conversations=false to include unrecorded ones. - A USER is someone who has signed into Metaview with a work email. Users are identified by a numeric user_id. - A CONTACT is a record of someone who appeared on a call. Contacts are identified by a UUID and are NOT unique per person — the same real-world person can have multiple contact records with different roles. For example, an employee who once interviewed at the company has one contact record as a candidate (linked to their personal email) and another as an interviewer (linked to their work email). This means searching by 'default:contact' may return duplicate results for the same person. To avoid this, always use role-scoped fields: 'default:interviewer' to find employees/interviewers, 'default:candidate' to find candidates. - A FIELD is any data property on a conversation — things like department, interviewer name, duration, or an AI-extracted insight. Fields can be used to filter, group, display as columns, or chart conversations. - A METRIC is a computed summary of a field's values across conversations — like the average, sum, or count. Metrics are used in groups (for breakdowns and rankings) and charts (for trends over time). - A GROUP is a collection of conversations grouped by a field (e.g. by department, interviewer, or conversation type). Groups can include metrics like average duration, question count, or talk time — making them the primary tool for breakdowns, rankings, and comparisons. - AI FIELDS (prefixed 'AI:') contain structured data extracted from transcripts by AI. They provide per-conversation insights without needing to read raw transcripts. Each AI field is analyzed per conversation, so applying filters focuses analysis on the conversations you care about and returns results faster. NOTE: In the Metaview web app, AI fields are displayed as 'AI Columns'. If the user refers to 'AI Columns', they mean AI fields. - The 'default:transcript' field returns full transcript text when explicitly requested as a field. Transcripts are large — keep limit to 5 or fewer conversations when requesting transcripts. Prefer AI fields over raw transcripts when possible. On the Free plan, transcripts are only available for recent sessions within the monthly quota. - The 'default:summary' field returns AI-generated summaries. Summaries are generated on the fly for conversations that don't have one yet. Generation is slow and capped at 100 per request. Each summary produces roughly 2,000 tokens per hour of conversation. Always narrow your query with tight filters before requesting summaries to avoid long waits and hitting the cap. On the Free plan, summaries are only available for recent sessions within the monthly quota. </data_model> <strategy_guide> Before executing a request, think about how many conversations are involved and pick the right strategy. This is critical for giving the user a good experience. 1-5 conversations: Fetch full transcripts directly via search_conversations with fields=['default:transcript']. You can read them in context and answer detailed questions. 5-20 conversations: Fetch summaries via search_conversations with fields=['default:summary']. Summaries give you the key points without overwhelming your context window. You can still fetch individual transcripts if you need to drill into a specific conversation. 20+ conversations: Use AI fields to extract specific data points from each conversation, then aggregate the results. This is the key pattern: a) Create an AI field (create_ai_field) that extracts one specific piece of information per conversation (e.g., salary expectation, candidate sentiment, key objection). b) Use search_conversations or group_conversations with the AI field to get structured results across all matching conversations. c) Analyze the aggregated structured data to identify trends, patterns, or insights. This works because each conversation is analyzed independently (no context window limit), and the extracted values are small enough to aggregate across hundreds of conversations. IMPORTANT: Any request that genuinely requires reading all transcripts of 20+ conversations at once is not technically feasible due to context window limits. Decompose it into per-conversation extraction (AI fields) followed by aggregation. If the user asks something vague like 'find trends across all my interviews', help them identify SPECIFIC data points to extract first. Helping users think through their approach: Many users are not experienced with data analysis tools. When a user gives a vague or broad request, help them clarify what they actually want to know before executing. For example: - If they say 'analyze my interviews', ask what specific questions they want answered. - If their request would work better as multiple focused AI fields rather than one broad one, suggest breaking it up. - Help them think about whether they need per-conversation detail or an aggregate view. - You do NOT need to help users write AI field prompts — the system automatically improves prompts before executing. Focus on helping them define what they want to learn. </strategy_guide> <filtering_by_current_user>When the user asks about 'my' conversations, 'I' recorded, or anything self-referencing, filter using "$self" — it resolves to the authenticated user's participant ID automatically. Example: {"field_id": "default:interviewer", "operation": "includes_one_of", "value": ["$self"]}</filtering_by_current_user>

list_mailboxes

ChatGPT
<usecase> List the email mailboxes you can send sequence emails from. Returns your own active mailboxes plus any mailboxes where you have send-on-behalf-of permission. Use the mailbox id as from_mailbox_id when creating EMAIL steps in a sequence. </usecase> <instructions>No parameters needed.</instructions> <response_format> {"mailboxes": [ {"id": "abc-123", "email_address": "alice@acme.com", "person_id": 123, "person_name": "Alice Smith", "is_default": true, "is_owned_by_me": true}]} </response_format>

list_note_template_groups

ChatGPT
<usecase> List the public folders (template groups) in the caller's workspace. Use this when the user wants to move a template into a named folder — call list_note_template_groups first to resolve the folder name, then pass it to manage_note_template(action='update', group_name='...'). Templates not in any public folder live in the caller's personal folder. </usecase> <instructions>Args: (none)</instructions> <response_format> {"groups": [ {"id": "...", "name": "Engineering", "template_count": 4}, {"id": "...", "name": "Recruiter", "template_count": 7}]} The id field is INTERNAL ONLY — never show it to the user. Refer to folders by name. </response_format>

list_note_templates

ChatGPT
<usecase> List AI Notes custom templates the caller can access. Returns a lightweight summary per template. Pass include_detail=true or call get_note_template for the full sections. </usecase> <instructions> Args: search_term: Filter templates by name (case-insensitive substring / regex). include_detail: When true, include the full sections list. offset: Pagination offset (default 0). limit: Page size (default 20, max 50). </instructions> <response_format> {"templates": [ {"id": "...", "name": "Engineering screen", "version": 3, "created_by": {"name": "Alice Smith"}, "created_at": "...", "updated_at": "...", "section_count": 5}], "total_count": 12, "has_more": false} The id field is INTERNAL ONLY — keep it for subsequent tool calls but never show it to the user. Refer to templates by name. </response_format> <data_model> - A NOTE TEMPLATE (AI Notes custom template) defines the structure of AI-generated interview notes. Each template has a name and an ordered list of sections. Template ids and group ids are internal — never surface them to the user; refer to both by name. - A SECTION is one named block in the generated notes — it has a directive (SINGLE for one block under a fixed heading, or REPEATING for one block per detected entity), a description (the instruction the LLM follows when writing that block — the single most important field), and an output type (TEXT, NUMBER, OPTIONS, or DATE). - A TEMPLATE GROUP (folder) is a public folder shared with the workspace. Templates live in the caller's personal folder by default or in a public template group. Use list_note_template_groups to see public folders, and manage_note_template to create/update/delete a template. - A SOURCE is a piece of content that feeds into AI Notes generation. Sources can be conversations (type=session — an interview transcript) or documents (type=document — a resume, job description, or other plain text). Notes always have an anchor conversation (the one passed to generate_notes). Additional sources can be added or removed via manage_notes_sources. </data_model>

list_sequence_candidates

ChatGPT
<usecase> List candidates enrolled in a sequence, or get a specific candidate's full journey. Non-admins can only access sequences they created. By default returns a summary per candidate. Use include_detail for per-step delivery status, and include_messages to see the actual email content. Pass candidate_sequence_id to jump straight to a specific candidate's full detail. </usecase> <instructions> Args: sequence_id: UUID of the sequence (required unless candidate_sequence_id is provided). candidate_sequence_id: Fetch a specific candidate's full journey directly. When provided, include_detail and include_messages are implied. include_detail: When true, include per-step delivery status (sent, delivered, opened, replied, bounced, skipped) and candidate_sequence_step_id for each candidate. Required to get step IDs for updates via manage_candidate_sequence. Default false. include_messages: When true, include email content for all sent steps. Requires include_detail. Default false. status: Filter by status: "active", "paused", "cancelled", or "completed". Omit to see all statuses. search_term: Filter by candidate name (case-insensitive substring match). offset: Pagination offset (default 0). limit: Number of results per page (default 50, max 100). </instructions> <response_format> {"sequence_id": "...", "sequence_name": "Outreach v2", "candidates": [ {"candidate_sequence_id": "...", "candidate_id": "...", "candidate_name": "John Doe", "candidate_email": "john@example.com", "candidate_phone": "+1234567890", "to_email": "john@example.com", "status": "active", "paused_reason": null, "cancelled_reason": null, "outcome": null, "created_by": {"name": "Alice Smith"}, "created_at": "2024-01-10T...", "steps_sent": 2, "steps_total": 4, "last_sent_at": "2024-01-15T...", "has_reply": true, "steps": [{"candidate_sequence_step_id": "...", "step_id": "...", ...}], "messages": [{...}]}], "total_count": 42, "has_more": false} </response_format> <examples> List all candidates in a sequence: list_sequence_candidates(sequence_id="abc-123") Active candidates with delivery detail: list_sequence_candidates(sequence_id="abc-123", status="active", include_detail=true) Full journey for a specific candidate (with emails): list_sequence_candidates(candidate_sequence_id="xyz-789") </examples>

list_sequences

ChatGPT
<usecase> List sequences the current user has access to, or get full details for a specific sequence. Admins can see all sequences in the workspace. Non-admins can only see sequences they created. Archived sequences are always excluded. Returns summary data including per-sequence stats so the caller can compare sequences without further round-trips. Pass sequence_id or include_detail=true for full step configuration. </usecase> <instructions> Args: sequence_id: Fetch a specific sequence with full detail (steps, templates, etc.). When provided, include_detail is implied. created_by_person_id: Only return sequences created by this person. Useful for admins who want to see just their own sequences. search_term: Filter sequences whose name contains this substring (case-insensitive). Also supports regex when the term contains special characters like .*+?[]|(). include_detail: When true, include full step configuration for each sequence. Default false (summary only). include_disabled: Whether to include disabled sequences (default true). offset: Pagination offset (default 0). limit: Number of sequences per page (default 20, max 50). </instructions> <response_format> {"sequences": [ {"id": "...", "name": "Outreach v2", "description": "...", "is_enabled": true, "is_valid": true, "is_modifiable": false, "created_by": {"name": "Alice Smith"}, "created_at": "2024-01-01T...", "updated_at": "2024-01-10T...", "step_count": 3, "stats": {"total_candidates": 42, "total_active": 10, "total_completed": 20, "total_paused": 2, "total_sent": 100, "total_replies": 15, "total_bounced": 3, "total_interested": 8}, "steps": [{...}]}], "total_count": 5, "has_more": false} </response_format> <examples> All enabled sequences: list_sequences(include_disabled=false) Search by name: list_sequences(search_term="outreach") Full detail for a specific sequence: list_sequences(sequence_id="abc-123") Only sequences created by a specific person: list_sequences(created_by_person_id=123) </examples> <data_model> - A SEQUENCE is an outreach campaign with one or more steps. Sequences can be enabled/disabled, and become locked (non-modifiable) once the first email has been sent. Only the creator can edit a sequence. Sending test emails and previewing emails should be done via the Metaview web app. - A STEP is a single action in a sequence. Supported channel types: EMAIL, LINKEDIN_CONNECTION, LINKEDIN_MESSAGE, SMS, PHONE, WHATSAPP. Each step has content templates and a schedule (when to execute). Steps can execute automatically or manually (with a timeout). See per-channel step fields for which execution types each channel supports. - A CANDIDATE SEQUENCE is the enrollment of a candidate into a sequence. It tracks delivery status per step and can be paused, resumed, or cancelled. Individual step email templates and schedules can be customized per candidate via overrides. - A MAILBOX represents an email account that can send sequence emails. list_mailboxes returns the user's available mailboxes, each with: id (the mailbox UUID — use as from_mailbox_id when creating EMAIL steps), email_address, person_id, person_name, is_default, is_owned_by_me (false when access is via send-on-behalf-of permission). - A SEND-ON-BEHALF PERMISSION allows one person to send sequence emails as another person. Each step has a from_mailbox_id (the sender's mailbox). To send as someone else, that person must grant you permission. Permissions can be granted to a specific person or to the entire workspace. </data_model>

list_sourcing_candidates

ChatGPT
<usecase> List candidates surfaced in a sourcing search with profile summaries and feedback status. Returns candidates ordered by when they were surfaced (newest first), with: - Profile summary sections (experience, skills, education, etc.) - Current feedback status (if any) - Pack number indicating which batch the candidate was presented in - Remaining candidate credits on the user's plan Hidden candidates (those not yet revealed due to credit limits) are excluded. IMPORTANT for large result sets: For searches with 100+ candidates, paginate with limit=50 and iterate through pages using offset. Do NOT attempt to fetch all candidates in a single call — this will exceed context limits for most AI agents. Use this to: - Review candidates the agent has found - Check which candidates still need feedback - Filter by pack to see only the latest batch of candidates - Get candidate IDs for use with give_sourcing_feedback - Get candidate IDs referenced in get_sourcing_messages candidate attachments </usecase> <instructions> Args: search_id: The search to list candidates for. pack: Filter to a specific pack (batch, 1-based). Omit to list all candidates. limit: Maximum candidates to return (default 20, max 100). offset: Pagination offset (default 0). detail_level: Controls how much data is returned per candidate. 'minimal' — candidate_id, name, linkedin_url only. Smallest response, best for getting an overview or building ID lists. 'summary' — (default) includes reasoning summary sections from the sourcing agent (experience, skills, education highlights). 'full' — includes summary PLUS the candidate's full profile data (location, experience history, education, skills list). Larger response but avoids needing separate fetch_candidates calls. feedback_status: Filter candidates by their feedback status. 'all' — (default) return all candidates. 'unreviewed' — only candidates with no feedback yet. 'yes' — only candidates marked YES. 'no' — only candidates marked NO. 'maybe' — only candidates marked MAYBE. </instructions> <response_format>{"search_id": "550e8400-...", "candidates": [{"candidate_id": "c1a2b3d4-...", "name": "Jane Smith", "linkedin_url": "https://linkedin.com/in/jane-smith", "pack": 2, "summary": [{"title": "Experience", "description": "10 years in backend..."}], "feedback": {"accepted": "YES", "text": "Great experience", "author": "Alice"}}], "total_count": 12, "total_packs": 3, "has_more": false, "remaining_credits": 88, "next": "Review these candidates and provide feedback..."}</response_format> <examples> List all candidates (default summary detail): list_sourcing_candidates(search_id="550e8400-...") List only the latest pack: list_sourcing_candidates(search_id="550e8400-...", pack=3) Get minimal list for overview: list_sourcing_candidates(search_id="550e8400-...", detail_level="minimal", limit=100) Get only unreviewed candidates with full profiles: list_sourcing_candidates(search_id="550e8400-...", detail_level="full", feedback_status="unreviewed", limit=50) Paginate through results: list_sourcing_candidates(search_id="550e8400-...", limit=50, offset=50) </examples>

list_sourcing_searches

ChatGPT
<usecase> List your sourcing and research searches with summary information. Returns enough detail per search (title, mode, candidate count, agent phase, timestamps) that a separate get-search tool is not needed. Use this to: - See all your active searches - Find a specific search to resume - Check which searches have candidates waiting for feedback - Distinguish between source and research searches via the mode field </usecase> <instructions> Args: limit: Maximum number of searches to return (default 20, max 50). offset: Pagination offset (default 0). </instructions> <response_format>{"searches": [{"id": "550e8400-...", "title": "Senior Backend Engineer", "mode": "source", "phase": "waiting", "candidate_count": 12, "created_at": "2025-01-15T10:30:00Z", "updated_at": "2025-01-16T14:22:00Z"}], "total_count": 8, "has_more": false}</response_format> <examples> List all searches: list_sourcing_searches() Paginate: list_sourcing_searches(limit=10, offset=10) </examples> <data_model> - A SEARCH is a sourcing conversation with an AI agent that finds candidates matching your requirements. Each search has a conversation thread, an ICP (Ideal Candidate Profile), and a list of surfaced candidates. Searches have a mode (SOURCE or RESEARCH) and can be active or archived. - The agent goes through phases: idle (waiting for input), busy (actively searching), waiting (needs your feedback on candidates), error (something went wrong). - CANDIDATES are people surfaced by the agent. Each has a profile summary and reasoning sections explaining why they match. - FEEDBACK is a YES, NO, or MAYBE verdict given by a user on a candidate. The acceptance rate is the percentage of YES out of total feedback. - An ICP is the Ideal Candidate Profile the agent builds from your conversation. It evolves as you provide feedback and refine requirements. - A SCHEDULED SEARCH is a search configured to run on a recurring schedule. - A SEARCH-SEQUENCE LINK connects a sourcing search to an outreach sequence, so accepted candidates flow into automated outreach. </data_model>

manage_candidate_sequence

ChatGPT
<usecase> Add candidates to a sequence, or pause, resume, cancel, remove, or update a candidate's enrollment. Dispatches based on the action parameter. Only the sequence creator can perform these actions. IMPORTANT: Always confirm with the user before calling this tool. Describe the exact changes you plan to make and get explicit approval first. </usecase> <instructions> Args: action: Required. One of: add, pause, resume, cancel, remove, update. - cancel: Stop sending further emails but keep the candidate visible in the sequence. - remove: Delete the candidate from the sequence entirely (archive/soft-delete). sequence_id: Required for add. candidate_ids: Required for add. List of candidate IDs to enroll. candidate_sequence_id: Required for pause, resume, cancel, remove. candidate_sequence_step_id: Required for update. Get this from list_sequence_candidates(sequence_id=..., include_detail=true). subject_override: Optional for update. Custom subject for this candidate's step. Supports {{variable_name}} placeholders filled in per-candidate by AI before sending. template_override: Optional for update. Custom body for this candidate's step. Supports {{variable_name}} placeholders filled in per-candidate by AI before sending. clear_subject_override: Optional for update. Set true to revert subject to template default. clear_template_override: Optional for update. Set true to revert body to template default. schedule_override: Optional for update. JSON object to override the step's schedule. Supported types: {"schedule_type": "instant"}, {"schedule_type": "next_business_day", "time_of_day": "HH:MM"}, {"schedule_type": "later", "delay_seconds": N}. Setting a specific time is NOT supported. clear_schedule_override: Optional for update. Set true to revert schedule to template default. context_source_type: Optional for add. Must be one of 'search' or 'project'. If provided, context_source_id is also required. IMPORTANT: Leave both context_source_type and context_source_id null if the source is unknown — do NOT guess or fabricate a value. context_source_id: Optional for add. UUID of the search or project the candidates came from. If provided, context_source_type is also required. Leave null if context_source_type is null. </instructions> <response_format> Add: {"added": N, "sequence_id": "...", "candidate_sequences": [...]} Pause/resume/cancel/remove: {"action": "paused|resumed|cancelled|removed", "candidate_sequence_id": "..."} Update: {"updated": true, "candidate_sequence_step_id": "..."} </response_format> <examples> Add candidates: manage_candidate_sequence(action="add", sequence_id="abc", candidate_ids=["c1", "c2"], context_source_type="search", context_source_id="search-uuid") Pause: manage_candidate_sequence(action="pause", candidate_sequence_id="xyz") Resume: manage_candidate_sequence(action="resume", candidate_sequence_id="xyz") Cancel: manage_candidate_sequence(action="cancel", candidate_sequence_id="xyz") Remove (archive): manage_candidate_sequence(action="remove", candidate_sequence_id="xyz") Override step template for a candidate: manage_candidate_sequence(action="update", candidate_sequence_step_id="step1", template_override="Custom body") Override step schedule for a candidate: manage_candidate_sequence(action="update", candidate_sequence_step_id="step1", schedule_override={"schedule_type": "later", "delay_seconds": 86400}) </examples>

manage_note_template

ChatGPT
<usecase>Create, update, or delete an AI Notes custom template.</usecase> <instructions> Args: action: Required. One of: create, update, delete. template_id: Required for update and delete. INTERNAL ONLY — never surface this id to the user (it's a UUID with no meaning to them). Refer to templates by name in user-facing messages. name: Required for create; optional for update. sections: Required for create; optional for update. When provided on update, the full list REPLACES the existing sections — omitted sections are removed. List order determines display order. See section_schema for the section shape. group_name: Optional (update only). Move the template into a named public folder in the caller's workspace. Pass an empty string (or 'personal') to move into the personal folder. Call list_note_template_groups first to see the available folder names. Omit the arg to leave the template where it is. </instructions> <response_format> Create / update: {"template": {template detail}} Delete: {"deleted": true, "template_id": "..."} The template_id / template.id fields are INTERNAL ONLY — retain them for subsequent tool calls but never show them to the user. When confirming a save or delete to the user, refer to the template by name. </response_format> <examples> Create with one TEXT + one OPTIONS section. Each description carries scope and a format contract — the LLM needs that level of specificity on every interview transcript. manage_note_template(action="create", name="Recruiter screen", sections=[ {"directive": "SINGLE", "heading": "Reasons for leaving", "description": "Summarise the candidate's reasons for leaving their current role in 3-4 bullets. Each bullet: Push or Pull in bold, colon, one sentence. Quote the candidate's own phrases in italics.", "output": {"type": "TEXT", "text_format": "BULLET_POINT", "detail": "medium"}}, {"directive": "SINGLE", "heading": "Remote preference", "description": "Pick \"Remote\" if the candidate said remote-only, \"Hybrid\" if they mentioned office days or hybrid setups, \"In-office\" if they said they want to be in the office full time, \"Not discussed\" if the topic never came up.", "output": {"type": "OPTIONS", "options_type": "SINGLE", "options": ["Remote", "Hybrid", "In-office", "Not discussed"]}}]) REPEATING for 'one block per X' (capture a block per technical question, not five near-identical SINGLE sections): manage_note_template(action="create", name="Tech screen", sections=[ {"directive": "REPEATING", "repeating_entity": "Technical question", "description": "For each technical question the interviewer asks: capture the question verbatim as a markdown heading, then one paragraph covering the candidate's approach and whether they arrived at a correct solution.", "output": {"type": "TEXT", "text_format": "PARAGRAPH", "detail": "high"}}]) Rename only: manage_note_template(action="update", template_id="abc", name="Renamed") Delete: manage_note_template(action="delete", template_id="abc") </examples> <section_schema> A SECTION is one named block in the generated notes. Every field is required. Shape: directive: 'SINGLE' | 'REPEATING' 'SINGLE' renders one block under a fixed heading. 'REPEATING' renders one block per detected entity in the transcript. Prefer REPEATING whenever the user's intent is 'one block per X' (per question / per role / per project / per competency). If you find yourself drafting several near-identical SINGLE sections that differ only in which question or topic they cover, collapse them into one REPEATING section with a clear repeating_entity. heading: str (required when directive == 'SINGLE') repeating_entity: str (required when directive == 'REPEATING'; e.g. 'Question', 'Topic', 'Role', 'Project') description: str THE single most important field. Treat it as a PROMPT to another LLM — not a note to a human colleague. It runs at inference time on every interview transcript. Cover two things: (a) SCOPE — what to include and what to leave out. (b) OUTPUT FORMAT — the exact shape. Caps on length (word / bullet / sentence count), markdown patterns, label conventions. e.g. '3 bullets max, each in the form Label: one sentence. Total under 120 words. No tables.' Encode any formatting preferences the user has stated verbatim. Examples: SINGLE section: 'Summarise the candidate's reasons for leaving their current role in 3-4 bullet points. Each bullet: Push or Pull in bold, colon, one sentence. Quote the candidate's own phrases in italics.' REPEATING section (directive=REPEATING, repeating_entity='Technical question'): 'For each technical question asked: capture the question verbatim as a markdown heading, then a paragraph with the candidate's approach and whether they arrived at a correct solution.' REPEATING descriptions are applied once per detected entity. output: dict (constrains the generated value; shape depends on type) TEXT: {type: 'TEXT', text_format: 'PARAGRAPH'|'BULLET_POINT', detail: 'low'|'medium'|'high'} TEXT carries structure via markdown inside the description — bold labels, sub-bullets, closed label sets. Most production templates use TEXT for everything that isn't a hard classification. NUMBER: {type: 'NUMBER', currency: str} (pass currency='' for a plain number; otherwise 'USD', 'EUR', ...) OPTIONS: {type: 'OPTIONS', options_type: 'SINGLE'|'MULTIPLE', options: ['Yes', 'No', ...]} For booleans, use options=['true', 'false'] with options_type='SINGLE'. CRITICAL: an OPTIONS description must include per-option selection criteria, not just the list. Tell the LLM exactly when to pick each value and — just as importantly — when NOT to. Example for options=['Strong Yes','Yes','Mixed','No','Strong No']: 'Rate the candidate's impact evidence. Mixed is NOT a hedge — use Mixed only when the interview contains concrete evidence supporting both positive and negative interpretations that cannot be resolved. Execution alone is not impact: if the candidate describes delivery without a validated outcome (measured, observed, or confirmed change), the rating must be No.' Prefer 2-5 well-defined options. If you need more than ~6, you're usually classifying something the LLM can describe in a TEXT section instead. DATE: {type: 'DATE', date_format: 'yyyy/mm/dd'|'mm/dd/yyyy'|'dd/mm/yyyy'} </section_schema> <design_guidance> Design guidance High-quality templates look like production LLM prompts, not polite notes to a colleague. When iterating with the user on a new template: - WRITE DESCRIPTIONS LIKE PROMPTS. Include scope and an explicit output format in every description. Descriptions under ~200 characters almost always produce vague notes. - BIAS TOWARD REPEATING. If the user's intent is 'one block per X', that's a REPEATING section — not 5 near-identical SINGLE sections. Scripted case-study questions, per-project recaps, per-competency assessments all belong in REPEATING. - SPLIT vs MERGE. Split a concept into multiple sections when (a) the outputs have different shapes, or (b) the user would want to iterate on them independently. Keep them together when the output is narrative prose about one topic. - USE OPTIONS SPARINGLY. A 10+ value OPTIONS enum is usually a classifier the LLM can handle inside a TEXT section description. Reserve OPTIONS for ratings or decisions that have a small, fixed, well-defined set of answers, and always include per-option criteria. </design_guidance>

manage_notes_sources

ChatGPT
<usecase> List, add, or remove sources on an existing AI Notes version. Use this tool to: - Inspect which conversations and documents are included in a notes version. - Add extra conversations so the notes cover multiple interviews. - Add a plain-text document (e.g. a resume, job description) as context. - Remove a source that was previously added. The notes must already exist — call generate_notes first if they do not. </usecase> <instructions> Args: conversation_id: The anchor conversation whose notes you want to manage. This is the conversation that generate_notes was originally called with. action: Required. One of: list, add, remove. conversation_ids: Conversations to add or remove. List of conversation ID strings. documents: Documents to add as plain text. Each entry is an object with: - name: A short name for the document (e.g. "Resume - Jane Smith"). - content: The full text content of the document. source_ids: Source IDs to remove (returned by a prior 'list' call). Use this when removing document sources or when you already know the source ID. IMPORTANT: Adding or removing sources triggers a full regeneration of the notes. After add/remove, wait ~30 seconds then poll with search_conversations. </instructions> <response_format> list: {"sources": [{"source_id": "...", "type": "session"|"document", "name": "..."}]} add: {"status": "sources_added", "added_source_ids": [...]} remove: {"status": "sources_removed", "removed_source_ids": [...]} </response_format> <examples> List current sources: manage_notes_sources(conversation_id="12345", action="list") Add another conversation: manage_notes_sources(conversation_id="12345", action="add", conversation_ids=["67890"]) Add a document as plain text: manage_notes_sources(conversation_id="12345", action="add", documents=[{"name": "Resume - Jane Smith", "content": "Jane Smith..."}]) Remove a source by ID (from a prior list): manage_notes_sources(conversation_id="12345", action="remove", source_ids=["<uuid>"]) Remove a conversation source: manage_notes_sources(conversation_id="12345", action="remove", conversation_ids=["67890"]) </examples>

manage_sequence

ChatGPT
<usecase> Create, update, duplicate, or delete a sequence. Dispatches based on the action parameter. Only the creator of a sequence can update or delete it; admins and creators can duplicate. Test sends, email previews, and send-now are NOT available via this tool. Direct users to the Metaview web app for these. IMPORTANT: Always confirm with the user before calling this tool. Describe the exact changes you plan to make and get explicit approval first. </usecase> <instructions> Args: action: Required. One of: create, update, duplicate, delete. sequence_id: Required for update, duplicate, delete. name: Required for create, optional for update. description: Optional for create and update. set_enabled: Optional for create and update. Enable or disable the sequence. steps: Optional for update. A JSON list of step objects to replace the current steps. Steps not in the list are deleted. Order in the list determines step order. Each step object has: channel_type: str (REQUIRED — one of: EMAIL, LINKEDIN_CONNECTION, LINKEDIN_MESSAGE, SMS, PHONE, WHATSAPP) sequence_step_id: str | null (include the existing step ID to update it; omit or set null for new steps — an ID will be generated automatically) template: str | null (message body; supports {{variable_name}} placeholders that are filled in per-candidate by an AI call before sending) description: str | null schedule: dict | null (e.g. {"schedule_type": "instant"}, {"schedule_type": "later", "delay_seconds": 86400}, {"schedule_type": "next_business_day", "time_of_day": "09:00:00"}. Setting a specific time is NOT supported. step_execution_type: str | null (AUTOMATIC or MANUAL) execution_timeout_seconds: int | null (only for MANUAL steps) EMAIL step fields: from_mailbox_id: REQUIRED (mailbox UUID — use list_mailboxes to get available mailboxes) step_type: REQUIRED (NEW_THREAD or REPLY) bcc: optional (list of email addresses) cc: optional (list of email addresses) step_execution_type: AUTOMATIC, MANUAL (default: AUTOMATIC) NOT used: from_whatsapp_account_id, linkedin_subject step_type values: NEW_THREAD or REPLY subject: str | null (REQUIRED for NEW_THREAD; forbidden for REPLY. Supports {{variable_name}} placeholders) LINKEDIN_CONNECTION step fields: step_execution_type: MANUAL (default: MANUAL) NOT used: bcc, cc, from_mailbox_id, from_whatsapp_account_id, linkedin_subject, step_type LINKEDIN_MESSAGE step fields: linkedin_subject: optional (str | null — subject line for the LinkedIn message) step_execution_type: MANUAL (default: MANUAL) NOT used: bcc, cc, from_mailbox_id, from_whatsapp_account_id, step_type subject shorthand: setting 'subject' auto-maps to linkedin_subject SMS step fields: step_execution_type: MANUAL (default: MANUAL) NOT used: bcc, cc, from_mailbox_id, from_whatsapp_account_id, linkedin_subject, step_type PHONE step fields: step_execution_type: MANUAL (default: MANUAL) NOT used: bcc, cc, from_mailbox_id, from_whatsapp_account_id, linkedin_subject, step_type WHATSAPP step fields: from_whatsapp_account_id: REQUIRED (WhatsappAccount UUID — the sender's connected WhatsApp account) step_execution_type: AUTOMATIC, MANUAL (default: AUTOMATIC) NOT used: bcc, cc, from_mailbox_id, linkedin_subject, step_type </instructions> <response_format> Create/update/duplicate: {"sequence": {sequence detail object with steps}} Delete: {"deleted": true, "sequence_id": "..."} </response_format> <examples> Create a sequence: manage_sequence(action="create", name="Outreach v2") Update name and enable: manage_sequence(action="update", sequence_id="abc", name="New Name", set_enabled=true) Duplicate: manage_sequence(action="duplicate", sequence_id="abc") Delete: manage_sequence(action="delete", sequence_id="abc") </examples>

search_conversations

ChatGPT
<usecase> Search conversations with filters and get tabular data. Returns individual conversations matching the given filters, with configurable fields showing attribute values for each conversation. IMPORTANT - choose the right tool AND approach based on scale: - For "how many" questions, use group_conversations — group by the relevant attribute and read the conversation_count per group, or use a single group to get the total. This avoids fetching full conversation rows when only a count is needed. - For breakdowns by attribute (e.g. by department, interviewer), use group_conversations. - For time-series trends, use get_chart_data. - Only use search_conversations when you need individual conversation rows. SCALE-AWARE STRATEGY — pick the right fields based on how many conversations match: - 1-5 conversations: Use fields=['default:transcript'] to read full transcripts. You can analyze them in detail within your context window. - 5-20 conversations: Use fields=['default:summary'] to get AI-generated summaries. Good middle ground — key points without overwhelming context. Fetch individual transcripts only for conversations you need to drill into. - 20+ conversations: Do NOT fetch transcripts or summaries in bulk. Instead use create_ai_field to extract specific data points per conversation, then query the AI field here or in group_conversations to aggregate results. This is the only way to analyze large numbers of conversations effectively. - When unsure of scale, first run a query with just default fields (no transcripts/summaries) to see total_count, then decide your approach. IMPORTANT - transcript token cost: A single 1-hour transcript uses roughly 10,000-15,000 tokens. Be careful not to fetch too many transcripts or else you may use up all your context. Prefer AI fields over raw transcripts when possible. Transcript format is one line per monologue: Speaker Name (Role) @M:SS-M:SS: What they said... The @start-end timestamps show when each monologue occurs (minutes:seconds). To deep-link to a specific moment, append ?t=<seconds> to the conversation URL (e.g. @1:23 means t=83). IMPORTANT - AI fields: AI fields (field IDs starting with 'AI:') require per-conversation analysis. Results are generated asynchronously and return faster with fewer conversations. Always apply tight filters (date range, department, interviewer, etc.) BEFORE requesting AI fields. If too many conversations need analysis, you will be asked to narrow your query. IMPORTANT - summary generation: When the 'default:summary' field is included, summaries are generated on the fly for conversations that don't have one yet. Summary generation is SLOW (each summary analyzes the full transcript) and produces roughly 2,000 tokens per hour of conversation. A maximum of 100 summaries can be triggered per request. To avoid long waits, always narrow your query with tight filters (date range, department, interviewer, etc.) BEFORE requesting summaries. When both report_id and filters are provided, filters are applied on top of the report's saved filters. Each filter object has three keys: field_id (str), operation (str), and value (format depends on attribute type, see below). Use list_fields to discover available fields and their operations. Use list_field_values to find valid values for a specific field. </usecase> <instructions> Args: report_id: ID of a saved report to use as the base filter set. filters: Array of filter objects, each with field_id (str), operation (str), and value (format depends on attribute type, see "Filter value formats" below). fields: Field IDs to include. If omitted, uses the report's configured fields or defaults. only_show_recorded_conversations: When true (default), only return recorded conversations. Set to false to also include unrecorded conversations (scheduled calls that were not recorded, or upcoming conversations that haven't happened yet). sort_by: Field ID to sort by (default: default:start_time). sort_ascending: Sort ascending (default: false — newest first when sorting by date). offset: Pagination offset (default 0). limit: Number of conversations per page (default 20, max 50). Keep low when requesting 'default:transcript' (see transcript token cost above). conversation_ids: Fetch specific conversations by ID (max 100). When provided, returns these conversations directly instead of using report/filter-based querying. Filter value formats by attribute type: DATE (DateAttribute) Operations: before, after, between values MUST be a dict with "scope" and "value" keys. Do NOT pass a bare date string. Absolute (single): {"scope": "absolute", "value": "2024-01-01T00:00:00.000Z"} Absolute (range, for between): {"scope": "absolute", "value": ["2024-01-01T00:00:00.000Z", "2024-06-01T00:00:00.000Z"]} Relative (seconds from now; negative = past): {"scope": "relative", "value": -2592000} Common relative values: -86400 (1 day), -604800 (7 days), -2592000 (30 days), -7776000 (90 days), -15552000 (180 days), -31536000 (1 year). STRING (StringAttribute) Operations: is_one_of, is_none_of, like_one_of, not_like_any_of values: list of strings. Example: ["Engineering", "Product"] PERSON (PersonAttribute) Operations: is_one_of, is_none_of values: list of person IDs (integers). Example: [123, 456] NUMBER (NumberAttribute) Operations: is, less_than, greater_than values: a number. Example: 30.0 BOOLEAN (BooleanAttribute) Operations: is values: true or false. CONTENT (ContentAttribute) Operations: references, does_not_reference, references_one_of, does_not_reference_any_of values: dict with "scope" and "value" keys. Scope: "anyone", "internal_participant", or "external_participant". Value: a string or list of strings. Example: {"scope": "anyone", "value": ["Python", "TypeScript"]} PARTICIPANT_SCOPED_NUMBER (ParticipantScopedNumberAttribute) Operations: is, less_than, greater_than values: dict with "scope" and "value" keys. Scope: "internal" or "external". Value: a number. Example: {"scope": "external", "value": 50} PARTICIPANT (ParticipantAttribute) Operations: is_one_of, is_none_of values: list of participant IDs (UUIDs), or ["$self"] for the current user. Example: ["550e8400-e29b-41d4-a716-446655440000"] STRING_LIST (StringListAttribute) Operations: includes_one_of, excludes_all_of values: list of strings. Example: ["Engineering", "Product"] PERSON_LIST (PersonListAttribute) Operations: includes_one_of, excludes_all_of values: list of person IDs (integers). Example: [123, 456] PARTICIPANT_LIST (ParticipantListAttribute) Operations: includes_one_of, excludes_all_of values: list of participant IDs (UUIDs), or ["$self"] for the current user. Example: ["550e8400-e29b-41d4-a716-446655440000"] JSON (JsonAttribute) Operations: is_one_of, is_none_of, like_one_of, not_like_any_of values: list of strings. Example: ["value1", "value2"] Common filter examples: Last 30 days: [{"field_id": "default:start_time", "operation": "after", "value": {"scope": "relative", "value": -2592000}}] January 2024: [{"field_id": "default:start_time", "operation": "between", "value": {"scope": "absolute", "value": ["2024-01-01T00:00:00.000Z", "2024-02-01T00:00:00.000Z"]}}] Engineering department, last 90 days (get the field ID from list_fields): [{"field_id": "default:start_time", "operation": "after", "value": {"scope": "relative", "value": -7776000}}, {"field_id": "OSPT:<uuid>", "operation": "is_one_of", "value": ["Engineering"]}] My conversations (use "$self" — resolved to your participant ID automatically): [{"field_id": "default:contact", "operation": "includes_one_of", "value": ["$self"]}] My interviews as interviewer: [{"field_id": "default:interviewer", "operation": "includes_one_of", "value": ["$self"]}] Specific candidate (use contact UUID from list_field_values): [{"field_id": "default:candidate", "operation": "includes_one_of", "value": ["<candidate-contact-uuid>"]}] Specific interviewer (use contact UUID from list_field_values): [{"field_id": "default:interviewer", "operation": "includes_one_of", "value": ["<interviewer-contact-uuid>"]}] </instructions> <response_format> {"field_definitions": [{"field_id": "default:start_time", "name": "Start Time", "type": "date"}], "conversations": [{"id": 12345, "url": "https://<app-domain>/notes/12345", "fields": {"default:start_time": [{"value": "2024-01-15", "label": "Jan 15"}]}}], "total_count": 142, "has_more": true, "ai_processing": {"AI:<uuid>": {"pending_count": 20, "total_count": 100}}} </response_format> <notes> Note: AI field values are processed asynchronously. If "ai_processing" is present in the response, some values are still being computed. Poll by retrying the same call every ~30 seconds until the data is complete. IMPORTANT: Including AI fields triggers analysis for every matching conversation that hasn't been analyzed yet. Always apply tight filters (date range, department, interviewer, etc.) to keep the set small and get results quickly. Broad unfiltered queries will be slow and may hit evaluation limits that require narrowing your search. </notes> <examples> Engineering conversations in the last 30 days with department and interviewer fields: First, find the department field ID: list_fields(search_term="department") Then use the returned OSPT:<uuid> field ID: search_conversations( filters=[ {"field_id": "default:start_time", "operation": "after", "value": {"scope": "relative", "value": -2592000}}, {"field_id": "OSPT:<uuid>", "operation": "is_one_of", "value": ["Engineering"]}], fields=["default:start_time", "default:calendar_event_title", "OSPT:<uuid>"]) </examples>

search_reports

ChatGPT
<usecase> List saved reports the user has access to, or fetch full details for specific reports. A report is a saved configuration — a named set of filters, fields, grouping, and charts that defines a particular way to analyze interview conversations. Pass a report's ID to search_conversations, group_conversations, or get_chart_data to reuse its saved filters. Use report_ids to fetch one or more specific reports by ID. Set include_detail=true to get the full configuration (filters, fields, grouping, charts) instead of just the summary. BEST PRACTICE: Use search_term when looking for a specific report by name instead of listing all reports and scanning. </usecase> <instructions> Args: report_ids: List of report IDs to fetch. Returns only these reports. include_detail: When true, returns full report configuration (filters, fields, grouping, charts) for each report. Default false (summary only). search_term: Filter reports by name (case-insensitive). Supports substring matching and regex patterns (automatically detected). category: Filter by category. One of: createdByMe, createdByMetaview, recentlyViewed, favorited. sort_key: Sort field. One of: updated_at (default), name, created_at. sort_order: Sort direction. One of: desc (default), asc. offset: Pagination offset (default 0). limit: Number of results per page (default 20, max 100). </instructions> <response_format> {"reports": [ {"id": "abc-123", "name": "Engineering Interviews Q1", "url": "https://<app-domain>/reports/abc-123", "description": "All engineering interviews in Q1 2024", "is_default": false, "created_by": {"name": "Alice Smith"}, "created_at": "2024-01-01 00:00:00+00:00", "updated_at": "2024-03-15 10:30:00+00:00"}], "count": 1, "has_more": false} </response_format> <examples> search_reports() search_reports(search_term="engineering") search_reports(category="createdByMe", sort_key="updated_at") search_reports(report_ids=["abc-123"], include_detail=true) search_reports(report_ids=["abc-123", "def-456"]) </examples>

send_sourcing_message

ChatGPT
<usecase> Send a message to a sourcing or research search agent. Use this to: - Start a new sourcing search (omit search_id) by describing who you are looking for - Start a new research search (omit search_id, set mode='research') by describing what you want researched - Send a follow-up message to an existing search to refine requirements, answer agent questions, or provide additional context Modes: - 'source' (default): AI recruiter that searches for candidates, surfaces profiles, runs calibration, and drafts outreach. - 'research': General research assistant that searches the web, synthesizes information, analyzes data with charts/CSVs, and writes reports. No candidate profiles or outreach. When no search_id is provided, a new search is created and its ID is returned. Save this ID for subsequent calls. The agent processes messages asynchronously. After sending, poll with get_sourcing_messages to see the agent's response and any candidates it surfaces. </usecase> <instructions> Args: message: The message to send. For a new source search, describe the role, requirements, and constraints (location, experience level, etc.). For a new research search, describe the topic or question to investigate. For follow-ups, provide refinements or answer the agent's questions. search_id: ID of an existing search. Omit to create a new search. mode: Search mode — 'source' (default) or 'research'. Only used when creating a new search (search_id is omitted). Ignored for follow-up messages. </instructions> <response_format>{"search_id": "550e8400-...", "status": "message_sent", "phase": "busy", "next": "Message sent. The sourcing agent is now processing..."}</response_format> <examples> Start a new sourcing search: send_sourcing_message(message="I need a senior backend engineer with Python and distributed systems experience, based in Europe") Start a new research search: send_sourcing_message(mode="research", message="Compare the engineering cultures and tech stacks at Stripe, Square, and Adyen") Send a follow-up: send_sourcing_message(search_id="550e8400-...", message="Also consider candidates with Go experience, not just Python") </examples>

create_ai_field

Claude

create_report

Claude

find_candidate_in_sequences

Claude

get_chart_data

Claude

get_enrichment_status

Claude

get_user_context

Claude

group_conversations

Claude

list_field_values

Claude

list_fields

Claude

list_send_on_behalf_permissions

Claude

list_sequence_candidates

Claude

list_sequences

Claude

manage_candidate_sequence

Claude

manage_sequence

Claude

search_conversations

Claude

search_reports

Claude

App Stats

45

Tools

0

Prompts

May 19, 2026

First seen

ChatGPT, Claude

Platforms

Works with

ChatGPT
Claude

Data refreshed daily