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"
}
}
}'
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();
};
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;
}
}
}
}
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
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"}
{
"jsonrpc": "2.0",
"error": {
"code": -32602,
"message": "Invalid params",
"data": {
"details": "Missing required field: messageId"
}
},
"id": "req-stream-001"
}
A2A Protocol Endpoints
message/stream
Send streaming messages to A2A agents and receive real-time responses via Server-Sent Events
POST
/
api
/
v1
/
a2a
/
{agent_id}
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"
}
}
}'
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();
};
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;
}
}
}
}
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
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"}
{
"jsonrpc": "2.0",
"error": {
"code": -32602,
"message": "Invalid params",
"data": {
"details": "Missing required field: messageId"
}
},
"id": "req-stream-001"
}
Overview
Themessage/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.
Streaming Communication: This method uses Server-Sent Events for real-time response streaming. The connection remains open until the agent completes the response.
Request
Headers
string
required
Must be
application/jsonstring
required
Must be
text/event-stream for SSE supportstring
required
Your API key for authentication
string
Recommended:
no-cache for real-time streamingPath Parameters
string
required
Unique identifier of the target agent
Body Parameters
string
required
JSON-RPC version, must be
"2.0"string
required
Unique identifier for this request (for response correlation)
string
required
Must be
"message/stream"object
required
Message parameters object (same structure as message/send)
Show params properties
Show params properties
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
string
JSON-RPC version, always
"2.0"object
Result object containing the current task state
Show result properties
Show result properties
string
Task ID for this streaming operation
object
Current status information
Show status properties
Show status properties
string
Current task state:
"submitted", "working", "completed", "failed", or "canceled"object
string
Context ID for multi-turn conversations
boolean
Whether this is the final event (
true when task is completed/failed/canceled)string
Request ID (matches the request ID)
Examples
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"
}
}
}'
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();
};
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;
}
}
}
}
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
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"}
{
"jsonrpc": "2.0",
"error": {
"code": -32602,
"message": "Invalid params",
"data": {
"details": "Missing required field: messageId"
}
},
"id": "req-stream-001"
}
Stream Lifecycle
1. Stream Initiation
1. Stream Initiation
State:
submittedThe request has been received and queued for processing.{
"result": {
"id": "task-789",
"status": {"state": "submitted"},
"final": false
}
}
2. Processing Updates
2. Processing Updates
State:
workingThe agent is actively processing the request. May include progress updates.{
"result": {
"id": "task-789",
"status": {
"state": "working",
"progress": {
"current": 3,
"total": 5,
"message": "Generating content"
}
},
"final": false
}
}
3. Completion
3. Completion
State:
completedThe agent has finished processing and provides the final response.{
"result": {
"id": "task-789",
"status": {
"state": "completed",
"message": {
"role": "agent",
"parts": [{"type": "text", "text": "Final response"}]
}
},
"contextId": "ctx-abc123",
"final": true
}
}
Error Handling
Stream Errors
Errors during streaming are sent as regular JSON-RPC error responses:{
"jsonrpc": "2.0",
"error": {
"code": -32000,
"message": "Agent processing failed",
"data": {
"taskId": "task-789",
"details": "Timeout exceeded"
}
},
"id": "req-stream-001"
}
Connection Management
Connection Handling
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
Error Recovery
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
Best Practices
Performance
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
Reliability
Reliability
- Event Parsing: Always validate JSON before parsing
- Final Flag: Check
finalflag to know when stream is complete - Error Handling: Implement proper error handling for network issues
User Experience
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
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 |
Was this page helpful?