wazap-mcp
Use wazap-mcp to put your WhatsApp account behind 21 MCP tools for reading, searching, drafting, and managing messages, chats, groups, contacts, and media—all locally.
Link and manage WhatsApp accounts securely (QR code or phone pairing).
Read chats, messages, stories, contacts, group info, and message details (reactions, receipts, polls).
Catch up across accounts: waiting replies, mentions, missed calls, groups, and stories.
Search messages by meaning and exact words, with filters.
Retrieve media: voice note transcripts, images, files.
Draft, confirm, edit, delete, and react to messages.
Manage chats: archive, pin, mute, mark read/unread, clear, delete, block.
Manage groups: create, join, add/remove members, promote/demote, settings, invite links, join requests.
Wait for new messages with cursor-based polling.
Keep local notes and tags about people (e.g., nickname, relationship).
Safety: read-only mode, send allow/deny rules, rate limiting, privacy tags.
Provides tools for interacting with a linked WhatsApp account, enabling management of chats, messages, media, contacts, and groups, including sending messages, searching history, downloading media, and administering group settings.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@wazap-mcpwhat did I miss on WhatsApp today?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
╭───────────────╮
│ ▄██▀ │ ██╗ ██╗ █████╗ ███████╗ █████╗ ██████╗
│ ▄██▀ │ ██║ ██║██╔══██╗╚══███╔╝██╔══██╗██╔══██╗
│ ▄███████▀ │ ██║ █╗ ██║███████║ ███╔╝ ███████║██████╔╝
│ ▄██▀ │ ██║███╗██║██╔══██║ ███╔╝ ██╔══██║██╔═══╝
│ ▄█▀ │ ╚███╔███╔╝██║ ██║███████╗██║ ██║██║
╰─╮╭────────────╯ ╚══╝╚══╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═╝
╰╯ WhatsApp for your AI agent.
wazap is an MCP server for your own WhatsApp account. It links as a device, the way WhatsApp Web does, keeps what it sees on your machine, and gives any MCP client — Claude, ChatGPT, Gemini, Cursor, Codex — 23 tools over your chats, messages, media, contacts and groups.
You stop opening WhatsApp to find things and ask instead:
"What did I miss on WhatsApp today?" — one answer across every linked account: who is waiting on you, mentions, missed calls, busy groups condensed.
"Find the invoice Dan sent in spring." — search by meaning and by words at once, then open the file.
"What did the voice note from mama say?" — voice notes come back as text.
"Tell Ana I'll be twenty minutes late." — you see the recipient and the exact words first. Nothing leaves until you say yes.
No browser, no business account, no third-party service. There is no wazap cloud: it runs where you run it.
Get started
You need Node.js 22.16+ on the 22 line, or 24+, and a phone with WhatsApp.
npx wazap-mcp setupsetup links your account, finds the MCP clients installed on this machine
(Claude Code, Claude Desktop, Cursor, Codex, Gemini CLI), writes their config,
installs the five skills where the client reads them, and tells you what to
restart. Then ask your assistant: "what did I miss on WhatsApp today?"
Rather let your agent do it? Paste this into it:
Set up WhatsApp for me: run
npx wazap-mcp setup --agentand follow what it prints.
npx wazap-mcp on its own, in a terminal, starts nothing: it prints where you
stand and the next command. When something is off, npx wazap-mcp status is
the first thing to run; it prints a fix next to anything broken.
Per client
Client | Fastest path |
Claude Code |
|
Claude Desktop | download |
Cursor | the badge below, then |
Codex CLI |
|
Gemini CLI |
|
claude.ai, ChatGPT, other hosted agents | a URL they sign in to with OAuth: see Remote access |
Anything else | command |

