Streaming Output
ERA Agent supports real-time output streaming using Server-Sent Events (SSE). This is perfect for LLM generation, progress tracking, long-running computations, and any scenario where you need immediate feedback as code executes.
Why Streaming?
Section titled “Why Streaming?”Traditional (Buffered) Execution:
# Wait 30 seconds...# Then get all output at once{"stdout": "Line 1\nLine 2\n...Line 100\n", "exit_code": 0}Streaming Execution:
# Get output immediately as it's generatedevent: stdoutdata: {"type":"stdout","content":"Line 1\n"}
event: stdoutdata: {"type":"stdout","content":"Line 2\n"}
# ...continues in real-timeQuick Start
Section titled “Quick Start”Basic Streaming Request
Section titled “Basic Streaming Request”curl -X POST https://anewera.dev/api/sessions/my-session/stream \ -H "Content-Type: application/json" \ -d '{ "code": "import time\nfor i in range(10):\n print(f\"Processing {i}\")\n time.sleep(0.5)" }'Output (real-time):
event: stdoutdata: {"type":"stdout","content":"Processing 0\n"}
event: stdoutdata: {"type":"stdout","content":"Processing 1\n"}
event: stdoutdata: {"type":"stdout","content":"Processing 2\n"}
...
event: donedata: {"type":"done","exit_code":0,"duration":"5.123s"}SSE Event Types
Section titled “SSE Event Types”| Event Type | Description | Data Fields |
|---|---|---|
stdout | Standard output line | type, content |
stderr | Standard error line | type, content |
done | Execution complete | type, exit_code, duration |
error | Execution error | type, error |
Client Examples
Section titled “Client Examples”JavaScript (Browser/Node.js)
Section titled “JavaScript (Browser/Node.js)”async function streamExecution(sessionId, code) { const response = await fetch( `https://anewera.dev/api/sessions/${sessionId}/stream`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ code }), } );
const reader = response.body.getReader(); const decoder = new TextDecoder(); let buffer = '';
while (true) { const { done, value } = await reader.read(); if (done) break;
buffer += decoder.decode(value, { stream: true }); const lines = buffer.split('\n'); buffer = lines.pop() || '';
for (const line of lines) { if (line.startsWith('data: ')) { const event = JSON.parse(line.slice(6));
switch (event.type) { case 'stdout': console.log('[OUT]', event.content); break; case 'stderr': console.error('[ERR]', event.content); break; case 'done': console.log(`Completed with exit code ${event.exit_code}`); break; case 'error': console.error('Error:', event.error); break; } } } }}
// Usageawait streamExecution('my-session', `import timefor i in range(10): print(f"Token {i}") time.sleep(0.2)`);Python
Section titled “Python”import requestsimport json
def stream_execution(session_id, code): url = f"https://anewera.dev/api/sessions/{session_id}/stream"
response = requests.post( url, json={"code": code}, stream=True )
for line in response.iter_lines(): if line: line = line.decode('utf-8') if line.startswith('data: '): event = json.loads(line[6:])
if event['type'] == 'stdout': print('[OUT]', event['content'], end='') elif event['type'] == 'stderr': print('[ERR]', event['content'], end='') elif event['type'] == 'done': print(f"\\nCompleted: exit_code={event['exit_code']}")
# Usagestream_execution('my-session', '''import timefor i in range(10): print(f"Processing {i}") time.sleep(0.5)''')Bash (with jq)
Section titled “Bash (with jq)”curl -X POST https://anewera.dev/api/sessions/my-session/stream \ -H "Content-Type: application/json" \ -d '{"code": "import time; [print(f\"Line {i}\") or time.sleep(0.3) for i in range(10)]"}' \ 2>/dev/null | while IFS= read -r line; do if [[ $line == data:* ]]; then JSON="${line#data: }" TYPE=$(echo "$JSON" | jq -r '.type')
if [ "$TYPE" = "stdout" ]; then CONTENT=$(echo "$JSON" | jq -r '.content') echo "[OUT] $CONTENT" elif [ "$TYPE" = "done" ]; then EXIT_CODE=$(echo "$JSON" | jq -r '.exit_code') echo "Completed with exit code: $EXIT_CODE" fi fidoneUse Cases
Section titled “Use Cases”1. LLM Token Streaming
Section titled “1. LLM Token Streaming”Stream AI-generated text token by token:
code = '''import timeimport sys
tokens = ["The", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog"]
for token in tokens: print(token, end=" ", flush=True) time.sleep(0.2)
print() # Final newline'''2. Progress Bar / Status Updates
Section titled “2. Progress Bar / Status Updates”code = '''import time
tasks = ["Loading data", "Processing", "Analyzing", "Generating report", "Done"]
for i, task in enumerate(tasks, 1): print(f"[{i}/{len(tasks)}] {task}...") time.sleep(1)'''3. Long-Running Computation
Section titled “3. Long-Running Computation”code = '''import time
def expensive_computation(n): print(f"Starting computation for n={n}") for i in range(n): result = i ** 2 if i % 100 == 0: print(f"Progress: {i}/{n} ({i/n*100:.1f}%)") time.sleep(0.01) print("Computation complete!") return result
expensive_computation(1000)'''4. Live Log Monitoring
Section titled “4. Live Log Monitoring”code = '''import timeimport random
events = ["INFO", "DEBUG", "WARNING", "ERROR"]
for i in range(20): level = random.choice(events) print(f"[{level}] Event {i}: Something happened") time.sleep(0.2)'''Best Practices
Section titled “Best Practices”1. Flush Output Immediately
Section titled “1. Flush Output Immediately”# Python - use flush=Trueprint("Immediate output", flush=True)
# Or flush stdout manuallyimport sysprint("Message")sys.stdout.flush()// Node.js - console.log flushes automaticallyconsole.log("Immediate output");2. Handle Errors Gracefully
Section titled “2. Handle Errors Gracefully”try { for await (const event of streamEvents(sessionId, code)) { if (event.type === 'error') { console.error('Execution error:', event.error); break; } // Process event }} catch (error) { console.error('Stream error:', error);}3. Set Appropriate Timeouts
Section titled “3. Set Appropriate Timeouts”# For long-running streaming tasks, increase timeoutcurl -X POST .../stream \ -d '{ "code": "...", "timeout": 300 }'4. Buffer Management
Section titled “4. Buffer Management”When consuming streams, always handle partial lines:
let buffer = '';
while (true) { const { done, value } = await reader.read(); if (done) break;
buffer += decoder.decode(value, { stream: true }); const lines = buffer.split('\n'); buffer = lines.pop() || ''; // Keep incomplete line in buffer
for (const line of lines) { // Process complete lines }}Streaming vs Regular Execution
Section titled “Streaming vs Regular Execution”| Feature | Regular /run | Streaming /stream |
|---|---|---|
| Output | Buffered, all at once | Real-time, line-by-line |
| Response Format | JSON | Server-Sent Events |
| Best For | Quick tasks, batch jobs | LLMs, progress tracking, long tasks |
| Timeout | Configurable | Configurable |
| Error Handling | JSON error response | SSE error event |
| Client Complexity | Simple | Moderate (SSE parsing) |
Troubleshooting
Section titled “Troubleshooting”Not Receiving Events
Section titled “Not Receiving Events”-
Check output is flushed:
print("Message", flush=True) # Python -
Verify content type:
Terminal window curl -v .../stream # Check for "Content-Type: text/event-stream" -
Test with simple code:
print("Test 1")print("Test 2")print("Test 3")
Slow Streaming
Section titled “Slow Streaming”- Increase buffer size in client
- Check network latency
- Ensure code isn’t blocking
Connection Closed Early
Section titled “Connection Closed Early”- Check timeout settings
- Monitor for network interruptions
- Implement retry logic on client
See Also
Section titled “See Also”- API Reference - Complete API documentation
- Environment Variables - Setting environment variables
- Timeout Configuration - Configuring execution timeouts