Framework-agnostic primitives for Keyframe Labs.
npm install @keyframelabs/elementsFramework-agnostic primitives for Keyframe Labs.
Which package should I use?
- @keyframelabs/sdk (high control)
- You implement the UI, state management, and agent/llm binding yourself
- @keyframelabs/elements (custom UI)
- You implement the UI; we handle the state and agent/llm binding (framework-agnostic)
- @keyframelabs/react: (drop-in)
- We handle the UI, state, and agent/llm binding
``bash`
pnpm add @keyframelabs/elements
This package provides two primary classes depending on your integration strategy:
1. PersonaEmbed: Fully managed. Uses a publishable key. Best for rapid frontend integration.
2. PersonaView: Bring your own backend. Uses session tokens generated by your server.
Use this if you have configured an embed in the Keyframe platform dashboard.
`ts
import { PersonaEmbed } from '@keyframelabs/elements';
const embed = new PersonaEmbed({
container: document.getElementById('persona-container'),
publishableKey: 'kfl_pk_live_...',
videoFit: 'cover',
onStateChange: (status) => console.log('Status:', status),
onAgentStateChange: (state) => console.log('Agent:', state),
onDisconnect: () => console.log('Disconnected'),
onError: (err) => console.error(err),
});
await embed.connect();
// Later...
embed.disconnect();
`
Use this when you want to manage authentication through your own backend.
`ts
import { PersonaView } from '@keyframelabs/elements';
const view = new PersonaView({
container: document.getElementById('persona-container')!,
sessionDetails,
voiceAgentDetails,
videoFit: 'contain',
onStateChange: (status) => console.log('Status:', status),
onAgentStateChange: (state) => console.log('Agent:', state),
onDisconnect: () => console.log('Disconnected'),
onError: (err) => console.error(err),
});
await view.connect();
// Later...
view.disconnect();
`
Supports Cartesia, ElevenLabs, Vapi, Gemini Live (closed alpha), OpenAI Realtime (closed alpha).
For PersonaEmbed, this is determined by the values you set in the Keyframe platform dashboard.
For PersonaView, this is determined by voiceAgentDetails.
#### Options
| Option | Type | Default | Description |
| -------------------- | ------------------------------- | -------------------------------- | ---------------------------------------------- |
| container | HTMLElement | Required | Target container for video and audio elements. |publishableKey
| | string | Required | Your publishable embed key. |apiBaseUrl
| | string | 'https://api.keyframelabs.com' | Base URL for the Keyframe API. |videoFit
| | 'cover' \| 'contain' | 'cover' | Video scaling mode (object-fit). |onStateChange
| | (status: EmbedStatus) => void | — | Fired when connection status changes. |onAgentStateChange
| | (state: AgentState) => void | — | Fired when agent state changes. |onDisconnect
| | () => void | — | Fired when the session disconnects. |onError
| | (err: Error) => void | — | Fired on fatal errors. |
#### Methods
| Method | Signature | Description |
| ------------ | --------------------- | -------------------------------------------------- |
| connect | () => Promise | Starts the session and establishes the connection. |disconnect
| | () => void | Disconnects the session and cleans up resources. |toggleMute
| | () => void | Toggles the user's microphone mute state. |
#### Properties
| Property | Type | Description |
| -------------- | ------------------ | -------------------------------------------------------------------------------------- |
| status | EmbedStatus | Current connection status: 'connecting' \| 'connected' \| 'disconnected' \| 'error'. |agentState
| | AgentState | Current agent state: 'idle' \| 'listening' \| 'thinking' \| 'speaking'. |isMuted
| | boolean | Whether the microphone is currently muted. |videoElement
| | HTMLVideoElement | The underlying video element used for rendering. |audioElement
| | HTMLAudioElement | The underlying audio element used for playback. |
#### Options
| Option | Type | Default | Description |
| -------------------- | ------------------------------- | --------- | ---------------------------------------------- |
| container | HTMLElement | Required | Target container for video and audio elements. |sessionDetails
| | SessionDetails | Required | Session configuration from your backend. |voiceAgentDetails
| | VoiceAgentDetails | Required | Voice agent configuration from your backend. |videoFit
| | 'cover' \| 'contain' | 'cover' | Video scaling mode (object-fit). |onStateChange
| | (status: EmbedStatus) => void | — | Fired when connection status changes. |onAgentStateChange
| | (state: AgentState) => void | — | Fired when agent state changes. |onDisconnect
| | () => void | — | Fired when the session disconnects. |onError
| | (err: Error) => void | — | Fired on fatal errors. |
#### Methods
Same as PersonaEmbed.
#### Properties
Same as PersonaEmbed.
#### Types
`ts
type SessionDetails = {
server_url: string;
participant_token: string;
agent_identity: string;
};
type VoiceAgentDetails = {
type: 'cartesia' | 'elevenlabs' | 'vapi' | 'gemini' | 'openai';
token?: string; // For gemini, cartesia
agent_id?: string; // For elevenlabs, cartesia
signed_url?: string; // For elevenlabs, vapi
};
``
MIT