Skip to content

Integration guide

@cavell/kit embeds the full Cavell AI-companion experience in your React application: chat with the Cavell agent, EHR tool cards, human-in-the-loop approvals and clarifying questions, Ask Aletta answers with citations, conversation history, and conversation starters/follow-ups. Under the hood it speaks the open AG-UI protocol over CopilotKit v2's headless core.

This page is the end-to-end path: prerequisites → install → first render → the host contract. The API reference documents every export; the component overview renders the design-system primitives; the cavell-kit-demo repo is a complete, runnable example of everything below.

Prerequisites

  1. A license. The kit is proprietary software of Polaris Health BV — using it requires written permission.
  2. Access tokens. The kit authenticates every request with the Authorization header your app provides (see Auth). For Corilus integrations these are the opaque tokens your platform already issues; tokens are per environment.
  3. This environment. This site documents the qa channel, whose API origin is https://qa.corilus.cavell.app. Each environment has its own docs site and release channel (and, from qa upwards, its own cavell-kit-demo branch) — a build you make against one environment should install that environment's kit release.
  4. FontAwesome Pro (see Peer assets).

Install

Grab the current release from the home page — the artifact is a versioned, immutable tarball:

bash
yarn add <tarball-url-from-the-home-page> \
         react react-dom zod \
         @copilotkit/react-core@1.65.0 @ag-ui/client@0.0.57 @ag-ui/core@0.0.57
  • One package. The Cavell design-system layer is bundled in and re-exported — Button, Icon, Tooltip, cn, markdownComponents, … all come from @cavell/kit.
  • Exact peers, on purpose. @copilotkit/react-core and the @ag-ui/* packages are peer dependencies pinned to exact versions: the kit instantiates the CopilotKit core, and a second copy in your tree would mean a second React context — your useFrontendTool registrations would land on a core the kit never reads. Upgrade them only together with a kit release that bumps the pin (that is always a major release). zod is CopilotKit's own peer.
  • Lockfiles. Pin the versioned tarball URL; your lockfile records its checksum. New releases are new URLs — upgrading is a deliberate dependency change, never a silent drift.

First render

tsx
import { CavellAssistant, CavellProvider } from '@cavell/kit'

import '@cavell/kit/styles.css'

const App = () => (
	<CavellProvider
		agentId="careconnect_gp"
		baseUrl="https://…" // this environment: see Prerequisites
		headers={() => ({ Authorization: `Bearer ${getToken()}` })}
		context={{ patient_resource_id: '…', emr_server_version: 'EMRServer-6.5' }}
		locale="nl"
		onSessionExpired={() => notifyHost()}
	>
		<CavellAssistant />
	</CavellProvider>
)

CavellAssistant is the complete surface (top bar, timeline, composer, history menu, context bar). Hosts composing their own layout can use the building blocks instead — ChatPanel, InputBar, TopBar, SessionMenu, … — every one is in the API reference.

Auth: the headers prop

The kit owns no credential. headers (object or thunk) rides every AG-UI run and every REST side call. Use the thunk form: it is re-resolved before each request, so a rotated token reaches the transport without a re-render. onSessionExpired fires on 401s and on the backend's session_expired run error; the surface shows a blocking overlay (typed drafts survive under it).

The declarative context

Pass the full current EHR context on the context prop — it is re-declared to the backend on every run, and the backend diffs it (patient switch, problem-in-focus change, …). Changing it takes effect on the next turn. Two conventions worth knowing:

  • Patient: declare patient_resource_id (and patient_name for instant display — never a photo). Auto-resume of a recent conversation requires a declared patient.
  • Problem in focus: declare problem (thesaurus code) plus optionally problem_term for instant chip display; clear by removing the key.

Scoped additions from anywhere in your tree can use the re-exported useAgentContext.

Your own tools (client-executed)

Register host tools with the re-exported CopilotKit hooks — the agent can then call your functions:

tsx
import { useFrontendTool } from '@cavell/kit'

useFrontendTool({
	name: 'open_patient_record',
	description: 'Open the patient record screen in the EHR',
	parameters: [{ name: 'patient_id', type: 'string', required: true }],
	handler: async ({ patient_id }) => openRecord(patient_id),
})
  • Up to 16 tools; the names request_approval and ask_user are reserved (the backend's human-in-the-loop primitives) and ignored server-side.
  • Avoid wildcard (*) tool handlers — they would swallow the reserved human-in-the-loop calls.
  • Human-gated host tools use useHumanInTheLoop; custom result rendering uses defineToolCallRenderer / the renderToolCalls prop (exact tool names only). The kit's own cards can be re-skinned per tool with the lighter toolCards prop.

Human-in-the-loop, sessions, feedback

These arrive without host code: server-side tools that require validation render an editable approval card (approve/reject with modifications), mid-execution clarifying questions render as prompts, SessionMenu lists and reopens past conversations, and every assistant answer carries feedback thumbs. The capabilities prop can gate each Cavell-profile feature off; pointing runUrl at a non-Cavell AG-UI agent gates them all off by default (plain chat + your client tools keep working).

Peer assets

The kit bundles no licensed assets. Two things your page must provide, both because they are licensed to you, not to us:

AssetWhyWithout it
FontAwesome ProIcon renders <i class="fa-light fa-…"> glyphs (light is the default family; solid/regular appear in a few components, brands rarely)icons render as empty boxes
InterThe type stack is 'Inter UI', 'Inter', system-ui, …text falls back to the system font

Nothing else: the Cavell logo is bundled into the kit (AssistantLogo, pass src to override), and @cavell/kit/styles.css carries every design token, reset rule and component style.

FontAwesome Pro — a Kit script

The one-line route if your FontAwesome account has a Kit. Add it to the page that mounts the assistant:

html
<script src="https://kit.fontawesome.com/<your-kit-code>.js" crossorigin="anonymous"></script>

FontAwesome Pro — self-hosted

Preferable when the page must not call out to a third-party CDN at runtime (and the route we take in our own applications). Your Pro subscription includes a private npm registry token (fontawesome.com → Account → Tokens). Point the @fortawesome scope at it — .yarnrc.yml for Yarn, .npmrc for npm:

yaml
npmScopes:
    fortawesome:
        npmRegistryServer: 'https://npm.fontawesome.com/'
        npmAuthToken: '<your FA Pro token>' # or the YARN_NPM_AUTH_TOKEN env var
bash
yarn add @fortawesome/fontawesome-pro
ts
import '@fortawesome/fontawesome-pro/css/all.min.css'

Your bundler emits the webfonts alongside the CSS, so nothing needs to be copied by hand. If you prefer static files, download Font Awesome Pro for the Web from your account instead and serve css/all.min.css together with the webfonts/ folder as siblings — the stylesheet resolves its fonts one level up, in a webfonts folder next to css. Keep at least fa-light-300, fa-solid-900 and fa-regular-400.

Inter

Inter is free (SIL Open Font License), so any route works — including self-hosting, which is what we recommend for the same reason as above:

bash
yarn add @fontsource/inter
ts
import '@fontsource/inter'

Serving your own copy works equally well: declare the woff2 files under the family name Inter in a @font-face block. One variable file covers every weight (font-weight: 100 900).

One stylesheet import covers everything else: @cavell/kit/styles.css (design tokens, base reset, components, utilities). If your app runs its own Tailwind v4 build over kit markup, import @cavell/kit/tokens.css (the raw @theme block) into your stylesheet instead of hand-copying token values.

Versioning & compatibility

  • The backend is fully backwards compatible with every released kit version — a Cavell backend release never forces you to update. New capabilities simply light up when you upgrade.
  • Every request carries the kit's build version (X-Cavell-Kit-Version). When your build falls behind the recommended version you'll hear it from us long before anything changes; in the rare, pre-announced case a version is end-of-lifed, runs answer with a structured client_outdated error and the surface shows an update-required notice — your application around it is untouched.
  • Releases are semver: major = action needed on your side (e.g. a peer-pin bump), minor = new features, patch = fixes. Artifacts are immutable; the home page always points at this environment's current release.

The worked example

cavell-kit-demo (branch = this environment) is the reference embedding: provider setup, frontend tools, human-in-the-loop, custom renderers, session list, feedback, host context declarations — written to be copied from. Clone it, yarn install, yarn dev, and paste a token.

Environment: qa — API https://qa.corilus.cavell.app