Graine AI

Chat

The typed side of the assistant on every SDK — how the chat and the call take turns, showing the chat in React Native, iOS, Android, Flutter and Kotlin Multiplatform, the window size, conversations that continue and starting a new one, drawing your own, and the chat window's design.

The chat is the same agent, typed. It knows the screen the customer is on, can run your actions, and draws the same components as the call — a list of plans, a set of time slots — in the chat window, in your brand's design. Customers who cannot talk out loud, on a train or in an office, still get the agent.

The call and the chat

What a customer gets is the agent's setting, not your code: Agent → Embed & Widgets → Appearance → Setup.

What visitors getIn your app
Call and chatThe bar opens on the one Opens on names, and carries a switch to the other
Voice onlyThe call. No switch
Chat onlyThe chat. No microphone is opened and no call engine is loaded

One conversation runs at a time. Moving to the chat ends the call, and moving back closes the chat — otherwise the agent would answer twice, aloud and in writing. A native call ends a chat as it ends a call in the bar.

How it works

The chat windowdrawn by the SDK,in your design:header, bubbles,starters, composerThe Graine SDKthe message, the screen,who the customer isanswers actions,draws componentsYour agentthe same prompt,knowledge and actionsas the call, replyingin textmessage · taptext · screenreply · componentwords as they comeThe welcome message arrives as the first reply. A tap on a component is the customer's next message.

The same agent as the call, with the same screen context, actions and components — in text.

Every SDK opens a text connection of its own for the chat — the native chat on iOS, Android and Flutter from 0.7.0 — so the chat needs no microphone and no permission, and draws in your brand's design.

Show it

The chat window in one design on two phones: on an iPhone, the demo app mid-conversation, with the welcome, the customer's request, the reply and a card of three call times; on Android, the dashboard's preview of a new chat with the brand's starters above the composer

GraineVoiceBar already draws the chat window when the agent offers the chat, with the switch when it offers both. Nothing more to mount. To open on the chat for one screen, or follow which is open:

<GraineProvider … surface="chat" onSurfaceChange={(s) => analytics.track("agent_surface", { s })}>
 
const { surface, canSwitch, setSurface } = useGraineSurface();   // "voice" | "chat"

surface chooses among what the dashboard allows; it cannot add a surface the agent does not offer.

Window size

How big the chat opens is part of the design: the Garage's Chat window tab → Window size — Compact (the default), Large or Full screen — the same in light and dark. Each agent opens at its own design's size.

On a phoneOn a tabletOn a website, on a computer
CompactThe window above the bar, as it has always beenThe sameThe panel above the launcher, as it has always been
LargeA sheet from the bottom over about 92% of the screen, the app dimmed behind it. Swipe it down, tap the dimmed app, or press the header's chevron to close itA panel 420 wide and up to 760 tall in the bottom corner on the launcher's side; the app beside it stays usableThe same panel, above the launcher
Full screenThe whole screen, with the close chevron leading the headerThe whole screenThe larger panel

Every SDK's bar draws these sizes — React Native's GraineVoiceBar, iOS's GraineAgentBar, Android's GraineAgentBarView, Flutter's GraineAgentBar and the Kotlin Multiplatform bar — and so does the website's widget. The chat views you place yourself (GraineChatView, GraineChatViewController, GraineChatActivity, Flutter's GraineChat and React Native's GraineChatScreen) fill whatever space your app gives them.

A phone is a window whose shorter side is under 600 points — or, for a website, a browser window narrower than 640 px. There a website behaves like a phone: Large is a sheet over 92% of the page, Full screen the whole page; the launcher steps aside and the page stops scrolling while it is open.

At every size the composer stays above the keyboard, the conversation, its components and the earlier messages look the same, and moving between the call and the chat keeps the size.

Your app can choose, for every chat and for one open. One open's size wins, then the app's, then the design's; a size an SDK does not know is passed over. An open moves the bar on screen to the chat, at that size, until the chat closes.

chatSize on GraineProvider for every chat, and client.openChat({ size }) to move to the chat and open it now. GraineChatScreen is the chat as a screen of your own app: while it is up, the customer is in the chat and the bar steps aside.

<GraineProvider baseUrl="https://www.graine.ai" publishableKey="pk_live_…" chatSize="large">
 
const client = useGraineClient();
client.openChat({ size: "full" });
 
<Stack.Screen name="Help">
  {({ navigation }) => <GraineChatScreen onClose={navigation.goBack} />}
</Stack.Screen>

