Skip to main content
Glama

Turbo Notify: WhatsApp for AI agents

Server Details

Send and receive WhatsApp messages from your AI agent, on your own number.

If you are the author of this connector, you can claim ownership by verifying the domain or GitHub account it belongs to. Claimed connector authors can inspect health checks, view analytics, and manage their listing.
Status
Healthy
Last Tested
Transport
Streamable HTTP · MCP 2025-11-25
URL
Repository
turbo-notify/agent-skills
GitHub Stars
0
ChatGPT
–
Claude
–

TDQS

A4.1/5.0

Scored across 36 tools

Disambiguation5/5

Every tool targets a distinct resource and action, and overlapping-looking tools such as send_text vs reply_to_message, edit_text_message vs edit_media_caption vs edit_calendar_event, and quota vs usage tools are explicitly separated in their descriptions. An agent can reliably choose the correct tool without guessing.

Naming Consistency5/5

All tool names are snake_case and follow a predictable verb_noun pattern (list_, get_, send_, edit_, cancel_, connect_, etc.). Even longer names like send_typing_indicator and get_contact_profile_picture remain consistent with the overall convention.

Tool Count2/5

The server exposes 36 tools, which is well above the 3-15 sweet spot and past the 25+ threshold for a heavy tool surface. Many tools are genuinely distinct, but the overall count is large enough to burden tool selection and could likely be consolidated in places.

Completeness4/5

The surface covers the core WhatsApp messaging lifecycle comprehensively: sending across content types, replying, reacting, editing, deleting, read receipts, status, event polling, contacts, groups, numbers, and quotas. Some gaps remain around group administration (creating groups or managing participants) and contact editing, but these may reflect platform limitations rather than avoidable dead ends.

Available Tools

36 tools
cancel_calendar_eventCancel a calendar event already sentA
Destructive
Inspect

Cancel a calendar event this number already sent.

The event stays in the chat marked as canceled, and WhatsApp tells the guests. Send the same name and start_at the event has, plus the details you want the canceled card to still show (description, end_at, join_link, location, has_reminder with reminder_offset_sec, extra_guests_allowed): the canceled event is shown with what you send here, and anything you leave out disappears from it.

Cancel when the date, time or place change and the guests must accept again: cancel the old event here, then send the new one with send_calendar_event, because the old answer does not carry over to a new event. To correct a mistake (a typo, the description, a link) use edit_calendar_event instead, and the guests keep their answer. A cancel does not change the entry a guest already added to their own calendar with the card's "Add to calendar" button. It stays on the old date, and adding again creates a second entry, which only the guest can delete.

Only a calendar event can be canceled. Using this tool on any other message answers invalid_request: message_not_editable; to take back a message of another kind, use delete_message.

Only a message sent THROUGH Turbo Notify can be canceled. One typed on the phone itself belongs to the same number but cannot be canceled here, and neither can a message received from someone else.

The 15-minute limit for a text or a caption does not apply to a calendar event.

The cancel is accepted at once and the outcome arrives as an event: message.edited when it worked, message.edit.failed when WhatsApp or the platform could not apply it. Read them with list_events.

The number first appears online and its unread messages in that conversation are marked as read, then the cancel happens. Opening the conversation this way is automatic and uses no quota of its own.

NameRequiredDescriptionDefault
nameYesThe event's title, up to 200 characters.
end_atNoWhen the event ends. ISO 8601 with an offset, and later than `start_at`.
locationNoWhere the event takes place: a map pin with an optional name and address.
start_atYesWhen the event starts. ISO 8601 with an offset, for example `2026-09-10T14:00:00Z`. A time without an offset is rejected.
join_linkNoA link guests can open to join, for example a video call.
message_idYesMessage id (`msg_…`), as returned by a send or by `list_messages`.
descriptionNoDetails shown on the event, up to 2000 characters.
has_reminderNoSet to true to remind guests before the event. Off when left out.
number_aliasNoWhich of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to see them. Defaults to the main number.main
reminder_offset_secNoHow many seconds before the event the reminder goes off, for example 600 for ten minutes. Only takes effect together with `has_reminder`.
extra_guests_allowedNoSet to true to let guests bring extra people. Off when left out.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Far beyond the annotations, it discloses that the card stays in the chat marked canceled, that WhatsApp notifies guests, that omitted fields disappear from the canceled card, and that a guest's own 'Add to calendar' entry is not updated and re-adding duplicates it. It also names the failure mode (`invalid_request: message_not_editable`), the eligibility limits (only messages sent through Turbo Notify), and the asynchronous outcome events (`message.edited` / `message.edit.failed`) readable via `list_events`. The side effect of bringing the number online and marking unread messages as read is a genuinely non-obvious behavior worth surfacing.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action and the required-field rule, then layered by concern (alternatives, guest-calendar caveat, error cases, async outcome). It is long, and the closing paragraph on going online / unread messages is somewhat tangential, but nearly every sentence carries operational information for a destructive, non-idempotent operation.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 11-parameter destructive mutation with an output schema, the description covers the omission semantics, eligibility restrictions, error code, async completion path, and downstream effects on guest calendars. 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.

Parameters4/5

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 meaning the schema does not: `name` and `start_at` must match the existing event, and the optional fields must be resent because anything left out disappears from the canceled card. That re-send semantic is the key invocation detail an agent could otherwise get wrong.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb and resource ('Cancel a calendar event this number already sent') plus the scope constraint that it must be a message this number sent. It is immediately distinguishable from edit_calendar_event and delete_message, both of which are named explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use ('Cancel when the date, time or place change and the guests must accept again'), explicit when-not ('To correct a mistake (a typo, the description, a link) use `edit_calendar_event` instead'), and an alternative for non-calendar messages (`delete_message`). The cancel-then-resend workflow with `send_calendar_event` is spelled out with its rationale.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

connect_numberBring a number back onlineA
Idempotent
Inspect

Reconnect a number that is currently offline.

Uses the credentials already stored for the number, so no QR code and no human are involved. Use it when get_number reports disconnected and you want to send.

Returns immediately, before the connection is established. The answer has the number's alias, status set to connecting and at, the moment the request was accepted. The number reaches connected a few seconds later: poll get_number, which stays the source of the current status and of its own at, rather than assuming it worked.

It works the same on every number and never charges. On an extra number scheduled for removal it does not change the removal: the number keeps working until its date. Cancelling a removal is not available to agents.

This cannot rescue a revoked number: that one was unlinked from the phone and needs a person to pair it again.

Calling it again changes nothing further. A number that is already connected or connecting answers with an already_connected or already_connecting error, which means the goal is met, not that the call failed.

NameRequiredDescriptionDefault
number_aliasNoWhich of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to see them. Defaults to the main number.main

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare write/idempotent/non-destructive/open-world; the description goes well beyond by disclosing the asynchronous contract (returns before connection, status `connecting`), the returned fields, that no QR or human is needed, that it never charges, and that a scheduled removal is unaffected. The idempotency annotation is made concrete via the `already_connected`/`already_connecting` errors being framed as success rather than failure.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The critical constraint (returns immediately, poll get_number) is front-loaded and each paragraph carries a distinct fact: async behavior, cost, scheduled removal, revoked case, idempotency. It runs long with a few near-redundant lines such as "It works the same on every number," keeping it just short of maximally tight.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter restore action with an output schema, the description covers everything an agent needs: async return semantics, which fields come back, how to confirm success, cost, edge cases (removal pending, revoked), and idempotent re-calls. Return-value detail is correctly delegated to the output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the `number_alias` description already explains main/alias/id forms and points to list_numbers, so the schema does the heavy lifting. The prose adds only that behavior is identical on every number, which is about scope rather than the parameter itself – baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("Reconnect a number that is currently offline") and implicitly bounds it against disconnect_number and get_number by naming the offline state as the precondition. An agent can distinguish it from every sibling without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit when-to-use ("Use it when `get_number` reports `disconnected` and you want to send") plus when-not cases: revoked numbers need a person, and already connected/connecting numbers return specific errors. It also routes follow-up to get_number for polling, so both the trigger and the alternative are named.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

delete_messageDelete a message for everyoneA
Destructive
Inspect

Revoke a message for everyone in the conversation.

This is WhatsApp's "delete for everyone". It is not reversible, and recipients see a tombstone where the message was, so they can tell something was deleted. Confirm with a human before using it on anything a person has plausibly already read.

The number first appears online and its unread messages in that conversation are marked as read, then the message is deleted. Opening the conversation this way is automatic and uses no quota of its own.

NameRequiredDescriptionDefault
message_idYesMessage id (`msg_…`), as returned by a send or by `list_messages`.
number_aliasNoWhich of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to see them. Defaults to the main number.main

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the destructiveHint/idempotentHint annotations: discloses irreversibility, that recipients see a tombstone, that the actor's number appears online, and that unread messages in the conversation are silently marked read. These are non-obvious side effects an agent could not infer from 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.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action and the safety caveat, and every paragraph carries information. Slight redundancy between 'Revoke a message for everyone' and 'This is WhatsApp's delete for everyone', plus a grammatically awkward sentence about the number appearing online, cost it a point.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive, open-world action with an output schema available, the description covers what the agent must know: irreversibility, recipient-visible effects, hidden state changes, and the human-confirmation norm. Nothing material is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and both parameters are documented in the schema, so the description needn't explain them. It adds no parameter-level meaning beyond the schema, which is the correct baseline for this coverage level.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (revoke/delete) and resource (a message) with explicit scope: 'for everyone in the conversation'. This distinguishes it from edit_text_message and edit_media_caption, which alter content rather than remove it.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives a clear usage condition: confirm with a human before deleting anything a person has plausibly already read. It does not explicitly name alternatives (e.g., edit_text_message when the goal is correction rather than removal), so routing 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.

disconnect_numberTake a number offline without unlinking itA
Idempotent
Inspect

Take a number offline deliberately, keeping its link to the phone.

The stored credentials survive, so connect_number brings it straight back with no pairing. Nothing is deleted. Disconnecting does not stop billing: an extra number is billed every cycle until it is removed.

Returns immediately, before the number is offline. The answer has the number's alias, status set to disconnecting and at, the moment the request was accepted. disconnecting is not a status that get_number reports: it keeps showing the previous status and its own at until the number is offline.

While disconnected the number cannot send or receive, and messages addressed to it are refused rather than queued. Deliberate: a message held for an unknown period and delivered later is worse than one that failed clearly.

Calling it again changes nothing further. A number that is already offline answers with an already_disconnected error, which means the goal is met, not that the call failed.

NameRequiredDescriptionDefault
number_aliasNoWhich of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to see them. Defaults to the main number.main

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Adds substantial context beyond the annotations: credentials survive so re-pairing is unnecessary, billing continues, the call returns before the number is actually offline, the `disconnecting` status is invisible to `get_number`, and messages are refused rather than queued. The stated idempotency and `already_disconnected` error are consistent with idempotentHint=true and destructiveHint=false, with no contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose, then consequences, then return semantics, then edge cases in a sensible order. Slightly long for a one-parameter tool, and the rationale sentence about refusing messages is a touch indulgent, but every clause conveys actionable behavior rather than filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with a single optional parameter and an output schema, the description covers the full picture an agent needs: reversibility, cost side effects, async completion, return shape, status visibility, message handling, and repeat-call behavior. Nothing material is left for the agent to guess.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and the parameter's schema entry already explains the alias/id forms and points to `list_numbers`. The description body never mentions `number_alias`, so it adds no meaning beyond the schema. Baseline 3 applies when the schema carries the parameter documentation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("take a number offline") plus the defining constraint that distinguishes it from removal: "keeping its link to the phone" and "Nothing is deleted." It explicitly names `connect_number` as the inverse, so an agent can separate 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.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear context for when this is the right call (deliberate temporary offline) and contrasts it with removal via the billing sentence ("billed every cycle until it is removed"), which implicitly routes to a delete/remove path. It also handles the repeat-call case. It stops short of naming a specific removal sibling tool, so the alternative is implied rather than explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

