wazap-mcp
██╗ ██╗ █████╗ ███████╗ █████╗ ██████╗
██║ ██║██╔══██╗╚══███╔╝██╔══██╗██╔══██╗
██║ █╗ ██║███████║ ███╔╝ ███████║██████╔╝
██║███╗██║██╔══██║ ███╔╝ ██╔══██║██╔═══╝
╚███╔███╔╝██║ ██║███████╗██║ ██║██║
╚══╝╚══╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═╝WhatsApp для вашего ИИ-агента. MCP-сервер, который предоставляет ваш аккаунт WhatsApp — чаты, сообщения, медиа, контакты, группы — через 22 инструмента, которые может вызывать любой MCP-клиент. Вход по коду сопряжения, без браузера, без перепродажи номеров телефонов, ~20 МБ ОЗУ.
Построен на Baileys, который говорит на мультиустройственном протоколе WhatsApp через WebSocket.
Начало работы
npm-пакет называется wazap-mcp; команда, которую он устанавливает, — wazap.
npx wazap-mcp setupЭто вся установка. Она связывает ваш аккаунт, находит MCP-клиентов, установленных на этой машине, записывает их конфигурацию и сообщает, что нужно перезапустить.
Или пусть это сделает ваш агент. Вставьте это:
Настрой мне WhatsApp: выполни npx wazap-mcp setup --agent и следуй тому, что он выведет.
Затем спросите агента: «Что я пропустил в WhatsApp сегодня?»
Ниже приведены шаги, которые setup выполняет за вас. Каждый из них — отдельная команда, если вы хотите выполнить её вручную.
npx wazap-mcp login показывает QR-код; отсканируйте его в Настройки → Связанные устройства → Привязать устройство. Нет камеры под рукой или связывание через SSH? npx wazap-mcp login --phone +15550100 выводит 8-значный код, который вы вводите в разделе Привязать по номеру телефона. В конце он спрашивает, может ли агент отправлять сообщения; ответ «нет», если вы не скажете «да», а npx wazap-mcp config writes on изменит это позже.
npx wazap-mcp connect claude-code записывает запись MCP для одного клиента. Остальные — в таблице под Подключение клиента.
npx wazap-mcp сам по себе безопасен для запуска: он выводит, где вы находитесь и что делать дальше, и не запускает сервер. Если что-то не так, npx wazap-mcp status — первое, что нужно запустить: он проверяет Node, каталог данных, блокировку, учётные данные и наличие новой версии, а рядом с каждой проблемой выводит исправление.
Подключение клиента
wazap connect <client> записывает запись за вас, сохраняя всё остальное в файле и делая резервную копию один раз перед первым изменением. --dry-run показывает, что он запишет.
Клиент | Что записывает |
| выполняет |
|
|
|
|
|
|
|
|
|
|
что-то удалённое | поле URL MCP клиента: |
Любой MCP-клиент работает одинаково: команда — npx -y wazap-mcp, транспорт — stdio. Скажите агенту сначала вызвать learn — он вернёт форматы идентификаторов, рабочие процессы и каждый код ошибки с указанием, что делать.
{
"mcpServers": {
"whatsapp": {
"command": "npx",
"args": ["-y", "wazap-mcp"]
}
}
}Claude Desktop, Cursor и Gemini CLI принимают именно это. VS Code вкладывает это в servers и требует "type": "stdio" рядом с command. Codex CLI — это TOML:
[mcp_servers.whatsapp]
command = "npx"
args = ["-y", "wazap-mcp"]Папка skills/ соответствует формату Agent Skills, поэтому Codex, Cursor и другие агенты, поддерживающие навыки, могут загрузить те же пять навыков.
Related MCP server: wa-bridge
Инструменты
Инструмент | Вид | Что делает |
| чтение | Руководство по каждому инструменту, формату идентификаторов и коду ошибки. Вызовите его первым. |
| чтение | Статус подключения, состояние синхронизации, связанный аккаунт, версии, каталог данных. |
| чтение | Разговоры от новых к старым; фильтр |
| чтение | Сообщения в чате; |
| чтение | Всё за последние N часов, сгруппированное по чатам. Инструмент для навёрстывания. |
| чтение | Текстовый поиск по локально хранимым сообщениям. |
| чтение | Одно сообщение полностью, с цитируемым сообщением и реакциями. |
| чтение | Поиск контактов по имени или номеру. |
| чтение | Имя, номер, текст «о себе», фото профиля. |
| чтение | Участники, администраторы, режим объявлений, ссылка-приглашение (если вы администратор). |
| чтение | Сохранить вложение на диск; небольшие изображения также возвращаются встроенно. |
| запись | Отправить текст, опционально как ответ, с @-упоминаниями. |
| запись | Отправить изображение, видео, аудио, голосовое сообщение или документ из пути или URL. |
| запись | Отправить опрос с 2–12 вариантами. |
| запись | Отправить метку на карте. |
| запись | Редактировать своё сообщение в течение 15-минутного окна WhatsApp. |
| запись | Добавить или удалить реакцию-эмодзи. |
| запись | Переслать сообщение в другой чат. |
| запись | Отозвать своё сообщение в течение 2-дневного окна WhatsApp. |
| запись | Архивировать, закрепить, заглушить (по умолчанию 8 часов), отметить прочитанным/непрочитанным. |
| запись | Создать группу и добавить участников. |
| запись | Добавить, удалить, повысить, понизить, выйти, переименовать, ссылки-приглашения. |
Каждое сообщение возвращается с непустым text: медиа- и системные сообщения содержат заполнитель, например [image] caption, [voice message], [deleted] или [poll] Pizza or pasta?. Временные метки — ISO 8601 со смещением UTC машины, рядом человекочитаемый age, например 2h ago.
Навыки
wazap поставляется с пятью Agent Skills, которые обучают агента рабочим процессам, стоящим за инструментами, а не только самим инструментам:
Навык | Что делает агент |
| Диагностика с помощью |
| «Что я пропустил?» Сортировка на нужно вам / к сведению / шум, с ранжированием, плюс забытые ответы. Только чтение |
| «Найди счёт, который отправил Дэн.» Поиск с вариантами запросов, листание назад во времени, загрузка и чтение файла. Только чтение |
| Наверстать группу из 300 сообщений: решения, даты, что от вас требуется. Только чтение |
| Черновик в собственном регистре чата, показ получателя и текста, отправка только после согласия пользователя |
Установите всё (сервер и навыки) как плагин Claude Code:
/plugin marketplace add razvangirgiz/wazap
/plugin install wazap@wazapИли скопируйте skills/<name>/ в любой каталог навыков, который читает ваш агент.
Ошибки
Каждый сбой — это структурированный { error, message, fix }, а не трассировка стека, чтобы агент мог решить: повторить попытку, спросить пользователя или остановиться.
Код | Значение |
| Аккаунт не связан. Выполните |
| Отвязан от телефона. Выполните |
| Учётные данные не читаются. Выполните |
| Всё ещё подключается или переподключается. |
| Синхронизация истории не завершена; результаты могут быть неполными. |
| Номер не в международном формате. |
| Не является идентификатором чата, контакта или группы WhatsApp. |
| У этого номера нет аккаунта WhatsApp. |
| Неизвестный идентификатор. |
| Права в группе. |
| WhatsApp истёк срок файла, или он никогда не был синхронизирован здесь. |
| Проблемы с исходящими медиа. |
| Превышен лимит сообщений WhatsApp. |
| Собственные ограничения WhatsApp на редактирование и удаление. |
| wazap работает в режиме только для чтения. |
| Слишком много записей; |
| WhatsApp не ответил или отклонил операцию. |
Каталог данных
Всё хранится в ~/.wazap (переопределяется с помощью --data-dir или WAZAP_DATA_DIR), создаётся с правами 0700, учётные данные записываются с правами 0600:
~/.wazap/
auth/ WhatsApp credentials — treat this like a password
media/ downloads from download_media
history/ per-chat message history, so a restart is not amnesia
store.json chat-list snapshot
server.lock pid of the running server
daemon.json loopback endpoint a second wazap bridges to
.env optional settings, see .env.exampleЗапись учётных данных идёт во временный файл и затем переименовывается на место, поэтому убийство процесса во время записи не заставит вас заново связывать телефон.
Несколько клиентов одновременно
Claude Desktop, Claude Code и Cursor — каждый запускает собственный wazap. WhatsApp
разрешает один сокет на привязанное устройство, поэтому они делят одну сессию, а не
борются за неё. Первый wazap в каталоге данных владеет сессией и открывает
MCP-эндпоинт на 127.0.0.1; каждый последующий подключается к нему через этот
эндпоинт. Ничего настраивать не нужно, и ни один клиент не видит разницы.
Владелец публикует <data-dir>/daemon.json (0600) со своим pid, своим портом
и токеном, с которым мост аутентифицируется.
Мост обслуживает всё, что предоставляет владелец, поэтому владелец, запущенный с --read-only,
делает каждого клиента доступным только для чтения, независимо от того, с какими флагами
был запущен этот клиент.
Когда владелец выходит, мосты выходят вместе с ним, а следующий wazap, который
запустит клиент, становится новым владельцем.
WAZAP_NO_SHARE=1 отключает это: второй wazap в том же каталоге завершается с
кодом 2 и указывает pid уже запущенного. Явный --http — это самостоятельный
сервер, а не мост, и ему отказывается так же.
Режим только для чтения
Запись — опциональна. login спрашивает один раз и сохраняет ответ в
<data-dir>/.env; wazap config writes on|off меняет его, а один wazap config
выводит все действующие настройки с указанием их источника.
WAZAP_READ_ONLY=1 или wazap serve --read-only вообще не регистрирует инструменты
записи. Агент их никогда не видит, поэтому не может отправить сообщение с вашего
номера даже по ошибке — полезно, когда привязанный аккаунт ваш личный.
Запись также ограничена по скорости до WAZAP_RATE_LIMIT в минуту (по умолчанию 20, 0
отключает). Отправка быстрее, чем человек, — это способ получить бан аккаунта.
HTTP-режим
WAZAP_READ_TOKEN=$(openssl rand -hex 32) \
WAZAP_WRITE_TOKEN=$(openssl rand -hex 32) \
npx wazap-mcp serve --http --host 0.0.0.0 --port 8766Streamable HTTP на /mcp с проверкой работоспособности по /healthz. Два bearer-токена:
токен чтения даёт инструменты чтения, токен записи дополнительно разблокирует инструменты
записи, так что утёкший токен чтения никогда не сможет никому написать. wazap
отказывается привязываться к адресу не-loopback без токена чтения.
Самостоятельный хостинг
Запустите wazap на собственном сервере, когда агент не на вашем ноутбуке: другая машина, VPS, инфраструктура клиента. Сессия остаётся на этом сервере; ничего не проходит через третьи стороны.
С systemd
npm install -g wazap-mcp
sudo useradd --system --home /var/lib/wazap --create-home wazap
sudo -u wazap WAZAP_DATA_DIR=/var/lib/wazap wazap login --phone +15550100 # pairing code works over SSH
sudo -u wazap tee /var/lib/wazap/.env >/dev/null <<END
WAZAP_READ_TOKEN=$(openssl rand -hex 32)
WAZAP_WRITE_TOKEN=$(openssl rand -hex 32)
END
sudo curl -fsSL https://raw.githubusercontent.com/razvangirgiz/wazap/main/deploy/wazap.service -o /etc/systemd/system/wazap.service
sudo systemctl enable --now wazap
curl -s http://127.0.0.1:8766/healthzЮнит привязывается только к loopback. Поставьте TLS спереди с помощью двухстрочного deploy/Caddyfile (caddy run --config deploy/Caddyfile после редактирования имени хоста) или любого обратного прокси, затем укажите клиенту https://your-host/mcp с Authorization: Bearer <read or write token>.
С Docker
git clone https://github.com/razvangirgiz/wazap && cd wazap
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 wazap-data volume
docker compose up -d
curl -s http://127.0.0.1:8766/healthzКонтейнер публикует 8766 только на loopback; добавьте тот же TLS-прокси спереди. Обновление — это git pull && docker compose up -d --build; том сохраняет сессию.
Какие клиенты могут подключиться
Claude Code, Claude Desktop, Cursor, Codex, VS Code и любой клиент с полем «MCP URL + header» подключаются с bearer-токеном. Connectors в claude.ai требуют OAuth, а не статический токен, поэтому они пока не могут использовать самостоятельный wazap. Держите read-токен в клиентах, которым нужно только читать; выдавайте write-токен осознанно.
Настройки
Переменная | По умолчанию | Значение |
|
| Где хранится всё. |
|
| Не регистрировать инструменты записи. |
|
| Запросить у WhatsApp более полную синхронизацию истории. |
|
| Сохранять чаты и сообщения между перезапусками. |
|
| Вызовы инструментов записи в минуту; |
|
|
|
|
| Адрес привязки HTTP. |
| не задан | Bearer-токены HTTP. |
|
|
|
Флаги важнее переменных окружения, а те важнее <data-dir>/.env.
Известные ограничения
Ключи медиа истекают. WhatsApp удаляет старые вложения со своих серверов, поэтому
download_mediaдля старого сообщения возвращаетMEDIA_UNAVAILABLE.История — это то, что синхронизирует телефон. wazap видит ту историю, которую WhatsApp передаёт привязанному устройству, а не всю вашу переписку.
@lidидентификаторы. WhatsApp адресует собеседников по приватному идентификатору, а не по номеру телефона. wazap переводит их обратно в номера телефонов, когда знает соответствие, и передаёт@lidкак есть, когда не знает.Телефон должен оставаться доступным. Привязанное устройство перестаёт получать сообщения, если телефон был офлайн достаточно долго;
get_statusсообщает об этом.Токен одного устройства. Привязка привязана к одному устройству; повторный вход переносит сессию и разлогинивает предыдущую.
@lidне везде. Некоторые поля адресуются по@lid, а не по номеру телефона; wazap преобразует их обратно в номера телефонов, когда узнаёт соответствие.
Разработка
npm install
npm run typecheck
npm test # builds, then runs node --test
node test/smoke-stdio.mjs # drives the built binary over MCP stdio
npm run dev -- status # run from source with tsxnpm test не требует подключённого телефона. Smoke-тест stdio запускает собранный бинарник с временным каталогом данных и проверяет, что инструменты перечисляются и get_status работает без привязки.
Лицензия MIT.
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 | Account id | |
| 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?
The description explains the non-idempotent behavior of moving the mark and the consequence of losing an answer (use since:'previous'), which goes beyond annotations. It also clarifies budget_tokens and cursor usage. Annotations (readOnlyHint true, destructiveHint false) are consistent, and the description adds meaningful behavioral detail without contradiction.
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 run-on sentence with heavy jargon ('the mark moves first', 'a lost answer is since: previous'). It is concise in length but not well-structured or front-loaded; the core purpose is somewhat buried. The cryptic phrasing reduces readability despite the compact size.
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 tool with six optional parameters and non-trivial behavior (mark movement, pagination, token budget), the description covers the essential operational details: sections, account narrowing, cursor handling, and the token limit. The output schema exists to handle return values. It lacks error handling or edge cases, but overall it is sufficiently complete for an advanced tool.
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?
Despite 100% schema description coverage, the description enriches parameter understanding: it explains 'since' options, the mark movement, and the meaning of 'more.cursor'. It also lists the sections returned, which aligns with the include parameter even though terminology differs slightly (e.g., 'mentions' vs 'addressed'). This adds value beyond 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 clear purpose: fetching what the user missed across all accounts, listing sections like waiting, mentions, calls, people, groups, stories. It distinguishes from siblings by focusing on aggregated missed content, though it does not explicitly name alternatives. The title reinforces this, so it is not a tautology.
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 some usage context, such as using account_id to narrow to one account and mentioning get_status for names, plus the mark movement behavior and cursor pagination. However, it does not explicitly state when to use this tool versus alternatives, nor does it provide exclusions or prerequisites. The guidance is implicit rather than direct.
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 | Account id |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare write/idempotent/non-destructive, so the bar is lower, but the description still adds real value: the once-per-draft guarantee, the 'never redo it unasked' rule, and the outcome-unknown recovery path. It stops short of disclosing auth needs or the concrete response payload, keeping it from 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?
Four dense, front-loaded sentences each carrying distinct actionable content with no filler. The telegraphic fragments ('A yes about something else:', 'Expired, missing or stale:') are efficient but slightly terse to parse.
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 write tool with no output schema, the definition covers the critical edge cases an agent would otherwise mishandle: stale drafts, re-previewing before resend, and the unknown-outcome branch. Little is missing given the annotations already cover the safety profile.
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 100% and both parameters are documented there, including the scheduled-vs-sent nuance on draft_id. The description adds only the loose framing 'this text, this recipient' for what a draft binds, so the baseline 3 applies.
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 ('Send a draft the user approved') with the exact scope ('this text, this recipient') and explicitly claims exclusivity ('the only call that sends, once per draft'), which separates it from send_message and scheduled_messages. An agent can identify the tool's role 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?
Gives explicit when-to-use (user approved this draft), when-not ('A yes about something else: show the preview again and ask'), and recovery paths for expired/missing/stale drafts plus the SEND_OUTCOME_UNKNOWN branch pointing to read_messages. Alternatives and preconditions are named rather than inferred.
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 | Account id | |
| 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?
Annotations already flag destructive behavior, but the description adds meaningful context: the 2-day retraction window, the admin-permission condition for group messages, and that for_everyone:false only affects the linked account's devices. This goes well beyond the structured hints and helps set expectations.
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 clauses with no filler; the mandatory user-confirmation is front-loaded, and the for_everyone branch is expressed compactly. Every sentence adds distinct 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?
With a rich behavioral description and an output schema present, the core invocation requirements are covered. The main remaining gap is that account_id's role is never explained, and there's no explicit statement of what happens if it is omitted. Still, for a destructive tool with strong annotations, this 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?
The description thoroughly explains for_everyone behavior, which the schema leaves undocumented, and indirectly clarifies message scope as 'the account's own message' or 'anyone's in a group.' However, account_id and message_id receive no real semantic help beyond the schema's minimal 'Account id' and name/minLength, so the compensation is incomplete.
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 ('Delete a message') and immediately clarifies the operation's scope via the for_everyone flag. The local-vs-everyone distinction separates it from siblings like edit_message and send_message even though those aren't named.
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 instructs the agent to confirm with the user first, which is a clear prerequisite before invoking. It also states when for_everyone is valid (true within 2 days, own message or admin in group) versus local-only removal (false), giving condition-based guidance. It doesn't explicitly name alternative tools, but it defines the choice space.
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 | Account id | |
| 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 signal destructiveHint=true and readOnly=false, so the description's 'replace' is consistent and not a contradiction. It adds the platform constraint of 15 minutes, but does not disclose behavioral details such as whether recipients see an edited indicator or what happens on failure. With annotations carrying the safety profile, the description contributes only moderate additional transparency.
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 with no filler. The core purpose is front-loaded, and the time-limit/fallback guidance is contained in a single follow-up sentence.
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 the simple mutation scope, existing output schema, and annotations, the description covers the essential operational constraint (15-minute window), the ownership constraint (linked account), and the fallback path. It does not detail error semantics, but the schema and annotations fill most of the remaining context.
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 33%, and the description gives only implicit semantics: 'text' maps to the replacement content, 'message' to message_id, and 'linked account' to the account context. It adds some meaning beyond the schema, but does not explicitly define the relationship of account_id or the expected format of message_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?
States a specific operation: replace the text of an existing message sent by the linked account. This clearly distinguishes it from siblings like send_message and delete_message, and the phrasing 'linked account sent' narrows the target.
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 states the 15-minute edit window and instructs to send a correction instead afterward. This gives a clear when-to-use and when-not-to-use condition, though it does not explicitly name the sibling tool (e.g., send_message) or list other exclusions.
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"), group, number or id means, before drafting. resolved: contact.chat_id, with number, note, tags, details and, in a write session, context. ambiguous or not_found: ask the user; never send to a guess. A name on 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 | Account id | |
| 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?
The annotations already supply readOnly/idempotent/non-destructive hints, and the description adds genuinely useful behavior: resolved results include chat_id plus notes/tags/details/context, ambiguity triggers a user question rather than a guessed send, tag mode returns people, and multi-account conflicts are flagged. No contradiction with annotations.
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, information-dense, and front-loaded with the core purpose. The telegraphic fragments and the unclear 'see fix' reference slightly hurt readability, but no sentence is filler.
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 lookup tool, the description covers the main usage flow, disambiguation behavior, tag mode, and write-session context, and an output schema exists so return values need not be spelled out. The only real gap is that the 'fix' handling for same-name-on-several-accounts is referenced but not defined.
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 high (86%) and each parameter already has a meaningful description, so the main description does not need to re-document them. It adds some outcome context (what resolved means, tag mode, ambiguity limits), but not significant per-parameter meaning beyond the schema, earning the baseline 3.
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 action: resolve what a name, nickname, relationship, group, number, or ID refers to before drafting, and names the resolved output (contact.chat_id). This clearly separates contact resolution from sibling messaging/chat tools such as send_message or list_chats.
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 usage timing ('before drafting') and a firm rule for ambiguous/not_found results: ask the user and never send to a guess. It does not explicitly name sibling alternatives such as search or list_chats, and the 'see fix' reference is not self-contained, so the alternative-selection guidance is slightly incomplete.
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 | Account id |
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 readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds value by specifying the conditional nature of the invite link ('for an admin') and the participant limit (up to 500), which are behavioral details not captured in annotations. It does not contradict annotations.
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 sentence that front-loads the key data returned, then appends a usage instruction. Every phrase earns its place, with no filler. It is concise yet complete.
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 the output schema exists and annotations cover read-only/idempotent behavior, the description covers what the tool returns, when to use it, and a sequencing note. Nothing essential is missing for an agent to correctly invoke this tool.
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 description coverage is 100%, with both group_id and account_id documented. The description does not add extra meaning beyond the schema—it mentions group info but not parameter-specific syntax or constraints. With full schema coverage, the baseline of 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 verb ('get') and resource ('group info'), then enumerates the exact fields returned (name, description, owner, participants, admin status, settings, community, invite link). It clearly distinguishes itself from sibling tools like manage_group and get_status by listing what it retrieves and by the explicit 'Call it before manage_group' directive.
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 explicitly says 'Call it before manage_group,' giving a clear precondition and usage context. This directly tells an agent when to invoke this tool versus alternatives, leaving no ambiguity about sequencing.
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 messageCRead-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 | Account id | |
| 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?
Annotations declare readOnlyHint=true, meaning the tool should not modify its environment. The description explicitly says files can be saved to disk via save_to ('any file saved at path on the machine running wazap') and that transcripts are created and billed ('kept once made; an API provider bills it'), which are environment-modifying side effects. This directly contradicts the readOnlyHint annotation. Although the description does add useful error context (MEDIA_UNAVAILABLE), the contradiction forces a score of 1.
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 dense, run-on sentence with semicolons that reads like internal shorthand rather than structured documentation. It is not front-loaded with a clear purpose statement, and the parenthetical asides make it hard to parse. While not excessively long, its structure impedes quick comprehension.
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 has an output schema, so return values need not be described. The description covers some behavioral details (transcript caching/billing, save_to effects, MEDIA_UNAVAILABLE error), but it is incomplete for a 4-parameter tool with no usage guidance, and its behavioral claims conflict with the readOnlyHint annotation. It leaves key questions unanswered, such as account_id semantics and whether saving files affects the annotation contract.
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 75%, so the schema already documents most parameters (save_to, language, account_id). The description adds marginal behavioral context for save_to ('its file, and no new transcript') and indirectly for language (transcript generation), but does not explain message_id or account_id. With high schema coverage, 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 conveys that the tool returns media content (transcripts, files, images) for a message, but it does so in a convoluted, note-like way rather than stating a clear verb+resource. The title supplies the missing 'Get the media of a WhatsApp message' framing, yet the description does not explicitly differentiate this from sibling tools like get_message or read_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?
There is no explicit guidance on when to use this tool versus alternatives. The description implies usage (when a message has media) but never states conditions, prerequisites, or when to prefer get_message/read_messages instead. An agent must infer that this is the media-retrieval counterpart to text retrieval.
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 | Account id | |
| 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 establish read-only, idempotent, non-destructive, open-world behavior, and the description goes beyond them by disclosing the cross-account lookup fallback when account_id is absent and by characterizing the rich payload returned. It omits any mention of permissions, rate limits, or cost of that multi-account scan, keeping it from 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?
It is a single long, dense sentence, front-loaded with the core claim 'One message in full,' which is good. However, much of the enumeration (reactions, poll votes, media, read receipts) restates what the output schema already provides, so several clauses do not fully earn their place.
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 annotations covering the safety profile and an output schema covering return values, the return-content enumeration is largely redundant and the real gaps remain: no guidance on when to use this versus read_messages or search. The account_id fallback is the one piece of essential context supplied.
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%: account_id has a bare 'Account id' string while message_id is undocumented. The sentence 'Without account_id the id is looked for on every account' genuinely adds semantics for account_id, but message_id (the only required param) gets nothing beyond the schema, so 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 resource is unambiguous ('one WhatsApp message in full') and the description enumerates exactly what 'in full' means: quoted message, reactions with authors, poll votes, media, and read receipts. The verb is only implied (the name/title supply 'get'), and no sibling such as search or read_messages is named to sharpen the distinction, so it lands short of 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?
Usage is implied rather than stated: an agent can infer 'call this when you have a specific message_id and need the complete message.' The one real guideline is the account_id fallback ('the id is looked for on every account'), but there is no when-not-to-use or pointer to alternative retrieval tools.
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 | Account id | |
| 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 readOnly/idempotent/non-destructive/closed-world, so the safety profile is covered. The description adds real behavioral context beyond them: it enumerates the diagnostic fields returned (sudo state codes, sync progress, history freshness, webhook delivery, versions) and notes that accounts includes the default.
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 — it leads with what the tool reveals, then the trigger states. It reads as a stack of fragments and the trailing ellipsis in 'linking with its pairing code…' is sloppy, but 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?
With no output schema, the description carries the burden of explaining the return payload and does so reasonably: state, sync, history freshness, webhook status, versions, accounts. It omits response structure and whether account_id defaults to the default account, but the essentials for calling and interpreting it are present.
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 100% and both parameters (account_id, include_picture with its link-expiry note) are documented in the schema itself. The description adds no parameter semantics beyond the structured fields, so the baseline 3 applies.
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 resource and enumerates exactly what the status covers: connection state, sync, history freshness, webhook delivery, versions, and the accounts list. No sibling tool in the set overlaps with this, so explicit differentiation is unnecessary, though no sibling is named either.
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 condition: 'Call it on NOT_CONNECTED, NOT_LINKED or SYNC_IN_PROGRESS.' That is clear when-to-call guidance tied to concrete state names, but it names no alternative tool or when-not-to-call scenario.
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 | Account id |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and non-destructive behavior. The description adds useful context beyond the annotations: the tool is a pure documentation read that has no effect on WhatsApp. This reinforces safety and clarifies that repeated reads are harmless.
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 tightly packed sentences with no wasted words. The core purpose is front-loaded, and the usage instruction is immediate and actionable. Topics are enumerated 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?
For a documentation/guide tool, the description fully covers what the tool is, what topics it contains, when to call it, and that it has no side effects. The optional account_id parameter is the only input, and the description provides enough context for correct invocation.
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 100% for the single account_id parameter, but its schema description is minimal ('Account id'). The tool description adds meaningful context by noting that account_id matters 'with several accounts,' which explains when the parameter is relevant.
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 clear purpose: a guide to the WhatsApp tools covering IDs, account_id, workflows, message shape, and error codes. It also distinguishes itself from the sibling operational tools by saying it 'never touches WhatsApp' and should be read 'before the other 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?
Explicitly tells the agent when to use it: 'Read it once, before the other tools.' It also clarifies what it is not for by stating it never touches WhatsApp, implicitly routing operational tasks to sibling tools.
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 | Account id |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag this as non-read-only and non-destructive. The description adds meaningful behavior beyond that: it returns a pairing code, requires the user to complete manual steps, and instructs polling get_status every 10 seconds until connected. This is useful operational context not captured by annotations.
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 deliver the trigger condition, the manual user steps, and the polling instruction without fluff. Every sentence carries operational meaning, and the most important condition is front-loaded.
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 description covers trigger, procedure, expected output (a code), and post-call polling. With no output schema, it could be more explicit about the return shape of the code, but for a straightforward pairing action the guidance is largely sufficient.
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 100%, so the schema already documents both parameters. The description adds little beyond referencing 'phone number' in the user flow; it does not explain account_id or clarify parameter semantics further. 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 verb ('Pair') and resource ('wazap with the user's WhatsApp'), and ties the action to explicit status conditions. It is clearly distinguishable from siblings like get_status or manage_chat because it defines the exact action and outcome.
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 says when to use the tool: when get_status returns not_linked, logged_out, session_corrupt, or auth_failure. It also gives the full user-facing workflow and the polling loop, leaving no ambiguity about when or how to invoke it.
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 |
|---|---|---|---|
| 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 | Account id | |
| include_pictures | No | Add picture_url, each chat's profile photo (links expire) |
Output Schema
| Name | Required | Description |
|---|---|---|
| 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 declare readOnlyHint, idempotentHint, non-destructive and openWorld, so the safety profile is covered. The description adds one genuinely new behavioral fact — that results are ordered most-recently-active-first — but omits pagination behavior, and its field inventory duplicates the output schema. One added trait over the annotations lands it at 3.
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 with the resource and ordering front-loaded and no filler. The field inventory is mildly redundant given the output schema exists, but it is short enough that nothing dominates.
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 description needn't explain return values, and annotations cover the safety profile; purpose, usage and ordering are all stated. Only minor gaps remain (no mention of pagination or the filter option), so it is close to complete for a 5-param list tool.
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% (cursor, filter and include_pictures are documented), so the schema carries the parameter burden. The description mentions archiving only in passing ('whether archived') and never explains limit, cursor paging, or the filter enum, so it adds no meaning beyond the schema — the baseline 3 for high coverage.
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 enumerates conversations and names the identifying fields (chat_id, name, type, unread count, last message, state flags). The verb is implied rather than stated ('Conversations...'), and it doesn't explicitly distinguish itself from the sibling list_contacts, but an agent can tell it retrieves chats, not contacts.
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 a concrete reason to reach for this tool, which is the main entry point before message-level tools. It stops short of naming exclusions or alternatives (e.g. search, list_contacts, read_messages) when a chat_id is already known, which keeps it from a 5.
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 | Account id |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive, open-world, so the safety profile is covered. The description goes beyond them by disclosing filtering behavior ('No message words; #private people left out') and an edge case ('address_book_synced false: not arrived yet'), which materially inform result contents.
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?
Purpose and returned fields are front-loaded in the first sentence, with filtering and the sync caveat appended tersely. The fragmentary phrasing ('address_book_synced false: not arrived yet') is dense but earns its place as an edge-case note; no redundant sentences.
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 usefully explains what each row contains and the privacy/status caveats, which is the key missing structured information. Minor gaps remain around account_id acquisition and ordering semantics, but the core call-and-interpret picture is 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 order and cursor carrying their own descriptions, so the schema does most of the work. The description only loosely reinforces account scoping ('one account') and pagination ('a page at a time') and adds no format or default detail for limit/order beyond the schema, so a 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?
Specific verb (list) and resource (the phone's address book / contacts), and it enumerates the returned fields (name, phone, chat_id, contact_id, last DM time and direction), which makes the resource unambiguous. It does not explicitly name or contrast with siblings such as find_contact or list_chats, so it stops short of 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?
'a page at a time' implies paginated browsing and 'on one account' implies account scoping, so usage is inferable. However, there is no explicit when-to-use / when-not-to-use guidance versus find_contact (lookup) or list_chats, leaving the agent to infer routing.
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
Change a chat on WhatsApp at once, with no draft: archive, pin, mute, mark_read or mark_unread; pin_message (for everyone) or star_message on a message_id; clear or delete it for the linked account; block a person. Say what will change and wait for a yes.
| 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 | Account id | |
| message_id | No | pin_message, star_message and their undo; in chat_id | |
| mute_hours | No | mute: 8 by default |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already signal destructive and non-idempotent behavior, so the description's job is to add context. It adds meaningful behavioral detail: actions happen 'at once, with no draft', pin_message affects 'everyone', clear/delete is scoped to 'the linked account', and user confirmation is required before changes. These are useful traits not captured in 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?
The description is a single efficient sentence that front-loads the action list and ends with the critical confirmation instruction. There is no filler, though the phrase 'at once, with no draft' is slightly ambiguous and could have been clearer or omitted.
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 multi-action, destructive tool with six parameters and no output schema, the description covers the key invocation context: what actions are available, the account scope, the need for message_id for certain operations, and the confirmation requirement. It does not describe return values or error behavior, but those are less critical given the schema already covers parameter details.
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 high (83%), so the schema already documents chat_id, account_id, message_id, pin_hours, and mute_hours. The description adds some semantic clarification — pin_message applies 'for everyone', star_message operates on a message_id, and clear/delete applies to the linked account — but does not deeply enrich the parameter understanding beyond 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 clearly states a specific verb ('Change a chat') and enumerates the concrete actions it performs (archive, pin, mute, mark_read, etc.), which is far more specific than the title alone. It doesn't explicitly contrast itself with sibling tools like send_message or manage_group, but the action list makes the resource and scope unambiguous.
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 gives clear context for when to use the tool: when a chat-level change is needed (archive, pin, mute, read state, message pin/star, clear/delete, block). It also includes an important process instruction — 'Say what will change and wait for a yes' — which tells the agent how to invoke it safely. It does not explicitly state when not to use it or point to alternatives, so it misses the top score.
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 | Account id | |
| 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?
Although annotations already declare destructiveHint=true and readOnlyHint=false, the description adds valuable behavioral detail beyond those flags: 'Most actions need admin' and 'Every change shows to all members at once: say what will change, wait for a yes.' It also discloses the confirm-before-join flow with 'preview first, then confirm: true,' which is exactly the kind of side-effect transparency an agent needs for a social, visible mutation tool. No contradiction with annotations.
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 sentences with no filler. The first sentence front-loads the tool's capabilities, and the second delivers the critical behavioral warning. Every clause earns its place.
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 broad tool with 21 enum actions and 10 parameters, the description gives a high-level map of capabilities plus the essential safety/social rules. The output schema exists, so return values need no explanation. It could be slightly more complete by steering read-only group lookups to get_group_info, but the description is sufficient for an agent to use it safely.
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 90%, so the schema carries most parameter meaning. The description adds important semantic context for the confirm parameter by tying it to user consent: 'preview first, then confirm: true' and 'wait for a yes.' This goes beyond the schema's bare 'join: true joins, after the user said yes to the preview' and reinforces how the parameter should be used.
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 specific verbs and resources: 'Create a group, join one from an invite ... or administer one: members, name, description, photo, invite link, join requests, settings, leave.' This clearly differentiates it from siblings like manage_chat and get_group_info by scoping it to group-level administration. It is not a tautology and communicates the tool's full intent.
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 gives practical context: 'Most actions need admin' and 'Every change shows to all members at once: say what will change, wait for a yes.' This tells the agent when it is appropriate to invoke the tool and what interaction pattern to follow. It does not explicitly name alternatives or exclusion conditions, but the group-vs-chat scope and admin caution make usage context clear.
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 | Account id | |
| 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?
The description adds a useful non-obvious behavior: an empty string removes the reaction. It does not, however, state whether an existing reaction is replaced or what happens when removing a reaction that does not exist, leaving part of the behavior to inference.
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, tight sentence conveys the primary operation and the important edge-case behavior with no filler. The key constraint is front-loaded and immediately actionable.
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 simple three-parameter tool with an output schema and annotations covering idempotence and non-destructiveness, the description is nearly sufficient. It explains the emoji special case and leaves message_id and account_id inferable from their names; a note on the optional account_id's default would make it fully 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?
The description meaningfully clarifies the emoji parameter: exactly one emoji is allowed, and an empty string requests removal. The schema only describes account_id as 'Account id' and leaves message_id and emoji without descriptions, so the description only partially compensates for the 33% coverage; the remaining parameters rely on their names.
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 concrete action ('React to a message') with an explicit constraint ('one emoji') and a distinct removal mode ('pass "" to take your reaction off'). This clearly separates it from siblings like send_message, edit_message, and 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 intended use is implied: call this when you want to add or remove an emoji reaction on a message. However, it names no sibling alternatives and gives no when-not-to-use guidance, so the agent must infer the selection context.
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 | Account id | |
| 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 cover read-only/idempotent safety, so the bar is lower, yet the description adds real behavioral context: backfilling from the phone when local history runs out, truncation of long texts unless full_text, and that stories appear nowhere else. Default limit and account scoping are left to the schema.
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 but front-loaded: read scope first, then pagination, then the status special case. The parenthetical about wazap asking the phone is slightly digressive but earns its place by explaining an observable latency/backfill behavior.
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 described, and annotations cover the safety profile. The description adequately covers the tool's oddities (status mode, backfill, truncation) for an 8-param reader, though it omits the default limit of 20 and the types/limit interaction wording.
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 88%, so the baseline is 3, but the description adds genuinely new meaning: the fallback behavior of 'before', the 'status' value for chat_id and its hours window, and the full_text truncation toggle. Only limit/account_id add nothing beyond 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?
Specific verb+resource ('Read one chat') with ordering and scope stated up front ('oldest to newest'), which tells an agent this is a single-chat reader rather than a global search. Sibling differentiation is implicit (no sibling named) but the 'chat_id "status"' carve-out usefully separates it from get_status/stories semantics.
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 pagination context ('or older ones with before') and hints at the status mode ('from the last hours, at most a day'), but never says when to prefer this over get_message, search, catch_up, or list_chats. 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.
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 | Chat id, or a phone number | |
| handled | No | Off catch_up's waiting until they write again | |
| add_tags | No | e.g. ["client"] | |
| account_id | No | Account id | |
| remove_tags | No | ||
| remove_fields | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| name | Yes | |
| note | No | |
| tags | No | |
| fields | No | |
| number | No | |
| chat_id | Yes | |
| 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?
The description adds meaningful behavioral context beyond the annotations: data is stored locally and never on WhatsApp, and the '#private' and '#no-catchup' tags control future retrieval behavior. This is genuinely useful information that the annotations alone do not 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?
The description is compact and front-loads the core purpose before explaining special flags. It is slightly dense and could be more readable, but every part adds meaningful information without unnecessary filler.
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 the output schema, 75% schema coverage, and annotations, the description covers the essential purpose, privacy behavior, and special handling for catch-up and private queries. The main gap is the lack of explicit differentiation from the 'learn' sibling, but the tool is still usable without that clarification.
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 high at 75%, so the baseline is 3. The description adds value by giving concrete examples for 'details' ('{"relatie": "mama"}'), explaining 'handled: true' as marking an ask dealt with elsewhere, and clarifying the privacy/catch-up semantics of the special tags.
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 clearly identifies a specific action ('Keep what the user says about someone') and resource (person-related memory), and it adds important scope with 'locally, never on WhatsApp.' It also references the 'find_contact' and 'catch_up' contexts, which helps distinguish it from those siblings, though it does not explicitly contrast it with the 'learn' 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?
The description provides useful context for when to set 'handled: true' and how '#private' and '#no-catchup' affect behavior, but it does not explicitly explain when to prefer this tool over alternatives like 'learn' or when not to use it. Usage is implied rather than directly stated.
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 | Account id | |
| 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?
Annotations only declare the generic safety profile (not read-only, not idempotent, not destructive, closed-world). The description adds real behavior beyond that: reminders are stored locally and delivered to the user's webhook when due, the no_reply condition is skipped if someone replied, and nothing is sent to WhatsApp. Storage/delivery semantics are exactly the kind of context annotations cannot carry.
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 identity is front-loaded in the first clause, then it moves through create, condition, and the list/cancel actions with no filler. The telegraphic fragments ('list, cancel.') and stacked parentheticals are dense but every element carries information for an 11-parameter multi-action tool.
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 the description still covers all three actions, storage location, delivery mechanism, the condition enum, and the no-WhatsApp guarantee. Only minor gaps remain, such as whether list scopes by account_id and what cancel does to already-fired reminders.
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 82%, so the baseline is 3, but the description adds meaning the schema does not encode: after_hours and due_at are alternatives for the same due time, and condition=no_reply means the reminder is suppressed if someone wrote after it was set. It also clarifies reminder_id comes from create or list.
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), the lifecycle operations (create/list/cancel), and the three create inputs, so an agent knows exactly what this tool manipulates. The closing line 'Nothing goes to WhatsApp' implicitly separates it from messaging siblings like scheduled_messages, though it never names that sibling outright.
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 clear per-action context: create takes chat_id, note and either after_hours or due_at; the no_reply condition fires only if nobody wrote since; list and cancel are named. The 'Nothing goes to WhatsApp' clause signals when not to expect messaging behavior, but no alternative tool is named explicitly, so this stops 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.
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 | Account id | |
| 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?
Annotations already declare readOnlyHint=false, idempotentHint=true, destructiveHint=false, so the safe/idempotent profile is covered. The description adds genuine context beyond that: list ordering (waiting soonest first, then the week's sent/missed/failed/cancelled) and the recency window, plus an explicit directive to surface missed/failed messages. It stops short of stating permission requirements or what happens if the cancel window has passed.
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-load the primary action, and the closing instruction ('Tell the user about every missed or failed one') is a behavioral requirement an agent genuinely needs. No filler or restatement of the title.
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 adequately covers both the list and cancel branches of the enum action. Minor gaps remain around the limit parameter and error behavior for a cancel attempted too late, but nothing essential to correct invocation is missing.
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 60%, and the description reinforces schedule_id's origin (from the list or confirm_send) and the meaning of the closed-message set, which matches the schema's own include_closed description. The limit parameter (default 50, max 100) is never mentioned, so the description does not fully compensate for the coverage gap. Baseline 3 is appropriate when the schema carries most parameter meaning.
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 resource (the account's scheduled messages) and two concrete verbs (list, cancel), and it explicitly distinguishes itself from the sibling tools send_message and confirm_send that handle scheduling. An agent can identify this tool's role without inspecting 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?
It names the alternative workflow for scheduling (send_message with send_at, then confirm_send) and the condition that selects it, plus the constraint that cancellation must happen 'before it goes.' Use vs. alternative is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
searchSearch WhatsApp messagesARead-onlyIdempotent
Find messages by meaning and by words at once, in every chat or one: a paraphrase still hits; another language seldom does, so ask in the chat's language. match: "words" for exact words (a number, URL). since, until, from narrow it; full_text: whole texts; coverage, freshness: how much was searched.
| Name | Required | Description | Default |
|---|---|---|---|
| from | No | "me", a number, an id, or a name only one person has | |
| limit | No | ||
| match | No | "words": only messages holding the words | hybrid |
| query | Yes | ||
| since | No | ISO date or time | |
| until | No | ISO date or time | |
| 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 | Account id |
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 | |
| coverage | No | null: it could not be counted |
| messages | Yes | |
| freshness | Yes | |
| account_id | Yes | |
| 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 |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnlyHint=true, idempotentHint=true, destructiveHint=false), so the bar is lowered. The description adds two genuinely non-structured traits: a paraphrase still matches while another language seldom does, and results carry coverage/freshness about how much was searched. This is useful behavioral context, though thin and mostly about query semantics rather than tool effects.
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 purpose is front-loaded in the first clause and there is essentially no filler. The remainder is telescoped into semicolon fragments, which is efficient but occasionally cryptic ('coverage, freshness: how much was searched'), slightly hurting readability.
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 description needn't explain returns, and it covers the key search behavior and most parameters. It omits any mention of limit/account_id and doesn't tie into sibling tools, but for a 9-param search with 78% schema coverage and a defined output, the description is largely sufficient.
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 78% (near-high), so the baseline is 3. The description restates several documented params (match:'words', since/until/from narrowing, full_text) and adds marginal value with the 'number, URL' example for exact matching. It adds little beyond the schema for limit, account_id, or chat_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 verb+resource is specific: 'Find messages by meaning and by words at once,' which conveys the hybrid semantic/keyword search in a way that no sibling name alone does. Scope ('in every chat or one') is stated. It stops short of naming a sibling (read_messages, get_message, catch_up) to disambiguate, so it's clear but not differentiated against relatives.
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 query-time guidance ('ask in the chat's language,' use match:'words' for exact words like a number or URL), which implies when this tool fits. But it never states when not to use it or names an alternative (e.g., read_messages for browsing a chat), so the when-to-use vs alternatives is left to inference.
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 | Account id | |
| 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?
Annotations already declare this as a non-destructive write (readOnlyHint=false, destructiveHint=false), so the safety profile is covered; the description adds the genuinely behavioral facts that nothing is sent, that it returns draft_id and preview, and that a confirmation gate exists. It stops short of disclosing draft persistence/expiry or auth requirements, 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?
Roughly two-and-a-half sentences with zero waste: the draft/send distinction and the required inputs lead, and the confirm protocol follows. Every clause carries operational weight, and the preview-then-confirm flow is front-loaded where an agent needs 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 16-parameter tool with no output schema, the description correctly compensates by explaining what comes back (draft_id, preview contents) and how the two-phase draft/confirm workflow proceeds. The remaining parameter surface (send_at, time_zone, mention_ids, account_id) is documented in the schema, though the description never signals scheduling or mentions at all.
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 high at 81%, so the schema already carries most parameter meaning; the description's mention of media, polls, locations and forwards loosely maps to the as/options/latitude/forward groups but adds no syntax or format detail. It reinforces the required recipient+text pair but does not go beyond the structured fields.
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 (drafts) plus the full range of content it can produce (text, media, polls, locations, forwards) and immediately resolves the name's ambiguity with "sends nothing." It distinguishes itself from confirm_send, which is the sibling that actually sends, so an agent can tell the two apart 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 explicit routing to the alternative ("confirm_send only on a yes to this text and recipient"), including an edge case that a send in the same request counts as that yes. Nothing about when versus when-not is left 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 | Account id | |
| 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 declare readOnlyHint, openWorldHint, idempotentHint, and non-destructive behavior. The description adds value beyond these by explaining cursor semantics ('nothing that lands between calls is missed') and the exact behavior of addressed_to_me (wakes only for direct messages, mentions, replies). No contradictions.
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 sentences, front-loaded with the core action, no filler. Every clause contributes: the wait behavior, timeout, cursor use, filter semantics, and intended use case. Highly efficient.
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 format is not required. The description covers waiting, timeout, cursor handling, and filter behavior. An agent has everything needed to call it correctly and integrate it into a polling loop. No critical 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 60% — cursor, chat_id, and account_id have descriptions, but addressed_to_me and timeout_seconds do not. The description explicitly explains both: timeout_seconds via 'up to timeout_seconds' and addressed_to_me via its wake filter. This fully compensates for the undocumented parameters, going beyond 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 clearly states the verb 'wait' with resource 'messages from other people' and a timeout. It distinguishes itself from read_messages by emphasizing waiting/blocking, and mentions the cursor for continuity. The purpose is specific and unambiguous.
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 phrase 'For agents that stay on the line' provides context for when to use this tool, and the cursor instruction implies a polling loop. However, it does not explicitly state when not to use it (e.g., for reading existing messages, use read_messages instead). The guidance is implied rather than explicit, so a 4 is appropriate.
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.
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 distinct action (send_message vs confirm_send vs edit_message clearly separated; find_contact vs list_contacts distinct). The message-reading cluster (read_messages, get_message, search, catch_up, wait_for_messages) risks overlap, but the very detailed descriptions draw clear boundaries. One or two could still be confused at a glance.
Casing is uniformly snake_case, which is good, but the verb_noun pattern is not maintained: get_/list_/read_/manage_/find_ sit alongside bare nouns and verbs (learn, reminder, remember, search, catch_up, scheduled_messages, wait_for_messages). Readable overall, but the verb choice for reading tools (get_status, list_chats, read_messages) is inconsistent.
23 tools is on the heavy side for an agent surface and lands in the 16-25 range. The WhatsApp domain is genuinely broad (messages, chats, groups, contacts, media, scheduling, reminders, status), so each tool is defensible, but the set is large enough that navigation costs are real.
Coverage is strong: linking, status, read/search/get, draft-confirm send lifecycle, edit, delete, react, chat and group administration, contacts, media, scheduling, reminders, memory and catch-up are all present. Only minor gaps remain (e.g. no dedicated forward/poll-creation tool, though both are folded into send_message).
Maintenance
Related MCP Connectors
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.
MCP server connecting AI agents to 100+ apps (Gmail, Slack, Notion, GitHub) via one-click OAuth.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceWhatsApp MCP server that exposes messaging, groups, contacts, and profile management as tools and resources for AI agents, supporting Baileys and Meta Cloud API.25MIT
- 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.6 npmMIT
- 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.16 npm1MIT