Streaming Execution
Technical reference. This page is for integrations, advanced configuration, or platform operations. For portal tasks, start with the user guide.
Orqestra streams execution progress in real-time via Server-Sent Events (SSE). Consumers see step starts, tool calls, and completion as they happen instead of waiting for the full execution to finish.
How it works
POST /v1/execute returns a text/event-stream response when the request
includes Accept: text/event-stream. Browser and SDK consumers normally call
POST /v1/workloads/by-slug/{slug}/execute; the control-plane proxies that
stream from the runtime gateway. Each SSE frame contains a typed
ExecutionEvent:
| Event Type | When | Data Fields |
|---|---|---|
step.started | Before each step executes | step_type |
step.completed | After step succeeds | outcome, tokens_used |
step.failed | Step errors | error |
step.progress | Intra-step progress update | progress_type, progress_value, progress_detail |
agent.tool_call | Agent calls a tool | tool_name, turn |
agent.tool_result | Tool returns | tool_name, turn, success |
budget.warning | Token budget near limit | tokens_used, tokens_remaining |
execution.completed | Execution finishes | outcome, total_tokens |
stream.error | Stream terminated by guard | error, optional max_bytes |
Every event includes event_type, execution_id, timestamp, and, when the
event belongs to a step, step_id. Consumers should switch on event_type
rather than assuming a fixed sequence. A single step may emit multiple
step.progress events, agent steps may emit many tool-call/result pairs, and a
stream can terminate with either execution.completed or stream.error.
Transport contract
The streaming endpoint uses the same authorization and execution request body
as non-streaming execution. The only transport difference is the Accept
header:
curl -N -X POST "http://localhost:8000/v1/workloads/by-slug/sample-review/execute" \
-H "Authorization: Bearer $ORQESTRA_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: text/event-stream" \
-d '{
"environment": "dev",
"inputs": {
"query": "screen ACME BV"
}
}'The control plane preserves the SSE response when proxying to the runtime
gateway. Runtime responses set Cache-Control: no-cache, Connection: keep-alive, and X-Accel-Buffering: no so browsers and reverse proxies do
not buffer the timeline.
SDK usage
async with OrqestraClient(base_url=url, api_key=key) as client:
async for event in client.workload_runtime.execute_stream("my-workload", {"query": "hello"}):
print(f"[{event['event_type']}] {event.get('data', {})}")The execute() and execute_stream() workload runtime calls wait up to 600
seconds by default for long agent flows. Pass timeout=<seconds> to use a
different caller-side timeout.
When an internal service credential dispatches work for a bound workload
principal, pass the subject fields to execute() or execute_stream():
await client.workload_runtime.execute(
"sample-review",
{"operation": "model_json"},
environment="dev",
subject_execution_mode="interactive",
subject_actor_ref="user:ops@orqestra.dev",
subject_actor_type="user",
subject_actor_auth_mode="programmatic",
)The SDK yields only data: lines parsed as JSON. It skips SSE control lines,
comments, and blank lines, which makes it safe to iterate directly in CLI
tools, notebooks, or background services.
Portal
The app runner page renders an ExecutionProgressTimeline showing a live
vertical timeline of events as the execution streams. Agent tool calls
appear indented under their parent step.
The portal’s streaming hook treats stream.error as a terminal error state.
It keeps already-received events visible so operators can see the last
successful step before the guard stopped the stream.
SSE frame format
event: step.started
data: {"event_type": "step.started", "execution_id": "exec-1", "step_id": "s1", "timestamp": "...", "data": {"step_type": "agent"}}
event: execution.completed
data: {"event_type": "execution.completed", "execution_id": "exec-1", "timestamp": "...", "data": {"outcome": "success", "result": {"answer": "Approved for review"}, "total_tokens": 1240}}Execution streams are capped by ORQESTRA_MAX_STREAM_BYTES on the runtime
gateway. If the next frame would exceed the cap, the stream emits a bounded
stream.error frame and stops before sending the oversized frame.
Failure modes
| Symptom | Meaning | Operator action |
|---|---|---|
HTTP 4xx before any SSE frame | The execute request was rejected before runtime dispatch | Fix authentication, workspace scope, subject fields, or request body |
HTTP 5xx before any SSE frame | Control-plane or runtime-gateway could not start the execution | Check service logs and readiness of runtime dependencies |
stream.error with stream_response_too_large | The response exceeded ORQESTRA_MAX_STREAM_BYTES | Increase the cap, reduce verbose tool output, or use non-streaming execution for very large results |
Missing execution.completed | The client disconnected or the stream stopped before a terminal event | Check caller timeout, proxy buffering, and runtime logs |
Do not treat step.completed as the final outcome. Only
execution.completed carries the execution-level result and total token count.
Context compaction
For long agent loops, the runtime compacts message history when approaching
the context window limit. The ConversationCompactor summarizes old
tool exchanges while preserving system prompts and the last 2 exchanges.
Compaction is triggered when estimated tokens exceed 80% of
context_window_size (set in model_config). The fast-tier model
is used for summarization when available.