edit_calendar_eventEdit a calendar event already sentA
Destructive
Inspect

Correct a calendar event this number already sent.

name and start_at are always required, plus whatever else the event has: description, end_at, join_link, location, has_reminder with reminder_offset_sec, and extra_guests_allowed. This REPLACES the whole event: anything you leave out is removed from it, including its location, reminder and guest setting, so send again every detail you want to keep. The event keeps its place in the chat and the guests keep the answer they already gave.

Use an edit to fix a mistake (a typo, the description, a link). When the date, time or place change and the guests must accept again, do not edit: cancel the event with cancel_calendar_event and send a new one with send_calendar_event, because the old answer does not carry over to a new event. Neither an edit nor a cancel changes the entry a guest already added to their own calendar with the card's "Add to calendar" button. It stays on the old date, and adding again creates a second entry, which only the guest can delete.

Only a calendar event can be edited here. Using this tool on any other message answers invalid_request: message_not_editable.

Only a message sent THROUGH Turbo Notify can be edited. One typed on the phone itself belongs to the same number but cannot be edited here, and neither can a message received from someone else.

The 15-minute limit does not apply to a calendar event.

The edit is accepted at once and the outcome arrives as an event: message.edited when it worked, message.edit.failed when WhatsApp or the platform could not apply it. Read them with list_events.

The number first appears online and its unread messages in that conversation are marked as read, then the edit happens. Opening the conversation this way is automatic and uses no quota of its own.

NameRequiredDescriptionDefault
nameYesThe event's title, up to 200 characters.
end_atNoWhen the event ends. ISO 8601 with an offset, and later than `start_at`.
locationNoWhere the event takes place: a map pin with an optional name and address.
start_atYesWhen the event starts. ISO 8601 with an offset, for example `2026-09-10T14:00:00Z`. A time without an offset is rejected.
join_linkNoA link guests can open to join, for example a video call.
message_idYesMessage id (`msg_…`), as returned by a send or by `list_messages`.
descriptionNoDetails shown on the event, up to 2000 characters.
has_reminderNoSet to true to remind guests before the event. Off when left out.
number_aliasNoWhich of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to see them. Defaults to the main number.main
reminder_offset_secNoHow many seconds before the event the reminder goes off, for example 600 for ten minutes. Only takes effect together with `has_reminder`.
extra_guests_allowedNoSet to true to let guests bring extra people. Off when left out.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already flag destructiveHint=true and non-idempotency, but the description adds far more: the edit is a full replacement that silently drops omitted fields, guests keep their prior answers, the guest's own 'Add to calendar' entry is not updated, and the 15-minute edit limit does not apply. It also discloses the async outcome events (message.edited / message.edit.failed) and the exact error for ineligible messages.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action and the replacement rule, then decision guidance, then edge cases. Dense and mostly waste-free, though the closing paragraph about the number coming online and unread messages is tangential to the edit itself and slightly dilutes focus.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive, async, 11-parameter mutation with rich sibling overlap, the description covers eligibility, replacement semantics, guest-side side effects, error behavior and result delivery. The return shape is covered by the output schema, so 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.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, but the description contributes semantics the schema cannot express: name and start_at are always required, and because the operation REPLACES the whole event, every optional field omitted is removed — so callers must resend all desired details. That materially changes how the 11 parameters are used.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("Correct a calendar event this number already sent") and clearly delineates it from edit_text_message, edit_media_caption, send_calendar_event and cancel_calendar_event, the latter two named explicitly. An agent can route correctly from the first line alone.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit decision rule: use an edit for a typo, description or link fix; use cancel plus send when the date, time or place change so guests must re-accept. Also names the exclusion cases (non-calendar messages, messages typed on the phone, received messages) and the sibling tools to use instead.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

edit_media_captionEdit the caption of an image, video or documentA
Destructive
Inspect

Replace the caption of an image, video or document this number already sent.

The recipient sees the new caption marked as edited. The file itself stays exactly as it was and the message keeps its id: only the caption changes. There is no way to replace the file; to send a different one, send a new message with send_media.

Only an image, video or document can be edited this way. Audio and stickers have no caption, and a location, contact card or link button cannot be edited at all: delete_message is the only change for them. For the text of a text message use edit_text_message. Using this tool on any other message answers invalid_request: message_not_editable.

Only a message sent THROUGH Turbo Notify can be edited. One typed on the phone itself belongs to the same number but cannot be edited here, and neither can a message received from someone else.

WhatsApp only accepts a change to a caption within 15 minutes of sending it. A later edit is refused up front with invalid_request: edit_window_expired; send a new message instead.

The edit is accepted at once and the outcome arrives as an event: message.edited when it worked, message.edit.failed when WhatsApp or the platform could not apply it. Read them with list_events.

The number first appears online and its unread messages in that conversation are marked as read, then the edit happens. Opening the conversation this way is automatic and uses no quota of its own.

NameRequiredDescriptionDefault
captionYesThe new caption, up to 1024 characters. It replaces the whole caption. Writing `@<number>` mentions that person, as in a caption on send.
message_idYesMessage id (`msg_…`), as returned by a send or by `list_messages`.
number_aliasNoWhich of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to see them. Defaults to the main number.main

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations: the recipient sees the caption as 'edited', the file and message id are untouched, there is no way to swap the file, the call is asynchronous with results arriving as message.edited / message.edit.failed events readable via list_events, and the call has a side effect of bringing the number online and marking the conversation's unread messages as read. That last side effect is exactly the kind of non-obvious behavior destructiveHint alone cannot convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action and its alternatives, then layered constraints and finally delivery mechanics. The paragraphs each do work, though the closing note about the number going online and unread messages being marked read could be tightened against the quota remark.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with real failure modes, the description covers eligibility, error codes (message_not_editable, edit_window_expired), timing limits and how to observe the outcome. An output schema exists so return values need no explanation, and nothing an agent needs 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.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so message_id, caption and number_alias are already fully documented, including the @-mention syntax and the replacement semantics. The description adds no additional parameter-level meaning beyond what the schema carries, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a precise verb and resource — 'Replace the caption of an image, video or document' — scoped to a message this number already sent, and immediately distinguishes it from send_media, edit_text_message and delete_message by name.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-not conditions (audio, stickers, locations, contact cards, link buttons), names the correct alternative for each case (delete_message, edit_text_message, send_media), and lists the two hard preconditions: message must have been sent through Turbo Notify and the edit must fall inside WhatsApp's 15-minute window.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

edit_text_messageEdit the text of a message already sentA
Destructive
Inspect

Replace the text of a text message this number already sent.

The recipient sees the new text marked as edited. The message keeps its id and its place in the conversation; only the text changes.

Only a text message can be edited here. For the caption of an image, video or document use edit_media_caption, and for a calendar event edit_calendar_event or cancel_calendar_event. A location, contact card, link button, sticker or audio message cannot be edited at all: delete_message is the only change for them. Using this tool on any message that is not text answers invalid_request: message_not_editable.

Only a message sent THROUGH Turbo Notify can be edited. One typed on the phone itself belongs to the same number but cannot be edited here, and neither can a message received from someone else.

WhatsApp only accepts a change to a text within 15 minutes of sending it. A later edit is refused up front with invalid_request: edit_window_expired; send a new message instead.

The edit is accepted at once and the outcome arrives as an event: message.edited when it worked, message.edit.failed when WhatsApp or the platform could not apply it. Read them with list_events.

The number first appears online and its unread messages in that conversation are marked as read, then the edit happens. Opening the conversation this way is automatic and uses no quota of its own.

NameRequiredDescriptionDefault
textYesThe new text. It replaces the whole text of the message.
message_idYesMessage id (`msg_…`), as returned by a send or by `list_messages`.
number_aliasNoWhich of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to see them. Defaults to the main number.main

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only flag destructive/non-idempotent/open-world; the description goes far beyond by disclosing the 15-minute acceptance window, the exact error codes returned (message_not_editable, edit_window_expired), the asynchronous outcome via message.edited / message.edit.failed events, and the side effect of bringing the number online and marking unread messages as read at no quota cost. That is exactly the operational context an agent needs before calling a mutation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well structured into short paragraphs, front-loaded with the core action, and nearly every sentence carries a distinct constraint or behavior. It runs slightly long, and the closing paragraph on presence/read marking is tangential to the edit itself, though still operationally useful.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

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, yet the description still clarifies that the call returns acceptance rather than the outcome and routes the agent to list_events for results. Combined with the constraint coverage, nothing needed 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.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so message_id, text, and number_alias are already documented in the schema. The description restates that only the text changes and keeps the id, but adds no format, default, or alias-resolution guidance beyond what the schema provides. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Uses a specific verb and resource ('Replace the text of a text message this number already sent') and immediately delimits scope against named siblings (edit_media_caption, edit_calendar_event, delete_message). An agent can distinguish this from every adjacent tool without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use and when-not-to-use rules: only text messages, only messages sent through Turbo Notify, not phone-typed or received messages, and only within 15 minutes. It names the correct alternative for each unsupported case, including the fallback to send_text after the window expires.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_contactGet one contactA
Read-onlyIdempotent
Inspect

Fetch one contact: name, phone number and activity timestamps.

first_messaged_at is when a message from this number first reached them on WhatsApp, and last_interaction_at is the last message that passed in EITHER direction, so it moves when they write to you as well. A message that failed before reaching WhatsApp moves neither.

refresh shows the last refresh_contact you asked for: when it was requested, when it finished, and its outcome (updated, unchanged, number_not_connected or unavailable). While completed_at is null it is still running.

The id must belong to the inbox named by number_alias. An id from a different number returns not found even though the person exists.

NameRequiredDescriptionDefault
contact_idYesContact id (`ct_…`), from `list_contacts`.
number_aliasNoWhich of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to see them. Defaults to the main number.main

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/non-destructive, so the bar is lower, yet the description still adds real behavior: failed messages move neither timestamp, and a cross-inbox id yields not-found despite the person existing. It stops short of describing response shape or rate/permission characteristics, but the semantic edge cases disclosed are substantial.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose is front-loaded in the first clause and the paragraphs are thematically split (timestamps, refresh block, scoping). It runs long and the `refresh`/outcome enumeration overlaps with what an output schema likely already conveys, costing a little tightness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter read with a full schema and an output schema, this covers everything an agent needs: what is returned, how timestamps behave, what the refresh block means, and the inbox-scoping failure mode. Nothing material is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

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 meaning the schema does not: `number_alias` acts as an inbox scope that makes otherwise-valid ids resolve to not-found. That is genuine semantic value beyond the parameter's own text.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb and resource ('Fetch one contact') plus the returned fields, which cleanly separates it from list_contacts and the picture/quota siblings. An agent can tell immediately this is the single-record read.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Clear operational context is given: the id must belong to the inbox named by `number_alias`, and a cross-number id returns not found. It also implicitly routes to `refresh_contact` by explaining what the `refresh` block reports, but it never explicitly says when to prefer this over list_contacts or get_contact_profile_picture.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_contact_profile_pictureGet a contact's profile pictureA
Read-onlyIdempotent
Inspect

Get a contact's profile picture, or the reason there is none.

The answer carries kind: available with a temporary URL, or unavailable with a reason. no_storage means the organization has not configured object storage, which is a setup step rather than a fault with this contact. The person may also simply have no picture, or have hidden it in their privacy settings.

NameRequiredDescriptionDefault
contact_idYesContact id (`ct_…`), from `list_contacts`.
number_aliasNoWhich of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to see them. Defaults to the main number.main

Output Schema

NameRequiredDescription

