> ## Documentation Index
> Fetch the complete documentation index at: https://docs.voiceos.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Limits & stability

> Every cap in one place, the security model, and the compatibility promise.

## Size limits

### Cards

| Limit                           | Value                                                                                                                |
| ------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| Blocks per glance card          | 3                                                                                                                    |
| Charts per card (and per `row`) | 1                                                                                                                    |
| Glance payload (serialized)     | 32,000 chars — 96,000 when a widget block is present                                                                 |
| Per-field string caps           | See the [glance](/integrations/reference/glance-blocks) and [UI](/integrations/reference/ui-blocks) block references |

### Widgets (identical as a result block and as a confirmation view)

| Limit                                      | Value                                                                                      |
| ------------------------------------------ | ------------------------------------------------------------------------------------------ |
| `html`                                     | 131,072 chars (128 KB)                                                                     |
| `data` (serialized)                        | 16,384 chars                                                                               |
| Height                                     | 60–420 px (default 180)                                                                    |
| `label` / `confirmLabel`                   | 60 chars                                                                                   |
| Confirm-button reserve (confirmation mode) | \~150 × 44 px, bottom-right                                                                |
| Outer corner radius                        | 26 px (a host with a concentric clip may send its own) — read `--k-radius`, never hardcode |

### Widget Kit asset budgets

| Limit                                  | Value                                  |
| -------------------------------------- | -------------------------------------- |
| One inlined image                      | 32,768 data-URI chars (\~24 KB source) |
| One inlined font (pre-subsetted WOFF2) | 42,000 data-URI chars                  |
| All inlined images combined            | 65,536 chars (half the HTML budget)    |

### Bridge messages

| Limit               | Value           |
| ------------------- | --------------- |
| `updateInput.key`   | 256 chars       |
| `updateInput.value` | 16,384 chars    |
| `openUrl`           | https URLs only |

## Degradation order

Nothing on the card surface fails loudly, and nothing vanishes without a
rule:

1. An **off-schema block** is dropped individually; its siblings render.
2. **Over-budget blocks** (4th block, 2nd chart) are dropped in declaration
   order.
3. A Widget-Kit card over the HTML budget sheds **content images first**
   (never the integration mark), then **trailing blocks** — the header goes
   last. (`renderCustom` throws instead, so you find out in your test run.)
4. A card with zero valid blocks is dropped whole — the spoken answer still
   happens.

`bun verify.ts` is how you catch all of this before a user does.

## Timing

| Budget                      | Value                                                                                                                              |
| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `sync` tool                 | Return within the turn; target well under 30 s, with \~8 s timeouts on your own fetches.                                           |
| Anything longer than \~20 s | Declare `execution.mode: "background"` + the `background` permission.                                                              |
| Setup-field prompt          | The user gets \~75 s to fill the notch card within the turn; the card survives past that and saves late answers for the next turn. |

## Security model

* **Process isolation.** Integration code never runs inside VoiceOS
  processes and never sees VoiceOS secrets. `local-mcp` servers run as child
  processes on the user's machine; `remote-mcp` runs on your infra.
* **UI is data.** Declarative blocks can't reach host APIs, and `markdown`
  is sanitized. Anything off-schema degrades to a safe placeholder.
* **Widgets are sandboxed.** Opaque origin, no network egress, validated
  postMessage only, clamped heights — and **no approve leg**: only VoiceOS's
  own button (or the user's voice) can approve an action.
* **The model never sees your UI, and can never author a widget.** Glance
  payloads are stripped from tool results before the model reads them, and
  the parser refuses `widget` blocks outside integration surfaces.
* **Secrets stay out of band.** Setup values are stored encrypted, injected
  as env vars, never echoed to the UI, and never enter the agent transcript.
* **Consent at the edges.** Permissions are declared in the manifest and
  shown at install; acting tools confirm before running; users hold per-tool
  "Asks first" overrides.

## Stability

Two version gates cover the whole contract:

| Constant                  | Current |
| ------------------------- | ------- |
| `MANIFEST_SCHEMA_VERSION` | 1       |
| `UI_SCHEMA_VERSION`       | 1       |

The promise (the "Minecraft rule"): **additive changes never bump them**. New
blocks, new fields, and new permissions arrive without breaking existing
manifests, and hosts render unknown future blocks as safe placeholders. An
integration authored today keeps working across years of VoiceOS updates.

Reserved-but-declared surfaces you'll see in the types — `hosted` runtime,
`store` and `webhook` permissions, `canvas` blocks, `role: "custom"`
actions, brokered `oauth2` — exist so that when they ship, nothing you wrote
changes.
