Streaming Progress Feed

Multi-line rolling status feed for tool progress during streaming

Replace the single overwritten tool line with a bounded, multi-line rolling status feed.

text
# Before — one overwritten line, looks frozen on long runs
🤔 Running web_search...

# After (progress_style="feed") — stable, in-place rolling feed
✓ web_search — 5 results
⏳ fetch_url
⏳ write_file — report.md
Diagram

📨 StreamEvent stream

🔀 merge_progress_line
state fold

📐 render_progress
bounded window

✏️ edit-in-place message

The compositor is a pure transform: ⏳ running, ✓ done, ✗ error.

Quick Start

  1. Turn it on for a bot

    Set progress_style: feed under a channel’s streaming block in your bot YAML:

    yaml
    channels:
      telegram:
        token: ${TELEGRAM_BOT_TOKEN}
        streaming:
          mode: progress
          progress_style: feed
  2. Tune the window

    Cap how many lines and characters the feed shows:

    yaml
    channels:
      telegram:
        token: ${TELEGRAM_BOT_TOKEN}
        streaming:
          mode: progress
          progress_style: feed
          progress_max_lines: 8
          progress_max_line_chars: 120
  3. Build your own renderer

    The core compositor is pure and reusable — fold events, then render:

    python
    from praisonaiagents.streaming import ProgressLine, merge_progress_line, render_progress
    
    lines = []
    for event in agent_events:
        lines = merge_progress_line(lines, event)
    
    print(render_progress(lines, max_lines=8, max_line_chars=120))

How It Works

Events fold by correlation id, so the same tool’s line advances in place from running to done or error.

Diagram
Draft editrender_progressmerge_progress_lineAgentDraft editrender_progressmerge_progress_lineAgentTOOL_CALL_START (id=1)⏳ web_searchedit messageTOOL_CALL_END (id=1)✓ web_search — 5 resultsedit message

The same correlation id updates the same line in place. Terminal states are sticky: once a line is error (or done), a late running event never downgrades it back.


Configuration Options

The streaming block accepts these keys per channel. Defaults preserve today’s single-line behaviour exactly.

OptionTypeDefaultDescription
progress_style`”line” \“feed”`"line"Legacy overwritten line vs. new multi-line feed.
progress_max_linesint8Trailing lines shown in feed style.
progress_max_line_charsint120Per-line cap; word-aware truncation.

The core render_progress function takes the same limits as keyword arguments max_lines and max_line_chars.


State Semantics

Each event type maps a line to a state and glyph.

Event typeLine stateGlyph
TOOL_CALL_START / DELTA_TOOL_CALLrunning⏳
TOOL_CALL_END / TOOL_CALL_RESULTdone✓
TOOL_PROGRESSrunning (command-output kind)⏳
ERRORerror (terminal, sticks)✗

A ProgressLine carries id, kind (tool, plan, approval, or command-output), text, and state (running, done, or error).


Best Practices

Use feed for long multi-tool turns

The rolling feed shines when a turn calls several tools. Short single-tool turns are fine with the default line style.

Keep max_lines small on chat platforms

Chat platforms rate-limit message edits. A small progress_max_lines keeps the rendered feed compact and edit-friendly.

Log errors even though the feed shows them

The feed renders ✗ for errors, but keep your own error logging — the feed is a bounded rolling view, not a durable audit trail.

Reuse the pure compositor anywhere

merge_progress_line and render_progress are pure and dependency-free, so you can render progress in a TUI, web UI, or tests without any transport.


Related