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

# message/stream

> Send streaming messages to A2A agents and receive real-time responses via Server-Sent Events

## Overview

The `message/stream` method enables real-time communication with A2A agents using Server-Sent Events (SSE). This allows you to receive partial responses as the agent processes your request, providing a more interactive experience.

<Note>
  **Streaming Communication**: This method uses Server-Sent Events for real-time response streaming. The connection remains open until the agent completes the response.
</Note>

## Request

### Headers

<ParamField header="Content-Type" type="string" required>
  Must be `application/json`
</ParamField>

<ParamField header="Accept" type="string" required>
  Must be `text/event-stream` for SSE support
</ParamField>

<ParamField header="x-api-key" type="string" required>
  Your API key for authentication
</ParamField>

<ParamField header="Cache-Control" type="string">
  Recommended: `no-cache` for real-time streaming
</ParamField>

### Path Parameters

<ParamField path="agent_id" type="string" required>
  Unique identifier of the target agent
</ParamField>

### Body Parameters

<ParamField body="jsonrpc" type="string" required>
  JSON-RPC version, must be `"2.0"`
</ParamField>

<ParamField body="id" type="string" required>
  Unique identifier for this request (for response correlation)
</ParamField>

<ParamField body="method" type="string" required>
  Must be `"message/stream"`
</ParamField>

<ParamField body="params" type="object" required>
  Message parameters object (same structure as message/send)

  <Expandable title="params properties">
    <ParamField body="params.message" type="object" required>
      The message to send to the agent

      <Expandable title="message properties">
        <ParamField body="params.message.role" type="string" required>
          Message role, must be `"user"`
        </ParamField>

        <ParamField body="params.message.messageId" type="string" required>
          UUID v4 identifier for this message
        </ParamField>

        <ParamField body="params.message.parts" type="array" required>
          Array of message parts (text, files, etc.)
        </ParamField>
      </Expandable>
    </ParamField>

    <ParamField body="params.contextId" type="string">
      Context ID for multi-turn conversations
    </ParamField>

    <ParamField body="params.sessionId" type="string">
      Optional session identifier
    </ParamField>
  </Expandable>
</ParamField>

## Response

### Server-Sent Events Stream

The response is delivered as a stream of Server-Sent Events. Each event contains a JSON object with the current state of the task.

#### Event Format

```
Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive

data: {"jsonrpc":"2.0","result":{"id":"task-123","status":{"state":"working"},"final":false},"id":"req-001"}

data: {"jsonrpc":"2.0","result":{"id":"task-123","status":{"state":"completed","message":{"role":"agent","parts":[{"type":"text","text":"Response content"}]}},"final":true},"id":"req-001"}
```

#### Event Data Structure

<ResponseField name="jsonrpc" type="string">
  JSON-RPC version, always `"2.0"`
</ResponseField>

<ResponseField name="result" type="object">
  Result object containing the current task state

  <Expandable title="result properties">
    <ResponseField name="result.id" type="string">
      Task ID for this streaming operation
    </ResponseField>

    <ResponseField name="result.status" type="object">
      Current status information

      <Expandable title="status properties">
        <ResponseField name="result.status.state" type="string">
          Current task state: `"submitted"`, `"working"`, `"completed"`, `"failed"`, or `"canceled"`
        </ResponseField>

        <ResponseField name="result.status.message" type="object">
          Agent's response message (present when state is "completed")

          <Expandable title="message properties">
            <ResponseField name="result.status.message.role" type="string">
              Message role, always `"agent"`
            </ResponseField>

            <ResponseField name="result.status.message.parts" type="array">
              Array of response parts
            </ResponseField>
          </Expandable>
        </ResponseField>

        <ResponseField name="result.status.progress" type="object">
          Progress information (optional, during "working" state)

          <Expandable title="progress properties">
            <ResponseField name="result.status.progress.current" type="number">
              Current progress value
            </ResponseField>

            <ResponseField name="result.status.progress.total" type="number">
              Total progress value
            </ResponseField>

            <ResponseField name="result.status.progress.message" type="string">
              Progress description
            </ResponseField>
          </Expandable>
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="result.contextId" type="string">
      Context ID for multi-turn conversations
    </ResponseField>

    <ResponseField name="result.final" type="boolean">
      Whether this is the final event (`true` when task is completed/failed/canceled)
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="id" type="string">
  Request ID (matches the request ID)
