# MCP Tool Reference

> All 70 tools of Reply.io's live MCP server (mcp2.reply.io), verified against the running server — real signatures, per-argument documentation, enum values, annotations, and per-tool failure modes.

This is the full tool reference for the [Reply MCP server](/mcp) — read live from `https://mcp2.reply.io/` via authenticated `initialize` + `tools/list` on 2026-07-05. For the server overview, auth, contract rules, response envelopes, error model, workflow recipes, and high-stakes guidance, see the [MCP overview](/mcp).

**Tool groups:** [Sequences — discover & inspect](#sequences--discover--inspect) · [Sequences — control & configuration](#sequences--control--configuration) · [Contacts](#contacts) · [Inbox & conversations](#inbox--conversations) · [Jason AI SDR — approvals & autopilot](#jason-ai-sdr--approvals--autopilot) · [Jason AI SDR — knowledge bases](#jason-ai-sdr--knowledge-bases) · [Jason AI SDR — reply handlers](#jason-ai-sdr--reply-handlers) · [Jason AI SDR — reengagement cards](#jason-ai-sdr--reengagement-cards) · [Jason AI SDR — offers](#jason-ai-sdr--offers) · [Jason AI SDR — playbooks](#jason-ai-sdr--playbooks) · [Tasks](#tasks) · [Workspace resolvers & accounts](#workspace-resolvers--accounts) · [Help & meta](#help--meta)

Every entry is the tool's real name, its server-sent annotation (📖 `readOnlyHint` / ✏️ `destructiveHint`, plus ⚠️ for the prospect-visible/irreversible subset), its **verified signature** (`param*` = required; `type?` = nullable), the server's own description — including ID rules, enum values, batch limits, and per-code failure guidance — and the per-argument documentation exactly as served.
### Sequences — discover & inspect

**`reply_search_sequences`** — 📖 read-only
`(name: string, status: string, isArchived: boolean, top: integer, skip: integer)`
Returns a paginated list of sequences (campaigns) the user owns or has access to, optionally filtered by name substring, status, and archive flag. Use this both to find sequences by human-friendly name and to retrieve their per-sequence summary fields (status, archived flag, owner, health) in a single call. Call reply_get_sequence_stats afterwards for email/LinkedIn performance metrics on a specific sequence. Does NOT include step content, prospect lists, or detailed stats. Failure modes: InvalidArguments (Status must be one of New/Active/Paused if supplied; Name capped at 256 chars); Forbidden (workspace cannot list sequences; tell the user, do not retry); ServiceUnavailable (transient; retry once, then tell the user).
- `name` (string, optional) — Optional case-insensitive substring filter on the sequence name. Pass null or omit to list all sequences.
- `status` (string, optional) — Optional status filter. Allowed values (case-insensitive): 'New', 'Active', 'Paused'. Pass null or omit to include every status.
- `isArchived` (boolean, optional) — Optional archive filter. true = archived only, false = non-archived only, null/omit = both.
- `top` (integer, optional) — Optional page size. Default 20, max 100. Increase only if the user explicitly asks for more.
- `skip` (integer, optional) — Optional pagination offset. Default 0. Use HasMore on the response to decide whether to call again with Skip = previous Skip + Top.

**`reply_get_sequence_steps`** — 📖 read-only
`(sequenceId*: integer)`
Returns the ordered steps of a sequence: each step's type, delay, position in the flow, and how many message content variants it has. Use this to inspect a sequence's structure and cadence, or to find a step's numeric ID before reading its content. REQUIRES the exact numeric sequence ID. Must come from a prior reply_search_sequences result or another tool's output. Never invent, estimate, default, or ask the user; if only the name is known, call reply_search_sequences first. Does NOT include the step text (subjects/messages); call reply_get_sequence_step_variants with a StepId to read an email or LinkedIn-message step's content. Failure modes: InvalidArguments (SequenceId must be > 0); NotFound (the sequence does not exist, has no steps, or is not accessible in this workspace; re-resolve via reply_search_sequences); ServiceUnavailable (transient; retry once, then tell the user).
- `sequenceId` (integer, required) — The exact numeric ID of the sequence whose steps to read. Must come from a prior reply_search_sequences result or another tool's output. Never invent, estimate, default, or ask the user; if only the name is known, call reply_search_sequences first. REQUIRED.

**`reply_get_sequence_step_variants`** — 📖 read-only
`(sequenceId*: integer, stepId*: integer)`
Returns the content variants (A/B variations) of a single sequence step: subject, message body, enabled flag, and attachment flag. Use this after reply_get_sequence_steps to read what an email or LinkedIn-message step actually says. REQUIRES the exact numeric sequence ID and step ID, both from prior tool output (reply_search_sequences, then reply_get_sequence_steps). Never invent, estimate, default, or ask the user. Only message-bearing steps (email, LinkedIn message/connect/InMail/voice) have variants; steps like Call, Task, or Condition do not. Failure modes: InvalidArguments (SequenceId and StepId must be > 0); NotFound (the sequence or step does not exist or is not accessible; re-resolve via reply_search_sequences then reply_get_sequence_steps); UnsupportedOperation (this step type does not support content variants; tell the user instead of retrying); ServiceUnavailable (transient; retry once, then tell the user).
- `sequenceId` (integer, required) — The exact numeric ID of the sequence. Must come from prior tool output (reply_search_sequences). Never invent, estimate, default, or ask the user. REQUIRED.
- `stepId` (integer, required) — The exact numeric ID of the step whose content variants to read. Must come from a prior reply_get_sequence_steps result for this same sequence. Never invent, estimate, default, or ask the user. REQUIRED.

**`reply_get_sequence_stats`** — 📖 read-only
`(sequenceId*: integer, from: string, to: string)`
Returns email and LinkedIn performance metrics for one sequence: contact volume, delivered/opened/replied/bounced rates, LinkedIn connection and message stats, meetings booked. REQUIRES the exact numeric sequence ID. Do NOT guess, fabricate, or estimate it. If the user refers to a sequence by name (e.g. 'Sales Q1') and the numeric ID is unknown, call reply_search_sequences first to discover it. Do NOT ask the user for a numeric ID; users do not know internal IDs. Date window defaults to all-time; pass From/To (UTC ISO-8601) for a custom range. Does NOT accept multiple sequence IDs. Call once per sequence and aggregate yourself when comparing. Failure modes: InvalidArguments (SequenceId must be > 0; From must be <= To); ServiceUnavailable (the stats backend is temporarily offline; retry once, then tell the user). A sequence the workspace cannot access produces empty Email/LinkedIn summaries rather than an error.
- `sequenceId` (integer, required) — The exact numeric ID of the sequence to retrieve stats for. Must come from a prior reply_search_sequences result or another tool's output earlier in this conversation. Never invent, estimate, default, or ask the user for this value. If only the name is known, call reply_search_sequences first. REQUIRED.
- `from` (string, optional) — Optional start of the date window (UTC, ISO-8601 with offset, e.g. '2025-01-01T00:00:00Z'). null/omit = all time.
- `to` (string, optional) — Optional end of the date window (UTC, ISO-8601 with offset, e.g. '2025-03-31T23:59:59Z'). null/omit = all time.

**`reply_compare_sequence_performance`** — 📖 read-only
`(sequenceIds*: array, from: string, to: string)`
Returns side-by-side email + LinkedIn performance metrics for multiple sequences in a single call. REQUIRES the exact numeric sequence IDs. Do NOT guess, fabricate, or estimate them. Each ID must come from a prior reply_search_sequences result or another tool's output earlier in this conversation. Do NOT ask the user for numeric IDs; users do not know internal IDs. Use this when the caller wants to compare two or more sequences directly. For a single sequence, call reply_get_sequence_stats instead. Accepts up to 25 sequence IDs per call. Date window defaults to all-time; pass From/To (UTC ISO-8601) for a custom range. Sequences with no activity in the window, or that you cannot access, are omitted from Items. Align by SequenceId (not by index) and treat a missing row as 'no data'. Does NOT include step content or prospect-level data. Failure modes: InvalidArguments (SequenceIds non-empty and <= 25 entries, each > 0; From must be <= To); ServiceUnavailable (the stats backend is temporarily offline; retry once, then tell the user). Inaccessible or empty-window sequences silently drop out of Items rather than causing an error.
- `sequenceIds` (array of integer, required) — Numeric IDs of the sequences to compare. Must come from prior tool output. Never invent, estimate, default, or ask the user. Maximum 25 IDs per call. REQUIRED.
- `from` (string, optional) — Optional start of the date window (UTC, ISO-8601 with offset, e.g. '2025-01-01T00:00:00Z'). null/omit = all time.
- `to` (string, optional) — Optional end of the date window (UTC, ISO-8601 with offset, e.g. '2025-03-31T23:59:59Z'). null/omit = all time.


### Sequences — control & configuration

**`reply_start_sequence`** — ✏️ mutation · ⚠️ high-stakes
`(sequenceId*: integer)`
Starts (or resumes) a sequence so it begins sending outreach. Mutation. REQUIRES the exact numeric sequence ID. Do NOT guess, fabricate, or estimate it. Must come from a prior reply_search_sequences result. Do NOT ask the user for a numeric ID; users do not know internal IDs. Will fail if the sequence has no contacts, no email accounts attached, or is archived. Starting a sequence that is already running succeeds and changes nothing. Does NOT add contacts; the sequence must already contain prospects. Failure modes: InvalidArguments (SequenceId must be > 0); NotFound (re-fetch via reply_search_sequences); Forbidden (workspace cannot start this sequence; tell the user, do not retry); Archived (the sequence is archived; tell the user before retrying); NoContacts (the sequence has no contacts; call reply_add_contact_to_sequence first); NoEmailAccounts (no mailbox is linked; call reply_assign_email_account_to_sequence first); SalesAgentNotAllowed (AI SDR is not enabled for this sequence; tell the user); Status (the sequence cannot be started from its current state; tell the user); ServiceUnavailable (transient; retry once, then tell the user).
- `sequenceId` (integer, required) — The exact numeric ID of the sequence to start. Must come from a prior reply_search_sequences result. Never invent, estimate, default, or ask the user for this value. REQUIRED.

**`reply_pause_sequence`** — ✏️ mutation
`(sequenceId*: integer)`
Pauses a sequence so it stops sending outreach. In-flight scheduled steps are halted. Mutation. REQUIRES the exact numeric sequence ID. Do NOT guess, fabricate, or estimate it. Must come from a prior reply_search_sequences result. Do NOT ask the user for a numeric ID; users do not know internal IDs. Paused sequences can be resumed via reply_start_sequence. Pausing a sequence that is already paused succeeds and changes nothing. Failure modes: InvalidArguments (SequenceId must be > 0); NotFound (re-fetch via reply_search_sequences); Forbidden (workspace cannot pause this sequence; tell the user, do not retry); Archived (the sequence is archived; tell the user); Status (the sequence is in a state from which it cannot be paused, e.g. it was never started; tell the user); ServiceUnavailable (transient; retry once, then tell the user).
- `sequenceId` (integer, required) — The exact numeric ID of the sequence to pause. Must come from a prior reply_search_sequences result. Never invent, estimate, default, or ask the user for this value. REQUIRED.

**`reply_add_contact_to_sequence`** — ✏️ mutation · ⚠️ high-stakes
`(sequenceId*: integer, contactIds*: array, removeFromExisting: boolean, startStepId: integer, ignoreStepDelay: boolean, startFrom: string)`
Adds one or more existing contacts to a sequence so they begin receiving its steps. Mutation, high-stakes: starting outreach to people. REQUIRES the exact numeric sequence ID and a non-empty list of contact IDs. All must come from prior tool output (reply_search_sequences, reply_search_contacts, reply_filter_contacts). Never invent, estimate, or ask the user. To start contacts at a specific step instead of the first one, pass that step's numeric Id as StartStepId; otherwise omit it to begin at the first step. Per-contact failures (already in sequence, opted out, etc.) are returned in NotProcessed; the call as a whole still succeeds. Accepts up to 100 contact IDs per call. Does NOT change the sequence's active/paused state; pair with reply_start_sequence when the sequence is paused. Failure modes: InvalidArguments (SequenceId > 0; ContactIds non-empty and <= 100 entries, all > 0; StartStepId > 0 when supplied; split into batches if needed); SequenceNotFound (re-fetch via reply_search_sequences); ContactNotFound (re-fetch contact IDs via reply_search_contacts); NoStepsInSequence (the sequence has no steps; tell the user to add steps before retrying); ContactLimitExceeded (the workspace plan has hit its sequence-contact limit; tell the user, do not retry); SequenceArchived (the sequence is archived; tell the user before retrying); Forbidden (workspace cannot operate on this sequence; tell the user, do not retry); ServiceUnavailable (transient; retry once, then tell the user). Per-contact reasons (e.g. ContactAlreadyInSequence, ContactInBlackList) appear in NotProcessed and are NOT hard failures.
- `sequenceId` (integer, required) — The exact numeric ID of the sequence to add contacts to. Must come from prior tool output. REQUIRED.
- `contactIds` (array of integer, required) — Numeric IDs of the contacts to add. Each must come from prior tool output. Never invent, estimate, default, or ask the user. Maximum 100 IDs per call. REQUIRED.
- `removeFromExisting` (boolean, optional) — Optional: when true, removes each contact from any other sequence it is currently in before adding it to this one. Defaults to false.
- `startStepId` (integer, optional) — Optional numeric ID of the sequence step to start contacts at. Only set it when you already have a valid step ID for this sequence; never invent or guess it. Pass null/omit to start at the first step.
- `ignoreStepDelay` (boolean, optional) — Optional: when true, the first step is sent immediately rather than waiting for the step's configured delay. Defaults to false.
- `startFrom` (string, optional) — Optional UTC timestamp (ISO-8601 with offset) to start the contacts from instead of 'now'. null/omit = start immediately within the schedule window.

**`reply_change_status_in_sequence`** — ✏️ mutation
`(sequenceId*: integer, contactId*: integer, status*: string)`
Sets the per-sequence status of a single contact inside one sequence. Mutation. Use this to pause a contact in a sequence, mark them as Finished, etc. REQUIRES the exact numeric sequence ID and contact ID. Both must come from prior tool output. Do NOT guess, fabricate, or estimate. Do NOT ask the user for numeric IDs; users do not know internal IDs. Allowed status values: 'Active', 'Paused', 'Finished', 'Inactive', 'OutOfOffice'. Does NOT change the contact's overall opt-out state; use a dedicated blacklist tool for that. Does NOT remove the contact from the sequence; use a removal tool for that. Failure modes: InvalidArguments (SequenceId and ContactId must be > 0; Status must be one of the five allowed values); SequenceNotFound (re-fetch via reply_search_sequences); ContactNotFound (re-fetch via reply_search_contacts); NotInSequence (the contact is not in this sequence; add it first via reply_add_contact_to_sequence); InvalidStatusTransition (this status change is not allowed from the current state; read the contact's current status first); SequenceArchived (the sequence is archived; tell the user before retrying); Forbidden (workspace cannot operate on that sequence; tell the user, do not retry); ServiceUnavailable (transient; retry once, then tell the user).
- `sequenceId` (integer, required) — The exact numeric ID of the sequence. Must come from prior tool output. REQUIRED.
- `contactId` (integer, required) — The exact numeric ID of the contact. Must come from prior tool output. Never invent, estimate, default, or ask the user. REQUIRED.
- `status` (string, required) — New status (case-insensitive). Allowed values: 'Active', 'Paused', 'Finished', 'Inactive', 'OutOfOffice'. REQUIRED.

