WhatsMCP: MCP for WhatsApp
Server Details
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.
- Status
- Healthy
- Uptime
- 91.6% over 42 days
- OAuth
- Works in Glama
- Last Tested
- Transport
- Streamable HTTP · MCP 2025-11-25
- URL
TDQS
Scored across 46 tools
Most tools have clearly distinct purposes, but several clusters overlap: wa_list_messages vs wa_get_chat vs wa_get_message vs wa_load_history for reading messages, and wa_list_calls vs wa_ai_list_calls for call history. The detailed descriptions usually clarify boundaries, but an agent could still misselect within these clusters.
All tools use a wa_ prefix and predominantly verb_noun snake_case, e.g. wa_send_message, wa_list_groups, wa_create_template. Deviations exist in the AI-call group (wa_ai_call_start, wa_ai_call_get, wa_ai_call_hangup vs wa_ai_list_calls) and in wa_pair_status, but overall naming is predictable.
46 tools is far above the typical 3–15 range and the rubric's 25+ threshold. Although the WhatsApp domain is broad, the surface is heavy enough to burden tool selection and warrants a lower score.
The server covers a wide lifecycle: accounts/pairing, messaging, media, contacts, groups, channels, templates, webhooks, calls, AI calls, profile, presence, and plans. Minor gaps exist (e.g., sending video/stickers/location, chat management), but core workflows are well covered.
Available Tools
46 toolswa_ai_call_getGet an AI Voice-Agent CallARead-onlyInspect
Read an AI call started with wa_ai_call_start: status (dialing, in_progress, done, failed, no_answer, busy), and once it has ended the summary, whether the agent judged it successful, the data it collected, the transcript, and a recording_url valid for one hour.
| Name | Required | Description | Default |
|---|---|---|---|
| call_ref | Yes | from wa_ai_call_start |
Output Schema
| Name | Required | Description |
|---|---|---|
| call | No | the call; transcript, summary and data fill in once it has ended |
| next | No | what to do next |
| refusal | No | present only when the request was declined |
| recording_url | No | MP3 of the call, valid for one hour; present once recording_state is saved |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, but the description adds real behavioral detail beyond them: the full status vocabulary, the fact that summary/success/collected-data/transcript only exist once the call has ended, and a one-hour expiry on recording_url. Those are exactly the operational details an agent cannot get from the structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One front-loaded sentence: verb and resource first, then the status list, then the post-completion fields. The tail is cumulative and dense, but every clause (status set, post-end availability, URL expiry) carries information an agent needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Return shape is backed by an output schema, yet the description still tells the agent which fields are conditional and when the recording link expires. Nothing needed to invoke this correctly 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?
The single call_ref parameter is 100% documented in the schema, and the description only restates its origin ('started with wa_ai_call_start'). With coverage this high the schema is doing the work, so 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?
The description opens with a specific verb+resource ('Read an AI call') and immediately scopes it to calls created by wa_ai_call_start, which cleanly separates it from wa_ai_list_calls and wa_ai_call_hangup. The enumerated status values confirm exactly what kind of object is returned.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Read an AI call started with wa_ai_call_start' establishes the prerequisite and implies polling, since statuses like dialing/in_progress indicate it is meant to be called before the call ends. It never names a sibling alternative or states an explicit when-not condition, so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_ai_call_hangupHang Up an AI Voice-Agent CallADestructiveIdempotentInspect
End a live AI voice-agent call — one you started with wa_ai_call_start, or an incoming call an agent answered. The call is hung up at once for both sides; its summary, transcript and recording then arrive as for any call (wa_ai_call_get). A call that has already ended is left alone (hung_up false).
| Name | Required | Description | Default |
|---|---|---|---|
| call_ref | Yes | the call to end, from wa_ai_call_start or wa_ai_list_calls |
Output Schema
| Name | Required | Description |
|---|---|---|
| next | No | what to do next |
| status | No | the call's status as recorded when you asked; it settles to done within a minute of a hangup |
| hung_up | Yes | true when the call was live and has been ended; false when it had already ended |
| refusal | No | present only when the request was declined |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag destructiveHint=true and idempotentHint=true, but the description adds real substance: the hangup is immediate and affects both parties, and calls that have already ended are left untouched with hung_up false. That tells the agent what actually happens on a repeat call, beyond the bare idempotency hint.
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 short sentences, front-loaded with the action, then effect, then downstream result and the idempotent edge case. 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?
For a single-parameter mutation with annotations and an output schema present, the description covers everything an agent needs: what it does, who it affects, what happens on repeat invocation, and where the artifacts surface afterwards.
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?
Only one parameter (call_ref) at 100% schema coverage, so the schema already explains it fully. The description adds a little framing by implying the ref must reference a live call, but no format or sourcing detail beyond what the schema states.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a precise verb+resource: 'End a live AI voice-agent call', and scopes it to calls started via wa_ai_call_start or answered incoming calls. That distinguishes it cleanly from wa_ai_call_start (initiate) and wa_ai_call_get (retrieve results) without needing the schemas.
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 says which calls it applies to (ones started with wa_ai_call_start or answered by an agent) and routes the agent to wa_ai_call_get for the resulting summary/transcript/recording. It also carves out the no-op case (already-ended calls). It does not name wa_ai_list_calls as the way to obtain a call_ref, which the schema does instead.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_ai_call_startStart an AI Voice-Agent CallAInspect
Have an AI voice agent call a WhatsApp number from one of your numbers, using a preset from wa_ai_list_presets. Pass per-call context in variables. Returns immediately with a call_ref; the call then rings and runs on its own. Poll wa_ai_call_get about every 30 seconds until status is done, failed, no_answer or busy — then it carries the summary, transcript, collected data and a recording link. One call at a time per number; a number that just finished a call must wait a moment.
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | the WhatsApp number to call, international format, e.g. +447700900123 | |
| preset | Yes | the preset name, from wa_ai_list_presets | |
| variables | No | per-call context for the agent: flat string/number/boolean values, merged over the preset's defaults, e.g. {"customer_name":"Ann","order_id":"A-1042"} | |
| first_message | No | override what the agent says first on this call |
Output Schema
| Name | Required | Description |
|---|---|---|
| next | No | what to do next |
| status | No | dialing once accepted |
| refusal | No | present only when the call was not placed |
| call_ref | No | pass to wa_ai_call_get to follow the call |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: it discloses that the tool is asynchronous ('returns immediately with a call_ref; the call then rings and runs on its own'), names the terminal statuses, and states the concurrency/cooldown limits that explain the non-idempotent, non-read-only annotation profile. This is the kind of context the structured fields 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?
Four sentences, front-loaded with the action, then the return shape, then the polling loop, then the constraints. No filler and nothing important is buried.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an async mutation tool with an output schema and full schema coverage, the description supplies everything an agent needs: how the call is started, that it returns a call_ref, how to observe completion, and the concurrency limits that cause failures.
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 every parameter is already documented in the schema, including variables merge semantics and format examples. The description only restates that per-call context goes in variables and the preset comes from wa_ai_list_presets, adding little beyond the schema baseline.
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 ('Have an AI voice agent call a WhatsApp number from one of your numbers') plus the required configuration source (a preset). It is unambiguously distinct from wa_ai_call_get, wa_ai_call_hangup and wa_list_calls, which it does not rely on the name alone to separate.
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?
Explicit about the prerequisite (preset from wa_ai_list_presets), the follow-up workflow (poll wa_ai_call_get about every 30 seconds until status is done/failed/no_answer/busy), and the constraints (one call at a time per number, cooldown after a call finishes). An agent knows exactly when to use this and what to do next.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_ai_list_callsList AI Voice-Agent CallsARead-onlyInspect
List this workspace's AI voice-agent calls, newest first: outbound calls started with wa_ai_call_start and inbound WhatsApp calls answered by a preset whose answers_inbound is true (direction says which; from is the caller of an inbound call). Use a call_ref with wa_ai_call_get for the transcript and recording link.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | how many to return, 1-100; defaults to 25 | |
| before | No | a call_ref from the previous page, to list older calls; omit for the newest |
Output Schema
| Name | Required | Description |
|---|---|---|
| next | No | pass as before for the next, older page; absent on the last page |
| calls | Yes | AI calls, newest first — outbound ones you started and inbound ones an answering preset took; each call_ref works with wa_ai_call_get |
| refusal | No | present only when the request was declined |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and idempotentHint=false, so safety is covered; the description adds real context beyond that: newest-first ordering, pagination via a call_ref from the previous page, and how to interpret the direction and from fields on inbound calls. It does not discuss whether the full history or only a recent window is available, which is the one remaining behavioral unknown.
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, zero waste, and the decisive information (what is listed, ordering) is front-loaded before the follow-up routing hint. Dense but every clause carries meaning.
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?
A read-only lister with an output schema, 100% parameter coverage, and annotations covering safety; the description supplies scope, ordering, pagination pattern, and the next-step tool. Nothing needed to invoke it correctly 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 description coverage is 100% and both parameters are documented in the schema (limit 1-100 default 25; before as a call_ref from the previous page). The description's mention of 'newest first' and the cursor-style paging corroborates but does not extend the schema, so the baseline of 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 ('List this workspace's AI voice-agent calls, newest first') and then defines exactly which calls qualify: outbound calls started with wa_ai_call_start and inbound WhatsApp calls answered by a preset with answers_inbound true. This scope definition is what separates it from the generic wa_list_calls, so an agent can distinguish it 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?
Explicitly routes the agent forward: 'Use a call_ref with wa_ai_call_get for the transcript and recording link.' That is clear context for the natural follow-up. It does not, however, state when to prefer the sibling wa_list_calls (non-AI calls) or anything about what is excluded, leaving one plausible routing question unanswered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_ai_list_presetsList AI Voice-Agent PresetsARead-onlyInspect
List the AI voice-agent presets of this workspace. A preset pairs a voice agent with one of your WhatsApp numbers (the line it calls from) and default variables. Use a preset's name with wa_ai_call_start; only presets with ready=true can call now (not_ready_reason says why otherwise). expected_variables are the variables the agent's prompt uses — pass them to wa_ai_call_start.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| presets | Yes | your presets; call wa_ai_call_start with a preset whose ready is true |
| refusal | No | present only when the request was declined |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
While annotations cover the safety profile, the description provides vital operational context: a preset pairs multiple entities (agent/number/vars) and dictates the caller's logic regarding the 'ready' status and 'not_ready_reason'. This adds significant value beyond the 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 definition is densely packed but highly efficient. Every sentence delivers a specific piece of actionable information, progressing from definition to usage and finally to dependency requirements.
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 that it is a 0-parameter read-only list operation, the description is perfectly complete. It addresses the 'how' (call start) and the 'status' (ready=true) needed for successful integration.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With zero parameters and 100% schema coverage, the baseline is strong. The description compensates slightly by defining the structure of the resource itself (what the preset object contains), ensuring the agent understands the context of the returned data.
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?
It clearly states the action ('List') and the specific resource ('AI voice-agent presets'). Furthermore, it defines what a preset encompasses (agent, WhatsApp number, variables), providing immediate conceptual clarity.
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 explicit instructions on how to consume the output by naming the required sibling tool (wa_ai_call_start). It also provides necessary run-time usage logic, stating that only presets with 'ready=true' can be used.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_block_contactBlock or Unblock ContactAInspect
Block a contact on one of your WhatsApp accounts, so they can no longer call or message it — or set unblock=true to unblock one. Reports who it acted on: their number, the name this account's address book has for them, and the country the number belongs to.
| Name | Required | Description | Default |
|---|---|---|---|
| jid | Yes | the contact — a phone number in international form or a full JID | |
| unblock | No | true to unblock a previously blocked contact instead | |
| account_id | Yes | the account, as returned by wa_list_accounts |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | ok (the operation succeeded) or refused (nothing was done) |
| blocked | No | every contact on the account's blocklist (wa_list_blocked only) |
| contact | No | the contact that was blocked or unblocked (wa_block_contact only) |
| refusal | No | present only when status is refused |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds genuine behavioral context beyond the annotations: the real-world consequence (contact can no longer call or message) and the shape of the result (number, address-book name, country). Annotations declare readOnlyHint=false and destructiveHint=false but say nothing about effect; the description fills that gap. It stops short of noting auth requirements or behavior on already-blocked/unknown contacts.
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 primary operation and the consequence, followed by the alternate mode and result shape. No filler; 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 a complete input schema, an output schema, and presence annotations, the description covers the remaining burden (effect of blocking, unblock mode) well. Minor gaps: no guidance on idempotency/already-blocked contacts and no cross-reference to wa_list_blocked, which sits right next to 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?
Schema description coverage is 100%, so jid, account_id, and unblock are already fully documented (including the 'as returned by wa_list_accounts' hint). The description restates the unblock toggle and adds no new syntax or format detail, 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 (block/unblock) on a specific resource (a contact on a WhatsApp account), plus the concrete effect ('can no longer call or message it'). Cleary distinguishes the two modes via the unblock flag, so an agent knows exactly what it does 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 clear context for use ('on one of your WhatsApp accounts') and explains the toggle case — set unblock=true to unblock rather than calling a different tool. It does not, however, reference siblings such as wa_list_blocked for checking current block state, nor does it state exclusions (e.g., what happens if the contact is already blocked).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_create_groupCreate GroupAInspect
Create a WhatsApp group with a name and initial members from one of your accounts. Returns the new group's JID (use it as wa_send_message's 'to') and an invite link.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | the group name (max 25 characters) | |
| members | No | initial members — phone numbers (E.164) or JIDs, comma- or space-separated; do NOT include your own number | |
| account_id | Yes | the account to create the group from, as returned by wa_list_accounts |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | No | the rows of a list operation |
| status | Yes | ok (the operation succeeded) or refused (see refusal; for wa_update_group, applied lists the changes that took effect before it) |
| applied | No | wa_update_group only: the settings that were changed, in order — on a refusal, the ones that took effect before it |
| refusal | No | present only when status is refused |
| summary | No | a human-readable result |
| group_jid | No | the new group's JID (wa_create_group only) — use it as wa_send_message's 'to' |
| invite_link | No | the group's invite link (wa_create_group or wa_get_group_invite_link) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare non-read-only and non-idempotent, and the description adds the useful downstream behavior: the returned JID should be passed to wa_send_message's 'to'. It does not warn that retries create duplicate groups (relevant given idempotentHint=false), which is a missed opportunity for a mutating tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the action and immediately followed by the return value and the cross-tool handoff. No filler or redundant restatement of structured fields.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given an output schema exists, the description needn't explain returns, yet it usefully names the JID and invite link and links the JID to a sibling call. The only gap is the absence of any warning about non-idempotent behavior or account validity prerequisites for a mutation 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 100%, so the schema already carries the detailed semantics (25-char name limit, E.164/JID member formatting, excluding your own number). The description only restates 'name and initial members' at a high level, adding no meaning beyond the schema, so 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 ('Create a WhatsApp group') plus the required inputs, so the action is unambiguous. It does not explicitly distinguish itself from nearby siblings such as wa_join_group or wa_update_group, leaving that inference to the agent.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied by the verb 'Create' and the phrase 'from one of your accounts', which hints at an account prerequisite. There is no explicit when-to-use versus wa_join_group/wa_update_group guidance and no mention of failure or prerequisite conditions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_create_templateCreate WhatsApp Business TemplateAInspect
Submit a new WhatsApp Business message template for Meta's review on one of your Business (Cloud API) numbers. Meta reviews it (usually minutes, sometimes longer); it can be sent with wa_send_message's template option only once wa_list_templates shows it APPROVED. Categories: MARKETING or UTILITY. Number body variables {{1}}, {{2}}, … in order and give one body_examples value per variable. Templates apply only to Business numbers.
| Name | Required | Description | Default |
|---|---|---|---|
| body | Yes | the message text, at most 1024 characters; variables are {{1}}, {{2}}, … numbered in order | |
| name | Yes | lowercase letters, digits and underscores, e.g. order_update | |
| footer | No | optional footer, at most 60 characters, no variables | |
| header | No | optional text header, at most 60 characters and one {{1}} variable | |
| buttons | No | optional buttons: at most 10, of which at most 2 URL and 1 PHONE_NUMBER | |
| category | Yes | MARKETING or UTILITY | |
| language | No | language code such as en_US (the default), en or pt_BR | |
| account_id | Yes | the Business (Cloud API) account to create the template on, as returned by wa_list_accounts | |
| body_examples | No | one example value per body variable, in order — Meta's reviewers read them | |
| header_example | No | example value for the header's {{1}}, required when it has one | |
| call_permission | No | true asks the customer to allow the business to call them (WhatsApp's call permission request); MARKETING or UTILITY only, and no buttons |
Output Schema
| Name | Required | Description |
|---|---|---|
| refusal | No | present only when the call was declined |
| template | No | the submitted template |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond annotations, the description discloses the asynchronous Meta review process, typical review duration, and the APPROVED-gating requirement before the template can be used. It also clarifies that body variables must be numbered in order with one example per variable, which is important behavioral context for submission.
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 front-loaded with the core action and review workflow, then adds only high-value constraints about categories, variables, examples, and Business-only applicability. Every sentence carries useful information without unnecessary repetition.
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 11-parameter schema, full schema coverage, annotations, and an output schema, the description provides the necessary workflow context: review, approval gating, Business-number restriction, category constraints, and variable/example expectations. An agent has enough information to invoke the tool correctly without needing return-value details in the description.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all 11 parameters in detail. The description reinforces category, body-variable ordering, and body_examples alignment, but most parameter semantics are carried by the schema rather than the description, making 3 the appropriate baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: submit a new WhatsApp Business message template for Meta review on a Business (Cloud API) number. It also distinguishes the creation action from downstream use by naming wa_list_templates for approval status and wa_send_message for sending an approved template.
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 context is clear: this creates a template for Meta review, templates only apply to Business numbers, categories must be MARKETING or UTILITY, and sending is only possible after wa_list_templates shows APPROVED. It does not explicitly contrast with sibling operations like wa_delete_template, but the create-specific purpose is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_delete_groupDelete GroupADestructiveInspect
Delete a WhatsApp group: remove every other member and then leave. The account must be a group admin. WhatsApp has no true group-delete, so this empties the group and exits it.
| Name | Required | Description | Default |
|---|---|---|---|
| group_jid | Yes | the group (…@g.us) JID to delete, as returned by wa_list_groups | |
| account_id | Yes | the account, as returned by wa_list_accounts |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | No | the rows of a list operation |
| status | Yes | ok (the operation succeeded) or refused (see refusal; for wa_update_group, applied lists the changes that took effect before it) |
| applied | No | wa_update_group only: the settings that were changed, in order — on a refusal, the ones that took effect before it |
| refusal | No | present only when status is refused |
| summary | No | a human-readable result |
| group_jid | No | the new group's JID (wa_create_group only) — use it as wa_send_message's 'to' |
| invite_link | No | the group's invite link (wa_create_group or wa_get_group_invite_link) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=false; the description adds the critical non-obvious behavior that WhatsApp has no true group-delete and the group is emptied and exited instead. That is exactly the kind of consequence an agent needs before invoking a destructive operation, plus the auth prerequisite.
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 short sentences, action first, then precondition, then the caveat that explains the mechanism. No filler and nothing that could be cut without losing information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter destructive mutation with full annotation coverage, a complete schema and an output schema, the description covers purpose, authorization requirement, and the surprising side effect. Nothing an agent needs in order to decide or call 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 description coverage is 100% and both parameters (group_jid, account_id) document where their values come from, so the schema does the heavy lifting. The description only implies that group_jid identifies the target and adds no format or edge-case detail beyond that, so 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 ('Delete a WhatsApp group') and immediately explains the mechanism — remove every other member then leave — which is exactly what separates it from wa_leave_chat and wa_remove_participants. An agent can distinguish the three without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a hard prerequisite ('The account must be a group admin'), which is real usage guidance for selecting and calling it correctly. It stops short of explicitly naming alternatives such as wa_leave_chat for a non-admin exit, so the when-not case 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.
wa_delete_messageDelete MessageADestructiveInspect
Delete a WhatsApp message for everyone. WhatsApp has no true delete for a peer that already has the message locally — this revokes it, which every modern client honours.
| Name | Required | Description | Default |
|---|---|---|---|
| chat | Yes | the chat the message is in — a phone number or a group/channel JID | |
| sender | No | group chats only, admin accounts: the phone number or JID of whoever sent the message being deleted; omit for your own message | |
| account_id | No | the account, as returned by wa_list_accounts; omit it when the workspace has only one account | |
| message_id | Yes | WhatsApp's id for the message, as returned by wa_send_message or seen in wa_list_messages |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | ok (the operation succeeded) or refused (nothing was done) |
| refusal | No | present only when status is refused |
| new_message_id | No | WhatsApp's id for the react/edit/revoke protocol message itself |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag destructiveHint=true and idempotentHint=false, so the safety profile is covered; the description still adds real value by explaining that this is a revoke rather than a true delete and that modern clients honour it. It stops short of stating irreversibility or any time-limit/failure conditions on revocation.
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, the action front-loaded and the semantic caveat immediately after. Every clause earns its place — nothing redundant with the schema or annotations.
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 and all four parameters are fully documented, so the description's only remaining burden is the action's semantics — which it covers by explaining revocation. Nothing an agent needs to call this correctly 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 description coverage is 100%, so the schema already explains chat, sender, account_id and message_id in detail; the description adds no parameter-level guidance. Baseline 3 applies since the schema does the heavy lifting.
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 ('Delete a WhatsApp message') plus the scope 'for everyone', which separates it from wa_edit_message and the unrelated delete siblings (wa_delete_group, wa_delete_template, wa_delete_webhook). The revocation clarification further pins down what kind of delete this is.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied: the revocation note tells the agent this removes a message for all recipients, but it never states when to prefer this over wa_edit_message, nor any precondition (e.g. only your own messages unless admin, per the sender param). No explicit when/when-not routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_delete_templateDelete WhatsApp Business TemplateADestructiveInspect
Delete a WhatsApp Business message template from one of your Business (Cloud API) numbers — one language, or every language of the name when language is omitted. Meta blocks reusing a deleted template's name for a while.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | the template name | |
| language | No | delete only this language, e.g. pt_BR; omit to delete every language of the name | |
| account_id | Yes | the Business (Cloud API) account that owns the template |
Output Schema
| Name | Required | Description |
|---|---|---|
| deleted | No | true when Meta deleted it |
| refusal | No | present only when the call was declined |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=false, so the description's added value is the Meta-side consequence: a deleted template's name is blocked from reuse for a while. That is genuinely useful non-obvious behavior, though it stops short of saying what happens when the name or language doesn't exist.
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 front-loaded sentence that packs scope, the language-omission rule, and the name-reuse warning with no 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?
An output schema exists and annotations cover the destructive profile, so the description only needs scope and side effects, both of which it supplies. The one gap is behavior on invalid name/language or partial multi-language deletion failures, which an agent might reasonably want before invoking a destructive call.
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 the schema already documents all three parameters including the 'omit to delete every language' semantics. The description only restates the language-omission rule and adds no format details (e.g. case sensitivity, locale validation), so 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?
Specific verb (delete) plus resource (WhatsApp Business message template) and scope (one language, or all languages when omitted). It is clearly distinguishable from the sibling wa_create_template and from other wa_delete_* tools that target messages, groups, or webhooks.
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 implies when to use it by describing the two deletion modes, but it never names the alternative (e.g. wa_list_templates to find the name first, or wa_create_template to recreate) and gives no prerequisites such as permissions or confirming the template exists. Usage is inferable but not spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_delete_webhookDelete WebhookADestructiveInspect
Stop delivering inbound messages to the configured endpoint. Messages keep arriving and stay readable through wa_list_messages; only the push stops.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| note | No | |
| deleted | Yes | |
| refusal | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and readOnlyHint=false, so the safety profile is covered. The description adds real value beyond that by clarifying the blast radius — inbound messages keep arriving and stay readable via wa_list_messages, only the push stops — which tells the agent no data is lost. It stops short of saying whether the endpoint configuration is removed irreversibly or what happens on a second call.
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 zero filler; the effect leads and the important reassurance (messages still readable) follows immediately. 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?
An output schema and annotations carry the return and safety details, so the description only needs the behavioral picture, which it largely provides. The remaining gap is whether deleting the webhook is reversible or errors when no webhook is configured — a real but minor omission for a zero-parameter 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 tool takes zero parameters, so there is nothing for the description to disambiguate and the baseline of 4 applies. No parameter-level claims are made or needed.
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?
Names a specific action (stop push delivery) rather than restating the tool name, and describes the effect in user terms. However, it never distinguishes deletion from mere disabling, despite the sibling wa_enable_webhook sitting right next to it — an agent cannot tell whether this removes the endpoint configuration or just pauses it.
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 usage context is only implied: 'stop delivering inbound messages' suggests when to call it, and the note that messages remain available points an agent at wa_list_messages as the fallback. There is no explicit when-to-use/when-not, and no routing guidance versus wa_set_webhook or wa_enable_webhook.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_edit_messageEdit MessageAInspect
Edit a WhatsApp message you sent. WhatsApp only accepts an edit within about 20 minutes of the original send.
| Name | Required | Description | Default |
|---|---|---|---|
| chat | Yes | the chat the message is in — a phone number or a group/channel JID | |
| text | Yes | the replacement message body | |
| account_id | No | the account, as returned by wa_list_accounts; omit it when the workspace has only one account | |
| message_id | Yes | WhatsApp's id for the message, as returned by wa_send_message |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | ok (the operation succeeded) or refused (nothing was done) |
| refusal | No | present only when status is refused |
| new_message_id | No | WhatsApp's id for the react/edit/revoke protocol message itself |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare this is a non-read-only but non-destructive mutation, and the description adds platform-specific behavioral context the annotations cannot: the ~20-minute edit window enforced by WhatsApp. It does not say what happens when the window has expired (error vs silent no-op), which keeps 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?
Two short sentences with no filler; the core action comes first and the constraint second. Every sentence carries information the agent needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need no explanation, and the full parameter set is described in the schema. What remains is failure behavior past the 20-minute cutoff, which would help the agent decide between retrying and sending a new message.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so chat, text, message_id and account_id are already fully documented, and description adds little per-parameter detail. The 20-minute rule implicitly constrains which message_id values are valid, but the description does not state this about the parameter directly. 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 ('Edit a WhatsApp message you sent'), so the agent can distinguish it from wa_send_message and wa_delete_message by intent. It stops short of naming the sibling tools it supersedes in a given situation, but the action is 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 two concrete applicability conditions: the message must be one 'you sent' and the edit must occur within roughly 20 minutes of the original. That is real guidance an agent can act on, though it never explicitly contrasts with alternatives such as sending a new message instead.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_enable_webhookPause or Resume WebhookAIdempotentInspect
Pause or resume delivery to the configured webhook WITHOUT changing the endpoint or its signing secret. Use this to stop deliveries temporarily — deleting and re-creating the webhook would issue a new secret. Messages keep arriving while paused and stay readable with wa_list_messages.
| Name | Required | Description | Default |
|---|---|---|---|
| reason | No | optional note recorded with a pause, shown in the console | |
| enabled | Yes | true resumes delivery, false pauses it; the endpoint and its signing secret are kept either way |
Output Schema
| Name | Required | Description |
|---|---|---|
| note | No | |
| enabled | Yes | |
| refusal | No | present only when the request was declined |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already signal non-destructive, idempotent mutation, but the description adds genuine operational context beyond them: credentials are preserved, delivery halts rather than data, and inbound messages continue to accumulate and remain readable. That is exactly the kind of side-effect detail annotations cannot express.
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 short sentences, front-loaded with the core action and the non-obvious constraint (secret preservation), then the usage scenario, then the follow-on reference. Nothing is repeated for 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?
An output schema exists, so return values need no explanation. With annotations covering safety and idempotency, and the description covering state effects and post-pause behavior, an agent has everything needed to invoke this correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and both parameter descriptions already explain that true resumes, false pauses, and that the endpoint/secret are kept. The description's 'WITHOUT changing the endpoint or its signing secret' reinforces the enabled flag but adds no new syntax or edge-case meaning, so the baseline of 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 the specific action (pause or resume webhook delivery) and the resource (the configured webhook) with emphasis that the endpoint and signing secret are untouched. This cleanly separates it from wa_delete_webhook and wa_set_webhook, which are the siblings an agent could otherwise confuse it with.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly frames the when-to-use case ('stop deliveries temporarily') and the when-not case by naming the destructive alternative ('deleting and re-creating the webhook would issue a new secret'). It also points to wa_list_messages as the path for messages received during a pause, so the agent knows what to do next.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_follow_channelFollow ChannelBInspect
Follow a WhatsApp Channel from one of your accounts using its link.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | Yes | the account to follow from, as returned by wa_list_accounts | |
| channel_link | Yes | the channel link (https://whatsapp.com/channel/…) or bare invite key |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | No | the rows of a list operation |
| status | Yes | ok (the operation succeeded) or refused (see refusal; for wa_update_group, applied lists the changes that took effect before it) |
| applied | No | wa_update_group only: the settings that were changed, in order — on a refusal, the ones that took effect before it |
| refusal | No | present only when status is refused |
| summary | No | a human-readable result |
| group_jid | No | the new group's JID (wa_create_group only) — use it as wa_send_message's 'to' |
| invite_link | No | the group's invite link (wa_create_group or wa_get_group_invite_link) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already disclose the mutating, non-idempotent, non-destructive profile. The description adds the useful detail that the action is scoped to a specific account and driven by a channel link, but it stays silent on what happens on a repeat follow or whether the channel appears in wa_list_channels afterwards.
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 well-formed sentence with the action and the two required inputs front-loaded. There is no filler or redundancy.
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 explained, and both required parameters are covered by the schema. What the description omits is the behavioral edge cases (already-following, invalid invite key, rate limits) that an agent needs before invoking a non-idempotent mutation.
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 the schema even names wa_list_accounts for account resolution and the accepted link formats. The description's phrasing ('from one of your accounts', 'using its link') just restates both parameters, 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?
The description gives a specific verb and resource ('Follow a WhatsApp Channel'), plus the qualifier 'from one of your accounts using its link'. That clearly separates it from wa_join_group and wa_list_channels, though it doesn't name those siblings explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description never says when to choose this tool over alternatives (e.g. wa_list_channels to inspect first) or what happens if the account already follows the channel. Usage is only inferable from the name and title.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_get_chatGet ChatARead-onlyInspect
Read the most recent messages for one account (WhatsApp or Telegram), oldest first — or, with chat, one conversation, including older history loaded with wa_load_history. Use this for context before replying; use wa_list_messages to page through everything new. Narrow with since/until (when sent; until is exclusive).
| Name | Required | Description | Default |
|---|---|---|---|
| chat | No | read ONE conversation — a phone number or a group JID — including history loaded with wa_load_history; omit for the account's most recent messages across all chats | |
| limit | No | how many recent messages, 1-200; defaults to 50 | |
| since | No | only messages sent at or after this time: RFC3339 with a zone (2026-10-01T09:00:00+03:00) or a date (2026-10-01 = midnight UTC); omit for no lower bound | |
| until | No | only messages sent BEFORE this time — exclusive, so all of 1 October is since 2026-10-01 until 2026-10-02; same formats as since; omit for no upper bound | |
| account_id | No | the account whose conversation to read, from wa_list_accounts; omit it when the workspace has only one account | |
| include_media_urls | No | also return attachment.media_url on each available attachment — a time-limited (1h) signed URL to GET the bytes with plain HTTP instead of a wa_get_media call; off by default |
Output Schema
| Name | Required | Description |
|---|---|---|
| account | No | the account this conversation was read from |
| refusal | No | present only when the request was declined |
| has_more | No | true when older messages match than were returned; page them with wa_list_messages(account_id, chat, since, until, include_history=true) |
| messages | Yes | recent messages for this account, oldest first |
| account_notices | No | present when a number this read covers is not working: new messages are not arriving on it; says why and what to do |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, and the description adds real behavioral detail beyond them: results are ordered oldest-first, the `chat` form includes history loaded via wa_load_history, and the time window is on send time with exclusive `until`. It does not explain the idempotentHint=false result (e.g. signed media URLs / shifting window), which is the one behavioral question left open.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the verb and resource, and every clause carries weight (scope switch, ordering, history, sibling routing, time semantics). It is a single dense sentence, though, so the two distinct modes are slightly harder to parse than they need be.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, and the description still covers ordering, default account scope, and history inclusion — enough to call it correctly. Missing only minor operational context such as the default limit and what happens when `chat` is an unknown JID.
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 every parameter is already documented in detail (limit range, RFC3339/date formats, media URL expiry). The description only restates the since/until and chat semantics, adding no syntax or edge-case information beyond the schema — 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 (read recent messages) plus the scope switch: account-wide by default, single conversation when `chat` is supplied. It also names the sibling used for paging (wa_list_messages), so an agent can separate it from wa_get_message and wa_list_messages 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 use case ("for context before replying") and an explicit alternative with its condition ("use wa_list_messages to page through everything new"). It also points at wa_load_history as the source of older history, so the routing decision is fully determined.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_get_group_invite_linkGet Group Invite LinkAInspect
Get a WhatsApp group's invite link, or set reset=true to revoke it and issue a new one. The account must be a group admin.
| Name | Required | Description | Default |
|---|---|---|---|
| reset | No | true to revoke the current link and issue a new one | |
| group_jid | Yes | the group (…@g.us) JID, as returned by wa_list_groups | |
| account_id | Yes | the account, as returned by wa_list_accounts |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | No | the rows of a list operation |
| status | Yes | ok (the operation succeeded) or refused (see refusal; for wa_update_group, applied lists the changes that took effect before it) |
| applied | No | wa_update_group only: the settings that were changed, in order — on a refusal, the ones that took effect before it |
| refusal | No | present only when status is refused |
| summary | No | a human-readable result |
| group_jid | No | the new group's JID (wa_create_group only) — use it as wa_send_message's 'to' |
| invite_link | No | the group's invite link (wa_create_group or wa_get_group_invite_link) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=false, idempotentHint=false and destructiveHint=false; the description usefully adds that reset=true revokes the existing link and that admin rights are required — the two facts an agent most needs before calling. It does not flag that revocation is irreversible for existing members or what error appears for non-admins, so it improves on annotations without fully covering them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, zero filler, with the primary action first and the destructive variant second. The admin prerequisite is appended where it is cheap to read.
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 full input schema, an output schema and annotations present, the description only needs to carry prerequisites and mode behavior, which it does. Minor gaps remain on failure behavior for non-admins and whether the old link dies immediately after reset.
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%, with per-parameter descriptions already explaining reset, group_jid (…@g.us from wa_list_groups) and account_id (from wa_list_accounts). The description's mention of reset adds no semantics beyond the schema text, 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 (get a WhatsApp group's invite link) and explicitly covers the two modes: plain retrieval versus reset=true revocation plus reissue. No sibling tool touches invite links, so the agent can distinguish it immediately.
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?
'set reset=true to revoke it and issue a new one' gives a clear condition for the non-default mode, and 'The account must be a group admin' states a prerequisite. It stops short of naming exclusions or what to do on failure, keeping it at a strong 4 rather than a full when/when-not treatment.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_get_mediaGet MediaARead-onlyInspect
Fetch the attachment (image/video/audio/document/sticker) a received WhatsApp message carried. A small attachment comes back as base64 in media_base64; a large one comes back as media_url, a time-limited link to GET the bytes. Use the message_id from wa_list_messages. 'refused' means no retrievable media for that id.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | No | the account that received the message, from wa_list_accounts; omit it when the workspace has only one account | |
| message_id | Yes | the message id whose attachment to fetch, from wa_list_messages (a WhatsApp message id, or on a Telegram account one of the form <chat>_<n>) |
Output Schema
| Name | Required | Description |
|---|---|---|
| mime | No | |
| size | No | the attachment size in bytes |
| status | Yes | ok (media returned, inline or as a url) or refused |
| refusal | No | |
| media_url | No | a time-limited (1h) URL to GET a large attachment's bytes, present instead of media_base64 when the attachment is over the inline cap |
| media_base64 | No | base64 of the attachment, present for a small attachment |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes far beyond standard annotations by detailing the behavioral differences in the output: small attachments return `media_base64` while large ones return a `media_url`. It also explains the meaning of the 'refused' status.
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 dense and informative but logically structured. It front-loads the primary function and then elaborates on the operational details (output types, failure modes) and dependency.
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 definition is complete for this specific use case. It covers what is fetched, how the output will look (URL vs Base64), the required input source, and the negative result, which covers all necessary concerns for an AI agent.
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?
Although schema coverage is 100%, the description provides essential semantic guidance by specifying that `message_id` must be retrieved specifically from `wa_list_messages`. This context is vital for correct orchestration.
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 tool is clearly defined to fetch media attachments (image/video/audio/etc.) from a received WhatsApp message. The naming convention and description immediately establish its purpose within the communication context.
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 a crucial usage dependency: the `message_id` must be sourced from the `wa_list_messages` tool, preventing agents from using arbitrary IDs. It also defines the failure state ('refused').
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_get_messageGet MessageARead-onlyInspect
Fetch ONE stored message from one of your accounts, by WhatsApp's message_id (as a webhook delivery or wa_list_messages gave it) or by its cursor. Use this to read the message a webhook told you about, or the one you are about to react to, edit or delete, without paging through history.
| Name | Required | Description | Default |
|---|---|---|---|
| cursor | No | the message's cursor, as wa_list_messages returned it (a webhook delivery carries it as message_seq). Pass this or message_id | |
| account_id | No | the account the message belongs to, from wa_list_accounts; omit it when the workspace has only one account | |
| message_id | No | WhatsApp's id for the message — the message_id a webhook delivery, wa_list_messages or wa_send_message gave you. Pass this or cursor | |
| include_media_urls | No | also return attachment.media_url when the message carries an available attachment — a time-limited (1h) signed URL to GET the bytes with plain HTTP instead of a wa_get_media call; off by default |
Output Schema
| Name | Required | Description |
|---|---|---|
| message | No | the message; absent when the request was declined |
| refusal | No | present only when the request was declined — including when no such message is stored |
| account_notices | No | present when a number this read covers is not working: new messages are not arriving on it; says why and what to do |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, and the description reinforces the non-mutating single-record read while adding that the caller avoids paging. It also points out that media bytes are normally fetched separately, though it does not state what happens when neither cursor nor message_id resolves.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One sentence for the what and keys, a second for the when, front-loaded with no filler. Every clause carries information an agent can act on.
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 full output schema and fully described parameters, the description only needs to justify the lookup path and the intended use, both of which it covers. Nothing an agent needs in order to call it correctly 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 100% and the schema already documents cursor vs message_id and the 1h signed media URL. The description only echoes that message_id comes from a webhook or wa_list_messages and adds no format or precedence detail beyond the parameter definitions, so 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 ('Fetch ONE stored message') and names the exact lookup keys (message_id or cursor). The capitalized 'ONE' plus 'without paging through history' separates it cleanly from wa_list_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?
Gives concrete triggers: read the message a webhook told you about, or the one you are about to react to, edit or delete. It implies history browsing belongs to wa_list_messages rather than naming it as the alternative with an explicit exclusion, so the routing guidance is clear but not fully spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_get_planGet PlanARead-onlyInspect
Show a plan, its limits and current usage. Plans are per WhatsApp number: pass account_id to see ONE number's plan, limits and the tools it does not include (excluded_tools); omit it for the whole workspace — every number's plan and limits (lines), with excluded_tools listing only what NO active number can use, and plan "mixed" when the numbers are on different plans. A tool listed on this server may still be refused on a number whose plan leaves it out; a tool called WITHOUT account_id acts on every number, so it needs every active number's plan to include it. Call this to see why a tool answers plan_required on a given number, why wa_send_message might be refused, or how much headroom is left. It also reports this service's version (server_version, server_build_date).
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | No | optional: report one line's plan; omit to report every line |
Output Schema
| Name | Required | Description |
|---|---|---|
| plan | Yes | the plan's slug, e.g. free, starter, pro — an identifier; show display_name to a person |
| lines | No | every line's plan and limits, present only for the workspace view |
| refusal | No | present only when account_id names a line that cannot be used |
| voice_plan | Yes | the SIP calls this plan allows, or null when it allows none — or, for a workspace whose numbers are on different plans, null: see each line's calls_inbound/calls_outbound |
| description | No | what the plan includes, for a human |
| messages_1h | Yes | the hourly message-send limit and usage |
| display_name | Yes | the plan's name as the customer sees it, e.g. Free, Pro |
| history_days | Yes | how long messages are retained, in days; 0 means forever |
| messages_24h | Yes | the 24-hour message-send limit and usage |
| excluded_tools | No | tools listed on this server that your plan does not include; calling one returns a plan_required refusal |
| server_version | Yes | the version of this MCP service |
| accounts_paired | Yes | WhatsApp numbers currently paired |
| webhooks_enabled | Yes | whether this plan can register inbound webhooks |
| max_attachment_mb | Yes | largest attachment this plan can send, in MB; 0 means unlimited |
| server_build_date | Yes | when that version was built |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The readOnlyHint: true annotation is consistent with a 'Show' operation, and the description adds substantial behavioral context beyond the annotation: per-number plan gating, excluded_tools semantics, the 'mixed' plan case, and why a tool may work on one number but be refused on another. This is exactly the kind of plan-enforcement information an agent needs before calling dependent tools.
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 front-loaded and every major clause carries useful information, but it is a dense, long paragraph with several semicolon-separated qualifications. It remains readable for a complex diagnostic tool, though a little more structure would improve scanability.
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 and read-only annotation, the description supplies the remaining context an agent needs: when to use it, how the account_id scope changes the results, and how to interpret plan-based tool refusals. Nothing essential for correct invocation appears to be 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 description coverage is 100%, so the basic meaning of account_id is already documented. The description still adds real meaning beyond the schema by explaining the different excluded_tools interpretation for one number versus the workspace and the 'mixed' plan result when omitting account_id.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a specific verb and resource: it shows a plan, its limits, and current usage. It also clearly distinguishes the two scopes, one number with account_id versus the whole workspace without it, which lets an agent separate this from sibling listing and messaging 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?
It explicitly says when to call it: to diagnose plan_required errors, understand why wa_send_message may be refused, or check remaining headroom. It also explains the key usage decision, passing account_id for one number and omitting it for every number, so the agent does not have to infer the routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_get_profileGet ProfileARead-onlyInspect
Look up who a phone number is on WhatsApp, from one of your accounts: whether it is registered, its public name, about text, profile picture and — for a business — its categories, contact details and hours. An empty about or picture means the peer has not shared it with this account, not that it has none.
| Name | Required | Description | Default |
|---|---|---|---|
| phone | No | the number to look up, in international form (e.g. +447700900111) | |
| account_id | No | which of your accounts to ask from, from wa_list_accounts; omit it when the workspace has only one account |
Output Schema
| Name | Required | Description |
|---|---|---|
| jid | No | |
| name | No | the best available public name |
| note | No | |
| about | No | the peer's status text, when they let this account see it |
| phone | No | |
| refusal | No | present only when the request was declined |
| business | No | present only for a business account |
| is_business | No | true or false when known; ABSENT means the lookup could not establish it (see note) — absence is not a no |
| name_source | No | business or none — a verified business name is vouched for by WhatsApp; "none" means nothing public is published |
| on_whatsapp | Yes | false means the number is not registered on WhatsApp at all |
| picture_url | No | a WhatsApp-hosted URL that expires; fetch it promptly |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, so the safety profile is covered. The description adds genuinely useful behavioral context beyond that: results are scoped to the querying account, and an empty about/picture reflects non-sharing rather than absence of data — a real interpretation pitfall it preempts. It does not address the idempotentHint=false nuance, which is a small remaining gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the purpose and return fields, followed by the one caveat that actually changes interpretation. No wasted text.
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 structure needn't be explained, and the description covers the account-scoping and partial-data caveats. Adequate for a 2-parameter read tool; only the non-idempotent read behavior is left unexplained.
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%, including the international phone format example and the wa_list_accounts provenance for account_id, so the schema does the heavy lifting. The description reinforces account scoping ('from one of your accounts') but adds no format or default details 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?
States a specific verb and resource ('Look up who a phone number is on WhatsApp') and enumerates exactly what is returned: registration status, public name, about, picture, and for businesses categories/contact/hours. This is clearly a single-peer lookup, distinct from sibling list tools like wa_list_contacts or wa_get_chat.
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 by the phrasing 'from one of your accounts' and the reference to picking an account, but there is no explicit when-to-use vs when-not guidance and no sibling tool is named as an alternative (e.g., wa_get_chat for known contacts).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_get_webhookGet WebhookARead-onlyInspect
Show the currently configured inbound webhook, including whether it is still enabled and why it was disabled if it was. The signing secret is never returned — it is shown only when the webhook is created.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | |
| events | No | |
| enabled | No | |
| configured | Yes | |
| webhook_id | No | |
| disabled_by | No | who paused delivery: owner, system (our delivery worker) or staff (support, and not resumable here) |
| disabled_reason | No | |
| last_delivery_at | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint annotation, the description discloses meaningful behavior: it never returns the signing secret, it reports whether the webhook is enabled, and it provides the reason if disabled. This tells the agent exactly what to expect and what not to expect, which is especially valuable for a read operation.
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 with no waste. The primary function is front-loaded, and the privacy caveat is placed second where it can warn the agent before it relies on getting the secret. 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 zero-parameter read tool with an output schema and readOnlyHint, the description covers the essential behavioral context: what is returned, what is deliberately omitted, and how disabled state is presented. No additional information is needed to invoke or interpret this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the description correctly adds no parameter explanations. With 100% schema coverage and an empty input schema, there is nothing more an agent needs to know about parameters.
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 ('Show') and a clear resource ('currently configured inbound webhook'), then adds distinctive detail: it reports enabled state and disable reason, and explicitly notes the signing secret is excluded. This differentiates it from wa_set_webhook, wa_enable_webhook, and wa_delete_webhook without needing those names.
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 'currently configured' and the read-only framing make it clear this is for inspecting existing webhook state, not creating, enabling, or deleting. The signing-secret caveat also implies that if the agent needs the secret, it must use the creation flow instead. However, it does not explicitly name the alternative tools or state when not to use this one.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_join_groupJoin GroupCInspect
Join a WhatsApp group from one of your accounts using its invite link.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | Yes | the account to join from, as returned by wa_list_accounts | |
| invite_link | Yes | the group invite link (https://chat.whatsapp.com/…) or bare code |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | No | the rows of a list operation |
| status | Yes | ok (the operation succeeded) or refused (see refusal; for wa_update_group, applied lists the changes that took effect before it) |
| applied | No | wa_update_group only: the settings that were changed, in order — on a refusal, the ones that took effect before it |
| refusal | No | present only when status is refused |
| summary | No | a human-readable result |
| group_jid | No | the new group's JID (wa_create_group only) — use it as wa_send_message's 'to' |
| invite_link | No | the group's invite link (wa_create_group or wa_get_group_invite_link) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly=false, idempotent=false, destructive=false, so the safety profile is covered; the description adds only the invite-link mechanism, which is already a parameter. It says nothing about what happens if the account is already a member, if the link is expired, or whether admin approval is required — meaningful gaps for a non-idempotent mutation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single well-formed sentence with the action front-loaded and zero filler. There is little structure to speak of, but nothing is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values need not be explained, and both required params are described in the schema. However, for a non-idempotent write operation with group-membership side effects, the description omits failure and idempotency behavior the agent would need to call it confidently.
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 via wa_list_accounts, invite_link accepting either a full URL or bare code) are fully documented there. The description adds no meaning beyond that, so 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+resource ('Join a WhatsApp group') plus scope ('from one of your accounts') and mechanism ('using its invite link'), which cleanly separates it from wa_create_group and wa_get_group_invite_link. It stops short of naming any sibling explicitly, so it lands at 4 rather than 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?
No guidance on when to use this versus wa_create_group, wa_update_group, or wa_follow_channel, and no exclusions or prerequisites. The agent must infer usage from the verb alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_leave_chatLeave ChatADestructiveInspect
Leave a group or unfollow a channel on one of your accounts, by its JID.
| Name | Required | Description | Default |
|---|---|---|---|
| jid | Yes | the group (…@g.us) or channel (…@newsletter) JID to leave, as returned by wa_list_groups / wa_list_channels | |
| account_id | Yes | the account, as returned by wa_list_accounts |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | No | the rows of a list operation |
| status | Yes | ok (the operation succeeded) or refused (see refusal; for wa_update_group, applied lists the changes that took effect before it) |
| applied | No | wa_update_group only: the settings that were changed, in order — on a refusal, the ones that took effect before it |
| refusal | No | present only when status is refused |
| summary | No | a human-readable result |
| group_jid | No | the new group's JID (wa_create_group only) — use it as wa_send_message's 'to' |
| invite_link | No | the group's invite link (wa_create_group or wa_get_group_invite_link) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already mark the tool as destructive and non-idempotent, but the description reinforces the behavioral implication of the action itself—namely, that it changes the user's membership status in the chat/channel. This adds necessary high-level context without redundancy.
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 definition is extremely concise, communicating the core function of the tool in a single, efficient sentence. It avoids jargon and 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 that the output schema is present and the input parameters are well-defined, the description is complete enough to enable an agent to select and invoke the tool correctly. It clearly defines the target of the action.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Since the schema coverage is 100%, the description provides little additional semantic value beyond repeating the information already supplied in the schema descriptions. It mentions the resource type (group/channel) but adds no unique constraints or format details.
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 precisely identifies the two types of actions: leaving a group or unfollowing a channel, and specifies the required identifier (JID) for both. This distinguishes its function clearly from other potential messaging actions.
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?
While it clearly states *how* the tool operates (by JID), it provides no guidance on when to use this tool versus siblings like `wa_join_group` or `wa_follow_channel`. The usage context is only implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_list_accountsList WhatsApp AccountsARead-onlyInspect
List the WhatsApp accounts available to you. You need it only when no message row gives you the account_id — before a first message to a number you have no messages with, or to see why an account is not working; when replying, reuse the row's account_id. An account is only usable while its state is "connected" (status "live"); otherwise status and what_to_do say why and what to do.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| accounts | Yes | the accounts this API key can use — WhatsApp numbers and Telegram accounts; each says which in backend |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the read-only profile, and the description adds genuine domain semantics: an account is only usable while state is 'connected' (status 'live'), otherwise status and what_to_do explain the failure. That tells the agent how to interpret results and why a listing may look unusable, which is more than the annotations 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?
Three tight sentences, front-loaded with the action, then the decision rule, then the state semantics. Every clause carries information the agent needs; nothing is padded.
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 fields need not be enumerated, yet the description still explains how to read the state/status/what_to_do fields. Combined with the covered safety annotations and parameterless schema, the definition is complete 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?
The tool takes zero parameters, so there is nothing for the description to disambiguate; baseline applies. No misleading parameter hints are introduced.
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 ('List the WhatsApp accounts'), and implicitly distinguishes itself from message-derived data by saying a message row's account_id should normally be reused. It never names an actual sibling tool, so the differentiation is contextual rather than explicit, but an agent can still tell what this returns.
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 triggers (before a first message to a number with no history, or diagnosing an account that is not working) and an explicit when-not-to-use rule (reuse the row's account_id when replying). This is the rare case where both the positive and negative conditions are stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_list_blockedList Blocked ContactsARead-onlyInspect
List every contact one of your accounts has blocked. Each entry carries the contact's number, the name this account's address book has for them — absent for someone not saved on the phone — and the country the number belongs to. WhatsApp does not report when a contact was blocked, so no date is available.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | Yes | the account whose blocklist to read, as returned by wa_list_accounts |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | ok (the operation succeeded) or refused (nothing was done) |
| blocked | No | every contact on the account's blocklist (wa_list_blocked only) |
| contact | No | the contact that was blocked or unblocked (wa_block_contact only) |
| refusal | No | present only when status is refused |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the read-only safety profile, and the description goes further by disclosing data limitations an agent would otherwise probe for: the name field is absent for unsaved numbers, and block timestamps are unavailable because WhatsApp doesn't report them. The one gap is that idempotentHint=false is unexplained for what reads like a stable list operation.
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 short sentences, front-loaded with the action, then the return shape, then the caveat that pre-empts a wrong assumption. 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?
A read-only single-parameter list tool with an output schema and safety annotations needs little more; the description still covers scope, entry contents, and the missing-timestamp caveat. Nothing required to invoke it correctly is absent.
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?
There is a single parameter with 100% schema description coverage, and the schema already explains it is the account whose blocklist is read. The description adds no further parameter semantics, 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 concrete verb and resource — list the contacts a given account has blocked — which cleanly separates it from wa_list_contacts and wa_block_contact without needing the schema opened. The scope qualifier 'one of your accounts' makes the per-account nature explicit.
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 by the 'blocked' qualifier but the description never states when to reach for this instead of wa_list_contacts, nor any prerequisite such as pairing status. The tool-chaining hint ('as returned by wa_list_accounts') lives in the schema, not the description.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_list_callsList Call HistoryARead-onlyInspect
Read call history across your WhatsApp accounts, oldest first. Page with after_cursor: pass back the next_cursor you were given, and keep going until has_more is false to export the whole history. Each call says whether it was answered and how long it lasted. Narrow with since/until (until is exclusive).
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | how many to return, 1-200; defaults to 50 | |
| since | No | only calls at or after this time: RFC3339 with a zone (2026-10-01T09:00:00+03:00) or a date (2026-10-01 = midnight UTC); omit for no lower bound | |
| until | No | only calls BEFORE this time — exclusive, so all of 1 October is since 2026-10-01 until 2026-10-02; same formats as since; omit for no upper bound | |
| account_id | No | limit to one account; omit for every account you have | |
| after_cursor | No | return calls after this cursor; omit to start from the oldest |
Output Schema
| Name | Required | Description |
|---|---|---|
| calls | Yes | calls in order, oldest first |
| refusal | No | present only when the request was declined |
| has_more | Yes | true when the page was full and more may be waiting |
| next_cursor | Yes | pass this as after_cursor next time; page until has_more is false to export everything |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only safety, so the description's value is in disclosing ordering (oldest first), the termination condition for pagination, and that each call reports answered status and duration. It does not state rate limits or what happens if the cursor is stale, but the core loop behavior is well disclosed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four short sentences, scope first, pagination mechanics next, filters last. No filler and no 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 and full parameter descriptions, the description only needs to cover workflow and ordering, which it does. The gap is sibling disambiguation against wa_ai_list_calls, the one thing an agent still has to guess.
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%, so baseline is 3; the description earns extra by explaining the cursor round-trip contract ('pass back the next_cursor you were given') and reiterating that until is exclusive, which is easy to get wrong even when documented in 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?
Opens with a specific verb and resource — 'Read call history across your WhatsApp accounts' — and states the ordering (oldest first). It does not distinguish itself from the sibling wa_ai_list_calls, so an agent cannot tell from the description alone which of the two list-call tools applies.
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 concrete operational guidance: page with after_cursor, feed back next_cursor, continue until has_more is false, and narrow with since/until. It lacks a when-not-to-use or which-alternative clause (notably versus wa_ai_list_calls and wa_load_history).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_list_channelsList ChannelsARead-onlyInspect
List the channels one of your accounts follows, with each channel's JID, name and subscriber count.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | Yes | the account whose channels to list, as returned by wa_list_accounts |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | No | the rows of a list operation |
| status | Yes | ok (the operation succeeded) or refused (see refusal; for wa_update_group, applied lists the changes that took effect before it) |
| applied | No | wa_update_group only: the settings that were changed, in order — on a refusal, the ones that took effect before it |
| refusal | No | present only when status is refused |
| summary | No | a human-readable result |
| group_jid | No | the new group's JID (wa_create_group only) — use it as wa_send_message's 'to' |
| invite_link | No | the group's invite link (wa_create_group or wa_get_group_invite_link) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Read-only behavior is already covered by readOnlyHint=true, and the description adds the returned fields (JID, name, subscriber count). It does not disclose pagination, rate limits, or the meaning of idempotentHint=false, but the output schema reduces the need for return-format details.
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 front-loaded sentence with no wasted words. It states the operation and the useful return fields compactly.
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 one-parameter read tool with an output schema and annotations, the description is nearly complete. It could mention pagination or result limits, but nothing essential for 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 100%, and the single account_id parameter is documented in the schema as coming from wa_list_accounts. The description's phrase 'one of your accounts' reinforces scope but adds no syntax or selection details 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?
States a specific verb and resource: list channels followed by one of the user's accounts, and names the returned fields. This clearly distinguishes it from the sibling write tool wa_follow_channel.
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: use it to list channels followed by a specific account. It does not explicitly state exclusions or alternatives, but the sibling set contains no competing list-channels tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_list_contactsList ContactsARead-onlyInspect
List or search the address book of one of your WhatsApp accounts — the contacts saved on the phone this account is linked to. Pass query to find someone by name or number; matching looks at saved names, the name the contact publishes, business names and the number. Use the returned phone numbers with wa_send_message. Set include_pictures to also get each contact's profile picture URL; that looks the contacts up on WhatsApp, so it returns at most 10 per page and is slower.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | how many to return (default 500, max 2000; max 10 with include_pictures) | |
| query | No | optional: only contacts whose name or number contains this; case-insensitive and ignores punctuation in numbers, so '+44 7700 900111' finds 447700900111. Omit to list everything | |
| account_id | Yes | which of your accounts to read, from wa_list_accounts | |
| after_cursor | No | return contacts after this cursor; omit to start from the beginning | |
| include_pictures | No | also return each contact's profile picture URL. This looks every contact on the page up on WhatsApp, so the page is capped at 10 and can take half a minute; leave it off for a fast listing |
Output Schema
| Name | Required | Description |
|---|---|---|
| note | No | |
| total | Yes | how many contacts matched in total, before the limit was applied |
| refusal | No | present only when the request was declined |
| contacts | Yes | |
| has_more | No | true when more contacts remain after this page |
| truncated | No | true when more contacts exist than were returned |
| next_cursor | No | pass this as after_cursor to continue; page until has_more is false to read the whole address book |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only cover the read-only safety profile, and the description adds genuinely non-obvious behavior: include_pictures triggers live WhatsApp lookups per contact, caps the page at 10, and 'can take half a minute.' That latency/cap tradeoff is exactly the kind of operational trait an agent cannot infer from readOnlyHint.
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 sentences, front-loaded with the core action, then query semantics, then the forward reference, then the costly optional flag. Every sentence carries information, though the include_pictures explanation overlaps heavily with the schema's own description of that parameter.
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 read-only list tool with an output schema, 100% parameter coverage, and 5 params, the description covers purpose, matching semantics, the performance trap, and the downstream use of results. Nothing needed to call it correctly 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 100%, so baseline is 3; the description earns above that by disclosing match fields the schema omits — 'saved names, the name the contact publishes, business names and the number.' It restates include_pictures and cursor behavior already well documented in the schema, so it doesn't reach 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource with scope: 'List or search the address book of one of your WhatsApp accounts — the contacts saved on the phone this account is linked to.' That scoping sentence alone separates it from wa_list_blocked, wa_list_group_members, and wa_get_profile, so an agent can pick the right tool without opening schemas.
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 pass query ('to find someone by name or number; omit to list everything') and when to set include_pictures (only when picture URLs are needed, at a page/latency cost). It also routes forward with wa_send_message. It stops short of naming competing tools (wa_list_blocked, wa_get_chat) or stating when this tool is the wrong choice.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_list_group_membersList Group MembersARead-onlyInspect
List a group's members. Each item is one participant with their JID, phone number (in 'name'), and an 'admin' flag.
| Name | Required | Description | Default |
|---|---|---|---|
| group_jid | Yes | the group (…@g.us) JID, as returned by wa_list_groups | |
| account_id | Yes | the account, as returned by wa_list_accounts |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | No | the rows of a list operation |
| status | Yes | ok (the operation succeeded) or refused (see refusal; for wa_update_group, applied lists the changes that took effect before it) |
| applied | No | wa_update_group only: the settings that were changed, in order — on a refusal, the ones that took effect before it |
| refusal | No | present only when status is refused |
| summary | No | a human-readable result |
| group_jid | No | the new group's JID (wa_create_group only) — use it as wa_send_message's 'to' |
| invite_link | No | the group's invite link (wa_create_group or wa_get_group_invite_link) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and idempotentHint. The description adds value by clarifying the output item shape: each item has a JID, a phone number stored in 'name', and an 'admin' flag. It does not mention pagination or error behavior, but the output schema covers return values.
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 written sentences, front-loaded with the purpose and followed by essential output field semantics. No wasted words.
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?
Complete for a simple list tool: purpose, output fields, and annotations are sufficient. Missing only minor behavioral details like pagination or group-existence preconditions, but the output schema and annotations cover the bulk of what an agent needs.
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 have descriptive text pointing to wa_list_groups and wa_list_accounts. The description adds no parameter meaning beyond the schema, so 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?
States a specific verb and resource: 'List a group's members.' Clearly distinct from wa_list_groups and wa_list_contacts, but doesn't explicitly name those siblings or contrast behavior.
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 by the name and resource, but the description gives no explicit when-to-use, when-not-to-use, or alternative tool (e.g., wa_list_contacts for non-group members).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_list_groupsList GroupsARead-onlyInspect
List the groups one of your accounts has joined, with each group's JID, name and member count.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | Yes | the account whose groups to list, as returned by wa_list_accounts |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | No | the rows of a list operation |
| status | Yes | ok (the operation succeeded) or refused (see refusal; for wa_update_group, applied lists the changes that took effect before it) |
| applied | No | wa_update_group only: the settings that were changed, in order — on a refusal, the ones that took effect before it |
| refusal | No | present only when status is refused |
| summary | No | a human-readable result |
| group_jid | No | the new group's JID (wa_create_group only) — use it as wa_send_message's 'to' |
| invite_link | No | the group's invite link (wa_create_group or wa_get_group_invite_link) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and idempotentHint=false. The description usefully adds that only joined groups are returned (not discoverable/created ones) and what fields come back, but it does not explain why the call is non-idempotent, whether results are ordered, or how they behave for large group lists. With annotations covering the safety profile, this is adequate but thin.
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 well-formed sentence that front-loads the action and scope and closes with the returned fields. No filler, nothing to trim.
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 only be summarized and they are. For a one-parameter read tool with full schema coverage and clear annotations, the description is sufficient, missing only ordering/pagination expectations that could matter for accounts in many groups.
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 the single account_id parameter is already documented in the schema with a cross-reference to wa_list_accounts. The description adds no format or sourcing detail beyond that, so the schema carries the load — 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?
States a specific verb and resource (list groups) with an explicit scope qualifier (groups 'one of your accounts has joined') and previews the returned fields (JID, name, member count). This separates it from wa_create_group and wa_list_group_members, though it never names those siblings directly.
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 'one of your accounts has joined' implies the prerequisite of a paired account and the scope of results, but there is no explicit when-to-use guidance or pointer to the relevant alternative (e.g. wa_list_group_members for participant-level detail, wa_get_chat for a single group).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_list_messagesList MessagesARead-onlyInspect
Read messages across all your accounts — WhatsApp and Telegram — oldest first. Page with after_cursor: pass back the next_cursor you were given to see only what has arrived since. Use this to catch up after being notified of a new message. Narrow with account_id, chat, and since/until (when the message was sent; until is exclusive). Add include_history to also read synced history. When a poll finds nothing new, wait about 30 seconds before the next one: calling again at once returns the same empty page.
| Name | Required | Description | Default |
|---|---|---|---|
| chat | No | only this conversation — a phone number or a group JID, or on a Telegram account the chat's Telegram id (<id>@telegram) | |
| limit | No | how many to return, 1-200; defaults to 50 | |
| since | No | only messages sent at or after this time: RFC3339 with a zone (2026-10-01T09:00:00+03:00) or a date (2026-10-01 = midnight UTC); omit for no lower bound | |
| until | No | only messages sent BEFORE this time — exclusive, so all of 1 October is since 2026-10-01 until 2026-10-02; same formats as since; omit for no upper bound | |
| account_id | No | only this account's messages, from wa_list_accounts; omit for every account | |
| after_cursor | No | return messages after this cursor; omit or 0 to start from the beginning | |
| include_history | No | also return imported history (pairing sync and wa_load_history); off by default. With it on, a page is in storage order rather than time order — sort by at | |
| include_media_urls | No | also return attachment.media_url on each available attachment — a time-limited (1h) signed URL to GET the bytes with plain HTTP instead of a wa_get_media call; off by default |
Output Schema
| Name | Required | Description |
|---|---|---|
| hint | No | present when the read found nothing new: wait before polling again |
| refusal | No | present only when the request was declined; next_cursor is then your after_cursor, unchanged |
| has_more | Yes | true when the page was full and more may be waiting |
| messages | Yes | messages in order, oldest first |
| next_cursor | Yes | pass this as after_cursor next time to get only newer messages |
| account_notices | No | present when a number this read covers is not working: new messages are not arriving on it; says why and what to do |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond readOnlyHint/idempotentHint=false: it discloses result ordering, how to page with next_cursor, that calling twice yields the same empty page (explaining the non-idempotent hint), and that include_history switches the page to storage order rather than time order. That last point is a subtle behavioral trap an agent would otherwise miss.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with scope and ordering, then paging, then use case, then filters, then the polling caveat. No filler; each sentence carries a distinct operational fact.
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-field documentation is unnecessary, and the description still names next_cursor because it is needed to drive paging. For an 8-parameter, zero-required list tool this covers everything an agent needs to call it and poll correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description still adds meaning: since/until are keyed to when the message was SENT and until is exclusive, and include_history changes the sort order so results must be re-sorted by 'at'. Useful clarification over identical schema text.
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 plus the scope that matters most: 'Read messages across all your accounts — WhatsApp and Telegram — oldest first.' The oldest-first ordering and multi-account default immediately separate it from single-message siblings like wa_get_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?
Gives a concrete use case ('catch up after being notified of a new message'), the polling cadence ('wait about 30 seconds'), and narrowing options. It stops short of naming when NOT to use it — e.g. wa_get_message or wa_list_channels — so the exclusion half of the guidance 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.
wa_list_templatesList WhatsApp Business TemplatesARead-onlyInspect
List the WhatsApp Business message templates of one of your Business (Cloud API) numbers, with each one's review status (APPROVED, PENDING, REJECTED — a rejected one carries Meta's rejected_reason). Use an APPROVED template's name and language with wa_send_message's template/template_language to start a conversation or message outside the 24-hour window, and supply its 'variables' count as template_variables, in order. Templates apply only to Business numbers, not personal linked-device numbers.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | Yes | the Business (Cloud API) account whose templates to list, as returned by wa_list_accounts |
Output Schema
| Name | Required | Description |
|---|---|---|
| refusal | No | present only when the call was declined |
| templates | No | every message template with its review status; only APPROVED ones can be sent, with the name/language/variables to pass to wa_send_message |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare readOnlyHint=true and idempotentHint=false. The description adds useful behavioral context beyond annotations: it explains returned review statuses, rejected_reason on rejected templates, and that templates only apply to Business numbers, not personal linked-device numbers.
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 purpose and status detail are front-loaded, and the later sentences carry useful downstream usage and scope-exclusion information. The second sentence is dense and could be split for readability, but no sentence is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With a fully documented single parameter, read-only annotations, and an output schema, the description gives everything else an agent needs: what is listed, status meanings, downstream usage with wa_send_message, and the Business-number-only scope. Return-value details can safely live in the output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There is one parameter and schema description coverage is 100%; the schema already documents account_id as the Business account returned by wa_list_accounts. The description adds that the account must be a Business (Cloud API) number rather than a personal linked-device number, but this is not parameter-specific meaning beyond the schema baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: list WhatsApp Business message templates for a Business (Cloud API) number, including review status. It also distinguishes the resource from personal linked-device numbers, so an agent can tell what this tool is for.
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 usage context: use an APPROVED template's name and language with wa_send_message to message outside the 24-hour window, and pass the variables count as template_variables in order. It also excludes personal linked-device numbers, but it does not explicitly contrast this listing tool with siblings like wa_create_template or wa_delete_template.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_load_historyLoad Older MessagesAInspect
Ask the account's phone for older messages in one conversation, before the oldest one stored here, and store them. The phone must be online; it usually answers within seconds. Read the result with wa_get_chat and the same chat. Loaded messages are history: they never trigger webhooks and appear in wa_list_messages only with include_history=true. They are kept for your plan's history window like any other message. A conversation needs at least one stored message to page back from.
| Name | Required | Description | Default |
|---|---|---|---|
| chat | Yes | the conversation to page back: a phone number for a direct chat, or a group JID (…@g.us) | |
| count | No | how many older messages to ask the phone for, 1-500; defaults to 50 | |
| account_id | No | the account, as returned by wa_list_accounts; omit it when the workspace has only one account |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | ok (the request reached the phone) or refused (nothing was asked) |
| refusal | No | present only when status is refused |
| answered | Yes | the phone answered in time; false means it may still answer later (it must be online) — read the chat again in a minute |
| imported | Yes | of those, how many were new here; 0 with answered=true usually means you reached the start of what the phone holds |
| received | Yes | messages the phone sent back |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only say it writes, is non-idempotent and non-destructive; the description adds the real behavioral facts: the phone must be online, it usually answers within seconds, loaded messages never trigger webhooks, and they fall inside the plan's history window. That is exactly the context an agent needs before invoking.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four short sentences, front-loaded with the action and the online requirement, followed by how to read the result and the retention semantics. No 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?
Covers the offline/latency caveat, the webhook-invisibility caveat, the visibility flag needed elsewhere, retention, and the prerequisite. With an output schema and annotations present, nothing an agent needs 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 100% – chat format, count range/default and account_id fallback are all documented in the schema. The description adds only lightweight framing ('one conversation', 'before the oldest one stored'), so 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: fetch older messages for one conversation from the account's phone and store them. The phrase 'before the oldest one stored here' precisely distinguishes it from wa_list_messages and wa_get_chat, which only read what is already stored.
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 concrete routing: read the result with wa_get_chat using the same chat, and load with include_history=true to see it in wa_list_messages. It also names the prerequisite (at least one stored message to page back from). It does not explicitly say when not to call it (e.g. when the phone is likely offline), but the context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_pair_accountPair AccountAInspect
Begin linking a new WhatsApp account — or a Telegram account, with network set to telegram. For WhatsApp there are two ways to link and the right one depends on the user's devices, so ASK FIRST: if they can scan a QR code from another screen (a second phone, or this computer's screen) using the WhatsApp app on their phone, call this with no phone and show the returned QR PNG; if they only have the one phone that runs WhatsApp — it cannot scan its own screen — pass phone in international format to get an 8-character code they type on that phone instead. A Telegram account links by QR only, scanned from Telegram → Settings → Devices → Link Desktop Device; if it has two-step verification the state becomes password_needed and the user enters their cloud password on the console's pairing page (never through a tool). Then poll wa_pair_status with the returned pair_id: a QR re-arms about every 20 seconds (show the newest each time), a phone code lasts a few minutes, and either way the state turns "paired" once it is linked. Pass import_history to choose whether a WhatsApp pairing loads the phone's recent messages as history.
| Name | Required | Description | Default |
|---|---|---|---|
| phone | No | link by phone-number code instead of a QR: the number to link, in international format with its country code (for example +52 998 123 4567). WhatsApp on that phone is asked to accept an 8-character code, returned as pair_code. Use it when the user has only the one phone that runs WhatsApp and cannot scan a QR from another screen (WhatsApp only) | |
| network | No | the messaging network of the account to link: whatsapp (the default) or telegram. A Telegram account links by QR only: the user scans it from Telegram → Settings → Devices → Link Desktop Device. Telegram accounts must be enabled for the workspace, or the call is refused | |
| import_history | No | import the phone's recent message history (about two months) as read-only history for this pairing; omit to use the workspace default (WhatsApp only) |
Output Schema
| Name | Required | Description |
|---|---|---|
| state | Yes | starting, qr, code, password_needed (a Telegram account with two-step verification: the user must enter their cloud password on the console's pairing page — never ask for it here), paired or failed |
| network | No | the messaging network the pairing links on: whatsapp or telegram |
| pair_id | No | pass this to wa_pair_status to follow the pairing |
| refusal | No | present only when pairing could not be started |
| pair_code | No | the 8-character code the user types on their phone (phone-number pairing only) |
| expires_at | No | when pair_code stops working, RFC 3339 (phone-number pairing only) |
| needs_plan | No | true when the linked number has no plan yet and will not run until the user buys one in the console |
| instructions | No | what to tell the user to do |
| qr_png_base64 | No | a PNG image of the QR code, base64 encoded — display this to the user |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare the non-read-only, non-idempotent, non-destructive profile; the description adds substantial context beyond that: QR re-arms roughly every 20 seconds and the newest must be shown, phone codes last a few minutes, Telegram two-step verification flips state to password_needed with the password entered on the console pairing page and never through a tool, and Telegram accounts must be enabled for the workspace or the call is refused. These are operational traits an agent cannot infer from the 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 core instruction ('ASK FIRST' plus the two-linking-methods branch) is front-loaded, and the sentence about polling and state transitions comes after. It is dense and long, but nearly every clause carries a rule the agent must apply; a small amount of the QR/phone description could be trimmed given the schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers everything needed for a pairing tool: which inputs to pass in which situation, the Telegram constraints, the follow-up polling behavior, timing windows, and the terminal 'paired' state. Return values are partly described (QR PNG, pair_code, pair_id) and an output schema exists, so nothing essential 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 100%, so the baseline is 3 and the schema already carries format details. The description still adds decision-level meaning by tying phone to the single-device case and import_history to choosing whether WhatsApp history loads, though it largely restates what the schema fields say rather than extending them.
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+resource ('Begin linking a new WhatsApp account') and immediately qualifies the scope with the Telegram variant ('or a Telegram account, with network set to telegram'). This clearly separates it from wa_pair_status (polling) and wa_unpair_account (teardown) without the agent needing to open sibling schemas.
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 decision procedure: 'ASK FIRST', then branch on whether the user can scan a QR from another screen versus having only one phone. It names the alternative call path (pass phone for a code), the Telegram-only path, and the required follow-up ('Then poll wa_pair_status with the returned pair_id'), so both when-to-use and what-comes-next are spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_pair_statusCheck Pairing StatusARead-onlyInspect
Check a pairing started with wa_pair_account. While state is "qr" a new image is returned each time — show the latest to the user. While state is "code", show pair_code. A Telegram pairing may report "password_needed": the user enters their cloud password on the console's pairing page, never here. When state becomes "paired" the account is ready and appears in wa_list_accounts.
| Name | Required | Description | Default |
|---|---|---|---|
| pair_id | Yes | the pair_id returned by wa_pair_account |
Output Schema
| Name | Required | Description |
|---|---|---|
| state | Yes | starting, qr, code, password_needed (a Telegram account with two-step verification: the user must enter their cloud password on the console's pairing page — never ask for it here), paired or failed |
| network | No | the messaging network the pairing links on: whatsapp or telegram |
| pair_id | No | pass this to wa_pair_status to follow the pairing |
| refusal | No | present only when pairing could not be started |
| pair_code | No | the 8-character code the user types on their phone (phone-number pairing only) |
| expires_at | No | when pair_code stops working, RFC 3339 (phone-number pairing only) |
| needs_plan | No | true when the linked number has no plan yet and will not run until the user buys one in the console |
| instructions | No | what to tell the user to do |
| qr_png_base64 | No | a PNG image of the QR code, base64 encoded — display this to the user |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds context the annotations can't carry: the non-idempotent character (new image returned on each call, so show the latest) and the security-relevant 'password_needed' path where the user must enter their cloud password on the console page, never in this tool. It does not mention whether pair_id expires or how long pairing sessions live, which is the main remaining behavioral unknown.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four short, front-loaded sentences that map cleanly onto state branches; no filler. Slightly dense, but each sentence carries actionable information and the ordering follows the agent's decision flow.
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 needn't be enumerated, yet the description still explains the meaningful state values and how to act on each. Combined with the password-handling caveat, an agent has enough to call and interpret this correctly; only session lifetime/polling cadence 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 description coverage is 100% and the single parameter's schema text ('the pair_id returned by wa_pair_account') already carries the full meaning. The description only repeats the provenance of pair_id, adding no format or constraint detail 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?
Opens with a specific verb and resource ('Check a pairing started with wa_pair_account'), and immediately ties itself to the sibling that starts the flow, so an agent can distinguish the initiate step from the poll step 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?
States the precondition (a pairing started with wa_pair_account) and gives per-state instructions: show the latest image while 'qr', show pair_code while 'code', and treat 'paired' as readiness signalled by wa_list_accounts. It stops short of telling the agent how often to poll or when to give up, which is a real gap for a polling tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_reactReact to MessageAInspect
React to a WhatsApp message with an emoji. Pass an empty reaction to remove a reaction you previously sent.
| Name | Required | Description | Default |
|---|---|---|---|
| chat | Yes | the chat the message is in — a phone number or a group JID; reacting to a channel (@newsletter) message is not supported | |
| sender | No | group chats only: the phone number or JID of whoever sent the original message; omit in a DM or for your own message | |
| reaction | Yes | the emoji to react with; an empty string removes a reaction you previously sent | |
| account_id | No | the account, as returned by wa_list_accounts; omit it when the workspace has only one account | |
| message_id | Yes | WhatsApp's id for the message, as returned by wa_send_message or seen in wa_list_messages |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | ok (the operation succeeded) or refused (nothing was done) |
| refusal | No | present only when status is refused |
| new_message_id | No | WhatsApp's id for the react/edit/revoke protocol message itself |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, destructiveHint=false and idempotentHint=false, so safety is partly covered. The removal-by-empty-string behavior is genuinely useful context, but it is duplicated verbatim in the reaction parameter's schema text, and nothing is said about visibility to other participants or the channel limitation documented only in 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?
Two short sentences, front-loaded with the core action and followed by the one non-obvious modifier. No 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?
With a complete input schema, an output schema and annotations present, the description only needs to nail purpose and the removal semantics, which it does. Minor gaps (channel-message restriction, group `sender` requirement) are covered by the schema rather than the description.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all five parameters (including the tricky group-only `sender` and the `account_id` fallback) are already fully documented in the schema. The description adds no parameter-level meaning beyond that, which is the expected baseline.
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 (react) and resource (a WhatsApp message) plus the emoji detail, which cleanly separates it from message-sending siblings like wa_send_message. It never names a sibling for comparison, so it stops short of full differentiation.
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 second sentence usefully explains how to undo a reaction (empty string), which is a real usage cue. But there is no explicit when-to-use/when-not guidance, no mention of prerequisites (e.g. channel messages unsupported) and no pointer to alternatives such as wa_send_message or wa_delete_message.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_remove_participantsRemove ParticipantsADestructiveInspect
Remove members from a WhatsApp group by phone number or JID. The account must be a group admin.
| Name | Required | Description | Default |
|---|---|---|---|
| members | Yes | members — phone numbers (E.164) or JIDs, comma- or space-separated | |
| group_jid | Yes | the group (…@g.us) JID, as returned by wa_list_groups | |
| account_id | Yes | the account, as returned by wa_list_accounts |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | No | the rows of a list operation |
| status | Yes | ok (the operation succeeded) or refused (see refusal; for wa_update_group, applied lists the changes that took effect before it) |
| applied | No | wa_update_group only: the settings that were changed, in order — on a refusal, the ones that took effect before it |
| refusal | No | present only when status is refused |
| summary | No | a human-readable result |
| group_jid | No | the new group's JID (wa_create_group only) — use it as wa_send_message's 'to' |
| invite_link | No | the group's invite link (wa_create_group or wa_get_group_invite_link) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare this as destructive and non-idempotent. The description adds useful behavioral context by stating the admin permission requirement, which is not captured in the annotations. It stops short of explaining failure behavior or edge cases, so it is strong but not exhaustive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two short sentences with the action and prerequisite front-loaded. There is no wasted text.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive group-membership mutation, the description covers the core action and the required admin privilege, while annotations cover the safety profile and the output schema covers return values. It is largely complete, though it could mention edge-case behavior for removal failures.
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 parameters are already well documented. The description mentions phone number or JID for members, but it largely repeats what the schema provides and adds little beyond it.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: remove members from a WhatsApp group. It is clear what the tool does, but it does not explicitly distinguish itself from sibling tools such as wa_update_participants or wa_leave_chat.
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 includes an important prerequisite that the account must be a group admin, which helps usage. However, it does not state when to use this tool instead of alternatives or describe exclusions, so the guidance is only implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_reportReport to WhatsMCPAInspect
Send a bug report, feature request or feedback about WhatsMCP to the WhatsMCP team. Use it when the person asks to report a problem, suggest a feature or leave feedback — not to contact a WhatsApp user (that is wa_send_message). The report is emailed to the team with the workspace and the sender's address, so a reply reaches the person by email. Write it in the person's words; for a bug include what was done, what happened, what was expected and any error text. Never include passwords, API keys or message contents the person did not ask to share.
| Name | Required | Description | Default |
|---|---|---|---|
| type | Yes | what kind of report this is,enum=bug,enum=feature_request,enum=feedback | |
| title | Yes | a one-line summary, at most 120 characters | |
| message | Yes | the report itself, at most 5000 characters: for a bug, what was done, what happened and what was expected, and which number it was on |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | ok when the report was accepted for delivery, refused when it was not |
| message | No | what happens next, for the person |
| refusal | No | present only when the report was not sent |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare a non-read-only, open-world, non-idempotent, non-destructive call, but not what happens to the payload. The description adds that the report is emailed to the team along with the workspace and the sender's address, so a reply reaches the person by email, and it sets a privacy boundary (no passwords, keys, unshared message contents). It doesn't mention rate limits or duplicate-submission behavior, so not 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 sentences, front-loaded with purpose then usage then content then safety; each sentence does work. The privacy sentence is slightly tacked-on but is genuinely necessary for a tool that forwards user text externally.
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, full parameter documentation and annotations present, the description only needed to add routing, behavioral destination and content expectations — and it does all three. Nothing an agent needs to call this correctly 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 100%, so baseline is 3, but the description adds semantic content beyond the field docs: it prescribes writing in the person's words and enumerates the structure a bug report should contain (what was done, what happened, what was expected, error text), which goes past the schema's shorter phrasing.
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 bug report, feature request or feedback about WhatsMCP to the WhatsMCP team') and explicitly contrasts with the nearest sibling, wa_send_message. An agent can route between the two 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 both the trigger ('when the person asks to report a problem, suggest a feature or leave feedback') and the exclusion ('not to contact a WhatsApp user (that is wa_send_message)'). Coverage guidance ('write it in the person's words') further shapes correct use.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_send_messageSend WhatsApp MessageAInspect
Send a message from one of your accounts (WhatsApp, or Telegram for an account whose backend is telegram) — text, or an attachment: an image via image_base64 (JPEG/PNG, at most 5 MiB; text becomes the caption), a document via document_base64 (any file, at most 20 MiB; text becomes the caption), or audio via audio_base64 (at most 16 MiB; no caption). For a Business (WhatsApp Cloud API) number, set 'template' to send a pre-approved message template (e.g. hello_world) — the only way to start a conversation or to message that number outside the 24-hour window. Check the returned status: "sent" means delivered; "queued" means the message was accepted but not yet confirmed and may still arrive, so do NOT send it again; "refused" means nothing was sent and the reason explains whether retrying will help.
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | the recipient. WhatsApp: a phone number in international form (digits only, e.g. 447700900123) for a 1:1 chat, or a full group/channel JID (…@g.us for a group, …@newsletter for a channel). Telegram (an account whose backend is telegram): the chat id exactly as wa_list_messages reports it (<id>@telegram; a group is -<id>@telegram, a channel or supergroup -100<id>@telegram) to reply, or to start a conversation an @username, a t.me/<name> link or a phone in +E.164 form — never a bare number, which could be a phone or a user id | |
| text | No | the message body; when an image is attached this is its caption and may be empty. Either text or image_base64 is required | |
| template | No | optional: the name of a pre-approved message template to send (Business/WABA numbers only), e.g. hello_world. Use this to start a conversation or to message outside the 24-hour window; text and attachments are ignored when set | |
| audio_ptt | No | optional: true to send as a voice note (push-to-talk) rather than a regular audio attachment | |
| account_id | No | the account to send from — the account_id on the message row you are replying to, or from wa_list_accounts; omit it when the workspace has only one account | |
| audio_mime | No | optional: the audio's mime type, e.g. audio/ogg; codecs=opus | |
| image_mime | No | optional: the image's mime type, image/jpeg or image/png | |
| audio_base64 | No | optional: base64-encoded audio to attach, at most 16 MiB decoded; audio has no caption | |
| image_base64 | No | optional: base64-encoded JPEG or PNG to attach, at most 5 MiB decoded; when set, text becomes the caption | |
| audio_seconds | No | optional: the audio's duration in seconds | |
| document_mime | No | optional: the document's mime type, e.g. application/pdf | |
| document_base64 | No | optional: base64-encoded document/file to attach, at most 20 MiB decoded; when set, text is the caption | |
| document_filename | No | optional: the filename shown to the recipient, e.g. report.pdf | |
| template_language | No | optional: the template's language/locale code, e.g. en_US; defaults to en_US | |
| template_variables | No | optional: values that fill the template body's positional {{1}}, {{2}}, … placeholders, in order |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | sent (delivered), queued (accepted but unconfirmed - do NOT re-send), or refused (not attempted) |
| refusal | No | present only when status is refused |
| message_id | No | WhatsApp's id for the message, present only when status is sent |
| request_id | No | correlation id; a queued message appears in wa_list_messages under this id once it settles |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With only readOnly/idempotent/destructive hints from annotations, the description adds critical behavioral context the annotations cannot convey: the meaning of 'sent', 'queued' (accepted but not confirmed — do NOT resend), and 'refused' (nothing sent, reason indicates retry viability). It also discloses per-attachment size limits and caption behavior, which directly affect how the agent should call it.
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 front-loaded with the core action and modes, then details, then status semantics. It is dense but earns most of its length given 15 parameters and multi-backend behavior; a few phrases overlap with the schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex, high-parameter-count mutation tool, the description covers the essential modes, restrictions (template windows, size limits), and the crucial return-status handling. An output schema exists, so the extra status explanation is bonus rather than a gap-filler.
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 every parameter in detail, setting the baseline at 3. The description reinforces the attachment parameters (sizes, caption semantics) but adds little beyond what the schema already states.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('Send a message from one of your accounts'), enumerates the supported message modes (text, image, document, audio, template), and covers both WhatsApp and Telegram backends. It is clearly distinguishable from siblings like wa_edit_message, wa_list_messages, and wa_create_template.
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 strong usage context: template for Business numbers is 'the only way to start a conversation or to message that number outside the 24-hour window', and status handling tells the agent not to resend on 'queued'. However, it doesn't explicitly compare against alternatives such as wa_edit_message for corrections or wa_react for reactions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_set_presenceSet PresenceAInspect
Announce a typing state ("composing"/"paused") to a chat, or set one of your accounts online/offline ("available"/"unavailable"). Fire-and-forget: there is no delivery confirmation.
| Name | Required | Description | Default |
|---|---|---|---|
| chat | No | the chat (a phone number or a group/channel JID) to announce a typing state to; required for composing/paused, ignored for available/unavailable | |
| state | Yes | composing (show "typing…"), paused (stop), available, or unavailable | |
| account_id | No | the account, as returned by wa_list_accounts; omit it when the workspace has only one account |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | ok (queued to the bridge) or refused (nothing was sent) |
| refusal | No | present only when status is refused |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=false, idempotentHint=false, destructiveHint=false; the description adds real value beyond them by disclosing 'fire-and-forget: there is no delivery confirmation.' It does not mention presence expiry or rate limits, which are the remaining behavioral unknowns for a presence tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences: the capability/state vocabulary comes first, then the fire-and-forget caveat. No filler and nothing to trim.
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, a complete input schema, and an output schema present, the description covers what an agent needs to call it correctly. Minor gaps (account defaulting behavior, how long a presence state persists) are not blocking given the structured fields.
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 'state' values and the conditional role of 'chat' are already documented in the schema; the description largely restates the enum vocabulary. Baseline 3 applies since the schema carries the parameter semantics.
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 (announce/set) with the two distinct resources it acts on: a chat's typing state and the account's online presence, enumerated with concrete values. An agent can immediately tell this is not a messaging tool like wa_send_message, though no sibling is named explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives a clear usage rule: 'chat' is required for composing/paused and ignored for available/unavailable, which tells the agent which mode to pick. It lacks explicit exclusions or a pointer to alternatives (e.g. use wa_send_message to actually deliver a message), keeping it below a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_set_profile_photoSet Profile PhotoADestructiveIdempotentInspect
Change the profile photo of one of your own WhatsApp accounts — the picture every contact sees. Pass image_base64 (JPEG, PNG or GIF, at most 5 MiB) to replace it: the image is center-cropped to a square and scaled to at most 640x640, as WhatsApp stores it. Or pass remove=true to delete the current photo. The previous photo cannot be restored afterwards. Contacts may keep seeing the old photo for a while until their app refreshes it.
| Name | Required | Description | Default |
|---|---|---|---|
| remove | No | true removes the account's current profile photo instead of replacing it; image_base64 must then be omitted | |
| account_id | Yes | the account whose own profile photo to change, as returned by wa_list_accounts | |
| image_base64 | No | the new photo: base64-encoded JPEG, PNG or GIF, at most 5 MiB decoded. It is center-cropped to a square and scaled to at most 640x640. Omit it when remove is true |
Output Schema
| Name | Required | Description |
|---|---|---|
| bytes | No | the size of the JPEG that was uploaded; absent on a removal |
| width | No | the stored photo's side in pixels (it is always square); absent on a removal |
| status | Yes | ok (WhatsApp accepted the change) or refused (nothing was done) |
| refusal | No | present only when status is refused |
| summary | No | a human-readable result |
| picture_id | No | the id WhatsApp assigned the new photo; absent on a removal |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag destructiveHint=true and idempotentHint=true, yet the description still adds real context: irreversible deletion ('previous photo cannot be restored'), server-side transformations (center-cropped to square, max 640x640), and propagation delay for contacts. This is behavior an agent would otherwise have to guess.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the effect and target, then the two modes, then the consequences. Slightly redundant with the schema on image format and cropping, but every sentence carries operational meaning and there is no 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?
An output schema exists, so return values need no explanation; the description covers what is left: ownership constraint, both invocation modes, irreversibility, and the caching behavior after success. Nothing an agent needs to avoid a wrong call 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 100%, so format, size and mutual-exclusion rules are already documented in the parameter descriptions; the description largely restates them. It adds only mildly, by framing the two modes as alternatives in prose. 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 ('Change the profile photo') and scopes it to the caller's own account with 'the picture every contact sees'. That distinguishes it cleanly from the read-only sibling wa_get_profile without needing to name it.
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 branch conditions: pass image_base64 to replace, or remove=true to delete, which is a clear either/or usage rule. It does not name the read-side sibling (wa_get_profile) or state exclusions at the account level, so it stops just 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.
wa_set_webhookSet WebhookAInspect
Register an HTTPS endpoint to receive WhatsApp events as they happen, so you do not have to poll wa_list_messages. By default it delivers inbound messages; pass events to also receive outbound messages (sent from your number), message delivery status (delivered/read/failed), account lifecycle events (connected, disconnected, unlinked, blocked), and call events (completed, missed). Returns a signing secret that is shown ONCE — store it immediately. Calling this again replaces the endpoint and issues a NEW secret.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | an https:// URL that will receive POSTed events; must be publicly reachable | |
| events | No | which events to receive — any of message.inbound, message.outbound, message.status, account.connected, account.disconnected, account.unlinked, account.blocked, call.completed, call.missed; defaults to message.inbound |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | |
| events | No | |
| secret | No | the signing secret — shown ONCE; store it now, it cannot be retrieved later |
| refusal | No | present only when the request was declined |
| webhook_id | No | |
| verification | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: it discloses that the call is non-idempotent in a consequential way ("Calling this again replaces the endpoint and issues a NEW secret") and that the returned signing secret is shown only once and must be stored immediately. That is exactly the operational context an agent needs before invoking a mutation, and it does not conflict with readOnlyHint=false or idempotentHint=false.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with the core action, then defaults, then the destructive replacement warning. Every sentence carries distinct information with no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter mutation with full schema coverage and an output schema, this covers everything material: what it does, the default event scope, the security-sensitive return value, and the overwrite behavior. Nothing an agent needs to call it safely 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 100%, so the baseline is 3, but the description adds real meaning: it states the default event behavior (inbound messages only) and groups the optional events into outbound, delivery status, lifecycle, and call categories. It doesn't restate the events array enum values, but the schema already enumerates them fully.
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?
Starts with a specific verb+resource ("Register an HTTPS endpoint to receive WhatsApp events") and immediately scopes the effect (events arrive as they happen rather than by polling). It is trivially distinguishable from wa_get_webhook, wa_delete_webhook, and wa_enable_webhook, which share the resource but not the action.
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 a clear motivating context ("so you do not have to poll wa_list_messages") and warns about the replacement semantics of a repeat call. It stops short of naming the sibling tools for inspecting or removing an existing webhook, so the agent must infer that wa_get_webhook/wa_delete_webhook are the alternatives for those needs.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_unpair_accountUnpair AccountADestructiveInspect
Disconnect a WhatsApp or Telegram account from this service. The account stops sending and receiving immediately. Message history is kept. Re-connecting requires pairing again (scanning a new code), so ask the user before calling this.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | Yes | the account to disconnect, from wa_list_accounts |
Output Schema
| Name | Required | Description |
|---|---|---|
| note | Yes | what happened, and what was kept |
| state | Yes | logged_out once the account has been disconnected |
| refusal | No | present only when the request was declined |
| account_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and non-idempotent, and the description adds real context beyond that: sending and receiving stop immediately, message history survives, and recovery requires re-pairing via a new code scan. It does not address what happens on a repeated call or whether unpairing an already-unpaired account errors, leaving the idempotency caveat only implied 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 short sentences, each carrying distinct information: what happens, what is preserved, what recovery costs. The caution comes last as a natural call to action, with no 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?
An output schema exists, so return values need no explanation. For a one-parameter destructive operation the description covers consequences, data retention, reversibility, and the confirmation requirement — everything an agent needs to decide and act.
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?
There is a single required parameter with 100% schema coverage, and the schema already tells the agent the account_id comes from wa_list_accounts. The description adds nothing further about the parameter, so 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 (disconnect) and resource (a WhatsApp or Telegram account from this service), and implicitly separates itself from wa_pair_account by noting that re-connecting requires pairing again. An agent can identify the operation and its scope 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 an explicit precondition for use – confirm with the user before calling, because the action is not trivially reversible. It does not name the sibling wa_pair_account as the counterpart operation directly, and gives no when-not guidance, so it falls just short of a full 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_update_groupUpdate GroupAInspect
Change a WhatsApp group's settings: its name, its description, whether only admins may change settings (locked), and whether only admins may post (announce). Pass only the fields to change; several can change in one call. If the group restricts settings to admins, the account must be one. WhatsApp applies each change separately, so on a refusal 'applied' lists the changes that took effect before it.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | a new group name (max 25 characters) | |
| locked | No | true lets only admins change the name, description and photo; false lets every member | |
| announce | No | true lets only admins post (an announcement group); false lets every member post | |
| group_jid | Yes | the group (…@g.us) JID, as returned by wa_list_groups | |
| account_id | Yes | the account, as returned by wa_list_accounts | |
| description | No | a new description; an empty string clears it |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | No | the rows of a list operation |
| status | Yes | ok (the operation succeeded) or refused (see refusal; for wa_update_group, applied lists the changes that took effect before it) |
| applied | No | wa_update_group only: the settings that were changed, in order — on a refusal, the ones that took effect before it |
| refusal | No | present only when status is refused |
| summary | No | a human-readable result |
| group_jid | No | the new group's JID (wa_create_group only) — use it as wa_send_message's 'to' |
| invite_link | No | the group's invite link (wa_create_group or wa_get_group_invite_link) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations by disclosing that changes are applied individually and that a refusal returns an 'applied' list of the changes that took effect before it — a failure-mode detail an agent cannot infer from readOnlyHint/idempotentHint/destructiveHint. It also states the admin-permission prerequisite, which no annotation conveys.
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 tight sentences: what it changes, how to call it, and what happens on refusal. The failure-mode caveat is placed last where it belongs, and nothing is repeated from the schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return shape needs no explanation, yet the description still explains the one return field that matters operationally ('applied'). Combined with the permission prerequisite and partial-apply semantics, an agent has everything needed to call this correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds real semantics the per-field schemas don't state: that omitted fields are left untouched and multiple fields can be changed atomically-ish in one call. It also implicitly clarifies that the nullable boolean fields should be omitted, not nulled, when unchanged.
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 ('Change a WhatsApp group's settings') and enumerates the exact fields it touches: name, description, locked, announce. This clearly separates it from wa_create_group, wa_delete_group, and wa_update_participants, which handle lifecycle or membership rather than group settings.
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 concrete operational guidance: 'Pass only the fields to change; several can change in one call,' plus the prerequisite that the account must be an admin if the group restricts settings. It doesn't explicitly name alternatives (e.g. wa_update_participants for membership), but the scope boundary is clear enough to choose correctly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wa_update_participantsUpdate ParticipantsAInspect
Add members to a WhatsApp group (action=add), make members admins (action=promote), or make admins ordinary members again (action=demote), by phone number or JID. Adding needs the account to be a member (and, for private groups, an admin); promote and demote need an admin. To remove members, use wa_remove_participants.
| Name | Required | Description | Default |
|---|---|---|---|
| action | Yes | add (new members), promote (members to admin) or demote (admins to members); to remove members use wa_remove_participants | |
| members | Yes | members — phone numbers (E.164) or JIDs, comma- or space-separated | |
| group_jid | Yes | the group (…@g.us) JID, as returned by wa_list_groups | |
| account_id | Yes | the account, as returned by wa_list_accounts |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | No | the rows of a list operation |
| status | Yes | ok (the operation succeeded) or refused (see refusal; for wa_update_group, applied lists the changes that took effect before it) |
| applied | No | wa_update_group only: the settings that were changed, in order — on a refusal, the ones that took effect before it |
| refusal | No | present only when status is refused |
| summary | No | a human-readable result |
| group_jid | No | the new group's JID (wa_create_group only) — use it as wa_send_message's 'to' |
| invite_link | No | the group's invite link (wa_create_group or wa_get_group_invite_link) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare non-read-only, non-idempotent, non-destructive; the description adds genuinely useful behavioral context on authorization requirements per action and per group type. It does not disclose what happens on duplicate adds or re-promoting an existing admin (relevant since idempotentHint=false), leaving one behavioral gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single dense sentence enumerating actions followed by permission rules and one routing sentence; every clause earns its place and the primary capability 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?
With an output schema present, return values need not be explained, and the description covers the operation set, permissions, and the removal alternative. The only omission is edge-case behavior for duplicate or no-op operations, which is minor given the annotation and schema richness.
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%, so all four parameters are already documented. The description restates the action values and member identifier formats (phone/JID) but adds little syntax or constraint detail beyond the schema, 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?
Names the specific resource (WhatsApp group members) and enumerates the three concrete operations (add, promote, demote) keyed to the action parameter. It explicitly distinguishes itself from wa_remove_participants, so an agent can select it without inspecting 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?
States when each action applies and names the sibling to use for member removal, with no ambiguity. It also gives the precondition context (account must be a member, admin for private groups; promote/demote require admin), which tells the agent when the call will succeed versus fail.
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.
44 tool updates
- Changed
wa_ai_call_get1 field changed- added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_ai_call_hangup1 field changed- added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_ai_call_start1 field changed- added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_ai_list_calls1 field changed- added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_ai_list_presets1 field changed- added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_block_contact1 field changed- added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_create_group1 field changed- added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_create_template1 field changed- added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_delete_group1 field changed- added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_delete_message3 fields changed- changed
Input schema / properties / account_id / descriptionPrevious value: -"the account, as returned by wa_list_accounts"New value: +"the account, as returned by wa_list_accounts; omit it when the workspace has only one account" - changed
Input schema / requiredPrevious value: -[ - "account_id", - "chat", - "message_id" -]New value: +[ + "chat", + "message_id" +] - added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_delete_template1 field changed- added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_delete_webhook1 field changed- added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_edit_message3 fields changed- changed
Input schema / properties / account_id / descriptionPrevious value: -"the account, as returned by wa_list_accounts"New value: +"the account, as returned by wa_list_accounts; omit it when the workspace has only one account" - changed
Input schema / requiredPrevious value: -[ - "account_id", - "chat", - "message_id", - "text" -]New value: +[ + "chat", + "message_id", + "text" +] - added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_enable_webhook1 field changed- added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_follow_channel1 field changed- added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_get_chat6 fields changed- changed
Input schema / properties / account_id / descriptionPrevious value: -"the account whose conversation to read, from wa_list_accounts"New value: +"the account whose conversation to read, from wa_list_accounts; omit it when the workspace has only one account" - added
Input schema / properties / include_media_urlsAdded value: +{ + "description": "also return attachment.media_url on each available attachment — a time-limited (1h) signed URL to GET the bytes with plain HTTP instead of a wa_get_media call; off by default", + "type": "boolean" +} - removed
Input schema / requiredRemoved value: -[ - "account_id" -] - changed
Output schema / properties / messages / items / properties / attachment / descriptionPrevious value: -"present on an image, video, audio, document or sticker message: the file's mime type, size and name; fetch the bytes with wa_get_media"New value: +"present on an image, video, audio, document or sticker message: the file's mime type, size and name; fetch the bytes with wa_get_media, or pass include_media_urls on the read to get a direct media_url" - added
Output schema / properties / messages / items / properties / attachment / properties / media_urlAdded value: +{ + "description": "a time-limited (1h) signed URL to GET the attachment's bytes, present only when the read passed include_media_urls and the attachment is available; an expired link is refused — read again for a fresh one", + "type": "string" +} - added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_get_group_invite_link1 field changed- added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_get_media3 fields changed- changed
Input schema / properties / account_id / descriptionPrevious value: -"the account that received the message, from wa_list_accounts"New value: +"the account that received the message, from wa_list_accounts; omit it when the workspace has only one account" - changed
Input schema / requiredPrevious value: -[ - "account_id", - "message_id" -]New value: +[ + "message_id" +] - added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_get_message6 fields changed- changed
Input schema / properties / account_id / descriptionPrevious value: -"the account the message belongs to, from wa_list_accounts"New value: +"the account the message belongs to, from wa_list_accounts; omit it when the workspace has only one account" - added
Input schema / properties / include_media_urlsAdded value: +{ + "description": "also return attachment.media_url when the message carries an available attachment — a time-limited (1h) signed URL to GET the bytes with plain HTTP instead of a wa_get_media call; off by default", + "type": "boolean" +} - removed
Input schema / requiredRemoved value: -[ - "account_id" -] - changed
Output schema / properties / message / properties / attachment / descriptionPrevious value: -"present on an image, video, audio, document or sticker message: the file's mime type, size and name; fetch the bytes with wa_get_media"New value: +"present on an image, video, audio, document or sticker message: the file's mime type, size and name; fetch the bytes with wa_get_media, or pass include_media_urls on the read to get a direct media_url" - added
Output schema / properties / message / properties / attachment / properties / media_urlAdded value: +{ + "description": "a time-limited (1h) signed URL to GET the attachment's bytes, present only when the read passed include_media_urls and the attachment is available; an expired link is refused — read again for a fresh one", + "type": "string" +} - added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_get_plan1 field changed- added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_get_profile3 fields changed- changed
Input schema / properties / account_id / descriptionPrevious value: -"which of your accounts to ask from, from wa_list_accounts"New value: +"which of your accounts to ask from, from wa_list_accounts; omit it when the workspace has only one account" - removed
Input schema / requiredRemoved value: -[ - "account_id" -] - added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_join_group1 field changed- added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_leave_chat1 field changed- added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_list_blocked1 field changed- added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_list_calls1 field changed- added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_list_channels1 field changed- added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_list_contacts1 field changed- added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_list_group_members1 field changed- added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_list_groups1 field changed- added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_list_messages4 fields changed- added
Input schema / properties / include_media_urlsAdded value: +{ + "description": "also return attachment.media_url on each available attachment — a time-limited (1h) signed URL to GET the bytes with plain HTTP instead of a wa_get_media call; off by default", + "type": "boolean" +} - changed
Output schema / properties / messages / items / properties / attachment / descriptionPrevious value: -"present on an image, video, audio, document or sticker message: the file's mime type, size and name; fetch the bytes with wa_get_media"New value: +"present on an image, video, audio, document or sticker message: the file's mime type, size and name; fetch the bytes with wa_get_media, or pass include_media_urls on the read to get a direct media_url" - added
Output schema / properties / messages / items / properties / attachment / properties / media_urlAdded value: +{ + "description": "a time-limited (1h) signed URL to GET the attachment's bytes, present only when the read passed include_media_urls and the attachment is available; an expired link is refused — read again for a fresh one", + "type": "string" +} - added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_list_templates1 field changed- added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_load_history3 fields changed- changed
Input schema / properties / account_id / descriptionPrevious value: -"the account, as returned by wa_list_accounts"New value: +"the account, as returned by wa_list_accounts; omit it when the workspace has only one account" - changed
Input schema / requiredPrevious value: -[ - "account_id", - "chat" -]New value: +[ + "chat" +] - added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_pair_account1 field changed- added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_pair_status1 field changed- added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_react3 fields changed- changed
Input schema / properties / account_id / descriptionPrevious value: -"the account, as returned by wa_list_accounts"New value: +"the account, as returned by wa_list_accounts; omit it when the workspace has only one account" - changed
Input schema / requiredPrevious value: -[ - "account_id", - "chat", - "message_id", - "reaction" -]New value: +[ + "chat", + "message_id", + "reaction" +] - added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_remove_participants1 field changed- added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_report1 field changed- added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_send_message3 fields changed- changed
Input schema / properties / account_id / descriptionPrevious value: -"the account to send from, as returned by wa_list_accounts"New value: +"the account to send from — the account_id on the message row you are replying to, or from wa_list_accounts; omit it when the workspace has only one account" - changed
Input schema / requiredPrevious value: -[ - "account_id", - "to" -]New value: +[ + "to" +] - added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_set_presence3 fields changed- changed
Input schema / properties / account_id / descriptionPrevious value: -"the account, as returned by wa_list_accounts"New value: +"the account, as returned by wa_list_accounts; omit it when the workspace has only one account" - changed
Input schema / requiredPrevious value: -[ - "account_id", - "state" -]New value: +[ + "state" +] - added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_set_profile_photo1 field changed- added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_set_webhook1 field changed- added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_unpair_account1 field changed- added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_update_group1 field changed- added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
- Changed
wa_update_participants1 field changed- added
Output schema / properties / refusal / properties / candidatesAdded value: +{ + "description": "on an account_ambiguous refusal: the accounts to choose from — retry with one of these as account_id", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the id to retry with as account_id", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + }, + "status": { + "description": "whether the number works right now — live, connecting, or why not, as wa_list_accounts reports it", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +}
8 tool updates
- Changed
wa_get_chat2 fields changed- changed
Output schema / properties / messages / items / properties / chat / descriptionPrevious value: -"the conversation JID; pass it to wa_send_message's 'to' to reply here — a group is …@g.us, a channel …@newsletter"New value: +"the conversation JID; pass it to wa_send_message's 'to' to reply here — a group is …@g.us, a channel …@newsletter; on a Telegram account a Telegram id: <id>@telegram for a user, -<id>@telegram for a basic group, -100<id>@telegram for a channel or supergroup" - changed
Output schema / properties / messages / items / properties / peer / descriptionPrevious value: -"the other party's phone number (for a group/channel this is the individual SENDER; use chat to reply)"New value: +"the other party's phone number (for a group/channel this is the individual SENDER; use chat to reply); on a Telegram account the other party's Telegram id, <id>@telegram"
- Changed
wa_get_media1 field changed- changed
Input schema / properties / message_id / descriptionPrevious value: -"the WhatsApp message id whose attachment to fetch, from wa_list_messages"New value: +"the message id whose attachment to fetch, from wa_list_messages (a WhatsApp message id, or on a Telegram account one of the form <chat>_<n>)"
- Changed
wa_get_message2 fields changed- changed
Output schema / properties / message / properties / chat / descriptionPrevious value: -"the conversation JID; pass it to wa_send_message's 'to' to reply here — a group is …@g.us, a channel …@newsletter"New value: +"the conversation JID; pass it to wa_send_message's 'to' to reply here — a group is …@g.us, a channel …@newsletter; on a Telegram account a Telegram id: <id>@telegram for a user, -<id>@telegram for a basic group, -100<id>@telegram for a channel or supergroup" - changed
Output schema / properties / message / properties / peer / descriptionPrevious value: -"the other party's phone number (for a group/channel this is the individual SENDER; use chat to reply)"New value: +"the other party's phone number (for a group/channel this is the individual SENDER; use chat to reply); on a Telegram account the other party's Telegram id, <id>@telegram"
- Changed
wa_list_accounts4 fields changed- changed
Output schema / properties / accounts / descriptionPrevious value: -"the WhatsApp accounts this API key can use"New value: +"the accounts this API key can use — WhatsApp numbers and Telegram accounts; each says which in backend" - changed
Output schema / properties / accounts / items / properties / backend / descriptionPrevious value: -"the account's backend: official (WhatsApp Business API) or personal (a linked device)"New value: +"the account's backend: official (WhatsApp Business API), personal (a WhatsApp linked device) or telegram (a Telegram user account; its chats and senders are Telegram ids of the form <id>@telegram)" - changed
Output schema / properties / accounts / items / properties / push_name / descriptionPrevious value: -"the display name WhatsApp shows for this account"New value: +"the display name WhatsApp (or Telegram) shows for this account" - changed
Output schema / properties / accounts / items / properties / status / descriptionPrevious value: -"whether the number is actually working: live, connecting, starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked"New value: +"whether the number is actually working: live, connecting, starting, not_running, whatsapp_down (telegram_down for a Telegram account), suspended, pairing, unlinked or locked"
- Changed
wa_list_messages3 fields changed- changed
Input schema / properties / chat / descriptionPrevious value: -"only this conversation — a phone number or a group JID"New value: +"only this conversation — a phone number or a group JID, or on a Telegram account the chat's Telegram id (<id>@telegram)" - changed
Output schema / properties / messages / items / properties / chat / descriptionPrevious value: -"the conversation JID; pass it to wa_send_message's 'to' to reply here — a group is …@g.us, a channel …@newsletter"New value: +"the conversation JID; pass it to wa_send_message's 'to' to reply here — a group is …@g.us, a channel …@newsletter; on a Telegram account a Telegram id: <id>@telegram for a user, -<id>@telegram for a basic group, -100<id>@telegram for a channel or supergroup" - changed
Output schema / properties / messages / items / properties / peer / descriptionPrevious value: -"the other party's phone number (for a group/channel this is the individual SENDER; use chat to reply)"New value: +"the other party's phone number (for a group/channel this is the individual SENDER; use chat to reply); on a Telegram account the other party's Telegram id, <id>@telegram"
- Changed
wa_pair_account5 fields changed- changed
Input schema / properties / import_history / descriptionPrevious value: -"import the phone's recent message history (about two months) as read-only history for this pairing; omit to use the workspace default"New value: +"import the phone's recent message history (about two months) as read-only history for this pairing; omit to use the workspace default (WhatsApp only)" - added
Input schema / properties / networkAdded value: +{ + "description": "the messaging network of the account to link: whatsapp (the default) or telegram. A Telegram account links by QR only: the user scans it from Telegram → Settings → Devices → Link Desktop Device. Telegram accounts must be enabled for the workspace, or the call is refused", + "type": "string" +} - changed
Input schema / properties / phone / descriptionPrevious value: -"link by phone-number code instead of a QR: the number to link, in international format with its country code (for example +52 998 123 4567). WhatsApp on that phone is asked to accept an 8-character code, returned as pair_code. Use it when the user has only the one phone that runs WhatsApp and cannot scan a QR from another screen"New value: +"link by phone-number code instead of a QR: the number to link, in international format with its country code (for example +52 998 123 4567). WhatsApp on that phone is asked to accept an 8-character code, returned as pair_code. Use it when the user has only the one phone that runs WhatsApp and cannot scan a QR from another screen (WhatsApp only)" - added
Output schema / properties / networkAdded value: +{ + "description": "the messaging network the pairing links on: whatsapp or telegram", + "type": "string" +} - changed
Output schema / properties / state / descriptionPrevious value: -"starting, qr, code, paired or failed"New value: +"starting, qr, code, password_needed (a Telegram account with two-step verification: the user must enter their cloud password on the console's pairing page — never ask for it here), paired or failed"
- Changed
wa_pair_status2 fields changed- added
Output schema / properties / networkAdded value: +{ + "description": "the messaging network the pairing links on: whatsapp or telegram", + "type": "string" +} - changed
Output schema / properties / state / descriptionPrevious value: -"starting, qr, code, paired or failed"New value: +"starting, qr, code, password_needed (a Telegram account with two-step verification: the user must enter their cloud password on the console's pairing page — never ask for it here), paired or failed"
- Changed
wa_send_message1 field changed- changed
Input schema / properties / to / descriptionPrevious value: -"the recipient: a phone number in international form (digits only, e.g. 447700900123) for a 1:1 chat, or a full group/channel JID (…@g.us for a group, …@newsletter for a channel)"New value: +"the recipient. WhatsApp: a phone number in international form (digits only, e.g. 447700900123) for a 1:1 chat, or a full group/channel JID (…@g.us for a group, …@newsletter for a channel). Telegram (an account whose backend is telegram): the chat id exactly as wa_list_messages reports it (<id>@telegram; a group is -<id>@telegram, a channel or supergroup -100<id>@telegram) to reply, or to start a conversation an @username, a t.me/<name> link or a phone in +E.164 form — never a bare number, which could be a phone or a user id"
1 tool update
- Changed
wa_list_messages1 field changed- added
Output schema / properties / hintAdded value: +{ + "description": "present when the read found nothing new: wait before polling again", + "type": "string" +}
2 tool updates
- Changed
wa_get_media4 fields changed- changed
Output schema / properties / media_base64 / descriptionPrevious value: -"base64 of the attachment, present when status is ok"New value: +"base64 of the attachment, present for a small attachment" - added
Output schema / properties / media_urlAdded value: +{ + "description": "a time-limited (1h) URL to GET a large attachment's bytes, present instead of media_base64 when the attachment is over the inline cap", + "type": "string" +} - added
Output schema / properties / sizeAdded value: +{ + "description": "the attachment size in bytes", + "type": "integer" +} - changed
Output schema / properties / status / descriptionPrevious value: -"ok (media returned) or refused"New value: +"ok (media returned, inline or as a url) or refused"
- Changed
wa_set_webhook1 field changed- changed
Input schema / properties / events / descriptionPrevious value: -"which events to receive; defaults to message.inbound"New value: +"which events to receive — any of message.inbound, message.outbound, message.status, account.connected, account.disconnected, account.unlinked, account.blocked, call.completed, call.missed; defaults to message.inbound"
1 tool update
- Changed
wa_pair_account1 field changed- changed
Input schema / properties / phone / descriptionPrevious value: -"link by phone-number code instead of a QR: the number to link, in international format with its country code (for example +52 998 123 4567). WhatsApp on that phone is asked to accept an 8-character code, returned as pair_code. Use it when the user has only that phone and cannot scan a QR"New value: +"link by phone-number code instead of a QR: the number to link, in international format with its country code (for example +52 998 123 4567). WhatsApp on that phone is asked to accept an 8-character code, returned as pair_code. Use it when the user has only the one phone that runs WhatsApp and cannot scan a QR from another screen"
3 tool updates
- Changed
wa_get_chat1 field changed- changed
Output schema / properties / messages / items / properties / kind / descriptionPrevious value: -"what the message is: text, image, video, audio, document, sticker, reaction, location, live_location, contact, poll, poll_vote, video_note, album, event, comment, pin, group_invite or template; other is a type this server does not classify. text carries a body, and so do image/video/document captions and template text; an image, video, audio, document or sticker attachment can be fetched with wa_get_media"New value: +"what the message is: text, image, video, audio, document, sticker, reaction, location, live_location, contact, poll, poll_vote, video_note, album, event, comment, pin, group_invite, template or call_permission; other is a type this server does not classify. text carries a body, and so do image/video/document captions, template text and a call_permission request or answer; an image, video, audio, document or sticker attachment can be fetched with wa_get_media"
- Changed
wa_get_message1 field changed- changed
Output schema / properties / message / properties / kind / descriptionPrevious value: -"what the message is: text, image, video, audio, document, sticker, reaction, location, live_location, contact, poll, poll_vote, video_note, album, event, comment, pin, group_invite or template; other is a type this server does not classify. text carries a body, and so do image/video/document captions and template text; an image, video, audio, document or sticker attachment can be fetched with wa_get_media"New value: +"what the message is: text, image, video, audio, document, sticker, reaction, location, live_location, contact, poll, poll_vote, video_note, album, event, comment, pin, group_invite, template or call_permission; other is a type this server does not classify. text carries a body, and so do image/video/document captions, template text and a call_permission request or answer; an image, video, audio, document or sticker attachment can be fetched with wa_get_media"
- Changed
wa_list_messages1 field changed- changed
Output schema / properties / messages / items / properties / kind / descriptionPrevious value: -"what the message is: text, image, video, audio, document, sticker, reaction, location, live_location, contact, poll, poll_vote, video_note, album, event, comment, pin, group_invite or template; other is a type this server does not classify. text carries a body, and so do image/video/document captions and template text; an image, video, audio, document or sticker attachment can be fetched with wa_get_media"New value: +"what the message is: text, image, video, audio, document, sticker, reaction, location, live_location, contact, poll, poll_vote, video_note, album, event, comment, pin, group_invite, template or call_permission; other is a type this server does not classify. text carries a body, and so do image/video/document captions, template text and a call_permission request or answer; an image, video, audio, document or sticker attachment can be fetched with wa_get_media"
45 tool updates
- Changed
wa_ai_call_get3 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_ai_call_hangup3 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_ai_call_start3 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_ai_list_calls3 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_ai_list_presets3 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_block_contact3 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_create_group3 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_create_template4 fields changed- added
Input schema / properties / call_permissionAdded value: +{ + "description": "true asks the customer to allow the business to call them (WhatsApp's call permission request); MARKETING or UTILITY only, and no buttons", + "type": "boolean" +} - added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_delete_group3 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_delete_message3 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_delete_template3 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_delete_webhook3 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_edit_message3 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_enable_webhook3 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_follow_channel3 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_get_chat4 fields changed- added
Output schema / properties / account_noticesAdded value: +{ + "description": "present when a number this read covers is not working: new messages are not arriving on it; says why and what to do", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the account this notice is about", + "type": "string" + }, + "message": { + "description": "what is wrong and what to do; tell the user", + "type": "string" + }, + "since": { + "description": "when it stopped working, RFC3339, when known", + "type": "string" + }, + "status": { + "description": "why it is not live: starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" + }, + "status_reason": { + "description": "the detail, e.g. no_egress, no_plan, stopped", + "type": "string" + } + }, + "required": [ + "account_id", + "status", + "message" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +} - added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_get_group_invite_link3 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_get_media3 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_get_message4 fields changed- added
Output schema / properties / account_noticesAdded value: +{ + "description": "present when a number this read covers is not working: new messages are not arriving on it; says why and what to do", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the account this notice is about", + "type": "string" + }, + "message": { + "description": "what is wrong and what to do; tell the user", + "type": "string" + }, + "since": { + "description": "when it stopped working, RFC3339, when known", + "type": "string" + }, + "status": { + "description": "why it is not live: starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" + }, + "status_reason": { + "description": "the detail, e.g. no_egress, no_plan, stopped", + "type": "string" + } + }, + "required": [ + "account_id", + "status", + "message" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +} - added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_get_plan3 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_get_profile3 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_join_group3 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_leave_chat3 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_list_accounts4 fields changed- added
Output schema / properties / accounts / items / properties / statusAdded value: +{ + "description": "whether the number is actually working: live, connecting, starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / accounts / items / properties / status_reasonAdded value: +{ + "description": "the detail when it is not live, e.g. no_egress, no_plan, stopped", + "type": "string" +} - added
Output schema / properties / accounts / items / properties / status_sinceAdded value: +{ + "description": "when it stopped working, RFC3339, when known", + "type": "string" +} - added
Output schema / properties / accounts / items / properties / what_to_doAdded value: +{ + "description": "what is wrong and what to do, when it is not live; tell the user", + "type": "string" +}
- Changed
wa_list_blocked3 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_list_calls3 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_list_channels3 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_list_contacts3 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_list_group_members3 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_list_groups3 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_list_messages4 fields changed- added
Output schema / properties / account_noticesAdded value: +{ + "description": "present when a number this read covers is not working: new messages are not arriving on it; says why and what to do", + "items": { + "additionalProperties": false, + "properties": { + "account_id": { + "description": "the account this notice is about", + "type": "string" + }, + "message": { + "description": "what is wrong and what to do; tell the user", + "type": "string" + }, + "since": { + "description": "when it stopped working, RFC3339, when known", + "type": "string" + }, + "status": { + "description": "why it is not live: starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" + }, + "status_reason": { + "description": "the detail, e.g. no_egress, no_plan, stopped", + "type": "string" + } + }, + "required": [ + "account_id", + "status", + "message" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] +} - added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_list_templates4 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +} - added
Output schema / properties / templates / items / properties / call_permissionAdded value: +{ + "description": "true when the template asks the customer to allow the business to call them (WhatsApp's call permission request)", + "type": "boolean" +}
- Changed
wa_load_history3 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_pair_account3 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_pair_status3 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_react3 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_remove_participants3 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_report3 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_send_message3 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_set_presence3 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_set_profile_photo3 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_set_webhook3 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_unpair_account3 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_update_group3 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
- Changed
wa_update_participants3 fields changed- added
Output schema / properties / refusal / properties / account_statusAdded value: +{ + "description": "when the number is not working: its status — starting, not_running, whatsapp_down, suspended, pairing, unlinked or locked", + "type": "string" +} - added
Output schema / properties / refusal / properties / account_status_reasonAdded value: +{ + "description": "the detail of account_status, e.g. no_egress, stopped, no_plan", + "type": "string" +} - added
Output schema / properties / refusal / properties / sinceAdded value: +{ + "description": "when the number stopped working, RFC3339, when known", + "type": "string" +}
2 tool updates
- Changed
wa_pair_account4 fields changed- added
Input schema / properties / phoneAdded value: +{ + "description": "link by phone-number code instead of a QR: the number to link, in international format with its country code (for example +52 998 123 4567). WhatsApp on that phone is asked to accept an 8-character code, returned as pair_code. Use it when the user has only that phone and cannot scan a QR", + "type": "string" +} - added
Output schema / properties / expires_atAdded value: +{ + "description": "when pair_code stops working, RFC 3339 (phone-number pairing only)", + "type": "string" +} - added
Output schema / properties / pair_codeAdded value: +{ + "description": "the 8-character code the user types on their phone (phone-number pairing only)", + "type": "string" +} - changed
Output schema / properties / state / descriptionPrevious value: -"starting, qr, paired or failed"New value: +"starting, qr, code, paired or failed"
- Changed
wa_pair_status3 fields changed- added
Output schema / properties / expires_atAdded value: +{ + "description": "when pair_code stops working, RFC 3339 (phone-number pairing only)", + "type": "string" +} - added
Output schema / properties / pair_codeAdded value: +{ + "description": "the 8-character code the user types on their phone (phone-number pairing only)", + "type": "string" +} - changed
Output schema / properties / state / descriptionPrevious value: -"starting, qr, paired or failed"New value: +"starting, qr, code, paired or failed"
1 tool update
- Added
wa_report
7 tool updates
- Added
wa_create_template - Added
wa_delete_template - Changed
wa_get_chat9 fields changed- added
Input schema / properties / sinceAdded value: +{ + "description": "only messages sent at or after this time: RFC3339 with a zone (2026-10-01T09:00:00+03:00) or a date (2026-10-01 = midnight UTC); omit for no lower bound", + "type": "string" +} - added
Input schema / properties / untilAdded value: +{ + "description": "only messages sent BEFORE this time — exclusive, so all of 1 October is since 2026-10-01 until 2026-10-02; same formats as since; omit for no upper bound", + "type": "string" +} - added
Output schema / properties / accountAdded value: +{ + "additionalProperties": false, + "description": "the account this conversation was read from", + "properties": { + "account_id": { + "description": "the id to pass to other wa_ tools", + "type": "string" + }, + "name": { + "description": "the account's WhatsApp display name", + "type": "string" + }, + "phone": { + "description": "the account's phone number, E.164", + "type": "string" + } + }, + "required": [ + "account_id" + ], + "type": [ + "null", + "object" + ] +} - added
Output schema / properties / has_moreAdded value: +{ + "description": "true when older messages match than were returned; page them with wa_list_messages(account_id, chat, since, until, include_history=true)", + "type": "boolean" +} - added
Output schema / properties / messages / items / properties / account_nameAdded value: +{ + "description": "the WhatsApp display name of that account", + "type": "string" +} - added
Output schema / properties / messages / items / properties / account_phoneAdded value: +{ + "description": "the phone number of your account this message was sent from or received on, E.164", + "type": "string" +} - added
Output schema / properties / messages / items / properties / attachmentAdded value: +{ + "additionalProperties": false, + "description": "present on an image, video, audio, document or sticker message: the file's mime type, size and name; fetch the bytes with wa_get_media", + "properties": { + "available": { + "description": "true when the file should be fetchable with wa_get_media(account_id, message_id) — a live received attachment; false for history and for files you sent, which are not kept", + "type": "boolean" + }, + "file_name": { + "description": "documents only: the file name the sender gave it", + "type": "string" + }, + "mime": { + "description": "the attachment's mime type as the sender declared it, e.g. image/jpeg or application/pdf; empty for a message stored before this was recorded", + "type": "string" + }, + "size": { + "description": "the attachment's size in bytes as the sender declared it; 0 when unknown", + "type": "integer" + } + }, + "required": [ + "available" + ], + "type": [ + "null", + "object" + ] +} - added
Output schema / properties / messages / items / properties / received_atAdded value: +{ + "description": "when this server received and stored the message, RFC3339; later than at for a message delivered late or loaded as history", + "type": "string" +} - added
Output schema / properties / messages / items / properties / sender_nameAdded value: +{ + "description": "who wrote the message, by name: for inbound the sender's name as saved in this account's contacts, or else the name they chose for themselves; for outbound this account's own WhatsApp name. Empty when no name is known", + "type": "string" +}
- Changed
wa_get_message5 fields changed- added
Output schema / properties / message / properties / account_nameAdded value: +{ + "description": "the WhatsApp display name of that account", + "type": "string" +} - added
Output schema / properties / message / properties / account_phoneAdded value: +{ + "description": "the phone number of your account this message was sent from or received on, E.164", + "type": "string" +} - added
Output schema / properties / message / properties / attachmentAdded value: +{ + "additionalProperties": false, + "description": "present on an image, video, audio, document or sticker message: the file's mime type, size and name; fetch the bytes with wa_get_media", + "properties": { + "available": { + "description": "true when the file should be fetchable with wa_get_media(account_id, message_id) — a live received attachment; false for history and for files you sent, which are not kept", + "type": "boolean" + }, + "file_name": { + "description": "documents only: the file name the sender gave it", + "type": "string" + }, + "mime": { + "description": "the attachment's mime type as the sender declared it, e.g. image/jpeg or application/pdf; empty for a message stored before this was recorded", + "type": "string" + }, + "size": { + "description": "the attachment's size in bytes as the sender declared it; 0 when unknown", + "type": "integer" + } + }, + "required": [ + "available" + ], + "type": [ + "null", + "object" + ] +} - added
Output schema / properties / message / properties / received_atAdded value: +{ + "description": "when this server received and stored the message, RFC3339; later than at for a message delivered late or loaded as history", + "type": "string" +} - added
Output schema / properties / message / properties / sender_nameAdded value: +{ + "description": "who wrote the message, by name: for inbound the sender's name as saved in this account's contacts, or else the name they chose for themselves; for outbound this account's own WhatsApp name. Empty when no name is known", + "type": "string" +}
- Changed
wa_list_calls4 fields changed- added
Input schema / properties / sinceAdded value: +{ + "description": "only calls at or after this time: RFC3339 with a zone (2026-10-01T09:00:00+03:00) or a date (2026-10-01 = midnight UTC); omit for no lower bound", + "type": "string" +} - added
Input schema / properties / untilAdded value: +{ + "description": "only calls BEFORE this time — exclusive, so all of 1 October is since 2026-10-01 until 2026-10-02; same formats as since; omit for no upper bound", + "type": "string" +} - added
Output schema / properties / calls / items / properties / account_nameAdded value: +{ + "description": "the WhatsApp display name of that account", + "type": "string" +} - added
Output schema / properties / calls / items / properties / account_phoneAdded value: +{ + "description": "the phone number of your account that placed or received this call, E.164", + "type": "string" +}
- Changed
wa_list_messages11 fields changed- added
Input schema / properties / account_idAdded value: +{ + "description": "only this account's messages, from wa_list_accounts; omit for every account", + "type": "string" +} - added
Input schema / properties / chatAdded value: +{ + "description": "only this conversation — a phone number or a group JID", + "type": "string" +} - added
Input schema / properties / include_historyAdded value: +{ + "description": "also return imported history (pairing sync and wa_load_history); off by default. With it on, a page is in storage order rather than time order — sort by at", + "type": "boolean" +} - added
Input schema / properties / sinceAdded value: +{ + "description": "only messages sent at or after this time: RFC3339 with a zone (2026-10-01T09:00:00+03:00) or a date (2026-10-01 = midnight UTC); omit for no lower bound", + "type": "string" +} - added
Input schema / properties / untilAdded value: +{ + "description": "only messages sent BEFORE this time — exclusive, so all of 1 October is since 2026-10-01 until 2026-10-02; same formats as since; omit for no upper bound", + "type": "string" +} - added
Output schema / properties / messages / items / properties / account_nameAdded value: +{ + "description": "the WhatsApp display name of that account", + "type": "string" +} - added
Output schema / properties / messages / items / properties / account_phoneAdded value: +{ + "description": "the phone number of your account this message was sent from or received on, E.164", + "type": "string" +} - added
Output schema / properties / messages / items / properties / attachmentAdded value: +{ + "additionalProperties": false, + "description": "present on an image, video, audio, document or sticker message: the file's mime type, size and name; fetch the bytes with wa_get_media", + "properties": { + "available": { + "description": "true when the file should be fetchable with wa_get_media(account_id, message_id) — a live received attachment; false for history and for files you sent, which are not kept", + "type": "boolean" + }, + "file_name": { + "description": "documents only: the file name the sender gave it", + "type": "string" + }, + "mime": { + "description": "the attachment's mime type as the sender declared it, e.g. image/jpeg or application/pdf; empty for a message stored before this was recorded", + "type": "string" + }, + "size": { + "description": "the attachment's size in bytes as the sender declared it; 0 when unknown", + "type": "integer" + } + }, + "required": [ + "available" + ], + "type": [ + "null", + "object" + ] +} - added
Output schema / properties / messages / items / properties / received_atAdded value: +{ + "description": "when this server received and stored the message, RFC3339; later than at for a message delivered late or loaded as history", + "type": "string" +} - added
Output schema / properties / messages / items / properties / sender_nameAdded value: +{ + "description": "who wrote the message, by name: for inbound the sender's name as saved in this account's contacts, or else the name they chose for themselves; for outbound this account's own WhatsApp name. Empty when no name is known", + "type": "string" +} - added
Output schema / properties / refusalAdded value: +{ + "additionalProperties": false, + "description": "present only when the request was declined; next_cursor is then your after_cursor, unchanged", + "properties": { + "message": { + "description": "a human-readable explanation", + "type": "string" + }, + "reason": { + "description": "why the call was declined", + "type": "string" + }, + "refused": { + "description": "true when the call was declined rather than performed", + "type": "boolean" + }, + "retry_after_seconds": { + "description": "seconds to wait before retrying; absent or 0 means retrying will not help", + "type": "integer" + } + }, + "required": [ + "refused", + "reason", + "message" + ], + "type": [ + "null", + "object" + ] +}
- Changed
wa_list_templates6 fields changed- changed
Output schema / properties / templates / descriptionPrevious value: -"the approved message templates, with the name/language/variables to pass to wa_send_message"New value: +"every message template with its review status; only APPROVED ones can be sent, with the name/language/variables to pass to wa_send_message" - added
Output schema / properties / templates / items / properties / bodyAdded value: +{ + "description": "the template's body text as Meta holds it, with its {{n}} variables", + "type": "string" +} - added
Output schema / properties / templates / items / properties / buttonsAdded value: +{ + "description": "one line per button, e.g. 'Quick reply: Yes' or 'Link: Shop → https://…'", + "items": { + "type": "string" + }, + "type": [ + "null", + "array" + ] +} - added
Output schema / properties / templates / items / properties / footerAdded value: +{ + "description": "the template's footer, if any", + "type": "string" +} - added
Output schema / properties / templates / items / properties / headerAdded value: +{ + "description": "the template's text header, if any", + "type": "string" +} - added
Output schema / properties / templates / items / properties / rejected_reasonAdded value: +{ + "description": "for a REJECTED template, Meta's reason code (e.g. INVALID_FORMAT, TAG_CONTENT_MISMATCH); fix the template and create it again under a new name", + "type": "string" +}
4 tool updates
- Changed
wa_get_chat1 field changed- added
Output schema / properties / messages / items / properties / statusAdded value: +{ + "description": "delivery status of an outbound message from the provider's receipts: sent, delivered, read or failed; empty when no receipt has arrived (or for inbound). Only Business (Cloud API) numbers report this today", + "type": "string" +}
- Changed
wa_get_message1 field changed- added
Output schema / properties / message / properties / statusAdded value: +{ + "description": "delivery status of an outbound message from the provider's receipts: sent, delivered, read or failed; empty when no receipt has arrived (or for inbound). Only Business (Cloud API) numbers report this today", + "type": "string" +}
- Changed
wa_list_messages1 field changed- added
Output schema / properties / messages / items / properties / statusAdded value: +{ + "description": "delivery status of an outbound message from the provider's receipts: sent, delivered, read or failed; empty when no receipt has arrived (or for inbound). Only Business (Cloud API) numbers report this today", + "type": "string" +}
- Added
wa_list_templates
1 tool update
- Changed
wa_send_message3 fields changed- added
Input schema / properties / templateAdded value: +{ + "description": "optional: the name of a pre-approved message template to send (Business/WABA numbers only), e.g. hello_world. Use this to start a conversation or to message outside the 24-hour window; text and attachments are ignored when set", + "type": "string" +} - added
Input schema / properties / template_languageAdded value: +{ + "description": "optional: the template's language/locale code, e.g. en_US; defaults to en_US", + "type": "string" +} - added
Input schema / properties / template_variablesAdded value: +{ + "description": "optional: values that fill the template body's positional {{1}}, {{2}}, … placeholders, in order", + "items": { + "type": "string" + }, + "type": [ + "null", + "array" + ] +}
1 tool update
- Changed
wa_list_accounts3 fields changed- added
Output schema / properties / accounts / items / properties / backendAdded value: +{ + "description": "the account's backend: official (WhatsApp Business API) or personal (a linked device)", + "type": "string" +} - added
Output schema / properties / accounts / items / properties / featuresAdded value: +{ + "description": "the functions this number supports, e.g. messaging, templates, groups, calls; call only tools whose function is listed here", + "items": { + "type": "string" + }, + "type": [ + "null", + "array" + ] +} - changed
Output schema / properties / accounts / items / requiredPrevious value: -[ - "account_id", - "phone", - "push_name", - "state" -]New value: +[ + "account_id", + "phone", + "push_name", + "state", + "backend", + "features" +]
2 tool updates
- Added
wa_ai_call_hangup - Changed
wa_ai_list_presets3 fields changed- added
Output schema / properties / presets / items / properties / ring_delay_secsAdded value: +{ + "type": "integer" +} - added
Output schema / properties / presets / items / properties / start_delay_secsAdded value: +{ + "type": "integer" +} - changed
Output schema / properties / presets / items / requiredPrevious value: -[ - "id", - "name", - "description", - "provider", - "agent_id", - "agent_name", - "account_id", - "line", - "default_variables", - "expected_variables", - "enabled", - "answers_inbound", - "ready" -]New value: +[ + "id", + "name", + "description", + "provider", + "agent_id", + "agent_name", + "account_id", + "line", + "default_variables", + "expected_variables", + "enabled", + "answers_inbound", + "ring_delay_secs", + "start_delay_secs", + "ready" +]
3 tool updates
- Changed
wa_ai_call_get3 fields changed- added
Output schema / properties / call / properties / directionAdded value: +{ + "type": "string" +} - added
Output schema / properties / call / properties / fromAdded value: +{ + "type": "string" +} - changed
Output schema / properties / call / requiredPrevious value: -[ - "call_ref", - "status", - "preset", - "account_id", - "to", - "created_at", - "recording_state" -]New value: +[ + "call_ref", + "direction", + "status", + "preset", + "account_id", + "to", + "created_at", + "recording_state" +]
- Added
wa_ai_list_calls - Changed
wa_ai_list_presets2 fields changed- added
Output schema / properties / presets / items / properties / answers_inboundAdded value: +{ + "type": "boolean" +} - changed
Output schema / properties / presets / items / requiredPrevious value: -[ - "id", - "name", - "description", - "provider", - "agent_id", - "agent_name", - "account_id", - "line", - "default_variables", - "expected_variables", - "enabled", - "ready" -]New value: +[ + "id", + "name", + "description", + "provider", + "agent_id", + "agent_name", + "account_id", + "line", + "default_variables", + "expected_variables", + "enabled", + "answers_inbound", + "ready" +]
Publisher details
- Operator
- WhatMCP
- Operator website
- https://whatsmcp.com/mcp?utm_source=glama&utm_medium=directory&utm_campaign=mcp_listing&utm_content=com.whatsmcp
- Vendor relationship
- First-party
- Documentation
- https://whatsmcp.com/docs?utm_source=glama&utm_medium=directory&utm_campaign=mcp_listing&utm_content=com.whatsmcp
- Restrictions
- Plans: Frees, Started, Business, Premium · Publisher source
Related MCP Connectors
Ask questions across your WhatsApp inbox from Claude, ChatGPT, Cursor or any MCP client.
- WhatSyncOAuthapp.whatsync
WhatsApp for Claude, ChatGPT or any AI agent: search, reply and send. Personal or Business API.
Read-only WhatsApp MCP for your AI agent: it reads the chats you choose. Try the public demo.
Let Claude or ChatGPT search, read and send your WhatsApp messages over MCP. OAuth sign-in.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceEnables driving a Claude Code (or other MCP client) session directly from WhatsApp chats, with bidirectional messaging, media and locally transcribed voice notes, polls, per-group personalities, cron tasks, and emoji-reaction approval of tool requests. Inbound traffic is gated by pairing codes, allowlists, and per-group policies, and it runs either through a linked personal-device account or Meta's official Cloud API for business DMs.MIT
- AlicenseBqualityBmaintenanceEnables sending messages, images, documents and more on WhatsApp directly from any MCP-compatible AI, with tools for chat management, groups, and webhooks.371MIT
- AlicenseNot gradedqualityCmaintenanceA self-hosted WhatsApp bridge with an AI agent enabling searchable context, message drafting, and approval workflow via MCP protocol for Claude Desktop and other MCP clients.1MIT
- FlicenseNot gradedqualityAmaintenanceConnects a Claude Code (or any MCP) session to a WhatsApp account as a linked device or via Meta's official Cloud API, enabling bidirectional chats, group support, media exchange, local voice-note transcription, and scheduled tasks. Inbound messages are gated by pairing codes, allowlists and per-group policies, and Claude's tool permission requests can be approved or denied remotely with an emoji reaction.-
Glama MCP Gateway
Add one secure layer between your agents and this server.