Docs Home Log in

MCP tools reference

Every tool the Kata MCP server exposes: 74 tools, with their parameters. This page is built from the server's own tool list, so it always matches what tools/list returns.

Call a tool with tools/call: {"name": "<tool>", "arguments": {...}}. See Connect your agent for the transport and auth. Tools that change bulk data take dry_run: run it first and act on the count.

Overview and reports

status

Overview: sends today, capacity, replies, interested leads, domains, mailboxes, company memory size, campaigns (each with state: ok, error with the reason it cannot send, completed when every lead went through the sequence, off when not active), and wrong_person: recent replies saying they are not the right person (with any address they gave in referral) so you can ask for the right contact.

No parameters.

health

Health score (0-100) of every sending domain and mailbox over the last 30 days: domain 50%, recipient behavior 30%, address 10%, IP/provider 10%. When Instantly warmup data is known (10 or more warmup emails landed in 7 days), inbox placement counts 15% (domain 45%, recipients 25%, address 10%, provider 5%): inbox_rate and placement {inbox, spam} per mailbox. Kata pauses a mailbox by itself when more than 10% of 20 or more warmup emails land in spam over 7 days. Use it to decide which mailboxes to pause or slow down.

No parameters.

campaign_report

Performance of one campaign (or all): state (ok, error with the reason, completed, off), totals (sent, sent today, replies, interested, conversions, bounces = hard bounces, soft_bounces, contacts in sequence), the last bounce reasons, and per-variant stats (step, angle, subject, status, sent, successes, rate, p_best = probability of being the best variant).

ParameterTypeDescription
campaign_idnumberone campaign; omit for all

leads_to_call

Interested contacts not handled yet, with their reply.

No parameters.

query

Run ONE read-only SQL SELECT (or WITH … SELECT) on the Kata SQLite database, max 200 rows. For anything the other tools do not cover. Dates are Unix ms. Tables: contacts(id, email, first_name, company, data JSON text: use json_extract(data,'$.country'), status new|enrolled|replied|bounced|unsubscribed|converted, value, soft_bounces, created_at, handled_at); campaigns(id, name, status draft|active|paused, target_url, brief, created_at); steps(campaign_id, step, delay_days); variants(id, campaign_id, step, angle, subject, body, status active|retired, parent_id, origin human|ai); enrollments(id, campaign_id, contact_id, step = next step, next_at, status pending|scheduled|done|stopped, mailbox); messages(id, token, enrollment_id, campaign_id, contact_id, mailbox, variant_id, step, subject, body, status scheduled|sending|sent|failed, send_at, sent_at, error, clicked, replied, interested, converted, bounced = hard bounce, bounce_type hard|soft, bounce_code, bounce_reason, value); events(id, type sent|click|open|reply|reply_sent|bounce|visit|unsubscribe|conversion|data|pause|evolve|error|domain, message_id, contact_id, detail, at; reply detail starts with the kind interested|not_interested|unsubscribe|ooo|wrong_person|other, bounce detail with hard|soft and the SMTP code); suppression(email, reason, at); mailboxes(email, domain, display_name, daily_cap, status, provider, note); domains(domain, daily_cap, status, provider, verify_status, note); context_files(id, scope, campaign_id, name, kind, content).

ParameterTypeDescription
sql requiredstringone SELECT statement

Company and integrations

get_integrations

Which integrations are configured (AgentMail key, Cloudflare token), with the last 4 characters and what the check found (plan, limits, domains, zones). Never returns the keys.

No parameters.

set_integration

Save an integration key after checking it with the service: agentmail_api_key (AgentMail API key of the account that holds the sending domains) or cf_api_token (Cloudflare API token with Zone:Read and DNS:Edit on the sending domains). The key is stored encrypted. Warn the user that a key pasted in a chat stays in the conversation history; the Integrations page in Kata is the safer place.

ParameterTypeDescription
name required"agentmail_api_key" | "cf_api_token" | "instantly_api_key"-
value requiredstringthe key or token

set_company_brief

Write the company memory (company.md), read by the AI everywhere: what the company does, for whom, proof (numbers, clients), tone, what to avoid. brief replaces the whole company.md. Only the fields you pass change.

ParameterTypeDescription
namestringcompany name
websitestringwebsite
briefstringfull company.md content

get_company_brief

Read the company memory (company.md), name and website.

No parameters.

Campaigns

create_campaign

