Docs

SSE Streaming

Queue a message with POST /message, then read the reply from GET /sessions/{session_id}/stream. Every Server-Sent Event type explained.

Messaging is two steps: queue the message with POST /message, then read the reply from GET /sessions/{session_id}/stream as Server-Sent Events — text, tool calls and results as they happen.

POST /message returns {"success": true, ...} immediately. The reply only arrives on the stream.

• How It Works

1
POST /message
Body {"message": "..."} (1–5000 characters) with your JWT.
2
Open the stream
GET /sessions/{session_id}/stream with the same JWT. Use the session_id from authentication.
3
Parse events
Each event is a line data: {json}. Switch on type.
4
Stop on done
Close the connection when you receive a done event, then send the next message.

• Event Types

typeFieldsMeaning
tokencontentA chunk of reply text. Append chunks in order.
contentcontentA complete block of reply text (sent instead of tokens in some flows).
tool_callname, call_id, argumentsMara is calling a tool.
tool_call_startedtool_name, call_idA tool started running.
tool_call_finishedtool_name, call_idA tool finished running.
tool_call_completename, call_idThe tool call was recorded.
tool_responsename, call_id, outputThe tool result, e.g. a quote or a transaction to sign.
ui_hintchart_contextDisplay hint for the web app. Safe to ignore.
completionmessage, metricsThe reply is complete, with usage metrics.
done—End of stream. Close the connection.
errormessageSomething failed. The message is safe to show.
session_expiredsession_id, messageThe previous session timed out and a new one was created.

• Python Example

Python
import json, requests

H = {"Authorization": f"Bearer {token}"}
requests.post(f"{BASE}/message", headers=H,
              json={"message": "swap 10 USDC for ETH on Base"}).raise_for_status()

with requests.get(f"{BASE}/sessions/{session_id}/stream",
                  headers=H, stream=True) as r:
    for line in r.iter_lines(decode_unicode=True):
        if not line or not line.startswith("data: "):
            continue
        event = json.loads(line[6:])
        kind = event["type"]
        if kind in ("token", "content"):
            print(event["content"], end="", flush=True)
        elif kind == "tool_response":
            handle_tool_output(event["name"], event["output"])
        elif kind == "error":
            raise RuntimeError(event["message"])
        elif kind == "done":
            break

• Tips

Do not buffer the response — process lines as they arrive
Ignore event types you do not recognise; new ones may be added
Sessions expire after inactivity (410). Authenticate again and retry
Share this page