Skip to main content
Use separate models to choose how your agent hears a caller and speaks its answer. In a cascade, transcription produces text, a reasoning model answers, and a synthesizer speaks. Turn detection decides when to start the reply. Streaming lets some stages overlap. On this page:

Quickstart

Create a new package with a LiveKit target. If initialization opens the console, select LiveKit and finish creating the package.
Terminal
Replace voice-desk/agent.yaml with this complete file:
voice-desk/agent.yaml
Keep the scaffold’s targets.yaml, but remove its target-level models: overrides because the model palette above replaces the scaffold’s. Keep its framework provider and version pin, and remove any phone connection: for this browser example. Replace voice-desk/instructions.md with this complete prompt:
voice-desk/instructions.md
Set OPENAI_API_KEY and SLNG_API_KEY in your shell or the package’s .env, then run:
Terminal
Use Docker for this LiveKit run. The Pipecat target is another option; it runs locally with uv. The example below stays with this same desk agent.

Pros and cons

Pros

  • Control the workflow. On LiveKit and Pipecat, combine tasks, handoffs, saved values, and tool calls. Each step can have its own instructions and access to the values it needs.
  • Choose each role. Use a supported transcriber, reasoning model, and voice independently. Spend more on the part that needs better quality without replacing the others.
  • Find the failing stage. Compare the recognized text, model reply, tool result, and spoken output. A wrong transcription needs a different fix from a failed tool.

Cons

  • More sources of delay. Turn detection, transcription, reasoning, speech generation, and tools all contribute. Streaming reduces the wait, but does not remove those costs.
  • More parts to operate. Several integrations bring separate credentials, availability limits, and failure modes.
  • Less audio context for reasoning. A transcript carries the words, but can lose tone, hesitation, and other clues in the caller’s voice.
LiveKit’s comparison explains these component tradeoffs. Coval’s comparison shows why control and diagnosis matter when the agent must complete real work.

1. Bind the three models

The quickstart names the transcriber, reasoning model, and voice under models. The agent binds its reasoning and voice by name. A single transcriber is selected automatically for the package.
cascade | realtime | live
Set cascade, or omit the key for the same result. Cascade is supported on all three targets, subject to each target’s model and feature limits.
a models.think entry name
required
Agent-level reasoning binding, such as agents.desk.think: reasoning.
a models.speak entry name
required
Agent-level voice binding, such as agents.desk.speak: voice.
a models.listen entry name
Package-level selector. Omit it when there is one transcriber; name an entry when there is more than one. It does not belong under an agent.
A model name is forwarded to its provider. Validation checks the binding, not whether your account can use that model.

2. Choose when the agent replies

The quickstart binds LiveKit’s local turn detector. A cascade needs a turn binding. When adding Pipecat, override detector for that target with provider: local and model: silero. Follow Turn detection for the target override shape and timing options.
a models.turn entry name
Package-level selector. One turn entry is selected automatically. With several entries, name the one to use here.
Listen for pauses and interruptions before changing settings. A shorter silence window can answer faster but may cut off callers who pause mid-sentence.

3. Add tools, tasks, or saved state

Extend the same desk with a local tool, then add a task when a job needs its own steps. For example, the caller wants to change an existing request:
  1. Look up the request with a tool.
  2. Collect the change in a task and save its result.
  3. Confirm the details before running the update tool.
  4. Handle a refused update, or hand the call to another agent with the context it needs.
Variables hold values across steps. Each prompt names the values it may read; the tool checks the conditions for changing the record. Separate steps give you places to check the behavior, but do not guarantee a correct tool call. Test successful updates, missing inputs, and failed actions. Tasks, task groups, and handoffs are supported on LiveKit and Pipecat cascade targets. SLNG has its own target limits. Both S2S architectures support tools, but their current Unmute integrations do not support these task and state controls. The complete salon concierge shows booking, task return, and handoff. Its phone routes and tracing need their own configuration and credentials.

Advanced

Transcription can run while the caller speaks, and synthesis can begin while the model generates text. Do not add all stage durations as though every stage waits for the previous one to finish. Model choice, turn timing, network placement, and tools affect the wait for the first audio.Tune the slow stage before replacing the architecture, and compare completed actions as well as response time. See where the time goes and the architecture comparison.
Follow Switch architecture. Replace the model palette and the agent’s think:/speak: bindings together. Remove old target overrides and any features the destination refuses.
Use the quickstart’s complete agent.yaml for a minimal cascade, keeping your prompt file. For an existing package, copy its model palette and think:/speak: bindings instead, and add the required provider secrets. Remove models.live, models.realtime, and the old agent binding before validating. Do not replace a larger package’s whole file if you need to retain its tools or workflow.

Troubleshooting

Validation rejects an agent-level listen field

Listening is selected for the package, not for each agent. Fix: move the selector to the top level, or omit it when only one transcriber exists.

The agent waits too long or cuts callers off

Turn settings or provider latency may be responsible. Fix: inspect the dev measurements and follow Turn taking before replacing all three models.

A provider is refused for one role

Targets support different providers for each role. Fix: choose a supported integration from that role’s reference, then validate every declared target.

Where to go next

Add a task

Give one job its own workflow.

Choose architecture

Compare and switch pipelines.