Architecture
- Your backend calls the token endpoint with credentials + optional
env/secrets(credentials stay server-side) - Your backend sends the short-lived JWT to the browser
- The browser uses the JWT to chat via the embedded widget
Setup
1. Create a Widget App
Create a widget app in the Console. Navigate to the Widget Apps section, click Create Widget App, and configure your app name and allowed origins. After creation, copy the App ID (appId) and App Secret (appSecret) from the portal.
2. Exchange Credentials for a JWT
From your backend, call the token endpoint:
Response:
3. Embed the Widget
Add two script tags to your page — no build step required:Live Demo
See the widget in action on a live customer website:Live Customer Demo
A live website that embeds the Sigmic AI chat widget with custom branding, logo, and per-user context. Visit simple-agent-chat.space to try it.
Passing Environment Variables & Secrets
You can pass per-userenv and secrets at token exchange time to connect the agent to each end user’s data. These values are stored server-side (never in the JWT or browser) and injected into your project’s MCP servers as {{mcp.KEY}} template variables.
For example, you can configure an MCP server with "Authorization": "Bearer {{mcp.API_TOKEN}}" in its headers, then pass each end user’s API token via secrets — the agent connects to the right service for each user automatically.
Environment Variables & Secrets Guide
Full guide with examples for HTTP, stdio, and SSE MCP servers, template reference, key naming rules, and a complete multi-tenant backend example.
Widget Configuration
Token Refresh
Widget JWTs have a limited lifetime (default 1 hour). For long-running sessions, provide afetchToken callback so the widget can automatically refresh expired tokens.
How it works
- Proactive refresh: ~60 seconds before the token expires, the widget requests a new token from the parent page
- Reactive refresh: If an API call returns 401, the widget requests a new token and retries the request once
- No
fetchToken: IffetchTokenis not provided, behavior is unchanged — a 401 on expiry is surfaced as an error
Configuration
Backend example (Express)
The
fetchToken callback can be synchronous or asynchronous. The widget wraps the return value in Promise.resolve() for compatibility.Widget Events
The widget communicates with the parent page viapostMessage:
End User Scoping
TheendUserId field isolates data between your end users:
- Conversations are scoped to the
endUserIdembedded in the JWT - One end user cannot access another’s conversation history
- Use a stable identifier from your system (database ID, email hash, etc.)
Authentication Details
JWT Claims
Expiration Format
Origin Validation
When a widget app hasallowedOrigins configured, the server validates the Origin header on every JWT-authenticated request.
- Set
allowedOriginsto["*"]to allow all origins (not recommended for production) - Leave
allowedOriginsempty to skip origin validation - Origins must match exactly (e.g.,
https://mysite.comdoes not matchhttps://www.mysite.com)