Teach it by example. Watch it prove the rule.
Apostol derives operational rules from finished examples, attacks its own conclusions, and refuses when the evidence does not determine one answer.
- LOCALLearns and runs on your machine
- VERIFIEDEvery adopted rule shown survived the recorded tests
- NON-GUESSINGAmbiguity produces a question, not a made-up answer
- REPRODUCIBLEThe decision path stays inspectable
Pick something to check
A spreadsheet executes a rule a person already wrote. Apostol derives the rule from finished examples — then tests whether the evidence truly determines it.
What Apostol is doing
- Examples
- Possible rules
- Elimination
- Hidden checks
- Trick attempts
- Adopt or refuse
- Decision record
Apostol searches a bounded space of possible rules. Evidence removes them. Tests attack the survivors. A rule is adopted only when exactly one behavior remains. Otherwise it names the evidence still missing.
It is not a chatbot, and no text generation hides its steps.
Flag patients who need urgent review
Twelve patient charts, each with a plain early-warning score. Watch it learn the escalation rule from examples, prove it can't be tricked into a confident wrong answer, then watch it apply the same discipline to a second vital sign entirely.
| Chart | Systolic BP | Heart rate | Temp (°C) | Score |
|---|---|---|---|---|
| P0001-E01 | 108 | 74 | 36.7 | 1 |
| P0002-E01 | 116 | 82 | 36.9 | 2 |
| P0003-E01 | 122 | 88 | 36.6 | 3 |
| P0004-E01 | 128 | 70 | 37.0 | 0 |
| P0005-E01 | 131 | 95 | 36.8 | 4 |
| P0006-E01 | 139 | 63 | 37.1 | 2 |
| P0007-E01 | 144 | 102 | 36.5 | 6 |
| P0008-E01 | 148 | 77 | 37.3 | 5 |
| P0009-E01 | 153 | 58 | 36.9 | 7 |
| P0010-E01 | 159 | 91 | 37.2 | 8 |
| P0002-E02 | 162 | 68 | 36.8 | 9 |
| P0011-E01 | 171 | 84 | 37.0 | 12 |
Chart IDs are placeholders only — no name, date of birth, or other identifying detail is in this sample.
ObserveYou show it 6 finished examples — the way you'd train a new hire.
ProposeIt came up with 89 possible rules — among them: news2_score ≥ 6.5 (the one it kept), news2_score ≥ 4.5, news2_score ≥ 7.
EliminateOnly 2 explanations held up.
WithholdIt hid 29 of the checks from itself until the end.
ChallengeThen it ran 20 trick attempts. One explanation survived everything.
Score 7 or higher on the NEWS2 scale: call the rapid response team.
Learned from 6 worked examples — nobody programmed this threshold in.
See it under the hood
The raw record:
op=classify params={"rule": ["ge", 6.5, "met_call", "ward_review"], "src": ["key", "news2_score"]}
accounting: proposals=89 train_checks=89 holdout_checks=29 survivors=2 adoptions=1 refusals=0
Its decision record, verbatim: “passed 29 held-out, 20 adversarial and 0 negative-rule checks; injected-contradiction check refused as required.”
Plain-English key for the record’s own terms: “held-out” = examples it hid from itself · “adversarial” = attempts to trick itself · “underdetermined” = your examples fit more than one rule.
Every AI you've used guesses when it's unsure. Watch this one refuse.
news2_score ≥ 4.5
news2_score ≥ 7
RefuseIt refused to guess.
Needed evidence:
“What should happen for a patient at score 6?”
It did not report low confidence. It constructed the exact example that separates the surviving rules.
See it under the hood
The raw record:
DECISION: REFUSE (underdetermined)
missing labeled input: {"news2_score": 6, "patient_ref": "P0198-E01", "resp_rate_bpm": 24, "spo2_pct": 93}
Plain-English key for the record’s own terms: “held-out” = examples it hid from itself · “adversarial” = attempts to trick itself · “underdetermined” = your examples fit more than one rule.
Taught separately on blood pressure alone — a different vital sign, the same discipline — it drew its own line, independently.
It learned: systolic BP 138 or higher also means review.
It formed 89 possible explanations, checked itself against 26 answers it had hidden from itself, then tried 16 ways to trick itself — one explanation survived everything. Same discipline, a different vital sign.
See it under the hood
The raw record, from 6 finished examples on bp_systolic_mmhg alone:
op=classify params={"rule": ["ge", 137.5, "review", "no_review"], "src": ["key", "bp_systolic_mmhg"]}
accounting: proposals=89 train_checks=89 holdout_checks=26 survivors=2 adoptions=1 refusals=0
Plain-English key for the record’s own terms: “held-out” = examples it hid from itself · “adversarial” = attempts to trick itself · “underdetermined” = your examples fit more than one rule.
Real result, recorded from a live run of the same toolkit you can download below — reproduce it on your machine.
Spot out-of-spec parts instantly
Twelve measured parts, each with how far off nominal size they landed. Watch it learn the tolerance line from examples, refuse to guess where the examples run out, then catch a drift no single reading would flag.
| Part | Machine | Deviation (µm) |
|---|---|---|
| PT-3001 | M4 | 8 |
| PT-3002 | M5 | 14 |
| PT-3003 | M4 | 19 |
| PT-3004 | M6 | 22 |
| PT-3005 | M5 | 31 |
| PT-3006 | M4 | 38 |
| PT-3007 | M6 | 44 |
| PT-3008 | M5 | 52 |
| PT-3009 | M4 | 61 |
| PT-3010 | M6 | 68 |
| PT-3011 | M5 | 77 |
| PT-3012 | M4 | 90 |
ObserveYou show it 8 finished examples — the way you'd train a new hire.
ProposeIt came up with 103 possible rules — among them: deviation_um ≥ 47.5 (the one it kept), deviation_um ≥ 52.5, deviation_um ≥ 80.
EliminateOnly 2 explanations held up.
WithholdIt hid 17 of the checks from itself until the end.
ChallengeThen it ran 12 trick attempts. One explanation survived everything.
A part is out of tolerance once it drifts 47.5 micrometers or more from nominal.
Learned from 8 worked examples — nobody programmed this threshold in.
See it under the hood
The raw record:
op=classify params={"rule": ["ge", 47.5, "out_of_tolerance", "in_tolerance"], "src": ["key", "deviation_um"]}
accounting: proposals=103 train_checks=103 holdout_checks=17 survivors=2 adoptions=1 refusals=0
Its decision record, verbatim: “passed 17 held-out, 12 adversarial and 0 negative-rule checks; injected-contradiction check refused as required.”
Plain-English key for the record’s own terms: “held-out” = examples it hid from itself · “adversarial” = attempts to trick itself · “underdetermined” = your examples fit more than one rule.
Every AI you've used guesses when it's unsure. Watch this one refuse.
deviation_um ≥ 52.5
deviation_um ≥ 80
RefuseIt refused to guess.
Needed evidence:
“What should happen for a part that drifts 65 micrometers?”
It did not report low confidence. It constructed the exact example that separates the surviving rules.
See it under the hood
The raw record:
DECISION: REFUSE (underdetermined)
missing labeled input: {"deviation_um": 65, "machine_id": "M9", "measured_um": 5065, "nominal_um": 5000, "part_id": "PT-2099"}
Plain-English key for the record’s own terms: “held-out” = examples it hid from itself · “adversarial” = attempts to trick itself · “underdetermined” = your examples fit more than one rule.
Show it seven in-spec readings from one machine, then a run where the last several drift the same direction.
It caught a drift no single reading would flag.
Every one of seven readings in a row was still within tolerance on its own. The eighth wasn't the trigger either — the run of 8 drifting the same direction was. Seven in a row wasn't enough; eight was exactly the line it drew.
See it under the hood
The raw record:
op=classify params={"rule": ["ge", 8, "flag_run", "no_flag"], "src": ["key", "consecutive_same_side"]}
Plain-English key for the record’s own terms: “held-out” = examples it hid from itself · “adversarial” = attempts to trick itself · “underdetermined” = your examples fit more than one rule.
Real result, recorded from a live run of the same toolkit you can download below — reproduce it on your machine.
Catch duplicate payments
A month of processor settlement payments, plus a chargeback policy nobody wrote down. Watch it learn the policy from examples, refuse to guess where it's genuinely unclear, then prove the whole month — right down to a single tampered character.
| Date | Vendor | Amount |
|---|---|---|
| May 1 | Summit Hardware | $2,899.10 |
| May 3 | NorthStar Retail | $4,520.00 |
| May 6 | Harbor Bakery | $355.20 |
| May 6 | NorthStar Retail | $4,520.00 |
| May 9 | Meridian Pet Supply | $940.25 |
| May 10 | BluePeak Coffee | $1,275.50 |
| May 12 | Granite Fitness | $1,540.00 |
| May 13 | BluePeak Coffee | $1,275.50 |
| and 18 more… | ||
ObserveYou show it 4 finished examples — the way you'd train a new hire.
ProposeIt came up with 19 possible rules — among them: days_to_chargeback ≥ 45.5 (the one it kept), days_to_chargeback ≥ 39, days_to_chargeback ≥ 75.
EliminateOnly 2 explanations held up.
WithholdIt hid 9 of the checks from itself until the end.
ChallengeThen it ran 8 trick attempts. One explanation survived everything.
A chargeback filed within 45 days needs a second look. 46 days or more, it's routine.
Learned from 4 worked examples — nobody programmed this cutoff in.
See it under the hood
The raw record:
op=classify params={"rule": ["ge", 45.5, "no_flag", "flag_review"], "src": ["key", "days_to_chargeback"]}
Its decision record, verbatim: “uniquely determined: 1 distinct behavior among 2 survivors of 19 proposals; fit on 4 worked examples only; passed 9 held-out, 8 adversarial and 0 negative-rule checks; injected-contradiction check refused as required.”
Plain-English key for the record’s own terms: “held-out” = examples it hid from itself · “adversarial” = attempts to trick itself · “underdetermined” = your examples fit more than one rule.
Every AI you've used guesses when it's unsure. Watch this one refuse.
days_to_chargeback ≥ 39
days_to_chargeback ≥ 75
RefuseIt refused to guess.
Needed evidence:
“What should happen for a chargeback filed after 47 days?”
It did not report low confidence. It constructed the exact example that separates the surviving rules.
See it under the hood
The raw record:
DECISION: REFUSE (underdetermined)
missing labeled input: {"days_to_chargeback": 47}
Plain-English key for the record’s own terms: “held-out” = examples it hid from itself · “adversarial” = attempts to trick itself · “underdetermined” = your examples fit more than one rule.
Found 2 duplicate payments worth $5,795.50 — the same vendor, same amount, just days apart.
NorthStar Retail: $4,520.00, paid twice, 3 days apart. BluePeak Coffee: $1,275.50, paid twice, 3 days apart. Both are highlighted above.
Matched 22 payments automatically. 10 lines need a second look.
Then we changed a single character in the finished workpaper.
It noticed instantly.
One byte flipped in a finished workpaper — a single digit changed in the matched-total line, “624.00” read “724.00” — and the fingerprint changed completely.
- Original
- 1d45dbc36cbc762824f65dc3d100bc6ad83a71dfeb185a7e3447bc681f59d7ed
- Tampered
- 30b73b95f047ed49fce635b97251790f50f626db74d8d1867b81bcc295da298e
See it under the hood
Commands run this session, against Apostol's own reconciler and sample files:
bash run_reconcile.sh samples/bank.csv samples/ledger.csv --html samples/workpaper_fresh.html sha256sum samples/workpaper_fresh.html # 1d45dbc36cbc762824f65dc3d100bc6ad83a71dfeb185a7e3447bc681f59d7ed cp samples/workpaper_fresh.html samples/workpaper_tampered.html # flipped one bit in one byte of the finished file: "624.00" now reads "724.00" sha256sum samples/workpaper_tampered.html # 30b73b95f047ed49fce635b97251790f50f626db74d8d1867b81bcc295da298e
Plain-English key for the record’s own terms: “held-out” = examples it hid from itself · “adversarial” = attempts to trick itself · “underdetermined” = your examples fit more than one rule.
Real result, recorded from a live run of the same toolkit you can download below — reproduce it on your machine.
Tie out the month-end close in one click
A 5-line lead sheet for the month-end close, plus an accrual policy nobody wrote down. Watch it learn the policy from examples, refuse to guess where it's genuinely unclear, then find the needle in the close — to the penny.
| Account | Reported | Ties? |
|---|---|---|
| Cash | $10,750.00 | —✓ ties |
| AR | $8,600.00 | —✗ off by $1,200.00 |
| AP | −$5,350.00 | —✓ ties |
| Accrued Liabilities | −$800.00 | —✓ ties |
| Fixed Assets (Net) | $15,900.00 | —✓ ties |
ObserveYou show it 4 finished examples — the way you'd train a new hire.
ProposeIt came up with 19 possible rules — among them: days_outstanding ≥ 28.5 (the one it kept), days_outstanding ≥ 37.5, days_outstanding ≥ 70.
EliminateOnly 2 explanations held up.
WithholdIt hid 9 of the checks from itself until the end.
ChallengeThen it ran 8 trick attempts. One explanation survived everything.
A balance outstanding 28 days or fewer gets flagged for accrual review. 29 days or more, it's routine.
Learned from 4 worked examples — nobody programmed this cutoff in.
See it under the hood
The raw record:
op=classify params={"rule": ["ge", 28.5, "no_flag", "flag"], "src": ["key", "days_outstanding"]}
Its decision record, verbatim: “uniquely determined: 1 distinct behavior among 2 survivors of 19 proposals; fit on 4 worked examples only; passed 9 held-out, 8 adversarial and 0 negative-rule checks; injected-contradiction check refused as required.”
Plain-English key for the record’s own terms: “held-out” = examples it hid from itself · “adversarial” = attempts to trick itself · “underdetermined” = your examples fit more than one rule.
Every AI you've used guesses when it's unsure. Watch this one refuse.
days_outstanding ≥ 37.5
days_outstanding ≥ 70
RefuseIt refused to guess.
Needed evidence:
“What should happen for a balance outstanding 45 days?”
It did not report low confidence. It constructed the exact example that separates the surviving rules.
See it under the hood
The raw record:
DECISION: REFUSE (underdetermined)
missing labeled input: {"days_outstanding": 45}
Plain-English key for the record’s own terms: “held-out” = examples it hid from itself · “adversarial” = attempts to trick itself · “underdetermined” = your examples fit more than one rule.
Found the needle: AR is off by exactly $1,200.00 — to the penny, provably.
Cash, AP, Accrued Liabilities, and Fixed Assets (Net) all check out clean — see the ticks above. 4 of 5 lines tie out exactly.
Found the needle: the rollforward is off by exactly $200.00 — to the penny, provably.
Beginning $15,000.00 + additions $1,500.00 − disposals $600.00 = $15,900.00 computed. The trial balance says $16,100.00.
Real result, recorded from a live run of the same toolkit you can download below — reproduce it on your machine.
Prepare your own lesson
Check that your examples contain enough structure, then export the lesson to the toolkit on your machine.
This page checks your examples are ready. The learning itself runs in Apostol — offline, on your machine.
One numeric field plus a label of “A” or “B” per example — whole numbers only.
Checks will appear here once you load or paste examples and press “Analyze lesson readiness.”
Then run it with:
bash ai_node/teach_skill.sh my_rule.json
What you just watched
Four things no filter, pivot table, or keyword search does.
It learns rules nobody programmed
Every rule on this page came from finished examples, not a config file — it formed its own explanations, tested them against examples it deliberately kept hidden from itself, tried to trick itself, and kept only the one that survived everything.
Receipt: between 19 and 103 possible explanations per lesson, narrowed to 2 finalists, exactly 1 kept — in medical, engineering, fintech, and accounting alike. experiments/industry_sample_packs/*/RESULTS.md
One honest caveat: a clean first-try result depends on how your examples are shaped. The recorded runs behind this page took two or three attempts in places before a clean adopt — and those attempts are on the books too, in the same RESULTS.md files.
It refuses instead of guessing
When two rules both fit the examples, it doesn't pick one and hope. It names the exact case that would settle the disagreement.
Receipt: score 6 (medical), 65µm (engineering), 47 days (fintech), 45 days (accounting) — the real deciding question it asked in every one of the four fields on this page. Same RESULTS.md files.
Every answer is provable
The workpaper it hands back is tamper-evident, and nothing about how it got there ever touched a network.
Receipt: sha256 1d45dbc3… → 30b73b95… after a single byte changed — run fresh during this build, and reproducible on your own machine from the download (not a pre-recorded file); zero network calls, verified at the operating-system level. experiments/cpa_reconcile_demo/VALUE_ASSESSMENT_FORMAL.md
It can expand its own verified skill library.
A skill is a small verified ability with its own tests. New abilities can be proposed by the system itself — but they enter the library only after surviving the same verification boundary. Generation 3 of the library is entirely machine-proposed.
Two growth targets failed their pre-set bars. They stay on the books — that is what makes the passing results worth believing.
Receipt: cumulative verified skills 8 → 40 → 45 across three generations, generation 3 machine-proposed only; two pre-registered scaling targets honestly failed and stay on the books. SCALING.md
See it on your own numbers
Apostol runs locally, offline — no install for the demo, no account, and nothing you enter here leaves your machine. To put it to work on your own data, get in touch.
Request access