Skip to main content

PersistAIBench

An evaluation benchmark for AI agents' memory truthfulness over long multi-step tasks.

PersistAIBench (harness/repo name: PersistBench) measures one unmeasured chain: a tool fails silently in Session 1 → the agent writes its own account of the outcome into long-term memory → different tasks in Sessions 2–4 act on that memory → whether a write-time guard stops the propagation. There is no attacker and no prompt injection; the failure mode is benign self-poisoning.

Paper: Karmendra Pandey, "Fail-Plausible, Then Persistent" (working title). Outline approved 2026-10-23; filed in Google Drive EB1 §03 (persistbench-outline.pdf, persistbench-outline-record-2026-10-23.md).

Quickstart

git clone https://github.com/karmendra8386/persistbench-bench.git
cd persistbench-bench
python3 -m venv .venv
.venv/bin/pip install .
.venv/bin/persistaibench run --chain chain01 --policy M1 --fault silent_wrong_value --backend fake

The last command runs one pilot cell (chain × fault × policy) end-to-end and prints the scored cell as JSON. --backend fake is a deterministic scripted backend — a plumbing smoke test, not a result: the model id in the output is stamped fake/... so it can never be mistaken for a real model run. --chain accepts a full chain id or a unique prefix (chain01); --policy is one of M0–M5; --fault one of the five fault conditions.

To run a cell with a real model (requires a GPU and torch + transformers, which the Kaggle notebook installs):

.venv/bin/persistaibench run --chain chain01 --policy M1 --fault silent_wrong_value --backend hf --model Qwen/Qwen2.5-7B-Instruct

To run the full pilot grid (2 models × 6 chains × 5 faults × M0–M5), use persistaibench pilot --config configs/pilot.json --out results/pilot --backend hf — or --backend fake for a plumbing-only pass. The Week 2 pilot results are in docs/results.md; the design rule they support is written up in docs/verified-memory-writes.md.

Provenance — read this first

Weeks 1–2 = harness, design, policy machinery, and the Week 2 formation pilot. The pilot ran on 2026-11-02 (Kaggle, GPU T4 x2) and its results — including a failed model arm, reported as such — are in docs/results.md with raw outputs in results/pilot/. Everything before the pilot (scripted-agent evidence below) is machinery validation, not model findings. What exists:

  • docs/design-freeze.md — the frozen design: RQ1–RQ5 / H1–H5, environment, fault conditions, memory policies M0–M5, six metrics, paired statistics plan.
  • docs/preregistration-draft.md — hypotheses, conditions, primary metrics, analysis plan, and the four pre-registered falsification checks.
  • docs/results.md — the Week 2 pilot: formation rates by policy × model and by fault, the classifier-gate result, and the Qwen3-8B write-generation anomaly.
  • docs/verified-memory-writes.md — the transferable design rule the pilot supports: verify memory writes against current state, not against the observation that produced them.
  • A working deterministic harness with scripted agents, validated by the test suite below.
  • Week 2 (code half, complete): memory policies M0–M5 all implemented under the frozen interface — M2 (self-summary + disclosure/provenance annotation), M3 (structured evidence-contract write), M4 (state-verified write with correction/rejection accounting) join Week 1's M0/M1/M5. Every policy records a per-write log (entries + cost placeholders) sufficient to compute the frozen metrics, and runner.run_chain executes a full chain under any policy × any fault.
  • Week 2 pilot execution package: persistbench/llm_agent.py (LLM origin agent behind a backend interface — deterministic fake backend for tests, HF transformers backend for real models; conservative JSON action parsing and claim extraction), real per-policy memory-write generation (M1 free-form summary, M2 under the disclosure instruction, M3 claims parsed into the evidence-contract format — unparseable claims are logged as unknown, never verified; M4 = model write through the state-verified policy), persistbench/pilot.py + configs/pilot.json + scripts/run_pilot.py (2 models × 6 chains × 5 faults × M0–M5, per-cell md/csv/jsonl outputs, and the 50-write hand-labelling sample export for the ≥90%-agreement classifier gate), the persistaibench CLI (persistbench/cli.py), and kaggle/week2-pilot.ipynb + kaggle/RUNBOOK.md. Plumbing was additionally smoke-tested with a real tiny model from the local cache (Qwen2.5-0.5B-Instruct, CPU): see results/smoke-llm-2026-10-23.md — labelled SMOKE, not a result.

