Your AI agent corrupted the codebase. Now what?
The only tool that physically deletes hallucinated files — git reset --hard, not just state rollback.
No API keys. No cloud. No vendor lock-in. Works with TERX — memory layer for browser agents.
The Problem Every AI Agent Developer Has Hit
You ran Claude Code, OpenHands, or a LangGraph agent autonomously.
It wrote 40 files. It failed at step 8. Now you have:
- 23 files that shouldn't exist
- A broken import chain
- State that says "success" on steps that half-ran
- No way to know what the repo looked like before step 6
Your repo after a bad autonomous run:
/src/handlers.py ← hallucinated, breaks import
/src/auth_v2.py ← duplicate of auth.py, never needed
/src/models_refactor.py ← partial rewrite, syntax error
/tests/test_fake.py ← tests for code that doesn't exist
/config/settings_new.py ← overwrote working config
Every other tool shows you logs. Agent VCR runs git reset --hard and deletes every one of those files.
ACID Rollback — The Feature Nobody Else Has
from agent_vcr import VCRRecorder from agent_vcr.integrations.openhands import ACIDWorkspace recorder = VCRRecorder() acid = ACIDWorkspace("/my/workspace", recorder=recorder) acid.begin(session_id="task-001") # isolated git branch acid.savepoint(state, node_name="coder") # checkpoint state + filesystem acid.savepoint(state, node_name="tester") # Agent writes 47 files. 23 are hallucinated garbage. Step 6 failed. acid.rollback(to_frame_index=1) # git reset --hard # All 23 files: physically deleted from disk. Not hidden. Gone. acid.commit() # merge only the clean branch
Before rollback: After rollback:
/src/handlers.py ✗ DELETED
/src/auth_v2.py ✗ DELETED
/tests/fake_test.py ✗ DELETED
/src/utils.py ✓ kept
/src/models.py ✓ kept
LangSmith shows you what happened. LangFuse shows you what happened. Arize shows you what happened.
Agent VCR changes what happened.
Ghost Replay — Never Pay for the Same Task Twice
Agent succeeds? Save it. Run it again for free forever.
from agent_vcr.golden_cache import GoldenRunCache cache = GoldenRunCache() cache.save_golden_run("Build a REST API with JWT auth", recorder) # Every future run of the same task: outputs, ledger = cache.replay("Build a REST API with JWT auth") print(ledger)
RUN 1 (original) RUN 2 (Ghost Replay)
───────────────── ─────────────────────
Tokens: 4,100 Tokens: 0
Cost: $0.0123 Cost: $0.00
Time: 2,350ms Time: 1ms
💰 100% savings · $0.0123 saved · 4,100 tokens · 2,349ms faster
Time-Travel Debugging
Agent fails at step 8 of 10? Don't re-run from zero.
from agent_vcr import VCRPlayer from agent_vcr.models import ResumeConfig player = VCRPlayer.load(".vcr/my_run.vcr") # See exact state at every step print(player.goto_frame(6)) # {'files_written': [...], 'plan': '...'} print(player.get_errors()) # what broke and where # Fix the prompt. Resume from step 6. Skip steps 0-5. player.resume( agent_callable=coder, config=ResumeConfig( from_frame=6, state_overrides={"plan": "use SQLAlchemy instead of raw SQL"} ) )
Without Agent VCR With Agent VCR
────────────────── ──────────────────────────
Agent fails step 8 Agent fails step 8
Patch the code player.goto_frame(7)
Re-run ALL 10 steps Fix the state
$0.04 + 2 min wasted Resume from step 7
Repeat for every bug Done. $0.00 extra.
Who This Is For
You need this if you're running:
- Claude Code / Cursor autonomous mode
- OpenHands on real codebases
- LangGraph agents that write files
- CrewAI pipelines with filesystem access
- Any autonomous coding agent on a repo you care about
You don't need this if you're only:
- Doing RAG / chatbots (no filesystem risk)
- Already happy with LangSmith for tracing
Quick Start
Record
from agent_vcr import VCRRecorder recorder = VCRRecorder() recorder.start_session("my_run") state = {"query": "build a REST API"} state = planner(state) recorder.record_step("planner", input_state, state) state = coder(state) recorder.record_step("coder", input_state, state) recorder.save() # → .vcr/my_run.vcr
Or use the context manager — frames are saved even if the agent crashes:
with VCRRecorder() as recorder: recorder.start_session("my_run") # ... your agent code ...
Rewind & Fix
player = VCRPlayer.load(".vcr/my_run.vcr") diff = player.compare_frames(5, 6) # {'added': {'bad_file': '...'}, 'modified': {'plan': '...'}} player.resume( agent_callable=coder, config=ResumeConfig(from_frame=5, state_overrides={"plan": "fixed"}) )
Integrations
LangGraph — one line
from langgraph.graph import StateGraph from agent_vcr import VCRRecorder from agent_vcr.integrations.langgraph import VCRLangGraph recorder = VCRRecorder() graph = VCRLangGraph(recorder).wrap_graph(graph) # ← one line, that's it result = graph.invoke({"query": "Build a todo app"}) recorder.save()
CrewAI
from agent_vcr.integrations.crewai import VCRCrewAI recorder = VCRRecorder() recorder.start_session("crew_run") result = VCRCrewAI(recorder).kickoff(crew) recorder.save()
pip install "ai-agent-vcr[crewai]" pip install "ai-agent-vcr[langgraph]"
Raw Python (decorator)
from agent_vcr.integrations.langgraph import vcr_record @vcr_record(recorder, node_name="research_step") def research(state: dict) -> dict: return {"findings": search(state["query"])}
Sentinel — Real-Time Code Guardian
Catches what the agent wrote before it moves to the next step.
from openhands_sentinel import Sentinel sentinel = Sentinel(recorder=recorder) sentinel.attach(runtime.event_stream) # 3 lines. auto-intercepts every write.
STEP 2: Agent writes handlers.py
🛡️ SENTINEL: VIOLATIONS DETECTED
CRITICAL hash_password() already exists in auth/utils.py:8 — reuse it
CRITICAL handle_auth_request() is 109 lines (limit: 40) — break it up
CRITICAL Cyclomatic complexity: 32 (limit: 8)
STEP 3: Agent self-corrects
🛡️ SENTINEL: handlers.py — CLEAN ✓
| Without Sentinel | With Sentinel | |
|---|---|---|
| Agent writes bad code | ✓ | ✓ |
| Sentinel catches it | — | < 10ms |
| Agent self-corrects | — | done |
| Human reviews PR | manual | zero |
| Cost | 2× LLM + human time | 1 extra LLM call |
Standalone scan:
sentinel scan ./my-ai-project
TUI Debugger
┌──────────────────────────────────────────────────────────┐
│ 📼 Agent VCR Session: my_run · 8 frames │
├──────────────────────────────────────────────────────────┤
│ ▶ Frame 0 │ planner │ 100ms │ ● │
│ Frame 1 │ researcher │ 250ms │ ● │
│ Frame 2 │ coder │ 480ms │ ✗ ERROR │
│ Frame 3 │ tester │ 80ms │ ● │
├──────────────────────────────────────────────────────────┤
│ { "query": "build a todo app", "plan": null } │
├──────────────────────────────────────────────────────────┤
│ ←/→ navigate │ e edit │ d diff │ r resume │ q quit │
└──────────────────────────────────────────────────────────┘
Keybindings: ↑/↓ or j/k navigate · e edit state · 1/2/3 input/output/diff · r resume · s search · q quit
Claude Code hooks:
DAG Visualization
vcr-server .vcr/
# localhost:8000original_run ──────────────────────────────────────────► [done]
│ frame 3
╰──► fork_v1 ──► [coder] ──► [tester] ──► [done]
╰──► fork_v2 ──► [coder] ──► [done]
Live WebSocket streaming. Every fork is a branch. Errors in red.
vs Everything Else
Honest take: LangSmith, Langfuse, Arize Phoenix, and AgentOps are serious platforms with large teams. They are observability tools — they show you what happened. Agent VCR is an intervention tool — it lets you change what happened. Different category. The overlap is tracing. Everything else diverges.
| Capability | 📼 Agent VCR | LangSmith | LangFuse | AgentOps | Arize Phoenix |
|---|---|---|---|---|---|
| Record execution traces | ✅ | ✅ | ✅ | ✅ | ✅ |
| Production dashboards | Local | ✅ best-in-class | ✅ | ✅ | ✅ |
| Eval / scoring pipelines | ❌ | ✅ | ✅ | ✅ | ✅ |
| Time-travel / session replay | ✅ | ❌ | ❌ | ✅ (view only) | ❌ |
| Edit state & resume mid-chain | ✅ | ❌ | ❌ | ❌ | ❌ |
| ACID filesystem rollback | ✅ | ❌ | ❌ | ❌ | ❌ |
| Ghost Replay (zero tokens) | ✅ | ❌ | ❌ | ❌ | ❌ |
| Sentinel (real-time code guard) | ✅ | ❌ | ❌ | ❌ | ❌ |
| Fork from any frame | ✅ | ❌ | ❌ | ❌ | ❌ |
| TUI debugger | ✅ | ❌ | ❌ | ❌ | ❌ |
| Fully local / self-hosted | ✅ | ❌ Cloud | ✅ | ❌ Cloud | ✅ |
| Framework-agnostic | ✅ | ✅ | ✅ | ✅ |
AgentOps — closest competitor on time-travel. It lets you view past sessions. It does not let you edit state and resume, fork a session, rollback the filesystem, or replay for zero tokens. If you need view-only replay, AgentOps is mature. If you need to actually intervene, you need Agent VCR.
Use LangSmith/Langfuse/Phoenix/AgentOps for production tracing and evals. Use Agent VCR when you need to actually fix a broken run without re-running it, rollback filesystem damage, or replay a successful run for free.
vs LangGraph's Built-In Checkpointer
LangGraph's checkpointer is solid if you're 100% LangGraph and only need state inspection.
The gap: when your agent writes files to disk and fails, the checkpointer rolls back the state object. The files stay. Agent VCR runs git reset --hard. The files are gone.
| LangGraph Checkpointer | Agent VCR | |
|---|---|---|
| Checkpoint in-memory state | ✅ | ✅ |
| Rollback files from disk | ❌ | ✅ |
| Ghost Replay (zero tokens) | ❌ | ✅ |
| Sentinel (code guardian) | ❌ | ✅ |
| Works with CrewAI, raw Python | ❌ | ✅ |
| JSONL format (git-diffable) | ❌ | ✅ |
| Session forking | ❌ | ✅ |
Performance
Every benchmark is enforced in CI. If it regresses, CI fails.
pip install -e ".[dev]"
pytest tests/benchmarks/ -v --benchmark-only| Benchmark | Limit | What it measures |
|---|---|---|
test_benchmark_recorder_overhead |
< 5ms mean | Serialize + buffer one state snapshot |
test_benchmark_file_write_speed |
> 1,000 frames/sec | Sustained write throughput (10K frames) |
test_benchmark_load_speed |
< 500ms | Load a 10,000-frame session from disk |
test_benchmark_goto_frame |
< 1ms | Random-access time-travel to any frame |
Historical results: ixchio.github.io/agent-vcr/dev/bench/
Storage Format
Plain JSONL. One object per line.
{"type": "session", "data": {"session_id": "my_run", "created_at": "..."}}
{"type": "frame", "data": {"node_name": "planner", "input_state": {...}, "output_state": {...}}}
{"type": "frame", "data": {"node_name": "coder", ...}}- Human-readable — open in any text editor
- Git-diffable — review agent state in PRs
- Append-only — safe for concurrent agents, no full-file rewrites
- Streamable — parse line-by-line without loading the full file
API Reference
VCRRecorder
recorder = VCRRecorder( output_dir=".vcr", auto_save=True, diff_mode=False, ) recorder.start_session(session_id="my_run", tags=["prod"]) recorder.record_step(node_name, input_state, output_state, metadata) recorder.record_llm_call(model, messages, response, tokens_input, tokens_output, latency_ms) recorder.record_tool_call(tool_name, tool_input, tool_output, latency_ms) recorder.record_error(node_name, input_state, error) recorder.save() -> Path recorder.fork(from_frame=3) -> VCRRecorder
VCRPlayer
player = VCRPlayer.load(".vcr/my_run.vcr") player.goto_frame(index) # → output state at frame N player.get_input_state(index) # → input state at frame N player.get_errors() # → [Frame, ...] player.compare_frames(a, b) # → {'added': {}, 'removed': {}, 'modified': {}} player.get_total_cost() # → float (USD) player.resume( agent_callable, config=ResumeConfig( from_frame=7, state_overrides={"k": "v"}, mode=ResumeMode.FORK, # FORK | REPLAY | MOCK ) )
ACIDWorkspace
acid = ACIDWorkspace("/workspace", recorder=recorder) acid.begin(session_id="task-001") acid.savepoint(state, node_name="coder") acid.rollback(to_frame_index=2) # git reset --hard acid.commit()
GoldenRunCache
cache = GoldenRunCache(cache_dir=".vcr/golden") cache.save_golden_run(task_description, recorder) outputs, ledger = cache.replay(task_description) cache.invalidate(task_description) cache.list_golden_runs()
Examples
# ACID rollback + Ghost Replay — start here python examples/acid_golden_run.py # Time-travel: rewind, edit state, resume python examples/time_travel_demo.py # Sentinel: watch agent self-correct in real time python examples/sentinel_demo.py # LangGraph auto-instrumentation python examples/langgraph_integration.py # Basic recording and playback python examples/basic_usage.py
Roadmap
- Core recording and playback
- Time-travel resume with state injection
- LangGraph + CrewAI integrations
- Async recorder and player
- Terminal TUI debugger (
vcr) - Claude Code hook scaffolding (
vcr init --claude-code) - Live dashboard with DAG visualization
- ACID Transactions (git-backed filesystem rollback)
- Ghost Replay (zero-cost replay of successful runs)
- Sentinel — real-time code quality guardian
- Context manager (
with VCRRecorder() as r:) - Claude Code / Cursor integration
- AutoGen integration
- Replay regression tests (golden paths as CI assertions)
- Collaborative debugging (share sessions)
- Cloud storage backend (S3, GCS)
Community
If Agent VCR saved your repo from a bad autonomous run, share it:
- OpenHands — Discord
#toolschannel - LangGraph — Discord
#communitychannel - r/LocalLLaMA — post your ACID rollback story
- Hacker News — Show HN posts with real before/after diffs get traction
The best growth comes from developers sharing the moment it saved them. If that's you, a post with your actual corrupted-repo story (even anonymized) is worth more than any ad.
Contributing
git clone https://github.com/ixchio/agent-vcr.git cd agent-vcr pip install -e ".[dev,tui]" pytest tests/unit/ -v
See CONTRIBUTING.md for guidelines.
License
MIT — see LICENSE.