> ## Documentation Index
> Fetch the complete documentation index at: https://docs.corti.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Stream agent responses

> Learn how to stream agent responses via SSE using message:stream and tasks:subscribe, including resumption with Last-Event-ID.

This guide shows you how to stream agent responses in real time using Server-Sent Events (SSE). You will learn about the two streaming endpoints, the SSE event format, and how to resume interrupted streams.

## Prerequisites

* An existing agent (see [Create an agent](/agentic/guides/create-agent))
* An access token or client credentials
* Understanding of the [task lifecycle](/agentic/task-lifecycle) and [A2A protocol](/agentic/a2a-protocol)

## When to stream

Use streaming when you need real-time updates as the agent processes a message:

* Showing incremental progress to users
* Displaying partial results as they arrive
* Monitoring long-running tasks

For simple request/response interactions, use [message:send](/agentic/guides/send-message) instead.

## Stream a new message

Use `message:stream` to send a message and receive the response as an SSE stream:

```bash theme={null}
# Replace these with your values
AGENT_ID="<your-agent-id>"
ENVIRONMENT="<eu-or-us>"
TENANT="<your-tenant-name>"
TOKEN="<your-access-token>"

curl -N -X POST "https://api.${ENVIRONMENT}.corti.app/v2/agentic/agents/${AGENT_ID}/a2a/message:stream" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Tenant-Name: ${TENANT}" \
  -H "Content-Type: application/json" \
  -H "A2A-Version: 1.0" \
  -d '{
    "message": {
      "role": "ROLE_USER",
      "parts": [{ "text": "Generate a clinical note for this encounter." }]
    }
  }'
```

<Note>The `-N` flag disables cURL's output buffering, which is necessary for receiving SSE events in real time.</Note>

## SSE event format

Each event follows the W3C SSE wire format. The server currently sends only `id` and `data` lines. The `event` and `retry` fields are declared for forward compatibility but are not sent:

```
data: {"task":{"id":"task.0192f4c8-...","contextId":"ctx.0192f4c8-...","status":{"state":"TASK_STATE_WORKING","timestamp":"2026-05-19T12:00:00Z"}}}

data: {"artifactUpdate":{"taskId":"task.0192f4c8-...","contextId":"ctx.0192f4c8-...","artifact":{"artifactId":"art.0192f4c8-...","name":"clinical-note","parts":[{"text":"SOAP Note..."}]},"lastChunk":true}}

data: {"statusUpdate":{"taskId":"task.0192f4c8-...","contextId":"ctx.0192f4c8-...","status":{"state":"TASK_STATE_COMPLETED","timestamp":"2026-05-19T12:00:01Z"}}}
```

### Event types

Each SSE event carries an `A2AStreamResponse` with exactly one field:

| Field            | Description                                                                             |
| ---------------- | --------------------------------------------------------------------------------------- |
| `task`           | The full task object, sent when the task is created or state changes                    |
| `message`        | A direct message response (no task lifecycle)                                           |
| `statusUpdate`   | Incremental status change (no `final` flag; clients infer finality from the task state) |
| `artifactUpdate` | Incremental artifact update with `lastChunk` flag                                       |

## Subscribe to an existing task

If you have a task ID (from a non-blocking `message:send` or after a stream dropped), use `tasks:subscribe` to stream updates:

```bash theme={null}
TASK_ID="<your-task-id>"

curl -N -X POST "https://api.${ENVIRONMENT}.corti.app/v2/agentic/agents/${AGENT_ID}/a2a/tasks/${TASK_ID}:subscribe" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Tenant-Name: ${TENANT}" \
  -H "A2A-Version: 1.0"
```

## Resumption with Last-Event-ID

<Warning>The server writes event IDs but does not yet read the `Last-Event-ID` request header, so resumption without gaps is not implemented. The section below describes the intended design for when this feature ships.</Warning>

If an SSE stream drops, the intended resumption mechanism is to send the `Last-Event-ID` header with the most recent event ID you received:

```bash theme={null}
LAST_EVENT_ID="event-123"

curl -N -X POST "https://api.${ENVIRONMENT}.corti.app/v2/agentic/agents/${AGENT_ID}/a2a/message:stream" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Tenant-Name: ${TENANT}" \
  -H "Content-Type: application/json" \
  -H "A2A-Version: 1.0" \
  -H "Last-Event-ID: ${LAST_EVENT_ID}" \
  -d '{
    "message": {
      "role": "ROLE_USER",
      "parts": [{ "text": "Continue generating the note." }]
    }
  }'
```

The server will replay events from that point forward once the feature is implemented. This will work with both `message:stream` and `tasks:subscribe`.

## Cancel a task

Cancel an in-flight task:

```bash theme={null}
curl -X POST "https://api.${ENVIRONMENT}.corti.app/v2/agentic/agents/${AGENT_ID}/a2a/tasks/${TASK_ID}:cancel" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Tenant-Name: ${TENANT}" \
  -H "A2A-Version: 1.0" \
  -H "Content-Type: application/json" \
  -d '{}'
```

The task transitions to `TASK_STATE_CANCELED`.

## JSON-RPC streaming binding

You can also stream via the JSON-RPC binding by sending a `message/stream` method to the base A2A endpoint:

```bash theme={null}
curl -N -X POST "https://api.${ENVIRONMENT}.corti.app/v2/agentic/agents/${AGENT_ID}/a2a" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Tenant-Name: ${TENANT}" \
  -H "Content-Type: application/json" \
  -H "A2A-Version: 1.0" \
  -d '{
    "jsonrpc": "2.0",
    "id": "msg-001",
    "method": "SendStreamingMessage",
    "params": {
      "message": {
        "role": "ROLE_USER",
        "parts": [{ "text": "Generate a clinical note." }]
      }
    }
  }'
```

The SSE events carry JSON-RPC response envelopes instead of raw `A2AStreamResponse` objects.

## Next steps

* Read about the [task lifecycle](/agentic/task-lifecycle) for state transitions
* Learn how to [send a message](/agentic/guides/send-message) without streaming
* Understand the [A2A protocol](/agentic/a2a-protocol) bindings
