Skip to main content
Runs represent individual message exchanges with an agent. Each run streams events via Server-Sent Events (SSE) to provide real-time updates on the agent’s progress.

Send Message (Streaming)

Send a message to an agent session and receive a streaming response.
POST /v1/sessions/{session_id}/messages
Authorization: Bearer YOUR_API_TOKEN
Content-Type: application/json
Accept: text/event-stream
Path Parameters:
session_id
string
required
Session ID (e.g., ses_xyz789)
Request Body:
prompt
string
required
Message to send to the agent
Example Request:
{
  "prompt": "What's the weather like in San Francisco?"
}

Server-Sent Events (SSE)

The response is a stream of Server-Sent Events. Each event has a type and data field.

Event Format

event: message.delta
data: {"content":"Hello"}

event: tool.start
data: {"tool":"get_weather","input":{"city":"San Francisco"}}

event: run.completed
data: {"duration_ms":1234}

Run Event Types

message.delta

Streamed text chunk from the agent’s response.
type
string
required
Always "message.delta"
data.content
string
Text content to append to the response
Example:
{
  "type": "message.delta",
  "data": {
    "content": "The weather in San Francisco is "
  }
}

tool.start

Agent started using a tool.
type
string
required
Always "tool.start"
data.tool
string
Name of the tool being invoked
data.input
unknown
Input parameters passed to the tool
Example:
{
  "type": "tool.start",
  "data": {
    "tool": "get_weather",
    "input": {
      "city": "San Francisco",
      "units": "celsius"
    }
  }
}

tool.end

Tool invocation completed.
type
string
required
Always "tool.end"
data.duration_ms
number
Tool execution time in milliseconds
Example:
{
  "type": "tool.end",
  "data": {
    "duration_ms": 342
  }
}

run.started

Run has started processing.
type
string
required
Always "run.started"
data
object
required
Empty object or metadata
Example:
{
  "type": "run.started",
  "data": {}
}

run.completed

Run finished successfully.
type
string
required
Always "run.completed"
data.duration_ms
number
Total run duration in milliseconds
data.max_turns_reached
boolean
Whether the agent hit its maximum turn limit
data.max_turns_message
string
Message explaining the turn limit if reached
Example:
{
  "type": "run.completed",
  "data": {
    "duration_ms": 5432,
    "max_turns_reached": false
  }
}

run.failed

Run encountered an error.
type
string
required
Always "run.failed"
data.error.message
string
Error message describing what went wrong
Example:
{
  "type": "run.failed",
  "data": {
    "error": {
      "message": "Agent exceeded memory limit"
    }
  }
}

run.cancelled

Run was cancelled by the user or system.
type
string
required
Always "run.cancelled"
data
object
required
Empty object or cancellation metadata
Example:
{
  "type": "run.cancelled",
  "data": {}
}

status

General status update from the agent.
type
string
required
Always "status"
data
object
required
Status information (structure varies)

heartbeat

Keep-alive event to prevent connection timeout.
type
string
required
Always "heartbeat"
data
object
required
Empty object

TypeScript Example

import { parseSSEStream } from './streaming'

const response = await fetch(
  'https://api.superserve.ai/v1/sessions/ses_xyz789/messages',
  {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer YOUR_API_TOKEN',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ prompt: 'Hello!' })
  }
)

for await (const event of parseSSEStream(response)) {
  if (event.type === 'message.delta') {
    process.stdout.write(event.data.content ?? '')
  } else if (event.type === 'tool.start') {
    console.log(`\nUsing tool: ${event.data.tool}`)
  } else if (event.type === 'run.completed') {
    console.log(`\nCompleted in ${event.data.duration_ms}ms`)
  }
}

Using the SDK

The Superserve SDK handles SSE parsing automatically:
import Superserve from '@superserve/sdk'

const client = new Superserve({ apiKey: 'YOUR_API_TOKEN' })

// Streaming
const stream = client.stream('my-agent', {
  message: 'Hello!'
})

for await (const chunk of stream.textStream) {
  process.stdout.write(chunk)
}

// One-shot (waits for full response)
const result = await client.run('my-agent', {
  message: 'Hello!'
})
console.log(result.text)

Error Responses

If the request fails before streaming starts, you’ll receive a standard HTTP error response:
status
number
HTTP status code
detail
string
Error message
details
object
Additional error context
Common Errors:
StatusMessage
401Not authenticated
404Session not found
422Invalid message format
429Rate limit exceeded
If streaming has already started, errors are communicated via run.failed events.

Build docs developers (and LLMs) love