POST /v1/orchestrate/runs/stream, most agent responses arrive synchronously as SSE events. However, when the agent triggers an async flow (a tool flow that runs asynchronously), the stream pauses and the agent sends a holding message. Your application must detect this condition and poll the message thread until the flow completes and the agent resumes.
This guide explains how to detect the async flow condition and how to poll for messages correctly.
This pattern applies only to applications that consume the watsonx Orchestrate chat API directly. If you use the embedded chat widget, the widget handles async flow polling automatically.
How async flows work
When the agent starts an async flow during a streaming run:- The SSE stream emits a
flow.slot.listenevent containing thethread_id. - The stream ends — no further
message.deltaevents arrive on this connection. - The flow runs asynchronously. The thread status changes to
async_wait. - When the flow needs user input (for example, a form or confirmation), the thread status changes to
async_slot_request. - When the flow completes, new messages are appended to the thread and the thread status returns to
ready.
Step 1 — Start a streaming run and capture the thread ID
Send a message toPOST /v1/orchestrate/runs/stream. Include the thread_id from the previous turn if you are continuing a conversation; omit it for a new conversation.
Step 2 — Detect the async flow condition
Check the return value ofstream_run. When flow_started is True, the agent has handed off to a flow and you must poll.
Step 3 — Poll for new messages
PollGET /v1/orchestrate/threads/{thread_id}/messages at a regular interval. Compare the message list with what you already have and display any new messages as they appear.
The flow is still running while the thread status is async_wait. When the flow needs user input, the status changes to async_slot_request — this is your cue to prompt the user. When the status returns to ready, the flow has completed.
Putting it together
Thread status reference
SSE event reference
Notes
- The
flow.slot.listenevent is the definitive signal that async polling is required. Do not rely on the absence of furthermessage.deltaevents as the detection mechanism. - The WebSocket-based notification API (equivalent to how the native chat UI receives live flow updates) is not yet available for external API consumers. Polling
/messagesis the supported approach. - Poll intervals of 1–3 seconds are appropriate for most flows. Avoid polling faster than once per second.
- Always use the
thread_idreturned in the SSE events — do not cache or infer it from elsewhere.

