How this is built

An automated pipeline of one-shot LLM agents reads a Talmudic sugya and distills it into a property graph of atomic knowledge units and typed edges — a knowledge model in which a claim about a claim is a first-class citizen — under mechanical checks and a human review gate. The graph — not the model — is the system's memory. This engine is stage one of a RAG system of a different kind: retrieval grounded in an approved, addressed knowledge graph rather than similarity search over raw text — an answer layer over a self-refining, status-graded store, where every answer carries addresses in the sources.

Status: the first sugya has passed the pipeline end to end, and the candidate graph behind this site is now under human review.

The problem

Why this corpus breaks conventional RAG

The decisive knowledge in a Talmudic sugya is relational structure that is written in no sentence of it: who transmits in whose name, which challenge lands on which resolution, what an okimta narrows a dispute down to, what is rejected and what stands. A single Mishnaic ruling carries a whole unwritten storey of claims about claims.

Similarity retrieval returns what is written — and here the question is decided by what is not. Two passages nearly identical in wording can be entirely different in status, so embedding distance is the wrong instrument. And the failure region of model memory is exactly this unwritten part: tested on this sugya, a model returned transmitters swapped with each other and a quotation that was never written — both fluent, both confident.

Architecture

What runs where, and why

System overview Graph-grounded RAG — answer layer planned — retrieval over the approved graph Status-graded store planned — refines itself with use Sugya text frozen per run Agent pipeline one-shot calls, mechanical checks staging candidate graph Review gate human, calibration main approved only Run journal + replay Graph viewer (this site)
Solid boxes are built and running; dashed boxes are designed, not yet built. The published snapshot on this site is exported from staging.

Storage — a property graph, physically split

Neo4j 5 Community, as two separate containers on one host: main on its own port for approved knowledge only, and staging for the candidate graph plus review-state properties that are stripped when it merges. Why a graph: the knowledge is a graph — claims hanging on claims — and similarity search cannot represent precise, directed, composable relations. Why two containers rather than a policy flag: the split is a structural guarantee — no query can mix approved with pending knowledge, because no connection reaches both. Stated flat: main currently holds nothing. The snapshot on this site is the first end-to-end candidate, exported from staging, now under human review — the store's first approved entry will come from it.

Processing — one-shot agents under an enforced schema

A Python pipeline (Python 3.14, dependencies locked with uv) runs every step as a single closed model call through the Claude Agent SDK, with no tools and no conversation. The model used for the run behind this site is recorded in the run's frozen config, alongside the frozen text and edge dictionary. Output is enforced twice: the API is given a flattened JSON schema, and the full schema — complete branches, no extra properties anywhere — is re-validated in process with jsonschema; a reply that fails is discarded with its agent, and a fresh agent retries the step. Why one-shot: an agent with no private memory accumulates no shadow store — everything it knows lives in the graph, where it has an address and a review. The set of legal edge types is not a code list; it is built at runtime from the edge dictionary, so the contract and the data cannot drift apart.

Serving — a static export with no backdoor

One VPS. Caddy is the only public entry point; every data service is bound to localhost, and the public site is static files with no process behind them at all — the block that serves it has no reverse proxy. A publish pipeline exports the site with per-file sha256 checksums, and the export is an allowlist, not a filter: only named properties are copied, so anything a future round adds has no path out by default. Minification strips internal commentary, and a scanner fails the publish if any survives. Why: hard separation between the live system and the public face.

Front end — vendored, no egress

vis-network renders the graph canvas; Heebo and Frank Ruhl Libre are the two typefaces. Everything is vendored — the site makes no external request at runtime, sets no cookies, and runs no analytics.

The run pipeline

From text to candidate graph

