Per-Platform Display Policy
Control verbosity per chat platform β stream on Telegram, post discrete steps on Slack, send a single final message for Email/SMS
from praisonaiagents import Agent
agent = Agent(name="assistant", instructions="Answer helpfully on chat platforms.")
agent.start("What is the status of order #42?")DisplayPolicy lets operators control how agent output is presented on each channel β streaming partial answers, showing tool progress, or sending a single final message β without touching adapter code.
The user messages the bot on a channel; display policy controls streaming, tool progress, and final message shape per platform.
How It Works
Resolution Precedence
Quick Start
- Use Platform Defaults (No Config)
Zero configuration: Telegram streams replies live, Slack posts discrete steps, Email sends one final message. Platform-tier defaults do the right thing automatically:
python from praisonaiagents import Agent from praisonai.bots import TelegramBot agent = Agent( name="Assistant", instructions="Answer questions helpfully.", ) bot = TelegramBot(token="YOUR_TOKEN", agent=agent) await bot.start() - Override One Field Globally
Turn off streaming for all platforms:
python from praisonaiagents import Agent, DisplayPolicy from praisonai.bots import TelegramBot, BotConfig config = BotConfig( display={"streaming": "off"} ) agent = Agent(name="Assistant", instructions="Answer questions.") bot = TelegramBot(token="YOUR_TOKEN", agent=agent, config=config) await bot.start() - Override Per Platform
Enable a compact footer on Telegram only:
python from praisonai.bots import BotConfig config = BotConfig( display={ "platforms": { "telegram": {"footer": "compact"}, "email": {"streaming": "off"}, } } )Platform keys are case-insensitive β
"Telegram","TELEGRAM", and"telegram"all match. - Use the DisplayPolicy Dataclass
python from praisonaiagents import DisplayPolicy from praisonaiagents.bots import resolve_display_policy policy = resolve_display_policy( "telegram", {"streaming": "draft", "platforms": {"telegram": {"footer": "compact"}}} ) print(policy.streaming) # "draft" print(policy.footer) # "compact" print(policy.tool_progress) # "off"
How It Works
The resolver applies this priority order for every field independently:
- Platform override β
display.platforms.<platform>(matched case-insensitively, so{Telegram: ...}works for"telegram") - Global field β the top-level
DisplayPolicyfield - Platform-tier default β automatic default based on the channel’s tier (
edit,work,noedit,batch) - Built-in default β the hard-coded fallback
Configuration Options
| Field | Type | Default | Description | ||
|---|---|---|---|---|---|
streaming | "off" \ | "draft" \ | "progress" | "off" | How to stream partial replies: off, show draft updates, or show progress markers |
tool_progress | "off" \ | "inline" | "off" | Whether to print tool-call progress inline during execution | |
interim_assistant_messages | bool | False | Whether to send “thinking⦔ messages between tool calls | ||
footer | "off" \ | "compact" | "off" | Append a compact attribution/source footer to replies | |
platforms | dict[str, DisplayPolicy] | {} | Per-platform overrides; keys are matched case-insensitively |
Platform Tiers
| Tier | Platforms | Default Behaviour |
|---|---|---|
edit | Telegram, Discord | streaming="draft" β edits the message as content arrives |
work | Slack, Linear | tool_progress="inline" β shows tool steps without streaming |
noedit | Email, SMS, AgentMail | streaming="off" β waits for completion, sends one message |
batch | Bulk broadcast | streaming="off", interim_assistant_messages=False |
Common Patterns
Telegram with draft streaming
from praisonaiagents import Agent
from praisonaiagents.bots import DisplayPolicy
agent = Agent(
name="assistant",
instructions="Be helpful",
display=DisplayPolicy(streaming="draft", interim_assistant_messages=True),
)Email with a compact footer
from praisonaiagents.bots import DisplayPolicy
display = DisplayPolicy(streaming="off", footer="compact")Different settings per channel
from praisonaiagents.bots import DisplayPolicy
display = DisplayPolicy(
streaming="off", # global default: no streaming
platforms={
"telegram": DisplayPolicy(streaming="draft"),
"discord": DisplayPolicy(streaming="draft"),
"slack": DisplayPolicy(tool_progress="inline"),
},
)
## Configuration Options
All four fields are set via the `display:` block in your bot config:
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `streaming` | `"off" \| "draft" \| "progress"` | `"off"` | When to surface partial assistant output: `"off"` (single final message), `"draft"` (edit in place), `"progress"` (compact status then final) |
| `tool_progress` | `"off" \| "inline"` | `"off"` | Whether to show tool-call progress markers: `"off"` (hidden) or `"inline"` (progress bubbles) |
| `interim_assistant_messages` | `bool` | `False` | Whether to send intermediate assistant messages before the final reply |
| `footer` | `"off" \| "compact"` | `"off"` | Runtime footer appended to replies: `"off"` or `"compact"` (e.g. `model Β· ctx% Β· cwd`) |
<Note>
`interim_assistant_messages` accepts string booleans from YAML/JSON/env: `"true"`, `"1"`, `"yes"`, `"on"` β `True`; `"false"`, `"0"`, `"no"`, `"off"` β `False`. Using `"off"` as a string evaluates to `False` (not `True`).
</Note>
---
## Platform Tiers and Built-in Defaults
Each platform maps to a tier that controls sensible defaults:
| Tier | Platforms | `streaming` | `tool_progress` | `footer` |
|------|-----------|-------------|----------------|---------|
| `edit` | Telegram, Discord | `"draft"` | `"off"` | `"off"` |
| `work` | Slack, Teams, Mattermost | `"off"` | `"inline"` | `"off"` |
| `noedit` | WhatsApp | `"off"` | `"off"` | `"off"` |
| `batch` | Email, SMS | `"off"` | `"off"` | `"off"` |
Platforms not listed above resolve to the built-in default (`streaming="off"`, all others `"off"` / `False`).
---
## Layered Resolution Diagram
```mermaid
graph TB
subgraph "Full Resolution Example for Telegram"
I1["Built-in default\nstreaming=off\ntool_progress=off\nfooter=off"]
I2["Tier 'edit' default\nstreaming=draft\ntool_progress=off\nfooter=off"]
I3["Global override\ndisplay: {streaming: 'progress'}"]
I4["Platform override\ndisplay.platforms.telegram:\n footer: 'compact'"]
RESULT["β
Resolved Policy\nstreaming=progress\ntool_progress=off\nfooter=compact"]
I1 -->|overridden by| I2
I2 -->|overridden by| I3
I3 -->|overridden by| I4
I4 --> RESULT
end
classDef layer fill:#6366F1,stroke:#7C90A0,color:#fff
classDef result fill:#10B981,stroke:#7C90A0,color:#fff
class I1,I2,I3,I4 layer
class RESULT resultWhich option to choose?
Best Practices
Trust the tier defaults β they're optimised per channel
Telegram in edit tier streams drafts which looks great; Email in batch tier correctly sends one final message. Only override when your use case genuinely differs from the tier default.
Use 'draft' only on edit-capable channels
streaming="draft" edits the original message in place. On channels without edit support (WhatsApp, Email) it falls through to the tier default β but explicitly setting "draft" on a batch channel is a misconfiguration.
Case-insensitive platform keys in config
Config keys like "Telegram", "TELEGRAM", or "telegram" all resolve to the same platform. This makes YAML configs more natural.
Layer selectively β don't repeat defaults
Only specify what you need to change. A global display: { streaming: "progress" } applies to all platforms, then per-platform overrides layer on top for specific exceptions.
Related
Deploy agents across Telegram, Slack, Discord, WhatsApp, and more
Platform CapabilitiesWhat each channel can render
Display SystemTerminal output and Rich rendering
Bot Streaming RepliesConfigure streaming for individual bot sessions
Channel CapabilitiesPlatform capability flags and limits
Relay TransportRoute agent replies through an out-of-process connector