No output parameters

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint, so the safety profile is covered. The description adds genuinely useful behavior beyond that: the URL is temporary, the response is discriminated by `kind`, and `no_storage` is an organization setup gap rather than a contact-level fault — that last point materially changes how an agent should report the result.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The core answer is front-loaded in the first sentence, and the following lines are a compact enumeration of result kinds. The prose is slightly padded by line-wrapping and the hedge 'may also simply have no picture', but nothing is wasteful.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With a full output schema present, the description does not need to spell out return fields, and annotations cover safety. It supplies the interpretive context (temporary URL, no_storage vs. privacy-hidden) that the structured fields alone would not convey; only explicit routing versus get_contact is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, with contact_id and number_alias both documented in the schema including the `ct_…`/`num_…` formats and the list_contacts/list_numbers sources. The description adds no parameter meaning on top of that, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource — 'Get a contact's profile picture' — plus the notable framing that a negative result is also a valid answer. The resource noun 'contact' naturally separates it from the sibling get_group_picture, 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.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied rather than stated: an agent learns that this tool returns either a picture or a reason, but not when to prefer it over get_contact (which likely also carries picture info) or what to do if the caller needs a fresh fetch. The `no_storage` explanation is interpretive guidance rather than a when-to-use rule.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_contact_quotaGet a number's contact quota for this billing cycleA
Read-onlyIdempotent
Inspect

Check how much of this number's contact allowance is left.

A contact counts once per billing cycle when this number messages them through Turbo Notify, new or returning. Messaging the same person again in a later cycle counts again.

Like the message quota, this is per number rather than per organization, and it resets at cycle_end.

NameRequiredDescriptionDefault
number_aliasNoWhich of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to see them. Defaults to the main number.main

Output Schema

NameRequiredDescription

No output parameters

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, and non-destructive, so the safety profile is covered. The description adds real domain context beyond that: what counts as a contact, that it counts once per billing cycle even for returning contacts, that it is per-number not per-organization, and that it resets at cycle_end. It does not cover error cases or behavior for unknown aliases, keeping it below 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the outcome the caller wants, followed by the counting rule and then scoping/reset facts. Every sentence carries information, though the 'new or returning / later cycle' explanation is a touch verbose for what it conveys.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be described, and annotations plus a fully documented single parameter reduce the description's burden. It supplies the quota semantics and reset behavior an agent needs to interpret results, leaving only minor gaps such as what happens if the number alias is invalid.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% for the single number_alias parameter, including accepted forms, the list_numbers pointer, and the 'main' default, so the baseline is 3. The description's phrase 'this number's' reinforces scoping but adds no syntax or selection guidance beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource with scope: 'Check how much of this number's contact allowance is left.' It also distinguishes itself from the adjacent quota concept by noting 'Like the message quota, this is per number rather than per organization,' so an agent can tell it apart from get_message_quota and get_usage.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The purpose implies when to call it (checking remaining allowance for a number), but there is no explicit 'use this when…' or exclusion of alternatives such as get_usage, get_message_quota, or get_number. The comparison to message quota clarifies scope, not routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_groupGet one groupA
Read-onlyIdempotent
Inspect

Fetch a group: its name, description, picture and settings.

Returns how many participants it has, not who they are. Membership is deliberately not readable: it arrives as it changes, on the group.participants_added / _removed / _promoted / _demoted events, which list_events can read.

NameRequiredDescriptionDefault
group_idYesGroup id (`grp_…`), from `list_groups`. It belongs to the number you listed it under: passing it under a different number answers not found, which means wrong inbox rather than deleted.
number_aliasNoWhich of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to see them. Defaults to the main number.main

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the safety profile (readOnly, idempotent, non-destructive), and the description adds a non-obvious behavioral limit the annotations cannot express: participants are counted but not listed, deliberately. It then names the mechanism that does expose membership, which prevents an agent from flailing at a dead end.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, front-loaded with what is returned, then the important negative constraint. Each sentence carries information, though the line-broken formatting is slightly airy for the amount of content.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

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 spelled out, and the description still summarizes the payload shape plus the one thing the schema can't convey (membership opacity). Nothing needed 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.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and both parameters are richly documented in the schema itself (including the wrong-inbox not-found trap and the number_alias semantics). The description adds no parameter-level meaning beyond that, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource ('Fetch a group') and enumerates what comes back: name, description, picture and settings. Combined with the required group_id, an agent can distinguish it from list_groups (many) and get_group_picture (one asset) without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly routes membership-change lookups to the `group.participants_*` events readable via `list_events`, which is genuine when-to-use-elsewhere guidance. What's missing is an explicit statement of when to prefer this over list_groups for a known group_id, though the required id makes that largely self-evident.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_group_pictureGet a group's pictureA
Read-onlyIdempotent
Inspect

Get a group's picture, or the reason there is none.

Same shape as a contact's picture. The answer carries kind: available with a temporary URL, or unavailable with a reason. no_storage means the organization has not configured object storage.

NameRequiredDescriptionDefault
group_idYesGroup id (`grp_…`), from `list_groups`. It belongs to the number you listed it under: passing it under a different number answers not found, which means wrong inbox rather than deleted.
number_aliasNoWhich of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to see them. Defaults to the main number.main

Output Schema

NameRequiredDescription

No output parameters

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint and destructiveHint=false, so safety is covered. The description adds genuinely useful semantics beyond that: the two-valued `kind` discriminator and the meaning of `no_storage` (org has not configured object storage), which tells the agent an empty result is a configuration state rather than a missing group. It does not mention URL expiry beyond "temporary".

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Short and front-loaded — the core action leads, followed by the return contract and the one non-obvious error code. The line breaks are awkward and the "same shape as a contact's picture" cross-reference assumes prior knowledge, but no sentence is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the description needn't enumerate return fields, and annotations plus a fully documented schema cover the rest. The only real gap is that it never says how long the temporary URL lasts or what to do on a not-found result, but nothing needed to call the tool correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and both parameters are documented in detail in the schema, including the grp_/num_ prefixes and the wrong-inbox failure mode. The description adds nothing about parameters, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("Get a group's picture") plus the fallback outcome ("or the reason there is none"), which distinguishes it from the sibling get_contact_profile_picture and from get_group. An agent knows exactly what this returns 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.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the resource scope — this is the group-picture reader, and the contact sibling is referenced only obliquely via "Same shape as a contact's picture". There is no explicit statement of when to prefer get_group or get_contact_profile_picture instead, and no stated prerequisites.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_messageGet one message in fullA
Read-onlyIdempotent
Inspect

Fetch one message with its full content, parties and mentions.

The answer includes the number's stable number_id (num_…) next to number_alias.

at is when the message actually happened on WhatsApp; status.at is when it reached its current delivery status and keeps moving as receipts arrive. They answer different questions and are not interchangeable.

Returns not found if the id belongs to a different number. Past the organization's content retention window (1 hour by default, up to 72 hours depending on the plan) the message is still returned, with content_expired true and its content empty.

NameRequiredDescriptionDefault
message_idYesMessage id (`msg_…`), as returned by a send or by `list_messages`.
number_aliasNoWhich of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to see them. Defaults to the main number.main

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well past the annotations (readOnly/idempotent/non-destructive) by disclosing real behavioral edges: a not-found result when the id belongs to another number, and a retention window (1h default, up to 72h) after which content is empty with content_expired true. It also disambiguates `at` from the moving `status.at`, which prevents a common misread.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action, then broken into short scannable paragraphs that each address a real ambiguity. The `at` vs `status.at` discussion borders on output-schema territory, but it is short and prevents a concrete mistake.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

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 need not be described, and the description still covers the operation's edge conditions: cross-number lookups fail, expired content returns empty with a flag, and timestamps have two distinct meanings. Nothing an agent needs before calling is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the schema already explains message_id format and that number_alias may be an alias or a stable `num_…` id. The description restates the stable `number_id`/`number_alias` pairing rather than adding new parameter meaning, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource with scope ('Fetch one message with its full content, parties and mentions'), which implicitly separates it from list_messages and from the narrower get_message_status/get_message_receipts/get_message_reactions siblings. It stops short of naming those alternatives explicitly, so an agent must infer the split.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied by the scope statement ('one message', 'full content'); there is no explicit when-to-use or when-not-to-use guidance and no sibling is named as an alternative. The failure/retention notes are useful context but are behavioral facts rather than routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_message_quotaGet a number's message quota for this billing cycleA
Read-onlyIdempotent
Inspect

Check how much of this number's message allowance is left.

The quota is per number, not per organization: an organization with three numbers has three separate allowances. It resets at cycle_end, which is the organization's real billing boundary rather than a rolling window, so resets_at is a date you can plan around.

Only messages sent through Turbo Notify consume it. Messages someone sends from the phone itself do not.

NameRequiredDescriptionDefault
number_aliasNoWhich of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to see them. Defaults to the main number.main

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint and destructiveHint=false, so the safety profile is covered. The description adds real behavioral context beyond that: the quota is per number rather than per organization, resets at a real billing boundary rather than a rolling window, and is consumed only by Turbo Notify traffic, not phone-originated messages.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core answer and structured as three short idea blocks (scope, reset semantics, consumption rules). Markdown bolding and backticked field names add slight visual noise but every sentence carries information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return values need no explanation, and the single parameter is fully documented. Remaining gaps are minor: it does not say what the agent should do when the quota is exhausted or whether the call can fail for an invalid alias.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

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 adds meaning beyond the schema by explaining why the single number_alias parameter matters: an organization with three numbers has three separate allowances, which motivates selecting the correct alias.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb and resource: 'Check how much of this number's message allowance is left.' The per-number scoping sentence distinguishes it from organization-wide usage tools, though it never names the closest siblings (get_usage, get_contact_quota) to make the routing explicit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear context for when the tool is appropriate (checking remaining allowance for a specific number) and clarifies the unit of measurement so the agent picks the right number. It stops short of stating exclusions or pointing to alternatives such as get_usage for aggregate consumption.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_message_reactionsGet the reactions on a messageA
Read-onlyIdempotent
Inspect

List the emoji reactions on a message, and who left each one.

Each entry names the reactor and the emoji. Reactions are replaced rather than accumulated per person: someone who reacts twice leaves one entry showing their latest emoji, so this is a current snapshot and not a history.

An empty list is the normal answer for most messages, and is not an error.

NameRequiredDescriptionDefault
message_idYesMessage id (`msg_…`), as returned by a send or by `list_messages`.
number_aliasNoWhich of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to see them. Defaults to the main number.main

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations, it discloses the two behaviors that actually change how an agent interprets results: reactions are replaced per person rather than accumulated, so the list is a current snapshot and not a history, and an empty list is a normal answer rather than an error. Those are exactly the non-obvious traits 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.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short paragraphs, each earning its place: purpose first, then the replacement-versus-history semantic, then the empty-result case. No redundancy with the title or schema, and the most decision-relevant fact is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is simple (one required param, output schema present), and the description covers the semantics an output schema cannot convey, such as snapshot behavior and empty-list handling. The only omission is routing guidance relative to react_to_message and get_message, which keeps it short of a 5.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% — message_id and number_alias are both fully documented in the schema, including the msg_/num_ formats and the list_numbers pointer. The description adds no additional meaning about either parameter, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'List the emoji reactions on a message, and who left each one.' That verb contrast (list) against the write-side sibling react_to_message makes the tool's role unambiguous without needing to open either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the purpose statement rather than stated: an agent can infer this is the read path for reactions, but the description never names read/write alternatives such as react_to_message (to add or remove a reaction) or get_message (for the message body itself). No explicit when-to-use or when-not-to-use guidance is given.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_message_receiptsGet per-recipient delivery and read receiptsA
Read-onlyIdempotent
Inspect

See who received and who read a message.

Most useful for group messages, where the single status on the message cannot express that some members read it and others have not.

Requires a plan that includes read receipts; on plans without it the call is refused with feature_not_available, which no retry will fix.

NameRequiredDescriptionDefault
message_idYesMessage id (`msg_…`), as returned by a send or by `list_messages`.
number_aliasNoWhich of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to see them. Defaults to the main number.main

