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 when the session ends its changes are merged onto that person’s contact record. Per-session configuration that should not follow the person belongs in vars.

Seeding it

An inbound phone call carries no request, so nothing seeds it; it starts from the contact record if conversation memory loads it.
Keys starting with _talqing are reserved and refused with a 400.

Reading it

{{userdata.field}} is substituted in the prompt, the greeting and every tool operation. A missing field resolves to nothing, so write the prompt to survive a blank:
The prompt and greeting resolve once, when the agent starts (or a handoff target takes over). A tool resolves on each run, so it sees whatever an earlier tool wrote.
The greeting is spoken exactly as it resolves: "Hi {{userdata.name}}, thanks for calling" becomes "Hi , thanks for calling" with no name. Only put a field in the greeting when every request that starts the session supplies it.
A tool reading a userdata key that no earlier operation in the same tool publishes is a publish warning, since the session may already hold it.

Writing it from tools

Two operations write with store: "userdata": publish_fields on an operation that returns data, and the set_variable operation.
store: "tooldata" lasts only for that tool run. Full rules: templating and data. The browser can neither read nor write userdata: it is seeded by the request that starts the session — on a web call, POST /v1/calls/token on your server — and changed only by tools during it. There is one userdata per session, shared by every agent on it — team members and handoff targets included, whatever the handoff’s context policy.

The contact record

When a call ends (and after each chat turn):
  • GET /v1/calls/{session_id} returns the call’s final bag as userdata.
  • What the call changed is merged onto the contact record, returned as contact_userdata: keys set or changed are written, keys removed are deleted, other keys are left alone. The request’s seeded userdata is merged too.
This happens on every call, whatever conversation.context says. Because only changes are written, a call that never loaded the record cannot wipe it, and two concurrent calls with the same person do not undo each other. PATCH /v1/conversations/{conversation_id} with userdata is the exception: it replaces the whole bag. Loading the record at the start of the next call is conversation.initialize_userdata; the request’s own userdata is layered on top and wins.

Who the person is

contact_key is at most 256 characters and cannot start with a reserved prefix. Omit it and Talqing mints a single-use one: the call has no history and leaves none a later call can find. On a number the identity is the pair of numbers: one contact, and one userdata, whether they call it, call it on WhatsApp or message it on WhatsApp. The same person reaching a different number of yours is a different contact. GET /v1/calls?contact_key=… lists one person’s calls.

Next

Conversation memory

What a new call loads from earlier ones.

Variables

vars, system_vars and templating rules.