TypeScript
What reply() does
conversation.reply(input) accepts a string, a piece of content, a list of content, or a stream. With a stream it:
- Turns the typing indicator on, and keeps it on (channels clear it after about 5 seconds).
- Reads text out of the stream as it arrives.
- Cuts a bubble at each natural break (below) and sends it while the model is still writing. Bubbles go out in order.
- Turns typing off when the stream ends, even if it failed.
Text goes out as markdown with
fallback: "auto", so channels without formatting get clean plain text.
The bubble rule (for any language)
Without the SDK, apply this rule to the model’s text and send each bubble withPOST /v1/conversations/{conversation_id}/messages, one after another, turning typing on (POST .../typing) before you start and every 4 seconds until you finish.
- A bubble ends at a paragraph break (a blank line), except after a lead-in line that ends with
:and between items of one list, unless the bubble is already past the channel’s soft length. - Past the soft length, a bubble ends at the next sentence end (
.,!,?or…followed by a space). - Never cut inside a fenced code block, unless the bubble would pass the channel’s hard limit; then cut at the last line break or space before it.
Use the event’s ID plus the bubble’s index as each send’s
Idempotency-Key (evt_...:0, evt_...:1), so retrying a failed reply never sends a bubble twice.
Showing work while the agent thinks
For tool calls, retrieval or anything slow before the first word:Related
- Content types: typing, read receipts and markdown per channel.
- Agent frameworks: full examples per framework.