Content-Security-Policy
If your site sends a CSP, allow the widget the following. These assume the default runtime originhttps://agent.karta.sh; if you set a custom
data-base-url, use that origin instead.
script-src https://cdn.karta.sh- the async loader (karta.js) and the code it lazily imports are served from the CDN.connect-src https://agent.karta.sh- from your page the loaderfetches the embed token mint (/v1/embed/session-tokens) and runtime config (/v1/embed/config) from the runtime origin. Use yourdata-base-urlorigin here if you override it.frame-src https://agent.karta.sh- the widget UI runs in a cross-origin iframe served from the runtime origin. The streaming session traffic runs inside that iframe against its own origin, so it needs nothing more from your page’s CSP.
The widget UI is isolated in a cross-origin iframe, so its styles and scripts
are scoped to the iframe’s own document and never touch your page - you do not
need
style-src 'unsafe-inline' for the widget. It also uses no eval or
new Function, so no script-src 'unsafe-eval' is needed.Origin allowlist
The publishablepk_live_... embed key is meant to ship in your page’s HTML - it
is not a secret. Its blast radius is fenced by the allowed-origins allowlist,
not by hiding the key.
- The browser sends its real
Originheader on the token mint. Karta reads that header (never a body-supplied value, which a hostile page could spoof) and refuses the mint if the origin is not on the key’s allowlist. - The match is exact on scheme + host + port. There are no wildcards - list each origin you embed on.
- Rotating or disabling the key on the Embed tab cuts off token minting immediately.
Hosted agent pages
The public/{org}/{agent} and /{org}/{agent}/embed pages are served from the
agent origin. They are top-level or iframe documents, so they do not depend on
JavaScript from your page.
When a hosted page runs without an explicit ?key=pk_live_xxx, it gets runtime
config from /v1/embed/first-party-config and mints a browser-safe session token
through /v1/embed/first-party-token on the same origin. Those endpoints are for
Karta-hosted pages. For your own page, use a publishable embed key with
/v1/embed/session-tokens, or mint a session token
from your backend.
The safety model
The widget never holds a long-lived credential, and anonymous traffic is bounded:- Short-lived session tokens. The embed key is exchanged for a short-lived, agent-scoped session token per session. The browser only ever holds that expiring token, never an API key.
- Anonymous spend cap. Each key has a hard ceiling on what anonymous (non-verified) traffic can cost per period, set on the Embed tab. On hit, minting stops.
- Rate limits. The token-mint edge is rate-limited per IP, as a backstop against a key being hammered from one source.
Graceful limits
When a usage, spend, or rate limit is hit, the widget does not show a raw error. It shows a calm “check back later” state, locks the composer so the user cannot keep hammering a capped agent, and emits a first-classlimit_reached event (with an optional
retryAfterSeconds) so your page can respond - for example, surfacing a contact
form. A hard cap has no client-side recovery within the page’s lifetime; the
limit clears server-side on its period boundary.
Privacy & data path
Be accurate with your users about where their chat goes:- Chat content reaches Karta and the model provider. Messages the end user types are sent to Karta and on to the model provider that backs the agent (your own, under BYOK, or Karta’s). See Trust & compliance for operator-access guidance.
- Soft identity is advisory. A soft
userIdis metadata, never an auth credential, and any page can set it. Use verified identity to bind a trusted subject, and a signedcontextbag when the agent needs facts about the user it can rely on. - The optional pre-chat consent string. The widget can show a pre-chat disclosure before the first message - with an optional Accept gate - to tell users the chat is AI-assisted and link your privacy policy. The disclosure text is sanitized through an escape-first renderer, so it is safe to author but cannot contain executable markup.
What you should disclose
As the site embedding the widget, you are the data controller for your users’ chats. Disclose, per your jurisdiction, that:- conversations are processed by an AI agent and sent to Karta and a model provider to generate replies;
- what you log or retain on your side. The widget keeps no chat transcript in the page; conversation continuity comes from server-side session state, so a reload can resume the session;
- how a user can reach a human, if you wire the
escalatehook.
Related
Session tokens
The short-lived, agent-scoped credential the embed key is exchanged for.
Identity
Anonymous, soft, and verified (HMAC) end-user identity.
Trust & compliance
The platform’s broader security posture and operator access.
BYOK
Keep your model-provider credentials under your own control.