Create a campaign (status draft) and its brief.md. The brief gives the target, offer, proof and expected action; the AI reads it together with company.md. Then run check_campaign_brief.

ParameterTypeDescription
name requiredstringshort name
brief requiredstringoffer, target, tone, proof, expected action
target_urlstringpage the {{link}} links point to
followup_delays_daysnumber[]follow-up delays in days, e.g. [3, 5]

update_campaign

Rename a campaign, replace its brief.md (brief) or its link (target_url), or set its sending hours: each email goes out in its lead's local time (hours, default 8-17, weekdays only by default); the time zone comes from the lead's country column, else its email domain (.ie, .fr…), else the campaign's country; a lead with none of them can get it at any hour. One source of truth for the link: the "Link:" line of brief.md. target_url is a shortcut that rewrites that line (it wins over a Link: line inside brief when both are given); campaigns.target_url is only a copy of it. The link may hold contact variables, e.g. https://site.com/start?email={{email}}&fn={{first_name}}: {{link}} fills them per lead, URL-encoded (sean+ie@x.com becomes sean%2Bie%40x.com), and adds kata=<token> for the postback. Returns link: the URL, its variables and an example. Only the fields you pass change.

ParameterTypeDescription
campaign_id requirednumberid
namestringname
briefstringfull brief.md content
target_urlstringdestination of {{link}}; may contain {{email}}, {{first_name}}, {{company}} or any data key
countrystringdefault country of its leads (ISO code like IE, or name): sets their time zone when a lead has no country column and its email domain says nothing; empty = none
hoursstringsending hours in each lead's local time, start-end, e.g. 8-17 (default)
weekdaysbooleanMonday to Friday only, in the lead's local time (default true)
autopilotbooleanon (default): the agent retires losing angles, writes new ones and gives the best angles more sends. Off: the angles in test stay and share the sends equally. Ask the user before turning it off.

read_campaign_brief

Read a campaign's brief.md: target, offer, proof, expected action, link, then notes and updates.

ParameterTypeDescription
campaign_id requirednumberid

update_campaign_brief

Replace a campaign's brief.md with the full new content. The campaign link is the line "Link: https://…" and only that line (other URLs in the brief are plain text); it is the destination of {{link}} and may hold contact variables ({{email}}, {{first_name}}, any data key), filled and URL-encoded per lead. Removing the Link: line removes the campaign link. Keep it current without asking: target, offer, proof, action, link, then a "Notes and updates" part. Plain text, no markdown headings: the user reads and edits it (angles tried, decisions, results, next steps). Read it first and keep what is still true.

ParameterTypeDescription
campaign_id requirednumberid
content requiredstringfull markdown content

check_campaign_brief

Check that a campaign's brief.md has what the AI needs to write and send. Returns ready, missing (to ask the user), tips, and checked: every point looked at, with ok and a note. ready covers the five essentials (target, offer, why, action, link = the Link: line). checked also lists informational sending checks that do not change ready: link_variables (the {{vars}} of the link exist on enrolled contacts), angles (each step has a live angle), tracked_links (live angles with hand-written URLs, which are not tracked). The result shows on the campaign page.

ParameterTypeDescription
campaign_id requirednumberid

set_campaign_status

Activate or pause a campaign. A campaign is the top switch: draft or paused = nothing planned for it, whatever the mailboxes. active = its emails are planned on the next scheduler run (every minute), only from its mailboxes that are themselves active. Run scheduler_dry_run first to see what would go out. Activating sends the campaign's first email at once when a planned lead is inside its local sending hours (the answer says to whom, or when it goes out), so the user sees it works; the others are spread over the day. Never activate without the user's approval.

ParameterTypeDescription
campaign_id requirednumberid
status required"active" | "paused" | "draft"-

set_steps

Set a campaign's sequence: follow-up delays in days after the previous email, e.g. [3, 5] = first email, follow-up 1 three days later, follow-up 2 five days after that. [] = no follow-up. Each follow-up step needs its variants (generate_angles with step).

ParameterTypeDescription
campaign_id requirednumberid
followup_delays_days requirednumber[]-

delete_campaign

Delete a campaign that never sent (variants, steps, enrollments, campaign files; contacts stay). A campaign that sent is refused: pause it instead. Ask the user first; dry_run shows what goes.

ParameterTypeDescription
campaign_id requirednumberid
dry_runboolean-

get_campaign_mailboxes

Which mailboxes a campaign sends from. mode all = every active mailbox; mode selected = only the chosen ones. Lists every mailbox with chosen/used, status, daily cap and sent today.