The run pipeline Entity registry Skeleton Routing Ingest steps Checks Debts ledger Summaries 👁 Review one focused correction round
A violation triggers one focused correction round; an agent that fails is discarded and a fresh one retries the same step.
  1. Entity-registry pre-pass

    A model proposes the sugya's canonical entities — sages, sources, concepts, measures — and a person approves the registry before intake begins. Approved entities carry a normalized merge key, and the normalization is written in code rather than asked of the model.

  2. Skeleton

    One agent reads the whole sugya and lays down the concept skeleton — the backbone of concepts the units will hang on — and a map of its sub-sugyot. Every boundary is anchored to a quote the machinery can locate mechanically.

  3. Routing

    A classification layer assigns each piece of text its move types from a catalog of sixteen move schemas — typed patterns of Talmudic argumentation: challenge, resolution, derivation, transmission, dispute and the rest. It is deterministic first — a table of opening formulas decides most pieces — and asks a model only when the table cannot decide. Each worker agent then gets a minimal-sufficient mandate: the relevant schemas, the piece, its graph neighbourhood, and a compact briefing. A piece that fits no schema gets an explicit fallback classification, never a silent generic bucket.

  4. Ingest steps

    Each step is a single closed model call, carrying a letter — the complete written mandate the agent works from. The agent returns one write decision as JSON under the enforced schema. The text is consumed by a front-anchored cursor: the piece the agent declares must match the front of the not-yet-marked text, so coverage is a mechanical guarantee rather than a matter of agent diligence.

  5. Mechanical checks on every write

    Transitive-shortcut ban, direction invariants from the edge dictionary, cycle detection, reference integrity, quote matching under deterministic normalization, transaction scope. A violation triggers one focused correction round whose scope is enforced mechanically — the correction may change only what the violation names.

  6. The debts ledger

    Work an agent intends but cannot do in the current step is recorded as a structured debt — target, requirement, redemption trigger — kept in run state and shown in every later letter. It has to be redeemed or explicitly waived at the sub-sugya summary. A promise is not knowledge, so it does not live in the graph — but it is not allowed to evaporate either.

  7. Summaries and a final audit

    Node-led consolidation per sub-sugya, then whole-graph checks: coverage crosschecked against the text, skeleton remnants, unanchored units, dispute mediators left without sides.

  8. Delta, staging, gate, main

    The run exports a delta — the candidate graph as one reviewable unit — the delta is loaded into staging, a person reviews it on the graph with each source quote shown against its converted unit, and only an approved review merges it into the store.

Where the figures come from

Everything below is rendered from the published snapshot. Node and edge counts come from the export itself, and test counts are collected from the repository's suites at publish time. Nothing on this site is a typed-in number.

How quality is made

An evolutionary loop, with evidence instead of reports

Every generation runs under review

The system improves by generations. Every graph generation runs under the full automated suites and a human review of its products; review findings do not patch the output — they change the architecture, and the next generation runs under the improved contract. A failure family found once becomes a mechanical check that makes it impossible twice.

A report is not evidence

A claim that a test passed is not accepted; the command output is shown. The same rule holds inside the system: agent self-report is never used as verification — a model asked "did you understand?" confirms that it did even when the input was nonsense, and that is a measured finding here, not a worry. Every check is a test against the product.

Two implementations, one truth

Where a claim matters, two independent implementations must agree on it. The graph-apply logic exists twice — in Python, and as a deliberate JavaScript re-implementation used by the run viewer — and a seam test holds them byte-identical over every recorded run. That test has already caught a real divergence: the first run to exercise a newly-added field showed every affected unit differing between the two ports. One implementation reporting on itself would never have seen it.

Replay and audit — two implementations that must agree

Every run writes a journal as a write-ahead log: each event is flushed to disk before the action it describes touches state, and a torn final line is discarded on read. Any step — and the run's final delta — can be reconstructed from the journal with no model call. The run viewer runs a separate JavaScript implementation of the same graph-apply logic, and a browser-based seam test requires exact equality with the Python output over every recorded run. Why: two independent implementations that agree are evidence; one implementation reporting on itself is not.

Evidence discipline

Every run directory keeps a frozen copy of its inputs, full transcripts of every agent call and reply including the attempts that failed, the journal as the source of truth, and per-call cost telemetry.

The site checks itself

