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 (email-based, with login) 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 log in with their email address via OTP (one-time password).
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 clicks “Chat” or opens the chat panel
- If not logged in, they enter their email
- Chipp sends an OTP to that email
- User enters the OTP (valid for 10 minutes)
- Session is created, attributed to that email
- Conversations are retained across browser sessions (until logout)
Session TTL: 8 hours per device. After logout or expiry, the user must re-authenticate.
Conversation history: Conversations are permanently stored under the user’s email. If the same user logs in from a different device, they see their full conversation history.
Anonymous mode
Anonymous users are not required to log in. Instead, a pseudonymous visitor session is created and stored in the browser.
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)
- A pseudonymous session ID is generated and stored in localStorage/sessionStorage
- Conversations begin immediately
- Subsequent messages in the same browser use the same session ID
- Conversations are retained for the duration of the session
Session TTL: 1 hour per session. If a user closes the browser or the session expires, the next chat is a new conversation.
Conversation history: Conversations are NOT permanently stored. They exist only for the duration of the session. If you need persistent history, upgrade to authenticated mode (see “Session upgrading” below).
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 → Authenticated | Start anonymous, upgrade when user signs up |
| Internal tool / employee app | Authenticated | Link to employee identity for compliance and support |
Session upgrading (anonymous → authenticated)
A common pattern is to start users as anonymous (low friction) and upgrade them to authenticated when they sign up or log in.
Frontend upgrade trigger
When a user completes authentication in your application, call the session upgrade endpoint:
// User just signed up or logged in
const userId = user.email; // Or their ID
// Get the current anonymous session ID (stored by the chat panel)
const anonSessionId = getStoredSessionId(); // Implementation depends on your setup
// Upgrade to authenticated
const response = await fetch('/api/chat/session/upgrade', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
currentSessionId: anonSessionId,
externalUserId: userId,
}),
});
const { token, threadId } = await response.json();
// Update the chat panel's session
updateChatSession(token, threadId);Backend upgrade handler
Implement /api/chat/session/upgrade in your backend:
import { ChippEmbedServerClient } from '@chipp/embed-client/server';
const client = new ChippEmbedServerClient({
baseUrl: process.env.ALCHEMIST_API_URL,
projectClientKey: process.env.ALCHEMIST_PROJECT_CLIENT_KEY,
});
app.post('/api/chat/session/upgrade', async (req) => {
const { currentSessionId, externalUserId } = req.body;
try {
const response = await client.upgradeSession({
currentAnonymousSessionId: currentSessionId,
userId: externalUserId,
});
return res.json({
token: response.token,
threadId: response.threadId, // Conversation is preserved
});
} catch (error) {
return res.status(400).json({ error: error.message });
}
});What happens after upgrade
- The user’s anonymous conversation is merged into their authenticated session
- Future messages are attributed to the authenticated email
- The user’s conversation history is now permanent (not lost when the session expires)
- If the user logs out and logs back in from any device, they see the full conversation history
Session endpoints (backend)
Your application’s backend uses these endpoints (never exposed to the browser) to manage sessions:
Create authenticated session
POST /api/client/embed/session
Content-Type: application/json
Authorization: Bearer {projectClientKey}
{
"externalUserId": "user@example.com",
"metadata": { "plan": "pro", "account_id": "123" }
}Returns:
{
"token": "embed_session_...",
"expiresAt": "2024-08-20T10:30:00Z",
"threadId": "thread_..."
}Create anonymous session
POST /api/client/embed/session/anonymous
Authorization: Bearer {projectClientKey}Returns:
{
"token": "embed_session_...",
"expiresAt": "2024-08-20T10:30:00Z"
}Upgrade anonymous to authenticated
POST /api/client/embed/session/upgrade
Content-Type: application/json
Authorization: Bearer {projectClientKey}
{
"currentSessionId": "embed_session_...",
"externalUserId": "user@example.com"
}Rotate session (refresh token)
POST /api/client/embed/session/rotate
Content-Type: application/json
Authorization: Bearer {projectClientKey}
{
"currentSessionId": "embed_session_..."
}Returns a new token with a fresh TTL.
Revoke session
POST /api/client/embed/session/revoke
Content-Type: application/json
Authorization: Bearer {projectClientKey}
{
"sessionId": "embed_session_..."
}Immediately invalidates the session. The user must re-authenticate.
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 the Chipp dashboard → Billing under 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 Billing)
To estimate costs, multiply:
(messages per user) × (avg tokens per response) × (rate per 1K tokens) × (# 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 permanently stored in Chipp
- Conversations are attributed to the email address indefinitely
- 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)
- Conversations expire after 1 hour (not permanently stored unless upgraded)
- If upgraded to authenticated, the conversation is merged and retained permanently
Multi-tenant applications
For multi-tenant SaaS (multiple customers sharing one Alchemist project), ensure proper data isolation:
-
Pass tenant context in metadata:
typescriptawait client.sendMessageAndWait({ userId: user.email, message: 'Help me', metadata: { tenant_id: user.tenantId }, // ← Isolate by tenant }); -
Scope prompts to tenant — Train the bound agent’s system prompt to respect tenant context
-
Monitor billing per tenant — Use the
metadata.tenant_idfield to track costs
GDPR / data deletion
If a user requests data deletion:
-
Revoke their session — Invalidates any active sessions
typescriptawait client.revokeSession(sessionId); -
Contact Chipp support — Request deletion of the user’s conversation threads
- Specify the email address and date range
- Conversations are permanently deleted
-
Delete local cache — Remove session tokens from localStorage (if 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 device/browser has a separate session. This is expected behavior.
- To fix, use authenticated mode or provide a login-to-sync feature.
”Session expired; user was logged out unexpectedly”
- Authenticated: TTL is 8 hours. If longer, rotate the token before expiry:
POST /api/client/embed/session/rotate - Anonymous: TTL is 1 hour. Prompt users to upgrade to authenticated for longer sessions.
”User upgraded from anonymous, but old conversation was lost”
- Verify the upgrade endpoint used the same session ID as the active session
- If a new anonymous session was created (e.g., in a different tab), they are separate conversations
- Sessions are unique per browser; upgrading one session does not affect others
”Different organizations seeing each other’s conversations”
- This should not happen (conversations are scoped by email and organization)
- Contact Chipp support if you suspect a data leak
Next steps
- Installation guide — Bind an agent
- Billing — Understand Chipp pricing & invoicing