Skip to main content
Send Message lets a running agent reach the user proactively on their configured channels — “I’ve finished the report, sending it to you on Telegram” — without waiting for the next user turn.

Quick Start

1

Give Your Agent the Tool

from praisonaiagents import Agent
from praisonaiagents.tools import send_message

agent = Agent(
    name="Reporter",
    instructions="When you finish a long task, message the user on their channel.",
    tools=[send_message],
)

agent.start("Generate the weekly report and notify me when it's ready.")
The agent can now call send_message at any point mid-task to push a notification to the user.
2

List Available Targets

# The model calls:
#   send_message(action="list")
# and gets back JSON like:
#   [{"target": "telegram:home", "platform": "telegram", "kind": "home", "label": "Telegram"}]
Use action="list" first when you want the agent to pick the right channel rather than defaulting to "origin".
3

Send with a File Attachment

# Model call:
#   send_message("origin", "Weekly report ready MEDIA:/tmp/report.pdf")
# Returns: "Delivered to origin"
Append MEDIA:<path> to the message text to attach a local file. Multiple attachments are supported.

How It Works

ComponentPurpose
send_message toolAgent-callable function; resolves messenger from context
OutboundMessengerProtocolInterface the gateway registers per-turn
SessionContextTask-local registry — no globals, safe for concurrent handlers
GatewayDelivers to Telegram, Slack, Discord, WhatsApp, etc.

Targets

Choose the right target form for your situation:
Target formExampleDescription
"origin""origin"The chat this conversation came from (default)
"<platform>""telegram"That platform’s configured home channel
"<platform>:<chat_id>""slack:#ops"A specific chat or channel
"<platform>:<chat_id>:<thread_id>""slack:#ops:T123"A specific thread within a chat
"<alias>""my-ops-alert"A named alias configured in the gateway

Attachments (MEDIA:)

Append MEDIA:<path> to the message string to attach a local file to the delivery.
# Single attachment
send_message("origin", "Report ready MEDIA:/tmp/report.pdf")

# Multiple attachments — each MEDIA: token is stripped and the paths collected
send_message("origin", "Charts attached MEDIA:/tmp/chart1.png MEDIA:/tmp/chart2.png")
File paths must not contain whitespace. The MEDIA: directive is stripped from the displayed message text before delivery.

Listing Targets

action="list" returns a JSON array of all reachable targets so the agent can pick the right one before sending.
# Model call:
#   send_message(action="list")

# Returns JSON:
# [
#   {"target": "origin", "platform": "telegram", "kind": "origin", "label": "Current chat"},
#   {"target": "telegram", "platform": "telegram", "kind": "home", "label": "Telegram"},
#   {"target": "slack:#ops", "platform": "slack", "kind": "alias", "label": "#ops"}
# ]
Each entry in the array:
FieldTypeDescription
targetstrToken to pass as the target argument to send_message
platformstrPlatform name (e.g. "telegram", "slack")
kindstrOne of "origin", "home", or "alias"
labelstrFriendly name for display

When It’s Available

RuntimeBehaviour
Bot / Gateway (Telegram, Slack, Discord, WhatsApp, …)Delivers the message; returns a short summary string
CLI / one-shot (agent.start(...) directly)Returns the string below — does not raise
When no gateway is active the tool returns:
No active gateway: send_message is only available inside a running bot/gateway (e.g. Telegram, Slack, Discord). It is unavailable for CLI/one-shot runs.
Agent instructions can check for this string and fall back gracefully.

User Interaction Flow

A user starts a long research task on Telegram, then closes their phone. The agent finishes compiling the report, calls send_message("origin", "Your report is ready MEDIA:/tmp/report.pdf"), and the user receives a Telegram push notification with the PDF attached — without ever having to ask “are you done yet?”.

Configuration Reference

send_message takes three arguments. All are optional:
ArgumentTypeDefaultDescription
targetstr"origin"Symbolic destination (see Targets table)
messagestr""Text to send; append " MEDIA:<path>" to attach files
actionstr"send""send" to deliver, "list" to enumerate reachable targets
action="send" vs action="list" at a glance:
actionReturns
"send"Short summary string, e.g. "Delivered to slack:#ops"
"list"JSON array of {target, platform, kind, label} objects

Common Patterns

Notify on long-task completion

agent = Agent(
    name="Analyst",
    instructions="""
    Run deep analysis tasks. When a task finishes, always call
    send_message("origin", "<summary>") to let the user know.
    """,
    tools=[send_message],
)

Cross-channel handoff

# Model calls send_message(action="list") first, picks slack:#ops, then:
#   send_message("slack:#ops", "Deploy finished ✅")

Pick the target from the list, then send

# 1. List targets
#    send_message(action="list")
#    → [{"target": "slack:#ops", ...}, {"target": "telegram", ...}]
# 2. Choose and send
#    send_message("slack:#ops", "All tests passed")

Best Practices

Call send_message(action="list") first when the user hasn’t specified where they want to be notified. Sending to a channel the user doesn’t monitor is noise.
"origin" sends to the chat the conversation started in — usually the right choice. Only override it when you have a specific reason (e.g., sending an ops alert to a dedicated Slack channel).
Include a note like “If send_message returns a ‘No active gateway’ message, skip the notification and continue.” so the agent doesn’t retry endlessly on CLI runs.
Mobile push notifications truncate long text. Send a one-line summary; attach details as a file with MEDIA:.

Clarify Tool

Ask the user mid-task for clarifying input

Channels Gateway

Connect agents to Telegram, Slack, Discord, and WhatsApp

Bot Gateway

Run the gateway server

Bot Routing

Route messages by channel and platform