Chat & Streaming
Send messages, stream replies, and read tool cards in the Desktop app
Every reply streams live from your local agent β text, reasoning, tool cards, and usage all arrive as typed events over 127.0.0.1.
from praisonaiagents import Agent
agent = Agent(
name="Assistant",
instructions="You are a helpful assistant.",
)
# The Desktop app streams this agent's reply token-by-token.
agent.start("Write a haiku about the sea", stream=True)Quick Start
- Send your first message
Type in the composer and press
Enter. The reply streams in as the agent produces it. - Watch the events render
Text, a live reasoning panel, tool cards, and a usage line all appear in the same turn as they stream.
- Act on the turn
Hover a turn to Copy, Regenerate, Fork, or Delete it.
How It Works
The Desktop app opens POST /chat and streams these 11 event types straight into the turn β you write no client code for it.
from praisonaiagents import Agent
agent = Agent(
name="Assistant",
instructions="You are a helpful assistant.",
)
# The Desktop app opens POST /chat and streams these 11 event types
# straight into the turn β you write no client code for it.
agent.start("Summarize today's notes", stream=True)The engine sends Server-Sent Events on POST /chat.
Each event maps to one visible piece of the turn:
Every event carries a msg_id that scopes it to a specific assistant message; start additionally carries a run_id that scopes it to a specific run, so a POST /approve/{aid} or POST /cancel sent later addresses the right run and not whichever one happens to be pending. The vocabulary is exactly the 11 events below β a StreamProtocolVocabulary test in the engine fails CI if a new emitter or a new documented event ever drifts from that list, so this table stays a faithful mirror of the wire.
Every event the stream emits (from engine/server.py), with the exact payload a client sees on the SSE wire:
| Event | Payload | Rendered as |
|---|---|---|
start | {msg_id, run_id} | New assistant turn container |
reasoning | {msg_id, text} (incremental) | Live “Thinkingβ¦ Xs” panel (collapses to “Thought for Xs”) |
delta | {msg_id, text} | Streamed text into the current turn |
tool_drafting | {msg_id, name} | “Preparing tool⦔ state / argument preview inside a tool card |
tool_call | {msg_id, call_id, name, args} | Tool card (running dot) |
tool_result | {msg_id, call_id, name, ok, output, seconds} | Tool card result pane (tail-truncated with Show all + Copy output) |
approval_request | {msg_id, approval_id, call_id, name, args} | Approval card (Allow / Always allow / Deny) β human-in-the-loop gate |
usage | {msg_id, chars, seconds, ttft} | Chars, seconds, time-to-first-token under the reply |
cancelled | {msg_id, run_id} | “Stopped” indicator |
error | {msg_id, message, kind} | Typed error card β auth / rate_limit / no_answer / empty / internal |
end | {msg_id, user_index, assistant_index, versions, active} | Finalizes the turn |
Every event carries msg_id so the client can address a specific message rather than assuming the last one is live. Clients integrating with the SSE stream should handle all 11 events β a client written against a subset silently ignores the rest, and approval_request in particular will block the run invisibly until the 300 s approval timeout if the client does not render it.
Capabilities
Reasoning panel
When the model emits reasoning, a live “Thinkingβ¦ Xs” panel shows it and collapses to “Thought for Xs” when the turn ends. Toggle it with Show reasoning and Collapse reasoning by default in Settings.
Tool cards
A tool_call opens a card with a running dot; tool_drafting previews the arguments; tool_result fills the result pane. Long output is tail-truncated with Show all and Copy output. Tool cards remain visible even if the model produces no follow-up answer β a no_answer banner then explains what didn’t come back.
Attachments
Drop a file and the composer branches on its MIME type β images and PDFs reach a vision model as bytes, everything else folds into the prompt as text.
Drag-drop or use the + button. Chips show each file’s size. Limits: 2 MB max, up to 5 files.
- **Images (
image/*) and PDFs** are read as base64 and passed to the agent asattachments=[...], so a vision-capable model (gpt-4o,claude-3-,gemini-) sees the image itself β not a text description of it. Point the Desktop app at a text-only model and the image is ignored silently. - Text files are clipped to 100 kB of text and folded into the prompt, so long pastes condense into an attachment instead of filling the context.
Only text is stored in the turn’s history; the image bytes are ephemeral to the turn.
Cancel, regenerate, fork
Stop cancels a live run β the client is told explicitly with a cancelled event rather than inferring it from silence. Cancelling with Stop no longer double-reports as “No output” β a cancelled event is the only banner the user sees. Per-turn hover actions cover Copy, Regenerate, Fork (POST /fork/{cid}/{idx}), and Delete message (DELETE /messages/{cid}/{idx}).
Message Versions
Regenerating an answer keeps the previous one as a prior version on the same message, so you can compare without copying anything out.
- Regenerate sends
POST /chatwithregenerate_ofset to the message index, so the new answer is filed as another version instead of a duplicate question. - A
< 1/2 >picker appears on hover once a message has more than one version, opening at the newest. - Stepping through the picker calls
POST /version/{cid}/{idx}/{n}and repaints the chosen answer. - In the server payload every assistant row exposes
versions,active,version_count, andversion_active.
Message Queue
Typing while a turn is running queues your next message instead of interrupting it.
- The queued message sends automatically when the current turn finishes.
- Stop clears the queue rather than sending it β cancelling means “not this either”.
In-App Confirmation Dialogs
Destructive actions β delete conversation, delete-all, delete message β route through an in-app modal, not the browser’s window.confirm.
Keyboard Shortcuts
| Key | Action |
|---|---|
βN | New chat |
βK | Search all conversations |
β, | Open settings |
Enter | Send |
Shift+Enter | Newline |
Esc | Close overlay |