Perxona Presentation SDK

Introduction #

The Perxona Presentation SDK enables seamless embedding of an interactive AI agent avatar into third-party applications via a lightweight widget. The SDK provides configurable options for conversation handling, lifecycle events, rendering settings, theme customization, and behavior control.

Prerequisites #

Before you begin, you will need:

  1. API Key: An API key is required to authenticate your widget. This key will be provided to you by your Perxona Account Manager after your organization is set up in our backend system.
    To ensure secure access, please provide us with a list of the hostnames that will be making requests to the Perxona Backend Service. These hostnames will be added to an allowlist, preventing unauthorized access.

  2. Session Token: The Session Token and API Key are alternatives; either one is required for the widget to access backend services. The difference is that the Session Token is provided to developers for self-managed authorization. It is usually set with a specific expiration time. When the key expires, you can decide whether to generate a new key and have the service re-establish itself based on the new key, allowing your company to manage authentication security independently.

  3. Agent Profile ID: Each <sv-agent> instance is associated with an "Agent Profile." You can configure and obtain the Agent Profile ID (a ULID string) through the Perxona Dashboard console. This ID determines which AI agent (Avatar) and configuration your widget will use.

Quick Start #

Step1. Import Perxona SDK from CDN #

To integrate the widget into your application, include the following TypeScript snippet first:

<script type="module" src="https://cdn.perxona.ai/prod/latest/widget/entry/index.js"></script>

Step2. Embedding the Widget and Layout Attributes #

The sv-agent widget is a custom web component that allows developers to quickly embed an AI avatar onto a website by inserting a specific code snippet into their application.

<sv-agent
  apiKey="<YOUR_API_KEY>"
  agentProfileId="<YOUR_AGENT_PROFILE_ID>"
  conversationMode="inputText"
  displayMode="fullPresentation"
  fov='{"distance": 1, "horizontal": 0, "vertical": 0}'
>
</sv-agent>
Notice: Don’t add CSS to effect the `sv-agent` widget, like below. It will cause the `sv-agent` widget to be laid out unexpectedly.
<style>
  #widget-container {
    display: flex;
    position: relative;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    height: 880px;
    width: 500px;
  }
</style>
...
<sv-agent
  apiKey="<YOUR_API_KEY>"
  agentProfileId="<YOUR_AGENT_PROFILE_ID>"
  conversationMode="inputText"
  displayMode="fullPresentation"
  fov='{"distance": 1, "horizontal": 0, "vertical": 0}'
>
</sv-agent>

Step3. Custom Widget Layout (Optional) #

You can dynamically set layout properties via Javascript methods if you prefer not to use attributes for configuration. If want to know more about the attributes see Widget Configuration section.

// Select the <sv-agent> element in the DOM
// and ensure it has the updateWidgetSetting method.
const widget = document.querySelector('sv-agent') as
  | (HTMLElement & {
      updateWidgetSetting: (settings: unknown) => boolean;
    })
  | null;

const layoutConfig = {
  presentationMode: 'bubble',
  readyToShowPolicy: 'showWhenAssetsReady',
  displayMode: 'fullPresentation',
  conversationMode: 'inputText',
  fov: { distance: 1, horizontal: 0, vertical: 0 },
  cameraAngle: 'fullBody',
  colorMode: 'light',
  colorTheme: {
    primary: {
      light: '#fff',
      dark: '#000',
    },
  },
};

if (!widget) {
  console.error('sv-agent widget not found in the DOM.');
} else if (typeof widget.updateWidgetSetting !== 'function') {
  console.error('updateWidgetSetting method is not available on sv-agent element.');
} else {
  console.log('sv-agent is ready to use.');
  widget.updateWidgetSetting(layoutConfig);
}

Event Handlers #

The sv-agent widget provides the following event hooks during the agent initialization and conversation lifecycle.

Agent Lifecycle Events #

Event NameDescription
DisconnectedTriggered when the widget loses connection or switches to another agent.
AgentPreparationFired when the agent connection process starts.
DownloadingAssetsCalled while assets are being downloaded.
ConnectionStartFired when the system is connecting to the AI backend.
ConnectionDoneFired when the system is connected to the AI backend. Otherwise, it returns to Disconnected and retries.
ReadyTriggered when the avatar successfully connects and is ready.

Example (Listening for Events)