The hand-written entry, for any client that takes the usual JSON:
{
"mcpServers": {
"whatsapp": { "command": "npx", "args": ["-y", "wazap-mcp"] }
}
}Every step setup takes, each file connect writes, and upgrading are in
docs/install.md.
Related MCP server: wa-bridge
Linking your account
Linking is a one-time step. setup does it for you; on its own it is:
npx wazap-mcp login # QR code: Settings → Linked devices → Link a device
npx wazap-mcp login --phone +15550100 # pairing code instead, no camera neededWith --phone, wazap prints an 8-character code. On the phone, go to
WhatsApp → Settings → Linked devices → Link a device → Link with phone number
instead and type it in. The pairing code works over SSH and on a headless
server, where a QR is impractical.
An assistant can link the account itself, too: the link_account tool returns
the same code, so a Claude Desktop user never needs a terminal.
Several WhatsApp accounts can live in one wazap (wazap account add <id>, then
wazap login --account <id>); see docs/accounts.md.
The 23 tools
What every argument means, and every error code, is in
docs/tools.md. The assistant gets all of it by calling learn.
Tool | Kind | What it does |
| read | The guide to every tool, id format, workflow and error code. Call it first. |
| read | Connection, sync, linked accounts, how fresh the history is, webhook delivery, versions. |
| read | Link an account from the assistant; returns the 8-character code to type into the phone. |
| read | Conversations newest-first: |
| read | One chat, paging back into the phone's history; |
| read | "What did I miss?" across every account, in one call and within a token budget. |
| read | Messages by meaning and by words at once, narrowed by chat, sender or date. |
| read | One message in full: its quote, reactions and who left them, poll votes, delivery and read receipts. |
| read | Who "mama", a nickname, a group name or a number means, before anything is drafted. |
| read | The phone's address book a page at a time: saved name, number, when you last talked. |
| read | Participants, admins, group settings, the invite link for an admin. |
| read | A voice note as its transcript, a photo as an image, any file saved to disk; served from the copy kept on arrival first. |
| read | Block up to 55 s until a message arrives, with a cursor so nothing is missed between calls. |
| local | A note, tags or details about a person, kept on this machine. Nothing changes on WhatsApp. |
| write | Draft a message, media, poll, location or forward — and send nothing. |
| write | Send that draft, once, after the user has seen the preview and said yes; a draft for later is scheduled. |
| write | Edit your own message, within WhatsApp's 15-minute window. |
| write | Add or remove an emoji reaction. |
| write | Delete for everyone (your own message, or anyone's in a group you admin), or only on this account. |
| write | Preview archive, pin, mute, star, clear, delete, block and undo actions; confirm the preview to apply once. |
| write | Create, join, rename, add, remove, promote, invite links, join requests, settings, leave. |
| write | List the scheduled messages (sent, missed, failed too) or cancel one before it goes. |
| local | "Remind me if Ana has not answered in 2 days": set, list or cancel; posted to your webhook when due. |
Scheduled messages and reminders. send_message with send_at ("tomorrow
at 9" as 2026-10-12T09:00 in Europe/Bucharest) drafts a message for later;
the user's yes to that preview, time included, schedules it, and every send
check runs again when it goes. One wazap could not send within 15 minutes of
its time is reported as missed, never sent late. reminder keeps "remind me if
Ana has not answered in 2 days" and posts it to your webhook when due. Both
survive restarts; see Scheduling a message
and Reminders.
Two features are off by default and can run entirely on your machine:
voice transcription with whisper.cpp (docs/voice.md) and
semantic recall, so search matches meaning and not only words
(docs/recall.md). Turn them on with
wazap config transcribe local and wazap config recall local.
Skills
Tools say what is possible; the five Agent Skills in
skills/ say how to do the job well.
Skill | What the agent does |
| Triage: needs you / FYI / noise, plus replies you forgot. Read-only. |
| Find an address, an invoice, a photo, a thing someone said. Read-only. |
| Catch up on a busy group: decisions, dates, what is asked of you. Read-only. |
| Find who you mean, draft in the chat's own tone, show it, send on a yes. |
| Diagnose, link or repair the connection. |
setup installs them for Claude Code, Codex and Cursor
(npx wazap-mcp skills install <harness> does it by hand). Every other client
gets the same five as MCP prompts from the server, with nothing to install.
Transports
stdio is the default: the client starts npx -y wazap-mcp and talks to it
over stdin/stdout. Nothing listens on the network.
HTTP (Streamable HTTP) is for a server that outlives the client, or one another machine reaches:
npx wazap-mcp serve --http # http://127.0.0.1:8766/mcp, health at /healthz--host/--port (or WAZAP_HOST/WAZAP_PORT) move it. wazap refuses to bind
anything but loopback without WAZAP_READ_TOKEN. Clients authenticate with a
static bearer token (WAZAP_READ_TOKEN, plus WAZAP_WRITE_TOKEN for the write
tools) or with OAuth 2.1, which wazap serves itself. Details in
docs/self-host.md.
Remote access
Two commands keep wazap running and reachable from hosted agents:
npx wazap-mcp service install # a launchd agent (macOS) or systemd user unit (Linux)
npx wazap-mcp expose # a public https URL through Tailscale Funnel or Cloudflare Tunnelexpose prints the URL and a consent password. Give the agent only the URL;
it registers itself, and the consent page asks you for the password and
whether that agent may only read or also send. See
Keep it running.
The service recovers by itself: a dropped link is retried with backoff, a
watchdog replaces a socket that went dead across a sleep or stopped answering,
and when reconnecting keeps failing wazap exits so launchd or systemd starts it
fresh. The linked session is never deleted for any of that; only WhatsApp
unlinking the device needs a new link. Set WAZAP_WEBHOOK_EVENTS to include
alert to be told when the link has been down for 5 minutes, when it is back,
and when it needs linking again (Link alerts);
get_status shows the same under link.
Deployment
On a server of your own, the session never leaves it. With Docker (images for
amd64 and arm64 at ghcr.io/razvangirgiz/wazap):
mkdir wazap && cd wazap
curl -fsSLO https://raw.githubusercontent.com/razvangirgiz/wazap/main/docker-compose.yml
printf 'WAZAP_READ_TOKEN=%s\nWAZAP_WRITE_TOKEN=%s\n' $(openssl rand -hex 32) $(openssl rand -hex 32) > .env
docker compose run --rm wazap login --phone +15550100 # once; the session lands in the volume
docker compose up -d
curl -s http://127.0.0.1:8766/healthzThe container publishes port 8766 on loopback only; put TLS in front
(deploy/Caddyfile is two lines). A systemd unit is in
deploy/wazap.service. Both setups, reverse-proxy
trust and the OAuth server are in docs/self-host.md.
Calling wazap from your own product, and receiving signed webhooks for incoming
messages, is in docs/api-and-webhooks.md.
Configuration
Every setting is optional. They are environment variables, read from the
process or from ~/.wazap/.env (a real environment variable wins, a flag wins
over both). You rarely edit them by hand: wazap config shows the effective
settings and changes one.
Setting | Default | What it does |
|
| Where credentials, databases and models live ( |
| unset |
|
|
|
|
|
| Where |
| unset | Static bearer tokens for HTTP; only the write token gets the write tools. |
| unset | Both together turn on OAuth for hosted agents. |
|
|
|
|
|
|
|
|
|
|
| Which chats' media is downloaded on arrival and kept, so |
The full list, including the webhook filters, kept-media limits, retention and proxy trust, is in
docs/settings.md; .env.example is the
same list as a commented file.
Security and privacy
Nothing is sent without a yes.
send_messageonly drafts: it returns the recipient and the exact text and touches no network. Onlyconfirm_sendsends, and a draft goes out at most once, even across a crash. Draft-then- confirm is a workflow, not proof of consent: an agent can call both tools unless your client makes you approve the second one.Read-only is a real switch. With
WAZAP_READ_ONLY=1,--read-onlyorwazap config writes off, the write tools are not registered, so the assistant cannot message anyone even by mistake. The Claude Desktop bundle ships with read-only ticked.Recipients can be pinned.
wazap config send allow +15550100,…limits an account to a list,denyrefuses the ones named; both are checked at draft and again at send (docs/send-rules.md).Writes are rate limited, 20 a minute per account by default, because sending faster than a human is how numbers get banned.
Your data stays on your machine. Credentials, messages, media and notes live in
~/.wazap(0700, credential files0600). No account, no telemetry. What leaves the machine: WhatsApp traffic; the npm registry, for the version check; Hugging Face, when you download a transcription or embedding model; a transcription API, only if you choseopenai; your own webhook, if you set one (docs/data.md).Some people can be kept out. Tag a contact
#privateand their words stay out of everything the assistant did not ask about them by name, and out of the webhook.#no-catchupkeeps their chat out ofcatch_up.What it does not do. No bulk send, no scheduler, no campaigns. It never marks anything read on its own, and sends text without link previews, so nothing fetches the pages you link.
Threat model, findings and the limits of each of these: docs/security-audit.md.
Known limitations
The protocol is unofficial. wazap is built on Baileys, a reverse-engineered implementation of WhatsApp's multi-device protocol. It is not the WhatsApp Business API and Meta does not support it. A protocol change can break wazap until Baileys catches up, and an account that sends in bulk or to people who did not ask can be restricted or banned. The safeguards above reduce that risk; they do not remove it, and the risk is yours.
Model behaviour is measured on Claude only. The evaluation in
eval/(58 cases, each run three times) has been run on Claude. Other clients get the same tools and the same server-side guards, but nobody has measured how their models use them. The manual protocol for ChatGPT iseval/chatgpt-protocol.md.History is what the phone syncs to a linked device, not your whole archive.
read_messageswithbeforeasks the phone for more, within what WhatsApp still keeps.Old media expires. WhatsApp drops old attachments from its servers;
get_mediathen returnsMEDIA_UNAVAILABLE, unless wazap kept a copy when it arrived. By default it keeps the photos, voice notes, audio and documents of unmuted chats, up to 16 MB each, 1 GB in all and 90 days, whilewazap serveruns; media that arrived and expired while nothing was keeping it cannot be brought back.Names come from the phone's address book, which WhatsApp only sends to a fresh connection. If contacts read as numbers (
contacts_named: 0inget_status),wazap contacts resyncasks again while no server runs.@lidids. Newer accounts are addressed by a privacy id; wazap maps it back to a number when it has learned the mapping.Calls are WhatsApp calls only, and a call that starts and ends while wazap is stopped may be missing. Cellular calls are never visible.
The phone must stay reachable. A linked device stops receiving once the phone has been offline too long;
get_statussays so.
What the 1.x line promises not to break is in docs/stability.md.
Documentation
| |
The 23 tools in full, the workflows, every error code | |
Several WhatsApp accounts, several MCP clients on one server | |
Voice notes as text: whisper.cpp locally, or an OpenAI-compatible API | |
Semantic search with a local embedding model | |
The data directory, | |
Read-only mode, per-account send rules, rate limits | |
HTTP mode, systemd, Docker, tunnels, proxy trust, OAuth | |
Static tokens in, signed webhook events out | |
Every | |
The security audit | |
What 1.0 promises to keep stable | |
Release by release |
Contributing
git clone https://github.com/razvangirgiz/wazap && cd wazap
npm ci
npm run check # lint, typecheck, then build and test
node test/smoke-stdio.mjs # drives the built binary over MCP stdio
npm run dev -- status # run from source with tsxThe tests need no WhatsApp account. CLAUDE.md is the contributor's map: layout, the rules that must never break, and the release procedure. Issues and pull requests are welcome at github.com/razvangirgiz/wazap.
License
MIT © Răzvan Girgiz
Available Tools
23 toolscatch_upCatch up on what the user missedARead-only
What the user missed, all accounts, within budget_tokens: waiting (every open ask of 14 days, whatever the window), mentions, calls, people, groups, stories. account_id narrows it to one account; get_status names them. The mark moves first; a lost answer is since: "previous". more.cursor: the rest.
| Name | Required | Description | Default |
|---|---|---|---|
| hours | No | The last N hours instead; never moves the mark | |
| since | No | "last" (default); "previous" repeats that catch-up; or an ISO date or time from the last 14 days | |
| cursor | No | more.cursor | |
| include | No | Only these sections; the mark then stays | |
| account_id | No | ||
| budget_tokens | No | Answer length in tokens |
Output Schema
| Name | Required | Description |
|---|---|---|
| more | Yes | Set when entries are left: call catch_up again with more.cursor |
| notes | No | Caveats to act on or tell the user |
| direct | Yes | |
| footer | Yes | On the last page: what the entries leave out |
| groups | Yes | |
| window | Yes | |
| stories | Yes | |
| waiting | Yes | |
| accounts | Yes | |
| addressed | Yes | |
| account_id | Yes | |
| missed_calls | Yes | |
| approx_tokens | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true and idempotentHint=false, and the description explains the non-obvious reason: 'The mark moves first', so a repeat call is not idempotent and a swallowed answer requires since: "previous". That is real side-effect disclosure the annotations cannot convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Every clause carries information and the scope comes first, but the telegraphic fragments ('The mark moves first', 'more.cursor: the rest', 'a lost answer is since: "previous"') force the reader to reconstruct the grammar, which costs clarity for very little length saved.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values need not be explained, and the description covers the remaining gaps: breadth across accounts, the token budget, the mark/cursor/repeat interaction. Only the 'waiting' 14-day exception ('whatever the window') is stated so tersely that its interaction with 'hours' stays murky.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is already 83%, so the baseline is 3, and the description still adds meaning: 'hours ... never moves the mark', 'include' makes the mark stay, 'more.cursor: the rest', 'since: "previous" repeats that catch-up'. These are behaviors of the parameters, not restatements of their types.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'What the user missed, all accounts' and enumerates the sections returned (waiting, mentions, calls, people, groups, stories), so the resource and scope are clear. It never names a verb, but the digest nature distinguishes it well enough from search/read_messages siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'account_id narrows it to one account; get_status names them' gives a concrete routing rule to a sibling. However there is no statement of when to prefer this over read_messages or search, and the 'lost answer is since: "previous"' hint is recovery guidance rather than use-case guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
confirm_sendSend a drafted WhatsApp messageAIdempotent
Send a draft the user approved — this text, this recipient: the only call that sends, once per draft. A yes about something else: show the preview again and ask. Expired, missing or stale: draft again, show the new preview, ask again. SEND_OUTCOME_UNKNOWN: read_messages, never redo it unasked.
| Name | Required | Description | Default |
|---|---|---|---|
| draft_id | Yes | From send_message; one with send_at is scheduled, not sent | |
| account_id | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, the description discloses key behavioral traits: it sends only the approved draft text to the approved recipient, sends once per draft, and must not be retried unasked after an unknown outcome. This adds meaningful safety and side-effect context for a high-stakes mutation tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is short, front-loaded with the main send action, and every sentence carries operational value. The terse error-handling clauses are efficient rather than wasteful.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a high-stakes send operation, it covers approval requirements, staleness, idempotency, and unknown-outcome recovery well. It does not describe successful return behavior or explain account_id, leaving a small completeness gap given there is no output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema documents draft_id but leaves account_id undocumented, and the description does not explain account_id either. It reinforces draft uniqueness and approved-recipient semantics but only partially compensates for the 50% schema coverage gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource ('Send a draft') and clarifies scope with 'this text, this recipient' and 'the only call that sends, once per draft.' It distinguishes the action from draft creation and from other sending-like siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly states when to send, what to do when the user's yes is about something else, what to do for expired/missing/stale drafts, and how to handle SEND_OUTCOME_UNKNOWN. These are concrete when/when-not and recovery instructions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_messageDelete a WhatsApp messageADestructiveIdempotent
Delete a message; confirm with the user first. for_everyone: true retracts it for everyone within 2 days: the account's own message, or anyone's in a group where it is admin. for_everyone: false removes any message from the linked account's devices only.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | No | ||
| message_id | Yes | ||
| for_everyone | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| account_id | Yes | |
| message_id | Yes | |
| for_everyone | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the destructiveHint/idempotentHint annotations, the description discloses the 2-day retraction window, the permission rule (own message or group admin), the limited blast radius of the local-delete mode, and the requirement to confirm with the user. These are exactly the facts an agent needs before performing an irreversible action.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The critical safety instruction (confirm first) and the primary parameter are front-loaded, and no sentence is filler. The second half is a dense run-on clause chain, but every clause carries distinct information about scope and permissions.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive, open-world mutation with an output schema, the description covers confirmation, permission scope, time limits, and deletion breadth. Only the account_id parameter and multi-device/account selection semantics are left implicit.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must carry the parameter burden; it does so thoroughly for for_everyeen (both boolean values, their effects, and their eligibility constraints). message_id and account_id remain semantically unexplained beyond their names, which is a small residual gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource ("Delete a message") and immediately distinguishes the two deletion scopes via for_everyone. It is clearly separable from siblings like edit_message or send_message, though it does not explicitly name or contrast any sibling.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives a concrete operational precondition ("confirm with the user first") and explains which mode applies when: for_everyone:true only within 2 days and only for one's own message or as a group admin; for_everyone:false for any message on the linked account's devices. Missing only an explicit comparison to alternative tools (e.g. edit_message) when a message should be changed rather than removed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
edit_messageEdit a WhatsApp message you sentADestructiveIdempotent
Replace the text of a message the linked account sent. WhatsApp allows it for 15 minutes after sending; later, send a correction instead.
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes | ||
| account_id | No | ||
| message_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| text | Yes | |
| chat_id | Yes | |
| timestamp | Yes | |
| account_id | Yes | |
| message_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=true, so the description's job is lighter; it still adds the genuinely non-obvious 15-minute window and the ownership constraint. It doesn't say what happens on a rejected/timeout edit or whether the original text is recoverable, which would be the remaining useful detail for a destructive mutation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, zero filler, with the ownership scope and the time constraint front-loaded before the fallback advice.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Output schema and annotations carry much of the load, and the time/ownership constraints are the key behavioral facts. However, for a destructive, open-world mutation with completely undocumented parameters, an agent is left guessing about account_id semantics and the failure modes of an expired or foreign message.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must carry parameter meaning. It conveys only that a message and its replacement text are involved, leaving account_id (optional, presumably the linked account selector) and the format/constraints of message_id undocumented anywhere.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a precise verb+resource ('Replace the text of a message') and narrows scope to messages 'the linked account sent', which cleanly separates it from send_message, delete_message, and react_to_message in the sibling list.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit eligibility window ('15 minutes after sending') and a fallback action ('send a correction instead'). It stops short of naming the sibling to use for the fallback, so the routing is implied rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_contactFind who the user meansARead-onlyIdempotent
Who a name, nickname, relationship ("mama"), filed detail ("AP-123"), group, number or id means, before drafting. resolved: contact.chat_id, with number, note, tags, details and, when writing, context. ambiguous or not_found: ask the user; never guess. Several accounts: see fix. tag: its people.
| Name | Required | Description | Default |
|---|---|---|---|
| tag | No | List everyone filed under this tag instead | |
| kind | No | any | |
| name | No | What the user calls them ("Ana", "mamei", "fotbal"), or a number or id | |
| limit | No | Ambiguous: at most 5 per account; a tag list: up to 50 | |
| qualifier | No | Tells two apart: "contabilitate", a group, the last 4 digits | |
| account_id | No | ||
| include_context | No | Recent messages and the user's style, when resolved in a write session |
Output Schema
| Name | Required | Description |
|---|---|---|
| fix | No | What to do next, when not resolved |
| next | No | Resolved: how a message to them starts |
| notes | No | Caveats to act on or tell the user |
| query | Yes | |
| status | Yes | |
| closest | No | Only when not_found |
| contact | No | Only when resolved |
| context | No | Only when resolved, in a session that can write: what a draft to them is written after |
| omitted | No | Only when listed and cut by limit: how many more on each account |
| contacts | No | Only when listed: everyone filed under the tag |
| can_draft | No | Resolved in a session that cannot send |
| account_id | No | The account that answered; null when several accounts were searched and none answered alone |
| candidates | No | Only when ambiguous; best first |
| accounts_searched | No | |
| accounts_unavailable | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/idempotent/non-destructive annotations, it discloses the success shape (contact.chat_id plus number, note, tags, details, and context when writing) and the ambiguity/not_found policy. Gaps remain: 'see fix' is unexplained and it doesn't clarify account scoping behavior. Output schema covers the return payload, so this is solidly above baseline.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is short and front-loads the core resolution act, but the compression goes too far: sentence fragments and dangling references ('see fix') cost parseability. Space is saved at the expense of clarity rather than through it.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 7-parameter, output-schema-backed lookup with strong annotations, the description covers resolution inputs, failure policy, write-session context, and the tag-listing mode. What's missing is a clear account_id/multi-account explanation and any note on limits, so it is good but not fully self-contained.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 71%, so most parameters are already documented. The description reinforces tag listing ('tag: its people') and hints at qualifier disambiguation ('tells two apart' is in schema, not description), but it adds little on kind, limit, account_id, or include_context beyond what the schema states. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific job: resolve whatever the user said (name, nickname, relationship, filed detail, group, number, id) into a contact before drafting. It distinguishes itself from plain listing by framing this as 'who the user means', but the phrasing is telegraphic and it never names the obvious sibling (list_contacts) it replaces.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives real usage context — call it 'before drafting', and on 'ambiguous or not_found: ask the user; never guess' — which tells the agent what to do when resolution fails. The 'Several accounts: see fix' branch points somewhere useful but the referent ('fix') is opaque and not a listed sibling, weakening the routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_group_infoGet WhatsApp group infoARead-onlyIdempotent
A group's name, description, owner and participants (up to 500), whether the account is admin, its settings (info_locked, member_add_mode, join_approval, disappearing_seconds), its community, and the invite link for an admin. Call it before manage_group.
| Name | Required | Description | Default |
|---|---|---|---|
| group_id | Yes | <id>@g.us | |
| account_id | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| name | Yes | |
| owner | Yes | |
| chat_id | Yes | |
| community | No | |
| account_id | Yes | |
| created_at | Yes | |
| i_am_admin | Yes | |
| description | Yes | |
| info_locked | Yes | |
| invite_link | No | |
| participants | Yes | |
| join_approval | Yes | |
| member_add_mode | Yes | |
| announcement_only | Yes | |
| participant_count | Yes | |
| disappearing_seconds | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive/openWorld, and the description adds useful context beyond them: a 500-participant cap and the fact that the invite link is only returned for an admin (an auth-conditional detail). It does not discuss pagination or failure modes, but the added constraints are valuable.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It fits the essential information into one dense sentence with no wasted words, and the sequencing cue lands at the end. It reads as a return-value list rather than a front-loaded purpose statement, but nothing is superfluous.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the return enumeration is technically redundant but helpful, and annotations cover the safety profile. The only real gap is the unexplained account_id, but otherwise an agent has enough to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
At 50% schema coverage, only group_id is documented ('<id>@g.us') while account_id is undocumented in both schema and description. The description adds no parameter meaning to compensate, leaving account_id's role ambiguous from the definition alone.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description enumerates exactly what the tool returns (name, description, owner, participants, settings, community, invite link), making the retrieval purpose clear. It also implies a read-only scope distinct from manage_group. It never quite states a leading verb, but an agent knows what it gets back.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit sequencing rule: 'Call it before manage_group,' which tells the agent when this precedes a mutation. It does not name alternatives or when-not conditions, but the primary usage context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_mediaGet the media of a WhatsApp messageBRead-only
What a message's media holds: a voice note or audio as its transcript (kept once made; an API provider bills it), or with save_to its file; a photo attached as an image; any file saved at path on the machine running wazap; a copy kept on arrival answers first. MEDIA_UNAVAILABLE: gone, none kept.
| Name | Required | Description | Default |
|---|---|---|---|
| save_to | No | Absolute directory; default <data-dir>/media. A recording: its file, and no new transcript | |
| language | No | What is spoken, e.g. "ro" | |
| account_id | No | ||
| message_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| mime | No | |
| path | No | |
| size | No | |
| type | Yes | |
| sender | Yes | |
| source | No | kept: the copy wazap kept when it arrived; whatsapp: downloaded now |
| caption | Yes | |
| filename | No | The name it was saved under |
| account_id | Yes | |
| message_id | Yes | |
| transcript | No | |
| image_attached | No | The photo, or a small preview of it, is attached |
| original_filename | Yes | |
| transcript_unavailable | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnlyHint/not destructive, openWorld), the description adds genuinely useful behavior: transcripts are billed by an API provider, save_to writes a file to the local machine, and a MEDIA_UNAVAILABLE outcome means the media is gone. These cost and failure-mode disclosures are exactly what annotations cannot convey, though the save_to disk-write side effect on a 'read-only' tool could have been called out more explicitly.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is short, but the elliptical fragments ('a photo attached as an image; any file saved at path on the machine running wazap; a copy kept on arrival answers first') are dense and hard to parse on first read, so compactness comes at the cost of clarity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values need not be spelled out, and the description covers media variants and the MEDIA_UNAVAILABLE case. However, for a tool that takes an account_id and writes files via save_to, the absence of any note on account scoping or where files land by default leaves real gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 50%: save_to and language are documented in the schema, and the description reinforces save_to's effect ('with save_to its file'), while message_id and account_id receive no explanation anywhere. With half the parameters undocumented, the description only partially compensates.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The phrase 'What a message's media holds' plus the enumeration (transcript, image, file) makes clear it fetches a message's attachments, but there is no verb-led statement of the action and no differentiation from the sibling get_message, which an agent could easily confuse it with.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit when-to-use or when-not-to-use guidance is given, and nothing says to prefer this over get_message or search. The only routing-like hint, 'a copy kept on arrival answers first,' concerns caching order, not tool selection, so usage must be inferred.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_messageGet one WhatsApp message in fullARead-onlyIdempotent
One message in full, its words never cut: the message it quotes, each reaction with who left it, poll votes and event answers by person, its media, and on the user's own messages who it reached and who read it. Without account_id the id is looked for on every account.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | No | ||
| message_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| text | Yes | |
| chat_id | Yes | |
| timestamp | Yes | |
| account_id | Yes | |
| message_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint and openWorldHint, so the safety profile is covered. The description adds one genuinely useful behavioral fact: without account_id the id is looked up across every account. The rest is a return-content inventory (quotes, reactions, poll votes, media, read receipts) that an existing output schema already carries.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single dense sentence front-loads the core promise ('One message in full') and then enumerates contents efficiently. The only waste is the return-content inventory, which duplicates what the output schema already declares.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values need little prose, and the annotations cover the safety profile; the only real gap an agent would care about is the lack of routing guidance versus read_messages or search. The account_id fallback note fills the other notable hole.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must carry parameter meaning, and it does explain account_id's optionality and its cross-account fallback behavior. message_id is left to the name and its minLength constraint, so the compensation is only partial.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The title and the opening 'One message in full' state the specific resource and scope, and 'one message' implicitly separates it from bulk readers like read_messages. The description text itself, though, never says the verb plainly and never names a sibling to distinguish against, leaving the differentiation to the title.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no explicit when-to-use or when-not-to-use guidance and no named alternative among siblings such as read_messages or search. That this is the single-message, full-fidelity fetch is only implied by 'One message in full'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_statusGet the WhatsApp connection statusARead-onlyIdempotent
Whether the account works: status (connected, not_linked, linking with its pairing code…), sync, how fresh the history is, webhook delivery, versions. accounts lists every account, with default. Call it on NOT_CONNECTED, NOT_LINKED or SYNC_IN_PROGRESS.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | No | ||
| include_picture | No | Add picture_url, the account's own profile photo (the link expires) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint=false, so the safety profile is covered. The description adds some useful context about what is inspected (sync, history freshness, webhook delivery, versions) and that accounts are listed with a default. It says nothing about authentication requirements, rate limiting, or failure behavior when the account is unreachable.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is short and the most useful content (the return-field inventory) comes first, but the structure is telegraphic: a colon list inside a sentence fragment with a trailing ellipsis, followed by a non-sequitur about accounts. Tightening into two clean sentences would cost nothing and read much better.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the enumeration of returned data (status, sync, history freshness, webhook delivery, versions, accounts) carries real weight and is the strongest part. What is missing is the meaning of the enumerated status values and of account_id, which an agent needs to act on the result rather than just fetch it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 50%: include_picture is documented in the schema (including the expiring link), but account_id has no description anywhere. The phrase "accounts lists every account, with default" hints at default-account behavior but never states what account_id defaults to or how it selects an account, so the description only partially compensates for the gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description makes clear this is a health/diagnostic read of the account: connection status, sync progress, history freshness, webhook delivery, versions, and the account list with the default marked. It is distinguishable from siblings like list_chats or link_account, though the verb is implied rather than stated ("Whether the account works") and the parenthetical with an ellipsis is loose.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit trigger conditions: "Call it on NOT_CONNECTED, NOT_LINKED or SYNC_IN_PROGRESS." That is more than most definitions offer. However, those state names are never defined or sourced, and no alternative is named for the NOT_LINKED case (link_account is an obvious sibling that is not mentioned).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
learnLearn how to use the WhatsApp toolsARead-onlyIdempotent
The guide to these tools: ids, account_id with several accounts, the workflows, the message shape and what to do about each error code. Read it once, before the other tools; it never touches WhatsApp.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover readOnly/idempotent/non-destructive/closed-world, and the description adds the meaningful behavioral point that the call has zero effect on the WhatsApp account itself. It also signals the content categories (ids, workflows, error codes), which is useful for judging whether to call it first, though it doesn't specify the response shape or size.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One dense sentence that front-loads the topics covered and ends with the strongest routing cue ('read it once, before the other tools'). No filler and every clause carries information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-optional-parameter documentation tool with no output schema, the description supplies everything needed: what the guide contains, the account scoping rule, the recommended call order, and confirmation of no side effects.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0% — account_id is an unexplained bare string — and the description compensates by explaining that account_id matters when several accounts are in play. It does not clarify when the parameter can be omitted despite being optional, which keeps it short of a 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
A specific resource is named — a guide covering ids, account_id semantics for multi-account setups, workflows, message shape, and error codes — and 'it never touches WhatsApp' immediately distinguishes it from every action sibling. An agent can tell this is documentation retrieval, not an API call, without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Read it once, before the other tools' gives explicit ordering guidance relative to the 22 sibling tools, and the exclusion ('never touches WhatsApp') tells the agent not to expect any live data or side effects. Both when-to-use and what-it-is-not are stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
link_accountLink a WhatsApp accountA
Pair wazap with the user's WhatsApp when get_status says not_linked, logged_out, session_corrupt or auth_failure. Show the user the code it returns: WhatsApp → Settings → Linked devices → Link a device → Link with phone number instead. Then poll get_status every 10 s until connected.
| Name | Required | Description | Default |
|---|---|---|---|
| phone | Yes | e.g. +15550100 | |
| account_id | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare the safety profile (not read-only, non-idempotent, open-world); the description adds what the agent actually needs: the tool returns a pairing code that must be shown to the user, the exact WhatsApp menu path the user follows, and the required polling cadence until the connection succeeds. That is substantial context beyond the structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with the trigger conditions, then the user-facing procedure, then the polling requirement. No filler; each sentence carries information the agent needs to act.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, so the description usefully explains that a code is returned and how to use it, plus the completion check via get_status. The only gap is the undocumented account_id parameter, which is minor for the primary linking flow.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 50% (phone has an example, account_id has nothing), and the description never mentions either parameter. It neither clarifies the phone format required nor explains when account_id should be supplied, so it fails to compensate for the coverage gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (pair the app with the user's WhatsApp) and ties it to a concrete precondition surfaced by the sibling get_status. An agent can distinguish this from status-checking or messaging tools without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly names the four get_status values that should trigger the call (not_linked, logged_out, session_corrupt, auth_failure) and specifies the follow-up loop (poll every 10 s until connected). It also gives the human-facing procedure to hand to the user, leaving little to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_chatsList WhatsApp chatsARead-onlyIdempotent
Conversations, most recently active first: chat_id, name, type, unread count, last message, and whether archived, pinned, muted or left. Use it to find a chat_id.
| Name | Required | Description | Default |
|---|---|---|---|
| tag | No | Only chats with people filed under this tag | |
| limit | No | ||
| cursor | No | Opaque next_cursor from the preceding page; keep the same filter | |
| filter | No | "all" leaves out archived | all |
| account_id | No | ||
| include_pictures | No | Add picture_url, each chat's profile photo (links expire) |
Output Schema
| Name | Required | Description |
|---|---|---|
| tag | No | |
| sync | Yes | |
| chats | Yes | |
| count | Yes | |
| filter | Yes | |
| account_id | Yes | |
| next_cursor | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive), so the description only needed to add context beyond that. It does: result ordering, the set of surfaced fields, and the presence of archived/pinned/muted/left flags. It says nothing about page size behavior or what happens when the account has no chats, so it stops short of a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences, front-loaded with what comes back and ordering, ending with the actionable purpose. The field enumeration is somewhat redundant given an output schema exists, but it earns its place by letting an agent judge suitability at a glance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Return values needn't be explained since an output schema exists, and the description covers ordering and flags. Gaps remain around pagination expectations (limit/cursor are only sketched in the schema), the required account_id, and how this differs from search or list_contacts — for a 6-parameter tool that's the minimum viable level.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage sits at 67% and the description mentions no parameters at all — tag, filter, cursor, and include_pictures are documented only in the schema, while limit and account_id are undocumented in both places. With the majority of parameters covered by structured fields, the baseline of 3 is right, but the description adds no semantic lift.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States the specific resource (chats/conversations), the ordering (most recently active first), and the fields returned, plus the concrete downstream purpose (find a chat_id). It does not distinguish itself from siblings like search or find_contact, which is the only thing keeping it from a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
"Use it to find a chat_id" gives one concrete use case, which implies this is the discovery/listing entry point. But there are no exclusions or comparisons to alternatives such as search or list_contacts, so the agent must infer when this beats a search.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_contactsList the phone's address bookARead-onlyIdempotent
The phone's address book on one account, a page at a time: saved name, phone (E.164), chat_id, contact_id, and when the last direct message was and its direction. No message words; #private people left out. address_book_synced false: not arrived yet.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| order | No | recent: latest direct chat first, then the rest in address book order | recent |
| cursor | No | next from the previous page | |
| account_id | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare it a safe, idempotent, open-world read, yet the description still adds real context: results arrive a page at a time, contacts with direct messages excluded from output are omitted, and 'address_book_synced false' means the book has not finished syncing. It adds value beyond the annotations without contradicting them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the resource and the returned fields, then the exclusions, then the sync caveat — a logical order with no filler. The telegraphic fragments are dense but each clause carries information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description responsibly enumerates the returned fields (name, E.164 phone, chat_id, contact_id, last DM timestamp/direction). The main residual gap is ordering and page-size behavior, which the schema only partly covers.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 50% — 'order' and 'cursor' are documented inline, but 'limit' and 'account_id' are bare. The description gestures at both gaps ('on one account' implies account scoping, 'a page at a time' implies cursor/limit) but gives no default, maximum, or cursor-lifetime detail, so it only partially compensates.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific resource (the phone's address book, scoped to one account) and states it is paginated. It is clearly a listing operation, distinguishable from find_contact or list_chats by its roster-of-contacts framing, though it never names a sibling explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied: the reader infers this is for enumerating contacts and that find_contact is the lookup alternative. There is no explicit when-to-use/when-not statement, and the '#private people left out' note scopes the output rather than the call decision.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
manage_chatManage a WhatsApp chatADestructive
Preview archive, pin, mute, pin_message, star_message, clear, delete, block and undo. After approval repeat chat_id/action with confirmation_id, without options. Expires in 15m; one attempt. mark_read runs directly.
| Name | Required | Description | Default |
|---|---|---|---|
| action | Yes | ||
| chat_id | Yes | Chat id, or a phone number | |
| pin_hours | No | pin_message: 168 by default | |
| account_id | No | ||
| message_id | No | pin_message, star_message and their undo; in chat_id | |
| mute_hours | No | mute: 8 by default | |
| confirmation_id | No | From preview; omit message/duration options |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and non-idempotent, and the description adds genuinely new operational facts: a 15-minute expiry, a single attempt per confirmation, and that optional options must be dropped on the confirming call. It does not say what 'clear' versus 'delete' actually removes, which is the one behavioral detail an agent would still want.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four short sentences with the approval flow and expiry front-loaded and no filler. The telegraphic action list reads as a fragment, but nothing in it is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 16-action, destructive, no-output-schema tool, the description covers the approval mechanics but leaves the action taxonomy under-specified (undo variants and mark_unread unlisted, clear vs. delete undefined) and never states that preview returns a confirmation_id. Adequate to call correctly, but an agent could still mis-select an action.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 71% schema description coverage, the schema already documents chat_id, message_id, pin_hours, mute_hours and confirmation_id. The description adds the sequencing rule (confirmation call carries only chat_id/action, no options), which is real value, but it never ties message_id to pin_message/star_message or explains which optional parameters pair with which of the 16 enum actions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description enumerates the concrete chat operations it fronts (archive, pin, mute, pin_message, star_message, clear, delete, block) and signals a preview-then-confirm shape, so an agent can tell it apart from siblings like manage_group or delete_message. It is slightly incomplete — the un* variants (unarchive, unpin, unblock) and mark_unread are never named, and the mutated resource ('chat') is only implied by the title.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The two-phase flow is spelled out: first call previews, then 'repeat chat_id/action with confirmation_id', and 'mark_read runs directly' carves out the exception that skips approval. It lacks any guidance on when to prefer this over siblings such as manage_group or delete_message, so the routing context is only partially covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
manage_groupManage a WhatsApp groupADestructive
Create a group, join one from an invite (preview first, then confirm: true), or administer one: members, name, description, photo, invite link, join requests, settings, leave. Most actions need admin. Every change shows to all members at once: say what will change, wait for a yes.
| Name | Required | Description | Default |
|---|---|---|---|
| url | No | set_picture: public image URL | |
| value | No | The name (create, set_subject) or description; "on"/"off"; set_add_mode "admins"/"all"; set_disappearing "off"/"24h"/"7d"/"90d" | |
| action | Yes | ||
| invite | No | join: a chat.whatsapp.com link or its code | |
| confirm | No | join: true joins, after the user said yes to the preview | |
| group_id | No | "<id>@g.us"; every action but create and join | |
| file_path | No | set_picture: local JPEG, PNG or WebP | |
| account_id | No | ||
| message_id | No | join: an invite message instead | |
| participant_ids | No | create, add, remove, promote, demote, approve or reject |
Output Schema
| Name | Required | Description |
|---|---|---|
| name | No | |
| next | No | join preview: the step after the user's yes |
| action | Yes | |
| status | No | join: preview joins nothing |
| applied | No | |
| group_id | Yes | |
| account_id | Yes | |
| description | No | |
| invite_link | No | |
| participants | No | |
| join_approval | No | |
| join_requests | No | |
| profile_pic_url | No | |
| participant_count | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag mutation, destructiveness, open-world behavior, and non-idempotence. The description adds important context beyond them: admin authorization is usually required, and every change is visible to all members, with a consent workflow. It does not distinguish which of the many actions are especially destructive or irreversible.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two tight sentences, front-loaded with the three usage modes and followed by the key admin and group-wide side-effect constraints. Every sentence carries useful selection or invocation information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex 21-action tool with an output schema and rich annotations, the description covers the operations, admin prerequisite, join preview/confirm flow, and group-wide side effects. It reasonably relies on the schema for per-action parameter mapping, though it could say more about which actions require particular parameters.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 80%, so the input schema already documents most parameters. The description maps action categories and mentions the invite/preview/confirm workflow, but adds little format or syntax detail beyond what the schema provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with specific verbs and resources: create a group, join from an invite, and administer members, name, description, photo, invite link, join requests, settings, and leave. This clearly separates it from read-oriented siblings like get_group_info and message-oriented siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives concrete usage conditions: join requires a preview then confirm: true, most actions need admin, and group-wide changes require telling users and waiting for yes. It does not name sibling alternatives or say when not to use this tool, so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
react_to_messageReact to a WhatsApp messageAIdempotent
React to a message with one emoji, or pass "" to take your reaction off.
| Name | Required | Description | Default |
|---|---|---|---|
| emoji | Yes | ||
| account_id | No | ||
| message_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| emoji | Yes | |
| account_id | Yes | |
| message_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare this is a non-read-only, non-destructive, idempotent, open-world operation. The description adds useful behavior beyond that: only one emoji is allowed, and an empty string removes the existing reaction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single front-loaded sentence with no wasted words. Both the main action and the removal behavior are stated efficiently.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple, has an output schema, and has annotations covering safety and idempotency. The description covers the core behavior sufficiently, though account_id and message_id semantics are left implicit.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must carry parameter meaning. It explains the emoji parameter well, including empty-string removal semantics, but does not explain message_id or account_id beyond their names in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: reacting to a WhatsApp message. It also distinguishes the add-reaction and remove-reaction cases, so an agent can tell it apart from siblings like send_message, edit_message, or delete_message.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly explains the two usage modes: pass one emoji to react, or pass an empty string to remove the reaction. It does not explicitly name alternatives, but the context is clear enough for this narrow operation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_messagesRead messages from a WhatsApp chatARead-onlyIdempotent
Read one chat, oldest to newest: the latest messages, or older ones with before (wazap asks the phone when the local history runs out). Long texts are cut unless full_text. chat_id "status" reads the stories people posted, newest first, from the last hours (at most a day); they show nowhere else.
| Name | Required | Description | Default |
|---|---|---|---|
| hours | No | "status" only: how far back, 24 by default | |
| limit | No | ||
| types | No | Only these types; limit counts them, so ["call"] gives that many calls | |
| before | No | The oldest message_id you have | |
| chat_id | Yes | Chat id from another tool, a phone number, or "status" for stories | |
| full_text | No | Each message's text whole; a list cuts long ones otherwise | |
| account_id | No | ||
| include_previews | No | Attach a small image of each photo, up to 12 |
Output Schema
| Name | Required | Description |
|---|---|---|
| sync | Yes | |
| count | Yes | |
| hours | No | |
| notes | No | Caveats to act on or tell the user |
| older | No | before ran past the local history: the phone was asked, and sent this many |
| types | No | |
| chat_id | Yes | |
| omitted | No | Older stories left out by limit |
| messages | Yes | |
| account_id | Yes | |
| preview_count | Yes | |
| unconfirmed_sends | No | Sends WhatsApp has not echoed yet: outcome unknown, not failed |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish readOnly/idempotent/openWorld, and the description adds real behavior the annotations don't: history gaps trigger a phone fetch (latency/implication), long texts are truncated unless full_text, and status items are ephemeral (max a day) and appear nowhere else. It does not cover error modes or rate limits, so not a full 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Dense and front-loaded, with the main retrieval model in the first clause and the status special case after. The prose is slightly idiosyncratic ("wazap asks the phone") but every sentence carries information, so nothing is wasteful.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given an output schema exists and annotations cover the safety profile, the description covers the non-obvious essentials: pagination, truncation, and the stories mode. The main gap is account_id (multi-account selection), which is undocumented in both the schema and the description.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 75% schema coverage the baseline is 3, and the description genuinely adds value: it explains the before-based pagination model, the truncation default that full_text overrides, and that "status" is a special chat_id value. `limit`, `types` and `account_id` are left to the schema (account_id is undescribed in both places).
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb and resource plus scope: "Read one chat, oldest to newest." It also carves out the special "status" mode for stories, which an agent could not infer from the name. Together these let an agent tell it apart from search, get_message, list_chats and wait_for_messages.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Clear context for the two main modes: fetch the latest messages, or page backwards using `before` once you have the oldest message_id. It also flags that stories require chat_id "status" and are time-bounded. It stops short of explicitly naming when to prefer search, catch_up or wait_for_messages instead.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
rememberRemember something about a personAIdempotent
Keep what the user says about someone, locally, never on WhatsApp: a note, tags, details find_contact matches ({"relatie": "mama"}), or handled: true for an ask dealt with elsewhere. #private keeps their words out of what you did not ask about them by name; #no-catchup keeps them out of catch_up.
| Name | Required | Description | Default |
|---|---|---|---|
| note | No | "" removes it | |
| fields | No | e.g. {"nickname": "Mișu", "role": "contabil"}; "" deletes a key | |
| chat_id | Yes | Several: tags and fields only | |
| handled | No | Off catch_up's waiting until they write again | |
| add_tags | No | e.g. ["client"] | |
| account_id | No | ||
| remove_tags | No | ||
| remove_fields | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| name | No | |
| note | No | |
| tags | No | |
| fields | No | |
| number | No | |
| people | No | Several chat_ids: each one's card |
| chat_id | No | |
| handled | No | The ask taken off the waiting list; null when nothing was open |
| account_id | Yes | |
| is_business | No | |
| is_my_contact | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare non-read-only, idempotent, non-destructive, closed-world behavior, so the bar is lower, and the description still adds genuinely new context: storage is local and never written to WhatsApp, and the privacy flags alter how the record is exposed in later reads. The explanation of #private ('keeps their words out of what you did not ask about them by name') is confusing enough to blunt the value, but the disclosure is substantive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The core constraint (local, never on WhatsApp) is front-loaded, and there is little outright filler. But the single run-on sentence stacks four distinct payload types and two hashtag modifiers into one breath, making it harder to parse than it needs to be.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need no explanation, and the annotations cover the safety profile. Still, for an 8-parameter mutation tool with nested objects, the description leaves gaps: precedence when note/fields/add_tags/remove_tags are combined, behavior on a chat_id array (only 'tags and fields only' is hinted), and the relationship to the 'learn' sibling.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 63%, so the schema carries most of the burden, and the description does add meaning for 'fields' by tying it to what find_contact matches, plus the deletion semantics for note. It says nothing about account_id, remove_tags, remove_fields, or the array form of chat_id beyond the schema's own note, so it only partially compensates for the coverage gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Keep what the user says about someone, locally') and enumerates what can be stored: note, tags, matched details, and the handled flag. It also implicitly distinguishes itself from send_message by saying 'never on WhatsApp'. The phrasing is compressed and jargon-heavy, but an agent can identify the operation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives conditional guidance for two cases ('handled: true for an ask dealt with elsewhere', '#no-catchup keeps them out of catch_up'), which is real when-to-use signal. However, it never explains how this differs from the sibling tool 'learn', nor does it state prerequisites such as a linked account or what happens on conflicting writes. Usage is implied rather than fully specified.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
reminderSet, list or cancel a reminder about a chatA
The user's reminders about a chat, kept locally and posted to their webhook when due: create (chat_id, note, after_hours or due_at); condition "no_reply" fires only if nobody wrote there since ("if Ana has not answered in 2 days"). list, cancel. Nothing goes to WhatsApp.
| Name | Required | Description | Default |
|---|---|---|---|
| note | No | create: what to remind the user of | |
| limit | No | ||
| action | No | list | |
| due_at | No | create: due then, "2026-10-14T09:00" in time_zone, or with an offset | |
| chat_id | No | create: the chat it is about | |
| condition | No | no_reply: skipped if someone wrote in the chat after it was set | always |
| time_zone | No | IANA zone for due_at; the server's by default | |
| account_id | No | ||
| after_hours | No | create: due this many hours from now | |
| reminder_id | No | cancel: from create or list | |
| include_closed | No | list: the week's fired, skipped and cancelled ones too |
Output Schema
| Name | Required | Description |
|---|---|---|
| count | Yes | |
| notes | No | Caveats to act on or tell the user |
| action | Yes | |
| cancelled | No | |
| reminders | Yes | |
| account_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnlyHint=false, destructiveHint=false, openWorldHint=false), the description discloses where state lives (kept locally), how it is delivered (posted to the user's webhook when due), and a crucial side-effect exclusion ('Nothing goes to WhatsApp'). It does not say whether cancel is recoverable or what happens to already-fired reminders, so it is strong but not exhaustive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The core framing (what it is, where it lives, how it fires) is front-loaded in the first clause, and there is no filler. The mid-sentence parentheticals and semicolon-joined fragments make it slightly telegraphic, but every clause carries information an agent needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an 11-parameter, three-action tool with an output schema and annotations in place, the description covers the action surface, the timing model and the delivery mechanism sufficiently to call it correctly. Remaining gaps (account_id scoping, pagination via limit, cancel irreversibility) are low-risk and largely covered by the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 73%, so some compensation is expected, and the description does add meaning: it maps action values to the parameters they consume (create: chat_id, note, after_hours or due_at) and gives a human-readable gloss of the 'no_reply' condition that goes beyond the schema's terse wording. It leaves account_id, limit, include_closed and reminder_id provenance to the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names the resource (the user's reminders about a chat) and the three supported actions (create, list, cancel) with the key create parameters spelled out. It also implicitly distinguishes itself from messaging siblings by stating reminders are kept locally and 'Nothing goes to WhatsApp'. It stops short of naming a specific sibling tool it supersedes, so not a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It clarifies the two scheduling modes (after_hours vs due_at) and explains when the 'no_reply' condition fires, with a concrete natural-language example. However, it never states when an agent should pick this tool over a nearby alternative such as scheduled_messages, nor does it state prerequisites for cancel (a reminder_id from create or list). Usage context is implied rather than prescribed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
scheduled_messagesList or cancel scheduled WhatsApp messagesAIdempotent
The account's scheduled messages: list (waiting ones soonest first, then the week's sent, missed, failed and cancelled ones) or cancel one by schedule_id before it goes. To schedule one, send_message with send_at, then confirm_send. Tell the user about every missed or failed one.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| action | No | list | |
| account_id | No | ||
| schedule_id | No | cancel: from the list or confirm_send | |
| include_closed | No | list: the week's sent, missed, failed and cancelled ones too |
Output Schema
| Name | Required | Description |
|---|---|---|
| count | Yes | |
| action | Yes | |
| cancelled | No | |
| scheduled | Yes | |
| account_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already indicate this is not read-only because cancellation is possible, and the description adds useful behavior: listing order, cancellation before send, and a user-notification requirement for missed/failed messages. It does not contradict the annotations, though it leaves permission and failure behavior for cancellation unstated.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded: it presents the list/cancel choice first, then the scheduling alternative, then the notification requirement. Every sentence adds operational value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-action tool with an output schema, this is largely complete: it covers what list returns, how cancel is targeted, and how scheduling relates to sibling tools. The main gap is that limit and account_id are not discussed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 40%, so the description should compensate more. It clarifies action modes, schedule_id for cancellation, and include_closed via the week’s sent/missed/failed/cancelled items, but it does not explain limit or account_id.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states specific verbs and resource: list or cancel scheduled WhatsApp messages. It distinguishes itself from scheduling siblings by directing users to send_message with send_at followed by confirm_send.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explains both modes explicitly: use list to see scheduled messages and cancel with schedule_id before sending. It also names the alternative workflow for creating a scheduled message and instructs the agent to tell the user about missed or failed messages.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
searchSearch WhatsApp messagesBRead-onlyIdempotent
Find by meaning and words, with nearby source contexts. Use the question and known context, never guessed filters. Auto: exact codes/quoted literals; words: substrings. Check corrections; assessment flags ambiguity. Cite the supporting message.
| Name | Required | Description | Default |
|---|---|---|---|
| tag | No | Only chats with people filed under this tag | |
| from | No | "me", a number, an id, or a name only one person has | |
| limit | No | ||
| match | No | auto: questions by meaning, codes/quotes by words | auto |
| query | Yes | ||
| since | No | ISO date or time | |
| until | No | ISO date or time | |
| before | No | Older lexical matches; auto uses words with a cursor | |
| chat_id | No | Chat id, or a phone number | |
| full_text | No | Each message's text whole; a list cuts long ones otherwise | |
| account_id | No | ||
| include_context | No | Nearby sources for the best five hits |
Output Schema
| Name | Required | Description |
|---|---|---|
| mode | Yes | keyword_fallback: meaning search could not run, see recall_unavailable |
| sync | Yes | |
| count | Yes | |
| index | No | |
| notes | No | Caveats to act on or tell the user |
| query | Yes | |
| contexts | No | |
| coverage | No | null: it could not be counted |
| messages | Yes | |
| freshness | Yes | |
| account_id | Yes | |
| assessment | Yes | |
| next_before | No | |
| scan_capped | No | Older matches may be missing: narrow the search |
| from_resolved | No | |
| private_omitted | No | Matches from people tagged #private, left out: chat_id or from shows them |
| searched_back_to | No | Older messages were not searched: narrow the search |
| recall_unavailable | No | |
| changed_during_read | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive, open-world behavior, so the safety profile is covered. The description adds real behavioral signal beyond that: results include nearby source contexts, come with 'corrections', and carry an 'assessment' that flags ambiguity — though it never says what these look like or how large results are.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is short and contains no filler, but the telegraphic fragments ('Check corrections; assessment flags ambiguity') and the trailing agent instruction 'Cite the supporting message' make it read as shorthand notes rather than front-loaded prose. Compact but choppy and harder to parse than necessary.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values need no explanation, and annotations carry the safety profile. However, for a 12-parameter search tool the description leaves the time filters, cursor paging via 'before', and account scoping entirely to the schema, so it is only adequately complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 75% with 12 parameters, so the baseline is 3. The description does add meaning for 'match' ('words: substrings', exact codes/quoted literals) and rules out guessed tag/from filters, but it says nothing about limit, since/until, chat_id, account_id, full_text, or the 'before' cursor.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The verb 'Find' plus 'by meaning and words' establishes this as a hybrid semantic/lexical message search, which is distinct from read_messages or list_chats. The resource (messages) is only implicit via the title, so it is clear but not fully self-contained.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Use the question and known context, never guessed filters' gives a query-construction rule, and the auto/words split hints at mode choice, but there is no explicit when-to-use-this-vs-siblings guidance (e.g. versus get_message or read_messages). Usage is implied rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
send_messageDraft a WhatsApp messageA
Drafts text, media, polls, locations, forwards; sends nothing. Call it as soon as you have recipient and text: it returns draft_id and preview (recipient, number, exact text). Show that preview; confirm_send only on a yes to this text and recipient — a send in the same request is that yes.
| Name | Required | Description | Default |
|---|---|---|---|
| as | No | Media: a plain document, a voice note, a looping GIF | |
| url | No | Media: public http(s) URL | |
| text | Yes | The message, or the caption, poll question or place name; "" for a forward, a voice note or audio | |
| address | No | Location: shown under the name | |
| chat_id | Yes | Chat id, or a phone number | |
| forward | No | Forward this message; text "" | |
| options | No | Poll answers | |
| send_at | No | Send later: "2026-10-12T09:00" in time_zone, or with an offset; 1 minute to 365 days ahead | |
| latitude | No | ||
| reply_to | No | ||
| file_path | No | Media: absolute path on the machine running wazap | |
| longitude | No | ||
| time_zone | No | IANA zone for send_at, e.g. "Europe/Bucharest"; the server's by default | |
| account_id | No | ||
| mention_ids | No | Chat ids to @-mention; write @<number> in text for each | |
| multi_select | No | Poll: several answers allowed |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds substantial context beyond the annotations: no message leaves the system, the call returns draft_id plus a preview covering recipient, number and exact text, and the preview must be shown before confirm_send. It does not cover rate limits or per-media-type side effects, so it stops short of 5, but the highest-risk behavior (accidental send) is fully disclosed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two dense sentences, front-loaded with the non-sending guarantee before the workflow. Every clause carries instruction the agent needs — the trigger condition, the return payload, and the confirmation gate — with no restatement of the title or schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 16-parameter drafting tool with no output schema, the description supplies the missing return-value summary (draft_id and preview) and the confirmation protocol, which is the critical gap. It is slightly thin on the scheduled-send and mention paths, though those are covered by schema descriptions.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 75% and the schema already documents per-parameter meaning including the empty-text convention for forwards, so the baseline of 3 applies. The description only names the two required inputs in passing and adds nothing about send_at scheduling, time_zone, mention_ids or account_id.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb and enumerated resource types ("Drafts text, media, polls, locations, forwards") and immediately bounds scope with "sends nothing." That clause alone separates it from the sibling confirm_send and edit_message without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit trigger ("Call it as soon as you have recipient and text") and an explicit routing rule to the alternative ("confirm_send only on a yes to this text and recipient"). It even resolves an ambiguous case — a send in the same request counts as the yes — leaving nothing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wait_for_messagesWait for new WhatsApp messagesARead-onlyIdempotent
Wait for messages from other people, up to timeout_seconds, and return them with a cursor: pass it to the next call so nothing that lands between calls is missed. addressed_to_me wakes only for direct messages, mentions and replies to the user. For agents that stay on the line.
| Name | Required | Description | Default |
|---|---|---|---|
| cursor | No | From the previous call | |
| chat_id | No | Chat id, or a phone number | |
| account_id | No | ||
| addressed_to_me | No | ||
| timeout_seconds | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| count | Yes | |
| cursor | Yes | Pass to the next call |
| messages | Yes | |
| timed_out | Yes | |
| account_id | Yes | |
| cursor_reset | Yes | The cursor was from another run; the wait started now |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover readOnly, idempotent, open-world and non-destructive, so the safety profile is done. The description adds genuinely non-obvious behavior: the call blocks for up to timeout_seconds, returns a cursor whose reuse prevents gaps between calls, and addressed_to_me narrows wake-ups to DMs, mentions and replies. It omits what is returned when the timeout elapses with no messages, which is the main behavioral gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action and its timing constraint, then the cursor contract, then the filter. Three dense clauses with no repetition of annotations. 'For agents that stay on the line' is a slightly decorative closer, but it frames the intended usage rather than wasting space.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Return values are covered by the existing output schema, and the crucial cross-call cursor contract is spelled out, which is what an agent needs to loop correctly. Missing only the empty-timeout outcome and any guidance on chat_id/account_id scoping; for a 5-param, zero-required tool that is close to complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 40%, so the description must compensate, and it does for three of five params: cursor provenance, addressed_to_me's exact semantics, and timeout_seconds as an upper bound. chat_id and account_id are left to the schema (chat_id has a description there, account_id has none), which is a minor shortfall rather than a blocker.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('wait for messages'), plus scoping ('from other people, up to timeout_seconds') and a distinguishing long-poll mechanism (cursor returned and passed back). It does not name the close siblings read_messages or catch_up, so an agent must infer the difference, but the 'wait/block' semantics separate it from the fetch tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'For agents that stay on the line' and 'pass it to the next call so nothing... is missed' imply the streaming/long-poll use case, but there is no explicit when-to-use-vs-alternatives guidance — nothing says to prefer read_messages for a one-shot fetch or catch_up for backlog. Usage is inferable rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
23 tool updates
v1.6.0- Changed
catch_up3 fields changed- removed
Input schema / properties / account_id / descriptionRemoved value: -"Account id" - added
Output schema / properties / direct / items / properties / tagsAdded value: +{ + "items": { + "type": "string" + }, + "type": "array" +} - added
Output schema / properties / waiting / items / properties / tagsAdded value: +{ + "items": { + "type": "string" + }, + "type": "array" +}
- Changed
confirm_send1 field changed- removed
Input schema / properties / account_id / descriptionRemoved value: -"Account id"
- Changed
delete_message1 field changed- removed
Input schema / properties / account_id / descriptionRemoved value: -"Account id"
- Changed
edit_message1 field changed- removed
Input schema / properties / account_id / descriptionRemoved value: -"Account id"
- Changed
find_contact1 field changed- removed
Input schema / properties / account_id / descriptionRemoved value: -"Account id"
- Changed
get_group_info1 field changed- removed
Input schema / properties / account_id / descriptionRemoved value: -"Account id"
- Changed
get_media1 field changed- removed
Input schema / properties / account_id / descriptionRemoved value: -"Account id"
- Changed
get_message1 field changed- removed
Input schema / properties / account_id / descriptionRemoved value: -"Account id"
- Changed
get_status1 field changed- removed
Input schema / properties / account_id / descriptionRemoved value: -"Account id"
- Changed
learn1 field changed- removed
Input schema / properties / account_id / descriptionRemoved value: -"Account id"
- Changed
link_account1 field changed- removed
Input schema / properties / account_id / descriptionRemoved value: -"Account id"
- Changed
list_chats3 fields changed- removed
Input schema / properties / account_id / descriptionRemoved value: -"Account id" - added
Input schema / properties / tagAdded value: +{ + "description": "Only chats with people filed under this tag", + "maxLength": 40, + "minLength": 1, + "type": "string" +} - added
Output schema / properties / tagAdded value: +{ + "type": "string" +}
- Changed
list_contacts1 field changed- removed
Input schema / properties / account_id / descriptionRemoved value: -"Account id"
- Changed
manage_chat2 fields changed- removed
Input schema / properties / account_id / descriptionRemoved value: -"Account id" - added
Input schema / properties / confirmation_idAdded value: +{ + "description": "From preview; omit message/duration options", + "maxLength": 64, + "minLength": 1, + "type": "string" +}
- Changed
manage_group1 field changed- removed
Input schema / properties / account_id / descriptionRemoved value: -"Account id"
- Changed
react_to_message1 field changed- removed
Input schema / properties / account_id / descriptionRemoved value: -"Account id"
- Changed
read_messages1 field changed- removed
Input schema / properties / account_id / descriptionRemoved value: -"Account id"
- Changed
remember7 fields changed- removed
Input schema / properties / account_id / descriptionRemoved value: -"Account id" - added
Input schema / properties / chat_id / anyOfAdded value: +[ + { + "description": "Chat id, or a phone number", + "minLength": 1, + "type": "string" + }, + { + "items": { + "$ref": "#/properties/chat_id/anyOf/0" + }, + "maxItems": 50, + "minItems": 1, + "type": "array" + } +] - changed
Input schema / properties / chat_id / descriptionPrevious value: -"Chat id, or a phone number"New value: +"Several: tags and fields only" - removed
Input schema / properties / chat_id / minLengthRemoved value: -1 - removed
Input schema / properties / chat_id / typeRemoved value: -"string" - added
Output schema / properties / peopleAdded value: +{ + "description": "Several chat_ids: each one's card", + "items": { + "additionalProperties": true, + "properties": {}, + "type": "object" + }, + "type": "array" +} - changed
Output schema / requiredPrevious value: -[ - "chat_id", - "name", - "account_id" -]New value: +[ + "account_id" +]
- Changed
reminder1 field changed- removed
Input schema / properties / account_id / descriptionRemoved value: -"Account id"
- Changed
scheduled_messages1 field changed- removed
Input schema / properties / account_id / descriptionRemoved value: -"Account id"
- Changed
search21 fields changed- removed
Input schema / properties / account_id / descriptionRemoved value: -"Account id" - added
Input schema / properties / beforeAdded value: +{ + "description": "Older lexical matches; auto uses words with a cursor", + "minLength": 5, + "type": "string" +} - added
Input schema / properties / include_contextAdded value: +{ + "default": true, + "description": "Nearby sources for the best five hits", + "type": "boolean" +} - changed
Input schema / properties / match / defaultPrevious value: -"hybrid"New value: +"auto" - changed
Input schema / properties / match / descriptionPrevious value: -"\"words\": only messages holding the words"New value: +"auto: questions by meaning, codes/quotes by words" - changed
Input schema / properties / match / enumPrevious value: -[ - "hybrid", - "words" -]New value: +[ + "auto", + "hybrid", + "words" +] - added
Input schema / properties / tagAdded value: +{ + "description": "Only chats with people filed under this tag", + "maxLength": 40, + "minLength": 1, + "type": "string" +} - added
Output schema / properties / assessmentAdded value: +{ + "additionalProperties": false, + "properties": { + "note": { + "type": "string" + }, + "state": { + "enum": [ + "no_matches", + "ambiguous", + "candidates" + ], + "type": "string" + } + }, + "required": [ + "state", + "note" + ], + "type": "object" +} - added
Output schema / properties / changed_during_readAdded value: +{ + "type": "boolean" +} - added
Output schema / properties / contextsAdded value: +{ + "items": { + "additionalProperties": false, + "properties": { + "anchor_id": { + "type": "string" + }, + "bounded": { + "const": true, + "type": "boolean" + }, + "messages": { + "items": { + "additionalProperties": true, + "properties": { + "chat_id": { + "type": "string" + }, + "message_id": { + "type": "string" + }, + "text": { + "type": "string" + }, + "timestamp": { + "type": "string" + } + }, + "required": [ + "message_id", + "chat_id", + "text", + "timestamp" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "anchor_id", + "messages", + "bounded" + ], + "type": "object" + }, + "type": "array" +} - added
Output schema / properties / messages / items / properties / chat_id / $refAdded value: +"#/properties/contexts/items/properties/messages/items/properties/chat_id" - removed
Output schema / properties / messages / items / properties / chat_id / typeRemoved value: -"string" - added
Output schema / properties / messages / items / properties / message_id / $refAdded value: +"#/properties/contexts/items/properties/messages/items/properties/message_id" - removed
Output schema / properties / messages / items / properties / message_id / typeRemoved value: -"string" - added
Output schema / properties / messages / items / properties / rank_scoreAdded value: +{ + "type": "number" +} - added
Output schema / properties / messages / items / properties / text / $refAdded value: +"#/properties/contexts/items/properties/messages/items/properties/text" - removed
Output schema / properties / messages / items / properties / text / typeRemoved value: -"string" - added
Output schema / properties / messages / items / properties / timestamp / $refAdded value: +"#/properties/contexts/items/properties/messages/items/properties/timestamp" - removed
Output schema / properties / messages / items / properties / timestamp / typeRemoved value: -"string" - added
Output schema / properties / next_beforeAdded value: +{ + "type": [ + "string", + "null" + ] +} - changed
Output schema / requiredPrevious value: -[ - "query", - "mode", - "count", - "messages", - "freshness", - "sync", - "account_id" -]New value: +[ + "query", + "mode", + "count", + "assessment", + "messages", + "freshness", + "sync", + "account_id" +]
- Changed
send_message1 field changed- removed
Input schema / properties / account_id / descriptionRemoved value: -"Account id"
- Changed
wait_for_messages1 field changed- removed
Input schema / properties / account_id / descriptionRemoved value: -"Account id"
1 tool update
v1.4.2- Changed
list_chats2 fields changed- added
Input schema / properties / cursorAdded value: +{ + "description": "Opaque next_cursor from the preceding page; keep the same filter", + "maxLength": 512, + "type": "string" +} - added
Output schema / properties / next_cursorAdded value: +{ + "type": [ + "string", + "null" + ] +}
9 tool updates
v1.4.0- Changed
confirm_send1 field changed- changed
Input schema / properties / draft_id / descriptionPrevious value: -"From send_message"New value: +"From send_message; one with send_at is scheduled, not sent"
- Changed
get_media1 field changed- added
Output schema / properties / sourceAdded value: +{ + "description": "kept: the copy wazap kept when it arrived; whatsapp: downloaded now", + "enum": [ + "kept", + "whatsapp" + ], + "type": "string" +}
- Changed
get_status1 field changed- added
Input schema / properties / include_pictureAdded value: +{ + "default": false, + "description": "Add picture_url, the account's own profile photo (the link expires)", + "type": "boolean" +}
- Changed
list_chats1 field changed- added
Input schema / properties / include_picturesAdded value: +{ + "default": false, + "description": "Add picture_url, each chat's profile photo (links expire)", + "type": "boolean" +}
- Changed
read_messages1 field changed- added
Input schema / properties / full_textAdded value: +{ + "description": "Each message's text whole; a list cuts long ones otherwise", + "type": "boolean" +}
- Added
reminder - Added
scheduled_messages - Changed
search1 field changed- added
Input schema / properties / full_textAdded value: +{ + "description": "Each message's text whole; a list cuts long ones otherwise", + "type": "boolean" +}
- Changed
send_message2 fields changed- added
Input schema / properties / send_atAdded value: +{ + "description": "Send later: \"2026-10-12T09:00\" in time_zone, or with an offset; 1 minute to 365 days ahead", + "maxLength": 40, + "minLength": 10, + "type": "string" +} - added
Input schema / properties / time_zoneAdded value: +{ + "description": "IANA zone for send_at, e.g. \"Europe/Bucharest\"; the server's by default", + "maxLength": 64, + "minLength": 1, + "type": "string" +}
1 tool update
v1.2.0- Added
list_contacts
43 tool updates
v1.0.3- Added
catch_up - Changed
confirm_send2 fields changed- changed
Input schema / properties / account_id / descriptionPrevious value: -"Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account."New value: +"Account id" - changed
Input schema / properties / draft_id / descriptionPrevious value: -"The draft_id returned by a send_* tool"New value: +"From send_message"
- Removed
create_group - Changed
delete_message4 fields changed- changed
Input schema / properties / account_id / descriptionPrevious value: -"Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account."New value: +"Account id" - removed
Input schema / properties / for_everyone / descriptionRemoved value: -"Required. true retracts it for everyone in the chat; false deletes it for the linked account only" - removed
Input schema / properties / message_id / descriptionRemoved value: -"Message id from read_messages / search_messages / get_message, e.g. \"false_4072...@s.whatsapp.net_3EB0...\"" - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "account_id": { + "type": "string" + }, + "for_everyone": { + "type": "boolean" + }, + "message_id": { + "type": "string" + } + }, + "required": [ + "message_id", + "for_everyone", + "account_id" + ], + "type": "object" +}
- Removed
download_media - Changed
edit_message4 fields changed- changed
Input schema / properties / account_id / descriptionPrevious value: -"Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account."New value: +"Account id" - removed
Input schema / properties / message_id / descriptionRemoved value: -"A message the linked account sent" - removed
Input schema / properties / text / descriptionRemoved value: -"The replacement text" - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "account_id": { + "type": "string" + }, + "chat_id": { + "type": "string" + }, + "message_id": { + "type": "string" + }, + "text": { + "type": "string" + }, + "timestamp": { + "type": "string" + } + }, + "required": [ + "message_id", + "chat_id", + "text", + "timestamp", + "account_id" + ], + "type": "object" +}
- Added
find_contact - Removed
forward_message - Removed
get_contact - Changed
get_group_info3 fields changed- changed
Input schema / properties / account_id / descriptionPrevious value: -"Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account."New value: +"Account id" - changed
Input schema / properties / group_id / descriptionPrevious value: -"Group chat id (\"<id>@g.us\")"New value: +"<id>@g.us" - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "account_id": { + "type": "string" + }, + "announcement_only": { + "type": "boolean" + }, + "chat_id": { + "type": "string" + }, + "community": { + "additionalProperties": false, + "properties": { + "is_community": { + "type": "boolean" + }, + "parent_group_id": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "is_community", + "parent_group_id" + ], + "type": "object" + }, + "created_at": { + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "disappearing_seconds": { + "type": "number" + }, + "i_am_admin": { + "type": "boolean" + }, + "info_locked": { + "type": "boolean" + }, + "invite_link": { + "type": "string" + }, + "join_approval": { + "type": "boolean" + }, + "member_add_mode": { + "enum": [ + "admins", + "all" + ], + "type": "string" + }, + "name": { + "type": "string" + }, + "owner": { + "type": [ + "string", + "null" + ] + }, + "participant_count": { + "type": "number" + }, + "participants": { + "items": { + "additionalProperties": false, + "properties": { + "contact_id": { + "type": "string" + }, + "is_admin": { + "type": "boolean" + }, + "name": { + "type": "string" + } + }, + "required": [ + "contact_id", + "name", + "is_admin" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "chat_id", + "name", + "description", + "owner", + "created_at", + "participant_count", + "participants", + "announcement_only", + "i_am_admin", + "info_locked", + "member_add_mode", + "join_approval", + "disappearing_seconds", + "account_id" + ], + "type": "object" +}
- Added
get_media - Changed
get_message3 fields changed- changed
Input schema / properties / account_id / descriptionPrevious value: -"Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account."New value: +"Account id" - removed
Input schema / properties / message_id / descriptionRemoved value: -"Message id from read_messages / search_messages / get_message, e.g. \"false_4072...@s.whatsapp.net_3EB0...\"" - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "properties": { + "account_id": { + "type": "string" + }, + "chat_id": { + "type": "string" + }, + "message_id": { + "type": "string" + }, + "text": { + "type": "string" + }, + "timestamp": { + "type": "string" + } + }, + "required": [ + "message_id", + "chat_id", + "text", + "timestamp", + "account_id" + ], + "type": "object" +}
- Removed
get_recent_messages - Changed
get_status1 field changed- changed
Input schema / properties / account_id / descriptionPrevious value: -"Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account."New value: +"Account id"
- Removed
get_stories - Removed
get_unanswered - Removed
join_group - Changed
learn1 field changed- changed
Input schema / properties / account_id / descriptionPrevious value: -"Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account."New value: +"Account id"
- Changed
link_account2 fields changed- changed
Input schema / properties / account_id / descriptionPrevious value: -"Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account."New value: +"Account id" - changed
Input schema / properties / phone / descriptionPrevious value: -"International format, e.g. +15550100"New value: +"e.g. +15550100"
- Removed
list_accounts - Changed
list_chats4 fields changed- changed
Input schema / properties / account_id / descriptionPrevious value: -"Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account."New value: +"Account id" - changed
Input schema / properties / filter / descriptionPrevious value: -"Which chats to list; \"all\" (default) excludes archived ones"New value: +"\"all\" leaves out archived" - removed
Input schema / properties / limit / descriptionRemoved value: -"Maximum number of chats (1-100)" - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "account_id": { + "type": "string" + }, + "chats": { + "items": { + "additionalProperties": true, + "properties": { + "chat_id": { + "type": "string" + }, + "last_message": { + "anyOf": [ + { + "additionalProperties": true, + "properties": { + "private": { + "const": true, + "description": "Tagged #private: no words", + "type": "boolean" + } + }, + "type": "object" + }, + { + "type": "null" + } + ] + }, + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "unread_count": { + "type": "number" + } + }, + "required": [ + "chat_id", + "name", + "type", + "unread_count" + ], + "type": "object" + }, + "type": "array" + }, + "count": { + "type": "number" + }, + "filter": { + "type": "string" + }, + "sync": { + "type": "string" + } + }, + "required": [ + "filter", + "count", + "chats", + "sync", + "account_id" + ], + "type": "object" +}
- Changed
manage_chat6 fields changed- changed
Input schema / properties / account_id / descriptionPrevious value: -"Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account."New value: +"Account id" - removed
Input schema / properties / action / descriptionRemoved value: -"What to do with the chat" - changed
Input schema / properties / chat_id / descriptionPrevious value: -"Chat id as returned by another tool (\"<digits>@s.whatsapp.net\" or \"<id>@g.us\"), or a phone number in international format"New value: +"Chat id, or a phone number" - changed
Input schema / properties / message_id / descriptionPrevious value: -"The message for pin_message, unpin_message, star_message and unstar_message; it must be in chat_id"New value: +"pin_message, star_message and their undo; in chat_id" - changed
Input schema / properties / mute_hours / descriptionPrevious value: -"Hours to mute, default 8; only used by \"mute\""New value: +"mute: 8 by default" - changed
Input schema / properties / pin_hours / descriptionPrevious value: -"How long pin_message keeps the message pinned: 24, 168 (default) or 720 hours"New value: +"pin_message: 168 by default"
- Changed
manage_group13 fields changed- changed
Input schema / properties / account_id / descriptionPrevious value: -"Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account."New value: +"Account id" - removed
Input schema / properties / action / descriptionRemoved value: -"Group action to perform" - changed
Input schema / properties / action / enumPrevious value: -[ - "add", - "remove", - "promote", - "demote", - "leave", - "set_subject", - "set_description", - "set_picture", - "remove_picture", - "get_invite_link", - "revoke_invite_link", - "list_join_requests", - "approve_join_requests", - "reject_join_requests", - "set_announcement_only", - "set_info_locked", - "set_add_mode", - "set_join_approval", - "set_disappearing" -]New value: +[ + "create", + "join", + "add", + "remove", + "promote", + "demote", + "leave", + "set_subject", + "set_description", + "set_picture", + "remove_picture", + "get_invite_link", + "revoke_invite_link", + "list_join_requests", + "approve_join_requests", + "reject_join_requests", + "set_announcement_only", + "set_info_locked", + "set_add_mode", + "set_join_approval", + "set_disappearing" +] - added
Input schema / properties / confirmAdded value: +{ + "default": false, + "description": "join: true joins, after the user said yes to the preview", + "type": "boolean" +} - changed
Input schema / properties / file_path / descriptionPrevious value: -"set_picture: absolute path of a local JPEG, PNG or WebP"New value: +"set_picture: local JPEG, PNG or WebP" - changed
Input schema / properties / group_id / descriptionPrevious value: -"Group chat id (\"<id>@g.us\")"New value: +"\"<id>@g.us\"; every action but create and join" - added
Input schema / properties / inviteAdded value: +{ + "description": "join: a chat.whatsapp.com link or its code", + "maxLength": 512, + "minLength": 1, + "type": "string" +} - added
Input schema / properties / message_idAdded value: +{ + "description": "join: an invite message instead", + "minLength": 5, + "type": "string" +} - changed
Input schema / properties / participant_ids / descriptionPrevious value: -"Targets of add/remove/promote/demote/approve_join_requests/reject_join_requests"New value: +"create, add, remove, promote, demote, approve or reject" - changed
Input schema / properties / url / descriptionPrevious value: -"set_picture: public http(s) URL to fetch and use as the photo"New value: +"set_picture: public image URL" - changed
Input schema / properties / value / descriptionPrevious value: -"New subject or description; \"on\"/\"off\" for set_announcement_only, set_info_locked, set_join_approval; \"admins\"/\"all\" for set_add_mode; \"off\"/\"24h\"/\"7d\"/\"90d\" for set_disappearing"New value: +"The name (create, set_subject) or description; \"on\"/\"off\"; set_add_mode \"admins\"/\"all\"; set_disappearing \"off\"/\"24h\"/\"7d\"/\"90d\"" - changed
Input schema / requiredPrevious value: -[ - "group_id", - "action" -]New value: +[ + "action" +] - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "account_id": { + "type": "string" + }, + "action": { + "type": "string" + }, + "applied": { + "type": "string" + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "group_id": { + "type": [ + "string", + "null" + ] + }, + "invite_link": { + "type": "string" + }, + "join_approval": { + "type": [ + "boolean", + "null" + ] + }, + "join_requests": { + "items": { + "additionalProperties": true, + "properties": {}, + "type": "object" + }, + "type": "array" + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "next": { + "description": "join preview: the step after the user's yes", + "type": "string" + }, + "participant_count": { + "type": [ + "number", + "null" + ] + }, + "participants": { + "items": { + "additionalProperties": false, + "properties": { + "id": { + "type": "string" + }, + "reason": { + "type": "string" + }, + "status": { + "enum": [ + "ok", + "invite_needed", + "failed" + ], + "type": "string" + } + }, + "required": [ + "id", + "status" + ], + "type": "object" + }, + "type": "array" + }, + "profile_pic_url": { + "type": [ + "string", + "null" + ] + }, + "status": { + "description": "join: preview joins nothing", + "enum": [ + "preview", + "joined", + "pending_approval" + ], + "type": "string" + } + }, + "required": [ + "action", + "group_id", + "account_id" + ], + "type": "object" +}
- Removed
mark_handled - Changed
react_to_message4 fields changed- changed
Input schema / properties / account_id / descriptionPrevious value: -"Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account."New value: +"Account id" - removed
Input schema / properties / emoji / descriptionRemoved value: -"A single emoji such as \"👍\", or \"\" to remove your reaction" - removed
Input schema / properties / message_id / descriptionRemoved value: -"Message id from read_messages / search_messages / get_message, e.g. \"false_4072...@s.whatsapp.net_3EB0...\"" - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "account_id": { + "type": "string" + }, + "emoji": { + "type": "string" + }, + "message_id": { + "type": "string" + } + }, + "required": [ + "message_id", + "emoji", + "account_id" + ], + "type": "object" +}
- Changed
read_messages8 fields changed- changed
Input schema / properties / account_id / descriptionPrevious value: -"Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account."New value: +"Account id" - changed
Input schema / properties / before / descriptionPrevious value: -"Return the messages immediately older than this message_id"New value: +"The oldest message_id you have" - changed
Input schema / properties / chat_id / descriptionPrevious value: -"Chat id as returned by another tool (\"<digits>@s.whatsapp.net\" or \"<id>@g.us\"), or a phone number in international format"New value: +"Chat id from another tool, a phone number, or \"status\" for stories" - added
Input schema / properties / hoursAdded value: +{ + "description": "\"status\" only: how far back, 24 by default", + "maximum": 24, + "minimum": 1, + "type": "integer" +} - changed
Input schema / properties / include_previews / descriptionPrevious value: -"Attach a small JPEG of each photo, newest first, up to 12 per call, so you can see what was sent: the preview WhatsApp shipped when there is one, otherwise the photo is downloaded once and shrunk on the machine running wazap"New value: +"Attach a small image of each photo, up to 12" - removed
Input schema / properties / limit / descriptionRemoved value: -"Maximum number of messages (1-200)" - changed
Input schema / properties / types / descriptionPrevious value: -"Keep only these message types; omit for every type. The limit counts matching messages, so [\"call\"] returns that many calls, not that many messages of which some are calls."New value: +"Only these types; limit counts them, so [\"call\"] gives that many calls" - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "account_id": { + "type": "string" + }, + "chat_id": { + "type": "string" + }, + "count": { + "type": "number" + }, + "hours": { + "type": "number" + }, + "messages": { + "items": { + "additionalProperties": true, + "properties": { + "chat_id": { + "type": "string" + }, + "message_id": { + "type": "string" + }, + "private": { + "const": true, + "description": "Tagged #private: no words", + "type": "boolean" + }, + "text": { + "type": "string" + }, + "timestamp": { + "type": "string" + } + }, + "required": [ + "message_id", + "chat_id", + "text", + "timestamp" + ], + "type": "object" + }, + "type": "array" + }, + "notes": { + "description": "Caveats to act on or tell the user", + "items": { + "type": "string" + }, + "type": "array" + }, + "older": { + "additionalProperties": false, + "description": "before ran past the local history: the phone was asked, and sent this many", + "properties": { + "asked_phone": { + "const": true, + "type": "boolean" + }, + "received": { + "type": "number" + } + }, + "required": [ + "asked_phone", + "received" + ], + "type": "object" + }, + "omitted": { + "description": "Older stories left out by limit", + "type": "number" + }, + "preview_count": { + "type": "number" + }, + "sync": { + "type": "string" + }, + "types": { + "items": { + "type": "string" + }, + "type": "array" + }, + "unconfirmed_sends": { + "description": "Sends WhatsApp has not echoed yet: outcome unknown, not failed", + "items": { + "additionalProperties": false, + "properties": { + "draft_id": { + "type": "string" + }, + "handed_at": { + "type": "string" + }, + "state": { + "const": "unknown", + "type": "string" + }, + "text": { + "type": "string" + } + }, + "required": [ + "draft_id", + "text", + "handed_at", + "state" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "chat_id", + "count", + "preview_count", + "messages", + "sync", + "account_id" + ], + "type": "object" +}
- Removed
recall - Added
remember - Removed
remove_contact - Removed
save_contact - Added
search - Removed
search_contacts - Removed
search_messages - Removed
send_location - Removed
send_media - Changed
send_message15 fields changed- changed
Input schema / properties / account_id / descriptionPrevious value: -"Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account."New value: +"Account id" - added
Input schema / properties / addressAdded value: +{ + "description": "Location: shown under the name", + "maxLength": 500, + "type": "string" +} - added
Input schema / properties / asAdded value: +{ + "description": "Media: a plain document, a voice note, a looping GIF", + "enum": [ + "document", + "voice", + "gif" + ], + "type": "string" +} - changed
Input schema / properties / chat_id / descriptionPrevious value: -"Chat id as returned by another tool (\"<digits>@s.whatsapp.net\" or \"<id>@g.us\"), or a phone number in international format"New value: +"Chat id, or a phone number" - added
Input schema / properties / file_pathAdded value: +{ + "description": "Media: absolute path on the machine running wazap", + "minLength": 1, + "type": "string" +} - added
Input schema / properties / forwardAdded value: +{ + "$ref": "#/properties/reply_to", + "description": "Forward this message; text \"\"" +} - added
Input schema / properties / latitudeAdded value: +{ + "maximum": 90, + "minimum": -90, + "type": "number" +} - added
Input schema / properties / longitudeAdded value: +{ + "maximum": 180, + "minimum": -180, + "type": "number" +} - changed
Input schema / properties / mention_ids / descriptionPrevious value: -"Chat ids to @-mention; write @<number> in the text for each, or wazap adds it at the end"New value: +"Chat ids to @-mention; write @<number> in text for each" - added
Input schema / properties / multi_selectAdded value: +{ + "description": "Poll: several answers allowed", + "type": "boolean" +} - added
Input schema / properties / optionsAdded value: +{ + "description": "Poll answers", + "items": { + "maxLength": 100, + "minLength": 1, + "type": "string" + }, + "maxItems": 12, + "minItems": 2, + "type": "array" +} - removed
Input schema / properties / reply_to / descriptionRemoved value: -"Quote-reply to this message" - changed
Input schema / properties / text / descriptionPrevious value: -"The message text"New value: +"The message, or the caption, poll question or place name; \"\" for a forward, a voice note or audio" - removed
Input schema / properties / text / minLengthRemoved value: -1 - added
Input schema / properties / urlAdded value: +{ + "description": "Media: public http(s) URL", + "format": "uri", + "type": "string" +}
- Removed
send_poll - Removed
set_contact_note - Removed
set_profile_picture - Removed
sync_contacts - Removed
transcribe_audio - Removed
update_contact_details - Changed
wait_for_messages6 fields changed- changed
Input schema / properties / account_id / descriptionPrevious value: -"Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account."New value: +"Account id" - removed
Input schema / properties / addressed_to_me / descriptionRemoved value: -"Only direct messages, @-mentions of the user and replies to the user's messages" - changed
Input schema / properties / chat_id / descriptionPrevious value: -"Only messages in this chat"New value: +"Chat id, or a phone number" - changed
Input schema / properties / cursor / descriptionPrevious value: -"The cursor returned by the previous call"New value: +"From the previous call" - removed
Input schema / properties / timeout_seconds / descriptionRemoved value: -"How long to wait (1-55 s)" - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "account_id": { + "type": "string" + }, + "count": { + "type": "number" + }, + "cursor": { + "description": "Pass to the next call", + "type": "string" + }, + "cursor_reset": { + "description": "The cursor was from another run; the wait started now", + "type": "boolean" + }, + "messages": { + "items": { + "additionalProperties": true, + "properties": { + "chat_id": { + "type": "string" + }, + "message_id": { + "type": "string" + }, + "private": { + "const": true, + "description": "Tagged #private: no words", + "type": "boolean" + }, + "text": { + "type": "string" + }, + "timestamp": { + "type": "string" + } + }, + "required": [ + "message_id", + "chat_id", + "text", + "timestamp" + ], + "type": "object" + }, + "type": "array" + }, + "timed_out": { + "type": "boolean" + } + }, + "required": [ + "count", + "messages", + "cursor", + "timed_out", + "cursor_reset", + "account_id" + ], + "type": "object" +}
13 tool updates
v0.21.0- Changed
delete_message3 fields changed- removed
Input schema / properties / for_everyone / defaultRemoved value: -false - changed
Input schema / properties / for_everyone / descriptionPrevious value: -"Retract for all participants (WhatsApp supports no other kind of delete here)"New value: +"Required. true retracts it for everyone in the chat; false deletes it for the linked account only" - changed
Input schema / requiredPrevious value: -[ - "message_id" -]New value: +[ + "message_id", + "for_everyone" +]
- Changed
get_recent_messages1 field changed- changed
Input schema / properties / types / items / enumPrevious value: -[ - "text", - "image", - "video", - "audio", - "voice", - "document", - "sticker", - "location", - "contact", - "poll", - "reaction", - "deleted", - "view_once", - "call", - "system", - "unknown" -]New value: +[ + "text", + "image", + "video", + "audio", + "voice", + "document", + "sticker", + "location", + "contact", + "poll", + "reaction", + "deleted", + "view_once", + "call", + "event", + "invite", + "system", + "unknown" +]
- Added
join_group - Changed
manage_chat3 fields changed- changed
Input schema / properties / action / enumPrevious value: -[ - "archive", - "unarchive", - "pin", - "unpin", - "mute", - "unmute", - "mark_read", - "mark_unread" -]New value: +[ + "archive", + "unarchive", + "pin", + "unpin", + "mute", + "unmute", + "mark_read", + "mark_unread", + "pin_message", + "unpin_message", + "star_message", + "unstar_message", + "clear", + "delete", + "block", + "unblock" +] - added
Input schema / properties / message_idAdded value: +{ + "description": "The message for pin_message, unpin_message, star_message and unstar_message; it must be in chat_id", + "minLength": 5, + "type": "string" +} - added
Input schema / properties / pin_hoursAdded value: +{ + "description": "How long pin_message keeps the message pinned: 24, 168 (default) or 720 hours", + "enum": [ + 24, + 168, + 720 + ], + "type": "number" +}
- Changed
manage_group5 fields changed- changed
Input schema / properties / action / enumPrevious value: -[ - "add", - "remove", - "promote", - "demote", - "leave", - "set_subject", - "set_description", - "get_invite_link", - "revoke_invite_link" -]New value: +[ + "add", + "remove", + "promote", + "demote", + "leave", + "set_subject", + "set_description", + "set_picture", + "remove_picture", + "get_invite_link", + "revoke_invite_link", + "list_join_requests", + "approve_join_requests", + "reject_join_requests", + "set_announcement_only", + "set_info_locked", + "set_add_mode", + "set_join_approval", + "set_disappearing" +] - added
Input schema / properties / file_pathAdded value: +{ + "description": "set_picture: absolute path of a local JPEG, PNG or WebP", + "minLength": 1, + "type": "string" +} - changed
Input schema / properties / participant_ids / descriptionPrevious value: -"Targets of add/remove/promote/demote"New value: +"Targets of add/remove/promote/demote/approve_join_requests/reject_join_requests" - added
Input schema / properties / urlAdded value: +{ + "description": "set_picture: public http(s) URL to fetch and use as the photo", + "format": "uri", + "type": "string" +} - changed
Input schema / properties / value / descriptionPrevious value: -"New subject or description"New value: +"New subject or description; \"on\"/\"off\" for set_announcement_only, set_info_locked, set_join_approval; \"admins\"/\"all\" for set_add_mode; \"off\"/\"24h\"/\"7d\"/\"90d\" for set_disappearing"
- Changed
read_messages1 field changed- changed
Input schema / properties / types / items / enumPrevious value: -[ - "text", - "image", - "video", - "audio", - "voice", - "document", - "sticker", - "location", - "contact", - "poll", - "reaction", - "deleted", - "view_once", - "call", - "system", - "unknown" -]New value: +[ + "text", + "image", + "video", + "audio", + "voice", + "document", + "sticker", + "location", + "contact", + "poll", + "reaction", + "deleted", + "view_once", + "call", + "event", + "invite", + "system", + "unknown" +]
- Added
recall - Added
remove_contact - Added
save_contact - Changed
search_contacts3 fields changed- changed
Input schema / properties / query / descriptionPrevious value: -"Name fragment or phone number (at least 2 characters)"New value: +"Name fragment, phone number, or tag/detail text (at least 2 characters). Omit with tag to list everyone carrying it." - added
Input schema / properties / tagAdded value: +{ + "description": "Only contacts filed under this tag (\"client\"); \"#\" optional", + "minLength": 1, + "type": "string" +} - removed
Input schema / requiredRemoved value: -[ - "query" -]
- Changed
search_messages1 field changed- changed
Input schema / properties / from / descriptionPrevious value: -"Only messages this person sent: \"me\", a contact id or a phone number"New value: +"Only messages this person sent: \"me\", a phone number, a contact/chat id, or a name that resolves to exactly one person (the error names the candidates when it does not)"
- Changed
send_message1 field changed- changed
Input schema / properties / mention_ids / descriptionPrevious value: -"Chat ids to @-mention; include their names in the text yourself"New value: +"Chat ids to @-mention; write @<number> in the text for each, or wazap adds it at the end"
- Added
update_contact_details
33 tool updates
v0.15.0- Added
confirm_send - Changed
create_group1 field changed- added
Input schema / properties / account_idAdded value: +{ + "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.", + "minLength": 1, + "type": "string" +}
- Changed
delete_message1 field changed- added
Input schema / properties / account_idAdded value: +{ + "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.", + "minLength": 1, + "type": "string" +}
- Changed
download_media1 field changed- added
Input schema / properties / account_idAdded value: +{ + "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.", + "minLength": 1, + "type": "string" +}
- Changed
edit_message1 field changed- added
Input schema / properties / account_idAdded value: +{ + "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.", + "minLength": 1, + "type": "string" +}
- Changed
forward_message1 field changed- added
Input schema / properties / account_idAdded value: +{ + "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.", + "minLength": 1, + "type": "string" +}
- Changed
get_contact1 field changed- added
Input schema / properties / account_idAdded value: +{ + "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.", + "minLength": 1, + "type": "string" +}
- Changed
get_group_info1 field changed- added
Input schema / properties / account_idAdded value: +{ + "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.", + "minLength": 1, + "type": "string" +}
- Changed
get_message1 field changed- added
Input schema / properties / account_idAdded value: +{ + "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.", + "minLength": 1, + "type": "string" +}
- Changed
get_recent_messages3 fields changed- added
Input schema / properties / account_idAdded value: +{ + "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.", + "minLength": 1, + "type": "string" +} - added
Input schema / properties / compactAdded value: +{ + "default": false, + "description": "Leave out media without a caption and messages with no words in them, fold what one person sent in a row into one line, and say per chat what was left out. About half the size; use it for a routine catch-up", + "type": "boolean" +} - added
Input schema / properties / include_previewsAdded value: +{ + "default": false, + "description": "Attach a small JPEG of each photo, newest first, up to 12 per call, so you can see what was sent: the preview WhatsApp shipped when there is one, otherwise the photo is downloaded once and shrunk on the machine running wazap", + "type": "boolean" +}
- Changed
get_status2 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / account_idAdded value: +{ + "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.", + "minLength": 1, + "type": "string" +}
- Added
get_stories - Added
get_unanswered - Changed
learn2 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / account_idAdded value: +{ + "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.", + "minLength": 1, + "type": "string" +}
- Added
link_account - Added
list_accounts - Changed
list_chats1 field changed- added
Input schema / properties / account_idAdded value: +{ + "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.", + "minLength": 1, + "type": "string" +}
- Changed
manage_chat1 field changed- added
Input schema / properties / account_idAdded value: +{ + "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.", + "minLength": 1, + "type": "string" +}
- Changed
manage_group1 field changed- added
Input schema / properties / account_idAdded value: +{ + "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.", + "minLength": 1, + "type": "string" +}
- Added
mark_handled - Changed
react_to_message1 field changed- added
Input schema / properties / account_idAdded value: +{ + "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.", + "minLength": 1, + "type": "string" +}
- Changed
read_messages2 fields changed- added
Input schema / properties / account_idAdded value: +{ + "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.", + "minLength": 1, + "type": "string" +} - added
Input schema / properties / include_previewsAdded value: +{ + "default": false, + "description": "Attach a small JPEG of each photo, newest first, up to 12 per call, so you can see what was sent: the preview WhatsApp shipped when there is one, otherwise the photo is downloaded once and shrunk on the machine running wazap", + "type": "boolean" +}
- Changed
search_contacts1 field changed- added
Input schema / properties / account_idAdded value: +{ + "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.", + "minLength": 1, + "type": "string" +}
- Changed
search_messages4 fields changed- added
Input schema / properties / account_idAdded value: +{ + "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.", + "minLength": 1, + "type": "string" +} - added
Input schema / properties / fromAdded value: +{ + "description": "Only messages this person sent: \"me\", a contact id or a phone number", + "minLength": 1, + "type": "string" +} - added
Input schema / properties / sinceAdded value: +{ + "description": "Only messages from this moment on: a date (\"2026-09-01\") or an ISO timestamp", + "minLength": 4, + "type": "string" +} - added
Input schema / properties / untilAdded value: +{ + "description": "Only messages up to this moment: a date or an ISO timestamp", + "minLength": 4, + "type": "string" +}
- Changed
send_location1 field changed- added
Input schema / properties / account_idAdded value: +{ + "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.", + "minLength": 1, + "type": "string" +}
- Changed
send_media2 fields changed- added
Input schema / properties / account_idAdded value: +{ + "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.", + "minLength": 1, + "type": "string" +} - added
Input schema / properties / as_gifAdded value: +{ + "default": false, + "description": "Send a .gif or an mp4 as a looping GIF, the way WhatsApp plays them", + "type": "boolean" +}
- Changed
send_message1 field changed- added
Input schema / properties / account_idAdded value: +{ + "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.", + "minLength": 1, + "type": "string" +}
- Changed
send_poll1 field changed- added
Input schema / properties / account_idAdded value: +{ + "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.", + "minLength": 1, + "type": "string" +}
- Added
set_contact_note - Added
set_profile_picture - Changed
sync_contacts2 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / account_idAdded value: +{ + "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.", + "minLength": 1, + "type": "string" +}
- Changed
transcribe_audio1 field changed- added
Input schema / properties / account_idAdded value: +{ + "description": "Registry account id (default, work, …). Omit to resolve from chat_id or message_id, or the default account.", + "minLength": 1, + "type": "string" +}
- Added
wait_for_messages
4 tool updates
v0.10.0- Changed
get_recent_messages2 fields changed- added
Input schema / properties / include_systemAdded value: +{ + "default": false, + "description": "Include WhatsApp's own system notices, which are excluded from the bodies and the counts by default", + "type": "boolean" +} - added
Input schema / properties / typesAdded value: +{ + "description": "Keep only these message types; omit for every type. The limit counts matching messages, so [\"call\"] returns that many calls, not that many messages of which some are calls.", + "items": { + "enum": [ + "text", + "image", + "video", + "audio", + "voice", + "document", + "sticker", + "location", + "contact", + "poll", + "reaction", + "deleted", + "view_once", + "call", + "system", + "unknown" + ], + "type": "string" + }, + "type": "array" +}
- Changed
read_messages1 field changed- added
Input schema / properties / typesAdded value: +{ + "description": "Keep only these message types; omit for every type. The limit counts matching messages, so [\"call\"] returns that many calls, not that many messages of which some are calls.", + "items": { + "enum": [ + "text", + "image", + "video", + "audio", + "voice", + "document", + "sticker", + "location", + "contact", + "poll", + "reaction", + "deleted", + "view_once", + "call", + "system", + "unknown" + ], + "type": "string" + }, + "type": "array" +}
- Added
sync_contacts - Added
transcribe_audio
22 tool updates
v0.9.3- First observed
create_group - First observed
delete_message - First observed
download_media - First observed
edit_message - First observed
forward_message - First observed
get_contact - First observed
get_group_info - First observed
get_message - First observed
get_recent_messages - First observed
get_status - First observed
learn - First observed
list_chats - First observed
manage_chat - First observed
manage_group - First observed
react_to_message - First observed
read_messages - First observed
search_contacts - First observed
search_messages - First observed
send_location - First observed
send_media - First observed
send_message - First observed
send_poll
TDQS
Scored across 23 tools
Most tools target a clear, distinct resource and action (list_chats vs read_messages vs search vs catch_up are well separated, and send_message/confirm_send are explicitly staged). A few pairs could be lightly confused at a glance — remember vs reminder, find_contact vs list_contacts, manage_chat vs manage_group — but descriptions draw the boundaries clearly.
Consistent snake_case throughout, with a dominant verb_noun pattern (get_status, list_chats, read_messages, confirm_send, manage_group, edit_message). Minor deviations exist in noun-form tools (reminder, scheduled_messages) and bare verbs (learn, remember, search, catch_up), but nothing ambiguous.
23 tools is on the heavy side, but the domain genuinely spans messaging, media, contacts, groups, scheduling, reminders, memory and account linking. Each tool covers a distinct capability, so the surface is broad rather than padded.
Strong lifecycle coverage: draft/confirm send, read, search, edit, delete, react, media, contacts, groups, scheduling and account linking. Minor gaps like profile/account settings management and explicit quoting/forwarding details (partially folded into send_message/get_message) keep it from a 5.
Maintenance
Related MCP Connectors
Read-only WhatsApp MCP for your AI agent: it reads the chats you choose. Try the public demo.
WhatsMCP connects Claude and other MCP-compatible AI agents directly to WhatsApp. Send and receive text, images, documents, and voice notes; manage groups (create, add/remove members, promote admins); look up contacts and profiles; follow channels; and read call and message history — all through a standard MCP interface. For voice use cases, WhatsMCP offers SIP-based calling plans (inbound-only, or full inbound/outbound) so AI voice agents can answer and place WhatsApp calls, plus low-latency WebSocket integrations with voice agent providers like ElevenLabs. Multiple WhatsApp accounts can be paired and managed per workspace, with webhook support for real-time inbound message delivery to your own infrastructure.
Drive WhatsApp from any MCP client: pair devices, send text and media, manage contacts and groups.
Your own WhatsApp as an MCP server: read, search and send from any MCP client.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceWhatsApp MCP server that exposes messaging, groups, contacts, and profile management as tools and resources for AI agents, supporting Baileys and Meta Cloud API.26MIT
- AlicenseNot gradedqualityBmaintenanceA self-hosted WhatsApp bridge that exposes a stdio MCP server with ~20 tools for reading conversations, sending messages, managing groups, contacts, and aliases, enabling AI agents to operate WhatsApp directly.4MIT
- AlicenseNot gradedqualityCmaintenanceMCP server that connects AI agents to WhatsApp using the multi-device API, enabling messaging, group management, and more as a regular user.3 npm1MIT
- AlicenseNot gradedqualityBmaintenanceA native MCP server for SocialMate that gives your AI a WhatsApp, enabling it to send and read messages, manage contacts and groups, and more through 44 tools.6 npm1MIT