Which agent spoke attribution

Per-agent attribution is what separates a transparent multi-agent system from a black box. When a user sees 'policy_agent is searching your policy...' then 'policy_agent answered', they understand the system. Ops teams can trace which subagent misbehaved. The same attribution feeds observability tools and lets you build dashboards that show request volume per route.

router.py
python
from fastapi import APIRouter
from fastapi.responses import StreamingResponse

from models import ChatRequest
from service import stream_chat

router = APIRouter(prefix='/insurance-copilot', tags=['insurance-copilot'])


@router.post('/chat/stream')
async def chat_stream(request: ChatRequest):
    """Server-Sent Events stream of the supervisor plus subagent trace."""

    async def event_source():
        async for chunk in stream_chat(
            message=request.message,
            thread_id=request.thread_id,
            customer_id=request.customer_id,
        ):
            yield chunk

    return StreamingResponse(
        event_source(),
        media_type='text/event-stream',
        headers={
            'Cache-Control': 'no-cache',
            'Connection': 'keep-alive',
            'X-Accel-Buffering': 'no',
        },
    )

Three headers matter. Cache-Control: no-cache prevents proxies from buffering. Connection: keep-alive keeps the socket open. X-Accel-Buffering: no tells nginx not to buffer SSE, which would otherwise batch your events and kill the real-time feel.

SSE event timeline for a single message

Events the browser receives during one chat turn, from start to done.

Matching exercise: Match SSE event to what the UI should render

Loading practice…

Checkpoint: Streaming and attribution checkpoint

Loading practice…