Host integration guide
A working assistant on one claim screen in thirty minutes: five minutes of wiring, twenty mapping the host's claim onto ours, five testing. It is not thirty minutes to production; read Before going live.
This page is written for the developer on the host side. It is also in the repository as docs/integration-guide.md, which is the version we hand to host teams.
What is being integrated
An assistant that answers questions about the one claim currently on screen. The host page gives it that claim; it reads the claim through its own tools and streams back an answer showing which lookups it made. It can also be spoken to.
It is read-only. It cannot change anything in the host system, and it never sees any claim other than the one it is handed.
Before starting
We provide three things:
| Script URL | where claimpilot-assistant.js is served from |
| API base | the origin the assistant calls, for example https://assistant.example.com |
| API key | only if that deployment requires one |
The host gives us one thing back before any of it works: the origins its pages are served from, production and development, for example https://claims.example.co.uk and http://localhost:3000. We add them to ALLOWED_ORIGINS. Until then the browser refuses every call, and it looks exactly like the service being down. Ask early.
And from the host's own application: a claim object on the page, which it almost certainly has already, because it rendered the screen from it.
Step 1: add the script and the tag (5 minutes)
<!-- in <head> -->
<script type="module" src="https://assistant.example.com/claimpilot-assistant.js"></script>
<!-- a direct child of <body>; it positions itself -->
<claimpilot-assistant id="assistant" locale="en-GB" api="https://assistant.example.com"></claimpilot-assistant>
| Attribute | Required | Meaning |
|---|---|---|
locale | no | en-GB (default) or en-US: spelling, date style, claims terminology, and the accent in voice. |
api | unless same-origin | The origin the assistant calls. |
api-key | only if issued | Sent on the model-facing endpoints. |
screen-actions | no | Let the assistant highlight parts of the host page. See below. |
feedback-content | no | Let us store the question and answer text with each vote. Without it we store the vote only. |
The element renders into a shadow root, places itself as a floating launcher bottom-right, and takes up no space in the layout.
The launcher and panel are positioned against the viewport. Any ancestor with a transform, filter or perspective silently becomes the thing they are positioned against instead, and the assistant ends up pinned to the corner of a card halfway down the page.
The launcher opens a floating window. Its expand button switches to a side panel the full height of the right-hand edge, which covers the right of the page rather than reflowing it, and sits above the host's own fixed headers deliberately. The choice is remembered per browser.
Step 2: give it the claim (20 minutes)
The claim is a property, not an attribute. HTML attributes hold strings; a claim is an object.
- Plain JavaScript
- React 19
- Angular
- Vue
- Server-rendered
<script>
document.getElementById('assistant').claim = toClaimpilotClaim(hostClaim);
</script>
// React 19 assigns non-string props as properties on custom elements.
<claimpilot-assistant locale="en-GB" api="https://assistant.example.com" claim={toClaimpilotClaim(hostClaim)} />
<!-- add CUSTOM_ELEMENTS_SCHEMA to the module or standalone component -->
<claimpilot-assistant locale="en-GB" api="https://assistant.example.com" [claim]="mappedClaim"></claimpilot-assistant>
<claimpilot-assistant locale="en-GB" api="https://assistant.example.com" :claim.prop="mappedClaim" />
<!-- .NET, Rails, Django …: an inline script, or a JSON island read on load -->
<script id="claim-json" type="application/json">@Html.Raw(Model.ClaimpilotJson)</script>
<script>
document.getElementById('assistant').claim = JSON.parse(document.getElementById('claim-json').textContent);
</script>
The claim can be assigned before or after the script loads; the element handles both. Re-assign it whenever the claim changes. The conversation resets when the claim id changes.
The minimum claim
Eight fields. Everything else is optional and defaults to "nothing recorded".
{
id: 'CPN-2026-0042',
lineOfBusiness: 'property', // auto | property | workers_compensation | general_liability
title: 'Aldridge v Northgate Mutual',
status: 'under_review', // filed | under_review | approved | paid | denied | closed | reopened | reclosed
currency: 'GBP', // GBP | USD
claimant: { name: 'Helen Aldridge', type: 'individual' }, // individual | organisation
incident: {
dateOfLoss: '2026-08-14', // every date is YYYY-MM-DD
dateReported: '2026-08-15',
cause: 'Escape of water',
description: 'The washing machine inlet hose failed overnight, flooding the kitchen…',
},
policy: {
policyNumber: 'NM-HH-773120',
effectiveFrom: '2026-03-01',
effectiveTo: '2027-02-28',
state: 'active', // active | lapsed | cancelled | expired | pending_renewal
policyholder: { name: 'Helen Aldridge', type: 'individual' },
coverages: [{ code: 'BLDG', name: 'Buildings', limit: 250000, deductible: 250 }],
},
}
Money is a plain number in the claim's currency. Put real narrative in incident.description: it is the single field that most improves answers, because it is what the assistant reasons over when the structured data runs out.
Beyond the minimum, see Claim mapping.
Step 3: check it works (5 minutes)
Open the claim screen. The launcher appears bottom-right. Open it and ask "What is the policy number, and was the policy in force at the date of loss?". It is a good first question because it exercises a tool rather than just reading the summary.
If nothing appears, see Troubleshooting.
Optional: let it point at the screen
By default the assistant never touches the host DOM. To let it highlight the part of the page it is talking about, add screen-actions and mark the regions:
<claimpilot-assistant screen-actions …></claimpilot-assistant>
<section data-panel="finance">…</section>
<section data-panel="documents">…</section>
Recognised panel names: home, schedule, documents, finance, involvements, proceedings, strategy, finance_resolution, mi, system_checks, key_facts, schedule_table, proceedings_table, notes.
Optional: receive answer feedback
Each thumbs up or down fires a claimpilot-feedback event on the element:
document.getElementById('assistant').addEventListener('claimpilot-feedback', (event) => {
const { turnId, rating, reasons, note, question, answer } = event.detail;
// rating is 'up', 'down', or null when the user takes the vote back.
// The same turnId arrives again if the user changes their mind: replace, do not append.
});
The event always carries the question and answer. We keep the vote, reasons and note so we can improve the prompts; we keep the question and answer only with feedback-content, because that text quotes the host's claim.
Voice
The microphone button opens a spoken conversation with the same claim, prompts and tools. It needs microphone permission, a modern browser, and a page served over HTTPS or from localhost.
Before going live
Claim content leaves the host's estate. The claim is sent to the model provider and passes through our gateway and observability, which log requests and responses. Nothing is stored in a claims database on our side, but "not stored" is not "never transmitted". Tell data protection early.
It is read-only and advisory. No diary notes, tasks, payments or correspondence. Anything it drafts is for a person to review and send. It is not a system of record, and not legal, medical or financial advice.
There is no audit trail on our side. To evidence what the assistant said on a claim, log the interaction against the claim in the host system, where an auditor will look.
One claim, no history. It cannot see other claims or prior claims by the same claimant. A fraud check reasons about this claim alone.
Documents are summaries, not files. It reads the summary provided for each document. It cannot open a PDF.
Answers track the mapping, and nothing measures that. There is no scored evaluation. A thin claim produces thin answers.
Users can see it is AI. The panel carries a permanent "AI can make mistakes" notice. Do not remove or obscure it.
The origin list is not the host's access control. The decision about who may see a claim stays entirely in the host application. If a user should not see a claim, do not put it on their screen.
Weight and support. About 145 KB gzipped (measured from npm run build). Needs custom elements and shadow DOM: every current evergreen browser.
What is different from the demo
- No Prompt Lab. Prompts are fixed at whatever the deployment ships. A change is a release on our side.
- No claims list, claim screens or demo hints. The host's product is the claim screen.
- No generator. The integrated assistant only ever sees the host's claims.