Two implementation notes that matter for reading the machinery (both follow the design freeze; flagged here so they are not mistaken for findings):

  • M3's evidence is tool observations, never DB state (checking state is M4's definition). Under explicit-error and empty/partial faults the contract therefore stores no false claim as fact. Under silent-wrong-value and stale faults, the corrupted response is the supporting observation, so M3 marks the false claim verified — the contract's boundary, asserted in the tests, and exactly why H3 orders M3 below M4.
  • M4 corrects rather than merely rejects where the DB holds a value (rejection is reserved for facts the DB does not hold and for unverifiable keys). Its write log accounts for every falsified field as corrected-or-rejected, and on no-fault writes it corrects/rejects nothing — pre-registration falsification check 3 (a guard that destroys legitimate utility is not viable) is tested directly.

The full live-model runs (Qwen2.5-7B, Qwen3-8B, Llama-3.1-8B, Mistral-7B; ~3,600 sessions) are Weeks 3–4 of the plan. Numbers from the Week 2 pilot are in docs/results.md; any other number quoted from this repo is a property of the scripted harness, not of any model.

Layout

persistbench/
  world.py     deterministic retail world; DB ground truth; agent tools
  chains.py    the 12 task chains (Session 1 + 3 dependents + correction fact)
  faults.py    seeded fault injection: no_fault / explicit_error /
               empty_partial / silent_wrong_value / stale_value
  agents.py    scripted oracle + naive origin agents; dependent agent
  memory.py    memory policies M0–M5 (all implemented, Week 2) + write logs
  scorer.py    programmatic grading vs DB end-state — no LLM judge
  runner.py    origin / dependent trajectory runners
  llm_agent.py LLM origin agent + per-policy write generation (Week 2
               pilot prep; fake + HF transformers backends)
  pilot.py     pilot config validation, grid runner, formation tables,
               hand-labelling sample export + agreement gate
  cli.py       the `persistaibench` command (run one cell / run the pilot)
configs/       pilot.json — the frozen pilot configuration
scripts/       run_pilot.py — pilot entry point (the CLI wraps the same code)
kaggle/        week2-pilot.ipynb + RUNBOOK.md (launch procedure)
results/       smoke evidence (labelled); pilot/ — Week 2 pilot outputs
tests/         pytest suite, incl. the Week 1 exit criterion
docs/          design freeze + pre-registration draft; results.md —
               Week 2 pilot results; verified-memory-writes.md — the
               design rule

Week 1 exit criterion — evidence

The harness grades hand-written/scripted trajectories correctly in all 5 fault conditions.

Verified by tests/test_exit_criterion.py (plus test_world.py, test_dependents.py):

  • Oracle agent under no-fault: task success + truthful claim on 12/12 chains.
  • Naive (unverifying) agent: scorer detects a falsified claim under each of the 4 injected faults × 12 chains (48/48), and names the falsified fields.
  • Oracle agent: claim never falsified under any fault (60/60 chain × fault cases).
  • The dissociation the paper rests on is mechanically demonstrated: silent/stale faults leave the DB correct but the naive claim false (24/24); explicit/empty faults fail both the task and the claim (24/24).
  • Propagation machinery: an M1 write of the naive claim is classified false on the corrupted fact (12/12); the dependent task that needs that fact then fails under M1 memory and succeeds under M5 (oracle) and M0 (query the world); the pre-Session-4 correction event repairs a revising agent and not a stubborn one (12/12).
  • Hand-written false trajectory (claims success for work never executed) is detected, including the task_success falsification.

Run it:

python3 -m venv .venv && .venv/bin/pip install pytest
.venv/bin/python -m pytest -q   # 1164 passed, 10 skipped (skips: Session-2 task
                                # does not depend on that chain's corrupted fact)

Standard library only at run time; pytest is the sole dev dependency.

Week 2 policy evidence (machinery, not results)

