User reads and writes one data record per end user and agent, exposes the end user’s read-only profile, sends messages into their conversation, and reads that conversation back. It’s available wherever a current end user exists: tools, dynamic jobs, and trigger-fired turns. A webhook’s execute and a LuaJob have no current end user, so pass an id there; see execution contexts for what each context resolves to. For many records per agent, use Data.
Verified against lua-cli 3.33.0.
Quick example
Methods
get()
Returns the current end user, an end user by id, or one found by email or phone.string | UserLookupOptions
Omit it for the current end user. Pass a user id, or
{ email } or { phone } to look an end user up. email wins when both are set; the phone may include or omit the leading +.UserDataInstance | null
The end user’s record and profile.
null only when an email or phone lookup finds nobody. An id returns an instance even before the end user has a data record; the first write creates it.getChatHistory()
Returns the current end user’s conversation with this agent.ChatHistoryMessage. Only user and assistant turns are included; each turn’s content is a list of typed parts. Equivalent to calling getChatHistory() on the instance get() returns.
Example
Inbox.push()
Files an approval, notice, or connection-fix card in the current end user’s inbox. Parameters, receipt, card kinds, and limits are onUser.Inbox.
UserDataInstance
The objectget() returns. Fields of the data record are readable and writable directly (user.plan) and through user.data. Direct assignments stay local until save(); update() and patch() write immediately.
Record<string, any>
The stored record.
JSON.stringify(user) and console.log(user) print this object only.{ userId: string; fullName: string; mobileNumbers: string[]; emailAddresses: string[] }
Read-only identity from the platform. Assignments to it are ignored. Empty strings and arrays when the platform sent no profile.
update()
Merges fields into the record on the server and locally.Record<string, any>
required
Fields to add or replace.
Failed to update user data, with the platform’s error as cause.
In deployed agents, writing
firstName or lastName also updates _luaProfile.fullName. Local runs leave the profile untouched.patch()
Sets and removes top-level fields in one request.Record<string, any>
Fields to set. A
null value is stored as null; use unset to remove a field.string[]
Top-level field names to remove.
Failed to patch user data, with the platform’s error as cause.
unset()
Removes top-level fields; shorthand forpatch({ unset: fields }).
patch().
clear()
Deletes the end user’s whole data record for this agent. The profile and the conversation are kept, and a laterget() reads _luaProfile without recreating the record.
true under lua test; deployed agents resolve { success: true } instead. Both are truthy and a failure throws, so don’t inspect the value.
Example
Failed to clear user data, with the platform’s error as cause.
save()
Writes the whole local record (user.data) to the server.
true.
Example
Failed to save user data, with the platform’s error as cause.
send()
Sends messages into the end user’s conversation on the channel they last used: WhatsApp, Messenger, Instagram, a Teams personal chat, MessageBird, or SMS. The web widget always receives a live copy; an end user whose last channel was Slack, Front, iMessage, or RCS can’t be reached this way. To pick a channel, reach a contact with no prior conversation, or send a WhatsApp message template, useChannels.
ChatMessage[]
required
One or more parts:
{ type: 'text', text }, { type: 'image', image, mediaType }, or { type: 'file', data, mediaType }. mediaType is the MIME type of the payload.true. In a deployed agent it resolves true whether or not the message was delivered, because the runtime discards the dispatch result; under lua test a failed send throws. Never branch on the value; confirm delivery in lua logs, or use Channels.send, which returns a deliveryId for getStatus.
Example
lua test, Failed to send message, with the platform’s error as cause; deployed code never throws from send().
In
lua test, send() and both forms of getChatHistory() use the signed-in developer’s own conversation with the agent, whichever end user the instance is bound to.getChatHistory()
Returns the conversation of the end user this instance is bound to.getChatHistory().
Example
Failed to get chat history, with the platform’s error as cause.
Types
UserLookupOptions
string
Email address to look up.
string
Phone number to look up, with or without the leading
+.ProfileResponse
The platform’s profile record behind email and phone lookups. Exported for typing your own helpers; noUser method returns it directly.
string
The user id.
string
Display name.
Array<{ number: string; validated: boolean; validatedAt: number }>
Phone numbers with verification state.
Array<{ address: string; validated: boolean; validatedAt: number }>
Email addresses with verification state.
{ code?: string; name?: string }
Country, when known.
ChatHistoryMessage
string
Message id.
'user' | 'assistant'
Who wrote the turn.
string
ISO 8601 timestamp.
ChatHistoryContent[]
The turn’s parts.
'voice' | 'chat'
voice for turns mirrored from a voice call. Optional.string
Model code that served the turn. Optional.
boolean
true when the turn used the Auto model selector. Optional.{ userId: string }
Author, when recorded. Optional.
{ agentId: string; name?: string }
Agent that answered. Optional.
{ url: string }
Recording of a voice-note user turn. Optional.
ChatHistoryContent
One part of a turn.type is one of text, reasoning, tool, image, video, audio, file, source-url, source-document, or a data-lua-* string; the other fields depend on it.
string
text and reasoning parts.string
image parts: URL or payload.string
video parts: URL or payload.string
audio and file parts: URL or payload.string
MIME type of a media part.
string
tool parts, with toolCallId, input, output, and toolState.string
source-url parts, with sourceId and title.string
source-document parts, with sourceId, title, mediaType, and providerMetadata.unknown
data-lua-* parts: the original data object.ChatMessage
TextMessage | ImageMessage | FileMessage, the parts send() accepts: { type: 'text'; text: string }, { type: 'image'; image: string; mediaType: string }, and { type: 'file'; data: string; mediaType: string }.
See also
User.Inbox— approval and notice cards for the current end userData— many records per agent, with filters and semantic searchChannels— send on a chosen channel or to a cold contact- Execution contexts — which contexts have a current end user
- Identify users — how-to