const widget = document.querySelector('sv-agent');
...
widget.addEventListener('LifeStatus', (event) => {
  const status = event.detail.status;
  console.log('Perxona Life Status: ' + status);

  switch (status) {
    case 'Disconnected':
      console.log('Perxona Widget: Connection lost or agent switched.');
      break;
    case 'AgentPreparation':
      console.log('Perxona Widget: Agent connection process started.');
      break;
    case 'DownloadingAssets':
      console.log('Perxona Widget: Downloading assets - ', event.detail.message);
      break;
    case 'ConnectionStart':
      console.log('Perxona Widget: Connecting to the AI backend.');
      break;
    case 'ConnectionDone':
      console.log('Perxona Widget: Connected to the AI backend.');
      break;
    case 'Ready':
      console.log('Perxona Widget: Avatar is ready.');
      break;
    default:
      console.log('Perxona Widget: Unknown Life Status');
      break;
  }
});

Conversation Lifecycle Events #

Event NameDescription
IdleNo active conversation, waiting for user input.
UserInputtingThe user inputs via voice or text.
UserInputDoneThe user has completed the input. The event returns the current user input to the event listener.
AwaitingResponseThe server is processing the request.
AwaitingResponseDoneThe widget receives the server response.
RenderingResponseThe widget is rendering the response.

Example

const widget = document.querySelector('sv-agent');
...
widget.addEventListener('ConversationStatus', (event) => {
  const status = event.detail.status;
  console.log('Conversation Status: ' + status);

  switch (status) {
    case 'Idle':
      console.log('Conversation: Idle.');
      break;
    case 'UserInputting':
      console.log('Conversation: User is inputting.');
      console.log('User input:' + event.detail.message);
      break;
    case 'UserInputDone':
      console.log('Conversation: User input done.');
      break;
    case 'AwaitingResponse':
      console.log('Conversation: Awaiting response from AI.');
      break;
    case 'AwaitingResponseDone':
      console.log('Conversation: Response received from AI.');
      break;
    case 'RenderingResponse':
      console.log('Conversation: Rendering AI response.');
      break;
    default:
      console.log('Conversation: Unknown Conversation Status');
      break;
  }
});

Widget Configuration #

The configuration you can setup via sv-agent widget attributes.

App Required #

AttributeDescription
apiKeyYour Perxona API key. This authenticates your widget. Keep this key secret. In the early access Perxona SDK.
session_tokenSession Token and API Key are alternatives; either one is required to access backend services.
The Session Token lets developers manage authorization and and expiration time themselves,
giving you control over authentication security. More information please reference the below Create your session token.
agentProfileIdThe ULID of the Agent Profile to use. This determines the AI agent and configuration. Obtain this from the Perxona Dashboard.

Create your session token #

Either apiKey or session_token allows you to use Perxona services normally. However, we provide a way for you to create and manage your own session_token, so your company can control its expiration time(for example, set it to expire in 3 hours) to enhance operational security.

You can use a JWT encoding library in your preferred programming language, or the online tool jwt.io to generate the token. Make sure to select HS256 as the JWT encryption algorithm.

Parameter descriptions:

  • iat: The “iat” (issued at) claim identifies the time at which the JWT was issued. This claim can be used to determine the age of the JWT. Its value MUST be a number containing a NumericDate value.
  • exp: The “exp” (expiration time) claim identifies the expiration time on or after which the JWT MUST NOT be accepted for processing. The processing of the “exp” claim requires that the current date/time MUST be before the expiration date/time listed in the “exp” claim.

Sample

// parameter
{
  "iat": 1516239022,
  "exp": 1758004103
}

// Result: Encode JWT (HS256) as session_token.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1MTYyMzkwMjIsImV4cCI6MTc1ODAwNDEwM30.p9iVZ3aYnkf5dNZ1jyyUdyH7uV7fPWhfIiHaEAJs8JE

Note: If both apiKey and session_token are present, authentication will prioritize apiKey. To use session_token for authentication, please remove the apiKey attribute.

Here are two methods for setting up the session_token.

Method 1: Set up via Web Component attributes Add your own session_token in the widget attributes during initial widget setup.

<sv-agent
  // Remove the apiKey for session_token authentication.
  // apiKey="<YOUR_API_KEY>"
  session_token="<YOUR_SESSION_TOKEN>"
  agentProfileId="<YOUR_AGENT_PROFILE_ID>"
  ...
>
</sv-agent>

Method 2: Setup by TypeScript After the widget is loaded onto the webpage, you can pass in the configuration using TypeScript.

