DeltaKitDeltaKit

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:

TypeDescription
text_deltaAppend text to the response. { type: "text_delta", delta: "..." }
tool_callA tool/function call. { type: "tool_call", tool_name, argument, call_id? }
tool_resultResult 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.

On this page