Before diving into implementation details, understand how Scenaro pieces fit together.

Scenario and publication

A scenario is the authored experience in Cockpit (prompt, features, collections, voice settings). A publication is the live UUID your frontend embeds. One scenario can have multiple publications (staging vs production). Your app always uses the publication UUID — it’s the scenario option you pass to useScenaroSession.

Two-hop authentication

Scenaro separates identity from session:
StepEndpointOutput
IdentifyPOST /v1/public/tokenuser_token (JWT), user_id, application_id
SessionPOST /v1/public/sessionTransport credentialslivekit_token, livekit_url (LiveKit is the current Transport implementation)
The legacy single-call generateToken flow has been removed. Every integration must use identify then session — useScenaroSession runs both automatically when you call start(). Identification is idempotent on the client: if a valid JWT is already in storage, no network call is made.

Transport data channel

Once connected, the voice agent and frontend communicate over the Transport data channel — implemented with LiveKit data topics today (see Transport for the engine-agnostic boundary):
  • config — agent sends feature definitions, collections, restore state
  • message:new — conversation messages (user, assistant, tool, event)
  • tool:{toolName} — dynamic tool response topics
  • state:update — frontend sends experience checkpoints to the agent
useScenaroSession subscribes to these topics for you — you only see the results (messages, config, tool calls). See the Protocol reference if you’re building on the raw channel.

Feature registry

The SDK’s FeatureProvider manages feature state (history, visibility, tool execution) but does not ship business features. Your app provides a registry:
Each registry entry maps tool names to React components and handler functions. When the agent calls a tool, the SDK session dispatches the RPC to your handler. For tools without a UI panel, you can skip the registry and pass a plain function via the tools option of useScenaroSession.

Event bus

ScenaroProvider creates a scoped ScenaroEventBus (replacing the legacy window.__ global). Subscribe with useScenaroEvents() for config, messages, tool requests, and session events.

Sub-exports mental model

LayerUse when
protocolDefining cross-language contracts, agent development, type sharing
clientNode scripts, non-React apps, API calls without UI
reactBrowser apps with voice sessions over Transport
Non-React browser apps can use the headless ScenaroSession class from @scenaro/sdk — see the Session reference.

Session lifecycle

  1. User calls start() → SDK identifies the visitor (cached JWT reused if valid)
  2. SDK starts the session and connects the Transport → status becomes 'connecting' then 'connected'
  3. Agent joins → sends config → SDK registers your tool handlers
  4. Conversation runs → messages accumulates, tool RPCs fire your handlers
  5. Agent or user ends → onSessionEnd fires, status becomes 'ended'

What stays in your app

  • Feature UI components (search, cart, comparison)
  • Brand styling and layout
  • Collection-specific API calls
  • Tool handler implementations (passed via tools or the feature registry)