# Embed limits and errors (/en/docs/developers/agent/embed/limits-and-errors)



This page covers embed tokens, Kit, iframe and Hosted. The source column distinguishes fixed validation, Dashboard policy and component behavior. Policy values come from the configuration saved for your agent.

## Limits [#limits]

| Item                           | Value and unit                                                                        | Source                                                                                 |
| ------------------------------ | ------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
| `external_user_id`             | 1–128 characters; ASCII letters, digits or `_ . : @ -`                                | Issuance validation                                                                    |
| `ttl_seconds`                  | 60–3600 seconds, capped by policy ttl\_max\_seconds; omission uses policy default     | Issuance validation and policy                                                         |
| `system_message`               | Text across all text blocks ≤8192 UTF-8 bytes                                         | Issuance validation                                                                    |
| `metadata`                     | ≤16 keys; keys 1–64 characters, string values ≤512 characters                         | Issuance validation                                                                    |
| `budget_cents`                 | 0 through policy session maximum, in US cents; omission uses policy default           | Issuance validation and policy                                                         |
| Issuance `allowed_origins`     | Subset of policy entries, matched exactly                                             | Issuance validation                                                                    |
| Policy origins                 | ≤50 HTTPS origins; wildcards match one subdomain level without a port                 | Embed policy                                                                           |
| `allow_localhost`              | false by default; allows HTTP localhost / 127.0.0.1, with optional port, when enabled | Embed policy                                                                           |
| `max_active_sessions_per_user` | 1–100 active sessions per user; idle history is excluded                              | Embed policy                                                                           |
| `per_user_rate_per_min`        | 1–600 requests/minute/user                                                            | Embed policy                                                                           |
| `blocked_end_users`            | ≤1000 user IDs                                                                        | Embed policy                                                                           |
| `monthly_cap_cents`            | Nonnegative integer US cents; null means uncapped; UTC calendar month                 | Policy and monthly accounting                                                          |
| Page context                   | ≤32 items; complete JSON ≤4096 UTF-8 bytes                                            | API validation; Kit trims oldest entries                                               |
| Session title / initial events | Title ≤500 characters; ≤50 initial plain-text user messages                           | Embedded session validation                                                            |
| Attachment picker              | ≤5 files/message; each ≤10 MiB (10,485,760 bytes); PNG, JPEG, GIF, WebP, PDF, TXT, MD | Kit input validation; the first message of a new session still accepts only plain text |
| `startScreen.prompts`          | First 4 displayed                                                                     | Kit component                                                                          |
| Hosted exchange credential     | 60 seconds, usable once                                                               | Hosted exchange validation                                                             |

The monthly action stop\_new\_sessions rejects new sessions; alert\_only does not block them. Dashboard monetary inputs use US dollars; API budget fields use cents. An exhausted session budget stops new work while retaining tool confirmation and interruption.

## Server errors [#server-errors]

These statuses apply to ordinary HTTP failures. Once a stream opens, errors arrive inside the stream and cannot change its HTTP status. Retryability refers to the original request, before changing configuration or credentials.

### EMBED\_TOKEN\_EXPIRED [#embed-token-expired]

**401 · Access · No direct retry.** The token expired. Refreshable Kit access obtains another token and replays an expiry-failed request at most once. Hosted requires a new host-issued link.

### EMBED\_TOKEN\_REVOKED [#embed-token-revoked]

**401 · Access/stream · Not retryable.** Kit stops refreshing. End old access and have the host recheck eligibility. Do not automatically issue tokens to bypass revocation.

### EMBED\_ORIGIN\_NOT\_ALLOWED [#embed-origin-not-allowed]

**403 · Origin check · Not retryable.** Check scheme, host and port against the policy and any narrower issuance allowlist. After correction, issue again and verify.

### EMBED\_USER\_BLOCKED [#embed-user-blocked]

**403 · Issuance/session creation · Not retryable.** An administrator must review the user under Operations → End users. If access should resume, unblock and issue a new token.

