Deterministic record/replay of LLM and tool calls for AI agents, captured into human-readable cassettes.
Project description
AgentTape
Deterministic record and replay for AI agents. Capture every external interaction your agent makes — LLM calls and tool calls — into human-readable "cassettes", then replay them deterministically so your tests run offline, for free, with zero side effects.
Why
Agent tests today are slow, flaky, expensive, and dangerous: they hit real LLM APIs (cost + nondeterminism) and real tools (a tool that charges a card, writes a row, or posts to Slack actually does it). AgentTape records those interactions once and replays them deterministically afterwards. Your CI runs with no network access, no API keys, and no risk of a real side effect.
- Local-first — no server, no telemetry, nothing leaves your machine.
- Deterministic — same inputs produce the same recorded outputs, byte-for-byte.
- Zero side effects in replay — a replayed tool never executes for real.
- Almost-no-code — add a decorator or a
withblock. - Git-friendly — cassettes are YAML: diffable, reviewable, hand-editable.
- Zero core dependencies — the engine is pure standard library.
Install
pip install agenttape # core (stdlib only)
pip install "agenttape[openai]" # + OpenAI adapter
pip install "agenttape[yaml]" # + PyYAML for extra-robust YAML loading
30-second quickstart
Record once (real API call), then replay forever (no network):
import agenttape
from openai import OpenAI
def run_agent():
client = OpenAI()
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "Say hi in 3 words"}],
)
return resp.choices[0].message.content
# --- record (hits the real API once, writes cassettes/hello.yaml) ---
with agenttape.use_cassette("hello", mode="record"):
print(run_agent())
# --- replay (zero network calls, milliseconds, free, deterministic) ---
with agenttape.use_cassette("hello", mode="none"):
print(run_agent()) # identical output, served from the cassette
Or as a decorator:
@agenttape.replay("hello") # mode="none": offline + deterministic
def test_agent():
assert "hi" in run_agent().lower()
Mixed / partial replay — "freeze all but one"
Change one thing — a prompt, a model, a single tool — and re-run while every other expensive or dangerous boundary stays frozen from the recording:
# Only the LLM runs for real; every tool is served from the cassette.
# A *derived* cassette is written — the original is never mutated.
with agenttape.use_cassette("checkout", live={"llm"}):
result = run_agent() # new prompt → new LLM output, tools stay frozen
# See exactly what changed:
# agenttape diff cassettes/checkout.yaml cassettes/checkout.derived.yaml
Any boundary that is not in live and has no recording raises
UnmatchedInteractionError — AgentTape will never silently run a real side effect.
Hand-edit a response
Cassettes are just YAML. Open cassettes/hello.yaml, edit a recorded LLM
response, save, and re-run in mode="none" — your agent behaves differently with
no API call at all. Perfect for testing edge cases and failure paths.
pytest plugin
Ships in the box. Tests run offline and deterministically by default:
import pytest
@pytest.mark.agenttape("weather_agent")
def test_weather(agenttape_cassette):
assert run_agent() == "It's sunny."
pytest # replay mode, offline, free (CI default)
pytest --agenttape-record # (re)record cassettes against the real API
CLI
agenttape init # scaffold agenttape.toml + cassettes/
agenttape inspect cassettes/hello # tokens, latency, cost, per-step I/O
agenttape timeline cassettes/hello # ASCII waterfall of the run
agenttape diff a.yaml b.yaml # prompt / model / tool / cost / output diff
agenttape validate cassettes/hello # schema + determinism + leaked-secret lint
agenttape view cassettes/hello # self-contained static HTML, no server
agenttape redact cassettes/hello # re-run secret/PII redaction
agenttape export cassettes/hello --format otel
What this is — and what it isn't
It is:
- A deterministic record/replay layer for agent I/O (LLM + tools + raw HTTP).
- A way to make agent tests fast, free, offline and side-effect-free.
- A diff/inspection toolkit for understanding and reviewing agent runs.
It isn't:
- It is not a way to "replay with a different prompt/model and get a
deterministic answer for free." Replay reconstructs recorded bytes. The moment
you change an input to a boundary marked
live, that boundary really executes (real API call, real cost) and produces a new recording. AgentTape is explicit about this everywhere — pure replay vs. re-execution are different verbs and we never blur them. - It is not an evaluation framework, a prompt optimizer, or a tracing SaaS.
See the determinism guide and the cassette format spec for details.
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file agenttape-0.1.0.tar.gz.
File metadata
- Download URL: agenttape-0.1.0.tar.gz
- Upload date:
- Size: 59.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7bf8b530b5d1a9d832cd54337ac7a7965a70e66041bd9b73a70e66a1705a9af8
|
|
| MD5 |
d9813c7748de945d107df2b728987884
|
|
| BLAKE2b-256 |
c27084b9b23e622f9482a53acd133ba15d029a8a86f092a67dc12fe4823842d0
|
Provenance
The following attestation bundles were made for agenttape-0.1.0.tar.gz:
Publisher:
release.yml on MITHRAN-BALACHANDER/AgentTape
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
agenttape-0.1.0.tar.gz -
Subject digest:
7bf8b530b5d1a9d832cd54337ac7a7965a70e66041bd9b73a70e66a1705a9af8 - Sigstore transparency entry: 1847237894
- Sigstore integration time:
-
Permalink:
MITHRAN-BALACHANDER/AgentTape@6e6b7e6afe5e4d77d54be5b4147e6c8fdff03322 -
Branch / Tag:
refs/tags/v0.0.0 - Owner: https://github.com/MITHRAN-BALACHANDER
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@6e6b7e6afe5e4d77d54be5b4147e6c8fdff03322 -
Trigger Event:
push
-
Statement type:
File details
Details for the file agenttape-0.1.0-py3-none-any.whl.
File metadata
- Download URL: agenttape-0.1.0-py3-none-any.whl
- Upload date:
- Size: 72.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ab330edce3cf279f49123d50e0a004896d15b986838dcf65af3e5e21d9dbcd98
|
|
| MD5 |
6b8929555ec5b4958b5e71834b0972b6
|
|
| BLAKE2b-256 |
90b72d8a296203e6672e16f572341088b0d2bb21bdd259978fabb0bf3d624e7f
|
Provenance
The following attestation bundles were made for agenttape-0.1.0-py3-none-any.whl:
Publisher:
release.yml on MITHRAN-BALACHANDER/AgentTape
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
agenttape-0.1.0-py3-none-any.whl -
Subject digest:
ab330edce3cf279f49123d50e0a004896d15b986838dcf65af3e5e21d9dbcd98 - Sigstore transparency entry: 1847238323
- Sigstore integration time:
-
Permalink:
MITHRAN-BALACHANDER/AgentTape@6e6b7e6afe5e4d77d54be5b4147e6c8fdff03322 -
Branch / Tag:
refs/tags/v0.0.0 - Owner: https://github.com/MITHRAN-BALACHANDER
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@6e6b7e6afe5e4d77d54be5b4147e6c8fdff03322 -
Trigger Event:
push
-
Statement type: