Graine AI

Variables

What your app can tell the agent — traits from identify, variables set at start-up or while the app runs, a call's reason — how each reaches the prompt's placeholders, what the agent sees in a chat, in the voice bar, on a call either way and on a call Graine rang, the limits on each path, the reserved keys, and what happens when a set is too big.

The agent's prompt reads placeholders — {name}, {plan}, {call_reason} — and your app fills them. A variable is a name and a short text value; the prompt uses it wherever it names it, in every channel the user meets the agent on.

What your app can send

SourceHowWhen it appliesMasked on the device
Traitsidentify(traits) — every trait except the identifierThe next conversationYes
Variables at start-upGraineConfig(variables:), the provider's variables, GraineAgent.load({ variables })Every conversationNo — your own constants
Variables while the app runssetVariables(values) (not on the website); null under a key removes itThe next conversationYes
A call's ownstartCall(reason:, variables:)That callYes
Set by Graine on callswho_called, call_reasonThat call—

The identifier — the trait your Who is the user? setting names, user_id by default — is never a variable: it identifies the user and nothing else. Masking replaces PAN, Aadhaar, card and account numbers, phone numbers and emails with a token ([PHONE], [EMAIL] …) before anything leaves the device; your own formats can be added (addMaskRule).

Merged in this order, the later winning on a shared name: any default values the dashboard holds for the agent, the variables at start-up, setVariables, the traits — and, on a call, the call's own variables, call_reason, then who_called.

How a variable reaches the prompt

  • The prompt names it. {plan} in the prompt (or the welcome message) reads the value sent under plan. List the agent's variables under its Custom Variables too: the Install tab's website snippet is written from that list, and your team sees what the prompt expects.
  • A variable nothing sets renders empty. Write sentences that read well without it: Hi {name}, welcome back reads "Hi , welcome back" for an anonymous user; Greet the user by name if you know it: {name} does not break.
  • Values are text. Numbers and booleans become their text (2, true); nested objects are dropped on iOS, Android, Flutter and Kotlin Multiplatform, and sent as JSON text by React Native.
  • Reserved names render empty. A {graine_…} placeholder never shows a value.

What the agent sees, channel by channel

ChannelWhat carries the variablesLimitsAlso set
Chat (every SDK and the website)The signed ticket that opens the conversation12 variables; names cut to 40 characters, values to 200; over about 1 KB in all, the SDKs leave off the biggest first, one at a time, until the rest fit (0.9.0) — from a website, over 1 KB none travel—
The voice bar, Standard call audioThe signed ticketThe same—
The voice bar and the website's voice, WebRTC call audio (High quality)The call itself40 variables; names cut to 64 characters, values to 300; then, when everything the call carries is over its budget (about 1.6 KB), the biggest values are dropped first until it fits—
A call the user places (the call engine)The signed ticketwho_called and call_reason first, then the call's own variables, then yours: 12 in all, 200 characters each; past about 1 KB the biggest are left off first, who_called and call_reason lastwho_called = customer; call_reason = your reason
A call Graine rang (booked by the agent, the user or your team)The signed ticket; the booking's reason added by Graine when the call connectsAs abovewho_called = scheduled; call_reason = the booking's reason
A call your own server rangAs above, with the push's variablesAs abovewho_called = agent; call_reason = the push's reason
Any of these three calls over WebRTC (0.9.0, with the SDK's WebRTC module)The call itself: the same set the signed ticket would carryAs above — the SDK trims the set the same way before it leaves the phoneAs for its direction

The iOS, Android, Flutter and Kotlin Multiplatform SDKs (from 0.8.0) and React Native (from 0.43.0) send the variables of a chat and of a call only in the signed ticket; the address of a connection opened with a ticket does not repeat them. The website's voice still repeats them on that address too; the agent reads the ticket's, so what it sees is the same. A connection opened without a ticket — rare: only when one cannot be issued — carries them on its address instead.

A ring itself carries no reason and no variables: only the call's id, the call name and the agent. The reason stays with Graine until the user answers.

Keep the set small: a name, a plan, an order number — 12 at most, a few hundred characters in all. Long text (a history, a document) does not belong in variables: over 1 KB on the ticket, the SDKs leave off your biggest values first — so the long one is the first to go — and from a website none of them reach the agent in that chat.

Reserved keys

Every key starting with graine_ is Graine's own, written only by Graine's servers:

KeyWhat it is
graine_user_keyThe one-way key memory and devices use for the user
graine_install_refThe install, as a one-way key
graine_memoryWhether this user's conversations are remembered
graine_devicesHow many devices the user may use
graine_tzThe device's time zone
graine_call_idThe call a ring or a placed call belongs to
graine_user_id, graine_user_fieldThe identifier and its field, for Call History

Your app can never set them: a graine_… key in setVariables, in identify's traits, in a call's variables or in load({ variables }) is dropped before the conversation starts — on every path — so no app can claim to be a user it is not. None of them is ever a prompt variable.

What you'll see if…

You sendWhat happensWhat to do
More than 12 variables (chat, Standard voice)The rest do not travel; which 12 depends on the platform's orderKeep the set to 12, traits included
More than 12 on a callwho_called, call_reason and the call's own travel; yours fill what is leftPass the call's essentials in startCall(variables:)
A value over 200 characters (300 on the voice bar's WebRTC call)Cut at the limitShorten it
A name over 40 characters (64 on the voice bar's WebRTC call)Cut at the limitShorter names
Over 1 KB in all, in a chat or a callThe SDKs leave off the biggest values first, one at a time, until the rest fit — who_called and call_reason last (0.9.0; before, none travelled). From a website, no variables at all in that conversationFewer, shorter values
Over the budget on the voice bar's WebRTC callThe biggest values dropped first, until it fitsFewer, shorter values
A graine_… keyDropped; the agent never sees itUse another name
An object or a listDropped (React Native: sent as JSON text)Send text
A placeholder the prompt names but nothing setsIt renders emptyWrite the prompt to read well without it

Examples

// At start-up: your own constants
GraineInApp.configure(GraineConfig(baseUrl: "https://www.graine.ai", publishableKey: "pk_live_…",
                                   variables: ["app_name": "Acme"]))
// Who is signed in: the identifier, then traits that become variables
GraineInApp.shared.identify(["user_id": user.id, "name": user.firstName, "plan": user.plan])
// While the app runs; nil removes one
GraineInApp.shared.setVariables(["cart_items": 3, "promo": nil])
print(GraineInApp.shared.currentVariables())             // the merged set, as the next conversation gets it
// One call's own
GraineInApp.shared.calls.startCall(reason: "order_help", variables: ["order_id": "A-1042"])

The prompt side

How a prompt might use them — in the agent's prompt, in the dashboard:

The user's name, if known: {name}. Their plan: {plan}.
If {who_called} is "customer", they called you: ask how you can help with {call_reason}.
If {who_called} is "scheduled", you are calling at a time they booked: say so, and talk about {call_reason}.
If {who_called} is "agent", the app's own team asked you to call: explain why, from {call_reason}.

Where the user's details come from: Identify the user · calls in both directions: the user calls, Graine rings.

On this page