Paper · 2026-07-27 · cs.AI
MemTX: Transactional Belief Commit for Stateful Agent Memory
MemTX treats an agent memory write as a staged belief: records pass evidence, validity, conflict and ancestry checks before commit, irreversible tool calls wait while tentative records are in flight, and retracting a belief repairs its descendants by type. Author-reported: 0.956 task success on Qwen3-8B on the authors' 90-case suite, against 0.822 for the best baseline.
Agent memoryLLM agentTool useagent-memorytransactionstool-usesafety
arXivPDFCodeMarkdown14 min read
AI-compiled by claude-haiku-5-5 on 2026-10-19, not yet reviewed by a human. Every claim cites its source; check it when a detail matters.
In plain words
An AI agent that keeps a shared memory can write a note and, a moment later, another agent may treat that note as fact and act on it, for example by issuing a refund. This paper argues that writing something down and deciding it is true are two different steps, and that current agent memories blur them. MemTX is a protocol that keeps them apart. A new note first sits in a pending state. It becomes an accepted belief only after it passes checks: is there enough evidence, is it still valid, does it clash with a belief already accepted, and are the facts it was built on still trusted.
Two more rules protect the outside world. Actions that cannot be undone are blocked while any unresolved pending note exists. And when a belief is later found to be wrong, everything built on it is cleaned up, with the kind of item deciding how: beliefs are withdrawn, summaries are marked for rebuilding, and actions already taken are logged as leaks when they cannot be reversed.
The authors test this on their own set of 90 scripted scenarios, each with traps and matching controls, and report that it scores highest on four of five language models. On the strongest model it only ties one baseline. The protocol is meant for agents whose shared memory feeds tools with real side effects.
TL;DR
- MemTX is a transactional commit protocol for agent memory: writes are staged, checked and then committed as beliefs §3.
- Calls that cannot be undone wait while a belief is still unsettled, and withdrawing a belief sets off a type-aware cleanup of everything derived from it, side effects included §3.3 §3.4.
- Relevant if your agents share persistent memory and that memory can drive irreversible actions. Results are author-reported on the authors' own simulated suites.
- The two invariants are checked by property-based tests and by bounded enumeration, not by a proof §3.5.
- The repository has no LICENSE file, so its code cannot be reused on the strength of this card; only the method description and cited paths are offered.
Problem
Existing systems assume that every accepted write is true and can be acted on. A bad tool output, an outdated update or an unfinished note from another agent can therefore trigger an action that cannot be reversed §1, abstract. The paper sorts these failures into six families: corrupted tool results, late writes that should have been rejected as stale, reads of unsettled state, contradictions, leaks of private data through derived notes, and rollbacks that miss dependent records §1. Prior systems resolve competing writes by last-writer-wins or an LLM-judged merge, without an isolation level or a commit contract §2. The paper also cites database work on isolation anomalies and snapshot isolation as the ideas it adapts §2.
Method
Every memory record is a governed object, not a string. It carries an entity, attribute and value, a source with an authority weight, a permission block (owner, reader and writer roles, and a private, shared or public scope), edges to the records it was derived from, a type (belief, summary, profile, index entry, shared copy or tool action), a validity window checked against a clock the scenario supplies, and the confidence the writer reports §3.1. The authors' running example is a support agent that stages "order 841 is refund-eligible" from a lookup tool's result §3.1 fig. 1.
Lifecycle. A record moves from raw to tentative, validated and committed, and to action-safe in external-action transactions. Quarantined records failed a check and may be revalidated; superseded records were displaced by a newer value that won adjudication; revoked records are terminal. Any other move is rejected §3.1 state_machine.py.
Risk tiers and isolation. Each transaction is tagged with one of four risk levels, the last being external action. The level selects the read isolation. The harness, not the agent, sets it; no agent-facing tool accepts a level argument §3.1. The code maps low to committed read, medium to verified read, high to causally stable read, and external action to action-safe read memtx_manager.py. Visibility per level is set in schema.py.
Transactions and staging. Opening a transaction records the snapshot: the records visible at its isolation level at open time §3.2 memtx_manager.py. Staging writes each extracted observation as tentative and adds provenance edges. Staged records are invisible to other agents at committed read and above §3.2 memtx_manager.py.
Commit pipeline. Each staged record passes four ordered checks §3.2:
- Evidence: confidence must reach 0.6, unless the source authority reaches 0.9. Both comparisons are inclusive memtx_manager.py.
- Validity: the interval must contain the logical now. This check runs only when the case sets a logical clock memtx_manager.py.
- Semantic conflict, for writes to the same entity and attribute. Values that hold in non-overlapping time windows can both stand. If a rival was committed after the transaction's snapshot, the candidate counts as a stale late write and is rejected before authority is compared. Otherwise, more authority replaces the existing record, less authority is rejected, and a tie between different sources is sent to user review. The check also aborts candidates derived from revoked parents, and candidates that republish a private parent into a wider scope conflict_detector.py.
- Dependency stability: reject a record whose transitive ancestors include a revoked record memtx_manager.py dependency_graph.py.
A record that fails a check is quarantined with a machine-readable reason. A passing record is committed, and additionally action-safe in external-action transactions §3.2 memtx_manager.py. A transaction can commit, partially commit or abort. Each conflict adjudication counts as a verifier call §3.2 memtx_manager.py.
Action gate. Domain tools are split into reversible and irreversible sets, and the gate runs before every irreversible call §3.3. The gate blocks when either condition holds:
- an unsettled (tentative) record that the transaction did not read exists anywhere in the store, including records this agent staged and has not committed; this applies at every tier;
- the transaction is external-action and its snapshot holds no action-safe record.
A blocked call returns a structured refusal with its reason. The agent can commit or abort, then retry §3.3 memtx_manager.py. Reversible tools are not gated §3.3.
Typed cascading repair. A belief can be withdrawn in two ways: aborting the transaction that staged it, or revoking a committed record. Both paths run one routine §3.4 memtx_manager.py. The routine walks every transitive descendant in the derivation graph and acts by type §3.4 memtx_manager.py:
- beliefs are revoked;
- derived views (summaries, profiles, index entries, shared copies) are held back and rebuilt from surviving sources;
- tool actions are compensated if reversible; if not, they are recorded as leaked irreversible effects memtx_manager.py.
Every repair writes an entry to a rollback log §3.4.
# Commit one transaction [§3.2] [code: src/memtx/memtx_manager.py#L192-L281]
# Records are checked one at a time, in staging order. Each commit becomes
# an active belief for the records checked after it.
def commit_transaction(tx, store):
for record in tx.staged:
# Checks 1 and 2, evidence then validity [§3.2]
if not evidence_ok(record) or not validity_ok(record, store.now):
quarantine(record)
continue
# Check 3, semantic conflict against active beliefs [§3.2]
# Returns "commit", "abort", "supersede_old" or "ask_user".
verdict = conflict_verdict(record, active_beliefs(store), tx.snapshot)
if verdict == "abort" or verdict == "ask_user":
quarantine(record)
continue
if verdict == "supersede_old":
supersede_rivals(record, store)
# Check 4, no revoked ancestor [§3.2]
if not dependencies_stable(record, store.revoked_ids):
quarantine(record)
continue
# Promote; external-action transactions also mark action-safe [§3.2]
commit(record)
if tx.risk_tier == "external_action":
mark_action_safe(record)# Conflict verdict for one candidate [§3.2]
# [code: src/memtx/conflict_detector.py#L70-L186]
# Order matters: revoked parents and laundering are checked before the slot.
def conflict_verdict(candidate, beliefs, retracted_ids, snapshot):
for source_id in candidate.derived_from:
if source_id in retracted_ids:
return "abort"
# Private parent republished to a wider scope [§3.2]
for parent in active_parents(candidate, beliefs):
is_private = parent.share_scope == "private"
if is_private and candidate.share_scope != "private":
return "abort"
rivals = same_slot_active(candidate, beliefs)
if not rivals:
return "commit"
for rival in rivals:
if rival.value == candidate.value:
return "commit"
# Stale late write: rival not in the snapshot [§3.2]
if snapshot and rival.id not in snapshot:
return "abort"
# Authority decides only when the write is not stale [§3.2]
if candidate.authority > rival.authority:
return "supersede_old"
if candidate.authority < rival.authority:
return "abort"
if candidate.source == rival.source:
return "supersede_old"
return "ask_user"
return "commit"# Action gate for one tool call [§3.3]
# [code: src/memtx/memtx_manager.py#L96-L134]
# Reversible tools pass. Irreversible tools wait while any tentative record
# outside the snapshot exists, including the caller's own uncommitted staging.
def gate_allows(tx, tool_name, store):
if tool_name not in irreversible_tools:
return True
for record in store.records:
if record.state == "tentative" and record.id not in tx.snapshot:
return False
# External-action: also need an action-safe record [§3.3]
if tx.risk_tier == "external_action":
return any(store.is_action_safe(rid) for rid in tx.snapshot)
return True# Retraction and cascade repair [§3.4]
# [code: src/memtx/memtx_manager.py#L329-L401]
# The root is revoked, then each transitive descendant is repaired by type.
def retract(root, store, rollback_log):
revoke(root)
store.revoked_ids.add(root.id)
for node in store.descendants(root):
if node.type == "tool_action":
# Compensate if reversible, else log a leak [§3.4]
rollback_log.append(compensate_or_leak(node))
revoke(node)
elif node.type in {"summary", "profile", "index_entry", "shared_copy"}:
# Derived views are quarantined so they can be rebuilt [§3.4]
quarantine(node)
else:
revoke(node)
store.revoked_ids.add(node.id)Invariants. The paper states two invariants and one corollary §3.5. I1 (action-safety gating): an irreversible call executes if and only if the gate conditions above hold. I2 (cascade-repair completeness): once a record is retracted, none of its live descendants stays active. Beliefs are revoked, views are quarantined and listed in the revocation registry, and every tool-action descendant carries a compensated or leaked entry. G3: no reachable state holds a committed or action-safe record whose transitive ancestor is revoked §3.5. The checker recomputes reachability from each record's own provenance fields, not from the manager's bookkeeping §3.5 verify_invariants.py. fig. 1 shows admission running left to right (I1) and the cascade running right to left after a belief is found wrong (I2).
Agent interface. Five memory tools map onto the protocol operations: read, stage, commit, abort and revoke. Domain tools route through the gate first §3.6.
Hyperparameters
| Name | Value | Where | Notes |
|---|---|---|---|
| evidence threshold | 0.6, inclusive | §3.2 memtx_manager.py | Not tuned. A sweep from 0.3 to 0.8 leaves safety metrics unchanged up to 0.6; above 0.6 it over-blocks the main suite app. A |
| authority bypass | 0.9, inclusive | §3.2 memtx_manager.py | Sources at or above it skip the confidence check memtx_manager.py |
| risk tier to isolation | low: committed read; medium: verified read; high: causally stable read; external action: action-safe read | §3.1 memtx_manager.py | Paper gives no table. LLM path opens only low and medium transactions §3.5 |
| retrieval cap | top 8 | memtx_manager.py | Code default for retrieve. Paper does not state it |
| sampling temperature | 0 for the main tables; 0.7 for the seed study | §5 app. D | Serving at temperature 0 is not bit-reproducible; drift band at most 0.022 task success §4 |
| seeds | 3, open backbones only | app. D | Closed backbones run once at temperature 0 §5 |
| main suite | 90 cases: 60 traps, 30 controls | §4 app. H tab. 15 | Six corruption families, each with 10 traps and 5 controls |
| hardened suite | 56 cases: 40 traps, 16 controls | §4 app. H tab. 15 | Compound corruptions |
| downstream episodes | 24 refund episodes | §4 | Scores realised harm, not proxy accuracy |
| mock tools | 11 domain tools, 5 memory tools | §4 | Paper says six of the 11 are irreversible; see Paper vs code |
| backbones | Qwen3-8B, Qwen2.5-14B, GLM-4.7-Flash (open, served locally, GLM 4-bit); GPT-5.4-mini, GPT-5.5 (closed, hosted) | §4 app. B | Closed endpoints accepted only when every call answered from one dated snapshot app. B |
| invariant check | 10,000 random traces; bounded enumeration of 4 records, 3 transactions, depth 10: 5,530,160 states, 10,537,260 transitions, 0 violations | §3.5 | Default script values are 3 records, 2 transactions, depth 8; see Paper vs code |
| verifier calls | 1.36 to 1.58 per case across backbones | app. F tab. 13 | Only MemTX has non-zero verifier calls |
| max tokens, top-p, retry budget for the agent | not stated |
Results
Author-reported, on the authors' own conformance suites. Every system uses one harness, prompts, tool definitions and a rule-based scorer, so the memory manager is the sole difference §4. The baseline shown is the strongest one in each row.
| Setting | Metric | Baseline | This paper | Source |
|---|---|---|---|---|
| Main 90-case, Qwen3-8B | task success, temp 0 | Cordon + revocation, 0.822 | MemTX, 0.956 | tab. 2 |
| Main 90-case, Qwen2.5-14B | task success, temp 0 | Cordon + revocation, 0.678 | MemTX, 0.811 | tab. 2 |
| Main 90-case, GLM-4.7-Flash | task success, temp 0 | Cordon + revocation, 0.833 | MemTX, 0.944 | tab. 2 |
| Main 90-case, GPT-5.4-mini | task success, temp 0 | Cordon + revocation, 0.811 | MemTX, 0.922 | tab. 2 |
| Main 90-case, GPT-5.5 | task success, temp 0 | Cordon + revocation, 0.778 | MemTX, 0.756 (tie per paper) | tab. 2 §5 |
| Hardened 56-case, Qwen3-8B | task success, temp 0 | Cordon + revocation, 0.679 | MemTX, 0.875 | tab. 3 |
| Hardened 56-case, GPT-5.5 | task success, temp 0 | Cordon + revocation, 0.768 | MemTX, 0.929 | tab. 3 |
| Seed study, Qwen3-8B | task success, temp 0.7, mean ± sd over 3 seeds | Cordon + revocation, 0.815 ± 0.013 | MemTX, 0.948 ± 0.006 | tab. 9 |
| Main 90-case, Qwen3-8B | abort recall | TOKI, 0.889 | MemTX, 0.922 | tab. 4 |
| Downstream, all five backbones | realised harm (lower is better) | Cordon + revocation, 0.250 on Qwen3-8B | MemTX, 0.000 on every backbone | tab. 11 §5 |
| Main 90-case, five backbones | verifier calls per case | none (all baselines 0) | 1.36 to 1.58 | app. F |
Other reported results:
- Pooled paired McNemar tests on the seed study are significant for all 24 comparisons, with p at most 3.5e-6 tab. 10 tab. 8.
- Ablations on the main suite: removing semantic-conflict adjudication, permission inheritance or cascading rollback each costs about 11 points of task success fig. 2 §5.
- Removing the action gate, visibility scoping or snapshot reads costs the hardened families they own, and nothing on the main suite fig. 3 §5.
- Scope blind spots: in the source-scope family every method fails every case, including MemTX §5. In the temporal-scope family, a retry after a correct abort can turn a late write into an on-time one, which empties the staleness axis on three backbones for every method §5.
- Four further single removals (dependency stability, typed repair, validity interval, evidence gate) leave task success unchanged on the scripted path. Removing the evidence gate only raises conflict adjudications, from 117 to 130 on the main suite tab. 5 app. C.
Paper vs code
Code: https://github.com/lxy1134/MEMTX_, commit
4e1124ccd5fd384857463020e3497aa73ec93be6. The paper's first-page footnote
links it p. 1, which is enough under the compile rules. The repository's
README names the same authors and paper README.md. The owner name is
not verified as an author's account.
The repository has no LICENSE file and no license notice in its source
files, so code_license is recorded as not stated. Do not copy code from it.
- Irreversible tools: the paper says six of the eleven mock domain tools are irreversible §4.
IRREVERSIBLE_TOOLSin the code lists eight names, includingdelete_recordandpublish_postmock_tools.py. The card does not establish which set the reported runs used. - Invariant bounds: the paper reports 4 records, 3 transactions, depth 10 §3.5. The script's defaults are 3 records, 2 transactions, depth 8 verify_invariants.py. The reported figures match the saved run with 4 records, 3 transactions and depth 10 invariants_growth_r4t3d10.csv.
- Equal authority from the same source: the paper says equal authority from different sources is quarantined for user review. The code supersedes the old record when both sources match conflict_detector.py. The paper does not describe this case.
- Stale late write: the paper describes the check without a precondition. The code applies it only when the transaction has a non-empty snapshot conflict_detector.py.
- Permission laundering: the paper describes the check for any parent. The code looks only at active beliefs (validated, committed or action-safe), so a private parent staged in the same transaction is not caught at commit. The code comment says widening this would change committed results conflict_detector.py.
- Evidence check, validity check, four-step order, gate conditions, and repair-by-type: no discrepancy found. Code and paper agree on the thresholds 0.6 and 0.9 with inclusive comparisons memtx_manager.py.
- Temperature: the LLM runner defaults to 0.0 run_llm_experiment.py, matching the paper.
Pitfalls
- Stale check disappears with an empty snapshot. The stale-late-write rule is skipped when the transaction opened on an empty visible set conflict_detector.py. An implementation that starts from an empty store loses that protection.
- Retry defeats the stale check. The paper's own scope finding: after a correct abort, the retry's snapshot already includes the rival, so the write stops counting as late and authority decides instead §5. Provenance does not follow content across transactions, and the paper calls this the most principled open problem §5 §6.
- Quarantined records are not in the revoked set. Dependency-stability and derived-from checks consult only revoked identifiers memtx_manager.py conflict_detector.py. Commit does not check that a parent is committed. The paper's argument that no later record can cite a quarantined parent relies on agents never seeing its id, and nothing in commit enforces it.
- Gate liveness. Any open transaction holding a tentative record blocks every irreversible call from every other agent until that record commits or aborts memtx_manager.py. A stalled agent therefore stalls the others.
- Authority bypass is a trust boundary. Any source with authority 0.9 or above skips the confidence check memtx_manager.py. The paper does not say how authority values are assigned. A missing source is treated as authority 0.5 conflict_detector.py.
- Own correction replaces a belief silently. Same-source writes with equal authority supersede the old record without review conflict_detector.py.
- Validity is off unless the case sets a clock. With no logical now, the validity check always passes memtx_manager.py. Dates compare at day granularity, and an unparsable bound counts as no bound memtx_manager.py.
- Repair can revoke a view instead of quarantining it. Quarantine is not allowed from action-safe, so such a view falls back to revoked and is not rebuilt memtx_manager.py state_machine.py.
- Leaks are logged, not undone. Compensation only records a decision. Replay of the compensating call is left to the runner, and the leak test depends on the static irreversible set memtx_manager.py.
- Staging order matters. Records in one transaction are checked in staging order, and each commit becomes an active belief for the next record memtx_manager.py.
- Hidden costs. Each record that reaches the conflict step costs one adjudication. The paper meters about 1.5 per case, and tokens exceed the baseline band on three backbones by up to 14 percent §5 app. F.
- Cold versus matured stores. Forcing every transaction to the external-action tier over a cold store cuts hardened success by 13 to 17 cases on every backbone app. C tab. 7. Inferring the tier from prompt text costs at most four main-suite cases app. C.
Lineage
- Builds on: database isolation levels and snapshot isolation, cited as the ideas behind the design §2 (no card in this wiki).
- Compared against, as faithful reimplementations in the repository: Cordon, Verified Concurrency, MemState (the authors' official code, vendored unmodified), Collaborative Memory and TOKI, plus three augmented variants that each add one MemTX feature to a baseline §4 .
- Also discussed: GateMem, Governed Shared Memory, SAFEFLOW and GEM §2. None has a card in this wiki.
- Superseded by: not stated.
Source and license
Adapted from “MemTX: Transactional Belief Commit for Stateful Agent Memory” by Xiaoyang Li, Yiqi Wang, Haohui Lu, Zhi Chen, Mo Li, Pingan Song, Mingkai Zheng, Taotao Cai (arXiv:2607.23929), used under CC BY 4.0. Changes: condensed and restructured for implementation, with tables, equations and algorithms taken from the paper and its code, each cited to its source. Not affiliated with or endorsed by the authors. Code citations refer to https://github.com/lxy1134/MEMTX_ at commit 4e1124ccd5fd (none stated (no LICENSE file)). Any quoted code is shown under that license.