Several agents in one app
Run more than one agent — a support agent in Help, a sales agent on Plans — each with its own key, design, chat and actions, while who the user is, the install and the screen stay shared; and place calls with a named agent.
Each agent is configured once under a name of your choosing, with its own publishable key. A screen talks to one of them. The user signs in once for all of them.
| Per agent | Shared by every agent |
|---|---|
| Its settings and design, its chat and its kept conversation, its bar, its components, its registered actions, its scheduling rules and bookings, its memory scope | The install, who the user is (identify once reaches all; identify(null) signs out of all), the memory choice, the current screen, the phone's one call engine |
One conversation runs at a time across all agents: starting one ends another.
What it needs in the dashboard
| Where | Setting | Value |
|---|---|---|
| Each agent → Embed & Widgets | Set up embedding | Each agent its own publishable key |
| Each agent → Embed & Widgets → Install | Allowed domains | app:// on every agent your app uses |
| Each agent → Memory → Settings | Who is the user? | The same field on every agent, so one sign-in is one person for all |
| Each agent → Calls & scheduling | Name on the incoming call | A different name per agent, so the user can tell who rings |
What to do, in order
- Configure each agent at launch: the default one without a name, the others with theirs.
- Identify the user once — on any agent. → Every agent knows them.
- Show each agent where it belongs: the views take the agent.
- Place calls with a named agent, and book calls with the agent the user is talking to. → A ring Graine sends answers as the agent that booked it, with its call name and design.
- Sign out once:
identify(null)on any agent signs out of all.
The code, platform by platform
1. Configure each agent:
→ GraineInApp.shared is the default agent; GraineInApp.named("sales") the
other (nil if never configured); GraineInApp.all every agent by name.
2. Identify once: GraineInApp.shared.identify(["user_id": user.id]).
3. The views take the agent:
GraineChatView(graine:), GraineWidgetView(graine:) and
.graineBookingSheet(isPresented:graine:) take it too.
4. Calls with a named agent:
5. Sign out: GraineInApp.shared.identify(nil).
Troubleshooting
| What you see | Why | Fix |
|---|---|---|
| The second agent does not know the user | A different Who is the user? field | The same field on every agent |
| A ring shows the wrong name | Both agents share one call name | Name on the incoming call per agent |
| Starting a chat with one agent ends a call with another | One conversation at a time, on purpose | — |
In depth: Use more than one agent in your app.

