A preview of a new class of System One-style models, extraction models, is now available. The first, Clairic, is hosted on Workers AI as @cf/cloudflare/clairic, with open weights intended for release soon. Clairic extracts, computes, estimates and forecasts values from unstructured inputs, claiming higher accuracy, lower latency and lower cost than traditional LLMs.
Where extraction models fit
TypeSafe's System One announcement drew on Daniel Kahneman's Thinking, Fast and Slow: a System One model should be fast and precise, unlike a System Two model capable of deliberate reasoning such as an LLM. TypeSafe's Jev, a purpose-fit model for a specific domain and priced to match, excelled where LLMs failed by helping users decide from probabilities and well-typed outputs, and it prompted interest in models that are not LLMs and how to slot them into workflows.
Much traffic to frontier LLMs consists of repeated structured-output calls of the same shape: What's the invoice total? When was this delivered? How many days late is it? What will this repair cost? What will traffic look like over the next 24 hours? Such answers can't be enumerated in advance, which is what a decision model needs to assign probabilities — hence the new class.
Values instead of probabilities
Every System One model until now has been a decision model: Jev and Clef take an input state and a list of questions and return probabilities against them. Clairic is the first System One extraction model. It is still fast, typed and cheap, but answers with values taken directly from the input, computed from it, or predicted beyond it.
Model tasks generally ask for one of three outputs: a number, a choice from a fixed set, or open-ended text. Clairic handles the first, returning numbers with an 80% range and pulling typed values such as names, dates and lists out of the input. Clef handles the second, selecting among options with a probability for each, and LLMs handle the third. Both are classed as System One models because they answer in a single pass without reasoning or generating tokens; they charge only for input and typically respond in under a second, whereas an LLM reasoning through the same step takes several seconds. An extraction model can return:
- Extracted values: text copied from the input, such as a name, an order ID or a description, each as a span with character offsets and a confidence score.
- Computed values: numbers, dates, times, datetimes, durations and lists, read from the input or worked out from it, following the rules of their type (two decimals for cents, for example) and carrying a confidence score.
- Estimated values: values the input doesn't state but gives evidence for, returned as a distribution inside declared bounds and on a specified grid, with a median and an 80% interval.
- Forecasted values: future values of a series, one estimate per step ahead, each with its own 80% interval.

