Skip to main content

Subscribe to Event SSE Stream

Subscribes to a real-time session event stream via SSE: assistant output messages, tool calls, and status changes. Upon connection, the server immediately sends a : connected comment line.

Prerequisites

A session must already be created. For details, see Create Session. {session_id} is in the format sesn_xxx....

Endpoint

GET /sessions/{session_id}/events/stream The request must include Accept: text/event-stream. Upon connection, the server immediately sends a : connected comment line, then pushes session events in real time.

Event envelope

The data field is a Message object with the following common fields:
FieldTypeDescription
objectstringAlways message
idstringEvent ID (prefix msg_ or out_). Clients use this ID for business-level deduplication
created_atstringISO 8601 timestamp
rolestringuser | assistant | tool
typestringEvent type, see table below
statusstringAlways completed
contentarrayContentBlock array, same structure as the send side
is_errorboolOnly on tool output events (tool_call_output / mcp_call_output), at the Message top level (not inside content[].data): true means the tool execution failed or was interrupted/rejected; data still contains at least call_id and output. Clients should read the top-level is_error to determine success and read data.output for the output
metadataobjectEvent additional information (such as thread_id, call_id, etc.)

Server-pushed event types

typeDescription
messageAssistant output message, can be streamed in chunks
tool_callBuilt-in tool call request
tool_call_outputBuilt-in tool execution result
tool_approval_requestTool approval request. Sent once only when a tool needs approval; data carries batch_id, call_id, name, arguments, and tool_type (builtin or mcp; MCP also includes server_label). Whether approval is needed is determined by this event
tool_approval_responseTool approval ruling (bidirectional: client submits upstream, server also replays downstream). Under requires_action, when a pure interrupt is sent, the server replays result=deny for each call in the batch not yet executed, paired with the corresponding *_call_output (is_error=true); this pairing is for display and audit only, best-effort — the pending set is still governed by pending_call_ids
function_callSelf-hosted function call request; requires client to backfill function_call_output
function_call_outputServer acknowledgment echo of received function result
mcp_callMCP tool call request
mcp_call_outputMCP tool execution result
session_statusSession status change (includes stop_reason, see below)
errorRuntime error event. Details are in the top-level error object (error.code / error.message), not in content[].data. Such errors are not synchronous 4xx responses of POST /sessions/{session_id}/events; observe via this stream or GET /events?types=error

session_status and stop_reason

data.content[0].data carries the specific status:
{
  "object": "message",
  "type": "session_status",
  "content": [{
    "type": "data",
    "data": {
      "session_status": "idle",
      "stop_reason": {"type": "end_turn"}
    }
  }]
}
  • session_status: running | idle | terminated
  • stop_reason only appears when the status transitions to idle, with three possible values:
    • {"type": "end_turn"}: Current turn completed normally (model ended on its own)
    • {"type": "requires_action", "pending_batch_id": "...", "pending_call_ids": ["..."]}: Waiting for tool approval. pending_batch_id and a non-empty pending_call_ids identify the current pending approval batch and calls; the pending set is governed by pending_call_ids
    • {"type": "retries_exhausted"}: Retries exhausted, current turn failed

Subscription example

curl -N "$AGENTSTUDIO_URL/sessions/sesn_xxx/events/stream" \
  -H "Authorization: Bearer $DASHSCOPE_API_KEY" \
  -H "Accept: text/event-stream"
Response (excerpt):
: connected

event: message
data: {"object":"message","id":"msg_001","created_at":"2025-10-24T08:15:30.500Z","role":"assistant","type":"message","status":"completed","content":[{"type":"text","text":"开始分析"}]}

event: message
data: {"object":"message","id":"out_8f2a","created_at":"2025-10-24T08:15:32.100Z","role":"assistant","type":"tool_call","status":"completed","content":[{"type":"data","data":{"name":"bash","arguments":{"command":"head -5 /mnt/session/uploads/sales.csv"},"call_id":"call_xxx"}}]}

:keepalive

event: message
data: {"object":"message","id":"msg_002","created_at":"2025-10-24T08:15:35.800Z","role":"assistant","type":"session_status","status":"completed","content":[{"type":"data","data":{"session_status":"idle","stop_reason":{"type":"end_turn"}}}]}

Delta streaming

By default, each event is delivered as a single complete Message (status: "completed") only after generation finishes. To stream text-type events (such as message and reasoning) chunk by chunk as they are generated, enable delta streaming for specific event types with the event_deltas[] query parameter at request time. This parameter can be repeated to declare multiple types; event types not declared are still delivered as a single complete Message.
curl -N --no-buffer --get "$AGENTSTUDIO_URL/sessions/sesn_xxx/events/stream" \
  -H "Authorization: Bearer $DASHSCOPE_API_KEY" \
  -H "Accept: text/event-stream" \
  --data-urlencode 'event_deltas[]=message' \
  --data-urlencode 'event_deltas[]=reasoning'
Once enabled, an event of a declared type is pushed as three kinds of frames in the following order; the client merges them into a single event by event_id:
Frame typeDescription
event_startEvent start frame. event.id is the id of the event's final complete Message, and event.type is the event type (message / reasoning); this frame itself carries no object / content
event_deltaDelta frame. event_id matches the event.id of event_start; delta.content is the newly added ContentBlock fragment, and delta.index is the content-block index
message / reasoningThe complete Message delivered when the event ends (object: "message", status: "completed"); content is the aggregated full content, identical to when delta streaming is off
event_delta frame fields:
FieldDescription
typeAlways event_delta
event_idID of the owning event, equal to the event.id of event_start and to the id of the final complete Message; used to merge delta frames into the corresponding event
delta.typeAlways content_delta
delta.indexIndex of the content block within the content array
delta.contentThe newly added ContentBlock fragment, e.g. {"type":"text","text":"…"}
Example stream (both reasoning and message have delta streaming enabled):
: connected

event: message
data: {"object":"message","status":"completed","id":"sevt_status_running_xxx","type":"session_status","content":[{"type":"data","data":{"session_status":"running"}}]}

event: message
data: {"type":"event_start","event":{"id":"msg_reasoning_xxx","type":"reasoning"}}

event: message
data: {"object":"message","status":"completed","id":"msg_reasoning_xxx","role":"assistant","type":"reasoning"}

event: message
data: {"type":"event_start","event":{"id":"msg_answer_xxx","type":"message"}}

event: message
data: {"type":"event_delta","event_id":"msg_answer_xxx","delta":{"type":"content_delta","index":0,"content":{"type":"text","text":"Quick"}}}

event: message
data: {"type":"event_delta","event_id":"msg_answer_xxx","delta":{"type":"content_delta","index":0,"content":{"type":"text","text":"sort is a divide-and-conquer algorithm."}}}

event: message
data: {"object":"message","status":"completed","id":"msg_answer_xxx","role":"assistant","type":"message","content":[{"type":"text","text":"Quicksort is a divide-and-conquer algorithm."}]}

event: message
data: {"object":"message","status":"completed","id":"sevt_status_idle_xxx","type":"session_status","content":[{"type":"data","data":{"session_status":"idle","stop_reason":{"type":"end_turn"}}}]}
To reassemble the text, accumulate each event_delta's delta.content in order by event_id + delta.index; the complete Message delivered when the event ends carries the aggregated full content and can be used for verification. A reasoning event may have only an event_start and a complete Message with no event_delta (the thinking preview carries no thinking text).
Flow Agent API
Sandbox API
RAG API
Long-term Memory
ParseX API
Security API
Framework Integration