Skip to main content
Zeus uses Server-Sent Events (SSE) to stream the Agent’s reasoning process and tool calls to the frontend in real time. This page describes the complete streaming pipeline, event types, and chunking behavior.

Streaming Pipeline

The streaming pipeline uses end-to-end SSE pass-through: the Python backend generates events -> the Next.js API proxies and forwards them -> the frontend StreamProcessor consumes them.

Event Types

Core Events

SSE EventTriggerKey Fields
textEach token output by the LLMcontent, role
tool_callLLM decides to invoke a tooltool_name, parameters, requires_approval
tool_call_resultTool execution completestool_name, result, is_error
completeAgent execution finishescontent, summary
errorAn exception occurserror, error_code, details
token_usageAfter an LLM call endsprompt_tokens, completion_tokens
Sandbox tool execution results (sandbox_exec_py, sandbox_exec_sh, etc.) are returned via the standard tool_call_result event and do not use a separate event type.

Event Mapping

Mapping from DeepAgents framework internal events to SSE messages:

Tool Call ID Queue

To correctly match on_tool_end events with their corresponding tool calls, the runtime maintains a FIFO queue (grouped by tool name, storing tool_call_id values). IDs are enqueued during on_chat_model_end and dequeued for matching during on_tool_end.

Frontend StreamProcessor

The frontend handleStreamMessage() consumes the SSE stream and routes events to the appropriate state management:

Tool Call Streaming

Tool calls support two-phase streaming: tool_call_chunk events stream the arguments in real time, then a tool_call event delivers the complete parameters.

Expected Event Order (Frontend)

tool_call_chunk  (first chunk — creates streaming preview card)
tool_call_chunk  (subsequent chunks — appends argument text)
tool_call_chunk  (continues appending...)
tool_call        (complete parameters — replaces streaming card with final version)
tool_call_result (tool execution result)
SSE EventTriggerKey Fields
tool_call_chunkLLM streams tool argumentstool_call_id, tool_name, args_chunk, index
tool_callArguments are completetool_name, parameters (complete dict)
stream-processor.ts creates/updates a streaming preview card (with streamingArgs) on each tool_call_chunk, then replaces it with the final card carrying complete parameters when the tool_call event arrives.

ai-backend (LangChain)

LangChain events naturally match this order:
on_chat_model_stream → tool_call_chunks → emits tool_call_chunk (streaming fragments)
on_chat_model_end    → tool_calls ready → emits tool_call (complete parameters)
At on_chat_model_end, the LLM has finished generating all arguments, so tc.get("args", {}) returns the fully parsed dict.

Video Pipeline SSE Events

When project_type === "video", the backend emits additional SSE events to drive the Video Workspace UI in real time.
SSE EventDirectionKey FieldsPurpose
video_storyboard_initBackend → Frontendstoryboard_id, elements[], segments[], audio_items[]Push initial storyboard structure to workspace
video_element_updateBackend → Frontendstoryboard_id, element_id, assetUpdate element with new asset (image)
video_shot_progressBackend → Frontendstoryboard_id, shot_id, progress (0-100)Real-time shot generation progress
video_shot_completeBackend → Frontendstoryboard_id, shot_id, assetShot video generation complete
video_audio_completeBackend → Frontendstoryboard_id, audio_id, assetAudio generation complete
These events are handled by stream-processor.ts which updates videoStore (Zustand), triggering reactive UI updates in the Storyboard and Timeline panels. The projectType is propagated from the frontend’s ChatInterface through the SSE request body to the AI backend’s agent.py context, which conditionally loads the VIDEO.md prompt layer.

Chunking & Batching

Message Batching

The frontend merges rapid successive text updates, flushing UI updates in batches at approximately 60fps to avoid excessive re-rendering.

Virtual Scrolling

Long conversations use virtual scrolling, rendering only the message cards within the visible viewport to improve scroll performance.

Selective State Persistence

Only essential state is persisted (such as sessionId and messageIds); full message content is loaded on demand from the server.