| Level | How it is set | Trusted by the server? |
|---|---|---|
| Anonymous | Nothing - the default | No. A per-browser visitor id is generated for continuity only. |
| Soft | karta("identify", { userId }) / data-user-id | No. Advisory metadata; any page can set any value. |
| Verified | userId + an HMAC identityToken | Yes. The token proves your server vouches for this userId. |
Anonymous
With no identity set, the widget stores a random visitor id inlocalStorage
so a reload resumes the same conversation in the same browser. Nothing about the
user is asserted to the server.
Soft (advisory) identity
Pass auserId (and optional attributes) to label the session for your own
analytics and to key reload continuity:
Verified identity (HMAC)
Verified identity proves to Karta that your server vouches for thisuserId, so the agent can safely act on per-user data. You sign the userId
with a per-key secret; the widget forwards the signature; Karta verifies it and
binds the verified subject into the short-lived session token.
The scheme
Compute the token on your server (never in the browser - the secret must not ship to a client):- The secret is the
identity_verification_secretyou generate on the project’s Embed tab. It is server-only and never shown in a browser. - The message is the exact
userIdstring you also pass to the widget. - The output is lowercase hexadecimal (a SHA-256 HMAC, 64 hex chars).
Server-side signing
Wiring it into the widget
Pass theuserId and identityToken together - on the tag:
user_id + identity_token to the embed token mint
(POST /v1/embed/session-tokens). Karta recomputes the HMAC with the
constant-time compare and, on a match, mints a session token whose sub is
bound to that userId. A bad signature is rejected; a userId with no token
stays soft (never bound).
The
identityToken is not an auth source on its own - the embed key (or
session token) is the credential. The token only upgrades a soft userId
to verified. Its validation is entirely server-side.Backend-minted tokens (alternative)
If you already mint session tokens server-side with akt_live_… API key, skip
the embed key entirely and hand the widget a token function or endpoint. Your
backend holds the secret key; the browser only ever sees the short-lived token.
POST https://api.karta.sh/agent_projects/:slug/session_tokens with your
kt_live_… key and returns the minted JWT. Because the kt_live_… key is the
trust anchor here, the subject you put on the token is authoritative without an
HMAC. See Session tokens.
The headless client also accepts a refreshable tokenFn (re-called with
{ force: true } after a 401) - see Headless & React.
Next
Theming & config
Generate and rotate the identity secret on the Embed tab.
Security & privacy
The credential boundaries and the data path.