Run agents via the API

Start an agent run and stream its events over Server-Sent Events.

Running an agent is different from running a task: an agent takes turns, calls tools, and can pause for approval, so its run streams back as Server-Sent Events rather than returning a single response body.

POST https://app.rightbrain.ai/api/v1/org/{org_id}/project/{project_id}/task-agent/{agent_id}/run

The response is a text/event-stream. All requests use bearer authentication — see Authentication.

Request body

FieldRequiredDescription
messageYesThe user message to send to the agent this turn.
session_idNoContinue an existing conversation. Omit to start a new session.
referenceNoYour own correlation string (max 64 chars).
context_idNoGroup related runs under a shared context ID (max 64 chars).

For a new session, select a revision with the revision_id query parameter; otherwise an active revision is selected. Existing sessions stay pinned to their original revision.

Stream a run

Set RB_TOKEN, RB_ORG, RB_PROJECT, and RB_AGENT to your credential and resource IDs. These examples send a review-triage message; change it to match your agent. Python requires httpx; TypeScript uses the built-in fetch in Node.js 22+.

curl --fail-with-body -N -X POST "https://app.rightbrain.ai/api/v1/org/$RB_ORG/project/$RB_PROJECT/task-agent/$RB_AGENT/run" \
-H "Authorization: Bearer $RB_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: text/event-stream" \
-d '{"message": "Triage this review: My toaster exploded during breakfast and set the bread on fire."}'

HTTP success only means the stream opened. The cURL example prints events; its exit code does not tell you whether the agent completed. The Python and TypeScript readers return completed on done, return waiting_for_human on approval_required, and raise an error on a run failure or unexpected end of stream. formatted_output.content is a string; parse it separately if your formatter produces JSON.

The event stream

Each event is one SSE frame: a line beginning with data: followed by a JSON object, terminated by a blank line. The JSON always carries an event_type; the fields populated depend on the type.

event_typeMeaningKey fields
session_idFirst event of the stream; carries the session to reuse for the next turn.metadata.session_id
textA chunk of the agent’s natural-language response.content
tool_callThe agent invoked a Task, Integration, MCP, or registered tool.tool_name, tool_display_name, tool_args, tool_call_id
tool_resultA tool returned a result.tool_name, tool_result, tool_outcome (success or error), tool_call_id
formatted_outputThe run’s structured output, produced by the output-formatter tool.content
approval_requiredA gated tool needs human approval; the run is now waiting_for_human.metadata (approval request details)
errorThe run failed.error
doneTerminal event; the run finished.metadata (run_id, session_id, duration_ms, total_tokens)

A representative sequence:

Event stream
data: {"event_type": "session_id", "metadata": {"session_id": "01909843-3596-da54-4756-28af46917e74"}}
data: {"event_type": "tool_call", "tool_name": "summarize_tickets", "tool_display_name": "Summarize tickets", "tool_args": {"month": "July"}, "tool_call_id": "call_01"}
data: {"event_type": "tool_result", "tool_name": "summarize_tickets", "tool_outcome": "success", "tool_call_id": "call_01", "tool_result": {"summary": "..."}}
data: {"event_type": "text", "content": "Here is the summary of this month's tickets..."}
data: {"event_type": "formatted_output", "content": "{\"summary\": \"...\", \"top_themes\": [\"billing\", \"latency\"]}"}
data: {"event_type": "done", "metadata": {"run_id": "0195d207-32bb-d03d-cfdc-f4516e9222c8", "session_id": "01909843-3596-da54-4756-28af46917e74", "duration_ms": 8421, "total_tokens": 5120}}

A run has one of four statuses: running, waiting_for_human, completed, or failed. Only completed confirms successful completion. A tool error is a tool outcome that the agent may handle; an error event is a run failure.

A client disconnect cancels the live execution. Do not automatically repeat the POST after a disconnect: inspect the recorded run and session first, because tools may already have executed. The stream does not support replay via Last-Event-ID. The approval /resume endpoint returns the same SSE format and can use the same readers.

If the stream ended before returning a run ID, list runs with ?session_id=<session_id> using the session ID from the first event. Check status, termination_reason, and the tool execution records. A disconnected run can be recorded as failed with termination_reason: "client_disconnect". Continuing that session starts another run; it does not resume the cancelled execution. Reconcile any completed tool actions before submitting the next turn.

An HTTP 200 stream can also end with error and no done, for example when an output formatter cannot resolve an uploaded file. Treat that as failure and inspect its error metadata and the stored run. Do not wait for a completion event after a terminal error.

Multi-turn sessions

The first session_id event and the final done event both carry the session ID. Pass it back as session_id on the next run to continue the same conversation with its full history intact.

cURL
curl -N -X POST https://app.rightbrain.ai/api/v1/org/{org_id}/project/{project_id}/task-agent/{agent_id}/run \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"message": "Now break that down by product area.", "session_id": "01909843-3596-da54-4756-28af46917e74"}'

Manage sessions directly:

Session endpoints
GET .../task-agent/{agent_id}/session list sessions
GET .../task-agent/{agent_id}/session/{session_id} fetch a session
DELETE .../task-agent/{agent_id}/session/{session_id} delete a session

Approval pauses

If a tool is configured to require approval, the run emits an approval_required event and its status becomes waiting_for_human. The stream ends without a done event. Approval records the decision; call /resume separately to execute the approved tool and continue the run. Rejection follows the tool’s configured behavior. See Approvals (HITL) for the full lifecycle.

Attach input files

Send files with a run the same two ways a task does.

Add a files array. Each entry has base64 content and a filename.

Request body
{
"message": "Analyze this document",
"files": [{ "filename": "report.pdf", "content": "<base64-encoded bytes>" }]
}

Runtime-generated files

A run also has a file registry for files acquired or produced after execution starts. A producer tool stores the bytes once and returns a run-scoped file reference. A later Task tool can consume that reference as file input without copying binary content into the prompt or through each tool response.

File promotion is explicit and format-aware; arbitrary base64-shaped tool output is not treated as a file. Input files and runtime-generated files remain distinguishable in the run record.

The run’s top-level files array contains file metadata and provenance, including whether each file was an input or generated by a Task tool. A paused approval run retains its file registry when resumed. Use the run file endpoint to download a retained file.

See Tasks for direct model file input and Input processors when a file must be converted before the Task model runs.

Retrieve a run after the fact

The stream is the live view. To read a completed run’s events or download files it produced, use the run endpoints — handy when a client disconnected mid-stream or you need the transcript later.

Run endpoints
GET .../task-agent/{agent_id}/run list runs (paginated)
GET .../task-agent/{agent_id}/run/{run_id} fetch a run
GET .../task-agent/{agent_id}/run/{run_id}/events fetch the run's events
GET .../task-agent/{agent_id}/run/{run_id}/file/{file_name} download a run file