Alchemist: Embedded Agent - Identity & Billing
Understand authenticated vs. anonymous sessions and how billing is attributed.
The embedded-Chipp-agent supports two identity modes for end users: authenticated (your app’s own signed-in users) and anonymous (pseudonymous, no login required). This guide covers when to use each, how they work, and billing attribution.
Identity modes
Authenticated mode
Authenticated users are the people who are signed in to your app. Chipp does not show its own login. Your project’s session route (POST /api/embedded-agent/session, generated by the pack) requires your app’s login, reads the current user, and mints a chat session for that user’s id, email, and name.
When to use:
- SaaS applications with registered user accounts
- When you want to attribute conversations to a specific person
- When users have account-specific context (order history, preferences, etc.)
Flow:
- User signs in to your app as usual
- User opens the chat panel or widget
- The component calls your session route, which mints a short-lived chat token on the server
- Conversations are attributed to that user’s email
Session TTL: chat tokens last 1 hour. The generated panel and widget mint a fresh token every 10 minutes while open, so a long chat keeps working. If the user signs out of your app, your session route stops minting tokens.
Conversation history: Conversations are stored under the user’s email. If the same user opens the chat from a different device, they see their conversation history.
Anonymous mode
Anonymous users are not required to log in. Instead, a pseudonymous visitor session is created for them.
When to use:
- Public websites or landing pages
- When you want low friction (no login required)
- Floating widgets for general visitors
- Evaluation / freemium experiences
Flow:
- User opens the chat panel or widget (no login prompt)
- The component calls
POST /api/embedded-agent/session/anonymous, which mints a token for a new pseudonymous visitor - Conversations begin immediately
Session TTL: 1 hour. The generated components mint a new anonymous session each time they load, so a page reload starts a new visitor and a new conversation.
Conversation history: By default, anonymous conversations are stored like any other conversation. A binding can instead be set to ephemeral retention, which keeps anonymous conversations in a short-lived store (up to 4 hours) and never writes them to the database. Choose this in the project’s Settings tab, under Embedded agent settings > Anonymous visitors. Anonymous access must be on for the binding; generating the integration in anonymous or both mode turns it on, and a binding without it rejects anonymous sessions.
Choosing a mode
| Scenario | Recommended | Why |
|---|---|---|
| SaaS app with user accounts | Authenticated | Link conversations to user identity; retain history |
| Public website / marketing site | Anonymous | Low friction; no login required |
| Floating support widget | Either | Authenticated if you want to track user history; anonymous for open access |
| Free trial / freemium | Anonymous, then Authenticated | Start anonymous, upgrade when user signs up |
| Internal tool / employee app | Authenticated | Link to employee identity for compliance and support |
Session upgrading (anonymous to authenticated)
A common pattern is to start users as anonymous (low friction) and upgrade them to authenticated when they sign up or log in. Choose the Both identity mode for this. The pack then generates the whole flow.
What “Both” mode generates
- Session start: the panel and widget try
POST /api/embedded-agent/sessionfirst. If the visitor is not signed in (401), they start an anonymous session withPOST /api/embedded-agent/session/anonymous. - Upgrade route:
POST /api/embedded-agent/session/upgradeinsrc/services/embedded-agent/router.ts. It requires your app’s login. The browser sends only{ "anonymousToken" }. The route takes the user’s id, email, and name from your server session (never from the request body) and calls the platform’s upgrade endpoint throughupgradeEmbedSession()insrc/services/embedded-agent/client.ts. It returns{ token, applicationId, expiresAt, runtimeBaseUrl, merged }. - Browser helpers in
web/src/lib/embedded-agent/session-client.ts:upgradeEmbeddedAgentSession(anonymousToken)andnotifyEmbeddedAgentSignedIn().
What you do when a visitor signs in
- Sign-in with a page reload (a redirect or a form post): nothing. The components keep the anonymous token for the browser tab (
sessionStorage) and upgrade it on the next load. - Sign-in without a reload (an SPA login): call
notifyEmbeddedAgentSignedIn()right after login succeeds. Any anonymous panel or widget on the page upgrades and keeps the conversation.
After the upgrade, the components mint a normal signed-in session too, so the agent gets your app’s agent tools.
The upgrade endpoint requires a full-scope project client key. The Builder preview’s narrower key cannot upgrade, so in the preview the anonymous conversation does not carry over; the deployed app carries it over.
If your integration was generated in “Authenticated users only” or “Anonymous visitors only” mode, it has no upgrade route. Generate it again in “Both” mode to get one.
What happens after upgrade
- The user’s anonymous conversation is merged into their authenticated identity (
merged: true) - The anonymous token is revoked
- Future messages are attributed to the authenticated email
- If the user opens the chat from another device, they see the full conversation history
- A missing or expired
anonymousTokenis not an error: the user still gets an authenticated session, with nothing to merge (merged: false)
Session endpoints (backend)
Your application’s backend calls these endpoints on CHIPP_PLATFORM_API_URL (default https://build.chipp.ai/alchemist-api). They are never exposed to the browser. Every response wraps its fields in data.
Create authenticated session
POST /api/client/embed/session
Content-Type: application/json
Authorization: Bearer {projectClientKey}
{
"externalUserId": "user_123",
"email": "user@example.com",
"name": "Ada"
}externalUserId and email are required; name, workspaceId, and sessionScope are optional.
Returns:
{
"data": {
"token": "...",
"expires_at": "2026-08-20T10:30:00Z",
"application_id": "..."
}
}Create anonymous session
POST /api/client/embed/session/anonymous
Content-Type: application/json
Authorization: Bearer {projectClientKey}
{}Returns the same fields plus retention ("retained" or "ephemeral").
Upgrade anonymous to authenticated
POST /api/client/embed/session/upgrade
Content-Type: application/json
Authorization: Bearer {projectClientKey}
{
"anonymousToken": "...",
"externalUserId": "user_123",
"email": "user@example.com"
}Returns the same fields plus merged (boolean).
Rotate session (refresh token)
POST /api/client/embed/session/rotate
Content-Type: application/json
Authorization: Bearer {projectClientKey}
{
"token": "..."
}Returns a new token with a fresh TTL. An invalid, expired, or revoked token returns HTTP 400 with code invalid_session.
Revoke session
POST /api/client/embed/session/revoke
Content-Type: application/json
Authorization: Bearer {projectClientKey}
{
"token": "..."
}Immediately invalidates the token and returns { "data": { "revoked": true } }. Revoking an already invalid token is not an error.
Upgrade, rotate, and revoke require a full-scope project client key.
Billing attribution
Usage is billed through the normal Chipp metering path. Every message sent to the bound agent is metered and attributed to the organization that owns the agent’s application.
How it works
- Your Alchemist project binds a Chipp agent (e.g.,
app_abc123) - End users interact with that agent (via UI, backend client, or API)
- Chipp records each interaction (message, token count, etc.)
- The application owner’s organization (
org_xyz) receives the invoice - You see usage in Settings > Billing for that organization
Example
- Organization:
org_acme(your company, Acme Inc.) - Agent:
app_support(customer support bot) - Bound to: Alchemist project
proj_website - Users: 1,000 customers using the floating widget on
www.acme.com - Billing:
org_acmeis billed for all 1,000 customer interactions (token usage, etc.)
Cost estimation
Costs depend on:
- Number of messages: Each user message = 1 metered interaction
- Token usage: Agent responses consume tokens based on model (GPT-4, Claude, etc.)
- Custom actions: Tool calls and integrations may incur additional costs
- Rate: Chipp’s standard metering rates apply (see Pricing)
To estimate costs, multiply:
(messages per user) x (avg tokens per response) x (rate per 1K tokens) x (# users)Cost control strategies
- Set reasonable timeouts - Prevent long-running requests that consume unnecessary tokens
- Monitor usage - Check the Chipp dashboard weekly to track token consumption
- Limit capabilities - Disable expensive features (file uploads, long knowledge bases) if unneeded
- Rate limiting - Implement application-level rate limits on chat endpoints
- Anonymous mode - For public websites, use anonymous mode to keep exploration costs low
Privacy & data retention
Authenticated sessions
- User email and conversations are stored in Chipp
- Conversations are attributed to the email address
- User can request data export or deletion (contact support)
Anonymous sessions
- No personally identifiable information is collected
- Session ID is pseudonymous (not linked to user identity)
- With the default
retainedsetting, conversations are stored like any other; withephemeral, they are kept only in a short-lived store - Inactive anonymous visitors are removed after 90 days
- If upgraded to authenticated, the conversation is merged into the user’s identity
Multi-tenant applications
For multi-tenant SaaS (multiple customers sharing one Alchemist project), ensure proper data isolation:
-
Use a distinct identity per user. Conversations are scoped to the user’s identity (keyed by email), so one user never sees another user’s threads.
-
Pass tenant context per message with
hostContext, using only keys you list incontextKeysinchipp/agent.json:typescripttransport.sendMessage(threadId, 'Help me', { clientMessageId: crypto.randomUUID(), hostContext: { tenantPlan: 'enterprise' }, });The runtime drops any key not on that list. Never put personal data in it.
-
Scope prompts to tenant - Write the bound agent’s system prompt to respect tenant context
Usage is billed to the agent owner’s organization as a whole; there is no per-tenant billing breakdown.
GDPR / data deletion
If a user requests data deletion:
-
Revoke their session - Invalidates the active token
plaintextPOST /api/client/embed/session/revoke { "token": "..." } -
Contact Chipp support - Request deletion of the user’s conversation threads
- Specify the email address and date range
-
Delete local cache - Remove any session tokens your app stored client-side
Troubleshooting
”User sees different conversation history on different devices”
- In authenticated mode, all devices see the same history (email-based). Verify the email is consistent.
- In anonymous mode, each page load starts a new visitor. This is expected behavior.
- To fix, use authenticated mode.
”Session expired”
- Tokens last 1 hour in both modes. The generated components re-mint authenticated tokens every 10 minutes. If you mint tokens yourself, rotate before expiry:
POST /api/client/embed/session/rotate - Anonymous: prompt users to sign in for persistent history.
”User upgraded from anonymous, but old conversation was lost”
- With the generated integration, check the identity mode is “Both”, and that an SPA login calls
notifyEmbeddedAgentSignedIn() - In the Builder preview the conversation never carries over (the preview key cannot upgrade); test on the deployed app
- Verify the upgrade request sent the visitor’s current anonymous token
- Check
mergedin the upgrade response:falsemeans no valid anonymous token was presented - Each anonymous session is a separate visitor; upgrading one does not affect others
”Different organizations seeing each other’s conversations”
- This should not happen (conversations are scoped by user and agent)
- Contact Chipp support if you suspect a data leak
Next steps
- Installation guide - Bind an agent
- Pricing - Understand Chipp pricing