Skip to main content

Embed a voice, video, or capture widget on your site

Orbit ships a family of embeddable web widgets — drop-in surfaces a visitor on your site can use without leaving the page. One install pattern covers four widgets, because they all share the same public, Origin-gated mount model:
  • Native-chat web widget — the omnichannel chat surface (with an optional conversation flow: pre-chat form, FAQ deflection, routing, AI handoff).
  • AI voice-agent widget — a “Talk to AI” button that opens a browser WebRTC voice call straight to your AI agent.
  • Prebuilt video room — the OrbitVideoRoom / <orbit-video-room> drop-in video-call UI (a live room on your own page).
  • Sign-up forms — an embeddable list-growth form (inline, popup, flyout, exit-intent) you publish from a no-code builder.
Everything on this page is inbound, browser-originated media or capture. No widget here wires an outbound voice or SMS leg — a visitor starts the session from their browser, and the call or form lives on Orbit’s own media + capture path.

The shared mount model — public key + origin allowlist

Every widget below mounts with two public values, and both are safe to put in a plain HTML page:
  • public_key — your widget’s public key (today the tenant id you see in Settings → Native Chat). This is a public identifier, not a secret.
  • Your site’s origin — added to the widget’s origin allowlist under Settings → Native Chat → Privacy, or switch on Allow embedding from any domain.
The public mint routes (POST /widget/session, POST /widget/voice-agent-session, POST /widget/video-session) are anonymous and Origin-gated: they read the browser’s Origin header and only mint a session when that origin is in your allowlist. Your API key never touches the browser — only the short-lived session token the widget needs.
All the widgets read the same origin allowlist and the same widget config row, so you configure privacy once and it applies to voice, video, chat, and signup formats alike.

2. Choose the widget and its config surface

Native-chat widget + conversation flow

The chat widget is driven by an optional conversation flow you author in the no-code builder (Settings → Native Chat → Flow). The flow is the chain of decisions the widget runs on first contact: The flow is published to the widget as part of the session bootstrap; a missing or partially-written flow degrades to the plain config-bootstrapped behaviour, so a bad publish never breaks the public widget.

AI voice-agent widget (OrbitVoiceAgent)

The voice widget is the browser’s front door to your AI voice agent — a “Talk to AI” button the visitor presses to hold a live WebRTC voice conversation with the agent you bind. You configure it in Settings → Channels → Voice Agent; the install snippet generator reads the same config. The voice widget never selects a phone carrier and never routes an outbound PSTN leg — it’s an inbound, visitor-initiated WebRTC call bridged to your AI agent on Orbit’s own media stack.

Prebuilt video room (OrbitVideoRoom / <orbit-video-room>)

The video drop-in paints a complete conferencing surface — participant tiles, control bar, screen share, device picker — from a single element. The fastest path is the Video Rooms → Embed dialog in the dashboard: open a live room, choose the options (camera on join, screen share, device picker), and copy the snippet. The dialog gives you three shapes:
  • Element — the declarative <orbit-video-room> tag:
  • JavaScript — the imperative OrbitVideoRoom.init():
  • Server — the token-mint call your backend makes (never in the browser).
For a site visitor joining a room (no dashboard access), the browser mints its token through the public POST /widget/video-session mount route — same public-key + origin-allowlist model as the chat and voice widgets, so a paste-in-page snippet needs no API key. See the full video-token flow in Using a video room access token.

3. The minimal HTML embed

Whichever widget you mount, the pattern is the same: a container element, the Web SDK module, and init() with the public values. Here’s the voice agent end to end:
The chat and video surfaces follow the same shape — a container + publicKey (chat) or a minted token + serverUrl (video) + init(container, …). Mount the widget on a click (not on page load) so an idle page costs nothing.

4. Web-call context — the screen-pop half

When a visitor starts a browser voice or chat call, the widget collects where the call came from and posts it along: the page URL, page title, referrer, and an optional bag of host-supplied attributes (plan tier, cart value, account id, …). That context rides with the session as the participant’s metadata, so the agent runtime that answers — and, on a handoff, the human agent’s screen-pop — knows which page the visitor was on and who they are, instead of a cold “anonymous web visitor.” Because the context arrives from an anonymous, public browser surface, it’s strictly bounded before it touches a room token:
  • URLs must be http(s) — any other scheme is dropped.
  • Page title, URLs, and attribute values are length-capped.
  • The attribute map is count- and size-capped, and the serialized blob is hard-capped so it always fits the media token’s metadata budget.
  • A malformed or oversized field is dropped, never fatal — a bad context attribute can’t block the visitor from starting their call.
On the SDK side you pass host attributes via metadata and control auto-collection with collectPageContext (set false on a privacy-sensitive embed that should send only an explicit bag, or nothing).

5. Sign-up forms — list growth on your own page

The sign-up form is a capture surface (not a chat routing aid): a tenant-authored form with display rules, A/B variants, field→contact mappings, and a consent block, that grows your own contacts and lists. You build it in the no-code builder and it publishes to the same widget surface as the chat. Each form is made of: Every form has a version the runtime can refuse if it doesn’t recognise it, and the public surface only ever serves enabled forms — a disabled draft is withheld from the visitor’s browser.

6. Transcripts + agent trust policy

Chat transcript

A visitor can email themselves a copy of a chat conversation (POST /widget/conversations/:id/transcript). The email is optional — when omitted, the transcript goes to the address the visitor already supplied; it’s only required if they’re still anonymous. This is the same “email me a copy” touch every chat widget ships, rendered by a pure, side-effect-free renderer.

Agent trust policy

This is the tenant-facing control for which foreign AI agents you trust when a browser-resident agent (via Web Bot Auth / an AP2 directory) drives your widget. You list the foreign agent directories you choose to trust by exact HTTPS directory URL, and what to grant a verified request:
  • allow — grant access at the surface’s normal posture.
  • deny — revoke a previously-trusted directory without deleting the row.
  • rate — allow, but apply that directory’s hourly rate limit.
Nothing is trusted by default: an empty list means every foreign signature is denied, exactly as it was before this control existed — the policy can only ever grant trust, and it defaults to closed. You edit it via PUT /api/v1/settings/native-chat/agent-trust-policy.

7. Guardrails for MCP / WebMCP agents

Opening the widget as an in-page tool surface a browser-resident AI agent can drive (WebMCP / agent action calling) is hardened by a set of independent write guardrails that run before any action executes:
  1. Rate lane — a per-visitor-session, per-hour sliding-window cap on agent-invoked actions (on top of the normal IP-keyed widget rate limit).
  2. Per-session caps — cumulative ceilings on actions and preview-cost “spend” for a single session.
  3. Audit — a structured line for every agent-invoked tool call, allowed or denied.
  4. Agent-identity attestation — verify + classify the calling agent (Web Bot Auth signature and/or a scoped agent token) so you can allow, deny, or rate by identity.
  5. Reputation (KYA) — a per-tenant behavioural score that can tighten — never loosen — the trust decision, downgrading an allowlisted agent that starts misbehaving.
  6. Compliance — an agent-scheduled callback is a future outbound voice leg, so it runs through your tenant-configured quiet-hours / dialing window. Per the compliance posture this is default-open and tenant-owned: with no channel opted into quiet hours the gate allows; when you’ve configured a window and the visitor is outside it, the request is rejected with a reason.
Guardrails only ever reject or attenuate — they never originate a new outbound termination path. A callback they allow is queued and dialed by the existing dispatch worker over the platform’s normal voice termination.

Where to go next