Because it generates no tokens, it cannot mistype an answer or "hallucinate" the way an LLM can, though it can still make mistakes. Outputs are a value of the requested type, or null when no answer is found, and confidence scores accompany the outputs so you can judge whether to trust the result or take a second look. The figure below places extraction models among System One and System Two models:
System One: Extract | System One: Decide | System Two | |
Example models | Clairic | Jev, Clef | GPT, Claude, Gemini, DeepSeek |
Sampling | One parallel pass | One parallel pass | One token at a time |
Purpose | Predict values | Make decisions | Write and reason |
ML framing | Regression and extraction | Classification | Generation |
Thinking mode | System 1: fast, one pass | System 1: fast, one pass | System 2: slow, deliberate |
Output | Typed values: spans, numbers, dates, times, lists, distributions, with calibrated probabilities | Typed decisions: options with calibrated probabilities | Free-form strings |
Output space | Continuous, but typed and bounded by your schema | A finite set of options you list | Anything |
What it answers | What's the amount? When does it happen? How much will it be? | Which category is it? Is it legitimate? Which action should we take? | Why did it happen? How should we approach it? Can you fix it? |
Output always a valid response? | Yes: every answer is a value of its declared type (or null), inside your bounds | Yes: answers are always one of your options | No: strings must be parsed and checked |
The three kinds work in concert: extraction models turn raw input into typed values, decision models turn values into decisions, and LLMs turn decisions into words.
Request anatomy
Like a decision model, Clairic processes only input tokens in a single forward pass and has no output-token charge. A request consists of a state — the text to read plus up to four optional images — and a map of typed fields. You name each field, assign a type and optional plain-language instructions, and receive one typed answer per field from a single parallel pass.
Type | Returns |
| A specific span of the input, with its offsets |
| A number read or computed, honoring |
| Calendar dates and valid times, in ISO form |
| A length of time in the unit you choose |
| Matching text, number or date, in input order |
| A distribution inside your |
| One estimate per future step of a series |
Every scalar answer carries p_null (the probability that the value isn't in the inputs) and confidence. Every estimate answer carries a median and an 80% interval (p10 to p90), with all 99 percentiles available on request. The number of fields is unlimited: if they don't fit beside the input in one pass, the server splits them into parallel passes that each see the whole input, then merges the answers.
The examples below illustrate the model's features; using them in a workflow would, of course, require appropriate inputs.
Extraction in practice
Extraction is among the most common jobs handed to LLMs: "return the invoice number, vendor and due date as JSON." It usually works, but the failure modes are hard to catch. The output may not be valid JSON, a digit can be misread while being generated, and a returned text excerpt cannot be traced back to its position in the source. Many teams respond with extraction pipelines of parsing layers, schema validation, retries and spot checks — and still pay for reasoning and output tokens on every field of every document.
Clairic instead returns values grounded in the input, computed values that avoid pre-sanitizing unstructured data, character offset spans pointing to where the data appeared, confidence labels for spotting values that need review, strongly typed output (a cents field has two decimals), null handling for missing fields (alongside an estimated probability of null and a guess), and cheaper, faster answers because every field is answered in the same parallel pass — asking for thirty fields costs about the same as asking for three.
Consider a customer support email:
Hi, order A-88412 arrived on Sept 28, 2026 with a cracked screen and a dented corner. I paid $649.00 plus $52.10 tax. It's now Oct 9, 2026 and I'd like this fixed or refunded. Thanks, Dana
From a Worker, a request to Clairic would look like this:
const { answers } = await env.AI.run("@cf/cloudflare/clairic", {
state: email,
fields: {
order_id: { type: "text", instructions: "Order number" },
delivered_on: { type: "date", instructions: "Delivery date" },
amount_paid: { type: "number", decimals: 2, unit: "USD", instructions: "Total paid including tax" },
days_since_delivery: { type: "duration", unit: "days", integer: true,
instructions: "Days from delivery to the date the customer wrote" },
damage: { type: "list", items: "text", instructions: "Each kind of damage described" },
tracking_number: { type: "text" },
},
});
The response contains the extracted values, spans in the input, the probability of null (p_null) and a confidence score:
{
"order_id": {
"type": "text",
"p_null": 3.4e-6,
"span": [10, 17],
"guess": "A-88412",
"confidence": 0.999957,
"value": "A-88412"
},
"delivered_on": {
"type": "date",
"p_null": 6.5e-8,
"guess": "2026-09-28",
"confidence": 0.999999,
"value": "2026-09-28"
},
"amount_paid": {
"type": "number",
"p_null": 1.6e-5,
"guess": 701.1,
"confidence": 0.999944,
"value": 701.1
},
"days_since_delivery": {
"type": "duration",
"p_null": 6.1e-9,
"unit": "days",
"guess": 11,
"confidence": 0.999999,
"value": 11
},
"damage": {
"type": "list",
"value": ["cracked screen", "dented corner"],
"spans": [[50, 64], [71, 84]]
},
"tracking_number": {
"type": "text",
"p_null": 1,
"span": [106, 112],
"guess": "$52.10",
"confidence": 0.416016,
"value": null
}
}
Several details stand out. amount_paid appears nowhere in the email; Clairic added price and tax in the same pass and returned the sum. days_since_delivery is likewise worked out from two dates rather than stated. damage lists both kinds of damage as exact spans, which supports highlighting them in the source. tracking_number isn't in the email, so it returns null rather than a plausible-looking guess; guess shows what the model would otherwise have picked.
Images as input
A real-life photo of a receipt — imperfect text and an unhelpful camera angle — was passed to Clairic to see what it could extract:

{
"model": "clairic",
"answers": {
"order_number": {
"type": "number",
"p_null": 0.0040206750854849815,
"guess": 77245,
"confidence": 0.776249383996532,
"value": 77245
},
"purchased_at": {
"type": "datetime",
"p_null": 4.136094133855295e-08,
"guess": "2026-07-01T13:34:00",
"confidence": 0.831464227002992,
"value": "2026-07-01T13:34:00"
},
"quantity": {
"type": "number",
"p_null": 5.2313655629632194e-08,
"guess": 2,
"confidence": 0.9997007500403496,
"value": 2
},
"unit_price": {
"type": "number",
"p_null": 0.001599092734977603,
"guess": 7.99,
"confidence": 0.9991279019989127,
"value": 7.99
},
"subtotal": {
"type": "number",
"p_null": 9.69956488461321e-08,
"guess": 15.98,
"confidence": 0.9999881983893096,
"value": 15.98
},
"sales_tax": {
"type": "number",
"p_null": 2.5511653802823275e-06,
"guess": 0,
"confidence": 0.9999800924450729,
"value": 0
},
"tip": {
"type": "number",
"p_null": 5.953857908025384e-05,
"guess": 2.39,
"confidence": 0.9335768781214697,
"value": 2.39
},
"discount": {
"type": "number",
"p_null": 0.9994148015975952,
"guess": 0,
"confidence": 0.91852733929319,
"value": null
}
}
}
It extracted all the values from the image with confidence scores, and correctly reported that no discount was shown, returning null for that value.
Estimation with declared bounds
Some values never appear in the input but are evidenced by it, and may be discernible from surrounding values. Asking an LLM usually yields a single number with no sense of the model's certainty: it makes safe guesses, hallucinates or reasons around the answer. Downstream processing can't distinguish a confident $180 from an unconfident $180, so it can't inform decisions about what to automate, and reasoning through an LLM is slower and more expensive. A decision model can approximate an estimate by choosing among buckets ("under $100", "$100–500", …), but buckets are coarse, each one adds input tokens, and each new category introduces more sources of confusion during decision making.
Clairic returns a distribution over the range you declare: a point value, a median, an 80% interval and every percentile on request. The estimate is designed to fall inside your bounds, so nothing needs clamping or rounding afterward. Interval width reflects data confidence — narrow for high certainty, wide for low — which can be used to route another check. Given historical home prices and comparable sales, for instance:
const { answers } = await env.AI.run("@cf/cloudflare/clairic", {
state: `Comparable sales:
sqft,beds,year_built,neighborhood,sale_price
1450,3,1998,Elm Park,412000
2100,4,2006,Elm Park,585000
980,2,1975,Riverside,265000
1600,3,2003,Elm Park,449000
1300,3,1990,Riverside,318000
Subject property:
sqft,beds,year_built,neighborhood
1620,3,2001,Elm Park`,
fields: {
sale_price: { type: "estimate", unit: "USD", min: 50000, max: 5000000, scale: "log", step: 1000 }
});
The model returns an estimated value:
{
"sale_price": { "type": "estimate", "value": 418000, "median": 415000, "p10": 370000, "p90": 470000, "p_below": 0.0, "p_above": 0.0 }
}
Values always fall inside the bounds, and the interval width shows how much the input informs the prediction: price is narrow ($370,000–$470,000) while days on market is wide (24–148). Since fields are unlimited and answered in parallel, many items — one estimate per candidate, lead or listing — can be scored in a single call and sorted in code.
Forecasting a time series
Forecasting time-series values is difficult for generalized models. The options are usually a dedicated pipeline per metric (parse, fit, tune, deploy) — accurate but costly and slow to build for every new series — or pasting 36 months of numbers into an LLM and asking for the next three, which is easy but yields point forecasts with no intervals, forecasts that shift with prompt wording, and limited confidence. Clairic sits between the two: it does not claim to replace a dedicated time-series model, but it is a little faster and cheaper than a regular LLM. A forecast field takes the history as plain text in state and returns, for every step ahead, a value and an 80% interval inside your declared bounds. It reads the history as you already have it — a CSV export, a pasted dashboard, or rows mixed with notes — and may often work without cleaning the data first.
To test this on real data, the count of people screened daily by the Transportation Security Administration (TSA) at U.S. airport checkpoints was used. Each morning for 21 days in a row, Clairic was asked for the next day's count given the real counts so far:
const { answers } = await env.AI.run("@cf/cloudflare/clairic", {
state: `Daily number of people screened at TSA checkpoints at US airports.
date,weekday,travelers
2026-07-16,Thu,2850229
...
2026-10-13,Tue,2353356
Forecast date: 2026-10-14 (Wed)`,
fields: {
travelers: { type: "forecast", horizon: 1, interval: "day",
min: 500000, max: 4000000, scale: "log",
instructions: "Number of people screened tomorrow" },
},
});
Which returns:
{
"travelers": { "type": "forecast", "value": [2416117], "median": [2419283], "p10": [2270774], "p90": [2556769] }
}
TSA actually screened 2,419,474 people that day, close to the median of 2,419,283 that Clairic predicted.

Data: TSA checkpoint travel numbers, accessed Oct. 15, 2026.
Over the 21 days, forecasts were off by 3.3% on average, and 17 of the 21 actual counts fell inside the 80% interval, consistent with what an 80% interval should do. The weekly rhythm emerged from the numbers alone: quieter Tuesdays and Saturdays, busier Thursdays, Fridays and Sundays. The misses are informative too: three of the four days outside the interval fall on the Columbus Day weekend, when more people flew than previous weeks suggested. Clairic forecasts from patterns in the series but doesn't account for events the series doesn't show, such as holidays.
Pairing Clairic with decision models and LLMs
A System One extraction model is meant to slot into an agentic workflow rather than replace it: the extraction model predicts values, a decision model decides what to do with them, and an LLM acts on the result. That split avoids the usual trade-off of either pulling data out of documents by hand for an LLM or letting an LLM parse messy inputs itself, which is slow, expensive and prone to hallucination.
The damaged-product claim workflow is one illustration, available as a live demo.
// 1. Clairic turns the email into values
const facts = (await env.AI.run("@cf/cloudflare/clairic", {
state: email,
fields: {
customer_name: { type: "text", instructions: "Customer's first name" },
order_id: { type: "text", instructions: "Order number" },
amount_paid: { type: "number", decimals: 2, unit: "USD", instructions: "Total paid including tax" },
days_since_delivery: { type: "duration", unit: "days", integer: true,
instructions: "Days from delivery to the date the customer wrote" },
damage: { type: "list", items: "text", instructions: "Each kind of damage described" },
repair_cost: { type: "estimate", unit: "USD", min: 10, max: 5000, scale: "log", step: 1,
instructions: "Cost to repair the damage described" },
},
})).answers;
const { customer_name, order_id, amount_paid, days_since_delivery, damage, repair_cost } = facts;
// 2. Clef decides from Clairic's values and the policy, not from the raw email
const options = {
refund: "Full refund of the amount paid",
repair: "Free repair, with a prepaid shipping label",
};
const { choice } = (await env.AI.run("@cf/cloudflare/clef", {
state: `Damage claim for order ${order_id.value}.
Paid: $${amount_paid.value.toFixed(2)}. Delivered ${days_since_delivery.value} days ago.
Damage reported: ${damage.value.join(", ")}.
Estimated repair cost: $${repair_cost.median} (80% range $${repair_cost.p10}-$${repair_cost.p90}).
Policy: refunds within 30 days of delivery. Prefer repair when it costs less than 60% of the price and the damage doesn't stop the product from working.`,
questions: {
resolution: { type: "choice", instructions: "What should we offer?", criteria: options },
},
})).answers.resolution;
// 3. An LLM writes the reply, from the decision and the facts it needs
const { response } = await env.AI.run("@cf/zai-org/glm-5.3", {
messages: [{
role: "user",
content: `Write a short, warm reply to ${customer_name.value}. Use only these facts: order ${order_id.value}; ` +
`damage: ${damage.value.join(", ")}; what happens next: ${options[choice]}. Under 60 words.`,
}],
});
Each stage receives cleaner input than the last. Clef decides from a five-line summary of typed values rather than a free-form email, which also shrinks its exposure to prompt injection. The LLM never sees the email, only the decision and the predictions it needs, so there is less numerical material it can misuse. Everything is typed and auditable, and exactly one step generates text. In an all-LLM pipeline, all three steps are generative calls, and every value in the reply has to be verified by hand.
Comparing a cascade against an all-LLM pipeline
Using GLM-5.3 to write the reply in both versions, with the all-LLM version also doing extraction and the decision from the same email, policy and prompts:
Clairic → Clef → GLM-5.3 | GLM-5.3 for every step | |
Latency, end to end | 19.3 s | 61.7 s |
1. Extract | Clairic: 0.46 s | GLM-5.3: 16.1 s |
2. Decide | Clef: 0.22 s | GLM-5.3: 21.9 s |
3. Reply | GLM-5.3: 18.6 s | GLM-5.3: 16.4 s |
Input tokens | 701 ($184 per million claims) | 390 ($546 per million claims) |
Output tokens | 1,329 ($5,848 per million claims) | 2,544 ($11,194 per million claims) |
Cost per million claims | $6,032 | $11,740 |
The cascade completed in 19.3 seconds versus 61.7 seconds, a 69% time reduction and roughly 3.2x faster. Clairic and Clef handled extraction and the decision together in under a second, where GLM-5.3 needed 38 seconds for those two steps, and the cascaded pipeline costs 49% less. Both approaches got the facts and the decision right in every run, but Clairic returned the same repair estimate each time, while GLM-5.3 varied ($250, $250 and $220, with a different range on each run).
With the all-LLM pipeline, both Gemma 4 and Qwen failed at the task, unable to derive values such as repair_cost from the inputs — a sign of how poorly LLMs handle data extraction.

What the preview does well, and what it doesn't
Clairic is now available as a hosted endpoint on Workers AI, with open weights planned for release later. The current endpoint is an early checkpoint; the observations so far:
- Reading is strong; multi-step arithmetic is not. One- and two-step calculations — totals, differences, conversions, date arithmetic — appear reliable. Longer chains of dependent steps are difficult for any one-pass model without a scratchpad, as is aggregating across many rows of a table. For now, let Clairic predict the value and have code do the math.
- Estimates need evidence. Clairic estimates best from comparables, history or descriptive text in the input. Values it has no evidence for may come back with limited specificity.
- Calibration is measured, not guaranteed. Intervals are trained to be calibrated and are on most held-out sets, but can run narrow on unfamiliar data.
- Forecasting is basic. The model is not built to replace time-series models trained on specific data. Use it for non-critical, general pattern matching rather than detailed long-horizon forecasting.
- Use confidence signals. The architecture makes every answer well formed, not necessarily correct. Use
confidence,p_nulland the intervals to decide what to automate and what to route for review.
Arithmetic, estimation and forecasting will be addressed further in future checkpoints.
Access and naming
Clairic is available as a preview on Workers AI under @cf/cloudflare/clairic. It can be called from a Worker via env.AI.run() or from anywhere through the REST API. Full model documentation is published, along with an explainer on the extraction model API.
The name follows from the same logic as Clef: the "cl" sound and musical roots (Clair de Lune), clerical tasks like extracting data clearly from a corpus and upholding accuracy in bookkeeping, the "Clair" root for estimating and predicting values, and [Cl]oudflare's [AI R]egression model.