Give the bar safeArea={useSafeAreaInsets()} (react-native-safe-area-context) for exact insets on a sheet or a full screen.

What the chat carries

In the chat
The welcome messageThe agent's first reply — not when the conversation continues (below)
RepliesText, arriving as it is written
Screen context and who the customer isExactly as for the call
Your actionsRun in your handlers, answered as for the call
ComponentsDrawn in the chat window; a tap is the customer's next message, and the structured answer goes to your webhook
MemoryWhen memory is on and the customer has an identifier — Memory
Earlier messagesFor a returning customer with memory on — below
Call HistoryThe conversation, its transcript and what happened in the app

Coming back to a conversation

For an identified customer with memory on, the chat continues where they left it — later that day, after the app was closed, on another of their devices — for 7 days after their last message with that agent. The chat window opens on the conversation instead of on a new chat:

  • The earlier messages, oldest first — up to the last 50 with this agent.
  • A voice call as one row: what was said on a call in your app or on your website shows as Voice call and the time it started, not as its transcript.
  • A date line — Today, Yesterday, or the date — wherever the day changes.
  • No starters, and no second welcome. The agent continues the conversation and the customer types next. A new call still opens with a greeting, and the agent knows what was said.

Each agent keeps its own conversation: the chat with your help desk never shows what was said to your sales agent. Messages still sending when the customer left stay at the end, and go when the chat connects.

The window opens on a new chat for an anonymous customer, a customer who turned memory off, a customer who was forgotten, and after 7 days without a message. forgetMemory() clears the chat on screen too, but only when it succeeds: a failure — Graine unavailable (503), another customer's device, no network — leaves the chat as it is, along with the memories. What is kept, and for how long: Memory → Conversations continue.

Start a new conversation

A support chat often wants a fresh thread. While the chat window holds earlier messages, its header shows New conversation — a compose icon beside close. Tapping it starts over at once, without asking: nothing is lost for your team, because Call History keeps every conversation.

Your app can do the same from a button of its own:

const client = useGraineClient();
await client.newConversation();
  • The agent's chat connection ends, Graine drops the conversation it kept for this agent and customer, the window clears, and a fresh chat opens — with the welcome message and the starters again.
  • Memory stays. What the agent remembers about the customer is untouched; to forget that, use forgetMemory().
  • Only this agent's conversation. With several agents, each starts over on its own: call it on the agent whose chat it is.
  • For an anonymous customer nothing was kept, so it only clears the window.
  • If Graine refuses — another customer's device, no network, Graine unavailable — nothing changes: the promise rejects (iOS and Flutter throw, Android's callback hears the error) and the chat is as it was.

Drawing your own chat

The SDK's chat window draws the design chosen in the dashboard. To draw your own in React Native, useGraineAgent() gives you messages, send(text) and connected, and useGraineWidget() the component on screen — Components → Drawing them yourself. Your own window stops following the dashboard's design; useGraineTheme() gives you its tokens to match. On iOS, Android, Flutter and Kotlin Multiplatform, draw from the chat's turns (messages on Android) and its state — Chat reference.

An earlier message put back when the conversation continued carries restored, and one said on a call carries channel voice: draw a run of those as one Voice call row, not as bubbles, and offer New conversation while any are on screen — GraineChatTurn. Every SDK hands you those rows, day separators included: React Native chatTurnRows(messages) (chatRows(items, read) for items of your own), iOS GraineChatRows.build(turns), Android ChatRows.build(messages), Flutter ChatRows.build(turns, now:) and Kotlin Multiplatform GraineChatRows.build(Graine.chat.turns.value) — GraineChatRows. To empty the chat on screen without ending the conversation: clear() (React Native clearChat()).

Its design

The chat window's size, title and subtitle, avatar, header, background, up to four starters, the composer's placeholder and timestamps are set in the Garage, under the Chat window tab, with the bubbles and the frame under Interior — The Garage.

Troubleshooting

What you seeCheck
No chat, only the callWhat visitors get is Voice only
No switchThe agent offers one of the two, not both
A microphone on a chat-only agentAn SDK older than native chat: update it
The agent answers twice, aloud and in writingTwo conversations are open: in React Native, a launcher and the provider's own connection — pass autoConnect={false} on SDKs older than 0.34
The chat window is not in your designYour app draws its own, or the SDK predates the design
A returning customer's chat opens emptyThey are not identified, memory is off for the agent or for them, it has been more than 7 days, or the SDK is older than 0.7.0 — Memory → Troubleshooting

Where next

On this page