A private, page-aware AI agent SDK that runs entirely in the visitor's browser.
No API keys. No servers. No per-message cost. Chat mounts instantly; a ~79 MB quick model answers first, then the full model upgrades in the background with tools. All inference is 100% offline after the first download (WebGPU / WebLLM).
Zero-config — mount the shell, download on first ask:
<script>
window.Coign = window.Coign || function() {
(window.Coign.q = window.Coign.q || []).push(arguments);
};
Coign('init'); // mounts chat; never waits on model download
</script>
<script type="module" src="https://cdn.coign.dev/coign-loader.es.js"></script>
<!-- or classic IIFE: -->
<!-- <script src="https://cdn.coign.dev/coign-sdk.iife.js" crossorigin="anonymous"></script> -->import { init, ask, warmUp, hasModelCached, on } from 'coign-sdk';
await init(); // shellReady — widget up
await ask('What is this?'); // loads quick (~79 MB) if needed, streams answer
// full model (coign-lite) upgrades in background; tools unlock on upgraded- Loader (recommended):
coign-loader.es.js(~0.3 KB gzip) → dynamic-imports core (~14 KB) + WebLLM only on engage (~2.1 MB gzip chunk, in the engine worker by default) - IIFE (single file):
coign-sdk.iife.js(~2.1 MB gzip) — convenience when you cannot use ES modules; pays full WebLLM cost up front
npm install coign-sdk| Phase | What happens |
|---|---|
init() |
Config + widget shell. Outline deferred until ask when engage: 'ask'. Never awaits model download. Emits shellReady. |
| Engage | First ask / warmUp / panel open (when engage: 'open') / or engage: 'init' |
| Quick | coign-quick (~79 MB SmolLM2-135M). Streamed Q&A + page outline. No tools. |
| Full | Background upgrade to coign-lite (or your preset). Manual tool loop unlocked. |
on('downloadProgress', (p) => console.log(p.phase, p.stage, p.progress));
on('modelReady', ({ tier }) => console.log('ready', tier));
on('upgraded', () => console.log('tools unlocked'));
on('token', ({ token }) => process.stdout?.write?.(token));
await hasModelCached('quick'); // true if weights already in browser cache| Preset | Download | VRAM (approx) | Tools | Best for |
|---|---|---|---|---|
coign-quick |
~79 MB | ~200 MB | none | First answer (default progressive path) |
coign-tiny |
~207 MB | ~376 MB | none | Quick fallback (SmolLM2-360M) |
coign-lite |
~700 MB | ~1.1 GB | manual | Default full — docs, FAQ |
coign-balanced |
~1.8 GB | ~2.3 GB | manual | Stronger reasoning |
coign-quality |
~4.5 GB | ~5.1 GB | manual | Long-form reasoning |
coign-tools |
~4.5 GB | ~5.1 GB | native | Tool-call reliability (native loop stubbed) |
Config knobs (defaults shown):
| Option | Default | Role |
|---|---|---|
preset / model |
coign-lite |
Target full model |
quick |
true |
Progressive path (false = full only) |
quickPreset |
coign-quick |
First-answer model |
engage |
'ask' |
'ask' | 'open' | 'init' |
engineMode |
'worker' |
'worker' | 'main' |
stream |
true |
Token streaming |
cacheBackend |
'cache' |
WebLLM cache backend |
widget |
true |
Mount chat UI |
Coign uses WebLLM exclusively (no Chrome AI, no cloud APIs). Weights download once and cache locally. Inference runs on-device via WebGPU. Default engine placement is a Web Worker so the UI stays responsive during download/compile/generate.
Available after the full tier upgrade:
agent.searchPage— Full-text search (MiniSearch, lazy-loaded)agent.getPageOutline— Structured page outlineagent.getElement— DOM element inspection
Coign.tool({
name: 'addToCart',
description: 'Add an item to the shopping cart.',
parameters: { type: 'object', properties: { item: { type: 'string' } } },
risk: 'write',
execute: async ({ item }) => {
cart.add(item);
return { success: true };
},
});Shell-first. Mounts widget, patches config (including prompt), emits shellReady. Does not download a model.
Start quick (then full) download without asking. Idempotent.
Queues until a usable tier is ready. Streams via opts.onToken and token events.
Wraps WebLLM hasModelInCache for 'quick' | 'full'.
Events: shellReady, downloadStart, downloadProgress, downloadComplete, modelReady, upgraded, token, ask, answer, error, toolCall, toolResult, …
Tear down widget + worker engine.
Also: config, mount / unmount, show / hide, open / close, tool, clearHistory / exportHistory, checkSupport, swapModel, cancelEngineInit.
🔗 https://nwestfall.github.io/coign/
npm run build
npm run build:site
npm run preview:sitenpm install
npm run dev # Vite → /demo/phase1.html
npm run build # ES + CJS (code-split) + IIFE + SRI
npm run test:unit
npm run test # unit + e2e (build first for IIFE e2e)- Chrome 113+, Edge 113+, or other WebGPU browsers
- Disk for model cache (~79 MB quick; more for full presets)
- Inference: @mlc-ai/web-llm (WASM + WebGPU), default
CreateWebWorkerMLCEngine - Search: MiniSearch (lazy)
- Build: Vite —
coign-loader/coign-sdkES chunks + IIFE CDN bundle + engine worker - UI: Shadow DOM widget, phase-aware loading overlay, streaming tokens
MIT