**`reply_assign_email_account_to_sequence`** — ✏️ mutation
`(sequenceId*: integer, emailAccountId*: integer)`
Links an email account (mailbox) to a sequence so the sequence can send from it. Mutation. REQUIRES both the exact numeric sequence ID and email account ID. Both must come from prior tool output (reply_search_sequences / reply_list_email_accounts). Never invent, estimate, or ask the user. Idempotent: re-linking an already-linked account is a no-op. Does NOT unlink other accounts; the sequence can be linked to multiple mailboxes. Failure modes: InvalidArguments (SequenceId > 0, EmailAccountId > 0); NotFound (the sequence or email account does not exist; re-fetch via reply_search_sequences or reply_list_email_accounts); Forbidden (workspace cannot link this account to this sequence; tell the user, do not retry); LimitReached (sequence has hit the maximum number of linked email accounts; tell the user); ServiceUnavailable (transient; retry once, then tell the user).
- `sequenceId` (integer, required) — The exact numeric ID of the sequence to link to. Must come from prior tool output. REQUIRED.
- `emailAccountId` (integer, required) — The exact numeric ID of the email account to link. Must come from a prior reply_list_email_accounts result. REQUIRED.

**`reply_assign_linkedin_account_to_sequence`** — ✏️ mutation
`(sequenceId*: integer, linkedInAccountId*: integer)`
Links a LinkedIn account to a sequence so the sequence can run LinkedIn steps from it. Mutation. REQUIRES both the exact numeric sequence ID and LinkedIn account ID. Both must come from prior tool output (reply_search_sequences / reply_list_linkedin_accounts). Never invent, estimate, or ask the user. Idempotent: re-linking an already-linked account is a no-op. Does NOT unlink other accounts; the sequence can be linked to multiple LinkedIn accounts. Failure modes: InvalidArguments (SequenceId > 0, LinkedInAccountId > 0); NotFound (the sequence or LinkedIn account does not exist; re-fetch via reply_search_sequences or reply_list_linkedin_accounts); Forbidden (workspace cannot link this LinkedIn account; tell the user, do not retry); ServiceUnavailable (transient; retry once, then tell the user).
- `sequenceId` (integer, required) — The exact numeric ID of the sequence to link to. Must come from prior tool output. REQUIRED.
- `linkedInAccountId` (integer, required) — The exact numeric ID of the LinkedIn account to link. Must come from a prior reply_list_linkedin_accounts result. REQUIRED.

**`reply_assign_schedule_to_sequence`** — ✏️ mutation
`(sequenceId*: integer, scheduleId*: integer)`
Sets the sending schedule (business-hours window) on a sequence. Mutation. REQUIRES both the exact numeric sequence ID and schedule ID. Both must come from prior tool output (reply_search_sequences / reply_list_schedules). Never invent, estimate, or ask the user. Replaces the sequence's current schedule with the supplied one; does not modify other sequence settings. Failure modes: InvalidArguments (SequenceId > 0, ScheduleId > 0); NotFound (the sequence does not exist; re-fetch via reply_search_sequences); ScheduleNotFound (the schedule does not exist; re-fetch via reply_list_schedules); Archived (the sequence is archived; tell the user); Forbidden (workspace cannot modify this sequence; tell the user, do not retry); ServiceUnavailable (transient; retry once, then tell the user).
- `sequenceId` (integer, required) — The exact numeric ID of the sequence to update. Must come from a prior reply_search_sequences result. REQUIRED.
- `scheduleId` (integer, required) — The exact numeric ID of the schedule to assign. Must come from a prior reply_list_schedules result. REQUIRED.

**`reply_attach_offer_to_sequence`** — ✏️ mutation
`(sequenceId*: integer, offerId*: integer)`
Attaches an offer to an AI SDR sequence so Jason pitches it for that sequence's outreach. Mutation. Replaces whatever offer the sequence currently uses. REQUIRES the exact numeric SequenceId (from reply_search_sequences) and the exact numeric OfferId (from reply_list_offers). Never invent, estimate, default, or ask the user for these values. Failure modes: InvalidArguments (SequenceId and OfferId must be > 0); Forbidden (the AI SDR feature is not enabled or you cannot access this sequence; tell the user, do not retry); NotFound (the sequence does not exist; re-fetch via reply_search_sequences); InvalidParameter (the sequence is not an AI SDR sequence; tell the user); InvalidOffer (no offer with this id; re-fetch via reply_list_offers); UpstreamFailure (the AI SDR backend is temporarily unavailable; retry once, then tell the user); ServiceUnavailable (transient; retry once, then tell the user).
- `sequenceId` (integer, required) — The exact numeric ID of the AI SDR sequence. Must come from a prior reply_search_sequences result. Never invent, estimate, default, or ask the user. REQUIRED.
- `offerId` (integer, required) — The exact numeric ID of the offer to attach. Must come from a prior reply_list_offers result. Never invent, estimate, default, or ask the user. REQUIRED.

**`reply_attach_playbook_to_sequence`** — ✏️ mutation
`(sequenceId*: integer, playbookId*: string)`
Attaches a playbook to an AI SDR sequence so Jason follows it for that sequence's outreach. Mutation. Replaces whatever playbook the sequence currently uses. REQUIRES the exact numeric SequenceId (from reply_search_sequences) and the exact playbook ID (from reply_list_playbooks). Never invent, estimate, default, or ask the user for these values. Failure modes: InvalidArguments (SequenceId must be > 0; PlaybookId must be non-empty); Forbidden (the AI SDR feature is not enabled or you cannot access this sequence; tell the user, do not retry); NotFound (the sequence does not exist; re-fetch via reply_search_sequences); InvalidParameter (the sequence is not an AI SDR sequence; tell the user); InvalidIdFormat (the PlaybookId is malformed; re-fetch via reply_list_playbooks); InvalidPlaybook (no playbook with this id; re-fetch via reply_list_playbooks); UpstreamFailure (the AI SDR backend is temporarily unavailable; retry once, then tell the user); ServiceUnavailable (transient; retry once, then tell the user).
- `sequenceId` (integer, required) — The exact numeric ID of the AI SDR sequence. Must come from a prior reply_search_sequences result. Never invent, estimate, default, or ask the user. REQUIRED.
- `playbookId` (string, required) — The exact playbook ID to attach. Must come from a prior reply_list_playbooks result. Never invent, estimate, default, or ask the user. REQUIRED.

**`reply_attach_knowledge_base_to_sequence`** — ✏️ mutation
`(sequenceId*: integer, knowledgeBaseId*: integer)`
Attaches a knowledge base to an AI SDR sequence so Jason uses it when answering prospects in that sequence. Mutation. Replaces whatever knowledge base the sequence currently uses. REQUIRES the exact numeric SequenceId (from reply_search_sequences) and the exact numeric KnowledgeBaseId (from reply_list_knowledge_bases). Never invent, estimate, default, or ask the user for these values. Failure modes: InvalidArguments (SequenceId and KnowledgeBaseId must be > 0); Forbidden (the AI SDR feature is not enabled or you cannot access this sequence; tell the user, do not retry); NotFound (the sequence does not exist; re-fetch via reply_search_sequences); InvalidParameter (the sequence is not an AI SDR sequence; tell the user); InvalidKnowledgeBase (no knowledge base with this id; re-fetch via reply_list_knowledge_bases); UpstreamFailure (the AI SDR backend is temporarily unavailable; retry once, then tell the user); ServiceUnavailable (transient; retry once, then tell the user).
- `sequenceId` (integer, required) — The exact numeric ID of the AI SDR sequence. Must come from a prior reply_search_sequences result. Never invent, estimate, default, or ask the user. REQUIRED.
- `knowledgeBaseId` (integer, required) — The exact numeric ID of the knowledge base to attach. Must come from a prior reply_list_knowledge_bases result. Never invent, estimate, default, or ask the user. REQUIRED.

**`reply_set_sequence_reply_mode`** — ✏️ mutation · ⚠️ high-stakes
`(sequenceId*: integer, mode*: string, sendExistingDrafts: boolean)`
Sets how the AI SDR (Jason) handles outgoing messages for one sequence. 'Review' means Jason drafts every message and holds it in the approval queue for the user to approve, edit, or reject (use reply_list_pending_approvals to see the queue). 'Autonomous' means Jason sends messages on its own, without approval. Mutation. REQUIRES the exact numeric SequenceId from a prior reply_search_sequences result. Never invent, estimate, default, or ask the user for this value. When switching to Autonomous, set SendExistingDrafts = true to also send the drafts already waiting in the approval queue, or false (default) to leave them in place. SendExistingDrafts is ignored for Review mode. This controls only the reply/approval mode; it does NOT control evergreen contact sourcing (autopilot). Setting a sequence to the mode it is already in succeeds and changes nothing. Failure modes: InvalidArguments (SequenceId must be > 0; Mode must be 'Review' or 'Autonomous'); Forbidden (the AI SDR feature is not enabled or you cannot access this sequence; tell the user, do not retry); NotFound (the sequence does not exist; re-fetch via reply_search_sequences); InvalidParameter (the sequence is not an AI SDR sequence; tell the user, do not retry); UpstreamFailure (the AI SDR backend is temporarily unavailable; retry once, then tell the user); ServiceUnavailable (transient; retry once, then tell the user).
- `sequenceId` (integer, required) — The exact numeric ID of the AI SDR sequence to update. Must come from a prior reply_search_sequences result. Never invent, estimate, default, or ask the user. REQUIRED.
- `mode` (string, required) — How Jason should handle outgoing messages (case-insensitive). Allowed values: 'Review' (Jason drafts and waits for approval) or 'Autonomous' (Jason sends on its own). REQUIRED.
- `sendExistingDrafts` (boolean, optional) — Only used when Mode is 'Autonomous': set true to also send the drafts already waiting in the approval queue, false (default) to leave them. Ignored for 'Review'.


### Contacts

**`reply_search_contacts`** — 📖 read-only
`(email: string, linkedIn: string, top: integer, skip: integer)`
Looks up contacts by exact email address or LinkedIn URL. Returns matching contacts with their full profile: name, company, custom fields, sequence/list membership, status flags. At least one of Email or LinkedIn must be provided; passing both narrows to contacts that match both. Does NOT accept name substrings, company filters, or other criteria. If the user provides only a name or company, ask them for an email or LinkedIn URL instead of calling this tool. Failure modes: InvalidArguments (at least one of Email or LinkedIn must be non-empty; both are capped at 512 chars); Forbidden (workspace is not allowed to read contacts; tell the user, do not retry); ServiceUnavailable (transient; retry once, then tell the user the system is temporarily offline).
- `email` (string, optional) — Exact email address to filter by. At least one of Email or LinkedIn must be provided.
- `linkedIn` (string, optional) — Exact LinkedIn URL to filter by. At least one of Email or LinkedIn must be provided.
- `top` (integer, optional) — Optional page size. Default 20, max 100.
- `skip` (integer, optional) — Optional pagination offset. Default 0. Use HasMore on the response to decide whether to call again with Skip = previous Skip + Top.