Verified by tests/test_week2_policies.py (811 cases) over all 12 chains × 5 fault conditions, with scripted agents:

  • M4: the stored write is never falsified, under any fault, for either scripted agent; its content matches the M5 oracle store; its log's corrected+rejected entries are exactly the scorer's falsified fields; on no-fault writes it accepts everything and its store equals M1's.
  • M3: under explicit-error / empty-partial faults the whole write classifies clean (success claims stored failed / unknown, never verified); under no fault every claim is verified and downstream behaviour matches M1. Under silent/stale faults the false claim is stored verified on the corrupted observation's evidence — the documented boundary above.
  • M2: the claim is stored verbatim with provenance on every entry (verified_against_state: False throughout); observed tool errors appear in the disclosures, and a success claim past an observed error is annotated contradicted_by_observation. Downstream behaviour matches M1 exactly — the annotation, not filtering, is M2's guard.
  • Correction: where a guard kept the false memory out (M3/M4 under evidence-visible faults; M4 under all faults), even a stubborn agent's Session 4 is correct. Where the lie reached the store (M2/M3 under silent/stale), the Week-1 pattern holds: stubborn resists, revising is repaired.

Next (per the approved plan)

  • Week 2 pilot — DONE (2026-11-02): 2 models × 6 chains × 5 faults × M0–M5, Session-1 formation rates measured; classifier gate passed (50/50 = 100% hand-label agreement). Results: docs/results.md. One arm (Qwen3-8B) produced almost no parseable writes — fixing its write generation (token cap / <think> handling) and re-piloting that arm, or replacing it, is a precondition for Week 3; scale-up is not cleared as a 2-model run until then.
  • Weeks 3–4: full runs; correction analysis; first results memo.
  • Month 2: LongMemEval + Mem0 transfer arms; write-up. Zenodo preprint week 8–10 after author review; NeurIPS 2027 Datasets & Benchmarks is the primary venue target.

Cite

If you use PersistAIBench in your work, please cite the software record on Zenodo:

@software{pandey_persistaibench_2026,
  author = {Pandey, Karmendra},
  title = {PersistAIBench: an evaluation benchmark for AI agents' memory truthfulness over long multi-step tasks},
  version = {0.1.0},
  doi = {10.5281/zenodo.23893975},
  url = {https://github.com/karmendra8386/persistbench-bench},
  date = {2026-11-02}
}

A CITATION.cff is included for automated citation tooling.

DOI: the v0.1.0 software release is archived on Zenodo as 10.5281/zenodo.23893975 (concept DOI: 10.5281/zenodo.23893974, which always resolves to the latest version). The accompanying paper ("Fail-Plausible, Then Persistent", working title) is unpublished.

Metadata

Release files for persistaibench 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for persistaibench 0.1.0
File Size Uploaded Provenance Actions
persistaibench-0.1.0.tar.gz 67.4 kB With provenance Details for persistaibench-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for persistaibench 0.1.0
File Interpreter ABI Platform Actions
persistaibench-0.1.0-py3-none-any.whl Python 3 none any Details for persistaibench-0.1.0-py3-none-any.whl

Total release size: 121.1 kB

Release files / persistaibench-0.1.0.tar.gz

Download URL persistaibench-0.1.0.tar.gz
Size 67.4 kB
Tags Source
SHA-256 checksum
How to use checksums
be24fd9467ea83d1b2aad6669846425e4609bf2ae9c480e8e2be781674915f99
BLAKE2b-256 checksum
How to use checksums
5e6a64460ed4d08b1c984ea37e75cda674c2035876a429aa668a7ffdcd64810b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 6, 2026.

Transparency log

Release files / persistaibench-0.1.0-py3-none-any.whl

Download URL persistaibench-0.1.0-py3-none-any.whl
Size 53.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
041e1ebf351e5e333584f6adc044cc242109eb0141a2d6fdb42f1d8744f20884
BLAKE2b-256 checksum
How to use checksums
5e65c91df6516b08cdd22d7e0dde94353f15b7194182936c6b3c5daf93c2d011
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 6, 2026.

Transparency log

Security for persistaibench 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for persistaibench-0.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 6, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page