### EMBED\_RATE\_LIMITED [#embed-rate-limited]

**429 · Requests/session creation/anonymous issuance · Retry later.** Request frequency, active sessions or daily anonymous sessions reached their limit. Wait for the rate window, running sessions or next UTC day respectively.

### EMBED\_BUDGET\_EXHAUSTED [#embed-budget-exhausted]

**402 · Session work/anonymous issuance · Not retryable.** Session budget or daily anonymous spending is exhausted. Review the budget; continue with a new token and session only when authorized, or wait for daily recovery. Do not loop issuance to bypass limits.

### EMBED\_MONTHLY\_CAP\_REACHED [#embed-monthly-cap-reached]

**402 · Session creation · Not retryable.** The monthly cap requires stopping new sessions. An administrator decides whether to change the cap or action, or wait for the next UTC month.

### EMBED\_FIELD\_NOT\_ALLOWED [#embed-field-not-allowed]

**400 · Issuance/session creation · Not retryable.** Remove unauthorized agent\_override. Embedded session creation accepts only title, time\_zone and initial\_events. Initial events are plain-text user.message events with optional page context.

### Other refusals [#other-errors]

| Code                   | HTTP / stage                      | Recovery                                                                                     | Retryable |
| ---------------------- | --------------------------------- | -------------------------------------------------------------------------------------------- | --------- |
| `INVALID_PARAMS`       | 400 / validation                  | Correct the reported type, range or size                                                     | No        |
| `UNAUTHENTICATED`      | 401 / authentication              | Check missing/invalid credentials or a disabled publishable key                              | No        |
| `NOT_FOUND`            | 404 / resource or Hosted exchange | Verify organization, public ID and policy; obtain a fresh Hosted link if expired or consumed | No        |
| `UPSTREAM_UNAVAILABLE` | 502 / upstream call               | Retry later; check management writes for partial completion first                            | Yes       |

For session permissions, archiving and event-content errors, see [Agent limits and errors](/en/docs/developers/agent/limits-and-errors).

## Kit errors and retries [#kit-errors]

praxis.error detail can be a KitError with code, status, retryable and message, or only `{ message }`. Status 0 means no HTTP response.

| Code                                   | Status / stage                    | Recovery and retryability                                               |
| -------------------------------------- | --------------------------------- | ----------------------------------------------------------------------- |
| `network_error`, `stream_disconnected` | 0 / network or stream             | Retry after restoring connectivity                                      |
| `http_error`                           | Response status / HTTP            | Inspect response; without explicit retryable, 429 and 5xx permit retry  |
| `invalid_token`                        | 0 / token retrieval               | getToken returned an empty value; correct it, retryable                 |
| `invalid_response`                     | Response status / JSON or history | Check format and pagination progress; no automatic retry                |
| `invalid_stream`                       | Response status / stream          | Check SSE content and JSON; no automatic retry                          |
| `event_cursor_not_found`               | 200 / history recovery            | Reload history to locate the session; no automatic retry                |
| `callback_error`                       | 0 / callback                      | Fix the host exception; not retryable                                   |
| `aborted`, `disposed`                  | 0 / lifecycle                     | Cancelled request or destroyed component; do not retry the old instance |

Non-Hosted token retrieval retries retryable failures up to 3 times at 1, 2 and 4 seconds. Revocation or budget refusal stops that retry loop. Transport-owned stream recovery reconnects at most 5 times; the interface may own recovery instead. Do not add an unlimited retry loop.

## Diagnose failures [#diagnostics]

Retain time, environment, public agent\_… ID, HTTP status, error code and X-Request-Id without credentials. Check token status under Operations → Issuance records, then [replay the session](/en/docs/developers/agent/monitor). Repeat [embed tests](/en/docs/developers/agent/embed/testing) after recovery. See the [Agent API](/en/docs/api/native/agent) for field definitions.
