Observed since 20 Oct, 23:02 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
Pytest for AI agents — record, score, replay, regress. Vendorable, judge-agnostic, domain-neutral. (Placeholder release; full library coming soon.)
Pytest for AI agents. Record trajectories, score them with any LLM judge, replay counterfactuals, and gate your CI with statistical rigor — no server, no SaaS, no vendor lock.
pip install agentpytest
agentpytest is a pytest plugin that turns agent behavior into regression tests. It records each run as a JSON cassette, scores trajectories with an LLM judge of your choice (Anthropic, OpenAI, Gemini, Groq, Llama, local Ollama — anything LiteLLM supports), and tells you whether a change is a real regression or stochastic noise.
It works for any agent in any domain — coding agents, SRE runbooks, sales outreach, healthcare scheduling, finance automation. You write the agent once, point agentpytest at it, pick a judge, and you have regression tests.
from agentpytest import trajectory_test, Judge
from agentpytest.scorers import goal_completion, right_tool, redundant_call
judge = Judge("gemini/gemini-2.5-pro")
@trajectory_test(cassette="cassettes/refactor.json", epochs=5)
def test_refactor():
result = my_agent("Refactor auth.py to use TokenStore")
assert goal_completion(result, judge=judge).value > 0.8
assert right_tool(result, judge=judge).value > 0.9
assert redundant_call(result).value < 0.1
pytest # diffs against cassette, fails on regression
pytest --update-trajectories # regenerate cassette after intentional changes
agentpytest regress \
--baseline runs/main.json \
--candidate runs/pr-412.json # CI gate with p-value + effect size
The agent-eval ecosystem has converged everywhere except the test layer:
| Layer | Owned by |
|---|---|
| Model abstraction | LiteLLM |
| Trace storage + UI | Phoenix, Langfuse, Weave |
| Benchmarks / leaderboards | Inspect AI, SWE-bench, τ-bench |
| Hosted eval platforms | Braintrust, LangSmith, Patronus |
| The pytest layer in your repo | agentpytest |
agentpytest fills the missing slot. It's the thing you pip install and run locally — like pytest, like mypy, like any other dev tool you'd commit alongside your code.
pip install, write tests, commit cassettes to git. No telemetry, no account, runs offline.fork_from(cassette, span_id, mutate) replays a trajectory up to step N, mutates one tool response, and runs the agent forward — debug "what if this tool had failed" without rerunning the whole trace.| Feature | agentpytest | Inspect AI | Phoenix | Braintrust | DeepEval | LangSmith | Ragas |
|---|---|---|---|---|---|---|---|
| Pytest-native, vendorable, no server | ✅ | ⚠️ harness | ❌ | ❌ SaaS | ✅ | ❌ SaaS | ✅ |
| Cassette record/replay with tool-lock | ✅ | ⚠️ cache | ❌ | ❌ | ❌ | ❌ | ❌ |
| Mutate-and-replay debugging | ✅ | ❌ | ⚠️ prompt-only | ❌ | ❌ | ❌ | ❌ |
| Statistical CI gate | ✅ | ⚠️ epochs | ❌ | ✅ paid | ❌ | ⚠️ paid | ❌ |
| Eval on YOUR repo's past PRs | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Any judge (~100 providers) | ✅ | ✅ | ⚠️ | ⚠️ | ⚠️ | ⚠️ | ⚠️ |
| Judge ensemble + variance signal | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| TRAIL failure-mode detectors | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
Same library, different rubrics:
| Domain | Example test |
|---|---|
| Coding agents | assert diff_minimality(r, judge=judge).value > 0.8 |
| SRE / incident response | assert dependency_order(r, expected_dag=runbook).value == 1.0 |
| Outbound sales | assert can_spam_compliance(r, judge=judge).value > 0.95 |
| Healthcare scheduling | assert phi_leak_check(r, judge=judge).value == 1.0 |
| Finance / spend | assert policy_adherence(r, judge=judge, policy=spend_policy).value > 0.99 |
Built-in coding-agent harness on day one; Harness plugin interface for SRE / sales / healthcare / finance harnesses (pagerduty, salesforce, epic, netsuite) shipping as separate packages.
| Required | Optional |
|---|---|
| An agent function | Expected tool sequence |
| A task / prompt | Custom rubric text |
| A judge model + key | Past PR list (for repo harness) |
| Domain policy documents |
No labeled corpus. The cassette is the ground truth, captured from the first run you accept. The judge evaluates against rubrics, not strings.
pip install agentpytest
export ANTHROPIC_API_KEY=... # or OPENAI_API_KEY, GEMINI_API_KEY, etc.
# tests/test_my_agent.py
from agentpytest import trajectory_test, Judge
from agentpytest.scorers import goal_completion
judge = Judge("anthropic/claude-sonnet-4-6")
@trajectory_test(cassette="cassettes/hello.json", epochs=3)
def test_hello():
result = my_agent("greet the user politely")
assert goal_completion(result, judge=judge).value > 0.8
pytest tests/test_my_agent.py
First run records the cassette. Future runs diff against it.
Runnable example repos, one per domain:
agentpytest-examples-coding — Claude Code-style agentagentpytest-examples-sre — incident-response agentagentpytest-examples-sales — outbound prospectingagentpytest-examples-healthcare — appointment bookingagentpytest-examples-finance — expense classificationv0.1.0-alpha — core (trajectory_test, cassettes), 5 scorers (goal_completion, right_tool, right_args, redundant_call, dependency_order), regression_test, OTel export. Roadmap in ROADMAP.md.
MIT. No CLA. Fork freely.
Issues and PRs welcome. See CONTRIBUTING.md. One rule: no PR that adds a server, dashboard, or hosted feature. This stays a library.
Built on the shoulders of LiteLLM, agent-vcr, pytest, and OpenTelemetry. TRAIL detector taxonomy inspired by Patronus AI's published research.
Download counts and popularity will appear here as the collector receives them.
| Version | Published | Direct dependencies | Open version |
|---|---|---|---|
| 0.0.0 | 29 Apr 2026 | 0 |
This describes our collected data; it is not a security assessment.
Shared repository data · GitHub
Observed since 20 Oct, 23:02 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:0a0aaec34052789bb3c2914bb2c96cd61cade9d797433330766c586c178cc26c