Quickstart
agent.py
CallState.settle_held() directly, as above.
Why use unmute for this
A model sometimes saves a guess, or an answer from an earlier step. The library refuses that save and makes the model ask. It still keeps the answer the caller gave before the step began, in case the call ends first.What a held save is
A step’s first reply may try to save values before the caller said anything in that step. To settle a held save is to decide, when the call ends, whether to keep it. The save is refused, because the model guessed or reused an old answer.- The model reads the refusal and asks the caller.
- When the refused reply already spoke, like “Your note: a call back. Is that right?”, no second reply follows. The caller answers next.
- The refused values are held for the end of the call. The caller may have given the answer before the step began, and heard the agent take it.
- When the call ends with a save still held, the result depends on what the caller did after the hold.
- A value saved this way is never marked confirmed. No step was left to confirm it.
- The step’s next finish releases the hold, so a step that goes on normally never uses it.
- The decision waits at most 4 seconds. One that fails or runs out of time saves nothing.
- A step whose values come from its own tool holds nothing. The caller cannot have given those before the step began.
- Let the adapter settle held saves when you can.
- Read a value saved this way as unconfirmed.
Settle held saves on each framework
On each framework. Each adapter settles held saves when the call ends:- LiveKit: automatic, when the session closes.
- Pipecat: with
UnmuteFlows(call=...),await call.end(...)afterrunner.run()settles them. Without hooks, callawait flows.settle()when the caller hangs up, before theEndFrame. The decision is then traced in the last turn.
CallState.settle_held() does the work. A host without an adapter calls it
directly:
Troubleshooting
A value is saved but never marked confirmed
It was saved from a hold. No step was left to confirm it. Fix: none is needed. Ask the caller again in a later step if you need it confirmed.Held values are lost on Pipecat
Nothing settled them when the caller hung up. Fix: passcall= to UnmuteFlows and call await call.end(...) after runner.run(). Without hooks, call await flows.settle() before the EndFrame.
In the salon tutorial: Book step by step.
Every argument: Tasks reference.
Where to go next
Reply and confirm in code
Ask the caller before a closing tool runs.
State
How the call state keeps held values.
How a step ends
The finish check that a held save uses.