ParameterTypeDescription
campaign_id requirednumbercampaign

set_campaign_mailboxes

Choose the mailboxes a campaign sends from. all=true: every active mailbox (default). emails: exactly these. add / remove: change the current list. Only new first emails follow the choice; follow-ups stay in the mailbox of their thread. A chosen mailbox still has to be active to send.

ParameterTypeDescription
campaign_id requirednumbercampaign
allbooleansend from every active mailbox
emailsstring[]exactly these mailboxes
addstring[]-
removestring[]-

Angles and emails

generate_angles

The AI writes variants (different angles) for one step. Step 0 = first email.

ParameterTypeDescription
campaign_id requirednumberid
stepnumber0 = first email, 1 = follow-up 1...
countnumber1 to 6, default 3
instructionsstringextra instructions

add_variant

Add a variant written by hand. Variables: {{first_name}}, {{company}}, {{email}}, any data key, {{sender_first}}; {{link}} = the campaign link (tracked when the mailbox has a link domain, always with kata=<token>). A variable inside a URL is URL-encoded; {{x|url}} encodes anywhere, {{x|raw}} never. A URL written by hand in the body is sent as is: not tracked, no token.

ParameterTypeDescription
campaign_id requirednumberid
step requirednumberstep
anglestringangle name
subjectstringsubject (empty for a follow-up)
body requiredstringbody, with {{first_name}} {{company}} {{link}}

list_variants

Variants (angles) of a campaign with full subject and body, status and stats (sent, clicks, replies, interested, conversions, rate, p_best), plus the sequence steps.

ParameterTypeDescription
campaign_id requirednumberid

set_variant

Retire a variant or put it back in the test (status), or edit its angle, subject or body. Only the fields you pass change. Editing a variant that already sent mixes its stats: prefer add_variant and retire the old one.

ParameterTypeDescription
id requirednumbervariant id
status"active" | "retired"-
anglestringangle
subjectstringsubject
bodystringbody

evolve

Retire losing variants and, if there is room, have a new one written from the best.

No parameters.

preview_email

Show an email exactly as a lead would get it (variables filled, opt-out line and signature added), without sending. Same inputs as send_test_email, to is optional. Returns link_in_email (what the email shows for {{link}}), link_destination (the final URL: the Link: line of brief.md with the lead's variables URL-encoded, plus kata=<token>; PREVIEW stands for the token), link_tracked (true when the mailbox's domain has a link domain: the click is counted, then redirected), and untracked_links: URLs written by hand in the body. Those go out as written (variables URL-encoded) but their clicks are not counted and they get no kata token: use {{link}} for anything you want tracked.

ParameterTypeDescription
mailboxstringsending address
contactstringemail of a lead in Kata whose fields and data fill the variables
campaign_idnumbercampaign
variant_idnumbervariant
stepnumberstep
subjectstringown subject
bodystringown body
varsobjectvariable values
tostringoptional

send_test_email

