Recipes← all recipesView on GitHub

Stream voice AI agent debug events

AI Agentsvoice AI observability

Select a voice AI debug level, stream matching events to your webhook, and handle them as they arrive.

observability

The claim

enable_debug_events(level) writes debug_webhook_url and debug_webhook_level into the document’s params. The URL is the agent’s own /debug_events route, behind the same basic auth as the rest of the agent. The platform POSTs each event the level selects, and the function you register with on_debug_event receives every one with its label and full body.

Why it holds

The ai params reference documents both fields. debug_webhook_url receives “each interaction between the AI and end user”. debug_webhook_level is 0 to 2, and level 2 adds conversation_add, llm_request and llm_response.

How it works

class WatchedAgent(AgentBase):
    def __init__(self):
        super().__init__(name="watched", route="/watched")
        self.enable_debug_events(level=DEBUG_LEVEL)

@agent.on_debug_event
def watch(event_type, data):
    EVENTS.append((event_type, data.get("call_id")))
    if event_type == "llm_error":
        ERROR_EVENTS.append({"call_id": data.get("call_id"), "detail": data})

What the platform receives in the document:

{"params": {"debug_webhook_url": "https://user:pass@host/watched/debug_events/?__token=...",
            "debug_webhook_level": 1}}

The SDK’s route, _handle_debug_events_request in web_mixin.py, reads the event label from label and falls back to action. It logs the event as debug_event, then calls your handler with the label and the whole body, awaiting it if it is async. The enable_debug_events docstring in ai_config_mixin.py describes level 1 as barge, errors, session start and end, and step changes.

Limitations

The verifier posts events of the documented shape; it cannot generate the platform’s own. Which labels arrive at level 1 is the SDK’s description, not something proven here.

Level 2 posts every model request and response. Through a tunnel on one call that is fine; across a fleet, size your endpoint for it. Per the reference, setting debug_webhook_url turns the stream on, so lowering the level thins the stream rather than stopping it.

What to change first

Remove enable_debug_events from __init__ and run the verifier. The first assertion fails because params no longer carries the URL, and the platform has nowhere to send anything. The verifier already renders at levels 1 and 2 itself; to hear level 2 on a call, set DEBUG_LEVEL=2 in .env and run python app.py.