The efficient handoff

A working handoff is not the same as a polished one. Callers notice when the specialist repeats a question, when markdown sneaks into TTS and gets read as asterisk asterisk, or when the silence between transfer and first reply feels long. This lesson tightens all of it.

Polish layers on a handoff

Three independent concerns that together make transfers feel natural.

triage_agent.py
python
import re

def strip_markdown(text: str) -> str:
    """Remove markdown so TTS does not read formatting as audio."""
    if not text:
        return text
    text = re.sub(r"```[\s\S]*?```", "", text)
    text = re.sub(r"`([^`]+)`", r"\1", text)
    text = re.sub(r"^#{1,6}\s+(.+)$", r"\1", text, flags=re.MULTILINE)
    text = re.sub(r"\*\*([^*]+)\*\*", r"\1", text)
    text = re.sub(r"\*([^*]+)\*", r"\1", text)
    text = re.sub(r"\[([^\]]+)\]\([^)]+\)", r"\1", text)
    text = re.sub(r"^[\s]*[-*+]\s+", "", text, flags=re.MULTILINE)
    return text.strip()

LLMs produce markdown by reflex. TTS will faithfully pronounce asterisks and backticks as words. Strip the formatting before sending text to TTS so the caller hears natural speech.

triage_agent.py
python
import json
from datetime import datetime
from typing import Optional, Any

async def emit_thought(
    self,
    category: str,
    content: str,
    metadata: Optional[dict[str, Any]] = None,
) -> None:
    """Publish an agent reasoning event to the frontend."""
    userdata: UserData = self.session.userdata
    room = userdata.ctx.room if userdata and userdata.ctx else None
    if not room:
        return

    thought = {
        "category": category,
        "content": content,
        "timestamp": datetime.now().isoformat(),
        "agent": self.__class__.__name__,
        "metadata": metadata or {},
    }

    await room.local_participant.publish_data(
        json.dumps({"thinking": thought}).encode("utf-8")
    )

Thinking events give your frontend a live view of what the agent is doing. Use categories like analysis, planning, or action so the UI can render a timeline next to the audio.

Quiz: Quiz

Loading practice…