What you add
First, the state. It is a Pydantic model. Every field has a default, because every value starts the call empty.salon/state.py
Phone is a type the library ships. It cleans a number and saves it with a plus and a country code. A number that cannot be right is refused.
Next, let the prompt read the state. A {{name}} placeholder is filled from the state before each model request.
salon/agent.py
CallState for each call and give it to the agent. save_values=True on the spec adds a tool the model calls to save these values.
See a refusal
You can check the state without a call. This is the same check the model’s save goes through.612345 is not a phone number, so nothing is saved. The refusal says what to fix, and the model reads it.
The confirm map says which task step must hear the caller agree to the number. Only that step can confirm it. You add the step in Book step by step, so the agent itself does not use confirm yet.
Try it
Start the agent as before. Then say these two lines.- “My number is six one two three four five.” Robin should ask again, and ask for the country code.
- “Sorry. Plus three four, six one two, three four five, six seven eight.” Robin saves it.
{{customer_phone}} on the next turn.
Why it works this way
A plain agent lets the model write any text into its memory. Here every save passes the type first, and the whole batch is refused if one value is wrong. The model gets a refusal worded for it, so it asks the caller instead of guessing. The state is a normal Pydantic model. The sameState class works on LiveKit and Pipecat.
What you have now
Next: Check the diary
Give Robin a tool that reads the salon’s diary.