</ResponseField>

## Examples

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST "http://localhost:8000/api/v1/a2a/my-agent" \
    -H "Content-Type: application/json" \
    -H "Accept: text/event-stream" \
    -H "x-api-key: your-api-key" \
    -N \
    -d '{
      "jsonrpc": "2.0",
      "id": "req-stream-001",
      "method": "message/stream",
      "params": {
        "message": {
          "role": "user",
          "parts": [
            {
              "type": "text",
              "text": "Generate a detailed report about AI trends"
            }
          ],
          "messageId": "6dbc13b5-bd57-4c2b-b503-24e381b6c8d6"
        }
      }
    }'
  ```

  ```javascript JavaScript (EventSource) theme={null}
  const eventSource = new EventSource('/api/v1/a2a/my-agent', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-api-key': 'your-api-key'
    },
    body: JSON.stringify({
      jsonrpc: "2.0",
      id: "req-stream-001",
      method: "message/stream",
      params: {
        message: {
          role: "user",
          parts: [
            {
              type: "text",
              text: "Generate a detailed report about AI trends"
            }
          ],
          messageId: crypto.randomUUID()
        }
      }
    })
  });

  eventSource.onmessage = function(event) {
    const data = JSON.parse(event.data);
    console.log('Received:', data);
    
    if (data.result?.final) {
      console.log('Stream completed');
      eventSource.close();
    }
  };

  eventSource.onerror = function(event) {
    console.error('Stream error:', event);
    eventSource.close();
  };
  ```

  ```javascript JavaScript (Fetch with Streaming) theme={null}
  const response = await fetch('http://localhost:8000/api/v1/a2a/my-agent', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Accept': 'text/event-stream',
      'x-api-key': 'your-api-key'
    },
    body: JSON.stringify({
      jsonrpc: "2.0",
      id: "req-stream-001",
      method: "message/stream",
      params: {
        message: {
          role: "user",
          parts: [
            {
              type: "text",
              text: "Generate a detailed report about AI trends"
            }
          ],
          messageId: crypto.randomUUID()
        }
      }
    })
  });

  const reader = response.body.getReader();
  const decoder = new TextDecoder();

  while (true) {
    const { done, value } = await reader.read();
    if (done) break;
    
    const chunk = decoder.decode(value);
    const lines = chunk.split('\n');
    
    for (const line of lines) {
      if (line.startsWith('data: ')) {
        const data = JSON.parse(line.slice(6));
        console.log('Received:', data);
        
        if (data.result?.final) {
          console.log('Stream completed');
          return;
        }
      }
    }
  }
  ```

  ```python Python theme={null}
  import requests
  import uuid
  import json

  payload = {
      "jsonrpc": "2.0",
      "id": "req-stream-001",
      "method": "message/stream",
      "params": {
          "message": {
              "role": "user",
              "parts": [
                  {
                      "type": "text",
                      "text": "Generate a detailed report about AI trends"
                  }
              ],
              "messageId": str(uuid.uuid4())
          }
      }
  }

  response = requests.post(
      "http://localhost:8000/api/v1/a2a/my-agent",
      headers={
          "x-api-key": "your-api-key",
          "Accept": "text/event-stream"
      },
      json=payload,
      stream=True
  )

  for line in response.iter_lines():
      if line:
          line_str = line.decode('utf-8')
          if line_str.startswith('data: '):
              data = json.loads(line_str[6:])
              print(json.dumps(data, indent=2))
              
              if data.get('result', {}).get('final'):
                  print("Stream completed")
                  break
  ```
</RequestExample>

<ResponseExample>
  ```text SSE Stream Example theme={null}
  data: {"jsonrpc":"2.0","result":{"id":"task-789","status":{"state":"submitted"},"final":false},"id":"req-stream-001"}

  data: {"jsonrpc":"2.0","result":{"id":"task-789","status":{"state":"working","progress":{"current":1,"total":5,"message":"Analyzing AI trends data"}},"final":false},"id":"req-stream-001"}

  data: {"jsonrpc":"2.0","result":{"id":"task-789","status":{"state":"working","progress":{"current":3,"total":5,"message":"Generating report sections"}},"final":false},"id":"req-stream-001"}

  data: {"jsonrpc":"2.0","result":{"id":"task-789","status":{"state":"completed","message":{"role":"agent","parts":[{"type":"text","text":"# AI Trends Report 2024\n\n## Executive Summary\nThe AI landscape continues to evolve rapidly with significant developments in...\n\n## Key Trends\n1. Large Language Models advancement\n2. Multimodal AI integration\n3. Edge AI deployment\n\n## Conclusion\nThese trends indicate a shift towards more accessible and integrated AI solutions."}]}},"contextId":"ctx-abc123","final":true},"id":"req-stream-001"}
  ```

  ```json Error Response theme={null}
  {
    "jsonrpc": "2.0",
    "error": {
      "code": -32602,
      "message": "Invalid params",
      "data": {
        "details": "Missing required field: messageId"
      }
    },
    "id": "req-stream-001"
  }
  ```
</ResponseExample>

## Stream Lifecycle

<AccordionGroup>
  <Accordion icon="play" title="1. Stream Initiation">
    **State: `submitted`**

    The request has been received and queued for processing.

    ```json theme={null}
    {
      "result": {
        "id": "task-789",
        "status": {"state": "submitted"},
        "final": false
      }
    }
    ```
  </Accordion>

  <Accordion icon="gear" title="2. Processing Updates">
    **State: `working`**

    The agent is actively processing the request. May include progress updates.

    ```json theme={null}
    {
      "result": {
        "id": "task-789",
        "status": {
          "state": "working",
          "progress": {
            "current": 3,
            "total": 5,
            "message": "Generating content"
          }
        },
        "final": false
      }
    }
    ```
  </Accordion>

  <Accordion icon="check" title="3. Completion">
    **State: `completed`**

    The agent has finished processing and provides the final response.

    ```json theme={null}
    {
      "result": {
        "id": "task-789",
        "status": {
          "state": "completed",
          "message": {
            "role": "agent",
            "parts": [{"type": "text", "text": "Final response"}]
          }
        },
        "contextId": "ctx-abc123",
        "final": true
      }
    }
    ```
  </Accordion>
</AccordionGroup>

## Error Handling

### Stream Errors

Errors during streaming are sent as regular JSON-RPC error responses:

```json theme={null}
{
  "jsonrpc": "2.0",
  "error": {
    "code": -32000,
    "message": "Agent processing failed",
    "data": {
      "taskId": "task-789",
      "details": "Timeout exceeded"
    }
  },
  "id": "req-stream-001"
}
```

### Connection Management

<AccordionGroup>
  <Accordion icon="plug" title="Connection Handling">
    * **Keep-Alive**: Server maintains connection until completion
    * **Heartbeat**: Server may send ping events to keep connection alive
    * **Timeout**: Connections timeout after 5 minutes of inactivity
    * **Reconnection**: Clients should implement reconnection logic
  </Accordion>

  <Accordion icon="shield" title="Error Recovery">
    * **Network Issues**: Implement exponential backoff for reconnection
    * **Partial Responses**: Store received data before reconnecting
    * **Task Continuation**: Use task ID to check status after reconnection
  </Accordion>
</AccordionGroup>

## Best Practices

<AccordionGroup>
  <Accordion icon="lightning" title="Performance">
    * **Buffer Management**: Process events as they arrive, don't buffer unnecessarily
    * **Connection Pooling**: Reuse connections when possible
    * **Timeout Handling**: Set appropriate timeouts for long-running tasks
  </Accordion>

  <Accordion icon="shield" title="Reliability">
    * **Event Parsing**: Always validate JSON before parsing
    * **Final Flag**: Check `final` flag to know when stream is complete
    * **Error Handling**: Implement proper error handling for network issues
  </Accordion>

  <Accordion icon="users" title="User Experience">
    * **Progress Indicators**: Use progress information to show user feedback
    * **Partial Results**: Display partial content as it arrives
    * **Cancellation**: Provide ability to cancel long-running streams
  </Accordion>
</AccordionGroup>

## Comparison with message/send

| Feature               | message/send     | message/stream     |
| --------------------- | ---------------- | ------------------ |
| **Response Type**     | Single response  | Multiple events    |
| **Real-time Updates** | No               | Yes                |
| **Progress Tracking** | No               | Yes                |
| **Connection**        | Request/Response | Persistent         |
| **Use Case**          | Quick queries    | Long-running tasks |
| **Complexity**        | Simple           | Moderate           |
