CallState holds what one call knows. It keeps typed values, tracks which ones the caller confirmed, and fills them into your prompts. It works on any Pydantic model, on LiveKit and on Pipecat.
In the salon tutorial, Remember the caller builds this step by step.
Define what the call remembers
state.py
- Every field needs a default, because every value starts the call empty. A field with no default raises
TypeError. confirmmaps a value to the task step that must hear the caller agree to it.- Every call needs an agent id. Set
UNMUTE_AGENT_ID, or passcall=with anagent_id. With neither,CallStateraisesSettingsError.
Save a value
savechecks the whole batch first. One bad value refuses all of it, and nothing is saved.- A good value is saved in its clean form. The phone number above is saved as
+34612345678. saveis the one way in. Readstate.valuesorstate.plain("note"), but never write to them.
save_values tool all save through the same save.
Ask the caller to confirm a value
- A value in
confirmis confirmed only when its own step saves it. - Any other save makes it unconfirmed again.
- Until it is confirmed, prompts show
none recorded yet., so the model never reads a misheard value back as fact. The confirming step still sees it, so it can read it back.
Filling a prompt
{{name}}names a value.{{customer.status}}reads a path into a shape.- A name the state does not hold raises
MissingVariablesError. - Call it again after a save, so the prompt shows the new values.
UnmuteAgent, UnmuteFlows or a ModelCall, you do not call it. The library fills the prompt on every request.
Values the call starts with
call_startnames the values the dispatch sets. Arequiredone must be there, orsave_call_startraisesCallStartError.dispatchedis thecall_startobject of the dispatch. For a local run, setUNMUTE_CALL_STARTto the same JSON.- The caller is never asked for these values, and the model cannot change them.
save_call_start runs.
Values the call carries: state.call
state.call from the line. Your State class does not declare it, and only the library writes it.
The inbound, outbound and web cases, a test phone call from a web session and the read-only rules are in the State reference.
Saving values no task saves
Some values belong to no task. The model learns them in free talk. Turn onsave_values to give it a tool for them.
- Each request ends with a short block that lists every value and what it holds now.
- The model saves with the
save_valuestool.nullputs a value back to its default. - A value a task saves, or a call-start value, is refused with a reason the model can act on.
Listen to changes
- A listener gets one event per save that changed something.
listen(show, replay=True)first sends the values already set.- Call
stop()to stop listening. A listener that raises is logged and removed.
Value types
Use these classes fromunmute_core.state as field types. Each one cleans and checks the value, and refuses a bad one with a reason the model can act on.
Every rule of each type is in the State reference.
Where to go next
State reference
Every argument, rule and error, and State from type text.
Tasks
Steps that save values, and the held save at the end of a call.
Prefetch
Fill values before the greeting.
The call's life
Where call-start values are saved.
Variables on Unmute
How
agent.yaml declares the same values.