SSE Events Reference¶
Complete reference for all Server-Sent Events emitted by the Nodexa streaming API (stream: true).
Event Format¶
Each event is sent as two lines followed by a blank line:
The stream ends with:
Heartbeat¶
Every 15 seconds of inactivity, a comment line is sent to keep the connection alive:
SSE comments (lines starting with :) are ignored by standard parsers.
Event Index¶
| Event | Description |
|---|---|
response.created |
Stream started, processing begins |
response.status |
Processing status update |
response.output_text.delta |
Text token from the assistant |
response.reasoning_summary_text.delta |
Reasoning summary token (reasoning models only) |
response.function_call_arguments.delta |
Partial function call arguments |
response.function_call_arguments.done |
Function call arguments complete |
response.output_item.added |
New output item added (message, mcp_call, handover, oauth_required) |
response.output_item.done |
Output item complete |
response.mcp_call.in_progress |
A server tool call is running (assistant or specialist) |
response.mcp_call.completed |
That tool call returned |
response.mcp_call.failed |
That tool call failed |
response.web_search_call.in_progress |
Web search starting |
response.web_search_call.searching |
Web search query submitted |
response.web_search_call.completed |
Web search results ready |
response.completed |
Response fully complete |
response.error |
Error occurred, stream closing |
Event Details¶
response.created¶
Emitted immediately when the platform starts processing the request.
{
"type": "response.created",
"response": {
"id": "resp_01234567-89ab-cdef-0123-456789abcdef",
"status": "in_progress"
}
}
| Field | Type | Description |
|---|---|---|
type |
string |
Always "response.created" |
response.id |
string |
Unique response ID for threading |
response.status |
string |
Always "in_progress" at this point |
Use case: Show a loading/typing indicator.
response.status¶
Emitted when internal processing status changes (e.g., the assistant decides to call tools, a tool runs, a specialist is consulted, the answer is regenerated on a fallback connector).
{
"type": "response.status",
"code": "tool_calling",
"message": "Calling 2 tool(s)",
"metadata": { "tools": ["get_forecast", "create_risk_alert"] }
}
| Field | Type | Description |
|---|---|---|
type |
string |
Always "response.status" |
code |
string |
Machine-readable status code (see below) |
message |
string |
Human-readable description, for logs — not localized |
metadata |
object |
Structured payload for the codes that carry one; absent for the others |
| Code | Meaning |
|---|---|
tool_calling |
The model asked for tools in this iteration. metadata.tools lists the server tools by name, one entry per call, in call order. Client-side function tools are not listed here: they reach you as function_call output items. |
tool_executing |
One server tool is running. metadata.toolName names it, metadata.callId identifies the call, metadata.arguments is the JSON the model asked with. Repeats while a slow tool runs (keepalive). A tool run by a consulted specialist adds metadata.specialistId / specialistName. |
tool_complete |
That call ended. Same metadata plus metadata.outcome: success, or error with metadata.error. The same call is also streamed as an mcp_call item, which is the shape to build a progress UI on. |
generating |
The model is producing output with nothing else on the wire (keeps the connection alive) |
regenerating |
The answer is being regenerated on a fallback connector; discard any interim items received so far |
iteration_limit |
The tool loop hit its iteration cap; the answer is whatever the model has produced |
Measuring what a turn did
A turn that consulted data and a turn that only chatted look the same in response.completed. The tool_calling events tell them apart: collect metadata.tools across the turn and you know which tools ran, without inspecting the user's text.
response.output_text.delta¶
Emitted for each text token. Concatenate all delta values to reconstruct the full text.
| Field | Type | Description |
|---|---|---|
type |
string |
Always "response.output_text.delta" |
delta |
string |
Token(s) to append to the current text buffer |
Use case: Append each delta to your text display buffer.
let textBuffer = '';
if (event.type === 'response.output_text.delta') {
textBuffer += event.delta;
updateUI(textBuffer);
}
response.reasoning_summary_text.delta¶
Emitted during the reasoning phase of models that expose a reasoning summary (e.g., OpenAI o1, o3-mini). These tokens represent the model's visible thinking process, not the final answer.
{
"type": "response.reasoning_summary_text.delta",
"delta": "The user is asking about the history of"
}
| Field | Type | Description |
|---|---|---|
type |
string |
Always "response.reasoning_summary_text.delta" |
delta |
string |
Reasoning summary token(s) |
Use case: Optionally display a "thinking..." section. These tokens arrive before response.output_text.delta events.
Note
Only emitted by reasoning models. Not present for standard chat models.
response.function_call_arguments.delta¶
Emitted as the model generates JSON arguments for a function call. Useful for showing a "preparing to call tool" indicator.
| Field | Type | Description |
|---|---|---|
type |
string |
Always "response.function_call_arguments.delta" |
delta |
string |
Partial JSON arguments string |
Use case: Display a tool-calling indicator in the UI.
response.function_call_arguments.done¶
Emitted when the function call arguments are fully assembled. This is the event that triggers client-side tool execution.
{
"type": "response.function_call_arguments.done",
"name": "get_weather",
"call_id": "call_abc123",
"arguments": "{\"city\": \"Paris\", \"unit\": \"celsius\"}"
}
| Field | Type | Description |
|---|---|---|
type |
string |
Always "response.function_call_arguments.done" |
name |
string |
Name of the function to call |
call_id |
string |
Unique ID for this call — include in function_call_output |
arguments |
string |
Complete JSON-encoded arguments string |
Use case: Parse arguments, execute the function, collect the call_id, then send a follow-up request. See Function Calling.
response.output_item.added¶
Emitted when the model adds a structured item to its output array. The item.type determines what kind of item it is.
Message item¶
{
"type": "response.output_item.added",
"item": {
"type": "message",
"role": "assistant",
"content": []
}
}
MCP call item¶
One server tool call of the turn, in the OpenAI Responses mcp_call shape — the item a ChatGPT-style progress UI draws a card for. Emitted for the assistant's own tools and for the tools a consulted specialist runs: server_label says who ran it ("assistant", or the specialist's name), and a specialist's call also carries specialist_id / specialist_name. The item is added with status: "in_progress", followed by response.mcp_call.in_progress while it runs and response.mcp_call.completed or response.mcp_call.failed when it ends, then response.output_item.done with the final item. output is always null: the tool result is the model's material, the answer is what the user gets.
{
"type": "response.output_item.added",
"output_index": 1,
"item": {
"type": "mcp_call",
"id": "mcp_01234567-89ab-cdef-0123-456789abcdef",
"status": "in_progress",
"server_label": "Analista de Operações Portuárias",
"specialist_id": "55425e00-124f-4a9e-9148-9d596578b9bf",
"specialist_name": "Analista de Operações Portuárias",
"name": "ClosureStudyController_getRiskTiers",
"arguments": "{\"port\":\"Santos\"}",
"output": null,
"error": null
}
}
| Field | Type | Description |
|---|---|---|
item.type |
"mcp_call" |
Identifies this as a server tool call |
item.id |
string |
Item id (mcp_<uuid>), the same across its lifecycle events |
item.status |
string |
in_progress, completed or failed |
item.server_label |
string |
Who ran the tool: "assistant" or the consulted specialist's name. Not an MCP server identifier today, so do not key server-specific behaviour on it |
item.name |
string |
Technical tool name, as the model called it (map it to your own label) |
item.arguments |
string |
JSON-encoded arguments the model produced |
item.output |
null |
Never sent. The tool result is the model's material and the one surface where a fetched secret could leak; the answer is what the user gets |
item.error |
string? |
Why the call failed, when status is failed |
item.specialist_id |
string? |
Present when a consulted specialist ran the tool |
item.specialist_name |
string? |
Present when a consulted specialist ran the tool |
Use case: show one activity row per call ("Consultando risco de fechamento…") and update it as the lifecycle events arrive. At the end, response.completed.output lists every mcp_call of the turn, which is how you know what the turn did without joining events. Client-side function tools are not mcp_call items: they stay function_call items, since you execute those.
Handover item¶
Emitted when control is transferred from one specialist agent to another.
{
"type": "response.output_item.added",
"item": {
"type": "handover",
"from_specialist": "General Assistant",
"to_specialist": "Technical Support",
"reason": "User is asking about API integration details"
}
}
| Field | Type | Description |
|---|---|---|
item.type |
"handover" |
Identifies this as a handover notification |
item.from_specialist |
string |
Display name of the specialist agent that was active |
item.to_specialist |
string |
Display name of the specialist agent that took over |
item.reason |
string |
Explanation of why the handover occurred |
Use case: Log routing information or show a "connecting you to [specialist agent]" notice.
OAuth required item¶
Emitted when a tool requires OAuth credentials that are not present in the request.
{
"type": "response.output_item.added",
"item": {
"type": "oauth_required",
"plugin_id": "plugin_abc123",
"plugin_name": "Google Calendar",
"provider_id": "google",
"required_scopes": ["https://www.googleapis.com/auth/calendar.readonly"],
"auth_url": "https://your-admin.example.com/oauth/google/authorize?state=xyz"
}
}
| Field | Type | Description |
|---|---|---|
item.type |
"oauth_required" |
Identifies this as an OAuth prompt |
item.plugin_id |
string |
Internal plugin identifier |
item.plugin_name |
string |
Human-readable plugin name |
item.provider_id |
string |
OAuth provider identifier (e.g., "google") |
item.required_scopes |
string[] |
OAuth scopes needed |
item.auth_url |
string |
URL to start the OAuth authorization flow |
Use case: Redirect the user to auth_url, then retry the request with the obtained token in x-user-tokens.
response.output_item.done¶
Emitted when an output item is fully assembled (after all delta events for that item).
{
"type": "response.output_item.done",
"item": {
"type": "message",
"role": "assistant",
"content": [
{
"type": "output_text",
"text": "The complete assembled response text."
}
]
}
}
| Field | Type | Description |
|---|---|---|
type |
string |
Always "response.output_item.done" |
item |
object |
The fully assembled output item |
response.mcp_call.in_progress¶
Emitted when a server tool call (an mcp_call item) is running. It repeats every few seconds while a slow tool runs, so the connection stays alive and a progress UI can keep the row active.
{
"type": "response.mcp_call.in_progress",
"item_id": "mcp_01234567-89ab-cdef-0123-456789abcdef",
"output_index": 1
}
| Field | Type | Description |
|---|---|---|
type |
string |
Always "response.mcp_call.in_progress" |
item_id |
string |
The mcp_call item this event belongs to |
output_index |
number |
Its position in the output array |
response.mcp_call.completed¶
Emitted when that tool call returned. response.output_item.done follows with the item at status: "completed".
{
"type": "response.mcp_call.completed",
"item_id": "mcp_01234567-89ab-cdef-0123-456789abcdef",
"output_index": 1
}
response.mcp_call.failed¶
Emitted when that tool call failed, or named a tool that does not exist. response.output_item.done follows with the item at status: "failed" and the same error. The assistant goes on with the answer, so a failed call is information for the UI, not the end of the response.
{
"type": "response.mcp_call.failed",
"item_id": "mcp_01234567-89ab-cdef-0123-456789abcdef",
"output_index": 1,
"error": "HTTP request failed (404)"
}
response.web_search_call.in_progress¶
Emitted when a web search tool is invoked and the search is about to begin.
| Field | Type | Description |
|---|---|---|
type |
string |
Always "response.web_search_call.in_progress" |
call_id |
string |
Unique identifier for this search call |
response.web_search_call.searching¶
Emitted when the search query has been determined and submitted.
{
"type": "response.web_search_call.searching",
"call_id": "ws_call_abc123",
"query": "latest AI regulation news 2024"
}
| Field | Type | Description |
|---|---|---|
type |
string |
Always "response.web_search_call.searching" |
call_id |
string |
Identifier for this search call |
query |
string |
The search query submitted |
Use case: Display "Searching for: [query]" in your UI.
response.web_search_call.completed¶
Emitted when search results are available and being incorporated.
| Field | Type | Description |
|---|---|---|
type |
string |
Always "response.web_search_call.completed" |
call_id |
string |
Identifier for this search call |
results_count |
number |
Number of search results found |
response.completed¶
Emitted when the full response is complete and the stream is about to close. Contains the complete response object.
{
"type": "response.completed",
"response": {
"id": "resp_01234567-89ab-cdef-0123-456789abcdef",
"object": "response",
"status": "completed",
"model": "asst_01234567-89ab-cdef-0123-456789abcdef",
"output_text": "The complete response text.",
"output": [
{
"type": "message",
"role": "assistant",
"content": [
{
"type": "output_text",
"text": "The complete response text."
}
]
}
],
"usage": {
"input_tokens": 12000,
"input_tokens_details": { "cached_tokens": 10400 },
"output_tokens": 350,
"output_tokens_details": { "reasoning_tokens": 0 },
"total_tokens": 12350
},
"created_at": 1700000000
}
}
| Field | Type | Description |
|---|---|---|
type |
string |
Always "response.completed" |
response.id |
string |
Unique response ID — save for conversation threading |
response.status |
string |
"completed" or "requires_action" |
response.output_text |
string |
Convenience field with full assembled text |
response.output |
array |
Full structured output array |
response.usage.input_tokens |
number |
Input tokens of every model call in the turn (tool loop and specialist consultations included) |
response.usage.input_tokens_details.cached_tokens |
number |
The share of input_tokens served from the provider's prompt cache. Present only when the provider reported it — absent means "not reported", never "nothing cached" |
response.usage.output_tokens |
number |
Output tokens, summed the same way |
response.usage.output_tokens_details.reasoning_tokens |
number |
Reasoning tokens inside output_tokens, when the provider reports them |
response.usage.total_tokens |
number |
input_tokens + output_tokens |
response.created_at |
number |
Unix timestamp |
The same usage object is returned on the non-streaming response. The totals are the ones the usage screen shows for the turn.
requires_action in response.completed
If response.status is "requires_action", the assistant called a client-side function tool and is waiting for results. You must execute the function and send a follow-up request. See Function Calling.
response.error¶
Emitted when a fatal error occurs during streaming. The stream closes after this event.
{
"type": "response.error",
"error": {
"type": "server_error",
"code": "upstream_timeout",
"message": "The LLM provider did not respond within the timeout period."
}
}
| Field | Type | Description |
|---|---|---|
type |
string |
Always "response.error" |
error.type |
string |
Error category (e.g., "server_error", "invalid_request_error") |
error.code |
string |
Machine-readable error code |
error.message |
string |
Human-readable error description |
See Errors for all error codes and their meanings.
Typical Event Sequence¶
Simple text response¶
response.created
response.output_item.added (type: message)
response.output_text.delta (repeated N times)
response.output_item.done
response.completed
[DONE]
Response with web search¶
response.created
response.web_search_call.in_progress
response.web_search_call.searching
response.web_search_call.completed
response.output_item.added (type: message)
response.output_text.delta (repeated N times)
response.output_item.done
response.completed
[DONE]
Response with specialist agent handover¶
response.created
response.output_item.added (type: handover)
response.output_item.done
response.output_item.added (type: message)
response.output_text.delta (repeated N times)
response.output_item.done
response.completed
[DONE]
Response requiring function call¶
response.created
response.output_item.added (type: function_call - not usually emitted separately)
response.function_call_arguments.delta (repeated)
response.function_call_arguments.done
response.completed (status: requires_action)
[DONE]