Skip to main content
POST
/
v1
/
agents
/
{agent_id}
/
invoke
/
stream
Invoke Agent (Stream)
curl --request POST \
  --url https://api.xpander.ai/v1/agents/{agent_id}/invoke/stream \
  --header 'Content-Type: application/json' \
  --header 'x-api-key: <api-key>' \
  --data '
{
  "input": {
    "text": "Explain the benefits of your product in detail"
  }
}
'
{
  "event": "task_created",
  "data": {
    "id": "task-uuid-12345",
    "agent_id": "agent-uuid-12345",
    "status": "running"
  }
}
Invoke an agent with real-time streaming via Server-Sent Events (SSE). Events fire as the agent works — you see tool calls, reasoning steps, and result chunks as they happen. Best for interactive UIs and chat applications.

Path Parameters

agent_id
string
required
Agent ID (UUID)

Request Body

The request body is identical to Invoke Agent (Sync). Only input.text is required.
input
object
required
id
string
Thread ID for multi-turn conversations. Pass the id from a previous task to continue the conversation.
disable_attachment_injection
boolean
default:"false"
When true, files in input.files are not injected into the LLM context window. See Invoke Sync: Processing Files.
think_mode
string
default:"default"
default or harder. Controls reasoning depth.
instructions_override
string
Additional instructions appended to the system prompt for this invocation only.
expected_output
string
Natural-language description of desired output

Query Parameters

version
string
Agent version to invoke. Defaults to latest deployed. Use "draft" to test undeployed changes.

Response Format

Returns Content-Type: text/event-stream. Each event is a JSON object prefixed with data: , separated by \n\n.

Event Types

Events are emitted in this order during a typical invocation:
task_created
event
Fired immediately. Contains the full task object with status: "pending".
task_updated
event
Fired when task status changes (e.g., to executing). Contains the updated task object.
think
event
Agent’s internal reasoning step. Contains the thought process as a string.
analyze
event
Agent’s analysis step before tool selection.
tool_call_request
event
Agent is calling a tool. Contains tool name, parameters, and reasoning.
tool_call_result
event
Tool returned a result. Contains the output from the tool.
chunk
event
A piece of the agent’s final response. Accumulate these to build the full result.
{"type": "chunk", "task_id": "...", "data": "partial response text..."}
task_finished
event
Task is done. Contains the complete task object with status, result, finished_at.
sub_agent_trigger
event
A sub-agent was triggered (multi-agent workflows).
plan_updated
event
Deep planning step was updated (when deep_planning is enabled on the agent).
auth_event
event
MCP connector requires authentication. Contains an auth URL the user must visit.

Basic Example

curl -s --no-buffer -X POST "https://api.xpander.ai/v1/agents/<agent-id>/invoke/stream" \
  -H "Content-Type: application/json" \
  -H "x-api-key: <your-api-key>" \
  -d '{"input": {"text": "Say hello in 5 words"}}'
Use --no-buffer (or -N) for real-time output.

Real Event Stream

Here’s what the actual SSE output looks like (from a live invocation):
data: {"type":"task_created","task_id":"c35476a3-...","time":"2026-02-07T10:14:48.466Z","data":{"id":"c35476a3-...","status":"pending","agent_id":"<agent-id>",...}}

data: {"type":"task_updated","task_id":"c35476a3-...","time":"2026-02-07T10:14:49.100Z","data":{"id":"c35476a3-...","status":"executing",...}}

data: {"type":"chunk","task_id":"c35476a3-...","time":"2026-02-07T10:14:50.200Z","data":"Hello there, nice to"}

data: {"type":"chunk","task_id":"c35476a3-...","time":"2026-02-07T10:14:50.300Z","data":" meet you!"}

data: {"type":"task_finished","task_id":"c35476a3-...","time":"2026-02-07T10:14:51.000Z","data":{"id":"c35476a3-...","status":"completed","result":"Hello there, nice to meet you!",...}}

Consuming the Stream (Node.js)

const response = await fetch(
  'https://api.xpander.ai/v1/agents/<agent-id>/invoke/stream',
  {
    method: 'POST',
    headers: {
      'x-api-key': '<your-api-key>',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      input: { text: 'Your task here' }
    })
  }
);

const reader = response.body.getReader();
const decoder = new TextDecoder();

while (true) {
  const { done, value } = await reader.read();
  if (done) break;

  const lines = decoder.decode(value).split('\n');

  for (const line of lines) {
    if (!line.startsWith('data: ')) continue;

    const event = JSON.parse(line.slice(6));

    switch (event.type) {
      case 'chunk':
        // Stream text to UI as it arrives
        process.stdout.write(event.data);
        break;
      case 'tool_call_request':
        console.log(`\n[Tool: ${event.data?.tool_name}]`);
        break;
      case 'task_finished':
        console.log('\n\nDone:', event.data.result);
        break;
    }
  }
}

Consuming the Stream (Python)

import requests
import json

response = requests.post(
    'https://api.xpander.ai/v1/agents/<agent-id>/invoke/stream',
    json={'input': {'text': 'Your task here'}},
    headers={
        'x-api-key': '<your-api-key>',
        'Content-Type': 'application/json'
    },
    stream=True
)

for line in response.iter_lines():
    if not line:
        continue
    line = line.decode('utf-8')
    if not line.startswith('data: '):
        continue

    event = json.loads(line[6:])

    if event['type'] == 'chunk':
        print(event['data'], end='', flush=True)
    elif event['type'] == 'tool_call_request':
        print(f"\n[Calling tool: {event['data'].get('tool_name', 'unknown')}]")
    elif event['type'] == 'task_finished':
        print(f"\n\nDone. Status: {event['data']['status']}")

Notes

  • Use curl --no-buffer or curl -N for real-time terminal output
  • The stream ends after the task_finished event — close the connection at that point
  • chunk events contain raw text fragments; concatenate them for the full response
  • tool_call_request and tool_call_result events let you show tool usage in your UI
  • think and analyze events show the agent’s reasoning (useful for debugging and transparency)
  • For multi-turn conversations, wait for task_finished before sending the next message with the same id

See Also

Authorizations

x-api-key
string
header
required

API Key for authentication

Path Parameters

agent_id
string
required

Body

application/json
input
AgentExecutionInput · object
required

The input to send to the agent

id
string | null

Thread ID for multi-turn conversations. Pass the id from a previous task to continue the conversation.

expected_output
string | null

Natural-language description of the desired output

think_mode
enum<string> | null

Controls the agent's reasoning depth. "default" for standard reasoning, "harder" for deeper analysis.

Available options:
default,
harder
disable_attachment_injection
boolean | null

When true, files in input.files are not injected into the LLM context window

instructions_override
string | null

Additional instructions appended to the agent's system prompt for this invocation only. Use this to adjust behavior per-request without changing the agent's configuration.

Response

Successful Response