Before
createSession()can run in the browser, your backend must mint a credential. The credential is a short-lived LiveKit URL and token, scoped to a single session. No secrets reach the client.
Getting a Session Credential
How the Credential Flow Works
A session credential is produced in two hops:
- Your backend authenticates with Bourne, then calls
POST /guide/sessionwith youragentIdand any session options. Bourne returns aSessionCredentialobject containing a LiveKit URL and a scoped token. - Your frontend receives that credential from your own token endpoint, then calls
createSession({ credential }). The SDK uses the credential to join the LiveKit room — your API key never leaves the server.
All session configuration (agent selection, interaction mode, language, credit cap) is baked into the credential at creation time. The browser cannot override these values after the fact.
Backend Step — Calling the Token Endpoint
Your backend calls:
POST /guide/session
The only required parameter is agentId. All others are optional and have sensible defaults.
| Parameter | Type | Default | Description |
|---|---|---|---|
agentId | string | required | Your agent configuration ID |
mode | "voice" | "video" | "voice" | Device mode |
interactionMode | "guided_steps" | "immediate_feedback" | "guided_steps" | Session interaction mode |
lang | string | "en-US" | Language code |
enableRag | boolean | true | Enable retrieval from user-uploaded documents |
activeAccesstag | string | "" | Filter system knowledge docs by this tag |
llmModel | string | "gpt-4o-mini" | LLM model for agent reasoning |
videoFps | number | 3 | Video frame rate (1–10) |
videoProcessor | string | "none" | Video processor (e.g. "yolo-pose") |
feedbackTask | string | "" | Task description — required when using immediate_feedback mode |
feedbackTipsPerCycle | number | 1 | Tips per feedback cycle (1–5) |
feedbackAutoIntervalSeconds | number | 0 | Auto-feedback interval in seconds (0–600) |
continueRunId | string | null | Resume a previous session by run ID |
endUserRef | string | null | End-user identifier (A-Za-z0-9_-, up to 64 chars) |
maxCreditsPerSession | number | null | Credit cap for this session |
The endpoint returns a SessionCredential object. Pass this object directly to createSession() — do not unpack or modify it.
Frontend Step — Calling createSession()
Once your backend exposes the credential at your own endpoint (e.g. /api/your-token-endpoint), your frontend fetches it and bootstraps the session:
import { createSession } from "@picoagent/embed-core";
const credential = await fetch("/api/your-token-endpoint").then(r => r.json());
const session = await createSession({ credential });
createSession() validates the credential's protocolVersion, connects to the LiveKit infrastructure, and returns a Session object. From here you attach transports (attachVoice, attachVideo) and subscribe to events.
Session Events
Once a session is created, subscribe to agent events with session.on():
| Event | Payload | Description |
|---|---|---|
plan | { plan } | The agent's current plan — list of steps and metadata. Fires on session start and whenever the plan changes. |
step_update | { stepIndex, totalSteps } | The active step index changed. Use this to update your step indicator UI. |
session_ended | { reason } | The session has ended. reason may be "completed", "timeout", "credit_limit", or "error". |
error | { code, message } | A session-level error occurred. Handle and surface to the user as appropriate. |
Session Resume
The SDK automatically persists the current runId in browser session storage. Use getResumeRunId() to retrieve it — do not read session storage directly, since the key name is an SDK implementation detail and may change. If the user refreshes the page mid-session, you can detect and resume the previous session:
import { createSession, getResumeRunId } from "@picoagent/embed-core";
// On page load — check for an in-progress session
const existingRunId = getResumeRunId();
// Pass it to your backend, which forwards it to the token endpoint
const credential = await fetch("/api/your-token-endpoint", {
method: "POST",
body: JSON.stringify({
agentId: "your-agent-id",
continueRunId: existingRunId ?? undefined,
}),
}).then(r => r.json());
const session = await createSession({ credential });
When continueRunId is set, Bourne resumes the session from where it left off — the plan state, step index, and conversation history are all restored.
Next Steps
- Voice and Video Transports — Attach the voice and video layers to your session
- API & SDK Overview — Package map and architecture overview