Skip to main content

causal-agent-replay

Find which step actually caused your agent to fail — by intervening on it and measuring whether the outcome changes.

When an LLM agent does something wrong — issues a refund it shouldn't have, calls the wrong tool, leaks data — observability tools (LangSmith, Langfuse) show you what happened, and eval tools (Promptfoo) score pass/fail. Neither answers the question that actually matters for debugging:

Which step caused the bad outcome?

causal-agent-replay (CAR) answers it the only principled way: it intervenes on a step and re-runs the agent forward to see if the outcome changes. The step where changing the decision changes the outcome — but changing later steps does not — is the causal locus. Proven by counterfactual, not guessed from a trace.


The idea in one picture

A recorded run is modelled as a structural causal model (Pearl):

τ = [ s0, (a1,o1), (a2,o2), …, (an,on), y ]
  • s_k — the exact state the agent decided from (system prompt, tools, full message history)
  • a_k — the action it took (a tool call or a final answer), drawn from the stochastic policy π
  • o_k — the tool result
  • y — the outcome, scored by a user-supplied function Y(τ)

An intervention is a do(·) on one variable, after which the agent re-decides everything downstream. Because the policy is stochastic, running forward K times gives a distribution over outcomes — never a single path. The causal effect of step k is how much that distribution shifts versus the observed run. Attribution ranks steps by causal effect.

The headline primitive is do_resample(k): change nothing except re-draw the action at step k from the same policy. If the bad outcome usually disappears when you resample step k — but persists when you resample k+1 — then k is where the agent committed to the failure.

The intervention algebra

do(·) meaning question it answers
do_resample re-draw a_k from the unchanged policy how sensitive is the outcome to this step?
do_action force a specific a_k what if it had done X instead?
do_observation replace the tool result o_k what if the tool had returned X?
do_context edit the message history at k what if the prompt hadn't contained X?
do_policy swap the model from k forward did the model upgrade break it?

See it

uv sync --extra dev
uv run python scripts/make_demo.py     # -> examples/demo_report.html  (open it)

The demo report attributes a support agent that absorbed a prompt injection. It shows the causal locus is the decision step — resampling it avoids the bad refund ~half the time, resampling the already-committed steps never does — with the injection visible in the exact context that step decided from, an attribution chart with confidence intervals, and a Shapley toggle. (docs/writeup.md explains the method; examples/gallery.md runs the engine on a live local model.)

Status

Built in phases (see PLAN.md); each phase is research-gated with a binary done-condition. Phases 0–4 are complete and validated against synthetic SCMs with known ground truth.

  • Phase 0 — faithful recording + deterministic replay. ✅
  • Phase 1 — intervention algebra + forward replay. ✅
  • Phase 2 — distributional outcomes + effect estimators (with confidence intervals). ✅
  • Phase 3 — causal attribution (contrastive + budget-bounded Monte-Carlo Shapley). ✅
  • Phase 4 — interactive visualization + technical writeup. ✅

Why this is honest about hard things

  • Counterfactual replay yields a distribution, not a path. The policy is stochastic; every effect is an estimate reported with Monte-Carlo confidence intervals.
  • Providers are not deterministic — even at temperature 0, and current Claude Opus models don't accept a temperature at all. CAR does not pretend otherwise: it measures the action-match rate of replay and reports residual nondeterminism as a metric. See RESEARCH/phase_0_foundations.md.
  • Attribution is validated against synthetic SCMs with known ground truth, not just against plausible-looking heatmaps. A method that can't recover a pivotal step you planted isn't trusted.

Install

pip install causal-agent-replay     # not yet published
# or, from source:
uv sync --extra dev

Quickstart — free, no API key (local Ollama)

CAR runs against any backend behind the Policy protocol, so you can record and replay agents with a free local model — no spend. Ollama exposes an OpenAI-compatible endpoint, so one policy covers it (and Groq / OpenRouter / vLLM / LM Studio too).

ollama serve &                 # start the local server
ollama pull llama3.1:8b        # a tool-capable model (qwen2.5:7b also works)

# record the support-agent demo against the local model, then replay it
uv run python scripts/record.py --backend ollama --model llama3.1:8b
uv run car replay support-injection-demo

Local seeded inference (seed + temperature=0 + a fixed num_ctx) reproduces far more reliably than hosted APIs — a real advantage for faithful replay. Hosted providers stay supported (--backend anthropic with ANTHROPIC_API_KEY, or any OpenAI-compatible endpoint via OPENAI_BASE_URL), and their nondeterminism is measured and reported, not hidden. See RESEARCH/phase_0_foundations.md.

Intellectual lineage

Pearl's do-calculus and SCMs · counterfactual credit assignment in RL (Mesnard et al.) · causal influence diagrams for agents (Everitt, Carey et al.) · Shapley attribution · record-replay / time-travel debuggers (rr, Pernosco). The novel intersection — causal credit assignment applied to LLM-agent traces as a practical debugging tool — is what CAR is.

License

Apache-2.0

Metadata

Release files for causal-agent-replay 0.0.1

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

Source distribution (sdist)

Source distribution for causal-agent-replay 0.0.1
File Size Uploaded
causal_agent_replay-0.0.1.tar.gz 38.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for causal-agent-replay 0.0.1
File Interpreter ABI Platform
causal_agent_replay-0.0.1-py3-none-any.whl Python 3 none any Details

Total release size: 90.1 kB

Release files / causal_agent_replay-0.0.1.tar.gz

Download URL causal_agent_replay-0.0.1.tar.gz
Size 38.6 kB
Tags Source
SHA-256 checksum
How to use checksums
9d1d05742c6b5ea80e17111373fc0e3d9d37823054b53923afb93b98b44784a9
BLAKE2b-256 checksum
How to use checksums
5454b25784904ed29aced124441bb742a40a121ba083a290b01a222258f9887e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","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}

Release files / causal_agent_replay-0.0.1-py3-none-any.whl

Download URL causal_agent_replay-0.0.1-py3-none-any.whl
Size 51.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c3356a6859dca377442f1cd3413dbbb4cbbb93679e01cee965b8358753ab0a8a
BLAKE2b-256 checksum
How to use checksums
a6e3a6982ffc3317e0b451dcd246293f0790d7584c20503eb2489137c58081dc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","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}

Release history Release notifications | RSS feed

This release

0.0.1 This release

2 release 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