Isnād–Rijāl framework for claim-level provenance in multi-agent knowledge systems
Project description
Isnād–Rijāl Framework
Grade the narrators, not just log them. Claim-level provenance for multi-agent knowledge systems.
60-second quickstart
from isnad import Registry, Chain, ChainLinkSpec, grade_chain, decide
from isnad.types import NarratorGrade, TransformType, ContentVerdict
from isnad.matn import DeterministicRuleCritic
# Build a transmission chain: source → scraper → model
chain = Chain([
ChainLinkSpec("openstax-v3", 0, domain="physics"),
ChainLinkSpec("pdf-scraper", 1, transform_type=TransformType.DESTRUCTIVE),
ChainLinkSpec("ingest-model", 2, transform_type=TransformType.GENERATIVE),
])
# Two narrators are ungraded → HASAN tier
reg = Registry()
reg.register("openstax-v3", "physics", grade=NarratorGrade.RELIABLE)
reg.register("pdf-scraper", "physics", grade=NarratorGrade.UNGRADED)
reg.register("ingest-model", "physics", grade=NarratorGrade.UNGRADED)
# Grade the chain
grades = [reg.get_grade(l.narrator_id, l.domain) for l in chain.links]
transforms = [l.transform_type for l in chain.links]
cg = grade_chain(grades, transforms, is_complete=True)
# Content criticism (fully decoupled from chain grading)
cv = DeterministicRuleCritic().evaluate("p = h/λ", "p = h/lambda", ["p = mv"])
# Decision matrix: HASAN × CONTRADICTION → REVIEW
action = decide(cg, cv)
print(f"Chain: {cg.value.upper()} | Content: {cv.value} | Action: {action.value}")
# Output: Chain: HASAN | Content: CONTRADICTION | Action: review
📄 Paper: "Grading the Narrators" — Ali Zahid Raja (2026)
📋 Companion gist: Schema & design notes
Install
git clone https://github.com/alizahidraja/isnad.git && cd isnad
make install # uv sync
make test # 90 tests, zero config, SQLite fallback
make demo # Paper's worked example (§4.5)
make check # lint + type-check + test
No database required for pure-logic tests. PostgreSQL is optional (docker compose up, set ISNAD_DATABASE_URL).
What problem does this solve?
In modern AI pipelines, a factual claim passes through many hands — a scraper extracts it, a model compiles it, another serves it — and each hand can drop, distort, or invent. Existing provenance tools record what happened. They don't grade who transformed the claim, so they can't tell you how much to trust the result.
This framework adapts classical Islamic hadith transmission science — one of history's most rigorous pre-modern epistemologies — into a Python library for AI systems. The core insight: the trustworthiness of a claim is a function of the graded reliability of every individual who transmitted it. Claims carry complete chains (isnād); transmitters are graded in a living registry (rijāl); chains are graded by their weakest link; independent corroboration can upgrade; and content is criticized independently of transmission quality.
Concept → module mapping
| Concept | What it does | Module |
|---|---|---|
| isnād (chain) | Ordered, gap-checked transmission chain per claim | isnad/chain.py |
| rijāl (registry) | Graded narrator store per (narrator, domain) | isnad/registry.py |
| jarḥ–taʿdīl | Evidence-driven state machine for narrator grades | isnad/registry.py |
| ittiṣāl/munqaṭiʿ | Completeness as epistemic property (gap → DAIF) | isnad/chain.py |
| Weakest-link grading | Chain grade = refined minimum over narrators | isnad/grading.py |
| mutābaʿāt | Independent-chain corroboration with correlation detection | isnad/corroboration.py |
| matn criticism | Content evaluated independently of chain quality | isnad/matn.py |
| Decision matrix | 4×2 (chain × content) → action router | isnad/matrix.py |
| ʿadālah / ḍabṭ | Integrity and precision as two distinct axes | isnad/types.py |
Pluggable strategies
The paper deliberately leaves certain transition arithmetic open (§4.2/§4.3). These are exposed as swappable interfaces:
| Strategy | Protocol | Default | What it decides |
|---|---|---|---|
GradingStrategy |
isnad/types.py |
RefinedWeakestLink |
How link grades combine into a chain grade |
TransitionPolicy |
isnad/types.py |
ThresholdTransitionPolicy |
How evidence moves narrators between ordinal states |
CorroborationPolicy |
isnad/types.py |
CappedCorroborationPolicy |
How independent chains upgrade a claim |
CorrelationDetector |
isnad/types.py |
SharedLineageDetector |
Whether two chains are truly independent |
ContentCritic |
isnad/types.py |
DeterministicRuleCritic |
Content contradiction detection |
Swap one in one line:
from isnad import grade_chain, RefinedWeakestLink
class MyStrategy:
def compute_chain_grade(self, grades, transforms, is_complete, *, corroboration_support=False):
# Your logic here
...
result = grade_chain(grades, transforms, is_complete=True, strategy=MyStrategy())
Status — what this does and does not validate
This implements: the framework's architecture, grading logic, and all pluggable strategy interfaces. It passes 90+ tests enforcing every epistemic commitment from the paper, including the paper's worked example (§4.5) as an end-to-end integration test.
This does NOT constitute: the end-to-end empirical validation (gated-vs-ungated served-error study) that the paper scopes as future work (§8). The registry bootstrapping, transition-policy thresholds, and corroboration arithmetic are reference defaults — not empirically calibrated values. Deployers should run the §8 experiment against their own pipelines.
Reference stubs are docstring-labeled:
DeterministicRuleCritic— hardcoded pattern matching; production needs semantic/LLM critic.LLMCritic— reference Anthropic integration; needs batching, caching, ensemble for production.SharedLineageDetector— exact-match heuristics; production needs structured model lineage data.- Seed-grade bootstrapping — designed but not yet implemented (see §7 of paper).
Contributing
See CONTRIBUTING.md. Especially welcome:
- New
CorrelationDetectorusing embedding similarity or model-card lineage data. - Seed-grade bootstrapper that initializes narrator grades from published benchmark accuracies.
- Domain-specific
ContentCriticwith formula canonicalization (physics, medicine, law). - Calibrated
TransitionPolicyfrom your own pipeline's §8 experiment data. - Pipeline adapters for LangChain, CrewAI, or Autogen tracing.
Citation
If you use this software, cite the paper:
@software{raja2026isnad,
author = {Ali Zahid Raja},
title = {Isnād–Rijāl Framework: Claim-Level Provenance in Multi-Agent Knowledge Systems},
year = 2026,
doi = {10.5281/zenodo.21211291},
url = {https://doi.org/10.5281/zenodo.21211291},
orcid = {0009-0003-7875-4590},
}
A dedicated software DOI will be added after the first Zenodo release.
GitHub's "Cite this repository" button is powered byCITATION.cff.
License
Code: Apache 2.0 · Paper & docs: CC BY 4.0
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file isnad-1.0.0.tar.gz.
File metadata
- Download URL: isnad-1.0.0.tar.gz
- Upload date:
- Size: 25.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.25 {"installer":{"name":"uv","version":"0.11.25","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1b5cf180036df0cd2c89b284af23542dca4b23472c93c900188a4347d890fb29
|
|
| MD5 |
d22b5a90b1e1d62055779836cf588e94
|
|
| BLAKE2b-256 |
9afbe644b104df2720069cfce8cc9db1e51365a7571c0db475a2f8cce03b439b
|
File details
Details for the file isnad-1.0.0-py3-none-any.whl.
File metadata
- Download URL: isnad-1.0.0-py3-none-any.whl
- Upload date:
- Size: 30.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.25 {"installer":{"name":"uv","version":"0.11.25","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ae52fb7fbf5c9a356436309701bba745b8a3196c987108c16e920a6742947c3e
|
|
| MD5 |
ab7adc34a3427b97889aab5b43a0f6e3
|
|
| BLAKE2b-256 |
3461159b65dc5e5ee8f3a0a359dd863b4a5bff4d9c1ad46d22dffc8aa3a7c716
|