Hosted Streaming API
The hosted streaming API is for UI and integration clients that submit input, observe live events, interrupt active runs, and answer interactive middleware requests.
All runtime routes use:
/agents/{agentId}/sessions/{sessionId}/threads/{threadId}That scope identifies the hosted runtime agent and thread path.
Submit Input
Submit simple text:
POST /agents/{agentId}/sessions/{sessionId}/threads/{threadId}/inputs
Content-Type: application/json
{
"text": "Explain this thread in one sentence.",
"runConfig": {}
}If the JSON body has no type property and has a non-empty text property, hosting treats it as a convenience text request and converts it to a UserMessagesInputEvent.
You can also submit an event envelope:
{
"version": "1.0",
"type": "USER_MESSAGES_INPUT",
"messages": [
{
"role": "user",
"text": "Continue from here."
}
]
}messages is optional on USER_MESSAGES_INPUT. Normal user submissions should include at least one message. Omitting it or sending an empty array asks the runtime to resume the scoped thread with the supplied run configuration; the thread must already have history.
Accepted input returns 202 Accepted with the backend-owned run identity:
{
"runtimeRunId": "run-123",
"startedAt": "2026-07-15T10:15:30Z"
}Observe committed SSE events to render output, completion, errors, and interactive requests. Keep the returned runtimeRunId for lifecycle state and safe interruption.
Only one active hosted run is allowed per thread. A second input submitted to the same sessionId + threadId while a run is active returns a conflict with a thread-run-active error.
Estimate Context Usage
Hosted clients can ask the runtime how much context the current thread is using for a candidate run configuration:
POST /agents/{agentId}/sessions/{sessionId}/threads/{threadId}/context-usage
Content-Type: application/json
{
"runConfig": {
"providerKey": "openai",
"modelId": "gpt-4.1",
"compaction": {
"modelContext": {
"providerKey": "openai",
"modelId": "gpt-4.1",
"contextWindow": 128000
}
}
}
}The response is ThreadContextUsage:
{
"sessionId": "session-1",
"threadId": "main",
"providerKey": "openai",
"modelId": "gpt-4.1",
"contextWindow": 128000,
"effectiveInputTokens": 64000,
"usageRatio": 0.5,
"isEstimate": false,
"source": "last-observed-provider-usage"
}This endpoint does not start a run or mutate thread history. Use it for model-switch warnings, context meters, and deciding whether to submit a config-only compaction run.
Force Compaction
There is no separate hosted compact endpoint. Compaction is part of the normal input pipeline, so hosted clients force it by submitting a USER_MESSAGES_INPUT envelope with empty or omitted messages and a run config that sets compaction mode to force:
{
"version": "1.0",
"type": "USER_MESSAGES_INPUT",
"messages": [],
"runConfig": {
"compaction": {
"mode": 1,
"behavior": 2
}
}
}mode: 1 is CompactionRunMode.Force. behavior: 2 is CompactionBehavior.StopAfterCompaction, which compacts and stops before a model call. Enum values use the hosted API's default numeric JSON representation unless the host customizes JSON options.
Load State Then Observe With SSE
First load the authoritative snapshot:
GET /agents/{agentId}/sessions/{sessionId}/threads/{threadId}/stateIt returns ordered committed events, their latestSequenceNumber, and the backend-owned activeRun. Render that snapshot and connect SSE after its cursor:
GET /agents/{agentId}/sessions/{sessionId}/threads/{threadId}/events/live?after=42
Accept: text/event-streamThe server replays every committed event after the cursor, then continues observing. Each event includes its committed sequence as the SSE id:
id: 43
data: {"version":"1.0","type":"TEXT_DELTA","sequenceNumber":43,"text":"hello","messageId":"..."}Process events serially and advance the cursor only after the consumer applies an event successfully. On EOF or a connection error, reconnect with the last acknowledged cursor. Comment heartbeats can be ignored. If an exception occurs after SSE headers have been sent, the stream writes a serialized error event instead of changing the HTTP status.
Input, interruption, and interactive responses use their HTTP routes. The hosted agent WebSocket lifecycle no longer exists. See Hosted Lifecycle And Recovery for the complete recovery contract.
Render Nested Activity
SSE delivers a linear committed stream. A hosted client can project that stream into a transcript, timeline, workflow tree, subagent view, or permission queue by grouping events with fields such as messageId, callId, permissionId, traceId, spanId, parentSpanId, eventFlowId, and agent metadata.
Workflow and subagent events may appear in the same live stream as parent agent events when child execution is routed through the parent event coordinator. Treat the transport as delivery only; use Render An Event Stream for UI projection guidance.
Fork Threads
Hosted clients fork threads with:
POST /agents/{agentId}/sessions/{sessionId}/threads/{threadId}/fork
Content-Type: application/json
{
"newThreadId": "try-short-answer",
"fromMessageId": "message-id-to-fork-from",
"name": "Short answer"
}ForkThreadRequest does not include a per-request compaction intent. If fork compaction is enabled for the hosted agent, it is controlled by the server-side agent and middleware configuration. Clients should read the created thread, thread projection, or thread events after the fork instead of assuming the target thread retained every raw copied message.
Interrupt A Run
Interrupt the active thread run:
POST /agents/{agentId}/sessions/{sessionId}/threads/{threadId}/interrupt
Content-Type: application/json
{
"expectedRuntimeRunId": "run-123",
"reason": "User cancelled the request.",
"eventFlowId": "optional-flow-id"
}Read /state immediately before cancellation and send its active run id as expectedRuntimeRunId. The body can also include an INTERRUPTION_REQUEST event envelope. Omitting a JSON object creates a default user interruption reason.
The 202 response has one of four statuses:
accepted: the expected active run received the interruptionalready_terminal: the expected run has already completed, failed, or been cancelledno_active_run: there is no current run and the expected run is not terminal historyactive_run_mismatch: another run is active; the response includes thatactiveRun
Do not automatically retry against a mismatched run. It may be newer work started by another client.
Answer Interactive Middleware
Current committed-stream limitation
The response route is mapped, but the committed SSE observer can only deliver event types persisted to the thread document. Built-in interactive request records currently default to non-persistent events. Do not build a hosted permission, clarification, continuation, or client-tool prompt flow until those request payloads are committed and replayable.
HTTP clients answer bidirectional requests through one response route:
POST /agents/{agentId}/sessions/{sessionId}/threads/{threadId}/responses
Content-Type: application/json
{
"version": "1.0",
"type": "PERMISSION_RESPONSE",
"permissionId": "permission-id-from-request",
"sourceName": "PermissionMiddleware",
"approved": true,
"choice": "ask"
}The body must be a serialized AgentEvent envelope whose event implements IResponseEvent, such as PermissionResponseEvent, ContinuationResponseEvent, ClarificationResponseEvent, ClientToolInvokeOutcomeEvent, or an app-owned custom response event.
Middleware responses are not thread runs. The route requires an existing session/thread scope, an active thread runtime, and a waiter that accepts the response. If the scope does not exist, it returns 404. If no runtime is active, the route returns a thread-runtime-not-active conflict. If the runtime exists but no waiter accepts the response, it returns 409 with the RespondResult status.
Event Bodies
Hosted streaming uses AgentEventSerializer envelopes: version, type, and camelCase payload properties, with null values omitted.
This page intentionally shows contract-level examples only. For event families and persistence caveats, see Events.