**`reply_filter_contacts`** — 📖 read-only
`(listId: integer, sequenceId: integer, searchTerm: string, top: integer, skip: integer)`
Lists contacts narrowed by list membership, sequence membership and/or a free-text search term applied to name/email/company. Use this when the caller asks for contacts "in list X", "in sequence Y", or matching some text. Numeric IDs (ListId, SequenceId) MUST come from prior tool output: call reply_search_lists to resolve a list name to ListId, reply_search_sequences for SequenceId. Do NOT guess, fabricate, or estimate IDs. Do NOT ask the user for numeric IDs; users do not know internal IDs. When summarising results to the user, refer to lists / sequences by their Name (already present on each returned contact under Lists[].ListName and Sequences[].SequenceName), not their numeric IDs. Does NOT accept rule-based property/condition filters (those require a separate tool). For exact email or LinkedIn URL lookups, call reply_search_contacts instead. A ListId or SequenceId that does not exist produces an empty page, not an error: if you expected matches, re-resolve the ID via reply_search_lists / reply_search_sequences. Failure modes: InvalidArguments (IDs must be > 0; SearchTerm capped at 512 chars); Forbidden (workspace cannot read contacts; tell the user, do not retry); ServiceUnavailable (transient; retry once, then tell the user).
- `listId` (integer, optional) — Optional contact list ID. Must come from a prior reply_search_lists result. Never invent, estimate, default, or ask the user for this value. If the caller mentions a list by name, call reply_search_lists first. Pass null/omit to skip.
- `sequenceId` (integer, optional) — Optional sequence ID. Must come from a prior reply_search_sequences result or another tool's output. Never invent, estimate, default, or ask the user for this value. Pass null/omit to skip.
- `searchTerm` (string, optional) — Optional free-text search applied to first/last name, email, and company. Pass null/omit to skip.
- `top` (integer, optional) — Optional page size. Default 20, max 100.
- `skip` (integer, optional) — Optional pagination offset. Default 0. Use HasMore on the response to decide whether to call again with Skip = previous Skip + Top.

**`reply_create_contact`** — ✏️ mutation
`(email: string, linkedInUrl: string, firstName: string, lastName: string, phone: string, title: string, company: string, industry: string, city: string, state: string, country: string, timeZoneId: string, notes: string)`
Creates a new contact in the workspace. Mutation. REQUIRES the contact's name: at least one of FirstName or LastName must be non-empty. If the user did not give a name, ask them for it ("What is the contact's full name?") BEFORE calling this tool; do not invent or default a name. REQUIRES at least one of Email or LinkedInUrl. Other fields are optional. Returns the newly created contact's full profile, including its numeric ID, which can be used in subsequent tool calls. Does NOT add the contact to any sequence; use a dedicated sequence-add tool for that. Does NOT validate or normalize phone / LinkedIn URL formats; pass them as the user provided. On workspaces with the Accounts feature enabled, a supplied Company (with optional Industry) is used to link the contact to a matching Account — found by company name and email domain, or created if none exists — instead of being stored on the contact directly; just pass the company name as Company. When the Accounts feature is off, Company and Industry are stored on the contact directly. Failure modes: InvalidArguments (FirstName or LastName must be non-empty, ask the user for the name; Email or LinkedInUrl is required; respect string length caps: Email 256, LinkedInUrl 512, names 128, Title/Industry/Phone 256, City 180, State 100, Country 90, TimeZoneId 90, Notes 512); InvalidInput (upstream rejected the payload after our checks; surface the message); Forbidden (workspace cannot create contacts; tell the user, do not retry); PERMISSION_DENIED (the user lacks permission to create Accounts, needed to link a new Company; surfaced as PERMISSION_DENIED on MCP and as a transient-looking error on other surfaces — either way do not retry, tell the user to use an existing company/Account or request the permission); ServiceUnavailable (transient; retry once, then tell the user).
- `email` (string, optional) — Email address. Required unless LinkedInUrl is provided.
- `linkedInUrl` (string, optional) — Public LinkedIn profile URL. Required unless Email is provided.
- `firstName` (string, optional) — First name.
- `lastName` (string, optional) — Last name.
- `phone` (string, optional) — Phone number.
- `title` (string, optional) — Job title.
- `company` (string, optional) — Company name. On workspaces with the Accounts feature enabled, this links the contact to a matching Account (found by name/email-domain, or created) rather than being stored on the contact directly.
- `industry` (string, optional) — Industry. On workspaces with the Accounts feature enabled, it is applied to the linked Account only when a new Account is created from Company.
- `city` (string, optional) — City.
- `state` (string, optional) — State / region.
- `country` (string, optional) — Country.
- `timeZoneId` (string, optional) — IANA timezone ID (e.g. 'America/New_York').
- `notes` (string, optional) — Free-form notes about the contact.

**`reply_update_contact`** — ✏️ mutation
`(contactId*: integer, email: string, firstName: string, lastName: string, phone: string, title: string, company: string, industry: string, city: string, state: string, country: string, timeZoneId: string, linkedInUrl: string, notes: string)`
Updates fields on an existing contact. Patch semantics: only the fields you pass are changed; null or omitted fields keep their current value. Mutation. REQUIRES the exact numeric contact ID. Must come from a prior reply_search_contacts or reply_filter_contacts result. Never invent, estimate, default, or ask the user. Does NOT add or remove the contact from sequences. Does NOT change the contact's owner; that requires a separate tool. On workspaces with the Accounts feature enabled, setting Company (with optional Industry) links the contact to a matching Account — found by company name and email domain, or created if none exists — instead of editing the contact directly; pass the company name as Company to relink. When the Accounts feature is off, Company and Industry are stored on the contact directly. Failure modes: InvalidArguments (ContactId must be > 0; at least one field other than ContactId must be set; respect string length caps); InvalidInput (V3 rejected the patch; surface the message and correct the field values); NotFound (the contact does not exist; re-fetch via reply_search_contacts); Forbidden (workspace cannot update this contact; tell the user, do not retry); PERMISSION_DENIED (the user lacks permission to create Accounts, needed to link a new Company; surfaced as PERMISSION_DENIED on MCP and as a transient-looking error on other surfaces — either way do not retry, tell the user to use an existing company/Account or request the permission); ServiceUnavailable (transient; retry once, then tell the user).
- `contactId` (integer, required) — The exact numeric ID of the contact to update. Must come from prior tool output. Never invent, estimate, default, or ask the user. REQUIRED.
- `email` (string, optional) — New email address. Pass null/omit to keep the current value.
- `firstName` (string, optional) — New first name. Pass null/omit to keep the current value.
- `lastName` (string, optional) — New last name. Pass null/omit to keep the current value.
- `phone` (string, optional) — New phone number. Pass null/omit to keep the current value.
- `title` (string, optional) — New job title. Pass null/omit to keep the current value.
- `company` (string, optional) — New company. Pass null/omit to keep the current value. On workspaces with the Accounts feature enabled, this relinks the contact to a matching Account (found by name/email-domain, or created) instead of editing the contact directly.
- `industry` (string, optional) — New industry. Pass null/omit to keep the current value. On workspaces with the Accounts feature enabled, it is applied to the linked Account only when a new Account is created from Company.
- `city` (string, optional) — New city. Pass null/omit to keep the current value.
- `state` (string, optional) — New state. Pass null/omit to keep the current value.
- `country` (string, optional) — New country. Pass null/omit to keep the current value.
- `timeZoneId` (string, optional) — New IANA timezone ID. Pass null/omit to keep the current value.
- `linkedInUrl` (string, optional) — New LinkedIn URL. Pass null/omit to keep the current value.
- `notes` (string, optional) — New notes. Pass null/omit to keep the current value.

**`reply_get_contact_activity`** — 📖 read-only
`(contactId*: integer, top: integer, skip: integer)`
Returns the activity history for one contact: emails sent / opened / replied, LinkedIn actions, calls, manual events, ordered newest first. REQUIRES the exact numeric contact ID. Do NOT guess, fabricate, or estimate it. If only the email or LinkedIn URL is known, call reply_search_contacts first. Do NOT ask the user for a numeric contact ID; users do not know internal IDs. Paginated; iterate with Skip until HasMore is false. Does NOT include sequence-level performance metrics (use reply_get_sequence_stats for those). Failure modes: InvalidArguments (ContactId must be > 0); NotFound (the contact does not exist in this workspace; re-fetch via reply_search_contacts using the email/LinkedIn URL); Forbidden (workspace cannot read this contact; tell the user, do not retry); ServiceUnavailable (transient; retry once, then tell the user).
- `contactId` (integer, required) — The exact numeric ID of the contact whose activity to fetch. Must come from a prior reply_search_contacts result or another tool's output earlier in this conversation. Never invent, estimate, default, or ask the user for this value. If only the email or LinkedIn URL is known, call reply_search_contacts first. REQUIRED.
- `top` (integer, optional) — Optional page size. Default 20, max 100.
- `skip` (integer, optional) — Optional pagination offset. Default 0. Use HasMore on the response to decide whether to call again with Skip = previous Skip + Top.

**`reply_mark_contacts_as_replied`** — ✏️ mutation
`(contactIds*: array, isReplied: boolean)`
Marks one or more contacts as having replied (or clears that flag), the same action as manually flagging a reply in Reply.io. Mutation. Marking a contact as replied stops further automated outreach to them in their active sequences. REQUIRES a non-empty list of numeric contact IDs. All must come from prior tool output (reply_search_contacts, reply_filter_contacts). Never invent, estimate, default, or ask the user; users do not know internal IDs. Set IsReplied=false only when the user explicitly asks to undo or clear a replied flag; omit it (or pass true) to mark as replied. Accepts up to 100 contact IDs per call. Contacts already in the requested state are treated as success and appear in Affected. Per-contact problems (contact not found, contact ineligible) are returned in NotProcessed and are NOT hard failures; the call as a whole still succeeds. Does NOT change the contact's per-sequence status directly (use reply_change_status_in_sequence) and does NOT blacklist or opt the contact out (use reply_blacklist_contact). Failure modes: InvalidArguments (ContactIds must be non-empty and <= 100 entries, all > 0; split into batches if needed); ServiceUnavailable (transient; retry once, then tell the user). Per-contact reasons appear in NotProcessed and are NOT hard failures: 'NotFound' means the contact ID does not exist in this workspace (re-resolve via reply_search_contacts); 'InvalidInput' means the contact was skipped as ineligible (e.g. opted out or not accessible).
- `contactIds` (array of integer, required) — Numeric IDs of the contacts to mark as replied. Each must come from prior tool output (reply_search_contacts or reply_filter_contacts). Never invent, estimate, default, or ask the user; users do not know internal IDs. Maximum 100 IDs per call. REQUIRED.
- `isReplied` (boolean, optional) — Optional. true (default) marks the contacts as having replied; false clears the replied flag. Omit to mark as replied.

**`reply_change_contact_owner`** — ✏️ mutation · ⚠️ high-stakes
`(contactIds*: array, newOwnerUserId*: integer, reassignTasks: boolean)`
Reassigns one or more contacts to a different Reply.io user. Mutation, high-stakes: changes who sees the contacts and can act on their behalf. REQUIRES a non-empty list of numeric contact IDs and the numeric UserId of the new owner. ContactIds must come from reply_search_contacts or reply_filter_contacts; NewOwnerUserId must come from reply_search_team_members. Never invent, estimate, or ask the user. ReassignTasks: when true, open tasks attached to those contacts are reassigned to the new owner too; when false (default), tasks keep their existing assignee. Accepts up to 100 contact IDs per call. When confirming completion to the user, refer to the new owner by their FullName (from reply_search_team_members), not by the numeric UserId. PARTIAL-SUCCESS HANDLING: AffectedContactIds is the authoritative list of contacts whose owner actually changed. Never claim that an input ContactId was reassigned unless it appears in AffectedContactIds. If AffectedContactIds.Count is less than the number of input ContactIds, report the exact counts (e.g. 'reassigned 48 of 50'). Contact IDs that do not exist, or whose per-contact owner could not be changed, are not reported as errors: they are simply absent from AffectedContactIds. Failure modes: InvalidArguments (ContactIds must be non-empty and <= 100 entries, all > 0; NewOwnerUserId must be > 0; split into batches if needed); NotFound (the target user is not a member of this workspace; re-fetch via reply_search_team_members); LimitExceeded (the reassignment would exceed the contact limit; tell the user, do not retry); Forbidden (workspace cannot reassign these contacts; tell the user, do not retry); ServiceUnavailable (transient; retry once, then tell the user).
- `contactIds` (array of integer, required) — Numeric IDs of the contacts to reassign. Each must come from prior tool output. Never invent, estimate, default, or ask the user. Maximum 100 IDs per call. REQUIRED.
- `newOwnerUserId` (integer, required) — Numeric UserId of the user who will become the new owner. Must come from a prior reply_search_team_members result. Never invent, estimate, or ask the user for this value; if the caller refers to the new owner by name, call reply_search_team_members first. REQUIRED.
- `reassignTasks` (boolean, optional) — Optional: when true, open tasks attached to these contacts are also reassigned to the new owner. Defaults to false.

**`reply_blacklist_contact`** — ✏️ mutation · ⚠️ high-stakes
`(contactId*: integer, blockEntireDomain: boolean)`
Adds the contact's email (or the contact's whole email domain) to the workspace blacklist so future outreach to that address (or any address on that domain) is blocked at send time. Mutation, high-stakes. REQUIRES the exact numeric contact ID. Must come from a prior reply_search_contacts or reply_filter_contacts result. Never invent, estimate, default, or ask the user. When BlockEntireDomain is true, every contact on the same email domain becomes blocked, including ones not yet in the workspace. Use the per-email default unless the user explicitly asks to block the whole company. Different from "opting out": opt-out is a per-prospect flag that stops sending; the blacklist is a workspace-wide email/domain pattern list that prevents sending even to new contacts matching the pattern. Does NOT delete the contact; their profile and history remain visible. Failure modes: InvalidArguments (ContactId must be > 0; business rejections also arrive under this code with the reason in the message: 'NotFound' means the contact does not exist, re-fetch via reply_search_contacts; 'Forbidden' means blacklisting is not allowed for this workspace, tell the user and do not retry); ServiceUnavailable (transient; retry once, then tell the user).
- `contactId` (integer, required) — The exact numeric ID of the contact to blacklist. Must come from a prior reply_search_contacts or reply_filter_contacts result. Never invent, estimate, default, or ask the user. REQUIRED.
- `blockEntireDomain` (boolean, optional) — Optional. When true, blacklists the entire email domain of the contact (e.g. all addresses on '@example.com'); when false or omitted, blacklists only this contact's exact email. Default false. Only set true when the user explicitly asks to block the whole company / domain.


