← all exhibits
Exhibit§ 01 · jn-bot Status● curator-managed · homelab-hosted Roledesign · build · operate Since2026 · single-account MVP

jn-bot

An audit agent that reads one account end-to-end, cites its evidence note by note, and throws out its own findings when it can't ground them.

TL;DR · 10-second read

It reads one customer's account in a roofing company's CRM and surfaces the few things a manager should actually act on — overdue money, a stalled job, the wrong person on a file — each tied to the exact note it's citing. It can only read the CRM; it never changes anything.

Read-only auditEvidence-grounding validatorAdaptive model routingCross-model agreement
§ 02 / DEMO

Run it live

embedded · interactive
jnbot.kenlly.dev/portal · anonymized demo LIVE
§ 03 / ARCHITECTURE

How it works

tap a node · drag + zoom
agreement signal read-only · get JN API deterministic Packet llm · routed Audit grounding Validator anonymized Render cross-model Cross-Check
§ 04 / REASONING

The ideas behind it

tradeoffs, stated
decision 01Why the bot is read-only by hard rule, not by config

The agent reads one account's data through a GET-only wrapper and never touches a write endpoint — no status changes, no notes, no task creation, nothing pushed back to the CRM. It identifies risk and the evidence behind it; a person decides and acts inside the CRM through normal channels. That boundary is enforced in the wrapper, not left to a prompt or a setting someone could flip under deadline.

tradeoff The bot can't "just fix it" — every action still needs a human. That's the point: an autonomous tool that mutates a system of record is a liability the first time it's confidently wrong. Surface-and-route is the safe half of the loop to automate.
decision 02Why a separate validator that drops the bot's own findings

Every concern the audit agent emits has to cite a real note id from that account's bundle — or the deterministic Tier-A header, flagged as such. A separate pass checks each citation against the actual input set; a concern that cites an id the model invented is dropped, and any recommended action that leaned on a dropped concern is cascade-dropped with it. The model that writes the finding is the worst judge of whether it's grounded, so grounding isn't its job.

tradeoff Occasionally a real risk gets dropped because the model cited it sloppily. I take that trade every time: a confident, well-written, ungrounded finding is the failure mode that erodes a manager's trust fastest, and conservative under-calling is recoverable where over-claiming isn't.
decision 03Why route models per account instead of using the strong one everywhere

A cheap, fast model handles the ~70% of accounts that are routine; a stronger model is routed in only where the file earns it. The router is real infrastructure — the open work is the routing strategy: knowing which accounts need the careful reasoning and which don't. That's account-domain judgment, not a bigger GPU.

tradeoff At a few hundred accounts a day the strong-model-everywhere bill is roughly $9K/yr versus ~$2K/yr routed. The delta buys nothing on the easy accounts; spending it only where it changes the answer is the whole game.
decision 04How I trust an autonomous auditor without reading every output

A second, independent model audits the same account in parallel. Cross-model agreement is the quality signal: where two models land on the same risk, confidence is high and it goes on the desk; where they diverge, that account jumps to the top of the curator's review queue. The point isn't a perfect bot — it's knowing which of its outputs to check first.

tradeoff You pay for a second model on every audited account. Cheap insurance against the single-model blind spot, and it turns "review everything" into "review the disagreements" — which is the difference between this being operable solo and not.

The honest version of this tool isn’t “the bot caught everything.” It’s that the bot reads every note on every stalled file every day — which no manager has time to do — and puts the few that matter on the desk with the evidence attached. Where it gets severity wrong (it will over-escalate a routine handoff on a closed-and-paid file, for instance), that’s the curator’s job to catch: right observation, wrong framing. The system is designed so that’s a correction, not a silent error — the cited evidence is right there to check.

The demo above is the owner portal with every customer and team name anonymized at build time. The renderer is fail-closed: if a known real name survives the scrub, it aborts rather than publish. That’s the same discipline this whole site runs on.

§ 05 / PROOF

Proof it's real

recorded run + artifact
run-trace · acct-1 · jn-bot
ken@audit ~/jn-bot $ ./demo acct-1 [00.0s] packet GET-only · Tier A header + 38 id-grounded notes [02.4s] route fast model (Haiku 4.5) · routine account [02.6s] audit calling live LLM (~50s, ~$0.04)… [48.7s] audit 5 questions walked · 4 concerns · 3 actions · 1 follow-up [48.9s] validator orphaned_task tier_a_header ✓ grounded [48.9s] validator verbal_oop_undoc cites note id ✓ grounded [49.0s] validator lien_window note id not in bundle ✗ dropped [49.0s] validator cascade-drop 1 action → referenced dropped concern [49.5s] x-check parallel cross-model · agrees 3/3 surviving ✓ [50.1s] render anonymized · leak-scan PASS · portal-demo.html ✓ 50.1s · 3 grounded concerns · 0 leaks · read-only (no CRM writes)
recorded · 50.1s · read-only
generated artifact ● validator passed

Manager Summary — accounts ranked by risk

dollar exposure per line · every concern evidence-cited
5
audit questions
GET-only
CRM access
0
name leaks
§ 06 / STACK

Stack & patterns

what it's built from

Audit pipeline

Deterministic packet builderTier-A header + id-grounded notes5-question auditEvidence-grounding validatorCascade-drop orphan actions

Models & routing

Claude Haiku 4.5Adaptive model routerParallel cross-model check

Safety

Read-only API (GET-only)Fail-closed anonymizerID-grounded citationsConservative under-calling

Runtime

Python · uvHomelab (LXC)Self-contained HTML portalCloudflare Access gate