Send one test email now to any address (usually the user's own), exactly as a lead would get it, from any Kata mailbox, paused ones included. Outside the scheduler: no campaign, mailbox status, enrollment or lead changes. Content: variant_id, or campaign_id (+ step) to use its best angle, or your own subject and body. Variables come from contact (a lead already in Kata) and vars; {{link}} is the campaign link with them filled in (URL-encoded), without token and not tracked. No approval needed beyond the user asking for a test.

ParameterTypeDescription
to requiredstringtest address
contactstringemail of a lead in Kata whose fields and data fill the variables
mailboxstringsending address in Kata (default: an active one, else any)
campaign_idnumbercampaign
variant_idnumbervariant
stepnumber0 = first email, 1 = follow-up 1…
subjectstringown subject instead of a variant
bodystringown body instead of a variant
varsobjectvalues for the variables, e.g. {"first_name": "Yoann"}

Leads and contacts

import_leads

Import contacts from a CSV (email column required; first_name, company and any other column become variables; a priority column orders the sends: 1 first, then 2, 3…, empty last). Each new address gets a free check (syntax, disposable, domain without mail server): invalid ones get status invalid and never enter a sequence; the result says how many (email_check). The full mailbox check happens on its own before each contact's first email. Pass either the CSV text (csv) or an uploaded file key (file, e.g. uploads/....csv). With campaign_id, contacts enter the sequence. With list_id, they join that lead list (and the campaigns it feeds).

ParameterTypeDescription
csvstringfull CSV content
filestringkey of a CSV already uploaded to Kata
campaign_idnumbercampaign to enroll them in
list_idnumberlead list to add them to (it also enrolls them in the campaigns it feeds)

add_leads

Add leads to a lead list, new or already in Kata: the simplest way for one lead or a few (for a CSV file, use import_leads). Each lead: email (required), first_name, company, priority (1 is sent first, then 2, 3…; none goes last), and any other field, which becomes a variable (country, phone…). New addresses get the free email check; invalid ones are kept out. The leads then enter the campaigns the list feeds, split between them when it feeds several; a person already in a live sequence is not enrolled twice. Max 1000 per call. Tell the user when the list feeds an active campaign: those people will get emails.

ParameterTypeDescription
list_id requirednumberlead list
leads requiredobject[]the leads
Each item: email*, first_name, company, priority, and any other field

list_contacts

List contacts (leads) with their data (CSV columns), status, value and sequences. Filters combine with AND. Returns count (all matches) and one page.

ParameterTypeDescription
emailstringone contact
idnumberone contact id
emailsstring[]these addresses
campaign_idnumbercontacts enrolled in this campaign
list_idnumbercontacts in this lead list
status"new" | "enrolled" | "replied" | "bounced" | "unsubscribed" | "converted"-
searchstringtext in email, first name or company
data_matchobjectdata fields equal to these values, e.g. {"country":"IE"}; null = key missing
sincestringadded on or after this date (ISO, e.g. 2026-10-01)
filestringcontacts listed in this imported CSV (file key returned by import_leads)
limitnumberpage size, default 50, max 200
offsetnumberskip this many

get_contact

One contact by email or id: fields, data, suppression, enrollments, every message (with body) and events (replies, clicks, bounces).

ParameterTypeDescription
emailstringemail
idnumbercontact id

update_contacts

Edit contacts: set first_name/company and merge keys into data (a value sets the key, null removes it). One contact (email/id) or bulk by filters. Bulk needs the user's approval: run with dry_run first and tell the user the count. Returns matched and changed.

ParameterTypeDescription
emailstringone contact
idnumberone contact id
emailsstring[]these addresses
campaign_idnumbercontacts enrolled in this campaign
list_idnumbercontacts in this lead list
status"new" | "enrolled" | "replied" | "bounced" | "unsubscribed" | "converted"-
searchstringtext in email, first name or company
data_matchobjectdata fields equal to these values, e.g. {"country":"IE"}; null = key missing
sincestringadded on or after this date (ISO, e.g. 2026-10-01)
filestringcontacts listed in this imported CSV (file key returned by import_leads)
allbooleanevery contact (no filter)
first_namestringnew first name
companystringnew company
dataobjectkeys to merge into data, e.g. {"country":"IE"}; null removes a key
dry_runbooleancount only, write nothing

delete_contacts

Delete contacts that were never emailed, with their enrollments and queued emails. Contacts already emailed are kept and listed (use suppress for them). Run dry_run first and get the user's approval.

ParameterTypeDescription
emailstringone contact
idnumberone contact id
emailsstring[]these addresses
campaign_idnumbercontacts enrolled in this campaign
list_idnumbercontacts in this lead list
status"new" | "enrolled" | "replied" | "bounced" | "unsubscribed" | "converted"-
searchstringtext in email, first name or company
data_matchobjectdata fields equal to these values, e.g. {"country":"IE"}; null = key missing
sincestringadded on or after this date (ISO, e.g. 2026-10-01)
filestringcontacts listed in this imported CSV (file key returned by import_leads)
dry_runbooleancount only

enroll_contacts

Put existing contacts into a campaign's sequence (they start at step 0). Selected by the same filters as list_contacts. Skips suppressed, bounced, unsubscribed, those already in that campaign, and replied/converted unless include_replied. Run dry_run first and get the user's approval.

ParameterTypeDescription
target_campaign_id requirednumbercampaign to enroll them in
emailstringone contact
idnumberone contact id
emailsstring[]these addresses
campaign_idnumbercontacts enrolled in this campaign
list_idnumbercontacts in this lead list
status"new" | "enrolled" | "replied" | "bounced" | "unsubscribed" | "converted"-
searchstringtext in email, first name or company
data_matchobjectdata fields equal to these values, e.g. {"country":"IE"}; null = key missing
sincestringadded on or after this date (ISO, e.g. 2026-10-01)
filestringcontacts listed in this imported CSV (file key returned by import_leads)
include_repliedboolean-
dry_runboolean-

stop_sequence

Stop the sequence for these contacts (all campaigns, or one campaign) and cancel their queued emails. They are not suppressed.

ParameterTypeDescription
emails requiredstring[]-
campaign_idnumberonly this campaign

suppress

Unsubscribe addresses for good: add them to the suppression list, stop every sequence, cancel queued emails, mark the contacts unsubscribed. undo=true removes them from the suppression list only.

ParameterTypeDescription
emails requiredstring[]-
reasonstringe.g. asked by phone
undoboolean-

mark_handled

The Done button on leads to call: mark an interested contact as handled (called, meeting booked). undo=true puts it back in leads_to_call.

ParameterTypeDescription
emailstringemail
idnumbercontact id
undoboolean-

check_emails

Check email addresses. mode free (default, no cost, up to 2000): syntax, typos (gmial.com, with the fix), disposable domains, generic addresses (info@…), and whether the domain has a mail server. mode deep (includes free, max 200, about 2 to 10 seconds per 10 addresses): then asks whether each mailbox really exists. Kata's SMTP verifier asks the recipient's server (free); when that server will not answer, MillionVerifier through Bourse (about $0.002 per address, paid); catch-all addresses go to a decision model (about $0.00003). Addresses the free pass rejects never reach the paid steps. The result says what it cost (cost.usd). Kata already runs free on every import and deep on its own before each contact's first email: use deep only when the user wants a list checked now, tell them it can cost up to $0.002 per address, and ask before more than 100. Give emails, or campaign_id for its contacts not checked yet. Results go to the email_checks table (status, reason, source, decision send/skip). suppress_invalid=true takes rejected addresses out of their sequences: only with the user's approval.

ParameterTypeDescription
emailsstring[]-
mode"free" | "deep"free = no cost (default); deep = the mailbox exists, may cost
campaign_idnumbercheck the contacts of this campaign
only_uncheckedbooleandefault true
limitnumbermax contacts, default 500 (free) or 200 (deep)
savebooleansave in email_checks, default true
suppress_invalidbooleanstop sequences of rejected addresses

enrich_leads

Enrich leads from their work email through Bourse (Tomba person + company lookup): job_title, seniority, role, company, company_domain, location, country, linkedin, twitter, company_industry, company_size, company_linkedin, company_description. Only empty fields of the lead's data are filled; enriched_at is set, and leads already enriched are skipped (only_missing=false to redo them). Personal inboxes (gmail, outlook…) are skipped. Costs about $0.021 per address found, nothing on a miss. Without confirm it spends nothing: it returns the count and the cost; tell the user, then call again with confirm=true and the same filters. Give emails, list_id or campaign_id. max: default 50, up to 200 per call.

ParameterTypeDescription
emailsstring[]-
list_idnumberthe people of this lead list
campaign_idnumberthe leads of this campaign
maxnumberat most this many leads, default 50, max 200
confirmbooleantrue = spend; without it only the estimate
only_missingbooleandefault true: skip leads already enriched

Lead lists

list_lists

Lead lists: id, name, description, members, unreachable (bounced or unsubscribed) and the campaigns each one feeds. A list is a source: connected to a campaign, its people enter that campaign's sequence, and people added later join too.

No parameters.

create_list

Create a lead list. Optionally fill it right away with the same filters as list_contacts (e.g. file from import_leads, data_match, search). Contacts are not duplicated: a list only groups them. from_unlisted: true makes the list from the leads that entered campaigns without a list (the 'Leads without a list' block of the Canvas) and connects it to those campaigns, with no new enrollment.

ParameterTypeDescription
name requiredstringe.g. Brokers Ireland
descriptionstringwho is in it, where it comes from
from_unlistedboolean-
emailstringone contact
idnumberone contact id
emailsstring[]these addresses
campaign_idnumbercontacts enrolled in this campaign
list_idnumbercontacts in this lead list
status"new" | "enrolled" | "replied" | "bounced" | "unsubscribed" | "converted"-
searchstringtext in email, first name or company
data_matchobjectdata fields equal to these values, e.g. {"country":"IE"}; null = key missing
sincestringadded on or after this date (ISO, e.g. 2026-10-01)
filestringcontacts listed in this imported CSV (file key returned by import_leads)

update_list

Rename a lead list or change its description.

ParameterTypeDescription
list_id requirednumberid
namestringnew name
descriptionstringnew description

add_to_list

Add existing contacts to a lead list, selected by the list_contacts filters. They also enter every campaign the list feeds (an active campaign starts emailing them): run dry_run first and get the user's approval. To add new people, import_leads with list_id.

ParameterTypeDescription
emailstringone contact
idnumberone contact id
emailsstring[]these addresses
campaign_idnumbercontacts enrolled in this campaign
list_id requirednumberlist to add to
status"new" | "enrolled" | "replied" | "bounced" | "unsubscribed" | "converted"-
searchstringtext in email, first name or company
data_matchobjectdata fields equal to these values, e.g. {"country":"IE"}; null = key missing
sincestringadded on or after this date (ISO, e.g. 2026-10-01)
filestringcontacts listed in this imported CSV (file key returned by import_leads)
dry_runboolean-

remove_from_list

Remove contacts from a lead list (filters as list_contacts; list_id alone is refused, add all: true to empty it). Their sequences in the campaigns this list feeds stop, unless keep_sequences or another connected list still holds them. Contacts stay in Kata. Run dry_run first and get the user's approval.

ParameterTypeDescription
emailstringone contact
idnumberone contact id
emailsstring[]these addresses
campaign_idnumbercontacts enrolled in this campaign
list_id requirednumberlist to remove from
status"new" | "enrolled" | "replied" | "bounced" | "unsubscribed" | "converted"-
searchstringtext in email, first name or company
data_matchobjectdata fields equal to these values, e.g. {"country":"IE"}; null = key missing
sincestringadded on or after this date (ISO, e.g. 2026-10-01)
filestringcontacts listed in this imported CSV (file key returned by import_leads)
allboolean-
keep_sequencesboolean-
dry_runboolean-

connect_list

Draw or erase the arrow from a lead list to a campaign. connect (default true) enrolls the list's people into the campaign (same rules as enroll_contacts) and keeps enrolling those added later. connect false stops new enrollments; sequences already started go on. Run dry_run first and get the user's approval when the campaign is active.

ParameterTypeDescription
list_id requirednumberlist
campaign_id requirednumbercampaign
connectboolean-
dry_runboolean-

delete_list

Delete a lead list and its arrows. Contacts and their sequences stay. Ask the user first; dry_run shows the counts.

ParameterTypeDescription
list_id requirednumberid
dry_runboolean-

list_webhook

The webhook URL of a lead list: another tool (a form, Zapier, n8n, a CRM) POSTs leads to it and they join the list on their own, with the free email check, and enter the campaigns the list feeds. Body: one lead {email, first_name, company, priority, other fields become variables} or {leads: [...]} up to 1000. priority 1 is sent first, then 2, 3…; no priority goes after the others. rotate=true makes a new URL (the old one stops working).

ParameterTypeDescription
list_id requirednumberlead list
rotateboolean-

Mailboxes and domains

list_mailboxes

Sending mailboxes: domain, provider, status (active/paused), daily_cap, note (why paused), sent today, total sent, bounces (hard), domain status, and inbox placement of the Instantly warmup emails over 7 days (warmup_inbox_7d, warmup_spam_7d, inbox_rate when 10 or more landed). A mailbox sends only when it and its domain are active AND an active campaign uses it. Kata never activates a mailbox on its own: only set_mailbox, create_mailbox (a new mailbox) or the user in the UI do, and each change is logged (events type audit). Kata pauses one by itself when hard bounces pass 3%, or when more than 10% of its warmup emails land in spam.

ParameterTypeDescription
domainstringonly this domain

create_mailbox

Add one mailbox to Kata, active. provider agentmail (default): creates a new inbox in the AgentMail account; domain is a verified AgentMail domain already in Kata, or empty for @agentmail.to. provider zapbox: connects an existing Zapmail (Google Workspace) mailbox; give its full email. Use a real first name. Ask the user first.

ParameterTypeDescription
provider"agentmail" | "zapbox"-
usernamestringpart before @, e.g. marc
emailstringfull address (zapbox)
domainstringverified domain, empty = agentmail.to
display_namestringe.g. Marc Dubois
daily_capnumberemails per day at start (default 10)

sync_mailboxes

Import the inboxes that already exist in the AgentMail account as Kata mailboxes, paused. Never changes the status of a mailbox already in Kata (it also runs every 15 minutes).

No parameters.

set_mailbox

Activate or pause a mailbox, change its daily_cap, or set its email signature (the line under the sender name). Give email (one address) or domain (all its addresses; activating them also resumes the domain). An active mailbox sends only for active campaigns that use it. Each change is logged (events type audit). Never activate without the user's approval.

ParameterTypeDescription
emailstringone mailbox
domainstringall mailboxes of this domain
status"active" | "paused"-
daily_capnumberemails per day per mailbox
signaturestringline under the sender name in every email from this mailbox, e.g. FightBets · fightbets.com; empty = none

remove_mailbox

Remove a mailbox from Kata (it stays at the provider; sync will not bring it back). Its queued emails are cancelled. Ask the user first.

ParameterTypeDescription
email requiredstringmailbox

connect_domain

Connect a domain from the Cloudflare account to AgentMail: writes the DNS records, starts verification, then creates the mailboxes (real first names recommended, 3 per domain). Stops if the domain already receives email elsewhere, unless force=true.

ParameterTypeDescription
domain requiredstringe.g. gofightbets.com
inboxes requiredobject[]Each item: username*, display_name*
daily_capnumberemails per day per mailbox at start (default 10)
forcebooleanreplace an existing MX record

check_domains

Check pending domains and create their mailboxes once verified.

No parameters.

set_domain

Resume a domain Kata paused for bounces, or pause it. Daily limits are set per mailbox (set_mailbox), not per domain.

ParameterTypeDescription
domain requiredstringdomain
status required"active" | "paused"-

remove_domain

Remove a domain and all its mailboxes from Kata (not from the provider or DNS). Ask the user first.

ParameterTypeDescription
domain requiredstringdomain

warmup_status

Warmup state of the mailboxes in Instantly: in Instantly or not, warmup on/off/paused/error.

ParameterTypeDescription
emailsstring[]default: every mailbox

warmup_enable

Turn warmup on in Instantly for mailboxes (emails, or all of a domain). AgentMail mailboxes not yet in Instantly are added automatically by IMAP/SMTP. Other providers must be connected in Instantly first. Ask the user first.

ParameterTypeDescription
emailsstring[]-
domainstringall mailboxes of this domain
daily_warmupnumberwarmup emails per day, default 20

warmup_disable

Turn warmup off in Instantly for mailboxes (emails or a domain). remove=true also removes them from Instantly. Ask the user first.

ParameterTypeDescription
emailsstring[]-
domainstringall mailboxes of this domain
removebooleanalso delete the accounts from Instantly

Sending and messages

scheduler_dry_run

What the next scheduler run would plan, without sending or writing anything: for each email the contact, campaign, step, mailbox, variant (angle), subject, planned time (UTC) and final link. Also explains what blocks sending, in this order: (1) campaign status (only active campaigns send; set_sending only flips every campaign at once), (2) mailbox status and its domain status (both must be active), (3) the campaign's chosen mailboxes (none chosen = every active mailbox), (4) daily cap per mailbox, (5) the lead's local sending hours (campaign setting), this shows tomorrow's first run), (6) contacts suppressed, stopped or not due yet. Also lists emails already planned and waiting. as_if_active=true simulates draft or paused campaigns as active (mailboxes stay as they are). No AI personalization in the preview.

ParameterTypeDescription
campaign_idnumberonly this campaign
as_if_activebooleantreat draft/paused campaigns as active
limitnumberemails listed, default 50, max 200

run_scheduler

REALLY SENDS. Runs the scheduler now, as the cron does every minute: plans the emails of active campaigns from active mailboxes, then sends every planned email whose time has come. It does nothing the cron would not do a minute later, but it is real sending. To look without sending, use scheduler_dry_run. Ask the user first.

No parameters.

set_sending

Global switch, a shortcut over campaign statuses (there is no separate flag): on=false pauses every active campaign and cancels the emails already planned; on=true sets every paused campaign back to active (drafts stay drafts). Mailbox statuses are not touched. Resuming needs the user's approval.

ParameterTypeDescription
on requiredboolean-

list_messages

Emails, newest first: scheduled, sent or failed, with a body preview. Filters: campaign_id, status, flag (clicked/replied/interested/converted/bounced), contact email. Returns count and one page.

ParameterTypeDescription
campaign_idnumbercampaign
status"scheduled" | "sending" | "sent" | "failed"-
flag"clicked" | "replied" | "interested" | "converted" | "bounced"-
emailstringcontact email
limitnumberdefault 50, max 200
offsetnumberskip

get_message

One email in full: subject, body, mailbox, contact, campaign, angle, status, flags and its events (reply text, click, bounce).

ParameterTypeDescription
id requirednumbermessage id

list_inbox

The Inbox: every reply received, one row per lead (its latest reply), newest first. Each row: contact_id, email, first_name, company, status (the reply kind: interested, not_interested, unsubscribe, ooo, wrong_person, other), unread (not opened in Kata yet), answered (you replied after it), replies (how many), message_id (pass it to reply), campaign, mailbox, subject, text (what they wrote), at. Also counts per status, the unread total, and the campaigns and mailboxes that got replies. Filters: status, campaign_id, mailbox, unread=true, q (text in email, name, company, subject or reply). 50 rows a page (limit up to 200), page from 0. Spam complaints and unsubscribe-link clicks are not listed.

ParameterTypeDescription
status"all" | "interested" | "not_interested" | "unsubscribe" | "ooo" | "wrong_person" | "other"-
campaign_idnumberone campaign
mailboxstringthe mailbox that received the reply
unreadbooleanonly replies not opened in Kata yet
qstringsearch text
pagenumberpage, from 0
limitnumberrows per page, default 50, max 200

set_reply_status

Correct the AI tag of a lead's latest reply (what the user does from the Inbox). status: interested, not_interested, unsubscribe, ooo, wrong_person or other. Nothing restarts: any status except ooo stops the lead's sequence, ooo leaves it as it is. unsubscribe suppresses the address; moving away from unsubscribe lifts that suppression. interested puts the lead in leads_to_call and counts as a success for the angle. Ask the user before you change a tag.

ParameterTypeDescription
contact_id requirednumberthe lead (contact_id from list_inbox)
status required"interested" | "not_interested" | "unsubscribe" | "ooo" | "wrong_person" | "other"-

reply

Reply to a lead in the same thread, from the mailbox that wrote to them (AgentMail, Gmail, Outlook, Kata's pool; Zapmail with its thread ids, like follow-ups, but Zapmail replies do not come back to Kata yet). Give message_id (one email Kata sent) or email (the lead: the last email sent to them), and text. draft_only=true sends nothing: with text it returns the email as it would go, without text the AI writes a draft from the brief, the company memory and the thread (instructions steers it). Show the draft to the user and send only with their approval. The reply goes out even if the mailbox is paused (a 1:1 answer, not a campaign send) and shows in the lead's timeline (event reply_sent). The sender name and signature are added. Sending marks the lead read in the Inbox (list_inbox gives message_id and email).

ParameterTypeDescription
message_idnumberan email Kata sent
emailstringthe lead's email: replies in its last thread
textstringthe reply body, plain text, without signature
draft_onlybooleansend nothing; without text the AI writes a draft
instructionsstringfor the AI draft, e.g. propose a call on Thursday

export_csv

Export to CSV and get a download link (valid 24 hours, works for anyone who has it; give it to the user). kind events (default) = the activity log: sent, click, reply, reply_sent, bounce, visit, conversion, pause…; kind messages = the emails with status, flags, bounce type and reason. Filters: campaign_id, type (an event type for events, a status scheduled|sent|failed for messages), mailbox, period 7d|30d|90d|all (default all). 50,000 rows at most.

ParameterTypeDescription
kind"events" | "messages"-
campaign_idnumberone campaign
typestringevent type, or message status
mailboxstringone sending mailbox
period"7d" | "30d" | "90d" | "all"-

Context files

list_context

List context files (no content). Company files are always in your context; campaign files must be read with read_context. With campaign_id: company files plus that campaign's files.

ParameterTypeDescription
campaign_idnumbercampaign id

read_context

Read the full content of one context file.

ParameterTypeDescription
id requirednumberfile id from list_context

save_context

Create or replace a context file (same scope, campaign and name = replaced). scope company: used everywhere (agent and emails). scope campaign: used for that campaign's emails and read on demand. Ask the user before saving.

ParameterTypeDescription
scope required"company" | "campaign"-
campaign_idnumberrequired when scope is campaign
name requiredstringfile name, e.g. pricing.md
content requiredstringfull text content

delete_context

Delete a context file. Ask the user first.

ParameterTypeDescription
id requirednumberfile id

Conversions

get_postback

The postback URL the user's backend calls to report a conversion (GET or POST, with email or kata=<token>, optional value, event and data: free lead fields saved on the contact, not a conversion when sent alone), and the last conversion received.

No parameters.