Skip to content

Bodhi integration surfaces ​

This document defines the two external integration surfaces for Agent Studio agents on a hosted Bodhi deployment. Pick one primary surface per product integration; they are intentionally separate.

Where the hosted client fits (your app only implements Leg 1; Bodhi runs Leg 2 to the model vendor):

text
[Your app / browser] ─── Leg 1 ───> [Bodhi / VoiceSession] ─── Leg 2 ───> [Gemini or OpenAI]

Surface A and Surface B both attach at Leg 1 (HTTPS + WebSocket or embed). They do not change how Bodhi connects to Google/OpenAI internally.


Surface A — Programmable API (full control) ​

Audience: Mobile, native, or web teams that own networking, UI, and session lifecycle.

What you integrate:

PieceRole
HTTPS POST /api/mobile/sessions (and related REST)Authenticated bootstrap; returns short-lived session intent + token.
WSS /ws/mobileRealtime PCM + JSON control after connecting with intent query params.

Transport mode (today): Surface A’s hosted path is WebSocket PCM + JSON on /ws/mobile. Framework-level direct_rtc (Opus RTP on the client leg, JSON + rtc.* signaling still on WebSocket) is a self-hosted / app-server integration option until a future hosted surface exposes it with its own contract, auth, and TURN story — see Hosted Bodhi voice API (“Current hosted contract vs framework direct_rtc”) and Transport.

Identifiers:

  • Saved agent id: ua_* (16 hex), chosen at bootstrap time.
  • Auth: Supabase session and/or Bodhi integration API key bsk_* per Hosted Bodhi voice API.

You implement: mic capture, playback, transcripts UI, reconnect policy, and any avatar/visual layer yourself.


Surface B — Publishable widget (hosted UI) ​

Audience: Web teams that want a one-line or iframe embed with Bodhi-managed Talk UI, bootstrap, WebSocket wiring, and optional Spatial Real avatar.

What you integrate:

PieceRole
Published widget id wg_*Public handle mapped to a saved ua_* agent (configured in Agent Studio).
Snippet or iframeLoad bodhi-widget.js or open the hosted /embed/avatar URL with params from bootstrap.

Public bootstrap (no user login on the visitor’s site):

  • POST /api/embed/widget-sessions with { "widgetId": "wg_..." }
  • Server checks published state and widget mode (voice vs voice_avatar) against the saved agent.
  • Response mirrors the short-lived embed intent shape (widget embed).

You do not expose raw ua_*, long-lived bsk_*, or manual WS assembly to the visitor’s browser for the default widget path—only the short-lived embed intent/token pair.


Choosing between surfaces ​

NeedUse
Native app, custom UI, wearable hooksSurface A — Hosted Bodhi voice API
Marketing site / SaaS embed with minimal codeSurface B — Widget embed
Web app with full control but browser-onlySurface A using the same REST + /ws contract as documented, or npm @bodhi_lab/bodhi-web-sdk (sibling repo bodhi-lab-client-packages — packages/web-sdk).

Relationship to internal embed APIs ​

Endpoints such as POST /api/embed/avatar-sessions remain the programmable, authenticated path for developers who already have Supabase session or bsk_* and want to drive /embed/avatar explicitly. They are foundational for tooling and advanced flows; the productized external embed path for third-party sites is wg_* + POST /api/embed/widget-sessions.

Built with VitePress