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

Diagram

Per-Platform Display Policy

πŸ“‹ User Request

βš™οΈ Per-Platform Display Policy

βœ… Result

python
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.

Diagram

Per-Platform Display Policy

πŸ“ User Message

βš™οΈ Resolve Policy

πŸ€– Agent

βœ… Platform-shaped Reply

How It Works

Diagram
AgentDisplayPolicyChannelUserAgentDisplayPolicyChannelUserSend messageResolve platform settingsstreaming / tool_progress flagsReply shaped for this platform

Resolution Precedence

Diagram

Resolution Precedence (highest β†’ lowest)

1️⃣ display.platforms.<name>.<field>\nPer-platform override

2️⃣ display.<field>\nGlobal default

3️⃣ Platform-tier default\n(edit / work / noedit / batch)

4️⃣ Built-in default\n(streaming=’off’, tool_progress=’off’, …)

Quick Start

  1. 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()
  2. 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()
  3. 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.

  4. 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

Diagram
Per-Platform Display PolicyAgentUserPer-Platform Display PolicyAgentUserRequestProcess requestResultResponse
Diagram

Platform Tiers

πŸ“± edit\nTelegram, Discord\nstreaming=draft

⚑ work\nSlack, Linear\ntool_progress=inline

πŸ“„ noedit\nEmail, SMS\nstreaming=off

πŸ“¦ batch\nbulk delivery\nno interims

Resolution Precedence

1️⃣ display.platforms.<platform>

2️⃣ display.<global field>

3️⃣ Platform-tier default

4️⃣ Built-in default

The resolver applies this priority order for every field independently:

  1. Platform override β€” display.platforms.<platform> (matched case-insensitively, so {Telegram: ...} works for "telegram")
  2. Global field β€” the top-level DisplayPolicy field
  3. Platform-tier default β€” automatic default based on the channel’s tier (edit, work, noedit, batch)
  4. Built-in default β€” the hard-coded fallback

Configuration Options

FieldTypeDefaultDescription
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_messagesboolFalseWhether to send “thinking…” messages between tool calls
footer"off" \"compact""off"Append a compact attribution/source footer to replies
platformsdict[str, DisplayPolicy]{}Per-platform overrides; keys are matched case-insensitively

Platform Tiers

TierPlatformsDefault Behaviour
editTelegram, Discordstreaming="draft" β€” edits the message as content arrives
workSlack, Lineartool_progress="inline" β€” shows tool steps without streaming
noeditEmail, SMS, AgentMailstreaming="off" β€” waits for completion, sends one message
batchBulk broadcaststreaming="off", interim_assistant_messages=False

Common Patterns

Telegram with draft streaming

python
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

python
from praisonaiagents.bots import DisplayPolicy

display = DisplayPolicy(streaming="off", footer="compact")

Different settings per channel

python
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 result

Which option to choose?

Diagram

Chat apps\nTelegram / Discord

Work tools\nSlack / Linear

Email / SMS

Bulk broadcast

What channel?

streaming=draft

tool_progress=inline

streaming=off\nfooter=compact

noedit tier

interim_assistant_messages=True\nif long tool chains

Add interim_assistant_messages=True\nfor complex tasks


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