const widget = document.querySelector("sv-agent") as
  | (HTMLElement & {
      updateWidgetSetting: (settings: unknown) => boolean;
    })
  | null;

if (!widget) {
  console.error("sv-agent widget not found in the DOM.");
  return;
}

if (typeof widget.updateWidgetSetting !== "function") {
  console.error("updateWidgetSetting method is not available on sv-agent element.");
  return;
}

widget.updateWidgetSetting({
  ...
  session_token: "<YOUR_SESSION_TOKEN>"
  agentProfileId: "<YOUR_AGENT_PROFILE_ID>"
  ...
});

Layout Config #

We offer a variety of layout configuration options to meet different requirements for displaying the AI Agent widget. Depending on your company’s privacy policies, usage scenarios, and website style, you can customize the widget to fit your preferences. For example: you can set the widget’s theme color, choose between 2D or 3D display, control when the widget loads, select between full-screen or bubble mode, configure text and voice interaction modes, and adjust the camera position for the Agent.

Display Policies #

Developers can configure readyToShowPolicy when the widget should be displayed: If you are not set up, the default is ShowWhenAssetsReady mode.

OptionDescription
ShowWhenAssetsReadyThe entire widget shows after the necessary assets are loaded. Includes:
ShowWhenAssetsLoadingShows the widget immediately. A loading icon appears on the widget while the assets are loading.

Display Mode #

Display mode is used to configure how the sv-agent is presented. You can choose to display only 2D, 3D, or use the fullPresentation mode. In some cases, developers may want to integrate only the text input mode without showing the 3D Agent and background, allowing users to interact with the AI through conversation. In this scenario, you can select the 2DPresentation mode. If developers want to display only the 3D Agent and control animations and conversation data themselves via our provided interfaces, you can select the 3DPresentation mode. If no display mode is set, the default will be fullPresentation mode.

OptionBehavior
fullPresentationThe developer uses the full preset widget, including input fields and chat bubbles.
3DPresentationThe developer builds their own UI while using the widget for rendering the 3d agent only.
2DPresentationThe developer builds their own UI while using the widget for rendering the conversation window only.

Conversation Mode #

Developers can define conversationMode how to interact with the Agent, either by responding with text input or voice commands. If the attribute is not set or is set incorrectly, the default is inputText mode.

OptionBehavior
inputTextThe user interacts with the agent using text input.
microphoneThe user interacts with the agent using voice commands.

Theme Customization #

Developers can set up themes via a name or style provider. Customizable components include:

  • appearanceMode (string): Switches widget UI color scheme.
<sv-agent
  ...
  appearanceMode="dark"
  ...
>
AttributeDescription
lightLight mode for bright environments.
darkDark mode for low-light environments. Like this: dark mode
  • userBubbleColor (object): Provides theme color overrides for components (e.g., bubble color). See example below the color is #FF6200.
<sv-agent
  ...
  userBubbleColor='#FF6200'
  ...
>
bubble color
  • bubbleSetting (object): Configure bubble UI presentation details such as the icon source.
<sv-agent
  ...
  bubbleSetting='{"icon": {"src": "https://.../icon.png"}}'
  ...
>
bubble icon

Camera Positioning #

Fine-tunes the 3D camera field-of-view and offsets. The developer can set the camera position via attributes:

<sv-agent
  ...
  // Fov sample values see below picture.
  initFov='{"distance": 6, "horizontal": 5, "vertical": 4}'
  ...
>
  • distance: The distance of the camera from the avatar.
  • horizontal: The horizontal offset of the camera. Positive values move the camera to the right, negative values move it to the left.
  • vertical: The vertical offset of the camera. Positive values move the camera up, negative values move it down.
camera positioning

Camera Angle #

Sets the default camera framing of the 3D avatar. You can set the camera angle via attributes:

<sv-agent
  ...
  cameraAngle="fullBody"
  ...
>
OptionBehavior
fullBodyFor showing full-body avatar. camera angle fullbody
halfBodyFor showing upper-body avatar. camera angle halfbody

Presentation Rendering #

To render presentation with text and animation, use the following API:

event: You can use these existing event values for testing.

  1. user_input: Creates a question block of user’s input in the chat UI, and initializes an answer block placeholder.
  2. agent_answer: Creates a question block of agent’s input in the chat UI, and use TTS( Text to Speech ) to play the context.
  3. agent_end: When you are ending a conversation with the agent, you should call this event. It will clear the last cached answer.

context: The text that will be rendered in the chat UI. It should be a string.

