> ## Documentation Index
> Fetch the complete documentation index at: https://docs.unpod.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Level Up to SuperDialog

> When a plain LLM brain stops being enough: plug a structured SuperDialog agent into your voice agent.

A plain LLM brain answers questions. It does not reliably follow a multi-step
process, collect required fields in order, branch on conditions, or call your
tools at the right moment. When your voice agent needs that -
appointment booking, triage, verification flows - level up to
[SuperDialog](/superdialog/introduction): a conversation runtime that executes a
**playbook** - journeys of checkpoints that gate outcomes - turn by turn. (Flow
graphs still work too, run compiled on the same engine.)

<Frame>
  <img src="https://mintcdn.com/unpodai/9OLw2S-v9psMSqik/images/diagrams/superdialog-session-integration.svg?fit=max&auto=format&n=9OLw2S-v9psMSqik&q=85&s=523b00a42e094afe363bba777ddfe445" alt="SuperDialog session integration diagram showing user speech passing through STT, user_turn hooks, DialogMachine.turn, agent_turn hooks, TTS, and caller playback." width="1672" height="941" data-path="images/diagrams/superdialog-session-integration.svg" />
</Frame>

## Wire it in

Assign a `DialogMachine` to `ctx.session.dialog_machine` - the SDK auto-wraps
it in a `SuperDialogAdapter` (see
[Adapters](/speech-stack/adapters#auto-wrapping)). On the Playbook engine the
Talker streams real tokens straight to TTS:

```python theme={null}
from superdialog import DialogMachine
from unpod import AgentRunner, CallContext

async def handle_call(ctx: CallContext) -> None:
    ctx.session.dialog_machine = DialogMachine(
        "clinic.yaml",                       # any format; Playbook engine by default
        llm="anthropic/claude-haiku-4-5",    # runtime model
    )
    await ctx.session.run()  # hands every turn to the agent

AgentRunner(entrypoint=handle_call, agent_id="my-agent").start()
```

<Note>
  Generate a playbook once with `superdialog generate` and version-control the
  YAML. You can edit it by hand and re-run `superdialog chat` to test - no voice
  setup needed. See the [SuperDialog Quickstart](/superdialog/quickstart).
</Note>

## Voice-specific patterns

These patterns are specific to running a SuperDialog agent inside a live call.
For playbooks, tools, and sessions themselves, see the
[SuperDialog docs](/superdialog/introduction).

### Give tools call context

Define tools as closures inside your entrypoint to capture per-call data:

```python theme={null}
from superdialog.tools import tool

async def handle_call(ctx: CallContext) -> None:
    caller_number = ctx.user_number

    @tool
    def lookup_caller() -> dict:
        """Look up the caller's account by phone number."""
        return crm.lookup_phone(caller_number)   # closure over call data

    ctx.session.dialog_machine = DialogMachine(
        "clinic.yaml", llm="anthropic/claude-haiku-4-5", tools=[lookup_caller]
    )
    await ctx.session.run()
```

### Inject instructions mid-call

Push a runtime directive into the machine from a session hook:

```python theme={null}
@ctx.session.on("user_turn")
async def on_user_turn(text: str) -> None:
    if "premium" in ctx.session.data.get("tier", ""):
        ctx.session.dialog_machine.assist(
            "This is a premium customer - prioritize quick resolution."
        )
```

### Switch flows mid-call (graph engine)

`switch_flow` is a **graph-engine** feature - build the machine with a `FlowSet`.
On the Playbook engine, model the same behaviour with
multiple `journeys` and `interrupts` in one playbook instead.

```python theme={null}
from superdialog import DialogMachine, Flow, FlowSet

flows = FlowSet({"triage": Flow.load("triage.json"), "billing": Flow.load("billing.json")})
ctx.session.dialog_machine = DialogMachine(flows, llm="anthropic/claude-haiku-4-5")

@ctx.session.on("user_turn")
async def on_user_turn(text: str) -> None:
    if "billing" in text.lower():
        ctx.session.dialog_machine.switch_flow("billing", preserve_memory=True)
```

### Detect completion

Both engines have terminal states. After `run()` returns, check whether the
dialog finished or the caller hung up mid-conversation:

```python theme={null}
async def handle_call(ctx: CallContext) -> None:
    machine = DialogMachine("clinic.yaml", llm="anthropic/claude-haiku-4-5")
    ctx.session.dialog_machine = machine
    await ctx.session.run()

    if machine.is_complete:
        print("Dialog reached a terminal checkpoint")
    else:
        print("Call ended mid-conversation (hang up / timeout)")
```

## Go deeper

<CardGroup cols={2}>
  <Card title="SuperDialog" icon="diagram-project" href="/superdialog/introduction">
    The framework itself: playbooks, tools, sessions, CLI.
  </Card>

  <Card title="Embedding Guide: Unpod Voice" icon="plug" href="/superdialog/embedding-guides/unpod-voice">
    The full worked example: a SuperDialog agent inside an AgentRunner session.
  </Card>

  <Card title="Thinking in Playbooks" icon="brain" href="/superdialog/thinking-in-playbooks">
    The mental model: checkpoints that gate outcomes.
  </Card>

  <Card title="Bring Your Agent" icon="bot" href="/speech-stack/bring-your-agent">
    Prefer your own brain? Adapters for LangChain, OpenAI, Anthropic, HTTP.
  </Card>
</CardGroup>
