Skip to main content

fathom-read

Catch the step where an AI agent contradicts a decision it already made.

On a long task, an agent loses track of what it already decided and starts acting against it. It renames guest_id to customer_id at step 1, then writes new code against guest_id at step 6. The change compiles, imports, and passes the tests. It fails at runtime.

fathom-read turns the traces your framework already records into an action stream and sends it to the Fathom read, which reconstructs the state the agent committed and flags the step that contradicts it. Deterministic. No model access. Nothing runs in your production path.

fathom demo

Install

pip install fathom-read

Run

fathom demo                                              # the bundled rename example, coherent and not
fathom read trace.json --supersede guest_id=customer_id  # your own trace
fathom read history.json --format langgraph              # or name the format
fathom read trace.json --ops                             # see the action stream before anything is sent
fathom formats                                           # the formats it reads

fathom read exits 0 when the committed state is coherent and 2 when it finds a contradiction, so it drops into a test suite or a CI step as it is. Add --json for a machine-readable verdict.

The package ships with a demo key that is rate-limited per day. For your own key, which lifts the limit and keeps your traces on a private tier, write to contact@embeddedriskanalytics.com and set FATHOM_API_KEY. --ops shows exactly what would be sent: the ops the adapter produced, and nothing else.

What it reads

Format What you export How
langgraph The checkpoint lineage [{"values": s.values, "step": s.metadata["step"]} for s in graph.get_state_history(config)]
openinference The spans Arize Phoenix stores Export the trace's spans as JSON; only TOOL spans matter
crewai The crew's event log A listener on the event bus, capturing tool_usage_finished, tool_usage_error, task_completed
letta Blocks, passages, and the memory-edit tool calls agents.blocks.list, agents.passages.list, the tool calls from agents.messages.list
dbos A workflow's step stream {"workflow_id": ..., "steps": [{"step_name", "args", "result", "ok"}]}
edits A coding agent's edit log {"initial_files": {...}, "edits": [{"tool": "str_replace_editor", "args": {...}, "ok": true}]}
events The native op stream One op per line: {"op": "set", "kind": "file", "key": "a.py", "value": "...", "ok": true}

Your tools have their own names. Map them once with --map tools.json:

{"save_decision": {"op": "set", "kind": "decision", "key": "topic", "value": "text"},
 "book_seat":     {"op": "add", "kind": "flight", "key": "seats", "value": "seat"},
 "confirm_booking": {"op": "commit", "kind": "flight", "key": "booking"}}

What it finds

Finding The agent...
stale_reference acts on a fact it already removed or renamed away
superseded_value writes or answers with a value it already replaced
authored_contradiction reintroduces a token into a record it had already migrated
residual ends the run with a record still carrying a value it replaced elsewhere
duplicate_commit adds an entity a collection already holds
post_commit_mutation changes a thing after committing it

Every finding cites the earlier step it contradicts, so the readout is a diff between what the agent decided and what it did.

How it reads

The read folds the agent's successful actions into a ledger of committed facts and checks every later action against the ledger. Two rules make this a reconstruction rather than a transcript. A failed action is a no-op: an edit the tool rejected leaves nothing behind. And the read consults only the agent's own actions and their results, never an answer key, so it attaches the same way on any framework. The adapters and the CLI in this repository build the action stream; the read itself runs in ERA's service.

Use it from Python

from fathom_read import Op, read

ops = [
    Op("set", "fact", "user.city", value="Denver"),
    Op("set", "fact", "user.city", value="Austin"),
    Op("answer", "fact", "user.city", value="The user lives in Denver."),
]
verdict = read(ops)          # uses FATHOM_API_KEY, or the demo key
for f in verdict.findings:
    print(f.kind, f.step, f.detail)
# superseded_value 2 step 2 answers 'Denver' for fact 'user.city', a value the agent replaced with 'Austin' at step 1.

What it does not do

It does not run your agent, call a model, or need one. It does not say why the agent contradicted itself or which repair would fix it; that is the design-partner engagement. It reads agents whose committed state lives in tool calls, checkpoints, memory writes, or edits; an agent that keeps state only in free-text logs is out of scope.

Research

The read comes out of the Fathom program at Embedded Risk Analytics. Case studies on LangGraph, CrewAI, Letta, OpenHands, Agent-E, ContextPilot, and τ-bench are at embeddedriskanalytics.com/research. The theory is in Records, Reflexive Modeling, and the Conditions for Stable Physical Histories (SSRN, 2026). See CITATION.cff.

Send us a trace

If you run long-horizon agents and want a readout on your own traces, send a batch: embeddedriskanalytics.com/contact.

License

MIT. Fathom is a trademark of Embedded Risk Analytics.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fathom_read-0.1.1.tar.gz (20.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fathom_read-0.1.1-py3-none-any.whl (22.1 kB view details)

Uploaded Python 3

File details

Details for the file fathom_read-0.1.1.tar.gz.

File metadata

  • Download URL: fathom_read-0.1.1.tar.gz
  • Upload date:
  • Size: 20.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for fathom_read-0.1.1.tar.gz
Algorithm Hash digest
SHA256 caa36df6078ff5e5e5b0cce7a990b96196bc7c51a7d91efb943c4fa4bdf5122a
MD5 f0c740bc9baec8dc3e7066319ab7a9ea
BLAKE2b-256 b85f22407c23aaa4dbd7f01231dd4bdbbb7c83859a1e22d419e55fbed598fb5f

See more details on using hashes here.

Provenance

The following attestation bundles were made for fathom_read-0.1.1.tar.gz:

Publisher: release.yml on ERA-Fathom/fathom

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fathom_read-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: fathom_read-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 22.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for fathom_read-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 6674b7152f2ba15d9ae6f2f2a8c6dd3e97ff6f608e4251f3aba00abbae2f2700
MD5 0ded2228632a532f75f652b8a14dddbd
BLAKE2b-256 80b7157b008b07262f95949a5bc63d7c2173b070c69e398bf41c2fb94c0039ed

See more details on using hashes here.

Provenance

The following attestation bundles were made for fathom_read-0.1.1-py3-none-any.whl:

Publisher: release.yml on ERA-Fathom/fathom

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.1.2

2 files

This release

0.1.1 This release

2 files

0.1.0

2 files

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