Skip to main content
Push outbound messages from an agent-backed bot — reply to the requesting chat, a home channel, or a named alias.
Blueprints carry a default_deliver (usually telegram), so jobs created from Automation Suggestions land on the right channel out of the box.
import asyncio
from praisonai.bots import BotOS, Bot, SessionSource
from praisonaiagents import Agent

agent = Agent(name="ops", instructions="Alert humans about incidents.")
botos = BotOS(bots=[Bot("telegram", agent=agent)])

botos.configure_channels({
    "telegram": {"home_channel": "123456", "aliases": {"ops-alerts": "123456"}},
})

async def notify():
    src = SessionSource(platform="telegram", channel_id="123456")
    await botos.deliver("origin", "Build finished!", origin=src)

asyncio.run(notify())
The user triggers an alert; BotOS delivers the agent’s message to the target channel.

Quick Start

1

Simple Usage

Reply to where the request came from:
import asyncio
from praisonai.bots import BotOS, Bot, SessionSource
from praisonaiagents import Agent

agent = Agent(name="ops", instructions="Send status updates.")
botos = BotOS(bots=[Bot("telegram", agent=agent)])

async def notify():
    src = SessionSource(platform="telegram", channel_id="123456")
    await botos.deliver("origin", "Build finished!", origin=src)

asyncio.run(notify())
2

With Configuration

Set home channels and deliver by alias:
botos.configure_channels({
    "telegram": {"home_channel": "123456", "aliases": {"ops-alerts": "123456"}},
})

await botos.deliver("telegram", "Nightly digest ready")
await botos.deliver("ops-alerts", "Disk usage at 90%")

How It Works

TargetResolves to
originChat that triggered the request (origin=SessionSource(...))
<platform>Platform home channel from /sethome or config
<platform>:<id>Explicit channel ID
<alias>Friendly name from configure_channels or overlay file
Resolution order: originplatform:id → bare platform → alias. Platform names win over aliases. Home and observed channels persist to ~/.praisonai/state/channel_directory.json.

Configuration Options

YAML

channels:
  telegram:
    token: ${TELEGRAM_BOT_TOKEN}
    home_channel: "123456"
    aliases:
      ops-alerts: "123456"

Alias overlay

Pre-name channels in ~/.praisonai/state/channel_aliases.json:
{
  "engineering": { "platform": "discord", "channel_id": "555" },
  "ops": "slack:C111"
}
Call botos.delivery_router.refresh_directory() periodically so adapters enumerate channels the bot has not yet heard from.

Rate Limiting

Scheduled and background sends share the reply-path rate limiter automatically — no config change required. Scheduled sends also fire at most once per due window across multiple BotOS processes — see BotOS → Multi-Process / HA Deployments.
You callWhat happens
botos.deliver("ops-alerts", "...")Rate-limited per platform via the shared reply-path rate limiter.
botos.deliver("ops-alerts", "...", origin=source)Rate-limited with origin context; used for targeted proactive replies.
Adapter’s send_message() returns FalseTreated as a transient failure. Dead-target flag not tripped. Safe to retry.
# Scheduled daily digest — proactive send to a named channel
await botos.deliver(
    "ops-alerts",
    "Nightly digest ready",
)
# Targeted proactive send with origin context
await botos.deliver(
    "ops-alerts",
    "Build finished",
    origin=source,
)

Best Practices

Aliases survive renumbering and read better in logs.
Bare-platform targets fail without a configured home channel.
telegram as an alias will never resolve — platform lookup wins.
deliver() returns False on resolution or send failure — log and retry as needed.
BotOS.deliver rate-limits sends via the shared reply-path rate limiter, but does not support idempotency deduplication. For dedup across retries or workers, use the reply-path delivery.send(...) outbox (see Durable Delivery).

BotOS

Multi-platform orchestration

Bot Gateway

Run multiple bots from one server