Copilots
Copilots are AI assistants embedded within your application that can answer questions, retrieve information, provide suggestions, and accelerate workflows by using application data and APIs. You can create copilots in the Continual console and configure them to connect to models, knowledge bases, and tools to provide a powerful conversational assistant that is deeply integrated with your application.
Copilots can be integrated into your application using:
- React components for a drop-in conversational UI.
- React hooks for custom frontend experiences.
- REST API for backend integration and other development frameworks.
How copilots work
Copilots connect Knowledge bases, Tools, and Models to provide responses that are accurate, relevant, and actionable within the context of your application.
Resource | Description | Details |
---|---|---|
Copilot | AI assistants that interact with users and provide responses | Copilots |
Model | AI models that power natural language understanding and generation | Models |
Knowledge Base | Data sources that copilots can query for information | Knowledge Bases |
Tool | Application APIs and services that copilots can interact with | Tools |
User interactions with a copilot occur within a thread. Threads consist of messages exchanged between users and copilots. Threads can support multiple users and copilots communicating with each other, although typically a thread will consist of a single user and a single copilot. Runs and steps capture the execution of a copilot to process a user message and generate a response.
Resource | Description |
---|---|
Thread | A conversation between users and copilots, consisting of messages |
Message | An individual piece of communication within a thread, sent by either a user or copilot |
Run | A single execution of a copilot to process a user message and generate a response |
Step | An individual action performed by a copilot during a run, such as API calls or knowledge base queries |
Continual copilots are similar to the OpenAI Assistant API but support multiple model providers, direct connectivity with frontend applications, and full extensibility by developers.
Creating a copilot
To create a new copilot, navigate to the Copilots tab in the Continual console and click Create copilot. Give your copilot a name, description, base instructions, and select the model to power its natural language and reasoning abilities. You can then configure its knowledge bases, tools, appearance and other settings.
Guiding behavior
A copilots behavior can be controlled by setting instructions. Instructions become part of the model's system prompt and provide high-level guidance and context to your copilot. We recommend adding a bulleted list of behavioral guidelines and context based on the observed behavior of your copilot.
Adding knowledge
Connecting Knowledge bases to your copilot allows it to draw upon curated information such as product documentation to provide accurate and relevant responses. In the knowledge bases section of the copilot's integrations tab, you can add knowledge bases from a variety of sources, includin websites or blob storage. The copilot will intelligently retrieve pertinent information from these sources based on the user's queries. To learn more about knowledge bases, including advanced features like metadata filtering, see Knowledge bases.
Adding skills
Using Tools, copilots can be connected to your application's backend APIs to perform useful actions and access real-time information on behalf of users. In the tools section of a copilot's integrations tab, you can define API endpoints using an OpenAPI specification that the copilot can use to either retrieve information or take actions. To learn more about tools, see Tools.
A critical part of adding skills to your copilot is to ensure that the copilot has the appropriate permissions to access the data and perform the actions on behalf of the user.
Embedding a copilot
The @continual/react package provides pre-built React components and hooks to
effortlessly embed a copilot into your React application. The <Copilot>
component offers a
plug-and-play converational UI, while the React hooks allow you build custom features using the
copilot API from your frontend. For even more avanced you cases, you can use the
REST API.
To embed a copilot in your React application, install the @continual/react
package and add the
<Copilot>
component to your application root:
import { Copilot, CopilotProvider } from "@continual/react";
import "@continual/react/dist/styles.css";
const copilotId = process.env.CONTINUAL_COPILOT_ID;
export function App() {
return (
<CopilotProvider copilotId={copilotId}>
{/* Your other app components here. */}
<Copilot />
</CopilotProvider>
);
}
The <CopilotProvider>
is responsible managing global configuration and state. The <Copilot>
component is the conversational UI that allows users to interact with the copilot. For more details,
see the @continual/react documentation.
Customizing appearance
Copilot appearance can be configured in two places:
- In the Continual console.
- In your application code.
When appearance is configured in the Continual console, the copilot component running in your application will automatically load these settings when it initializes. When appearance is configured in your application code, these settings will override any settings made in the Continual console.
Customizing in the console
Copilot appearance can be set in the Appearance tab of a copilot page. Give your copilot a custom greeting message, chat icon, and display format.
Customizing with code
There are three levels of customization available:
-
Appearance Props: quickly customize basic UI elements
-
CSS styling: define the look and feel of the copilot using CSS
-
Customizing Prebuilt Components: use subcomponents to make a completely custom
copilot UI.
Appearance props
The following properties can be used to control the visual appearance of the copilot component.
Display format
The <Copilot />
component has four built-in display formats:
-
POPUP
(default) - Displays the copilot toggle and window as a floating popup at the bottom right of your application's screen. -
SIDEBAR
- Displays the copilot as a floating window pane on the right side of your application -
INLINE
- Looks the same asPOPUP
but is positioned within the parent element instead of being fixed to the bottom right of the screen -
INLINE_FILL
- Functions the same asINLINE
but stretches to the width and height of the parent element
To configure the display mode in your application code, set the displayFormat
property of the
<CopilotProvider />
config
parameter:
<CopilotProvider config={{ displayFormat: "POPUP" }}>
<Copilot />
</CopilotProvider>
Avatars and icons
The Copilot avatar and icon can be configured in your application code.
Built-in icons
<CopilotProvider
config={{
config: {
chatIconType: "BUILT_IN",
chatIcon: "sparkles",
avatarType: "BUILT_IN",
avatar: "sparkles",
},
}}
/>
Image URLs
<CopilotProvider
config={{
config: {
chatIconType: "URL",
chatIcon: "my_app.jpg",
avatarType: "URL",
avatar: "my_app.jpg",
},
}}
/>
Image data URIs
const CopilotIconJpgAsDataUri = "data:image/jpeg;base64,...";
<CopilotProvider
config={{
config: {
chatIconType: "URL",
chatIcon: CopilotIconJpgAsDataUri,
avatarType: "URL",
avatar: CopilotIconJpgAsDataUri,
},
}}
/>;
SVG data URIs
import { renderToStaticMarkup } from "react-dom/server";
const IconAsSvg = () => (
<svg ...>...</svg>
)
const IconSvgAsString = renderToStaticMarkup(<IconAsSvg />);
const IconSvgAsDataUri = `data:image/svg+xml,${encodeURIComponent(
IconSvgAsString
)}`;
<CopilotProvider
config={{
config: {
chatIconType: "URL",
chatIcon: IconSvgAsDataUri,
avatarType: "URL",
avatar: IconSvgAsDataUri,
},
}}
/>;
Emojis
const CopilotIconJpgAsDataUri = "data:image/jpeg;base64,...";
<CopilotProvider
config={{
config: {
chatIconType: "EMOJI",
chatIcon: "🚀",
avatarType: "EMOJI",
avatar: "🚀",
},
}}
/>;
CSS Styling
Setting the theme with CSS
The overall copilot theme can be styled via CSS variables:
<style>
:root {
--cai-color-primary: 241 91.1% 64.7%;
}
</style>
<Copilot />;
Available theme variables are:
--cai-color-primary
--cai-color-primary-contrast
Styling components with CSS
To set custom CSS styling on <Copilot />
components, target the built-in class names:
.cai .continual__copilot__toggle {
background-color: red;
}
import "./MyCopilotStyles.css";
<Copilot />;
Available built-in class names are:
continual__copilot
continual__copilot__toggle
continual__copilot__window
continual__copilot__window__messenger
continual__copilot__window__messenger__header
continual__copilot__window__messenger__session
cai-avatar-copilot
cai-avatar-user
continual__copilot__window__messenger__user_input
continual__copilot__window__messenger__footer
Class names are under active development. We expect significant changes soon.
If you have more than one instance of Copilot in your application, constrain the styling with an
additional className
:
.copilot_1.cai .continual__copilot__toggle {
background-color: red;
}
import "./App.css";
<Copilot className="copilot_1" />;
Customizing your Copilot
Using the <Copilot />
component is the quickest and easiest way to integrate your copilot.
But if you need more control over where and how the copilot UI components are rendered, you can omit
using <Copilot/>
and instead use the individual UI components.
For example, to render the copilot toggle component in your application header, while rendering the copilot window in your existing sidebar:
import { CopilotProvider, CopilotToggle, CopilotWindow } from "@continual/react";
import "@continual/react/dist/styles.css";
function App() {
return (
<>
<CopilotProvider copilotId={ContinualCopilotId}>
<Header>
<CopilotToggle />
</Header>
<Sidebar>
<CopilotWindow />
</Sidebar>
<Content>{/* the rest of your application */}</Content>
</CopilotProvider>
</>
);
}
Securing a copilot
Continual Access Tokens are used to verify a user's identity when interacting with a copilot. They
are JWT tokens signed with the copilot's secret key. The access token must contain the copilot ID
(iss
claim) and user ID (identity
claim).
To enable authentication, generate the access token on your backend server and pass it to the
<CopilotProvider>
component:
const accessToken = generateAccessToken(userId, copilotId, copilotSecretKey);
<CopilotProvider accessToken={accessToken}>
<Copilot />
</CopilotProvider>;
Adding client context
Client context is additional information you can send to the copilot from your application. Client context is included as part of a user message that is sent to the copilot.
You can use client context to inform the copilot about the state of your application, what page or screen the user is on, and what the content on the page or screen is.
Setting application level context
If your application keeps track of application level context such as who is logged in, what the
active organization unit is, etc., you can set this at the <CopilotProvider />
component level:
import { Copilot } from "@continual/react";
const user = api.user(...);
const organization = api.organization(...)
<CopilotProvider
context={{
user: {
fullName: user?.fullName,
location: user?.location,
},
organization: {
id: organization?.id,
name: organization?.name,
},
}}
/>
Setting page-level context
If you'd also like to send page or screen specific information to the copilot, such as the contents
of the screen whenever the user is navigating through your application, you can set this at the page
level using the useCopilotContext
hook:
import { useCopilotContext } from "@continual/react";
const [copilotContext, setCopilotContext] = useCopilotContext();
products = api.load(...)
useEffect(() => {
setCopilotContext((c) => {
return {
...c,
screen: {
content: ["A list of products", ...products],
},
};
});
}, [products]);
Context content
It is up to you to decide what client context you'd like to send to the copilot. If you don't want your copilot to respond to information that is on the user's screen or page, don't send any client context. If you'd like the copilot to provide detailed responses based on what the user has on their page or screen, send as much data in the client context as is appropriate.
Context format
The format and data type of the client context is up to you to decide, based on what you want to send, and how you want to manage it.
You can send a simple string:
<CopilotProvider context="I am on the products page" />
You can also send a complex JSON object:
<CopilotProvider
context={{
pageUrl: "/products",
pageTitle: "List of products",
pageContents: [...products.map(p => ({title: p.title, description: p.description price: p.price}))]
}}
/>
In either case the copilot will take the contents of the context
field, stringify it, and use it
as context to its reasoning process.
Custom UIs
If you don't want to use the pre-built UI components, you can also use React hooks or the the Continual REST API in a headless way to build your own components.