userdata is what the agent knows about the person it is talking to. You seed it
on the request that starts the session, the agent reads it as {{userdata.field}},
tools write to it mid-call, and it is merged onto that person’s contact record when
the session ends — so their next conversation can start from it.
It is one bag per session, shared by every agent on that session. If you want
per-session configuration rather than facts about a person, that is
vars.
Seeding it
On the call token, the outbound call and the conversation,
userdata is a JSON
object and values may be any JSON type. On a batch recipient, values are strings.
An inbound phone call carries no request of yours, so nothing seeds it there.
What an inbound agent starts with is whatever it already learned about that caller
— see conversation memory.
Reading it
{{userdata.field}} is substituted in the prompt, the greeting and every tool
operation. A field that is not in the bag resolves to nothing — so write the prompt
so it still reads when one is absent:
userdata key that no operation in the same tool publishes first is a
warning at publish, not an error, because the session may well already hold it:
Tools writing it
Two operations write intouserdata, both taking store: "userdata":
publish_fieldson an operation that returns something — pull a value out of the response and keep it.- The
set_variableoperation — write a value you supply.
store: "tooldata" is the other choice and it is not the same thing: tooldata
lives for one tool run and is gone afterwards. The full rules are on
templating and data.
On a web voice or video call, your own page can also read and patch userdata
mid-call over the browser SDK — see web call features.
One bag, every agent
Everything on the session shares oneuserdata: the entry agent, every team
member, and any handoff target. A field written by a tool on the first agent is
readable by the third. This is true regardless of a handoff’s context policy —
summary narrows what the target model is shown of the conversation, and does
nothing to userdata.
What happens when the session ends
Two writes, in one transaction:- The call’s final
userdatais stored on the call itself.GET /v1/calls/{id}returns it asuserdata— what this call ended holding. - The same bag replaces the contact record: what the platform knows about this
person across all their conversations.
GET /v1/calls/{id}returns that ascontact_userdata.
conversation.context is. Reading it back at the start of a call is a choice
(conversation.initialize_userdata); keeping it current is not.
When a call does read it back, the request’s own userdata is layered on top: what
you send wins over what was remembered.
contact_key
contact_key is your stable id for the person, and it is what makes a contact
record a person’s record rather than a call’s.
The same key always reaches the same identity, so
userdata written on one call is
there on the next. GET /v1/calls?contact_key=... filters a customer’s whole
history. See conversations.
A worked example: one agent, personalized per call
One published agent. Nothing about it changes per call; only the bag does. The prompt:look_up_order publishes last_order_id and last_order_status
into userdata. When the call ends, all five fields are on Priya’s contact record.
An agent whose conversation.context is summary or transcript, with
initialize_userdata left on, starts her next call already knowing them, without
you sending anything.
Where to see it
The call detail view shows the finaluserdata for the call and the contact record
beside it — see calls. GET /v1/calls/{session_id} returns
both: userdata for this call, contact_userdata for the person.
Next
Conversation memory
What a new call knows about earlier ones, and
initialize_userdata.Variables
vars, system_vars, and every templating rule.Templating and data
publish_fields, set_variable, and tooldata versus userdata.