# Atomic Question Decomposition
Atomic question decomposition means replacing one broad question to an AI model ("is this spam?") with several narrow questions that each check a single fact ("does the body ask for a password?", "does the link domain match the sender?"). The model answers each one independently, and **code** combines the answers, applies the thresholds and does anything numeric. [[TypeSafe AI]]'s docs call it "probably the most important concept" for building with [[Jev]], and I think it's useful far beyond Jev.
It's the same move as [[Atomic notes]] in knowledge management, and [[Divide and conquer]] in programming: one idea per unit, so each unit can be inspected, reused and fixed on its own.
## Why broad questions fail
A broad question hides several judgments behind one answer. When "is this spam?" returns 0.6, you don't know *which* part of the reasoning was uncertain, you can't tune one criterion without touching the others, and you can't reuse any of it. Decomposed questions expose each judgment, so you can see which one misfired and fix only that one.
There's also a model-specific reason. The Jev 1.13 docs admit the model reads literally, struggles with indirection (a property of a property, double negatives), and loses accuracy as irrelevant context grows (i.e. [[AI Context Rot]]). Narrow questions pointing at a specific part of the state avoid all three.
## What it looks like
**Spam.** One `is_spam` question becomes six yes/no questions (Nouls, see [[System One Primitives]]):
1. Does `message.body` ask for a password or login credential?
2. Does it claim an unexpected prize, payment or reward?
3. Does the subject or body pressure the recipient to act quickly?
4. Does the sender's display name conflict with the email domain?
5. Does the link domain conflict with the organization named?
6. Does the link text disguise its real destination?
**Tool-call verification.** "Is this trace correct?" becomes nine checks: is the geocoding tool relevant, does the location match the request, are the coordinates reused from the previous result, does the date match "tomorrow", is the unit Fahrenheit as requested, and so on. When the trace is wrong, you know exactly where.
**Wording matters as much as splitting.** In the autoformat cookbook, asking "does this line pick up mid-sentence?" rebuilt 17 correct blocks from a de-formatted memo, while "is this line in the same paragraph?" gave 12, because list items share a topic and got merged. Ask about the narrowest fact that decides the case.
## Model reads, code computes
The second half of the method: **keep everything that isn't a judgment out of the model**. Jev's docs list what to keep out: math, counting, date comparison, numeric closeness (e.g., comparing hex colors) and multi-hop logic.
- **Counting**: don't ask "how many fruits are in this list?". Ask one Noul per item ("is `items[3]` a fruit?") and sum in code
- **Dates**: don't ask "is the deadline before the end of Q3?". Extract the parts as Choices (month, day, year with explicit `none` and `out_of_range` options), assemble the date in code, compare in code. The date extraction cookbook got 6/6 dates right with confidences 0.91-0.97, and flagged the one date the document never stated (0.46) for review
- **Business rules**: `days_overdue > 30` belongs in code, always
This goes with a broader architecture TypeSafe calls "AI-powered software": **code owns the control flow**, and the model is only called for narrow, typed judgments. It's the opposite of an agent loop where the model decides what happens next. See [[Machine Native Intelligence]].
## Decomposition doesn't cost round trips
The obvious objection: six questions instead of one means six times the calls. With a decision model, it doesn't. All questions in a request share the same state and run in parallel, so extra questions cost only their own tokens (13 questions in one call were 12.2x cheaper and 10x faster than 13 calls in the parallel questions cookbook). The docs only recommend a second request when the dependency is real, i.e. code can't even *build* the next question without the first answer (ranking 182 skills before fetching the full text of the top 3, or walking a taxonomy one level at a time in [[Hierarchical Classification]]).
## The independent evidence (and its catch)
Rajesh Beri tested this on 2,000 phishing emails (PhishNChips v5.2):
| Setup | Jev | Claude Haiku 4.5 |
|---|---|---|
| One binary question | 62.6% | 81.3% |
| Five atomic questions + logistic regression (fit on 1,000, tested on 1,000 held out) | **95.0%** | 93.2% |
Jev was 12-27x cheaper. So decomposition turned Jev from clearly worse to slightly better. But read the catch: Haiku's single best signal alone reached 94.2%, and Beri's verdict is sharp: "The 95% is not Jev. It is Jev plus your labelled data plus a regression you maintain." Decomposition is a method, and the method helps LLMs too.
## How to apply it
- **One snap judgment per question.** Something a knowledgeable person decides in about a second. "Analyze and determine the best course of action" is a sign you need to split
- **Phrase it so "yes" means the interesting case.** For verifiers, make "bad = TRUE"
- **Ask about intent or action when that's what separates cases**, not about the topic
- **Filter the state** to what the question needs; point at fields by name
- **Combine in code**: rules, weighted sums ([[Composite Scoring]]), or a small model trained on the answers ([[LLM-Generated Features for Classical ML]], [[Logistic Regression]])
- **Keep questions and thresholds in one reviewed file.** TypeSafe warns that coding agents write bad questions
## Limits
- **Composition isn't free.** Anthony Maio's point: "Individually calibrated judgments do not automatically compose into a calibrated workflow once you run them through thresholds, weights, and branches." You need to measure the combined system, not just the parts
- **The combining logic needs data or judgment.** Weights and regressions have to come from somewhere, usually labeled examples
- **Some questions don't decompose.** Open-ended reasoning, writing or anything whose answer space you can't enumerate still belongs to an LLM
## My take
I find this idea almost comforting, because it's the same lesson I keep relearning with notes, code and prompts: small, explicit units compose; big, vague ones rot. What changes with cheap decision models is the economics. Asking nine questions instead of one used to be a luxury; now it's the cheap option. The real work moves to writing good questions, which is a skill worth practicing.
## References
- [How to build with System One (TypeSafe docs)](https://docs.typesafe.ai/concepts/how-to-build-with-system-one)
- [Jev 1.13 jaggedness (TypeSafe docs)](https://docs.typesafe.ai/model-jaggedness/jev-1.13)
- [Date extraction cookbook (TypeSafe docs)](https://docs.typesafe.ai/cookbooks/date_extraction_cookbook)
- [Autoformat cookbook (TypeSafe docs)](https://docs.typesafe.ai/cookbooks/autoformat)
- [Parallel questions cookbook (TypeSafe docs)](https://docs.typesafe.ai/cookbooks/parallel_questions)
- [TypeSafe Jev: typed decision model, calibration, decomposition (Rajesh Beri)](https://www.beri.net/article/typesafe-jev-typed-decision-model-calibration-decomposition-shadow-eval)
- [Jev: the language model that won't talk (Anthony Maio)](https://anthonymaio.substack.com/p/jev-the-language-model-that-wont)
## Related
- [[Jev]]
- [[System One Primitives]]
- [[Machine Native Intelligence]]
- [[Composite Scoring]]
- [[Speculative Fan-Out]]
- [[LLM-Generated Features for Classical ML]]
- [[Candidate-Then-Select Extraction]]
- [[Hierarchical Classification]]
- [[AI Context Rot]]
- [[Atomic notes]]
- [[Divide and conquer]]
- [[Prompt Engineering]]