Custom Events
The SSE event protocol for custom event types.
DeltaKit's SSE protocol supports any JSON event with a type field. Beyond the built-in text_delta, tool_call, and tool_result events, you can define and stream your own event types.
Event Format
Every SSE event is a data: line containing a JSON object with a type field:
data: {"type":"your_event_type","key":"value"}DeltaKit's parseSSEStream yields each parsed JSON object as-is. There is no validation. Any valid JSON with a type field works.
Built-in Event Types
These are the standard types defined by SSEEvent:
| Type | Description |
|---|---|
text_delta | Append text to the response. { type: "text_delta", delta: "..." } |
tool_call | A tool/function call. { type: "tool_call", tool_name, argument, call_id? } |
tool_result | Result of a tool call. { type: "tool_result", call_id, output } |
See SSE Events for the full type definitions.
Custom Event Examples
Reasoning / Chain-of-Thought
yield f'data: {json.dumps({"type": "reasoning_delta", "delta": "Let me think about this..."})}\n\n'Progress Indicators
yield f'data: {json.dumps({"type": "progress", "step": "searching", "percent": 50})}\n\n'Image Generation
yield f'data: {json.dumps({"type": "image", "url": "https://example.com/result.png", "alt": "Generated image"})}\n\n'Citations
yield f'data: {json.dumps({"type": "citation", "title": "Source", "url": "https://example.com", "snippet": "..."})}\n\n'Server Example (FastAPI)
A complete example streaming multiple event types:
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
import json
app = FastAPI()
@app.post("/api/chat")
async def chat(request: dict):
async def generate():
# Reasoning
yield f'data: {json.dumps({"type": "reasoning_delta", "delta": "Let me think..."})}\n\n'
# Progress
yield f'data: {json.dumps({"type": "progress", "step": "searching", "percent": 50})}\n\n'
# Text response
yield f'data: {json.dumps({"type": "text_delta", "delta": "Here is what I found:"})}\n\n'
# Done
yield 'data: [DONE]\n\n'
return StreamingResponse(generate(), media_type="text/event-stream")Stream Termination
The stream ends when the server sends data: [DONE]. This is not JSON. It's a special sentinel that parseSSEStream recognizes to stop iteration.
data: [DONE]Client-Side Handling
For handling custom events in React with useStreamChat, see Custom Event Handling.