Output Schema

NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, non-destructive, and open-world behavior, so the safety profile is covered. The description's genuine addition is the plan gate: a refusal with `feature_not_available` that no retry will fix, which prevents wasted retries. It adds nothing about rate limits, permissions, or result shape, so it is a solid but not rich supplement.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short paragraphs: what it returns, when it matters, and what blocks it. The most decision-relevant facts (per-recipient view, plan gate) are front-loaded with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return-value explanation is unnecessary, and parameters are fully covered by the schema. The description supplies the one non-obvious operational fact (plan-gated, non-retryable failure). Only the explicit sibling routing is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and both parameters (message_id, number_alias) are fully documented in the schema with format hints and a pointer to list_numbers. The description adds no parameter-level meaning, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence states a specific verb and resource: per-recipient receipt and read status for a message. The second paragraph implicitly separates it from get_message_status by explaining that the message-level single status cannot express partial reads in groups, though it never names that sibling directly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear usage context (group messages where per-member read state matters) and a hard prerequisite (a plan with read receipts). It stops short of an explicit 'use X instead when...' routing statement against get_message_status or get_message_responses.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_message_responsesGet the guests' answers to a calendar eventA
Read-onlyIdempotent
Inspect

See how the guests answered a calendar event: going, not going or maybe.

Only works on a calendar event; any other message answers invalid_request: message_not_calendar.

The answer has counts (how many guests are going, not going or maybe, and how many extra guests those who are going or maybe are bringing) and responses, one entry per guest with who they are, their answer, any extra guests they bring and when they answered. A guest who changes their mind leaves one entry showing the latest answer, so this is a current snapshot and not a history. To be told as answers come in, watch for message.calendar_responded with list_events.

An event nobody has answered yet returns zero counts and an empty list, which is the normal answer and not an error.

NameRequiredDescriptionDefault
message_idYesMessage id (`msg_…`), as returned by a send or by `list_messages`.
number_aliasNoWhich of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to see them. Defaults to the main number.main

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/non-destructive, and the description adds real behavioral context beyond them: the snapshot-not-history semantics for guests who change their mind, the specific error code for wrong message types, and the reassurance that zero counts with an empty list is a normal answer rather than a failure.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the purpose, then layers the error condition, the return shape, and the empty-result caveat in a logical order. Mild redundancy in describing `counts` and `responses` fields when an output schema exists, which costs some words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers everything an agent needs: applicability constraint, error identifier, return semantics including the snapshot caveat, and the empty-result non-error case. Any remaining field-level detail is handled by the output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and both parameters are documented in the schema with formats and defaults, so the description does not need to explain them. It adds no meaning about `message_id` or `number_alias` beyond what the schema already says; baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource (see how guests answered a calendar event) and enumerates the answer space. It is clearly distinguishable from neighboring read tools like get_message_reactions and get_message_receipts, since it is scoped to calendar events.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly restricts applicability: 'Only works on a calendar event' with the exact error returned otherwise, and points to `list_events` plus the `message.calendar_responded` event for live tracking. It stops short of naming which sibling to use for non-calendar messages, leaving that inference to the agent.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_message_statusGet a message's delivery statusA
Read-onlyIdempotent
Inspect

Check where a message got to: queued, sent, delivered, read, failed.

Status only moves forward. A failed status always carries an error code, and for a few media and reaction problems it also carries a hint naming the field to change; most failures give the code alone. Read the code before retrying, because most failures repeat identically.

NameRequiredDescriptionDefault
message_idYesMessage id (`msg_…`), as returned by a send or by `list_messages`.
number_aliasNoWhich of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to see them. Defaults to the main number.main

Output Schema

NameRequiredDescription

