Streaming
ask_stream() yields events as they happen — tool calls, results, and the final answer. Use it to build real-time UIs.
Python
async for event in agent.ask_stream("Who are the top 10 users by order count?"):
match event["type"]:
case "tool_call":
print(f"→ Calling {event['tool_name']}({event['tool_args']})")
case "tool_result":
status = "✓" if event["success"] else "✗"
print(f" {status} {event['tool_name']}: {event['preview']}")
case "answer":
print(f"\n{event['text']}")
case "done":
print(f"\nTokens: {event['input_tokens']} in / {event['output_tokens']} out")
print(f"Memory hits: {event['memory_hits']}")
Event reference
tool_call
Emitted before a tool is executed.
{
"type": "tool_call",
"tool_name": "run_mql",
"tool_args": {"operation": "aggregate", "collection": "orders", ...}
}
tool_result
Emitted after a tool completes.
{
"type": "tool_result",
"tool_name": "run_mql",
"success": True,
"preview": "[{\"_id\": \"user_1\", \"count\": 42}, ...]" # first 200 chars
}
answer
Emitted when the LLM produces a final text response.
{
"type": "answer",
"text": "The top 10 users by order count are..."
}
done
Emitted after answer. Contains full metadata for the turn.
{
"type": "done",
"iterations": 2,
"input_tokens": 1820,
"output_tokens": 94,
"memory_hits": 1,
"tool_calls_made": ["list_collections", "run_mql"]
}
FastAPI + SSE
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
import json
app = FastAPI()
@app.post("/ask")
async def ask(body: dict):
async def event_stream():
async for event in agent.ask_stream(body["question"]):
yield f"data: {json.dumps(event)}\n\n"
return StreamingResponse(event_stream(), media_type="text/event-stream")
JavaScript client
const res = await fetch('/ask', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ question: 'How many orders last week?' }),
})
for await (const chunk of res.body) {
const lines = new TextDecoder().decode(chunk).split('\n')
for (const line of lines) {
if (!line.startsWith('data: ')) continue
const event = JSON.parse(line.slice(6))
if (event.type === 'tool_call') showSpinner(event.tool_name)
if (event.type === 'answer') showAnswer(event.text)
if (event.type === 'done') hideSpinner()
}
}