For AI agents: a documentation index is available at the root level at /llms.txt and /llms-full.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
GitHubGet Support
DocsGuidesAPI Reference
DocsGuidesAPI Reference
  • Get started
    • Overview
    • Partner Setup
    • Quickstart
  • Guides
    • Authentication
    • Profile Sync
    • Artifacts
    • Key Concepts
  • Changelog
    • Changelog
LogoLogo
GitHubGet Support
On this page
  • Quick start
  • Authentication options
  • Return value
  • Programmatic control
  • Customization
  • Concierge mode
  • React example
  • Next steps
Get started

Quickstart

Get up and running with the Sunny Agents SDK in minutes
||View as Markdown|
Was this page helpful?
Previous

Partner Setup

Next

Authentication

Built with

This guide shows you how to integrate the Sunny Agents SDK into your application using createSunnyChat.

Quick start

1

Get your credentials

Sign in to Sunny Central (or staging) and go to Developer Tools. Create an API key and note your partner name. See Partner Setup for details.

2

Install the SDK

Install the Sunny Agents SDK:

$npm install @sunnyhealthai/agents-sdk
3

Add the chat widget

Create an HTML file and add a container for the chat widget:

index.html
1<!DOCTYPE html>
2<html>
3<head>
4 <title>Sunny Agents Chat</title>
5</head>
6<body>
7 <div id="sunny-chat"></div>
8 <script type="module">
9 import { createSunnyChat } from "@sunnyhealthai/agents-sdk";
10
11 const chat = createSunnyChat({
12 container: document.getElementById("sunny-chat"),
13 partnerIdentifier: "acme-health",
14 publicKey: "pk-sunnyagents_abc_xyz",
15 authType: "passwordless",
16 headerTitle: "Sunny Health Concierge",
17 placeholder: "How can I help you find care?",
18 });
19 </script>
20</body>
21</html>
4

Test it out

Open your HTML file in a browser and start chatting! The widget will automatically connect and handle all WebSocket communication.

Authentication options

Choose the authentication mode that fits your application:

Custom Token Exchange:

1import { createSunnyChat } from "@sunnyhealthai/agents-sdk";
2
3const chat = createSunnyChat({
4 container: document.getElementById("chat"),
5 partnerIdentifier: "acme-health",
6 publicKey: "pk-sunnyagents_abc_xyz",
7 authType: "tokenExchange",
8 idTokenProvider: async () => {
9 return localStorage.getItem("id_token");
10 },
11});

Return value

createSunnyChat returns a VanillaChatInstance with these members:

MemberDescription
clientThe underlying client for programmatic control (events, sending messages, state)
destroy()Unmount the widget and close the WebSocket connection
setAuthType(authType, opts?)Switch authentication mode at runtime (see Authentication)

Programmatic control

Use the client property for programmatic access:

1const chat = createSunnyChat({
2 container: document.getElementById("chat"),
3 partnerIdentifier: "acme-health",
4 publicKey: "pk-sunnyagents_abc_xyz",
5 authType: "passwordless",
6});
7
8// Listen to state changes
9chat.client.on("snapshot", (snapshot) => {
10 console.log("Current conversations:", snapshot.conversations);
11 console.log("Active conversation:", snapshot.activeConversationId);
12});
13
14// Listen to streaming updates
15chat.client.on("streamingDelta", ({ conversationId, messageId, text }) => {
16 console.log("Streaming response:", text);
17});
18
19// Send a message programmatically
20await chat.client.sendMessage("I need to find a cardiologist");
21
22// Clean up when done
23chat.destroy();

Customization

Customize the widget’s appearance:

1const chat = createSunnyChat({
2 container: document.getElementById("chat"),
3 partnerIdentifier: "acme-health",
4 publicKey: "pk-sunnyagents_abc_xyz",
5 authType: "passwordless",
6 headerTitle: "Sunny Health Concierge",
7 placeholder: "How can I help you find care?",
8 colors: {
9 primary: "#006fff",
10 secondary: "#212124",
11 accent: "#22c55e",
12 },
13 fontSize: "14px",
14 fontFamily: "'Inter', sans-serif",
15 dimensions: {
16 width: "1200px", // Modal width (default: 1390px)
17 height: "800px", // Modal height (default: 980px)
18 triggerMaxWidth: "500px", // Collapsed bar max-width (default: 600px)
19 },
20});

Concierge mode

By default the widget renders a collapsed trigger bar that opens a modal. Switch to a full-panel concierge layout with intro copy, prompt chips, and an inline trigger by setting displayMode: "concierge":

1const chat = createSunnyChat({
2 container: document.getElementById("chat"),
3 partnerIdentifier: "acme-health",
4 publicKey: "pk-sunnyagents_abc_xyz",
5 authType: "passwordless",
6 displayMode: "concierge",
7 concierge: {
8 introText:
9 "I'm your Care Concierge. I can help you book appointments and find providers.",
10 introStrongText: "Give it a try.",
11 suggestions: [
12 "I need a dental cleaning",
13 "I need to see a specialist",
14 { label: "View or change my appointment", emphasis: "primary" },
15 ],
16 align: "left", // or "center"
17 },
18});

Each suggestion entry is either a plain string (used as both label and prompt) or a VanillaChatPromptSuggestion:

FieldDescription
labelText shown on the chip
promptOptional prompt sent on click (defaults to label)
emphasis"primary" renders a solid, conspicuous call-to-action chip

React example

ChatWidget.tsx
1import { useEffect, useRef } from "react";
2import { createSunnyChat } from "@sunnyhealthai/agents-sdk";
3import type { VanillaChatInstance } from "@sunnyhealthai/agents-sdk";
4
5export function ChatWidget() {
6 const containerRef = useRef<HTMLDivElement>(null);
7 const chatRef = useRef<VanillaChatInstance | null>(null);
8
9 useEffect(() => {
10 if (!containerRef.current) return;
11
12 chatRef.current = createSunnyChat({
13 container: containerRef.current!,
14 partnerIdentifier: "acme-health",
15 publicKey: "pk-sunnyagents_abc_xyz",
16 authType: "passwordless",
17 });
18
19 return () => {
20 chatRef.current?.destroy();
21 };
22 }, []);
23
24 return <div ref={containerRef} />;
25}

Next steps

Authentication

Set up authenticated sessions

Artifacts

Parse and render rich content

Key Concepts

Events, state management, and more