No output parameters

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already establish readOnly, idempotent, non-destructive, openWorld, so the safety profile is covered. The description adds genuine behavioral context beyond that: status only moves forward (monotonic, so polling is meaningful), failures always carry an error code, and only a subset of media/reaction failures include a corrective field hint.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Short and front-loaded: the first clause names the tool's job and the possible outcomes before any caveats. The third sentence about retrying is useful but slightly editorial; overall little waste.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

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 nonetheless characterizes the failure payload shape. For a two-parameter read-only lookup with high schema coverage, this is close to complete; only sibling routing guidance is absent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, with message_id format and number_alias semantics fully documented in the schema. The description adds no parameter-level 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.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource (check a message's delivery stage) and enumerates the exact status values returned: queued, sent, delivered, read, failed. What is missing is differentiation from look-alike siblings such as get_message, get_message_receipts, and get_message_responses, which an agent must choose between.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is real guidance on interpreting results ('read the code before retrying, because most failures repeat identically'), but nothing on when to call this versus get_message_receipts or get_message. The when-to-use is only implied by the word 'status'.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_numberGet one number and its connection statusA
Read-onlyIdempotent
Inspect

Check one number: its phone number, status, and when that status began.

id (num_…) is the number's permanent identifier. The alias can be renamed, the id cannot. Either one works as number_alias.

connected means it can send right now. connecting means a connection was just requested and is being set up; check again in a few seconds. reconnecting means the number lost its connection and Turbo Notify is bringing it back by itself: there is nothing to do but wait and check again. Until it is connected again, sends are refused with number_not_connected. disconnected means the link to the phone still exists but the number is offline, so connect_number brings it back. inactive is the same for a number that was linked and has not been brought online yet: connect_number brings it online too. pending means the number was never linked to a phone, and no_main_number (what a brand-new account gets for main, and list_numbers is empty) means there is no number at all yet: either way a person has to link it from the Numbers page of the dashboard, so tell them and do not retry the send meanwhile. revoked means the phone unlinked the device, or another connection took it over. failed means a pairing did not complete, and reason says why (for example pairing_timeout when the code or QR code was not used in time, paired_phone_mismatch when another WhatsApp used it). Either one has to be paired again by a person holding that phone: from the dashboard (main or extra number) or, for an extra number, through the API's pairing endpoint, by code or by QR code. No tool here pairs a number: it needs a person with the phone.

pairing means a person is pairing the number right now. The code or QR code they use is not part of this answer: it belongs to that person. Check again later; the status moves to connected, or to failed with a reason.

NameRequiredDescriptionDefault
number_aliasNoWhich of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to see them. Defaults to the main number.main

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare it as a safe, idempotent read; the description goes far beyond by mapping every status value to its operational meaning, disclosing the downstream failure mode (`number_not_connected` refusals), and stating that pairing requires a human with the phone. That is exactly the context an agent needs to interpret the result rather than just fetch it.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The status-by-status enumeration is organized but roughly 350 words for a one-parameter read tool, and much of it re-describes values that an output schema already carries. The leading sentence is well front-loaded, but the body is longer than the decision requires.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Nothing an agent needs to call and interpret this tool is missing: the identifier forms, the default of `main`, every status value, and the correct follow-up action for each. Given annotations and an output schema already cover safety and shape, this is fully sufficient.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the schema already explains `main` vs alias vs `num_…` id, including that the id survives renames. The description restates the same fact ("The alias can be renamed, the `id` cannot") without adding format, validation, or edge-case detail beyond it, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource plus the exact fields returned: "Check one number: its phone number, status, and when that status began." The single-resource scope is clearly distinct from the sibling `list_numbers`, which the description references.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives strong action-oriented guidance per state: wait for `reconnecting`, use `connect_number` for `disconnected`/`inactive`, and tell a person to link from the dashboard for `pending`/`no_main_number`/`revoked`/`failed`. It also rules out retrying sends and notes "No tool here pairs a number." It does not explicitly state when to pick this over `list_numbers` for a single lookup, which keeps it 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.

get_usageGet the organization's usage across all numbersA
Read-onlyIdempotent
Inspect

Get message and contact usage for the whole organization.

The top-level totals are the sum across every live number: an organization with two numbers on a 50,000-message plan reports a quota of 100,000, not 50,000. The numbers[] breakdown shows each number separately, which is what you need to find the one that is close to its own ceiling, so a healthy-looking total can hide a number at 99%.

For one number, get_message_quota and get_contact_quota are more direct.

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover safety (readOnly, idempotent, non-destructive), so the description's real contribution is the aggregation semantics: top-level totals are the sum across live numbers, and the `numbers[]` array carries the per-number detail. That is non-obvious behavior an agent would otherwise get wrong when interpreting results. It does not mention auth scope or staleness of the numbers, 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.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short paragraphs: what it returns, the aggregation caveat, then the alternative. The quota example and the 99% warning both earn their place by preventing misreading of the totals. Nothing is repeated from the title or annotations.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

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 there are no parameters to document. The remaining risk — misinterpreting org totals as per-number quota — is addressed head-on, which is exactly what a zero-argument aggregate tool needs.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so there is no schema surface for the description to compensate for. The description correctly spends no words on inputs and instead explains how the response is partitioned.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("Get message and contact usage") and pins the scope to the whole organization across every live number. The distinction from the per-number siblings is made concrete by the quota-doubling example, so an agent can identify this tool 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.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent: use this for the org-wide picture and the `numbers[]` breakdown, and use `get_message_quota` or `get_contact_quota` when only one number matters. It also gives the condition that makes this tool necessary — a healthy total can mask a number at 99%.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_contactsList an inbox's contactsA
Read-onlyIdempotent
Inspect

List the people this number has exchanged messages with.

Filter by phone or by name. They are separate filters, not one search box: name matches the contact's name, phone matches the number.

source restricts to how the contact first appeared: inbound (they messaged this number), outbound (this number messaged them), mention (named in a group message) or self (the number's own contact card).

contacted_in_cycle=true narrows the list to exactly the people counting against this number's contact quota this billing cycle: those messaged through Turbo Notify inside the cycle, whether newly or again. Use it to see what the quota gauge is actually counting.

NameRequiredDescriptionDefault
nameNoOnly contacts whose name matches.
limitNoHow many items to return, 1-200. Defaults to 50.
phoneNoOnly contacts whose phone number matches.
cursorNoOpaque cursor for the next page. Pass back the `cursor` from the previous response, with the same filters; omit it for the first page.
sourceNoOnly contacts that first appeared this way: `inbound` (they messaged this number), `outbound` (this number messaged them), `mention` (named in a group message) or `self` (the number's own contact card).
number_aliasNoWhich of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to see them. Defaults to the main number.main
contacted_in_cycleNoWhen true, return only the people who count against this number's contact quota in the current billing cycle: those messaged through Turbo Notify inside the cycle, new or returning. Use it to see exactly what the quota figure is counting.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, non-destructive and openWorld, so the safety profile is covered. The description adds real domain context beyond that: what 'first appeared' means per source value, and precisely which population counts against the billing-cycle quota. Pagination behavior is left to the schema rather than the prose.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded and readable, with the core purpose in the first sentence. However, the source paragraph duplicates the schema's enum descriptions nearly word-for-word, and the contacted_in_cycle explanation is given twice within the same description, which is avoidable repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

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 needn't be explained, and cursor semantics live in the schema. For a seven-parameter filtered list tool the description covers the non-obvious parts (quota population, source meanings). It is slightly short on how limit interacts with the quota view, but nothing critical is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

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 does contribute one genuinely additive clarification — that name and phone are independent filters rather than a single fuzzy search — but the source enumeration paragraph essentially restates the enum description already in the schema, and limit/cursor/number_alias get no prose treatment.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening line states a specific verb and resource ('List the people this number has exchanged messages with'), which cleanly separates it from the singular sibling get_contact. It does not name any sibling outright, so the differentiation is implied by list-vs-get rather than stated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives concrete guidance on how the filters compose (name and phone are separate, not a combined search box) and explains the exact scenario for contacted_in_cycle=true ('use it to see what the quota gauge is actually counting'). It stops short of naming get_contact as the alternative for looking up one person, and never states when not to use this list tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_eventsPoll the organization's event logA
Read-onlyIdempotent
Inspect

Poll everything that happened: messages, contacts, groups, numbers, quotas.

This is how an agent learns about inbound messages without hosting a webhook endpoint.

Events come back newest first, so polling for new ones uses ending_before, not starting_after. Typical loop: call with no cursor and remember the id of the FIRST event in the page (the newest one); next time, pass that id as ending_before to get only what has happened since. An empty page means you are caught up.

starting_after does the opposite: it walks BACKWARD into history, which is what you want for reading a backlog, and never what you want for noticing something new. Passing the last id you handled to starting_after in a loop returns steadily older events and never reaches the present.

request_id returns everything that came of one earlier call. A write tool's result carries request_id when the platform issued one; keep it and you can ask later what became of that specific send.

number_id restricts to one number and keeps matching its events after the number is renamed. number_alias restricts to one inbox by the alias it had when the event happened, so a rename hides the older events; the two can be combined. Either one excludes storage.* and media.unavailable events, which belong to the organization rather than to any one number.

Most events carry a number_alias telling you which inbox they belong to, and number_id (num_…), the same number's permanent identifier. The alias is the one at the time of the event and can be renamed later; the number_id cannot. You need one of them: message, contact and group ids are unique but not self-addressing, so an id alone does not tell you which number's tools to use with it, and both work as number_alias in the other tools. Read the fields defensively rather than assuming they are there: storage.* and media.unavailable belong to the organization as a whole and have no single number to name, so on those the keys are absent rather than empty.

NameRequiredDescriptionDefault
limitNoHow many events to return, 1-100. Defaults to 25.
number_idNoRestrict results to one number by its `id` (`num_…`, as returned by `list_numbers`). It keeps matching the number's events after the number is renamed, unlike `number_alias`, which matches the alias the number had when the event happened. Can be combined with `number_alias`. Absent means every number. Setting it excludes `storage.*` and `media.unavailable` events, which belong to the organization rather than to any one number.
event_typeNoFilter to exactly one event type, e.g. `message.received`. Common ones: `message.sent`, `message.delivered`, `message.read`, `message.received`, `message.reacted`, `message.edited` (a text or caption edit, or a calendar event that was edited or canceled), `message.calendar_responded` (a guest answered a calendar event), `message.quota.warning`, `number.connected`, `number.disconnected`, `contact.created`, `contact.quota.warning`, `group.joined`, `group.participants_added`. Use `event_types` instead to filter on more than one at once.
request_idNoReturn only the events that came of one earlier call (`req_…`). A write tool's result carries `request_id` when the platform issued one; keep it and you can ask later what became of that send.
created_gteNoOnly events created at or after this instant. ISO 8601 with an offset, e.g. `2026-09-01T00:00:00Z`.
created_lteNoOnly events created at or before this instant. ISO 8601 with an offset, e.g. `2026-09-10T00:00:00Z`.
event_typesNoFilter to several event types at once, e.g. `message.sent` and `message.delivered`. Same vocabulary as `event_type`. The API accepts at most 20.
number_aliasNoRestrict results to one inbox by the alias it had when the event happened, so events from before a rename are missed. Use `number_id` to follow a number across renames. **Absent means every number**, which is the usual choice. Note this is a filter, not a subject: unlike the messaging tools it does not default to `main`. Setting it also excludes `storage.*` and `media.unavailable` events, which belong to the organization rather than to any one number.
ending_beforeNoCatch up: return events NEWER than this id. Pass the newest id you have already handled to see only what has happened since. This is the one to poll with.
starting_afterNoRead further back: return events OLDER than this id. This is the one for walking a backlog, and the wrong one for noticing something new.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations cover the safety profile (readOnly, idempotent, openWorld), so the description goes further: it discloses result ordering (newest first), that an empty page means caught up, that number_alias is a point-in-time filter that hides pre-rename events, that either number filter excludes storage.* and media.unavailable, and that those keys are absent rather than empty. These are non-obvious traits an agent would otherwise learn only by trial.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well front-loaded with the core purpose and the critical ordering rule before edge cases, and bold emphasis marks the trap. It is long for a list tool, and a few passages are redundant—the starting_after misconception is stated twice, and the number_alias rename caveat largely duplicates the schema's own parameter text.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Ten optional parameters with an output schema present; the description need not explain return values and doesn't. It covers every decision an agent must make—which cursor, which number filter, when to use request_id, how to read missing keys defensively—so nothing material is left unresolved.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

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 supplies the operational semantics the schema cannot—how ending_before and starting_after compose into a working polling loop versus a history walk. It does restate some number_id/number_alias behavior already present in the schema, limiting added value, but the cursor workflow is genuinely new.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb and resource—'Poll everything that happened'—and immediately enumerates the resource families covered (messages, contacts, groups, numbers, quotas). No sibling tool in the list has overlapping scope, so an agent can identify this as the sole event-log reader 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.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit when-to-use case ('how an agent learns about inbound messages without hosting a webhook endpoint') and a concrete loop recipe. It also draws a hard exclusion between the two cursors: ending_before for new events, starting_after for backlog, with the failure mode of misusing the latter spelled out. Alternatives like request_id and the two number filters are each given a selecting condition.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_groupsList the groups a number belongs toA
Read-onlyIdempotent
Inspect

List the WhatsApp groups this number is a member of.

The list is built when the number connects: every group it belongs to is picked up then, whether or not anything has been said in it. A group joined since then is picked up from the join itself, without waiting for anyone to speak in it.

name filters by group name. include_left=true also returns groups this number has left, which are otherwise hidden.

NameRequiredDescriptionDefault
nameNoOnly groups whose name matches.
limitNoHow many items to return, 1-200. Defaults to 50.
cursorNoOpaque cursor for the next page. Pass back the `cursor` from the previous response, with the same filters; omit it for the first page.
include_leftNoInclude groups this number has left. Off by default, so a plain listing shows only groups the number is currently in.
number_aliasNoWhich of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to see them. Defaults to the main number.main

Output Schema

NameRequiredDescription

No output parameters

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint, so the safety profile is covered. The description adds genuinely non-obvious behavior beyond that: the group list is materialized at connection time, groups joined since are captured from the join event without requiring messages, and left groups are otherwise hidden. It does not discuss pagination cost or ordering, 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.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the purpose, then the freshness semantics, then parameter notes; every paragraph is short and scannable. The middle paragraph on join-time capture is slightly verbose for what it conveys but still earns its place as non-obvious behavior.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a paginated read tool with a full output schema, the description covers the important caller-relevant behavior (freshness of the list, default exclusion of left groups) and all five optional parameters are documented via the schema. It omits nothing critical, though it could note that pagination cursors must pair with the same filters (the schema covers this).

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description's notes on `name` and `include_left=true` largely restate what the schema already says ('Off by default, so a plain listing shows only groups the number is currently in'), and it says nothing about `limit`, `cursor`, or `number_alias`, which the schema documents instead.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb and resource, 'List the WhatsApp groups this number is a member of', and scopes it to a particular number. An agent can immediately distinguish it from get_group (singular fetch) and from list_numbers without reading either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains the meaning of two parameters (name, include_left) but gives no explicit when-to-use guidance or named alternative such as get_group for a single group. Usage is implied rather than stated: the agent infers this is the enumeration tool, but nothing says when to prefer it over other listing tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_messagesList messages in an inboxA
Read-onlyIdempotent
Inspect

List messages for one number, newest first, received and sent.

Each item says who it is from and to, which number it belongs to, its direction, content_type, origin, a short preview, at, status and content_expired. Mentions, transcription and full media detail are only on get_message, so fetch the one message you care about rather than paging for detail.

To read a group, find its grp_ id with list_groups and pass it as group_id. contact_id returns what that contact sent or received, which in a group includes what they said there. direction keeps only inbound or outbound. Filters combine: group_id with contact_id answers what one person said in one group.

Ids belong to one number, so use the same number_alias you got them from: an id from another number answers not found. For the next page, pass back the cursor from the previous response together with the same filters.

Content older than the plan's retention window comes back with preview empty and content_expired true. The message, its sender and its group stay listed for 12 months.

NameRequiredDescriptionDefault
limitNoHow many items to return, 1-200. Defaults to 50.
cursorNoOpaque cursor for the next page. Pass back the `cursor` from the previous response, with the same filters; omit it for the first page.
group_idNoOnly the messages of one group (`grp_…`, from `list_groups`). The group must be one of this number's: an id from another number answers not found. Can be combined with `contact_id`.
directionNoOnly messages the number received (`inbound`) or sent (`outbound`). Absent means both.
contact_idNoOnly the messages this contact sent or received (`ct_…`, from `list_contacts`). In a group that includes what the contact said there. The contact must be one of this number's: an id from another number answers not found. With `group_id` too, you get what that contact said in that group.
number_aliasNoWhich of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to see them. Defaults to the main number.main

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/non-destructive, so safety is covered; the description adds genuinely new behavior: newest-first ordering, id scoping per number ('an id from another number answers not found'), pagination contract, and retention semantics where old content returns an empty preview with content_expired true while the message, sender and group remain listed 12 months.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four short paragraphs, front-loaded with purpose before filters, paging and retention, with no wasted filler. Slight redundancy with the already-descriptive schema parameter docs (cursor, number_alias) keeps it from a 5.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a six-parameter, zero-required listing tool with an output schema, everything needed for correct invocation is present: filtering model, pagination protocol, cross-number constraint, and the retention edge case that explains apparently empty previews. Return-value detail is delegated to the output schema, as expected.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

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 earns one extra point by framing the semantics of filter combinations conceptually ('group_id with contact_id answers what one person said in one group') and by stressing that the same number_alias must be reused for ids and cursors. Much of the rest (group_id, contact_id, direction, cursor) restates the schema descriptions, so it does not exceed that.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb and resource plus scope and ordering: 'List messages for one number, newest first, received and sent.' It then explicitly contrasts itself with get_message ('Mentions, transcription and full media detail are only on get_message'), so an agent can separate this list tool from the single-message sibling 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.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives concrete routing rules and conditions: use this for enumeration, call get_message for the one message whose detail you need, resolve a group's grp_ id via list_groups, use contact_id for what a contact sent or received, direction to restrict to inbound/outbound, and note that filters combine. It also states the cross-number failure mode and the cursor-plus-same-filters requirement for paging.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_numbersList the organization's WhatsApp numbersA
Read-onlyIdempotent
Inspect

List every WhatsApp number this organization has, with its status.

Start here when you do not know which aliases exist. The main number is always main; extras carry the alias the customer chose, and that alias is what every other tool's number_alias expects.

Each number also carries id (num_…), which never changes, even when the alias is renamed. Keep it if you need to recognise a number later: events carry the same value as number_id, and the other tools accept either one as number_alias. To find the numbers that need attention, pass status, for example disconnected.

Only connected numbers can send. status.at is when the number entered its current state, which is how you tell a fresh disconnection from one that has been down for hours.

NameRequiredDescriptionDefault
statusNoOnly numbers currently in this status, for example `disconnected` to find the numbers that need attention.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover read-only/idempotent/non-destructive, and the description adds value on top: main number is always `main`, ids are `num_…` and stable across renames, events carry the same value as `number_id`, and either form is accepted as `number_alias`. It also states the operational constraint that only `connected` numbers can send and explains `status.at` for judging stale disconnections.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short paragraphs, front-loaded with the core action and the entry-point rule before the finer details about ids and aliases. A little redundancy with the schema's `status` example, but nearly every sentence carries a distinct fact.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-optional-filter read tool with an output schema present, this is complete: it covers purpose, entry-point usage, alias-vs-id semantics, cross-tool interoperability, and the `connected`-required constraint. Nothing an agent needs to call it or interpret its output is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the `status` filter is already documented, and the description's « pass `status`, for example `disconnected` » largely repeats it. However it goes beyond by tying status to a goal (find numbers needing attention) and by explaining the semantics of `status.at` in the returned data.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

« List every WhatsApp number this organization has, with its status » gives a specific verb (list) plus resource (org's numbers) and immediately distinguishes itself from get_number, the sibling that fetches one. The agent can tell it apart from every other sibling without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

« Start here when you do not know which aliases exist » is an explicit routing rule, and the follow-on « the other tools' number_alias expects » tells the agent how output feeds other calls. The alternative path (get_number when you already know the alias) is implied by that framing and the pointer to filtering by status is concrete.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

mark_as_readClear a conversation's unread backlogAInspect

Mark a conversation's unread messages as read, without sending anything.

Set exactly one recipient: number, group_id, or contact_id.

This is independent of the automatic mark-as-read that already happens when you send, reply, react, edit, delete or start typing (the number also appears online first): use it to clear an unread badge on its own, for example when handing a conversation to a human who has already seen it. No message is sent and no message.* event is produced, but the sender sees the messages as read (blue ticks) on WhatsApp.

Needs a plan that includes read receipts (BUSINESS and above). Without it this answers payment_required: feature_not_available, and the answer will not change by retrying.

NameRequiredDescriptionDefault
numberNoRecipient phone number in E.164 form, digits only, country code first (e.g. `5511999999999`). Set exactly one of `number`, `group_id` or `contact_id`.
group_idNoRecipient group id (`grp_…`), from `list_groups`. A group id belongs to one number: an id from one inbox does not address the same group in another. Set exactly one of `number`, `group_id` or `contact_id`. Addressing a group needs a plan that includes group messaging: without it the call answers `payment_required: feature_not_available`, and retrying will not change that.
contact_idNoRecipient contact id (`ct_…`), from `list_contacts`. A contact id belongs to one number: an id from one inbox does not address the same person in another. Set exactly one of `number`, `group_id` or `contact_id`.
number_aliasNoWhich of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to see them. Defaults to the main number.main

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well past the annotations: it explains that read receipts are a real, externally visible side effect ('sender sees the messages as read (blue ticks)'), which justifies readOnlyHint=false, while also stating no message is sent and no message.* event fires. It adds plan gating and the exact failure mode ('payment_required: feature_not_available') with the warning that retrying is futile.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action and the recipient constraint, and every paragraph carries information. Minor deductions for a parenthetical aside ('the number also appears online first') that is hard to parse and for line breaks splitting sentences mid-clause.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a four-parameter mutation with an output schema and annotations already present, the description supplies the remaining essentials: side effects visible to third parties, plan prerequisite, error code, and non-retryability. An agent has everything needed to decide and call correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and each parameter already documents its format, the exactly-one-of rule, and the cross-inbox caveat for ids. The description's 'Set exactly one recipient: number, group_id, or contact_id' restates the schema rather than adding 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.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Mark a conversation's unread messages as read') plus the key negative scope ('without sending anything'). An agent can immediately separate this from send_text, reply_to_message, or react_to_message, none of which exist to clear unread state.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says this is independent of the automatic mark-as-read triggered by send/reply/react/edit/delete/typing, and gives the one condition that selects it: clearing a badge on its own, e.g. handing a conversation to a human who has already seen it. That is a real when-to-use and implicit when-not-to-use rule.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

react_to_messageReact to a message with an emojiAInspect

Attach an emoji reaction to a message, or remove one.

Pass a single emoji character, e.g. 👍. Passing an empty string removes the reaction this number previously left. A new emoji replaces this number's previous reaction rather than adding beside it; to bring the earlier one back, react with it again.

Works on messages in either direction: reacting to something a customer sent is often a cheaper acknowledgement than a reply.

The number first appears online and its unread messages in that conversation are marked as read, then the reaction is sent. Opening the conversation this way is automatic and uses no quota of its own.

Needs a plan that includes reactions. On a plan that does not, this answers payment_required: feature_not_available, and the answer will not change by retrying.

NameRequiredDescriptionDefault
emojiYesA single emoji, for example `👍`. An empty string removes the reaction this number left before.
message_idYesMessage id (`msg_…`), as returned by a send or by `list_messages`.
number_aliasNoWhich of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to see them. Defaults to the main number.main

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations by disclosing a hidden side effect (the number appears online and unread messages in the conversation are marked as read), the quota cost of that side effect, and a plan gating condition with the exact error code `payment_required: feature_not_available` plus the instruction not to retry. These are exactly the traits an agent cannot infer from readOnlyHint/destructiveHint/idempotentHint, and none of it contradicts them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose is front-loaded in the first sentence and the paragraphs are short and purposeful, covering removal, replacement, side effects, and billing. The replacement semantics are restated in two places, which costs a little tightness but not comprehension.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a three-parameter mutation tool with an output schema, the description covers everything an agent needs: required inputs, removal path, replacement behavior, hidden read-marking side effect, quota implications, and a non-retryable billing failure. Nothing material is left to inference.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

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 meaning the schema does not: that a new emoji replaces this number's previous reaction rather than stacking, and how to restore the earlier one. The single-emoji-character guidance partially duplicates the schema's own emoji description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence names a specific verb and resource ('Attach an emoji reaction to a message, or remove one') and covers both directions of the operation. This clearly separates it from siblings like get_message_reactions (read) and reply_to_message (send), so an agent can pick it without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives a concrete usage cue: 'reacting to something a customer sent is often a cheaper acknowledgement than a reply,' which implicitly routes the agent away from reply_to_message. It also explains the empty-string removal path and the replace-not-add semantics, but it never explicitly names an alternative tool or states 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.

refresh_contactRefresh a contact's WhatsApp nameAInspect

Ask WhatsApp for this contact's current name.

Only the name is refreshed. The profile picture updates on its own the next time this number exchanges a message with the contact, and this does not change how messages reach them.

It answers right away with requested_at; the refresh then runs in the background. Call get_contact and read refresh: when completed_at is set, outcome says what happened (updated means the name changed, unchanged means it was already current, number_not_connected means the number was offline, unavailable means WhatsApp did not answer).

This is the one contact tool that is not read-only: it queries WhatsApp over the live connection and spends the organization's per-minute refresh budget, so it needs a key with contacts write access. Do not call it in a loop over a list. Refresh the one contact whose name looks stale.

NameRequiredDescriptionDefault
contact_idYesContact id (`ct_…`), from `list_contacts`.
number_aliasNoWhich of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to see them. Defaults to the main number.main

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations, the description discloses that the call is asynchronous, returns requested_at immediately, runs in the background, and spends the organization's per-minute refresh budget. It also explains the outcome values and the required write access. These are exactly the behavioral details an agent needs for a non-read-only, open-world operation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core action and then layers in scoping, async behavior, polling instructions, outcomes, and limitations. Every sentence carries operational value, and there is no redundant restatement of the schema or annotations.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is a non-idempotent, open-world async mutation with rich annotations and an output schema. The description completes the picture by explaining background execution, polling via get_contact, outcome interpretation, and budget/access constraints, leaving no critical gap for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already documents both parameters with 100% description coverage, including contact_id format and number_alias lookup guidance. The description does not add parameter-specific meaning beyond the schema, so the baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Ask WhatsApp for this contact's current name.' It immediately scopes the operation by clarifying that only the name is refreshed, not the profile picture, and that message delivery is unaffected. This distinguishes it from sibling read tools like get_contact and from broader profile operations.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly says not to call it in a loop and to refresh 'the one contact whose name looks stale.' It also explains how to observe completion via get_contact and the refresh field. This gives clear when-to-use and when-not-to-use guidance, and the write-access requirement further frames appropriate use.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

reply_to_messageReply to a message in the same conversationAInspect

Reply to an EARLIER message, quoting it, without naming a recipient.

Use it to bring context into the conversation: when the conversation has moved on and your answer depends on something said a while ago (by the contact, by you or, in a group, by any participant). To answer the message you just received, do not use this tool: send a normal message with send_text and let the chat carry the context, as a person would.

The recipient is worked out from the original: an inbound message is answered to its sender, an outbound one to whoever received it, and a group message to the group.

The message must belong to the inbox named by number_alias; a message_id from a different number returns not found.

Like a person opening the chat, the number first appears online and its unread messages in that conversation are marked as read, then the reply is sent. Opening the conversation this way is automatic and uses no quota of its own.

NameRequiredDescriptionDefault
textYesThe text of your reply, 1 to 4096 characters.
message_idYesMessage id (`msg_…`), as returned by a send or by `list_messages`.
number_aliasNoWhich of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to see them. Defaults to the main number.main
idempotency_keyNoAny printable ASCII text you choose, 1 to 255 characters, for example the id of the event you are answering. Reusing it for the same number suppresses a duplicate if you retry. Without it, retrying after a timeout may deliver the message twice, and the recipient sees both.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false, destructiveHint=false, openWorldHint=true and idempotentHint=false, so the write/safety profile is covered. The description adds genuinely non-obvious behavior: the number goes online, unread messages in that conversation are marked as read, and that step consumes no quota. However, the side effect of marking messages as read is mentioned without noting it is irreversible/visible to other participants, and the interaction with idempotency_key is left entirely to the schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core distinction from send_text, then recipient resolution, then failure mode, then side effects — a logical order. Some sentences are wordier than necessary (the 'like a person opening the chat' framing and the trailing quota remark could be tighter), but nothing is redundant or bloated.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 4-parameter write tool with full schema coverage, annotations, and an output schema (so return values need no explanation), the description covers everything an agent needs: when to use it, how the recipient is resolved, the cross-number validation rule, and the read-marking side effect.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

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 earns an extra point by explaining semantics the schema does not: the recipient is derived from the original message (inbound → sender, outbound → receiver, group → group), and message_id must belong to the inbox named by number_alias or it returns not found.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (reply), a specific resource (an EARLIER message), and the defining constraint (quoting it, no recipient named). It also explicitly distinguishes itself from send_text, so an agent can choose between them 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.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives a positive condition ('conversation has moved on and your answer depends on something said a while ago') and an explicit negative one ('to answer the message you just received, do not use this tool: send a normal message with send_text'), naming the alternative.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

send_calendar_eventSend a calendar eventAInspect

Send a calendar event invitation.

Set exactly one recipient: number, group_id, or contact_id.

start_at and end_at are ISO 8601 with an offset, for example 2026-09-10T14:00:00Z. A timestamp without one is rejected: the recipient's phone renders the event in their own timezone, so an ambiguous instant would show the wrong hour on their screen.

When set, end_at must be after start_at; an event that ends before (or exactly when) it starts is rejected.

location pins where it happens (latitude and longitude, with an optional name and address). has_reminder reminds guests, and reminder_offset_sec says how many seconds before the event; extra_guests_allowed lets guests bring extra people.

To fix a mistake later (a typo, the description, a link), use edit_calendar_event: guests keep their answer. When the date, time or place change and guests must accept again, cancel the event with cancel_calendar_event and send a new one with this tool. The entry a guest added to their own calendar with the card's "Add to calendar" button never follows an edit or a cancel: it stays on the old date and adding again creates a second entry, so tell guests to delete the old one. To see who said they are coming, use get_message_responses.

NameRequiredDescriptionDefault
nameYesThe event's title, up to 200 characters.
end_atNoWhen the event ends. ISO 8601 with an offset, and later than `start_at`.
numberNoRecipient phone number in E.164 form, digits only, country code first (e.g. `5511999999999`). Set exactly one of `number`, `group_id` or `contact_id`.
group_idNoRecipient group id (`grp_…`), from `list_groups`. A group id belongs to one number: an id from one inbox does not address the same group in another. Set exactly one of `number`, `group_id` or `contact_id`. Addressing a group needs a plan that includes group messaging: without it the call answers `payment_required: feature_not_available`, and retrying will not change that.
locationNoWhere the event takes place: a map pin with an optional name and address.
start_atYesWhen the event starts. ISO 8601 with an offset, for example `2026-09-10T14:00:00Z`. A time without an offset is rejected.
join_linkNoA link guests can open to join, for example a video call.
contact_idNoRecipient contact id (`ct_…`), from `list_contacts`. A contact id belongs to one number: an id from one inbox does not address the same person in another. Set exactly one of `number`, `group_id` or `contact_id`.
descriptionNoDetails shown on the event, up to 2000 characters.
has_reminderNoSet to true to remind guests before the event. Off when left out.
number_aliasNoWhich of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to see them. Defaults to the main number.main
idempotency_keyNoAny printable ASCII text you choose, 1 to 255 characters, for example the id of the event you are answering. Reusing it for the same number suppresses a duplicate if you retry. Without it, retrying after a timeout may deliver the message twice, and the recipient sees both.
quoted_message_idNoQuote an earlier message (`msg_…`) so it appears above yours. Do this only when your text depends on something said a while ago, yours or theirs; do not quote the message you are answering right now, send a normal message instead.
reminder_offset_secNoHow many seconds before the event the reminder goes off, for example 600 for ten minutes. Only takes effect together with `has_reminder`.
extra_guests_allowedNoSet to true to let guests bring extra people. Off when left out.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations (readOnlyHint=false, openWorldHint=true, destructiveHint=false, idempotentHint=false) it discloses real validation behavior: exactly one recipient, offsetless timestamps rejected, end_at must be strictly after start_at. It also warns of a non-obvious side effect the annotations cannot express — a guest's own 'Add to calendar' entry never follows an edit or cancel and re-adding duplicates it. Missing only delivery/response behavior, which the output schema covers.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose, then recipient, then timing, then location/reminder, then sibling routing — a sensible order with short paragraphs and backticked field names. Some content duplicates the schema's own parameter descriptions, so it is slightly longer than strictly necessary.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 15-parameter mutation tool with an output schema, the description covers the risky decisions an agent must make: recipient exclusivity, timestamp offset, ordering, and the edit-versus-cancel fork. Return values are handled by the output schema, so nothing essential is left out.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so a 3 is the floor; the description still adds the why behind the offset requirement (the recipient's phone renders in its own timezone, so an ambiguous instant shows the wrong hour). It restates a few rules already present in the schema (reminder_offset_sec, location pin), which caps it below 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening line names a specific verb and resource ('Send a calendar event invitation') and the description immediately positions it against cancel_calendar_event and edit_calendar_event. An agent can tell this apart from the other event tools without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit routing rules: use edit_calendar_event for typos/description/link fixes, but cancel and re-send when date, time or place change so guests must re-accept. It also points to get_message_responses for RSVPs, so each alternative tool is tied to a concrete condition.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

send_contact_cardSend a contact cardAInspect

Send a contact card the recipient can save to their phone.

Set exactly one recipient: number, group_id, or contact_id.

phones takes plain E.164 numbers, 1 to 10 of them. emails, organization, title and address are optional extra fields on the card; emails allows up to 10 as well.

A contact card cannot be edited after it is sent: delete_message is the only change for it.

NameRequiredDescriptionDefault
titleNoThe job title shown on the card, up to 100 characters.
emailsNoThe email addresses on the card, up to 10.
numberNoRecipient phone number in E.164 form, digits only, country code first (e.g. `5511999999999`). Set exactly one of `number`, `group_id` or `contact_id`.
phonesYesThe phone numbers on the card, 1 to 10, each in E.164 form with the country code first (e.g. `5511999999999`).
addressNoThe postal address on the card, up to 500 characters.
group_idNoRecipient group id (`grp_…`), from `list_groups`. A group id belongs to one number: an id from one inbox does not address the same group in another. Set exactly one of `number`, `group_id` or `contact_id`. Addressing a group needs a plan that includes group messaging: without it the call answers `payment_required: feature_not_available`, and retrying will not change that.
contact_idNoRecipient contact id (`ct_…`), from `list_contacts`. A contact id belongs to one number: an id from one inbox does not address the same person in another. Set exactly one of `number`, `group_id` or `contact_id`.
display_nameYesThe name shown on the card, 1 to 200 characters.
number_aliasNoWhich of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to see them. Defaults to the main number.main
organizationNoThe company shown on the card, up to 200 characters.
idempotency_keyNoAny printable ASCII text you choose, 1 to 255 characters, for example the id of the event you are answering. Reusing it for the same number suppresses a duplicate if you retry. Without it, retrying after a timeout may deliver the message twice, and the recipient sees both.
quoted_message_idNoQuote an earlier message (`msg_…`) so it appears above yours. Do this only when your text depends on something said a while ago, yours or theirs; do not quote the message you are answering right now, send a normal message instead.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations cover the safety profile (destructiveHint=false, openWorldHint=true, idempotentHint=false), so the bar is lower. The description adds real behavior beyond them: the card is immutable after sending and delete_message is the only way to remove it, which materially affects an agent's decision to send.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four short, front-loaded sentences: purpose, recipient rule, card field constraints, immutability. No filler and every sentence carries actionable information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

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 description covers purpose, recipient exclusivity and post-send immutability. It omits delivery guarantees or plan/permission caveats, though those live in the group_id schema description.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so every parameter is already documented in detail (E.164 format, limits, idempotency and quoting semantics). The description restates the phones range and optional card fields but adds no syntax or constraint the schema doesn't already carry; baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Send a contact card') plus the outcome ('the recipient can save to their phone'), which separates it cleanly from send_text, send_media, send_location and send_cta_button in the sibling list.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives the key selection rule for the recipient parameters ('Set exactly one recipient: number, group_id, or contact_id') and notes deletion as the only follow-up action. It stops short of naming an alternative tool or an explicit when-not-to-use condition, but the context is unambiguous.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

send_cta_buttonSend a message with a call-to-action link buttonAInspect

Send an interactive message carrying one link button.

Set exactly one recipient: number, group_id, or contact_id.

A link button is the only interactive type WhatsApp accepts on this kind of connection. Reply buttons and list pickers are not available and will not become available, so do not try to emulate them.

body is the text above the button (up to 1024 characters), button_text its label (up to 20), header and footer optional short lines above and below (up to 60 each).

A message with a link button cannot be edited after it is sent: delete_message is the only change for it.

NameRequiredDescriptionDefault
bodyYesThe text above the button, 1 to 1024 characters.
footerNoA short line below the text, up to 60 characters.
headerNoA short line above the text, 1 to 60 characters.
numberNoRecipient phone number in E.164 form, digits only, country code first (e.g. `5511999999999`). Set exactly one of `number`, `group_id` or `contact_id`.
group_idNoRecipient group id (`grp_…`), from `list_groups`. A group id belongs to one number: an id from one inbox does not address the same group in another. Set exactly one of `number`, `group_id` or `contact_id`. Addressing a group needs a plan that includes group messaging: without it the call answers `payment_required: feature_not_available`, and retrying will not change that.
button_urlYesThe link the button opens when the recipient taps it.
contact_idNoRecipient contact id (`ct_…`), from `list_contacts`. A contact id belongs to one number: an id from one inbox does not address the same person in another. Set exactly one of `number`, `group_id` or `contact_id`.
button_textYesThe label on the button, 1 to 20 characters.
number_aliasNoWhich of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to see them. Defaults to the main number.main
idempotency_keyNoAny printable ASCII text you choose, 1 to 255 characters, for example the id of the event you are answering. Reusing it for the same number suppresses a duplicate if you retry. Without it, retrying after a timeout may deliver the message twice, and the recipient sees both.
quoted_message_idNoQuote an earlier message (`msg_…`) so it appears above yours. Do this only when your text depends on something said a while ago, yours or theirs; do not quote the message you are answering right now, send a normal message instead.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare this is a non-read-only, non-destructive, non-idempotent open-world send, so the safety profile is covered elsewhere. The description adds a genuinely non-obvious behavioral fact beyond that: a link-button message cannot be edited after sending and `delete_message` is the only remedy. It does not itself discuss retry/duplicate semantics, though the schema's idempotency_key field does.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four short paragraphs, front-loaded with the purpose and then the recipient rule, then constraints. Mild redundancy in re-quoting the character limits that already appear in the schema, but no wasted filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With 11 parameters, full schema descriptions, an output schema, and complete annotations, the description's remaining job is to convey the behavioral gotchas — immutability, recipient exclusivity, and the unavailable interactive types — all of which it does. 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.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so both the recipient and character-limit semantics are already documented in the schema. The description restates the 1024/20/60 limits and the header/body/footer positioning rather than adding anything new, which is the baseline case when the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

"Send an interactive message carrying one link button" names a specific verb and resource and pins down the exact message shape. It also distinguishes this tool from the plain send_text / reply_to_message family by stating that a link button is the only interactive type available on this connection.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives concrete selection rules: set exactly one of `number`, `group_id`, or `contact_id`, and explicitly rules out emulating reply buttons or list pickers. It does not name the sibling to use for plain text or quoted replies, so the routing back to send_text or reply_to_message is left implicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

send_locationSend a map locationAInspect

Send a location pin.

Set exactly one recipient: number, group_id, or contact_id.

latitude is between -90 and 90, longitude between -180 and 180. name and address label the pin; url adds a link beside it.

A location cannot be edited after it is sent: delete_message is the only change for it.

NameRequiredDescriptionDefault
urlNoA link shown beside the pin.
nameNoA name for the place, up to 200 characters.
numberNoRecipient phone number in E.164 form, digits only, country code first (e.g. `5511999999999`). Set exactly one of `number`, `group_id` or `contact_id`.
addressNoThe place's address, up to 500 characters.
group_idNoRecipient group id (`grp_…`), from `list_groups`. A group id belongs to one number: an id from one inbox does not address the same group in another. Set exactly one of `number`, `group_id` or `contact_id`. Addressing a group needs a plan that includes group messaging: without it the call answers `payment_required: feature_not_available`, and retrying will not change that.
latitudeYesLatitude, between -90 and 90.
longitudeYesLongitude, between -180 and 180.
contact_idNoRecipient contact id (`ct_…`), from `list_contacts`. A contact id belongs to one number: an id from one inbox does not address the same person in another. Set exactly one of `number`, `group_id` or `contact_id`.
number_aliasNoWhich of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to see them. Defaults to the main number.main
idempotency_keyNoAny printable ASCII text you choose, 1 to 255 characters, for example the id of the event you are answering. Reusing it for the same number suppresses a duplicate if you retry. Without it, retrying after a timeout may deliver the message twice, and the recipient sees both.
quoted_message_idNoQuote an earlier message (`msg_…`) so it appears above yours. Do this only when your text depends on something said a while ago, yours or theirs; do not quote the message you are answering right now, send a normal message instead.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations, the description discloses the critical behavior that a sent location is immutable and that delete_message is the only corrective action, which an agent needs before committing. The group plan gate (`payment_required: feature_not_available`) and the retry-duplication behavior of idempotency_key live only in the schema, so the description leaves some operational context uncovered.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with a one-line purpose, then grouped into recipient rule, coordinate bounds, labeling fields, and immutability. Every line carries a distinct constraint and there is no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 11-parameter outbound-send tool with a full schema and an output schema, the description covers the highest-risk facts: destination selection and irreversibility. It omits the number_alias channel selector and the idempotency retry story, both of which are documented in the schema, so the gap is minor.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

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 recipient exclusivity, lat/long bounds, name/address limits, number_alias, and idempotency_key. The description restates the exactly-one-recipient rule and coordinate ranges without adding syntax or examples, so it meets the baseline rather than exceeding it.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

"Send a location pin" states a specific verb and resource, and the resource is clearly distinct from the neighboring send_* tools (send_text, send_media, send_contact_card, send_cta_button). An agent can select this tool 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.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives the key selection constraint (exactly one of number, group_id, contact_id) and points to delete_message as the only remedy after sending, which routes the agent correctly on follow-up actions. It does not explicitly contrast with text/media sending, but the resource distinction makes that implicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

send_mediaSend an image, video, audio, document or stickerAInspect

Send media by URL: an image, video, audio clip, document or sticker.

Set exactly one recipient: number, group_id, or contact_id.

url must still be reachable when the send happens: Turbo Notify fetches the bytes from it. A copy is kept in the organization's own object storage afterwards when that is configured, which never blocks the send and is not required for one.

caption applies to image, video and document only; audio and stickers have nowhere to render one. filename applies to document only. Pairing either with a kind that cannot carry it is rejected here, before anything is sent.

After sending, only the caption of an image, video or document can be changed, with edit_media_caption. The file itself, an audio clip and a sticker cannot be edited: delete_message is the only change for them.

mime_type is optional and does not change how the message is sent. The type WhatsApp receives comes from what the URL's own server serves, so point url at a file that server labels correctly.

NameRequiredDescriptionDefault
urlYesLink to the file to send. It must still be reachable when the message goes out.
kindYesWhat the file is: image, video, audio, document or sticker.
numberNoRecipient phone number in E.164 form, digits only, country code first (e.g. `5511999999999`). Set exactly one of `number`, `group_id` or `contact_id`.
captionNoText shown with an image, video or document, up to 1024 characters. Audio and stickers cannot carry one.
filenameNoThe file name the recipient sees on a document, up to 255 characters. Documents only.
group_idNoRecipient group id (`grp_…`), from `list_groups`. A group id belongs to one number: an id from one inbox does not address the same group in another. Set exactly one of `number`, `group_id` or `contact_id`. Addressing a group needs a plan that includes group messaging: without it the call answers `payment_required: feature_not_available`, and retrying will not change that.
mime_typeNoThe media's MIME type, recorded alongside the message. It does not change how the file is sent: the type WhatsApp receives comes from what the URL's own server serves. Optional.
contact_idNoRecipient contact id (`ct_…`), from `list_contacts`. A contact id belongs to one number: an id from one inbox does not address the same person in another. Set exactly one of `number`, `group_id` or `contact_id`.
number_aliasNoWhich of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to see them. Defaults to the main number.main
idempotency_keyNoAny printable ASCII text you choose, 1 to 255 characters, for example the id of the event you are answering. Reusing it for the same number suppresses a duplicate if you retry. Without it, retrying after a timeout may deliver the message twice, and the recipient sees both.
quoted_message_idNoQuote an earlier message (`msg_…`) so it appears above yours. Do this only when your text depends on something said a while ago, yours or theirs; do not quote the message you are answering right now, send a normal message instead.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false, openWorldHint=true and destructiveHint=false, so the description's job is to add context, and it does: the URL must still be reachable at send time, a copy is stored in the org's object storage without blocking the send, and post-send mutability is limited to captions. It does not discuss rate limits or failure modes beyond the caption/filename rejection, which keeps it just short of a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Paragraphs are short and front-loaded, with the recipient constraint immediately after the purpose. The mime_type paragraph partially restates the schema description, which is the only mild redundancy; everything else earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 11-parameter mutation tool with an output schema, the description covers the essentials an agent needs: recipient exclusivity, kind-dependent optional fields, URL reachability, and what can be changed afterwards. Return values need not be explained because an output schema exists.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

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 explains that mime_type is recorded only and does not affect delivery (the URL server's type wins), and it reinforces the mutually exclusive recipient parameters and the kind-dependent caption/filename rules. That is value beyond the schema text.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence names a specific verb (send) and enumerates the exact resource kinds (image, video, audio, document, sticker), which cleanly separates it from send_text, send_location, send_contact_card and send_cta_button. An agent can pick this tool 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.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states the recipient rule explicitly ('Set exactly one recipient: number, group_id, or contact_id') and gives when-not guidance by naming the follow-up alternatives: edit_media_caption for captions, delete_message as the only change for audio and stickers. It also warns that invalid caption/filename pairings are rejected before sending.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

send_textSend a text messageAInspect

Send a WhatsApp text message.

Set exactly one recipient: number, group_id, or contact_id.

Writing @<number> in the text mentions that person, for example @5511999999999. The platform detects it automatically; there is no separate mentions argument.

This is also how to answer the message you just received: a normal message to its sender, as a person does in a chat, with no quote. Quote (quoted_message_id, or reply_to_message) only an earlier message that your answer depends on.

A text message you sent can be corrected later with edit_text_message.

Like a person opening the chat, the number first appears online and its unread messages in that conversation are marked as read, then the message is sent. Opening the conversation this way is automatic and uses no quota of its own.

Returns the new message_id and its initial status. Delivery happens asynchronously; poll get_message_status or watch list_events for the outcome.

NameRequiredDescriptionDefault
textYesThe message text, 1 to 4096 characters. Write `@<number>` to mention someone.
numberNoRecipient phone number in E.164 form, digits only, country code first (e.g. `5511999999999`). Set exactly one of `number`, `group_id` or `contact_id`.
group_idNoRecipient group id (`grp_…`), from `list_groups`. A group id belongs to one number: an id from one inbox does not address the same group in another. Set exactly one of `number`, `group_id` or `contact_id`. Addressing a group needs a plan that includes group messaging: without it the call answers `payment_required: feature_not_available`, and retrying will not change that.
contact_idNoRecipient contact id (`ct_…`), from `list_contacts`. A contact id belongs to one number: an id from one inbox does not address the same person in another. Set exactly one of `number`, `group_id` or `contact_id`.
number_aliasNoWhich of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to see them. Defaults to the main number.main
idempotency_keyNoAny printable ASCII text you choose, 1 to 255 characters, for example the id of the event you are answering. Reusing it for the same number suppresses a duplicate if you retry. Without it, retrying after a timeout may deliver the message twice, and the recipient sees both.
quoted_message_idNoQuote an earlier message (`msg_…`) so it appears above yours. Do this only when your text depends on something said a while ago, yours or theirs; do not quote the message you are answering right now, send a normal message instead.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations, it discloses a real side effect the schema does not: opening the conversation brings the number online and marks unread messages in that chat as read, without consuming quota. It also discloses asynchronous delivery and the duplicate-on-retry risk. The only gap is that quota/pricing and failure modes for unsupported recipients aren't covered in the description (group plan errors live in the schema instead).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the one-line purpose, then short paragraphs each covering a distinct concern (recipient, mentions, quoting, editing, side effects, returns). Slightly long, and the "like a person opening the chat" analogy plus the online/read-marking sequence takes more words than the behavior strictly needs.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 7-parameter open-world write tool this is complete: recipient rules, mention syntax, quoting policy, side effects, retry safety, and the return value plus how to observe async delivery. Output schema exists, so the brief note about `message_id` and status is sufficient rather than required.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

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 earns an increment by clarifying that mentions are parsed inline as `@<number>` and need no separate argument, and by framing quote-vs-normal-message semantics rather than just restating parameter names.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb plus resource ("Send a WhatsApp text message") that cleanly separates it from send_media, send_location, send_contact_card, and reply_to_message. The follow-on guidance about quoting and editing further sharpens the boundary against reply_to_message and edit_text_message.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit selection rules: exactly one of `number`/`group_id`/`contact_id`, don't quote the message currently being answered, quote only when the answer depends on an earlier message, and use `edit_text_message` to correct a sent message. It also tells the agent to poll `get_message_status` or `list_events` rather than assume delivery.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

send_typing_indicatorShow the typing indicator in a conversationAInspect

Show "typing…" to a recipient while you prepare an answer.

Set exactly one recipient: number, group_id, or contact_id.

Useful before a reply that takes a few seconds to compose, so the person on the other end sees something is happening. It expires on its own, so clearing it is optional: pass is_typing=false only if you decide not to answer after all and want the indicator gone at once.

There is no duration argument. WhatsApp decides how long it lives.

Starting to type also opens the conversation: the number appears online, its unread messages in that conversation are marked as read, and after a short pause "typing…" appears, so it never shows over unread messages. Stopping (is_typing=false) only clears the indicator and reads nothing. Opening the conversation this way is automatic and uses no quota of its own.

Needs a plan that includes the typing indicator, and showing it in a group needs one that includes group messaging as well. Without either, this answers payment_required: feature_not_available, and the answer will not change by retrying.

NameRequiredDescriptionDefault
numberNoRecipient phone number in E.164 form, digits only, country code first (e.g. `5511999999999`). Set exactly one of `number`, `group_id` or `contact_id`.
group_idNoRecipient group id (`grp_…`), from `list_groups`. A group id belongs to one number: an id from one inbox does not address the same group in another. Set exactly one of `number`, `group_id` or `contact_id`. Addressing a group needs a plan that includes group messaging: without it the call answers `payment_required: feature_not_available`, and retrying will not change that.
is_typingNo`true` shows "typing…" (the default), `false` clears it.
contact_idNoRecipient contact id (`ct_…`), from `list_contacts`. A contact id belongs to one number: an id from one inbox does not address the same person in another. Set exactly one of `number`, `group_id` or `contact_id`.
number_aliasNoWhich of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to see them. Defaults to the main number.main

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations: it discloses that starting to type opens the conversation, marks unread messages as read, appears only after a short pause, expires on its own, consumes no quota, and returns payment_required: feature_not_available for gated plans. These are non-obvious side effects an agent could not infer from readOnlyHint=false and destructiveHint=false alone.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well structured and front-loaded: purpose, recipient constraint, timing rationale, cleanup behavior, side effects, then plan gating. A few sentences are redundant with the schema text (the group plan caveat is repeated verbatim from the group_id description), which costs some efficiency but not clarity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite five parameters and no required ones, the description supplies everything needed to call it correctly: recipient selection, the default is_typing behavior, lifespan, side effects on unread state, quota impact, and the exact failure mode for unentitled plans. Return values are covered by the output schema, so nothing material is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents each parameter; the description reinforces the exactly-one-of number/group_id/contact_id constraint and adds meaning about the absent duration argument ("WhatsApp decides how long it lives"). The clarification that is_typing=false only clears the indicator and reads nothing is a genuine semantic addition beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb and resource ("Show 'typing…' to a recipient") and states the intent context ("while you prepare an answer"). It is immediately distinguishable from sibling send tools such as send_text or send_media, which deliver content rather than a transient presence state.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives a concrete when-to-use condition ("before a reply that takes a few seconds to compose") and a when-not/cleanup rule ("pass is_typing=false only if you decide not to answer after all"). It does not explicitly contrast with send_text/reply_to_message or say what to do if the feature is unavailable beyond not retrying, so it falls short of full alternative routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 36 tool updates
    • First observedcancel_calendar_event
    • First observedconnect_number
    • First observeddelete_message
    • First observeddisconnect_number
    • First observededit_calendar_event
    • First observededit_media_caption
    • First observededit_text_message
    • First observedget_contact
    • First observedget_contact_profile_picture
    • First observedget_contact_quota
    • First observedget_group
    • First observedget_group_picture
    • First observedget_message
    • First observedget_message_quota
    • First observedget_message_reactions
    • First observedget_message_receipts
    • First observedget_message_responses
    • First observedget_message_status
    • First observedget_number
    • First observedget_usage
    • First observedlist_contacts
    • First observedlist_events
    • First observedlist_groups
    • First observedlist_messages
    • First observedlist_numbers
    • First observedmark_as_read
    • First observedreact_to_message
    • First observedrefresh_contact
    • First observedreply_to_message
    • First observedsend_calendar_event
    • First observedsend_contact_card
    • First observedsend_cta_button
    • First observedsend_location
    • First observedsend_media
    • First observedsend_text
    • First observedsend_typing_indicator

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    C
    maintenance
    WhatsApp notifications and human-in-the-loop for AI agents. Text "join" to get an API key, then send messages, ask questions with tap-to-answer buttons, and read replies - no Meta account, no templates, no dashboard.
    5
    1
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables AI agents to send WhatsApp notifications to their owner and read the owner's replies through a local gateway, without requiring the Meta Business API.
    MIT
Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.