Textual Status Line
Live progress on channels that can't edit messages or add reactions
Channels that can neither edit messages nor add reactions (email, SMS, IRC, many webhook transports) can show a short, replaceable status line such as 🔍 Searching the web… while the agent works. Without it, the user sees nothing until the final answer.
from praisonaiagents import Agent
agent = Agent(name="assistant", instructions="Help the user research the web.")
agent.start("Find the latest release notes for Python.")On a channel that opts in, the user sees 🤔 Thinking..., then an activity line such as Searching the web…, then the final answer. The status line clears when the turn ends.
Quick Start
- Use auto or progress streaming
You don’t need to change the agent. Set streaming to
auto(orprogress) on the channel, the same way as for any other bot.yaml channels: my_sms: streaming: mode: auto activity_status: enabled: true phrases: web: "Searching the web…" default: "Working on it…"activity_statusis optional. Without it the line reads🤔 Running <tool>..., which shows the raw tool name. - Opt in from your adapter
Your adapter needs three things: it reports that it can’t edit, it sets
supports_status_text=True, and it has anasync set_status_text(channel_id, text)method.python import asyncio from praisonaiagents.bots import PlatformCapabilities from praisonai_bot.bots import DraftStreamer, StreamingConfig, StreamingMode class SmsAdapter: """A channel that can't edit messages or add reactions.""" capabilities = {"live_edit": False, "reactions": False} platform_capabilities = PlatformCapabilities(supports_status_text=True) async def set_status_text(self, channel_id: str, text: str) -> None: # Empty text means the turn is over: clear the line. print(f"[status] {text or '(cleared)'}") async def send_message(self, channel_id, content, reply_to=None, thread_id=None): print(f"[message] {content}") async def main(): streamer = DraftStreamer( adapter=SmsAdapter(), channel_id="+15551234567", config=StreamingConfig(mode=StreamingMode.AUTO), ) await streamer.start() # status: 🤔 Thinking... await streamer.finalize("Here is your answer.") # message, then status cleared asyncio.run(main())Output:
text [status] 🤔 Thinking... [message] Here is your answer. [status] (cleared)
How It Works
| Step | What happens |
|---|---|
start() | No placeholder message is sent. placeholder_text becomes the first status line. |
| Tool events | The curated activity line is pushed with set_status_text. |
finalize() | The full answer goes out with send_message, split into chunks as usual. Then the status line is cleared with an empty string. |
The streamer logs Channel <id> can't edit; routing streaming mode '<mode>' to status text at INFO when this mode is active.
Choosing a surface
Each channel uses the best surface it supports:
draft is never switched to a status line. Choosing draft means you want in-place edits, so on a channel that can’t edit it still falls back to off.
When to enable
| Channel type | Where the status line can go |
|---|---|
| A draft subject or header | |
| SMS | A short interim notice or carrier status field |
| IRC | Channel topic or a status bar |
| Custom / webhook | Any replaceable field your transport exposes |
Configuration Options
| Option | Type | Default | Description |
|---|---|---|---|
supports_status_text | bool | False | Turns on the status-text surface for the adapter (a field on PlatformCapabilities). |
There is no new StreamingConfig field. The behaviour comes only from the capability flag and the method being present.
Required method
async def set_status_text(self, channel_id: str, text: str) -> None: ...- An empty
textclears the line when the turn ends. - The method is not part of
BotProtocol. It is optional and checked at runtime withcallable(...). Adding it to the@runtime_checkableprotocol would makeisinstance(adapter, BotProtocol)fail for every existing adapter. - If the flag is
Truebut the method is missing, the channel falls back tooff, the same as before.
Behaviour details
- Only
autoandprogressuse the status line.draftfalls back tooffon channels that can’t edit. - If a status line hasn’t changed, it isn’t sent again, so there are no extra API calls.
- The multi-line
progress_style: feedis not used here. You get a single line. - Status updates share the edit rate limiter and flood backoff (
disable_progressive_edits_after,flood_backoff_factor,max_interval). - If
set_status_textfails, the turn carries on and the final answer is still delivered. - With the default
supports_status_text=False, nothing changes: channels that can’t edit stay silent until the answer arrives.
Privacy
The status line uses the same activity line as progress mode. Set activity_phrases and tool names, arguments, URLs and file paths never reach the user. Outbound redaction (redact_outbound_text) runs before every push.
Best Practices
Prefer a status line over nothing
If an email, SMS, or IRC channel can carry a short header or subject-like field, opt in. Several minutes of silence makes users think the bot is broken.
Don't deduplicate in the adapter
The streamer already skips unchanged lines, so your adapter can forward every call straight to the provider.
Treat empty text as end of turn
The streamer sends "" after the final answer. Remove the line instead of showing a blank status.
Fail quietly
Raise or log inside set_status_text if the provider rejects an update. The streamer catches the error, logs it at debug level, and still delivers the final answer.