motion_id: You can use a motion_id alongside a reply to perform desired actions at your chosen points within the conversation, making your agent more lively/expressive during a dialogue.You can use these existing default motion_id values for play animation at any time you want.

  1. idle: The agent idle animation is waiting for user input.
  2. talking: Talking animation is playing while the agent is speaking.
  3. listening: Listening animation is playing while the agent is waiting for user input.
  4. greeting: Greeting animation is playing while the agent is greeting the user.
  5. error: Error animation is playing while the agent is showing an error.
  6. custom: The other custom animations you can find the list of playlet in the Perxona Storyboard.

Example

const widget = document.querySelector("sv-agent") as
  | (HTMLElement & {
      agentReply: (data: unknown) => boolean;
    })
  | null;

if (!widget) return;

const userInputMsg = {
  event: "user_input",
  message: "Hi, nice to meet you~",
};

const agentResponse = {
  event: "agent_answer",
  message: "Hello! How can I help you?",
  motion_id: "greeting",
};

const agentEnd = {
  event: "agent_end",
  message: "Goodbye!",
};

// Simulate user sending a message.
widget.agentReply.(userInputMsg);

// Control agent response a answer with message and specific animation.
widget.agentReply.(agentResponse);

// End the agent response.
widget.agentReply.(agentEnd);

Feature Flags & Advanced #

Multimedia Display #

The supportedFeatures object lets you toggle optional widget features. Multimedia Display Attribute allows you to show/hide multimedia displayer in the widget. This feature lets you embed videos, PDFs, or images that are configured in the Knowledge Base tab of the console. To enable it, set the multimedia attribute to true in the widget’s properties. By default, this value is already true. The multimedia display is stacked on the browser’s main window body to prevent other user interface element from hiding or blocking it.

<sv-agent
  ...
  supportedFeatures={
    "multimedia": true
  }
  ...
>

When you enable multimedia display, the widget will dispatch a chatAttachment event to notify you when an attachment is presented. Attachment Event carries attachment information in each displayed multimedia item. We provide multimedia-related events that are dispatched to the sv-agent component, allowing you to listen for them and create more engaging and interactive experiences when integrating with your website. For example, when the Agent starts displaying a video, you can disable or pause your own website’s video features to avoid multiple videos playing at the same time, which may cause audio confusion. mediaType: Currently supports three formats: image, video, and pdf. mediaSource: The URL location of the corresponding media format.

const widget = document.querySelector('sv-agent');
widget.addEventListener('chatAttachment', (event) => {
  // You can extract first attachment from array.
  const attachment = event.detail[0];
  const { mediaType, mediaSource } = attachment;
  console.log(`chatAttachment mediaType: ${mediaType}, mediaSource: ${mediaSource}`);

  switch (mediaType) {
    case 'video':
      // Example: Mute your website video.
      break;
    case 'image':
      // Example: Popup this image on your website.
      break;
    case 'pdf':
      // Example: Set your website to dark mode for better reading experience.
      break;
  }
});

Here is the screenshot of the multimedia display in the widget: When you ask some specific questions, the Agent can show you related videos, images, or PDF documents as part of its response. All multimedia’s Q&A pairs are configured in the Knowledge Base tab of the console. But this feature is only available to cooperative customers now. If you have any related needs, please contact our Support. multimedia display

Customer Reference ID #

  • customerRefId (string): Optional free-form identifier provided by integrators to attach a customer reference to the widget session.

    Customer conversation data is stored in our backend systems, and each organization sets the retention period according to regional privacy regulations. This conversation data is used during interactions with the Agent to improve dialogue continuity and overall quality. For example, a user may prefer certain products or have specific settings — by linking those records with a customerRefId, the Agent can remember this information across conversations and provide more personalized service.

<sv-agent
  ...
  // Optional customer reference ID for session tracking.
  customerRefId="user-id-00001"
  ...
>

Then you can see the conversation history in the Conversation History tab of the console.

conversation history

Mute Audio #

  • muted (boolean): If false, the widget initializes with audio output muted (TTS disabled or muted at browser level).
<sv-agent
  ...
  // Optional: Initialize the widget with audio muted.
  muted=false
  ...
>

Conclusion #

The Perxona Presentation SDK provides a flexible, customizable, and developer-friendly way to integrate AI-powered avatars into third-party applications. With robust event handling, UI customization, and webhook support, developers can create engaging, interactive experiences.

© 2025 XRSPACE CO., LTD. All rights reserved.