### Inbox & conversations

**`reply_get_inbox_emails`** — 📖 read-only
`(top: integer, skip: integer)`
Returns inbox threads (email + LinkedIn replies), typically newest first by LastActivityDate as ordered by the underlying service, with a short body preview, contact info, sequence link, category, and read state. Use this when the caller asks "what's in my inbox", "any new replies", "unread messages", etc. Does NOT include full message bodies; if the LLM needs the full thread, a future thread-get tool is required. Does NOT accept filter criteria in v1; pagination only. Failure modes: Forbidden (workspace cannot read the inbox; tell the user, do not retry); ServiceUnavailable (transient; retry once, then tell the user).
- `top` (integer, optional) — Optional page size. Default 20, max 100.
- `skip` (integer, optional) — Optional pagination offset. Default 0. Use HasMore on the response to decide whether to call again with Skip = previous Skip + Top.

**`reply_send_inbox_reply`** — ✏️ mutation · ⚠️ high-stakes
`(threadId*: integer, channel*: string, message*: string)`
Sends a reply on an existing inbox thread. Mutation, high-stakes: the message goes to the contact as soon as the call succeeds. REQUIRES the exact numeric thread ID. Must come from a prior reply_get_inbox_emails result. Never invent, estimate, default, or ask the user. Channel ('Email' or 'LinkedIn') must match the thread's channel; reply_get_inbox_emails exposes it. The wrong channel will be rejected. Message is the body, plain text or HTML; the underlying service applies the user's signature for email when applicable. Does NOT support Cc/Bcc, attachments, or scheduling in v1. Use only when the user has explicitly approved the exact text being sent. Failure modes: InvalidArguments (ThreadId > 0; Channel must be Email or LinkedIn; Message non-empty, max 32000 chars); InvalidInput (V3 rejected the payload); NotFound (thread does not exist; re-fetch via reply_get_inbox_emails); ChannelMismatch (the Channel does not match the thread's actual channel; re-read the thread to find its channel); ContactOptedOut (the contact is blacklisted; cannot send, tell the user); ThreadSendFailed (delivery failed at the provider; tell the user, do not retry blindly); Forbidden (workspace cannot send on this thread; tell the user, do not retry); ServiceUnavailable (transient; retry once, then tell the user).
- `threadId` (integer, required) — Numeric ID of the inbox thread to reply on. Must come from a prior reply_get_inbox_emails result. Never invent, estimate, default, or ask the user. REQUIRED.
- `channel` (string, required) — Channel of the thread (case-insensitive). Must match the thread's channel from reply_get_inbox_emails. Allowed values: 'Email', 'LinkedIn'. REQUIRED.
- `message` (string, required) — Message body to send. Plain text or HTML for email; plain text for LinkedIn. Max 32000 characters. REQUIRED.

**`reply_change_inbox_category`** — ✏️ mutation
`(threadId*: integer, categoryId: integer)`
Assigns (or clears) the workspace-defined category on one inbox thread. Mutation. REQUIRES the exact numeric thread ID. Must come from a prior reply_get_inbox_emails result. Never invent, estimate, default, or ask the user. Pass CategoryId = null/omit to clear the category. Categories are workspace-scoped; CategoryId must match a category the workspace has defined (e.g. via the inbox UI). Failure modes: InvalidArguments (ThreadId must be > 0; CategoryId must be > 0 when set); NotFound (the thread or category does not exist; re-fetch thread via reply_get_inbox_emails); Forbidden (workspace cannot modify this thread; tell the user, do not retry); ServiceUnavailable (transient; retry once, then tell the user).
- `threadId` (integer, required) — Numeric ID of the inbox thread. Must come from a prior reply_get_inbox_emails result. REQUIRED.
- `categoryId` (integer, optional) — Numeric ID of the category to assign. Must match a workspace-defined category. Pass null/omit to clear the category.


### Jason AI SDR — approvals & autopilot

**`reply_list_pending_approvals`** — 📖 read-only
`(top: integer, skip: integer, sequenceId: integer, ownerUserId: integer, channel: string, sortMode: string)`
Returns the queue of AI SDR (Jason) draft messages waiting for the user's approval before they are sent, newest first by default. Each item names the contact and sequence, the channel, the step, the drafted subject and full message text, and whether it is currently being regenerated. Use this when the user asks what is waiting for approval or what Jason has drafted, and before approving, rejecting, or regenerating drafts. Optional filters narrow the queue by a single sequence, a single owner (team member), and the channel; use the same filters to gather references for reply_bulk_approve_messages. Does NOT include already-sent messages or full conversation history. Failure modes: Forbidden (the AI SDR feature is not enabled for this workspace; tell the user, do not retry); UpstreamFailure (the AI SDR backend is temporarily unavailable; retry once, then tell the user); ServiceUnavailable (transient; retry once, then tell the user).
- `top` (integer, optional) — Optional page size. Default 20, max 100.
- `skip` (integer, optional) — Optional pagination offset. Default 0. Use HasMore on the response to decide whether to call again with Skip = previous Skip + Top.
- `sequenceId` (integer, optional) — Optional. Restrict the queue to one sequence. Must come from a prior reply_search_sequences result; never invent or ask the user. Omit to include all sequences.
- `ownerUserId` (integer, optional) — Optional. Restrict the queue to drafts owned by one team member. Must come from a prior reply_search_team_members result; never invent or ask the user. Omit to include all owners.
- `channel` (string, optional) — Optional channel filter (case-insensitive). Allowed values: 'Email', 'LinkedIn'. Omit to include both channels.
- `sortMode` (string, optional) — Optional sort order (case-insensitive). Allowed values: 'NewestFirst' (default), 'OldestFirst'.

**`reply_approve_message`** — ✏️ mutation · ⚠️ high-stakes
`(sequenceId*: integer, contactId*: integer, body: string, subject: string)`
Approves a single AI SDR draft and sends it to the contact immediately. Mutation, high-stakes: the message goes out as soon as the call succeeds. Identify the draft by the exact numeric SequenceId and ContactId from a prior reply_list_pending_approvals result. Never invent, estimate, default, or ask the user for these values. Optionally override the drafted Body and/or Subject; omit them to send exactly what Jason drafted. Only call this after the user has explicitly approved sending. Failure modes: InvalidArguments (SequenceId and ContactId must be > 0); Forbidden (the AI SDR feature is not enabled; tell the user, do not retry); NotFound (no pending approval exists for this sequence and contact, e.g. it was already sent, rejected, or is regenerating; re-list via reply_list_pending_approvals); UpstreamFailure (the AI SDR backend is temporarily unavailable; retry once, then tell the user); ServiceUnavailable (transient; retry once, then tell the user).
- `sequenceId` (integer, required) — Numeric ID of the sequence the draft belongs to. Must come from a prior reply_list_pending_approvals result. Never invent, estimate, default, or ask the user. REQUIRED.
- `contactId` (integer, required) — Numeric ID of the contact the draft is addressed to. Must come from a prior reply_list_pending_approvals result. Never invent, estimate, default, or ask the user. REQUIRED.
- `body` (string, optional) — Optional edited body to send instead of the drafted text. Omit to send exactly what Jason drafted.
- `subject` (string, optional) — Optional edited subject (email only). Omit to keep the drafted subject.

**`reply_bulk_approve_messages`** — ✏️ mutation · ⚠️ high-stakes
`(items*: array)`
Approves multiple AI SDR drafts at once and sends them all immediately. Mutation, high-stakes: every listed message goes out as soon as the call succeeds. Pass the exact SequenceId and ContactId pairs from a prior reply_list_pending_approvals result. To approve everything matching a sequence, owner, or channel, first call reply_list_pending_approvals with those filters, show the user the matching drafts and the count, get explicit confirmation, then pass those references here. The batch is atomic: if any reference is not a current pending approval, the whole batch is rejected and nothing is sent. Up to 100 references per call. Failure modes: InvalidArguments (Items must be non-empty, at most 100, each with SequenceId and ContactId > 0); Forbidden (the AI SDR feature is not enabled; tell the user, do not retry); NotFound (at least one reference is not a current pending approval, e.g. already sent, rejected, or regenerating; nothing was sent, re-list via reply_list_pending_approvals and retry with only current drafts); UpstreamFailure (the AI SDR backend is temporarily unavailable; retry once, then tell the user); ServiceUnavailable (transient; retry once, then tell the user).
- `items` (array of object, required) — The drafts to approve and send, each identified by SequenceId and ContactId from a prior reply_list_pending_approvals result. Non-empty, at most 100 items. REQUIRED.

**`reply_reject_message`** — ✏️ mutation · ⚠️ high-stakes
`(sequenceId*: integer, contactId*: integer)`
Rejects a single AI SDR draft. High-stakes and irreversible: this discards the draft AND removes the contact from that sequence entirely, so the contact stops receiving any further steps. Identify the draft by the exact numeric SequenceId and ContactId from a prior reply_list_pending_approvals result. Never invent, estimate, default, or ask the user for these values. Only call this after the user has explicitly confirmed they want the contact removed from the sequence, not merely that they dislike the draft. To only revise the draft instead, use reply_regenerate_message. Failure modes: InvalidArguments (SequenceId and ContactId must be > 0); Forbidden (the AI SDR feature is not enabled; tell the user, do not retry); NotFound (no pending approval exists for this sequence and contact; re-list via reply_list_pending_approvals); UpstreamFailure (the AI SDR backend is temporarily unavailable; retry once, then tell the user); ServiceUnavailable (transient; retry once, then tell the user).
- `sequenceId` (integer, required) — Numeric ID of the sequence the draft belongs to. Must come from a prior reply_list_pending_approvals result. Never invent, estimate, default, or ask the user. REQUIRED.
- `contactId` (integer, required) — Numeric ID of the contact the draft is addressed to. Must come from a prior reply_list_pending_approvals result. Never invent, estimate, default, or ask the user. REQUIRED.

**`reply_regenerate_message`** — ✏️ mutation
`(sequenceId*: integer, contactId*: integer, recommendations: string)`
Asks the AI SDR to rewrite a single pending draft, optionally guided by the user's feedback. Mutation: this replaces the current draft. Identify the draft by the exact numeric SequenceId and ContactId from a prior reply_list_pending_approvals result. Never invent, estimate, default, or ask the user for these values. Pass Recommendations with the user's instructions for the rewrite (for example 'make it shorter and mention the free trial'); omit to regenerate without specific guidance. Regeneration runs in the background: the call returns a job id and the draft reports IsRegenerating = true until the new version is ready. Re-list via reply_list_pending_approvals to see the regenerated draft. Failure modes: InvalidArguments (SequenceId and ContactId must be > 0); Forbidden (the AI SDR feature is not enabled; tell the user, do not retry); NotFound (no pending approval exists for this sequence and contact; re-list via reply_list_pending_approvals); UpstreamFailure (the AI SDR backend is temporarily unavailable; retry once, then tell the user); ServiceUnavailable (transient; retry once, then tell the user).
- `sequenceId` (integer, required) — Numeric ID of the sequence the draft belongs to. Must come from a prior reply_list_pending_approvals result. Never invent, estimate, default, or ask the user. REQUIRED.
- `contactId` (integer, required) — Numeric ID of the contact the draft is addressed to. Must come from a prior reply_list_pending_approvals result. Never invent, estimate, default, or ask the user. REQUIRED.
- `recommendations` (string, optional) — Optional instructions for the rewrite, in the user's words (for example 'make it shorter and mention the free trial'). Omit to regenerate without specific guidance.


### Jason AI SDR — knowledge bases

**`reply_list_knowledge_bases`** — 📖 read-only
`(top: integer, skip: integer, search: string)`
Lists the AI SDR (Jason) knowledge bases in the workspace: the bundles of company information Jason uses to answer prospects, which can be attached to sequences. Returns each knowledge base's id, name, and last-updated time. Use this to find a knowledge base and its id before getting, adding sources to, or attaching it. This is NOT the Reply.io Help Center; for product how-to questions use reply_search_knowledge_base instead. Optional case-insensitive name search. Failure modes: Forbidden (the AI SDR feature is not enabled; tell the user, do not retry); UpstreamFailure (the AI SDR backend is temporarily unavailable; retry once, then tell the user); ServiceUnavailable (transient; retry once, then tell the user).
- `top` (integer, optional) — Optional page size. Default 20, max 100.
- `skip` (integer, optional) — Optional pagination offset. Default 0. Use HasMore on the response to decide whether to call again with Skip = previous Skip + Top.
- `search` (string, optional) — Optional case-insensitive substring to match against the knowledge base name. Omit to list all.

**`reply_get_knowledge_base`** — 📖 read-only
`(knowledgeBaseId*: integer)`
Returns one AI SDR (Jason) knowledge base in full: its name, its free-text Instructions, the web-page URL sources it contains (with their source ids), and how many reply handlers and reengagement cards it holds. Use this to check what Jason already knows before adding or replacing content. To edit the Instructions text use reply_update_knowledge_base. REQUIRES the exact numeric knowledge base ID from a prior reply_list_knowledge_bases result. Never invent, estimate, default, or ask the user for this value. Only URL link sources are listed inline (up to 100); for the reply handlers use reply_list_reply_handlers and for the reengagement cards use reply_list_reengagement_cards. Uploaded documents are managed in the app UI, not via chat. Failure modes: InvalidArguments (KnowledgeBaseId must be > 0); Forbidden (the AI SDR feature is not enabled; tell the user, do not retry); NotFound (no knowledge base with this id; re-fetch via reply_list_knowledge_bases); UpstreamFailure (the AI SDR backend is temporarily unavailable; retry once, then tell the user); ServiceUnavailable (transient; retry once, then tell the user).
- `knowledgeBaseId` (integer, required) — The exact numeric knowledge base ID to fetch. Must come from a prior reply_list_knowledge_bases result. Never invent, estimate, default, or ask the user. REQUIRED.

**`reply_create_knowledge_base`** — ✏️ mutation
`(name*: string, instructions: string)`
Creates a new AI SDR (Jason) knowledge base. Mutation. Name is required. Instructions is optional free text telling Jason how to use this knowledge when answering prospects. Add URL sources afterwards with reply_add_knowledge_base_source, then attach it to a sequence with reply_attach_knowledge_base_to_sequence. Failure modes: InvalidArguments (Name must be non-empty); Forbidden (the AI SDR feature is not enabled; tell the user, do not retry); Conflict (a knowledge base with this name already exists; choose another name); InvalidParameter (the content was rejected; the message explains why); UpstreamFailure (the AI SDR backend is temporarily unavailable; retry once, then tell the user); ServiceUnavailable (transient; retry once, then tell the user).
- `name` (string, required) — Knowledge base name (a short label). REQUIRED.
- `instructions` (string, optional) — Optional free-text instructions telling Jason how to use this knowledge. Omit to leave empty.

**`reply_update_knowledge_base`** — ✏️ mutation
`(knowledgeBaseId*: integer, name: string, instructions: string)`
Updates an existing AI SDR (Jason) knowledge base. Mutation, patch semantics: only the fields you pass are changed; omitted fields are left as-is. This is how you save typed text guidance for Jason: pass it as Instructions (free text telling Jason how to use this knowledge when answering prospects). You can also rename the knowledge base. REQUIRES the exact numeric knowledge base ID from a prior reply_list_knowledge_bases result. Never invent, estimate, default, or ask the user for this value. Changes take effect for any sequence already using this knowledge base. Failure modes: InvalidArguments (KnowledgeBaseId must be > 0; provide at least one of Name or Instructions); Forbidden (the AI SDR feature is not enabled; tell the user, do not retry); NotFound (no knowledge base with this id; re-fetch via reply_list_knowledge_bases); Conflict (a knowledge base with this name already exists; choose another name); InvalidParameter (the content was rejected; the message explains why); UpstreamFailure (the AI SDR backend is temporarily unavailable; retry once, then tell the user); ServiceUnavailable (transient; retry once, then tell the user).
- `knowledgeBaseId` (integer, required) — The exact numeric knowledge base ID to update. Must come from a prior reply_list_knowledge_bases result. Never invent, estimate, default, or ask the user. REQUIRED.
- `name` (string, optional) — New name. Omit to keep the current value.
- `instructions` (string, optional) — New free-text instructions telling Jason how to use this knowledge. Pass an empty string to clear them. Omit to keep the current value.

**`reply_add_knowledge_base_source`** — ✏️ mutation
`(knowledgeBaseId*: integer, url*: string)`
Adds a web-page URL as a source to an AI SDR (Jason) knowledge base, so Jason can use that page's content when answering prospects. Mutation. REQUIRES the exact numeric knowledge base ID from a prior reply_list_knowledge_bases result. Never invent, estimate, default, or ask the user for this value. This tool adds web-page URLs only. To save typed text guidance, edit the knowledge base Instructions with reply_update_knowledge_base; to add a templated answer use reply_create_reply_handler; to add a win-back card use reply_create_reengagement_card. Uploading documents is done in the app UI, not via chat. Failure modes: InvalidArguments (KnowledgeBaseId must be > 0; Url must be non-empty); Forbidden (the AI SDR feature is not enabled; tell the user, do not retry); NotFound (no knowledge base with this id; re-fetch via reply_list_knowledge_bases); Conflict (this URL is already a source; no action needed); InvalidParameter (the URL was rejected; tell the user); UpstreamFailure (the AI SDR backend is temporarily unavailable; retry once, then tell the user); ServiceUnavailable (transient; retry once, then tell the user).
- `knowledgeBaseId` (integer, required) — The exact numeric knowledge base ID to add the source to. Must come from a prior reply_list_knowledge_bases result. Never invent, estimate, default, or ask the user. REQUIRED.
- `url` (string, required) — The web-page URL to add as a source. REQUIRED.

**`reply_delete_knowledge_base_source`** — ✏️ mutation
`(knowledgeBaseId*: integer, sourceId*: string)`
Removes a URL source from an AI SDR (Jason) knowledge base. Mutation. REQUIRES the exact numeric knowledge base ID and the source id, both from a prior reply_get_knowledge_base result. Never invent, estimate, default, or ask the user for these values. Failure modes: InvalidArguments (KnowledgeBaseId must be > 0; SourceId must be a valid source id from reply_get_knowledge_base); Forbidden (the AI SDR feature is not enabled; tell the user, do not retry); NotFound (the knowledge base or source does not exist; re-fetch via reply_get_knowledge_base); UpstreamFailure (the AI SDR backend is temporarily unavailable; retry once, then tell the user); ServiceUnavailable (transient; retry once, then tell the user).
- `knowledgeBaseId` (integer, required) — The exact numeric knowledge base ID the source belongs to. Must come from a prior reply_get_knowledge_base result. Never invent, estimate, default, or ask the user. REQUIRED.
- `sourceId` (string, required) — The source id to remove. Must come from a prior reply_get_knowledge_base result. Never invent, estimate, default, or ask the user. REQUIRED.


### Jason AI SDR — reply handlers

**`reply_list_reply_handlers`** — 📖 read-only
`(knowledgeBaseId*: integer, top: integer, skip: integer, search: string)`
Lists the reply handlers in an AI SDR (Jason) knowledge base. A reply handler tells Jason how to answer a specific kind of prospect question (for example pricing or security): it pairs a question type with instructions. Returns each handler's id, question type, instructions, and whether Jason sends its answer automatically. Use reply_get_reply_handler for the full detail of one handler. REQUIRES the exact numeric knowledge base ID from a prior reply_list_knowledge_bases result. Never invent, estimate, default, or ask the user for this value. Optional case-insensitive search. Failure modes: InvalidArguments (KnowledgeBaseId must be > 0); Forbidden (the AI SDR feature is not enabled; tell the user, do not retry); NotFound (no knowledge base with this id; re-fetch via reply_list_knowledge_bases); UpstreamFailure (the AI SDR backend is temporarily unavailable; retry once, then tell the user); ServiceUnavailable (transient; retry once, then tell the user).
- `knowledgeBaseId` (integer, required) — The exact numeric knowledge base ID whose reply handlers to list. Must come from a prior reply_list_knowledge_bases result. Never invent, estimate, default, or ask the user. REQUIRED.
- `top` (integer, optional) — Optional page size. Default 20, max 100.
- `skip` (integer, optional) — Optional pagination offset. Default 0. Use HasMore on the response to decide whether to call again with Skip = previous Skip + Top.
- `search` (string, optional) — Optional case-insensitive substring to match against the reply handler question type or instructions. Omit to list all.

**`reply_get_reply_handler`** — 📖 read-only
`(knowledgeBaseId*: integer, replyHandlerId*: string)`
Returns one reply handler from an AI SDR (Jason) knowledge base in full: its question type, instructions, sample answer, tone of voice, response length, link URLs, attached media file names, and auto-send flag. Use this to review how Jason is told to answer a question type before changing it. REQUIRES the exact numeric knowledge base ID (from reply_list_knowledge_bases) and the exact reply handler id (from reply_list_reply_handlers). Never invent, estimate, default, or ask the user for these values. Failure modes: InvalidArguments (KnowledgeBaseId must be > 0; ReplyHandlerId must be a valid id from reply_list_reply_handlers); Forbidden (the AI SDR feature is not enabled; tell the user, do not retry); NotFound (the knowledge base or reply handler does not exist; re-fetch via reply_list_reply_handlers); UpstreamFailure (the AI SDR backend is temporarily unavailable; retry once, then tell the user); ServiceUnavailable (transient; retry once, then tell the user).
- `knowledgeBaseId` (integer, required) — The exact numeric knowledge base ID the reply handler belongs to. Must come from a prior reply_list_knowledge_bases result. Never invent, estimate, default, or ask the user. REQUIRED.
- `replyHandlerId` (string, required) — The reply handler id to fetch. Must come from a prior reply_list_reply_handlers result. Never invent, estimate, default, or ask the user. REQUIRED.

**`reply_create_reply_handler`** — ✏️ mutation
`(knowledgeBaseId*: integer, typeOfQuestion*: string, instructions*: string, sampleAnswer: string, toneOfVoice: string, responseLength: string, links: array, isAutoSend: boolean)`
Adds a reply handler to an AI SDR (Jason) knowledge base so Jason knows how to answer a specific kind of prospect question. Mutation. TypeOfQuestion is the kind of question it covers (for example 'Pricing' or 'Security'); Instructions tells Jason how to respond. SampleAnswer, ToneOfVoice, ResponseLength, and link URLs are optional. ToneOfVoice (case-insensitive): 'Confident', 'Persuasive', 'Witty', 'Straightforward', 'Empathetic'. ResponseLength (case-insensitive): 'SuperShort', 'Short', 'Medium', 'Long'. IsAutoSend lets Jason send this answer without review. REQUIRES the exact numeric knowledge base ID from a prior reply_list_knowledge_bases result. Never invent, estimate, default, or ask the user for this value. Failure modes: InvalidArguments (KnowledgeBaseId must be > 0; TypeOfQuestion and Instructions must be non-empty; ToneOfVoice and ResponseLength must be allowed values); Forbidden (the AI SDR feature is not enabled; tell the user, do not retry); NotFound (no knowledge base with this id; re-fetch via reply_list_knowledge_bases); InvalidParameter (the content was rejected; the message explains why); UpstreamFailure (the AI SDR backend is temporarily unavailable; retry once, then tell the user); ServiceUnavailable (transient; retry once, then tell the user).
- `knowledgeBaseId` (integer, required) — The exact numeric knowledge base ID to add the reply handler to. Must come from a prior reply_list_knowledge_bases result. Never invent, estimate, default, or ask the user. REQUIRED.
- `typeOfQuestion` (string, required) — The kind of prospect question this handler covers (for example 'Pricing' or 'Security'). REQUIRED.
- `instructions` (string, required) — How Jason should answer this kind of question. REQUIRED.
- `sampleAnswer` (string, optional) — Optional example answer for this question type.
- `toneOfVoice` (string, optional) — Optional tone of voice (case-insensitive): 'Confident', 'Persuasive', 'Witty', 'Straightforward', 'Empathetic'.
- `responseLength` (string, optional) — Optional response length (case-insensitive): 'SuperShort', 'Short', 'Medium', 'Long'.
- `links` (array of string, optional) — Optional list of supporting link URLs.
- `isAutoSend` (boolean, optional) — Optional. When true, Jason sends this answer automatically without review. Defaults to false.

**`reply_update_reply_handler`** — ✏️ mutation
`(knowledgeBaseId*: integer, replyHandlerId*: string, typeOfQuestion: string, instructions: string, sampleAnswer: string, toneOfVoice: string, responseLength: string, links: array, isAutoSend: boolean)`
Updates a reply handler in an AI SDR (Jason) knowledge base. Mutation, patch semantics: only the fields you pass are changed; omitted fields are left as-is. ToneOfVoice (case-insensitive): 'Confident', 'Persuasive', 'Witty', 'Straightforward', 'Empathetic'. ResponseLength (case-insensitive): 'SuperShort', 'Short', 'Medium', 'Long'. Passing Links replaces the whole link list. REQUIRES the exact numeric knowledge base ID (from reply_list_knowledge_bases) and the exact reply handler id (from reply_list_reply_handlers). Never invent, estimate, default, or ask the user for these values. Failure modes: InvalidArguments (KnowledgeBaseId must be > 0; ReplyHandlerId must be a valid id; provide at least one field to change; ToneOfVoice and ResponseLength must be allowed values); Forbidden (the AI SDR feature is not enabled; tell the user, do not retry); NotFound (the knowledge base or reply handler does not exist; re-fetch via reply_list_reply_handlers); InvalidParameter (the content was rejected; the message explains why); UpstreamFailure (the AI SDR backend is temporarily unavailable; retry once, then tell the user); ServiceUnavailable (transient; retry once, then tell the user).
- `knowledgeBaseId` (integer, required) — The exact numeric knowledge base ID the reply handler belongs to. Must come from a prior reply_list_knowledge_bases result. Never invent, estimate, default, or ask the user. REQUIRED.
- `replyHandlerId` (string, required) — The reply handler id to update. Must come from a prior reply_list_reply_handlers result. Never invent, estimate, default, or ask the user. REQUIRED.
- `typeOfQuestion` (string, optional) — New question type. Omit to keep the current value.
- `instructions` (string, optional) — New instructions. Omit to keep the current value.
- `sampleAnswer` (string, optional) — New sample answer. Omit to keep the current value.
- `toneOfVoice` (string, optional) — New tone of voice (case-insensitive): 'Confident', 'Persuasive', 'Witty', 'Straightforward', 'Empathetic'. Omit to keep the current value.
- `responseLength` (string, optional) — New response length (case-insensitive): 'SuperShort', 'Short', 'Medium', 'Long'. Omit to keep the current value.
- `links` (array of string, optional) — New full list of supporting link URLs (replaces the existing list). Omit to keep the current value.
- `isAutoSend` (boolean, optional) — New auto-send flag. Omit to keep the current value.

**`reply_delete_reply_handler`** — ✏️ mutation
`(knowledgeBaseId*: integer, replyHandlerId*: string)`
Removes a reply handler from an AI SDR (Jason) knowledge base. Mutation. REQUIRES the exact numeric knowledge base ID (from reply_list_knowledge_bases) and the exact reply handler id (from reply_list_reply_handlers). Never invent, estimate, default, or ask the user for these values. Failure modes: InvalidArguments (KnowledgeBaseId must be > 0; ReplyHandlerId must be a valid id from reply_list_reply_handlers); Forbidden (the AI SDR feature is not enabled; tell the user, do not retry); NotFound (the knowledge base or reply handler does not exist; re-fetch via reply_list_reply_handlers); UpstreamFailure (the AI SDR backend is temporarily unavailable; retry once, then tell the user); ServiceUnavailable (transient; retry once, then tell the user).
- `knowledgeBaseId` (integer, required) — The exact numeric knowledge base ID the reply handler belongs to. Must come from a prior reply_list_knowledge_bases result. Never invent, estimate, default, or ask the user. REQUIRED.
- `replyHandlerId` (string, required) — The reply handler id to remove. Must come from a prior reply_list_reply_handlers result. Never invent, estimate, default, or ask the user. REQUIRED.


### Jason AI SDR — reengagement cards

**`reply_list_reengagement_cards`** — 📖 read-only
`(knowledgeBaseId*: integer, top: integer, skip: integer, search: string)`
Lists the reengagement cards in an AI SDR (Jason) knowledge base. A reengagement card tells Jason how to win back a prospect who went quiet, and after how many days to reach out again. Returns each card's id, name, instructions, send-after days, enabled flag, and auto-send flag. Use reply_get_reengagement_card for the full detail of one card. REQUIRES the exact numeric knowledge base ID from a prior reply_list_knowledge_bases result. Never invent, estimate, default, or ask the user for this value. Optional case-insensitive search. Failure modes: InvalidArguments (KnowledgeBaseId must be > 0); Forbidden (the AI SDR feature is not enabled; tell the user, do not retry); NotFound (no knowledge base with this id; re-fetch via reply_list_knowledge_bases); UpstreamFailure (the AI SDR backend is temporarily unavailable; retry once, then tell the user); ServiceUnavailable (transient; retry once, then tell the user).
- `knowledgeBaseId` (integer, required) — The exact numeric knowledge base ID whose reengagement cards to list. Must come from a prior reply_list_knowledge_bases result. Never invent, estimate, default, or ask the user. REQUIRED.
- `top` (integer, optional) — Optional page size. Default 20, max 100.
- `skip` (integer, optional) — Optional pagination offset. Default 0. Use HasMore on the response to decide whether to call again with Skip = previous Skip + Top.
- `search` (string, optional) — Optional case-insensitive substring to match against the reengagement card name or instructions. Omit to list all.

**`reply_get_reengagement_card`** — 📖 read-only
`(knowledgeBaseId*: integer, reengagementCardId*: string)`
Returns one reengagement card from an AI SDR (Jason) knowledge base in full: its name, instructions, sample answer, send-after days, tone of voice, response length, link URLs, attached media file names, enabled flag, and auto-send flag. Use this to review how Jason is told to win back a quiet prospect before changing it. REQUIRES the exact numeric knowledge base ID (from reply_list_knowledge_bases) and the exact reengagement card id (from reply_list_reengagement_cards). Never invent, estimate, default, or ask the user for these values. Failure modes: InvalidArguments (KnowledgeBaseId must be > 0; ReengagementCardId must be a valid id from reply_list_reengagement_cards); Forbidden (the AI SDR feature is not enabled; tell the user, do not retry); NotFound (the knowledge base or reengagement card does not exist; re-fetch via reply_list_reengagement_cards); UpstreamFailure (the AI SDR backend is temporarily unavailable; retry once, then tell the user); ServiceUnavailable (transient; retry once, then tell the user).
- `knowledgeBaseId` (integer, required) — The exact numeric knowledge base ID the reengagement card belongs to. Must come from a prior reply_list_knowledge_bases result. Never invent, estimate, default, or ask the user. REQUIRED.
- `reengagementCardId` (string, required) — The reengagement card id to fetch. Must come from a prior reply_list_reengagement_cards result. Never invent, estimate, default, or ask the user. REQUIRED.

**`reply_create_reengagement_card`** — ✏️ mutation
`(knowledgeBaseId*: integer, name*: string, instructions*: string, sendAfter*: integer, sampleAnswer: string, toneOfVoice: string, responseLength: string, links: array, isEnabled: boolean, isAutoSend: boolean)`
Adds a reengagement card to an AI SDR (Jason) knowledge base so Jason knows how to win back a prospect who went quiet. Mutation. Name is a short label; Instructions tells Jason how to re-engage; SendAfter is the number of days after the last contact before Jason reaches out. SampleAnswer, ToneOfVoice, ResponseLength, and link URLs are optional. ToneOfVoice (case-insensitive): 'Confident', 'Persuasive', 'Witty', 'Straightforward', 'Empathetic'. ResponseLength (case-insensitive): 'SuperShort', 'Short', 'Medium', 'Long'. IsEnabled turns the card on (default on); IsAutoSend lets Jason send without review. REQUIRES the exact numeric knowledge base ID from a prior reply_list_knowledge_bases result. Never invent, estimate, default, or ask the user for this value. Failure modes: InvalidArguments (KnowledgeBaseId must be > 0; Name and Instructions must be non-empty; SendAfter must be >= 0; ToneOfVoice and ResponseLength must be allowed values); Forbidden (the AI SDR feature is not enabled; tell the user, do not retry); NotFound (no knowledge base with this id; re-fetch via reply_list_knowledge_bases); Conflict (the SendAfter window overlaps an existing reengagement card in this knowledge base; pick a different SendAfter value); InvalidParameter (the content was rejected; the message explains why); UpstreamFailure (the AI SDR backend is temporarily unavailable; retry once, then tell the user); ServiceUnavailable (transient; retry once, then tell the user).
- `knowledgeBaseId` (integer, required) — The exact numeric knowledge base ID to add the reengagement card to. Must come from a prior reply_list_knowledge_bases result. Never invent, estimate, default, or ask the user. REQUIRED.
- `name` (string, required) — Reengagement card name (a short label). REQUIRED.
- `instructions` (string, required) — How Jason should win back the prospect. REQUIRED.
- `sendAfter` (integer, required) — Number of days after the last contact before Jason reaches out with this card. Must be >= 0. REQUIRED.
- `sampleAnswer` (string, optional) — Optional example re-engagement message.
- `toneOfVoice` (string, optional) — Optional tone of voice (case-insensitive): 'Confident', 'Persuasive', 'Witty', 'Straightforward', 'Empathetic'.
- `responseLength` (string, optional) — Optional response length (case-insensitive): 'SuperShort', 'Short', 'Medium', 'Long'.
- `links` (array of string, optional) — Optional list of supporting link URLs.
- `isEnabled` (boolean, optional) — Optional. When false, the card is created paused. Defaults to enabled.
- `isAutoSend` (boolean, optional) — Optional. When true, Jason sends this message automatically without review. Defaults to false.

**`reply_update_reengagement_card`** — ✏️ mutation
`(knowledgeBaseId*: integer, reengagementCardId*: string, name: string, instructions: string, sampleAnswer: string, sendAfter: integer, toneOfVoice: string, responseLength: string, links: array, isEnabled: boolean, isAutoSend: boolean)`
Updates a reengagement card in an AI SDR (Jason) knowledge base. Mutation, patch semantics: only the fields you pass are changed; omitted fields are left as-is. ToneOfVoice (case-insensitive): 'Confident', 'Persuasive', 'Witty', 'Straightforward', 'Empathetic'. ResponseLength (case-insensitive): 'SuperShort', 'Short', 'Medium', 'Long'. Passing Links replaces the whole link list. Set IsEnabled to false to pause the card. REQUIRES the exact numeric knowledge base ID (from reply_list_knowledge_bases) and the exact reengagement card id (from reply_list_reengagement_cards). Never invent, estimate, default, or ask the user for these values. Failure modes: InvalidArguments (KnowledgeBaseId must be > 0; ReengagementCardId must be a valid id; provide at least one field to change; SendAfter must be >= 0; ToneOfVoice and ResponseLength must be allowed values); Forbidden (the AI SDR feature is not enabled; tell the user, do not retry); NotFound (the knowledge base or reengagement card does not exist; re-fetch via reply_list_reengagement_cards); Conflict (the new SendAfter window overlaps another reengagement card in this knowledge base; pick a different SendAfter value); InvalidParameter (the content was rejected; the message explains why); UpstreamFailure (the AI SDR backend is temporarily unavailable; retry once, then tell the user); ServiceUnavailable (transient; retry once, then tell the user).
- `knowledgeBaseId` (integer, required) — The exact numeric knowledge base ID the reengagement card belongs to. Must come from a prior reply_list_knowledge_bases result. Never invent, estimate, default, or ask the user. REQUIRED.
- `reengagementCardId` (string, required) — The reengagement card id to update. Must come from a prior reply_list_reengagement_cards result. Never invent, estimate, default, or ask the user. REQUIRED.
- `name` (string, optional) — New name. Omit to keep the current value.
- `instructions` (string, optional) — New instructions. Omit to keep the current value.
- `sampleAnswer` (string, optional) — New sample answer. Omit to keep the current value.
- `sendAfter` (integer, optional) — New send-after days (>= 0). Omit to keep the current value.
- `toneOfVoice` (string, optional) — New tone of voice (case-insensitive): 'Confident', 'Persuasive', 'Witty', 'Straightforward', 'Empathetic'. Omit to keep the current value.
- `responseLength` (string, optional) — New response length (case-insensitive): 'SuperShort', 'Short', 'Medium', 'Long'. Omit to keep the current value.
- `links` (array of string, optional) — New full list of supporting link URLs (replaces the existing list). Omit to keep the current value.
- `isEnabled` (boolean, optional) — New enabled flag (false pauses the card). Omit to keep the current value.
- `isAutoSend` (boolean, optional) — New auto-send flag. Omit to keep the current value.

**`reply_delete_reengagement_card`** — ✏️ mutation
`(knowledgeBaseId*: integer, reengagementCardId*: string)`
Removes a reengagement card from an AI SDR (Jason) knowledge base. Mutation. REQUIRES the exact numeric knowledge base ID (from reply_list_knowledge_bases) and the exact reengagement card id (from reply_list_reengagement_cards). Never invent, estimate, default, or ask the user for these values. Failure modes: InvalidArguments (KnowledgeBaseId must be > 0; ReengagementCardId must be a valid id from reply_list_reengagement_cards); Forbidden (the AI SDR feature is not enabled; tell the user, do not retry); NotFound (the knowledge base or reengagement card does not exist; re-fetch via reply_list_reengagement_cards); UpstreamFailure (the AI SDR backend is temporarily unavailable; retry once, then tell the user); ServiceUnavailable (transient; retry once, then tell the user).
- `knowledgeBaseId` (integer, required) — The exact numeric knowledge base ID the reengagement card belongs to. Must come from a prior reply_list_knowledge_bases result. Never invent, estimate, default, or ask the user. REQUIRED.
- `reengagementCardId` (string, required) — The reengagement card id to remove. Must come from a prior reply_list_reengagement_cards result. Never invent, estimate, default, or ask the user. REQUIRED.


### Jason AI SDR — offers

**`reply_list_offers`** — 📖 read-only
`(top: integer, skip: integer, search: string)`
Lists AI SDR (Jason) offers: what Jason can pitch to prospects. Returns each offer's id and name only (use reply_get_offer for the full content). Use this to find an offer and its id before getting, updating, or attaching it. Optional case-insensitive name search. Failure modes: Forbidden (the AI SDR feature is not enabled; tell the user, do not retry); UpstreamFailure (the AI SDR backend is temporarily unavailable; retry once, then tell the user); ServiceUnavailable (transient; retry once, then tell the user).
- `top` (integer, optional) — Optional page size. Default 20, max 100.
- `skip` (integer, optional) — Optional pagination offset. Default 0. Use HasMore on the response to decide whether to call again with Skip = previous Skip + Top.
- `search` (string, optional) — Optional case-insensitive substring to match against the offer name. Omit to list all.

**`reply_get_offer`** — 📖 read-only
`(offerId*: integer)`
Returns one AI SDR (Jason) offer in full: company name and description, ideal customer profile (ICP), reason for outreach, and the lists of case studies, pain points, proof points, value propositions, and calls to action. Use this to review what Jason says about the product before it goes into outreach. REQUIRES the exact numeric offer ID from a prior reply_list_offers result. Never invent, estimate, default, or ask the user for this value. Failure modes: InvalidArguments (OfferId must be > 0); Forbidden (the AI SDR feature is not enabled; tell the user, do not retry); NotFound (no offer with this id; re-fetch via reply_list_offers); UpstreamFailure (the AI SDR backend is temporarily unavailable; retry once, then tell the user); ServiceUnavailable (transient; retry once, then tell the user).
- `offerId` (integer, required) — The exact numeric offer ID to fetch. Must come from a prior reply_list_offers result. Never invent, estimate, default, or ask the user. REQUIRED.

**`reply_create_offer`** — ✏️ mutation
`(name*: string, companyName: string, companyDescription: string, icp: string, reasonForOutreach: string, caseStudies: array, painPoints: array, proofPoints: array, valuePropositions: array, callToActions: array)`
Creates a new AI SDR (Jason) offer that Jason can pitch. Mutation. Name is required; the other fields are optional and describe what Jason sells: company context, ideal customer profile (Icp), reason for outreach, and lists of case studies, pain points, proof points, value propositions, and calls to action. To draft these fields automatically from a company website, use reply_generate_offer_from_website first, then pass the results here. Failure modes: InvalidArguments (Name must be non-empty); Forbidden (the AI SDR feature is not enabled; tell the user, do not retry); InvalidParameter (the offer content was rejected; the message explains why); UpstreamFailure (the AI SDR backend is temporarily unavailable; retry once, then tell the user); ServiceUnavailable (transient; retry once, then tell the user).
- `name` (string, required) — Offer name (a short label). REQUIRED.
- `companyName` (string, optional) — Company name pitched in the offer. Omit to leave empty.
- `companyDescription` (string, optional) — Company description. Omit to leave empty.
- `icp` (string, optional) — Ideal customer profile (ICP) the offer targets. Omit to leave empty.
- `reasonForOutreach` (string, optional) — Reason for reaching out. Omit to leave empty.
- `caseStudies` (array of string, optional) — Case studies used as evidence. Omit to leave empty.
- `painPoints` (array of string, optional) — Prospect pain points the offer addresses. Omit to leave empty.
- `proofPoints` (array of string, optional) — Proof points that back up the pitch. Omit to leave empty.
- `valuePropositions` (array of string, optional) — Value propositions. Omit to leave empty.
- `callToActions` (array of string, optional) — Calls to action. Omit to leave empty.

**`reply_update_offer`** — ✏️ mutation
`(offerId*: integer, name: string, companyName: string, companyDescription: string, icp: string, reasonForOutreach: string, caseStudies: array, painPoints: array, proofPoints: array, valuePropositions: array, callToActions: array)`
Updates an existing AI SDR (Jason) offer. Mutation, patch semantics: only the fields you pass are changed; omitted fields are left as-is. A provided list field replaces the whole list. Use this to sharpen the pitch, add proof points, or change the value proposition. REQUIRES the exact numeric offer ID from a prior reply_list_offers result. Never invent, estimate, default, or ask the user for this value. Changes take effect for any sequence already using this offer. Failure modes: InvalidArguments (OfferId must be > 0; provide at least one field to change); Forbidden (the AI SDR feature is not enabled; tell the user, do not retry); NotFound (no offer with this id; re-fetch via reply_list_offers); InvalidParameter (the offer content was rejected; the message explains why); UpstreamFailure (the AI SDR backend is temporarily unavailable; retry once, then tell the user); ServiceUnavailable (transient; retry once, then tell the user).
- `offerId` (integer, required) — The exact numeric offer ID to update. Must come from a prior reply_list_offers result. Never invent, estimate, default, or ask the user. REQUIRED.
- `name` (string, optional) — New name. Omit to keep the current value.
- `companyName` (string, optional) — New company name. Omit to keep the current value.
- `companyDescription` (string, optional) — New company description. Omit to keep the current value.
- `icp` (string, optional) — New ideal customer profile (ICP). Omit to keep the current value.
- `reasonForOutreach` (string, optional) — New reason for outreach. Omit to keep the current value.
- `caseStudies` (array of string, optional) — Replacement case studies list. Omit to keep the current list.
- `painPoints` (array of string, optional) — Replacement pain points list. Omit to keep the current list.
- `proofPoints` (array of string, optional) — Replacement proof points list. Omit to keep the current list.
- `valuePropositions` (array of string, optional) — Replacement value propositions list. Omit to keep the current list.
- `callToActions` (array of string, optional) — Replacement calls to action list. Omit to keep the current list.

**`reply_generate_offer_from_website`** — 📖 read-only
`(url*: string, additionalContext: string, provider: string)`
Asks Jason to draft offer content from a company website URL (and optional extra notes). Returns suggested fields (company name and description, ICP, reason for outreach, value propositions, proof points, etc.) for the user to review. Does NOT save anything: to persist the result, review it with the user and then call reply_create_offer with the chosen fields. If ReusedOfferId is set, an existing offer already matches this content and can be used as-is instead of creating a new one. Failure modes: InvalidArguments (Url must be non-empty; Provider, if set, must be 'Claude', 'OpenAi', 'Gemini', or 'Mistral'); Forbidden (the AI SDR feature is not enabled; tell the user, do not retry); ServiceUnavailable (generation failed or the backend is unavailable; retry once, then tell the user).
- `url` (string, required) — The company website URL to draft the offer from. REQUIRED.
- `additionalContext` (string, optional) — Optional extra context or instructions to guide the draft (for example which product line to focus on).
- `provider` (string, optional) — Optional LLM provider for the draft (case-insensitive). Allowed values: 'Claude' (default), 'OpenAi', 'Gemini', 'Mistral'.


### Jason AI SDR — playbooks

**`reply_list_playbooks`** — 📖 read-only
`(top: integer, skip: integer, type: string, search: string)`
Lists AI SDR (Jason) playbooks: the named sets of selling instructions Jason can follow. Returns id, name, short description, visibility type (Global, Organization, Team), and last-updated time, but NOT the full instruction body (use reply_get_playbook for that). Use this to find a playbook and its id before getting, updating, or attaching it. Optional filters: visibility type and a name/description substring search. Does NOT list which sequences a playbook is attached to. Failure modes: InvalidArguments (Type must be 'Global', 'Organization', or 'Team'); Forbidden (the AI SDR feature is not enabled; tell the user, do not retry); UpstreamFailure (the AI SDR backend is temporarily unavailable; retry once, then tell the user); ServiceUnavailable (transient; retry once, then tell the user).
- `top` (integer, optional) — Optional page size. Default 20, max 100.
- `skip` (integer, optional) — Optional pagination offset. Default 0. Use HasMore on the response to decide whether to call again with Skip = previous Skip + Top.
- `type` (string, optional) — Optional visibility filter (case-insensitive). Allowed values: 'Global', 'Organization', 'Team'. Omit to include all.
- `search` (string, optional) — Optional case-insensitive substring to match against playbook name and description. Omit to list all.

**`reply_get_playbook`** — 📖 read-only
`(playbookId*: string)`
Returns one AI SDR (Jason) playbook in full, including its instruction Body (the prompt that tells Jason how to sell), visibility type, and the names of any attached style files. Use this to review how Jason is currently instructed to sell before changing a playbook. REQUIRES the exact playbook ID from a prior reply_list_playbooks result. Never invent, estimate, default, or ask the user for this value. Failure modes: InvalidArguments (PlaybookId must be non-empty); Forbidden (the AI SDR feature is not enabled; tell the user, do not retry); NotFound (no playbook with this id; re-fetch via reply_list_playbooks); InvalidIdFormat (the id is malformed; re-fetch via reply_list_playbooks); UpstreamFailure (the AI SDR backend is temporarily unavailable; retry once, then tell the user); ServiceUnavailable (transient; retry once, then tell the user).
- `playbookId` (string, required) — The exact playbook ID to fetch. Must come from a prior reply_list_playbooks result. Never invent, estimate, default, or ask the user. REQUIRED.

**`reply_create_playbook`** — ✏️ mutation
`(name*: string, description*: string, body*: string, visibility: string)`
Creates a new AI SDR (Jason) playbook: a named set of selling instructions. Mutation. Name and Description are short labels; Body is the actual instruction text (the prompt) that tells Jason how to sell. Visibility controls who can use it: 'Team' (default) or 'Organization'. Global playbooks cannot be created here. Failure modes: InvalidArguments (Name, Description, and Body must be non-empty; Visibility must be 'Team' or 'Organization'; the Body must not contain unrecognized personalization variables, the message lists them); Forbidden (the AI SDR feature is not enabled, or you lack permission to create organization playbooks; tell the user, do not retry); UpstreamFailure (the AI SDR backend is temporarily unavailable; retry once, then tell the user); ServiceUnavailable (transient; retry once, then tell the user).
- `name` (string, required) — Playbook name (a short label). REQUIRED.
- `description` (string, required) — Short description of what the playbook is for. REQUIRED.
- `body` (string, required) — The instruction text (the prompt) that tells Jason how to sell. REQUIRED.
- `visibility` (string, optional) — Optional visibility (case-insensitive). Allowed values: 'Team' (default) or 'Organization'. Global playbooks cannot be created here.

**`reply_update_playbook`** — ✏️ mutation
`(playbookId*: string, name: string, description: string, body: string)`
Updates an existing AI SDR (Jason) playbook. Mutation, patch semantics: only the fields you pass are changed; omitted fields are left as-is. REQUIRES the exact playbook ID from a prior reply_list_playbooks result. Never invent, estimate, default, or ask the user for this value. Body is the instruction text (the prompt) Jason follows. Changes take effect for any sequence already using this playbook. Failure modes: InvalidArguments (PlaybookId must be non-empty; at least one of Name, Description, or Body should be provided; the Body must not contain unrecognized personalization variables, the message lists them); Forbidden (the AI SDR feature is not enabled, or you lack permission to edit organization playbooks; tell the user, do not retry); NotFound (no playbook with this id; re-fetch via reply_list_playbooks); InvalidIdFormat (the id is malformed; re-fetch via reply_list_playbooks); GlobalPlaybookReadOnly (Global playbooks cannot be edited; tell the user); UpstreamFailure (the AI SDR backend is temporarily unavailable; retry once, then tell the user); ServiceUnavailable (transient; retry once, then tell the user).
- `playbookId` (string, required) — The exact playbook ID to update. Must come from a prior reply_list_playbooks result. Never invent, estimate, default, or ask the user. REQUIRED.
- `name` (string, optional) — New name. Omit to keep the current value.
- `description` (string, optional) — New description. Omit to keep the current value.
- `body` (string, optional) — New instruction text (the prompt). Omit to keep the current value.

**`reply_duplicate_playbook`** — ✏️ mutation
`(playbookId*: string, newName: string, visibility: string)`
Duplicates an existing AI SDR (Jason) playbook into a new one with the same description and instruction Body. Mutation. Use this when the user wants a copy of a playbook to tweak. The copy is named '<original> (copy)' unless you pass NewName. Visibility of the copy defaults to the original's (Team or Organization); a Global playbook is copied as Team since Global playbooks cannot be created. Pass Visibility to override ('Team' or 'Organization'). Style files are NOT copied. REQUIRES the exact playbook ID from a prior reply_list_playbooks result. Never invent, estimate, default, or ask the user for this value. Failure modes: InvalidArguments (PlaybookId must be non-empty; Visibility must be 'Team' or 'Organization' when provided; the original Body must not contain unrecognized personalization variables, the message lists them); Forbidden (the AI SDR feature is not enabled, or you lack permission to create organization playbooks; tell the user, do not retry); NotFound (no playbook with this id; re-fetch via reply_list_playbooks); InvalidIdFormat (the id is malformed; re-fetch via reply_list_playbooks); UpstreamFailure (the AI SDR backend is temporarily unavailable; retry once, then tell the user); ServiceUnavailable (transient; retry once, then tell the user).
- `playbookId` (string, required) — The exact playbook ID to duplicate. Must come from a prior reply_list_playbooks result. Never invent, estimate, default, or ask the user. REQUIRED.
- `newName` (string, optional) — Optional name for the copy. Omit to use '<original> (copy)'.
- `visibility` (string, optional) — Optional visibility for the copy (case-insensitive): 'Team' or 'Organization'. Omit to keep the original's visibility ('Global' originals are copied as 'Team').


### Tasks

**`reply_list_my_tasks`** — 📖 read-only
`(taskType: string, status: string, overdue: boolean, from: string, to: string, contactId: integer, top: integer, skip: integer)`
Returns the user's tasks (To Do, Call, Meeting, LinkedIn, Manual Email, Sms, WhatsApp), filterable by status, type, due window, and contact. Use this when the caller asks "what's on my task list", "any overdue tasks", "my LinkedIn tasks today", etc. Numeric ContactId, if supplied, MUST come from prior tool output. Do NOT guess, fabricate, or estimate IDs. Do NOT ask the user for a numeric contact ID; users do not know internal IDs. Does NOT execute tasks; this is read-only. Does NOT include task body content; that requires a dedicated get-by-id tool. Failure modes: InvalidArguments (TaskType must be one of the seven allowed values if supplied; Status one of the five; ContactId > 0; From must be <= To when both are set); Forbidden (workspace cannot list tasks; tell the user, do not retry); ServiceUnavailable (transient; retry once, then tell the user).
- `taskType` (string, optional) — Optional task type filter (case-insensitive). Allowed values: 'ToDo', 'Call', 'Meeting', 'LinkedIn', 'ManualEmail', 'Sms', 'WhatsApp'. Pass null/omit for any type.
- `status` (string, optional) — Optional status filter (case-insensitive). Allowed values: 'New', 'Finished', 'Cancelled', 'Archived', 'SequenceDetached'. Pass null/omit for any status.
- `overdue` (boolean, optional) — Optional overdue filter. true = only tasks past their DueTo; false = only tasks not yet due; null/omit = both.
- `from` (string, optional) — Optional start of the date window (UTC, ISO-8601 with offset, e.g. '2025-01-01T00:00:00Z') applied to task DueTo. The offset, if any, is honored: the value is normalized to UTC for the filter. null/omit = open-ended.
- `to` (string, optional) — Optional end of the date window (UTC, ISO-8601 with offset). Same UTC normalization as From. null/omit = open-ended.
- `contactId` (integer, optional) — Optional contact ID to restrict to tasks for one contact. Must come from a prior reply_search_contacts or reply_filter_contacts result. Never invent or ask the user; users do not know internal IDs. Pass null/omit to skip.
- `top` (integer, optional) — Optional page size. Default 20, max 100.
- `skip` (integer, optional) — Optional pagination offset. Default 0. Use HasMore on the response to decide whether to call again with Skip = previous Skip + Top.

**`reply_create_task`** — ✏️ mutation
`(taskType*: string, linkedInTaskType: string, startAt*: string, dueTo*: string, contactId: integer, subject*: string, body*: string)`
Creates a new task (ToDo / Call / Meeting / LinkedIn / ManualEmail / Sms / WhatsApp) for the user. Mutation. REQUIRES TaskType, StartAt, DueTo, Subject, and Body. If TaskType is 'LinkedIn', LinkedInTaskType is required ('Message', 'Connect', 'InMail', 'ViewProfile'). ContactId, if supplied, must come from prior tool output. Never invent, estimate, default, or ask the user. Does NOT schedule the task inside a sequence; this is a standalone (manual) task. Failure modes: InvalidArguments (TaskType and LinkedInTaskType must be from the allowed sets; Subject non-empty and <= 1024 chars; Body non-empty and <= 32000 chars; StartAt must be <= DueTo; ContactId > 0 if set; LinkedInTaskType required when TaskType is LinkedIn. Business rejections also arrive under this code with the reason in the message: 'InvalidInput' means V3 rejected the create payload; 'InvalidDates' means V3 rejected the date window, e.g. dates in the past; 'ContactNotAccessible' means the contact does not exist or this workspace cannot see it, re-fetch via reply_search_contacts; 'RenderError' means the Subject/Body template failed to render, check for stray placeholders; 'Forbidden' means the workspace cannot create tasks, tell the user and do not retry); ServiceUnavailable (transient; retry once, then tell the user).
- `taskType` (string, required) — Task type (case-insensitive). Allowed: 'ToDo', 'Call', 'Meeting', 'LinkedIn', 'ManualEmail', 'Sms', 'WhatsApp'. REQUIRED.
- `linkedInTaskType` (string, optional) — LinkedIn sub-type, required when TaskType is 'LinkedIn'. Allowed: 'Message', 'Connect', 'InMail', 'ViewProfile'.
- `startAt` (string, required) — When the task becomes actionable in the USER'S LOCAL TIME zone (ISO-8601, e.g. '2025-05-01T09:00:00'). The UTC offset suffix is ignored; the date+time portion is treated as the user's local clock time and converted to UTC server-side. REQUIRED.
- `dueTo` (string, required) — When the task is due in the USER'S LOCAL TIME zone. Same format and semantics as StartAt. Must be on or after StartAt. REQUIRED.
- `contactId` (integer, optional) — Optional numeric contact ID to attach the task to. Must come from a prior reply_search_contacts or reply_filter_contacts result. Never invent or ask the user; users do not know internal IDs.
- `subject` (string, required) — Task subject (short title). Max 1024 characters. REQUIRED.
- `body` (string, required) — Task body / instructions. Max 32000 characters. REQUIRED.

**`reply_complete_task`** — ✏️ mutation
`(taskId*: integer, callResolution: string, finishProspectInSequence: boolean)`
Marks an existing task as completed. Mutation. REQUIRES the exact numeric task ID. Must come from a prior reply_list_my_tasks result. Never invent, estimate, default, or ask the user. For Call tasks, CallResolution is recommended ('Positive', 'ToCall', 'Negative'). FinishProspectInSequence, when true, also marks the contact as Finished in the related sequence. Failure modes: InvalidArguments (TaskId > 0; CallResolution one of Positive/ToCall/Negative if supplied. Business rejections also arrive under this code with the reason in the message: 'NotFound' means the task does not exist, re-fetch via reply_list_my_tasks; 'CannotComplete' means the task is in a state from which it cannot be completed, e.g. already Finished or Cancelled, tell the user; 'Forbidden' means the workspace cannot complete this task, tell the user and do not retry); ServiceUnavailable (transient; retry once, then tell the user).
- `taskId` (integer, required) — Numeric ID of the task to complete. Must come from a prior reply_list_my_tasks result. Never invent, estimate, default, or ask the user. REQUIRED.
- `callResolution` (string, optional) — Optional call resolution for Call tasks (case-insensitive): 'Positive', 'ToCall', 'Negative'. Ignored for non-Call tasks.
- `finishProspectInSequence` (boolean, optional) — Optional: when true, also marks the contact as Finished in the related sequence. Defaults to false.


### Workspace resolvers & accounts

**`reply_list_email_accounts`** — 📖 read-only
`(top: integer, skip: integer)`
Returns the email accounts (mailboxes) configured in the workspace, with their connection status, daily send limit, default flag, and tags. Use this when the caller asks "which mailboxes can I send from", "which inbox is disconnected", "daily limits", etc. Does NOT include credentials or SMTP/IMAP settings. Failure modes: Forbidden (workspace cannot list email accounts; tell the user, do not retry); ServiceUnavailable (transient; retry once, then tell the user).
- `top` (integer, optional) — Optional page size. Default 20, max 100.
- `skip` (integer, optional) — Optional pagination offset. Default 0. Use HasMore on the response to decide whether to call again with Skip = previous Skip + Top.

**`reply_list_linkedin_accounts`** — 📖 read-only
`(no parameters)`
Returns the LinkedIn accounts connected to the workspace, with status, cookie health, account tier, and ownership. Use this when the caller asks "which LinkedIn accounts are connected", "is my LinkedIn cookie valid", "do I have a Sales Navigator account", etc. Does NOT include nested limits/usage/voice-profile blocks; those require a separate detail tool. Does NOT support paging at the underlying layer; the response is the full list. A workspace with no LinkedIn accounts returns an empty Items list, not an error. Failure modes: ServiceUnavailable (transient; retry once, then tell the user).

**`reply_list_schedules`** — 📖 read-only
`(no parameters)`
Returns all sending schedules (business-hours / sending-window configurations) in the workspace, with timezone, default flag, and counts of main + follow-up time slots. Use this when the caller asks "which schedules exist", "which is the default schedule", "does the EU schedule exist", etc. Does NOT include the per-day time-window slots themselves; only counts. For schedule assignment to a sequence, a dedicated mutation tool is required. Failure modes: ServiceUnavailable (transient; retry once, then tell the user). This tool takes no parameters and only reads, so InvalidArguments and Forbidden are not expected.

**`reply_search_lists`** — 📖 read-only
`(name: string, top: integer, skip: integer)`
Resolves contact lists (a.k.a. prospect lists) in the current workspace to their numeric ListId by name substring. Call this whenever the caller refers to a contact list by name ("contacts in the SaaS Founders list", "add to the Cold Outreach Q2 list") so the next tool gets a real ListId instead of a guess. Returns ListId, name, and shared flag. Do NOT ask the user for a numeric ListId; users do not know internal IDs. When confirming an action to the user, refer to the list by its Name, not the ListId. Failure modes: Forbidden (workspace cannot list contact lists; tell the user, do not retry); ServiceUnavailable (transient; retry once, then tell the user).
- `name` (string, optional) — Optional case-insensitive substring filter on the list name. Pass null or omit to list every contact list in the workspace.
- `top` (integer, optional) — Optional page size. Default 20, max 100.
- `skip` (integer, optional) — Optional pagination offset. Default 0. Use HasMore on the response to decide whether to call again with Skip = previous Skip + Top.

**`reply_search_team_members`** — 📖 read-only
`(search: string, top: integer, skip: integer)`
Resolves teammates in the current workspace to their numeric UserId by name or email substring. Call this whenever the caller refers to a teammate by name ("assign to John", "reassign these contacts to Sarah") so the next tool gets a real UserId instead of a guess. Returns UserId, full name, email, role, status. Do NOT ask the user for a numeric UserId; users do not know internal IDs. When confirming an action to the user, refer to the teammate by their FullName, not the UserId. Failure modes: ServiceUnavailable (transient; retry once, then tell the user).
- `search` (string, optional) — Optional case-insensitive substring filter on the teammate's full name or email. Pass null or omit to list every teammate in the workspace.
- `top` (integer, optional) — Optional page size. Default 20, max 100.
- `skip` (integer, optional) — Optional pagination offset. Default 0. Use HasMore on the response to decide whether to call again with Skip = previous Skip + Top.


### Help & meta

**`reply_search_knowledge_base`** — 📖 read-only
`(query*: string)`
Searches the Reply.io Help Center for articles that answer product how-to and support questions (for example 'how do I add an account', 'what does autopilot mode do', 'why are my emails not sending'). Returns up to 8 short article summaries ordered by relevance, each with a slug, title, section, snippet, and sourceUrl. Use this for questions about how Reply.io features work or how to accomplish something in the product; do NOT use it for the user's own workspace data (counts, statuses, contents), which comes only from the dedicated tools. After choosing the most relevant result, call reply_get_knowledge_base_article with its slug to read the full article before you answer, then cite its sourceUrl. Failure modes: an empty Articles list means nothing matched (tell the user you could not find a help article and do not invent an answer); InvalidArguments when Query is empty or longer than 500 characters (ask the user what they need help with). The catalog is bundled, so ServiceUnavailable and Forbidden are not expected.
- `query` (string, required) — The user's support or how-to question, in natural language and in the user's own words. REQUIRED.

**`reply_get_knowledge_base_article`** — 📖 read-only
`(slug*: string)`
Returns the full text and source URL of a single Reply.io Help Center article identified by its slug (obtained from reply_search_knowledge_base). Use it to read an article before answering a how-to or support question, and always cite the returned sourceUrl as a clickable markdown link in your answer. Failure modes: ArticleNotFound when the slug does not exist or is misspelled (re-run reply_search_knowledge_base to obtain a valid slug, never invent one); InvalidArguments when Slug is empty or longer than 300 characters.
- `slug` (string, required) — The slug from a reply_search_knowledge_base result, e.g. 'accounts/accounts-overview'. REQUIRED.

**`reply_get_app_map`** — 📖 read-only
`(no parameters)`
Returns the catalog of Reply.io app areas: each entry has a title, a short description, the exact in-app navigation steps, and a relative URL. Use this when the user asks where something is in the app, how to set up or find a feature, or about functionality no other tool covers; call it BEFORE refusing or describing the UI from memory. When the matching entry has a relativeUrl, give the user a direct link by rendering the entry title as a markdown link to it (e.g. '[Email accounts](/settings/email-accounts)'); use the URL exactly as returned, never construct or alter URLs yourself. Entries also state what the chat can already do in that area; when an entry lists a chat capability matching the user's request, use the dedicated tools instead of sending the user to the UI. Does NOT answer workspace-data questions (counts, statuses, contents); those come only from the dedicated tools. Failure modes: ServiceUnavailable (transient; retry once, then tell the user the system is temporarily offline). This tool takes no parameters and reads a static catalog, so InvalidArguments and Forbidden are not expected.

**`reply_report_unsupported_request`** — 📖 read-only
`(requestSummary*: string, requestKey*: string, category*: string, verbatimQuote: string)`
Records, for the product team, that the user asked for a capability Reply.io does not currently have. Call this ONLY after you have already confirmed the capability is genuinely missing: the available tools cannot do it, reply_search_knowledge_base has no matching how-to, and reply_get_app_map has no matching place in the app. After calling it, tell the user plainly that this is not something you can do, exactly as you would without this tool; never promise that the feature exists, is planned, or is coming. Do NOT call it for: a tool that failed transiently (ServiceUnavailable) or with bad arguments, an action blocked by the user's plan (Forbidden), a how-to question answered by the knowledge base or app map, or anything you can actually accomplish with another tool. Call it at most once per distinct missing capability in a turn; do not log the same request twice. Always pass a stable RequestKey naming the capability so repeated asks for the same thing aggregate for the product team. Returns a simple acknowledgement; it has no user-visible effect and triggers no notification to the user. Failure modes: InvalidArguments (RequestKey, RequestSummary or Category missing or invalid; fix the call and retry once).
- `requestSummary` (string, required) — One neutral English sentence describing the capability the user wants that Reply.io does not have. State the desired outcome, not a transcript. Do not include the user's name, email, or other personal data. REQUIRED.
- `requestKey` (string, required) — A short, stable kebab-case identifier for the missing CAPABILITY itself, not for this particular phrasing (e.g. 'salesforce-contact-sync', 'add-to-blacklist-via-chat', 'weekly-stats-email'). Use the SAME key every time a user asks for the same underlying capability so identical requests group together for the product team. Lowercase letters, digits and hyphens only; keep it general and reuse an obvious key rather than inventing a new variant. REQUIRED.
- `category` (string, required) — The closest category for the missing capability: integrations (other apps/CRMs), reporting (analytics/dashboards/exports), sequences, contacts (contacts/lists), email (sending/deliverability/mailboxes), linkedIn (or other channels), ai (AI/assistant features), other. REQUIRED. Allowed: integrations, reporting, sequences, contacts, email, linkedIn, ai, other.
- `verbatimQuote` (string, optional) — Optional short direct quote of the user's own words that triggered this, for the product team's context. Keep it to one sentence; omit if it would expose personal data.



---

Back to the [MCP overview](/mcp) — auth, contract rules, envelopes, recipes, and how to reproduce this reference against the live server.
