Assay

Get started

Install it, pick the check that fits, read the verdict.

On this page
  1. 1. Install
  2. 2. Pick the check that fits
  3. 3. Show the result
  4. Good to know

1. Install

npm install @extrafemi-ai/assay

2. Pick the check that fits

You ask an AI to write with sources: check the citations

import { createAssay, strip } from '@extrafemi-ai/assay';

const assay = createAssay({ mailto: 'you@example.org' });   // lets the record services contact you instead of blocking you
const report = await assay.check(aiText);

report.summary.text;                 // "Citations: 3 · ✓ 2 verified · ✕ 1 not verified"
report.ok;                           // false if any citation failed
const clean = strip(aiText, report); // failed citations become "[citation removed: could not be verified]"

You ask an AI to write from your own documents (a CV, a brief, a call): check quotes and numbers

import { checkQuote } from '@extrafemi-ai/assay/quotes';
import { checkFigures } from '@extrafemi-ai/assay/figures';

checkQuote(jobPosting, 'Visa sponsorship is available for this role');   // found, or missing
checkFigures(draft, [cv, brief]).summary.text;                           // "Figures: 3 · ✓ 2 supported · ✕ 1 not in your materials"

These two never touch the network, so they are safe to run on private text.

You publish claims that need a good source: use the gate

import { createGate, rules } from '@extrafemi-ai/assay/gate';

const gate = createGate({ rules: [rules.estimatesCausalLegalNeedSpecialist] });
gate.check([{ text: 'Delays cost traders an estimated $400m.', category: 'loss-estimate', sources: [{ url: 'https://reuters.com/x', date: '2026-01-01' }] }]);

Your draft tags each line with the approved fact it came from: check the grounding

import { checkGrounding } from '@extrafemi-ai/assay/grounding';

checkGrounding('The rate moved to ₦425 in 2023 [[c1]].', [{ ref: 1, text: 'The official rate averaged ₦645.19 in 2023.' }]);

3. Show the result

Every check answers the same way: ok, a one-line summary.text, and a verdict for each item with a message in plain words. Messages can contain text that came from the web or from a model, so put them on a page with textContent, or run escapeHtml() (exported) first.

Good to know

  • Browsers and servers. Citations, quotes, figures, the gate, grounding and values run anywhere with fetch: Node 20 or later, browsers, Cloudflare Workers. The link checker is server-side only on purpose.
  • Be polite to the free services. Give mailto so CrossRef and OpenAlex can reach you. OpenAlex also gives each address a small daily budget; a free key from openalex.org lifts it.
  • Read the limits before you trust a green tick. What it cannot do.
  • Every option, every status, every message is in the reference.