Skip to main content
The manifest is the root of an integration: one JSON file, voiceos.integration.json, validated on install and on every reload. Validation errors are flat path: message strings; anything not listed here is rejected or ignored.

The smallest valid manifest

Everything else on this page is optional or a variation of these eight fields:

Top level

publisher

runtime

One of three shapes:

auth

  • apiKey fields default to required: true; values are collected via setup fields, stored encrypted, and injected as process.env.<key>. Never persisted in plaintext, never shown to the agent.
  • oauth2 is in the contract today; the VoiceOS-brokered login flow ships with the managed broker. pkce defaults to true.

permissions

All opt-in, all shown to the user at install time:

preferences

tools[]

intents[]

Intents make short Agent voice or typed requests eligible for a dedicated selector running alongside the normal agent. They reuse declared tools and do not change schemaVersion: 1. See Fast intents for a complete authoring walkthrough and rollout requirements. Utterances and responses use single-brace placeholders ({bot}) referring to slots or fixed arguments. Every required slot that is not fixed must appear in every utterance. Each required tool input must be fixed or declared as a required slot. Slot/fixed-argument keys must match /^[A-Za-z_][A-Za-z0-9_]{0,63}$/; __proto__, prototype, and constructor are forbidden.

IntentSlot

Live choices are published under MCP tool metadata _meta["voiceos/intent-slot-values"][slotName]. The SDK exports the key as INTENT_SLOT_VALUES_META_KEY. Resolved lists need 1–30 strings of at most 200 characters each. Invalid or empty lists omit the entire intent. A string enum in the live tool schema also restricts the allowed values; where both sources restrict values, VoiceOS uses their intersection. Publish changed tool metadata with notifications/tools/list_changed. VoiceOS’s optional read-only refresh hint is notifications/voiceos/refresh_intent_values, exported as INTENT_REFRESH_NOTIFICATION_METHOD. See Keeping choices current for the MCP update example and refresh behavior.

asr.vocabulary

An optional array of up to 50 nonempty terms, each 1–80 characters after trimming, with no commas or control characters. These are recognition hints for Agent voice commands, not intent slots or tool arguments. They do not affect Dictate mode or typed input, grant transcript access, or modify the user’s dictionary. The host budgets up to 10 unique terms / 1 KiB across enabled apps; provider limits also apply. Put useful terms first and reload after changing the list. See App vocabulary.

Cross-field validation

These fire even when every field parses:
  1. A tool with execution.mode: "background" requires the background permission.
  2. A select preference must declare non-empty options.
  3. An auth field and a preference cannot share a name — they share one config namespace and one env var.
  4. Every {{binding}} in a tool’s confirmation must name a property of that tool’s inputSchema.
  5. A confirmation view may contain at most one widget block, and a widget view may not also contain button/actions blocks.
  6. canvas blocks are rejected in schemaVersion: 1 (reserved for a future sandboxed renderer), and would additionally require a network permission.
  7. role: "custom" buttons/actions are rejected (reserved for a future server round-trip).
  8. Each intent references a declared tool; slots and fixed arguments name its input properties. Every required tool input is fixed or supplied by a required slot, and utterance placeholders cover required extracted slots.

Validating

or in code: validateManifest(json) / validateView(view) from @voiceos/integration-sdk — both return { ok: true, value } | { ok: false, errors: string[] }.