Publish
- Open Agents, choose an Agent, then open Connect → Website.
- Add every exact website origin that may host the widget, for example
https://www.example.com. Production origins must use HTTPS. - Choose the launcher, position, colors, labels, and branding.
- Publish and copy the generated snippet:
Security model
On page load, v7 resolves only safe display configuration. When a visitor starts a call, PyAI checks the exact browserOrigin, the widget and Agent
status, account credit, and daily widget/IP limits. It then mints one
short-lived key with only omni:session, concurrency 1, the visitor origin,
and the Agent as its session label. The browser never receives a long-lived
credential.
If recording is enabled on the Agent, the widget shows the Agent’s consent
notice before requesting microphone permission.
Runtime errors
Listen forpyai:widget-error. Its detail is a stable, sanitized object:
mic_permission_denied, unsupported_browser,
origin_not_allowed, credit_exhausted, daily_cap_exceeded,
session_unavailable, websocket_failed, config_unavailable, and
consent_required. Error events never include session tokens, internal
identifiers, upstream responses, or visitor addresses.
Listen for pyai:widget:transcript to receive the same sanitized transcript
rows shown in the widget. The current public capability is
capabilities.transcript: "caller": production emits caller text only, so the
widget never fabricates Agent text from audio. detail.version is 1; its
fields are role, text, and final. Partial caller updates replace one open
row and freeze once at the response boundary. A future runtime can advertise a
broader transcript capability without changing this versioned event envelope.
Listen for pyai:widget:state to receive semantic listening, thinking, and
agent_speaking transitions derived from session controls and response audio.
Neither event nor the UI exposes raw frames, tool arguments, tokens, or
identifiers.
For a strict Content Security Policy, allow the versioned script from
https://cdn.pyai.com, API requests to https://api.pyai.com, and voice
WebSockets to wss://api.pyai.com. The runtime does not evaluate strings as
code or inject customer-provided HTML. If your policy requires nonces for
inline styles, put a nonce on the script element; v7 copies it to its style
element.
Advanced integration
Use widget v3 when you operate your own session broker and need runtime configuration from your application. Your backend must callPOST /v1/omni/sessions; do not use publishable or secret keys in browser
voice code.
The hosted widget supports the same safe declarative launcher variants and URL,
telephone, and event actions. It never evaluates custom JavaScript or HTML.