> ## Documentation Index
> Fetch the complete documentation index at: https://praison.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# 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

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    subgraph "Per-Platform Display Policy"
        Request[📋 User Request] --> Process[⚙️ Per-Platform Display Policy]
        Process --> Result[✅ Result]
    end

    classDef input fill:#6366F1,stroke:#7C90A0,color:#fff
    classDef process fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef output fill:#10B981,stroke:#7C90A0,color:#fff

    class Request input
    class Process process
    class Result output
```

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
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.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    subgraph "Per-Platform Display Policy"
        In[📝 User Message] --> Policy[⚙️ Resolve Policy]
        Policy --> Agent[🤖 Agent]
        Agent --> Out[✅ Platform-shaped Reply]
    end

    classDef input fill:#6366F1,stroke:#7C90A0,color:#fff
    classDef process fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef agent fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef output fill:#10B981,stroke:#7C90A0,color:#fff

    class In input
    class Policy process
    class Agent agent
    class Out output
```

## How It Works

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
sequenceDiagram
    participant User
    participant Channel
    participant DisplayPolicy
    participant Agent

    User->>Channel: Send message
    Channel->>DisplayPolicy: Resolve platform settings
    DisplayPolicy->>Agent: streaming / tool_progress flags
    Agent-->>User: Reply shaped for this platform
```

### Resolution Precedence

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph TB
    subgraph "Resolution Precedence (highest → lowest)"
        L1["1️⃣  display.platforms.&lt;name&gt;.&lt;field&gt;\nPer-platform override"]
        L2["2️⃣  display.&lt;field&gt;\nGlobal default"]
        L3["3️⃣  Platform-tier default\n(edit / work / noedit / batch)"]
        L4["4️⃣  Built-in default\n(streaming='off', tool_progress='off', ...)"]
        L1 --> L2
        L2 --> L3
        L3 --> L4
    end

    classDef high fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef mid fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef low fill:#6366F1,stroke:#7C90A0,color:#fff
    classDef base fill:#F59E0B,stroke:#7C90A0,color:#fff

    class L1 high
    class L2 mid
    class L3 low
    class L4 base
```

## Quick Start

<Steps>
  <Step title="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 theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    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()
    ```
  </Step>

  <Step title="Override One Field Globally">
    Turn off streaming for all platforms:

    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    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()
    ```
  </Step>

  <Step title="Override Per Platform">
    Enable a compact footer on Telegram only:

    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    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.
  </Step>

  <Step title="Use the DisplayPolicy Dataclass">
    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    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"
    ```
  </Step>
</Steps>

***

## How It Works

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
sequenceDiagram
    participant User
    participant Agent
    participant Feature as Per-Platform Display Policy

    User->>Agent: Request
    Agent->>Feature: Process request
    Feature-->>Agent: Result
    Agent-->>User: Response
```

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph TB
    subgraph "Resolution Precedence"
        P1["1️⃣ display.platforms.&lt;platform&gt;"]
        P2["2️⃣ display.&lt;global field&gt;"]
        P3["3️⃣ Platform-tier default"]
        P4["4️⃣ Built-in default"]
        P1 --> P2 --> P3 --> P4
    end

    subgraph "Platform Tiers"
        TE[📱 edit\nTelegram, Discord\nstreaming=draft]
        TW[⚡ work\nSlack, Linear\ntool_progress=inline]
        TN[📄 noedit\nEmail, SMS\nstreaming=off]
        TB[📦 batch\nbulk delivery\nno interims]
    end

    classDef step fill:#6366F1,stroke:#7C90A0,color:#fff
    classDef tier fill:#189AB4,stroke:#7C90A0,color:#fff

    class P1,P2,P3,P4 step
    class TE,TW,TN,TB tier
```

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

| 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`         |

<Note>
  String booleans (`"false"`, `"0"`) are parsed correctly in YAML/JSON config files, so `interim_assistant_messages: "false"` works as expected.
</Note>

***

## Common Patterns

### Telegram with draft streaming

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
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 theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents.bots import DisplayPolicy

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

### Different settings per channel

````python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
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?

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph TB
    Q{What channel?} -->|Chat apps\nTelegram / Discord| A[streaming=draft]
    Q -->|Work tools\nSlack / Linear| B[tool_progress=inline]
    Q -->|Email / SMS| C[streaming=off\nfooter=compact]
    Q -->|Bulk broadcast| D[noedit tier]
    A --> AA[interim_assistant_messages=True\nif long tool chains]
    B --> BB[Add interim_assistant_messages=True\nfor complex tasks]

    classDef q fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef a fill:#10B981,stroke:#7C90A0,color:#fff

    class Q q
    class A,B,C,D,AA,BB a
```

***

## Best Practices

<AccordionGroup>
  <Accordion title="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.
  </Accordion>

  <Accordion title="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.
  </Accordion>

  <Accordion title="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.
  </Accordion>

  <Accordion title="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.
  </Accordion>
</AccordionGroup>

***

## Related

<CardGroup cols={2}>
  <Card title="Messaging Bots" icon="robot" href="/docs/features/messaging-bots">
    Deploy agents across Telegram, Slack, Discord, WhatsApp, and more
  </Card>

  <Card title="Platform Capabilities" icon="sliders" href="/docs/features/bot-platform-capabilities">
    What each channel can render
  </Card>

  <Card title="Display System" icon="display" href="/docs/features/display-system">
    Terminal output and Rich rendering
  </Card>

  <Card title="Bot Streaming Replies" icon="zap" href="/docs/features/bot-streaming-replies">
    Configure streaming for individual bot sessions
  </Card>

  <Card title="Channel Capabilities" icon="settings" href="/docs/features/channel-capabilities">
    Platform capability flags and limits
  </Card>

  <Card title="Relay Transport" icon="network-wired" href="/docs/features/relay-transport">
    Route agent replies through an out-of-process connector
  </Card>
</CardGroup>