This page lives under the same discipline. A battery of automated checks runs against the built site and again against the live one: every source anchor on the home page must match a quote in the published graph, layout shift and contrast are measured on every page, and every guided-tour step must frame its subject on the canvas. Publishing is gated on the battery being green.

Design principles

What this is built on, and what was rejected

When in doubt, split fine

Principle
A unit is atomic when no part of its content could be pointed at by another edge — a test against the graph, not against the agent's feeling about its own phrasing. Where the boundary falls is set by the questions the corpus actually gets asked: who disputes what, what a law rests on, which challenges hang on this text.
Why
Three independent grounds. Empirically, an agent held "one sentence, one claim" to its own satisfaction while review found mixed nodes, duplicated content and missing nodes — a rule measured from the inside is not a mechanism. Structurally, this is first normal form in graph language, and a graph gives it neither for free nor enforced. And the risk is asymmetric: with no general join, an unsplit relation is not slow, it is silent — the graph looks healthy. A companion rule follows: identical content appearing in two units is not a phrasing flaw but a missing-node detector — had the node existed, both would point at it.
Rejected
"One sentence stating one thing" as the operative test, because it measures from inside. Splitting by potential hangability, because it has no stopping point. Splitting only when an edge in the current material demands it, because it is blind to omission. The real cost of splitting fine is review load at the gate, accepted knowingly.

One-shot agents: the graph is the only memory

Principle
Every pipeline agent is a single closed model call. All of its knowledge arrives in its letter; all of its output is recorded in the graph and the journal. No persistent agents, no agent memory, no hidden state between steps.
Why
Two reasons that are really one. Knowledge accumulated in an agent's private memory is a shadow store: it influences decisions with no address, no gate and no review — precisely what this project exists to prevent. And reproducibility: a closed call is a pure function, so when a step goes wrong, the letter and the reply are the complete evidence. Discard-and-retry works operationally because memory is zero — the agent that did not fail is not committed to the failure.
Rejected
A standing expert team with persistent memory. Specialization as agent identity — if step types need specialization, its form is different templates for the same one-shot agents. And solving letter-size limits with agent memory: that problem belongs to the feeding layer — at scale, what changes is how the agent is fed, never the principle.

A promise is not knowledge — and it may not evaporate

Principle
Work an agent intends but cannot do now must live somewhere mechanical. A pattern whose second storey is already known at ingest is written in both storeys in a single step; anything else becomes a structured debt — filed in the agent's reply, kept in run state, shown in every later letter, and closed at the sub-sugya summary by redemption or a recorded waiver. Silent deferral is not a legal move.
Why
A measured architecture failure: an intention written into a free-text rationale field does not travel to the next agent. Making the graph the only memory left a promise with no home — so it evaporated. The measured cost in one full run was zero transmission edges and a dead classification axis: the second storey of the text, the very thing the system exists to capture, lost silently.
Rejected
Relaying free prose between agents, which reintroduces through the back door the framing-alignment that one-shot agents exist to prevent. Monitoring agents that scan transcripts, which buys dearly what a state file carries for free. And recording debts as graph nodes, which pollutes the knowledge store with process entities.

Honest limits

What you cannot check from here — and the route onward

There is an honest gap in all of this, and it is worth naming rather than papering over. The system itself is private by design — the corpus, both databases, and the pipeline that fills them are not exposed, and no run artifact is published. So the numbers above cannot be independently reproduced by a reader of this page.

What is offered instead is narrower and checkable. The site is fed by a dated snapshot, and meta.json publishes a sha256 for every file in it, so what arrived is verifiably what was written — an integrity check, not a signature, and not a claim that anyone has vouched for the contents. The snapshot comes from a system in calibration: it is the first end-to-end candidate, and it has not yet passed its human review.

During calibration a human gate reviews every product in full. The exit from the gate is a bar written in advance — consecutive clean runs on unseen sugyot, zero surviving violations, zero retrieval failures, a converged cross-sugya identity layer — never a felt sense of readiness.

The route onward is deliberate: more sugyot through the same pipeline first; then the commentators' storey, built on the approved base; then the world of psak, ruling across both. Each storey inherits the precision of the one beneath it.

Author