Skip to main content
Glama

messages_send

Destructive

Send a message to a thread, channel, or contact. Supports Telegram, Email, LinkedIn, and other connected channels. For LinkedIn posts (comment_thread kind), this posts a comment on the post. Can automatically resolve recipients and channels when not specified. Can send files/images/documents as attachments — pass attachments=[file_id, ...] with integer file IDs obtained from collections.list_files, search.files, or files.search. text is optional when attachments are provided.

Input Schema

NameRequiredDescriptionDefault
textNoMessage text to send. Optional if attachments provided.
formatNoMessage formattext
silentNoSend without notification
buttonsNoInline reply buttons shown under the message, one per row (max 10). Each item is {"label": "<visible button text>"} plus exactly one target: "value" (a string sent back as a normal incoming message when tapped, defaults to the label, max 64 bytes), "url" (opens a link) or "web_app" (opens an https page as a Telegram Mini App). A "url" button may add "track": true: the tap is then counted for this conversation (analytics_link_clicks_v in analytics.query) and the person is sent on to the url; "tag": <ai_tag id> beside it also puts that tag on the CONVERSATION at the tap (a group's tag is any member's tap; a first message to a new contact has no conversation yet and goes out untagged); "pass": "<name>" opens the url with <name>=<the chat's id on its channel> added, so the site can name the person back in its own events. Only on channels that support buttons (Telegram bot accounts); can accompany at most one attachment, and when the text is too long for a media caption the buttons arrive with the text as a second message.
mentionsNoPeople of a group chat to @-tag so the platform really notifies them (WhatsApp, Telegram groups). Each item names one member of THIS chat by one of: "name" (as shown in the chat), "phone" (international number) or "entity_id". If the text already holds "@<name>" that spot is the tag, otherwise "@<name> " is put in front of the text. A person who is not in the chat, or who matches several, refuses the whole send and lists the members. Without this parameter a "@Name" in the text of a group message tags the member it names in the same way, and an @-word that names nobody refuses the send (on Telegram it stays text: a typed @username is a link there). Not combinable with attachments or buttons, and not available while the agent sends drafts. Text may be empty: the tags alone are sent.
templateNoWhatsApp Business API only. An approved template to send instead of free text, in Meta's shape: {name, language, components:[{type:'body', parameters:[{type:'text', text:...}]}, ...]}; `language` is the code as a string ('en_US'). Required when the 24-hour window of the conversation is closed (the send answers WINDOW_EXPIRED otherwise). Read the approved templates and their variables with channels.list(account_id=...).
thread_idNoTarget thread. OMIT to reply in the same chat you received the triggering message from — the backend defaults to the current thread. Pass an explicit value ONLY to reply in a DIFFERENT thread, and only use: (a) a numeric DB thread id from search.threads, or (b) a channel_ref like 'telegram:-12345'. To write to a phone number nobody has a thread with yet: 'whatsapp_business:+<number in international format>' opens a WhatsApp conversation from a WhatsApp Business API number (from_account_id picks which one; the first message must be a `template`), and 'sms:+<number>' texts it from a workspace phone number that has SMS turned on (from_account_id picks which one), landing in that number's conversation with the recipient, next to their calls. 'x:@<handle>' sends a first X direct message to that person from a connected X account; X refuses it when their inbox is closed to the sender. 'discord:<user id>' (the person's numeric Discord id) sends a first Discord DM from a connected Discord account, into the DM that exists with them or one opened for it; new DMs are limited per account and day, and refused in words with a retry_after when over. 'skool:user:<user id>' (optionally '@<community id>' after the id, when the two share several communities) sends a first message on Skool from a connected Skool account; a Skool post thread ('skool:<account>:post:<post id>') takes a comment instead. NEVER use a chat-type word (dm, group, channel, livechat, comment_thread) — those are category labels from the SITUATION block, not ids.
attachmentsNoArray of integer file IDs to send as attachments (images, documents, any files). Get file IDs from collections.list_files (field `file_id`), search.files (field `file_id`), or files.search — only ids returned by those calls in this workspace. The file must already exist in the workspace (status=ready) — no separate upload step needed. When attachments are provided, `text` becomes optional (a caption can be included alongside).
in_workspaceNoRun this one call in this workspace id instead of the session's. Nothing is stored; other sessions are not affected.
private_replyNoComment threads only (Instagram, Facebook): answer the comment in the commenter's private messages instead of publicly under the post (Meta's Private Replies). One message per comment, within 7 days of the comment. The message is filed in the person's private conversation. To also answer publicly, make a second call without this flag. OMIT for a normal send.
recipient_nameNoName of person to send to (e.g., 'Jane', 'John'). Tool will auto-resolve channel. Optional if thread_id provided.
from_account_idNoWhich of the workspace's accounts on this channel SENDS the message, i.e. the number or handle the recipient sees. A numeric thread_id is one conversation on one account: naming a different account for it is refused. With a channel_ref or recipient_username, the conversation ON THIS ACCOUNT is used, or opened where the channel can start one; if it has none, the send is refused rather than made from another account. OMIT and the platform picks the most recently active account, which is a coin flip in a workspace with several numbers: pass it whenever one of them must not be used to open conversations (a personal line, or one under a spam restriction). An account that is not active in this workspace is refused, never silently swapped.
recipient_usernameNoTelegram @username to message (e.g. '@some_username'). Use this for a Telegram user NOT yet in contacts — it resolves the handle, adds the contact, and creates the thread. Telegram only; for existing contacts prefer thread_id or recipient_name.
reply_to_message_idNoID of message to reply to (optional)

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • changedInput schema / properties / buttons / description
      Previous value: -"Inline reply buttons shown under the message, one per row (max 10). Each item is {\"label\": \"<visible button text>\"} plus exactly one target: \"value\" (a string sent back as a normal incoming message when tapped, defaults to the label, max 64 bytes), \"url\" (opens a link) or \"web_app\" (opens an https page as a Telegram Mini App). A \"url\" button may add \"track\": true: the tap is then counted for this conversation (analytics_link_clicks_v in analytics.query) and the person is sent on to the url; \"tag\": <ai_tag id> beside it also puts that tag on the CONVERSATION at the tap (a group's tag is any member's tap; a first message to a new contact has no conversation yet and goes out untagged). Only on channels that support buttons (Telegram bot accounts); can accompany at most one attachment, and when the text is too long for a media caption the buttons arrive with the text as a second message."New value: +"Inline reply buttons shown under the message, one per row (max 10). Each item is {\"label\": \"<visible button text>\"} plus exactly one target: \"value\" (a string sent back as a normal incoming message when tapped, defaults to the label, max 64 bytes), \"url\" (opens a link) or \"web_app\" (opens an https page as a Telegram Mini App). A \"url\" button may add \"track\": true: the tap is then counted for this conversation (analytics_link_clicks_v in analytics.query) and the person is sent on to the url; \"tag\": <ai_tag id> beside it also puts that tag on the CONVERSATION at the tap (a group's tag is any member's tap; a first message to a new contact has no conversation yet and goes out untagged); \"pass\": \"<name>\" opens the url with <name>=<the chat's id on its channel> added, so the site can name the person back in its own events. Only on channels that support buttons (Telegram bot accounts); can accompany at most one attachment, and when the text is too long for a media caption the buttons arrive with the text as a second message."
  2. Changed2 schema fields changed
    • changedInput schema / properties / buttons / description
      Previous value: -"Inline reply buttons shown under the message, one per row (max 10). Each item is {\"label\": \"<visible button text>\"} plus exactly one target: \"value\" (a string sent back as a normal incoming message when tapped, defaults to the label, max 64 bytes), \"url\" (opens a link) or \"web_app\" (opens an https page as a Telegram Mini App). A \"url\" button may add \"track\": true: the tap is then counted for this conversation (analytics_link_clicks_v in analytics.query) and the person is sent on to the url. Only on channels that support buttons (Telegram bot accounts); can accompany at most one attachment, and when the text is too long for a media caption the buttons arrive with the text as a second message."New value: +"Inline reply buttons shown under the message, one per row (max 10). Each item is {\"label\": \"<visible button text>\"} plus exactly one target: \"value\" (a string sent back as a normal incoming message when tapped, defaults to the label, max 64 bytes), \"url\" (opens a link) or \"web_app\" (opens an https page as a Telegram Mini App). A \"url\" button may add \"track\": true: the tap is then counted for this conversation (analytics_link_clicks_v in analytics.query) and the person is sent on to the url; \"tag\": <ai_tag id> beside it also puts that tag on the CONVERSATION at the tap (a group's tag is any member's tap; a first message to a new contact has no conversation yet and goes out untagged). Only on channels that support buttons (Telegram bot accounts); can accompany at most one attachment, and when the text is too long for a media caption the buttons arrive with the text as a second message."
    • changedInput schema / properties / mentions / description
      Previous value: -"People of a group chat to @-tag so the platform really notifies them (WhatsApp, Telegram groups). Each item names one member of THIS chat by one of: \"name\" (as shown in the chat), \"phone\" (international number) or \"entity_id\". If the text already holds \"@<name>\" that spot is the tag, otherwise \"@<name> \" is put in front of the text. A person who is not in the chat, or who matches several, refuses the whole send and lists the members. A plain \"@Name\" typed without this notifies nobody. Not combinable with attachments or buttons, and not available while the agent sends drafts. Text may be empty: the tags alone are sent."New value: +"People of a group chat to @-tag so the platform really notifies them (WhatsApp, Telegram groups). Each item names one member of THIS chat by one of: \"name\" (as shown in the chat), \"phone\" (international number) or \"entity_id\". If the text already holds \"@<name>\" that spot is the tag, otherwise \"@<name> \" is put in front of the text. A person who is not in the chat, or who matches several, refuses the whole send and lists the members. Without this parameter a \"@Name\" in the text of a group message tags the member it names in the same way, and an @-word that names nobody refuses the send (on Telegram it stays text: a typed @username is a link there). Not combinable with attachments or buttons, and not available while the agent sends drafts. Text may be empty: the tags alone are sent."
  3. Changed1 schema field changed
    • changedInput schema / properties / thread_id / description
      Previous value: -"Target thread. OMIT to reply in the same chat you received the triggering message from — the backend defaults to the current thread. Pass an explicit value ONLY to reply in a DIFFERENT thread, and only use: (a) a numeric DB thread id from search.threads, or (b) a channel_ref like 'telegram:-12345'. To write to a phone number nobody has a thread with yet: 'whatsapp_business:+<number in international format>' opens a WhatsApp conversation from a WhatsApp Business API number (from_account_id picks which one; the first message must be a `template`), and 'sms:+<number>' texts it from a workspace phone number that has SMS turned on (from_account_id picks which one), landing in that number's conversation with the recipient, next to their calls. 'x:@<handle>' sends a first X direct message to that person from a connected X account; X refuses it when their inbox is closed to the sender. 'discord:<user id>' (the person's numeric Discord id) sends a first Discord DM from a connected Discord account, into the DM that exists with them or one opened for it; new DMs are limited per account and day, and refused in words with a retry_after when over. NEVER use a chat-type word (dm, group, channel, livechat, comment_thread) — those are category labels from the SITUATION block, not ids."New value: +"Target thread. OMIT to reply in the same chat you received the triggering message from — the backend defaults to the current thread. Pass an explicit value ONLY to reply in a DIFFERENT thread, and only use: (a) a numeric DB thread id from search.threads, or (b) a channel_ref like 'telegram:-12345'. To write to a phone number nobody has a thread with yet: 'whatsapp_business:+<number in international format>' opens a WhatsApp conversation from a WhatsApp Business API number (from_account_id picks which one; the first message must be a `template`), and 'sms:+<number>' texts it from a workspace phone number that has SMS turned on (from_account_id picks which one), landing in that number's conversation with the recipient, next to their calls. 'x:@<handle>' sends a first X direct message to that person from a connected X account; X refuses it when their inbox is closed to the sender. 'discord:<user id>' (the person's numeric Discord id) sends a first Discord DM from a connected Discord account, into the DM that exists with them or one opened for it; new DMs are limited per account and day, and refused in words with a retry_after when over. 'skool:user:<user id>' (optionally '@<community id>' after the id, when the two share several communities) sends a first message on Skool from a connected Skool account; a Skool post thread ('skool:<account>:post:<post id>') takes a comment instead. NEVER use a chat-type word (dm, group, channel, livechat, comment_thread) — those are category labels from the SITUATION block, not ids."
  4. Changed1 schema field changed
    • changedInput schema / properties / thread_id / description
      Previous value: -"Target thread. OMIT to reply in the same chat you received the triggering message from — the backend defaults to the current thread. Pass an explicit value ONLY to reply in a DIFFERENT thread, and only use: (a) a numeric DB thread id from search.threads, or (b) a channel_ref like 'telegram:-12345'. To write to a phone number nobody has a thread with yet: 'whatsapp_business:+<number in international format>' opens a WhatsApp conversation from a WhatsApp Business API number (from_account_id picks which one; the first message must be a `template`), and 'sms:+<number>' texts it from a workspace phone number that has SMS turned on (from_account_id picks which one), landing in that number's conversation with the recipient, next to their calls. 'x:@<handle>' sends a first X direct message to that person from a connected X account; X refuses it when their inbox is closed to the sender. NEVER use a chat-type word (dm, group, channel, livechat, comment_thread) — those are category labels from the SITUATION block, not ids."New value: +"Target thread. OMIT to reply in the same chat you received the triggering message from — the backend defaults to the current thread. Pass an explicit value ONLY to reply in a DIFFERENT thread, and only use: (a) a numeric DB thread id from search.threads, or (b) a channel_ref like 'telegram:-12345'. To write to a phone number nobody has a thread with yet: 'whatsapp_business:+<number in international format>' opens a WhatsApp conversation from a WhatsApp Business API number (from_account_id picks which one; the first message must be a `template`), and 'sms:+<number>' texts it from a workspace phone number that has SMS turned on (from_account_id picks which one), landing in that number's conversation with the recipient, next to their calls. 'x:@<handle>' sends a first X direct message to that person from a connected X account; X refuses it when their inbox is closed to the sender. 'discord:<user id>' (the person's numeric Discord id) sends a first Discord DM from a connected Discord account, into the DM that exists with them or one opened for it; new DMs are limited per account and day, and refused in words with a retry_after when over. NEVER use a chat-type word (dm, group, channel, livechat, comment_thread) — those are category labels from the SITUATION block, not ids."
  5. Changed1 schema field changed
    • addedInput schema / properties / mentions
      Added value: +{
      +  "description": "People of a group chat to @-tag so the platform really notifies them (WhatsApp, Telegram groups). Each item names one member of THIS chat by one of: \"name\" (as shown in the chat), \"phone\" (international number) or \"entity_id\". If the text already holds \"@<name>\" that spot is the tag, otherwise \"@<name> \" is put in front of the text. A person who is not in the chat, or who matches several, refuses the whole send and lists the members. A plain \"@Name\" typed without this notifies nobody. Not combinable with attachments or buttons, and not available while the agent sends drafts. Text may be empty: the tags alone are sent.",
      +  "items": {
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
  6. Changed1 schema field changed
    • changedInput schema / properties / thread_id / description
      Previous value: -"Target thread. OMIT to reply in the same chat you received the triggering message from — the backend defaults to the current thread. Pass an explicit value ONLY to reply in a DIFFERENT thread, and only use: (a) a numeric DB thread id from search.threads, or (b) a channel_ref like 'telegram:-12345'. To write to a phone number nobody has a thread with yet: 'whatsapp_business:+<number in international format>' opens a WhatsApp conversation from a WhatsApp Business API number (from_account_id picks which one; the first message must be a `template`), and 'sms:+<number>' texts it from a workspace phone number that has SMS turned on (from_account_id picks which one), landing in that number's conversation with the recipient, next to their calls. NEVER use a chat-type word (dm, group, channel, livechat, comment_thread) — those are category labels from the SITUATION block, not ids."New value: +"Target thread. OMIT to reply in the same chat you received the triggering message from — the backend defaults to the current thread. Pass an explicit value ONLY to reply in a DIFFERENT thread, and only use: (a) a numeric DB thread id from search.threads, or (b) a channel_ref like 'telegram:-12345'. To write to a phone number nobody has a thread with yet: 'whatsapp_business:+<number in international format>' opens a WhatsApp conversation from a WhatsApp Business API number (from_account_id picks which one; the first message must be a `template`), and 'sms:+<number>' texts it from a workspace phone number that has SMS turned on (from_account_id picks which one), landing in that number's conversation with the recipient, next to their calls. 'x:@<handle>' sends a first X direct message to that person from a connected X account; X refuses it when their inbox is closed to the sender. NEVER use a chat-type word (dm, group, channel, livechat, comment_thread) — those are category labels from the SITUATION block, not ids."
  7. Changed1 schema field changed
    • changedInput schema / properties / from_account_id / description
      Previous value: -"Which of the workspace's accounts on this channel SENDS the message, i.e. the number or handle the recipient sees. Only meaningful when starting a NEW conversation — an existing thread already belongs to an account and that one is used. OMIT and the platform picks the most recently active account, which is a coin flip in a workspace with several numbers: pass it whenever one of them must not be used to open conversations (a personal line, or one under a spam restriction). An account that is not active in this workspace is refused, never silently swapped."New value: +"Which of the workspace's accounts on this channel SENDS the message, i.e. the number or handle the recipient sees. A numeric thread_id is one conversation on one account: naming a different account for it is refused. With a channel_ref or recipient_username, the conversation ON THIS ACCOUNT is used, or opened where the channel can start one; if it has none, the send is refused rather than made from another account. OMIT and the platform picks the most recently active account, which is a coin flip in a workspace with several numbers: pass it whenever one of them must not be used to open conversations (a personal line, or one under a spam restriction). An account that is not active in this workspace is refused, never silently swapped."
  8. Changed1 schema field changed
    • changedInput schema / properties / buttons / description
      Previous value: -"Inline reply buttons shown under the message, one per row (max 10). Each item is {\"label\": \"<visible button text>\"} plus exactly one target: \"value\" (a string sent back as a normal incoming message when tapped, defaults to the label, max 64 bytes), \"url\" (opens a link) or \"web_app\" (opens an https page as a Telegram Mini App). Only on channels that support buttons (Telegram bot accounts); can accompany at most one attachment, and when the text is too long for a media caption the buttons arrive with the text as a second message."New value: +"Inline reply buttons shown under the message, one per row (max 10). Each item is {\"label\": \"<visible button text>\"} plus exactly one target: \"value\" (a string sent back as a normal incoming message when tapped, defaults to the label, max 64 bytes), \"url\" (opens a link) or \"web_app\" (opens an https page as a Telegram Mini App). A \"url\" button may add \"track\": true: the tap is then counted for this conversation (analytics_link_clicks_v in analytics.query) and the person is sent on to the url. Only on channels that support buttons (Telegram bot accounts); can accompany at most one attachment, and when the text is too long for a media caption the buttons arrive with the text as a second message."
  9. Changed1 schema field changed
    • changedInput schema / properties / thread_id / description
      Previous value: -"Target thread. OMIT to reply in the same chat you received the triggering message from — the backend defaults to the current thread. Pass an explicit value ONLY to reply in a DIFFERENT thread, and only use: (a) a numeric DB thread id from search.threads, or (b) a channel_ref like 'telegram:-12345'. To write to a phone number nobody has a thread with yet: 'whatsapp_business:+<number in international format>' opens a WhatsApp conversation from a WhatsApp Business API number (from_account_id picks which one; the first message must be a `template`), and 'sms:+<number>' texts it from a workspace phone number that has SMS turned on (from_account_id picks which one), landing in that number's conversation with the recipient, next to their calls. NEVER use a chat-type word (dm, group, channel, livechat) — those are category labels from the SITUATION block, not ids."New value: +"Target thread. OMIT to reply in the same chat you received the triggering message from — the backend defaults to the current thread. Pass an explicit value ONLY to reply in a DIFFERENT thread, and only use: (a) a numeric DB thread id from search.threads, or (b) a channel_ref like 'telegram:-12345'. To write to a phone number nobody has a thread with yet: 'whatsapp_business:+<number in international format>' opens a WhatsApp conversation from a WhatsApp Business API number (from_account_id picks which one; the first message must be a `template`), and 'sms:+<number>' texts it from a workspace phone number that has SMS turned on (from_account_id picks which one), landing in that number's conversation with the recipient, next to their calls. NEVER use a chat-type word (dm, group, channel, livechat, comment_thread) — those are category labels from the SITUATION block, not ids."
  10. Changed3 schema fields changed
    • changedInput schema / properties / template / description
      Previous value: -"WhatsApp Business API only. An approved template to send instead of free text, in Meta's shape: {name, language, components:[{type:'body', parameters:[{type:'text', text:...}]}, ...]}; `language` may be the code as a string ('en_US') or Meta's {code:'en_US'}. Required when the 24-hour window of the conversation is closed (the send answers WINDOW_EXPIRED otherwise). Read the approved templates and their variables with channels.list(account_id=...)."New value: +"WhatsApp Business API only. An approved template to send instead of free text, in Meta's shape: {name, language, components:[{type:'body', parameters:[{type:'text', text:...}]}, ...]}; `language` is the code as a string ('en_US'). Required when the 24-hour window of the conversation is closed (the send answers WINDOW_EXPIRED otherwise). Read the approved templates and their variables with channels.list(account_id=...)."
    • addedInput schema / properties / template / properties
      Added value: +{
      +  "components": {
      +    "description": "Variable values per component, in Meta's shape.",
      +    "items": {
      +      "properties": {
      +        "parameters": {
      +          "items": {
      +            "properties": {
      +              "text": {
      +                "description": "The value of this variable.",
      +                "type": "string"
      +              },
      +              "type": {
      +                "description": "'text'.",
      +                "type": "string"
      +              }
      +            },
      +            "type": "object"
      +          },
      +          "type": "array"
      +        },
      +        "type": {
      +          "description": "'body', 'header' or 'button'.",
      +          "type": "string"
      +        }
      +      },
      +      "type": "object"
      +    },
      +    "type": "array"
      +  },
      +  "language": {
      +    "description": "Template language code, e.g. 'en_US'.",
      +    "type": "string"
      +  },
      +  "name": {
      +    "description": "Template name as approved at Meta.",
      +    "type": "string"
      +  }
      +}
    • changedInput schema / properties / thread_id / description
      Previous value: -"Target thread. OMIT to reply in the same chat you received the triggering message from — the backend defaults to the current thread. Pass an explicit value ONLY to reply in a DIFFERENT thread, and only use: (a) a numeric DB thread id from search.threads, or (b) a channel_ref like 'telegram:-12345'. To text a phone number, pass 'sms:+<number in international format>': the message goes out from a workspace phone number that has SMS turned on (from_account_id picks which one) and lands in that number's conversation with the recipient, next to their calls. NEVER use a chat-type word (dm, group, channel, livechat) — those are category labels from the SITUATION block, not ids."New value: +"Target thread. OMIT to reply in the same chat you received the triggering message from — the backend defaults to the current thread. Pass an explicit value ONLY to reply in a DIFFERENT thread, and only use: (a) a numeric DB thread id from search.threads, or (b) a channel_ref like 'telegram:-12345'. To write to a phone number nobody has a thread with yet: 'whatsapp_business:+<number in international format>' opens a WhatsApp conversation from a WhatsApp Business API number (from_account_id picks which one; the first message must be a `template`), and 'sms:+<number>' texts it from a workspace phone number that has SMS turned on (from_account_id picks which one), landing in that number's conversation with the recipient, next to their calls. NEVER use a chat-type word (dm, group, channel, livechat) — those are category labels from the SITUATION block, not ids."
  11. Changed1 schema field changed
    • addedInput schema / properties / template
      Added value: +{
      +  "description": "WhatsApp Business API only. An approved template to send instead of free text, in Meta's shape: {name, language, components:[{type:'body', parameters:[{type:'text', text:...}]}, ...]}; `language` may be the code as a string ('en_US') or Meta's {code:'en_US'}. Required when the 24-hour window of the conversation is closed (the send answers WINDOW_EXPIRED otherwise). Read the approved templates and their variables with channels.list(account_id=...).",
      +  "type": "object"
      +}
  12. Changed1 schema field changed
    • addedInput schema / properties / in_workspace
      Added value: +{
      +  "description": "Run this one call in this workspace id instead of the session's. Nothing is stored; other sessions are not affected.",
      +  "type": "integer"
      +}
  13. Changed1 schema field changed
    • changedInput schema / properties / thread_id / description
      Previous value: -"Target thread. OMIT to reply in the same chat you received the triggering message from — the backend defaults to the current thread. Pass an explicit value ONLY to reply in a DIFFERENT thread, and only use: (a) a numeric DB thread id from search.threads, or (b) a channel_ref like 'telegram:-12345'. To text a phone number that has no thread yet, pass 'sms:+<number in international format>' (the workspace needs a phone number with SMS turned on; from_account_id picks which one). NEVER use a chat-type word (dm, group, channel, livechat) — those are category labels from the SITUATION block, not ids."New value: +"Target thread. OMIT to reply in the same chat you received the triggering message from — the backend defaults to the current thread. Pass an explicit value ONLY to reply in a DIFFERENT thread, and only use: (a) a numeric DB thread id from search.threads, or (b) a channel_ref like 'telegram:-12345'. To text a phone number, pass 'sms:+<number in international format>': the message goes out from a workspace phone number that has SMS turned on (from_account_id picks which one) and lands in that number's conversation with the recipient, next to their calls. NEVER use a chat-type word (dm, group, channel, livechat) — those are category labels from the SITUATION block, not ids."
  14. Changed1 schema field changed
    • changedInput schema / properties / thread_id / description
      Previous value: -"Target thread. OMIT to reply in the same chat you received the triggering message from — the backend defaults to the current thread. Pass an explicit value ONLY to reply in a DIFFERENT thread, and only use: (a) a numeric DB thread id from search.threads, or (b) a channel_ref like 'telegram:-12345'. NEVER use a chat-type word (dm, group, channel, livechat) — those are category labels from the SITUATION block, not ids."New value: +"Target thread. OMIT to reply in the same chat you received the triggering message from — the backend defaults to the current thread. Pass an explicit value ONLY to reply in a DIFFERENT thread, and only use: (a) a numeric DB thread id from search.threads, or (b) a channel_ref like 'telegram:-12345'. To text a phone number that has no thread yet, pass 'sms:+<number in international format>' (the workspace needs a phone number with SMS turned on; from_account_id picks which one). NEVER use a chat-type word (dm, group, channel, livechat) — those are category labels from the SITUATION block, not ids."
  15. Added
  16. Removed
  17. Changed1 schema field changed
    • addedInput schema / properties / recipient_username
      Added value: +{
      +  "description": "Telegram @username to message (e.g. '@some_username'). Use this for a Telegram user NOT yet in contacts — it resolves the handle, adds the contact, and creates the thread. Telegram only; for existing contacts prefer thread_id or recipient_name.",
      +  "type": "string"
      +}
  18. Changed8 schema fields changed
    • changedInput schema / properties / attachments / description
      Previous value: -"Array of integer file IDs to send as attachments (images, documents, any files). Get file IDs from collections.list_files (field `file_id`), workspace.search with scope=['files'] (field `file_id`), or files.search. Example: [302237]. The file must already exist in the workspace (status=ready) — no separate upload step needed. When attachments are provided, `text` becomes optional (a caption can be included alongside)."New value: +"Array of integer file IDs to send as attachments (images, documents, any files). Get file IDs from collections.list_files (field `file_id`), search.files (field `file_id`), or files.search. Example: [302237]. The file must already exist in the workspace (status=ready) — no separate upload step needed. When attachments are provided, `text` becomes optional (a caption can be included alongside)."
    • removedInput schema / properties / bcc
      Removed value: -{
      -  "description": "Email addresses to BCC (blind carbon copy). Only for email channel.",
      -  "items": {
      -    "type": "string"
      -  },
      -  "type": "array"
      -}
    • removedInput schema / properties / cc
      Removed value: -{
      -  "description": "Email addresses to CC (carbon copy). Only for email channel.",
      -  "items": {
      -    "type": "string"
      -  },
      -  "type": "array"
      -}
    • removedInput schema / properties / channel
      Removed value: -{
      -  "description": "Channel hint (e.g. 'telegram'). Required when using recipient_username. Only 'telegram' is currently accepted for handle-based routing.",
      -  "type": "string"
      -}
    • removedInput schema / properties / recipient_email
      Removed value: -{
      -  "description": "Email address to send to (e.g., 'john@example.com'). Creates new email thread. Only for email channel.",
      -  "type": "string"
      -}
    • removedInput schema / properties / recipient_username
      Removed value: -{
      -  "description": "Telegram @handle (e.g. '@smartdeveloper' or 'smartdeveloper'). Resolves or opens a DM without needing a DB thread_id. Requires channel='telegram'. Only Telegram supported in this release.",
      -  "type": "string"
      -}
    • removedInput schema / properties / subject
      Removed value: -{
      -  "description": "Email subject line. Required for new emails, optional for replies (auto-generates 'Re: ...').",
      -  "type": "string"
      -}
    • changedInput schema / properties / thread_id / description
      Previous value: -"Target thread. OMIT to reply in the same chat you received the triggering message from — the backend defaults to the current thread. Pass an explicit value ONLY to reply in a DIFFERENT thread, and only use: (a) a numeric DB thread id from threads.list / workspace.search, or (b) a channel_ref like 'telegram:-12345'. NEVER use a chat-type word (dm, group, channel, livechat) — those are category labels from the SITUATION block, not ids."New value: +"Target thread. OMIT to reply in the same chat you received the triggering message from — the backend defaults to the current thread. Pass an explicit value ONLY to reply in a DIFFERENT thread, and only use: (a) a numeric DB thread id from search.threads, or (b) a channel_ref like 'telegram:-12345'. NEVER use a chat-type word (dm, group, channel, livechat) — those are category labels from the SITUATION block, not ids."
  19. First observed

TDQS

A4.2/5.0
Behavior5/5

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

Goes well beyond the destructive/non-idempotent/openWorld annotations: WINDOW_EXPIRED refusal, Discord DM per-account daily limits with retry_after, private reply limited to one per comment within 7 days, mentions refusing the whole send and listing members, buttons only on Telegram bot accounts, and from_account_id refused rather than silently swapped. This is exactly the operational context an agent needs for an irreversible send.

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?

Five sentences, front-loaded with the core action, then attachments, then text-optional caveat. Efficient for a 14-parameter tool; the channel list sentence is the only mildly redundant part given sibling overlap.

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 14-parameter open-world mutation with no output schema, the description covers the risky branches (window expiry, account selection, rate limits, refusal modes) and notes that text is optional with attachments. Only the return value (e.g. sent message id for later reply_to_message_id) is unaddressed, and no output schema exists to cover it.

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 carries the baseline. The description still adds cross-tool provenance for attachments (file_id sources), thread_id/channel_ref formats, and template-as-alternative-to-text semantics, which meaningfully supplements the schema.

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 ('Send a message to a thread, channel, or contact') and adds scope (Telegram, Email, LinkedIn, channel kinds, LinkedIn comment_thread behavior). It is clear, but it claims Email support while a sibling messages_send_email exists, so differentiation from that sibling is left implicit.

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 conditional guidance: omit thread_id to reply in the current chat, pass attachments=[file_id,...] with IDs from collections.list_files/search.files/files.search, text optional with attachments, template required when the WhatsApp 24h window is closed, private_reply for comment threads. It stops short of explicitly routing between messages_send, messages_send_email, and posts_publish.

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

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.