Skip to main content

graphtrace

Regression testing for LangGraph agents — as a pytest plugin.

CI License: Apache 2.0 Python 3.10+ Status: v0.1 complete

The problem

A LangGraph agent with branches, retries, and tool calls can look fine on a lucky run while silently changing how it got there — a node path that changed, a retry that's now firing on every single call, a tool call that quietly stopped happening, a human-approval gate the agent learned to route around. A test that only checks the final answer text can't catch any of that, because the final answer can still look right while the path that produced it is wrong, expensive, or unsafe.

graphtrace makes that path a first-class, assertable thing — the same way a web framework lets you assert on a response's status code and headers, not just the rendered HTML.

What it does

  • run_graph(graph, inputs, ...) — drives a real compiled LangGraph and records every node visited, every state change, and every tool/LLM call into a Trajectory. No code changes to the graph under test; interception happens entirely through patching, undone automatically when the run ends. Subgraphs are handled transparently (inner nodes show up as their own steps, bracketed by subgraph_enter/subgraph_exit), not collapsed into one opaque step that would silently drop their LLM/tool calls.
  • A small, readable assertion API, 12 functions — assert_path, assert_visited/assert_visits, assert_state/assert_state_at, assert_tool_called/assert_tool_not_called, assert_tool_calls_match (strict/unordered/subset/superset), assert_retries, assert_interrupted_at, assert_budget. Every failure raises with a readable diff, not a repr of two values.
  • Record/replay cassettes — a run's LLM and tool calls are recorded to YAML once, then replayed with zero real calls on every CI run after that. record / replay / record_missing / live modes, set via the GRAPHTRACE_MODE env var or pytest --gt-mode=<mode>.
  • An LLM-as-judge contract with calibration — a rubric-graded verdict via litellm (any provider), cached in the same cassette mechanism as any LLM/tool call, plus graphtrace calibrate scoring the judge against a human-labelled set (agreement % and Cohen's kappa per criterion). Verified against a real, live Groq model, not just a faked one.
  • Trace-to-test — graphtrace from-trace export.json --target my_app.graph:build_graph turns a real production trace export (Langfuse/OTel/LangSmith) into a cassette + a generated pytest file, with an honest assert_visited-based assertion (not an overclaimed exact path) and a # TODO marker for what should actually happen.
  • A static HTML report with a real go/no-go executive summary — pytest --gt-report=report.html renders a release verdict (READY / NOT READY, N blocking issues), blocking issues ranked by severity with plain-language descriptions (@pytest.mark.graphtrace(description=..., severity=..., category=...)), and a coverage breakdown by category — the layer a QA lead, manager, or auditor actually needs, not just an engineer. The full per-test trajectory tree, judge verdicts, and cost/latency totals are still there, collapsed below. XSS-safe by construction (Jinja2 autoescape=True), no server.
  • Cost, latency, and token budgets as assertions — assert_budget(traj, cost_usd=0.05, latency_s=8) fails the same way a path or tool-call assertion does, computed from real recorded usage, never an estimate.
  • pytest-native, plus a real CLI — pip install registers the plugin automatically (confirmed from a real built wheel, not just an editable install) and installs a graphtrace console command (from-trace / calibrate / report). A run_graph fixture is available in any test with no -p flag, and auto-applies a project's configured default budget even if the test itself never calls assert_budget.

Example

Real, runnable code — not pseudocode — against examples/refund_agent, the bundled demo agent (router -> lookup_order -> human_approval -> refund, using LangChain's own fake chat model, so this needs no API key):

from graphtrace import assert_path, assert_tool_called, run_graph

# First run: records real calls to tests/cassettes/refund_happy_path.yaml
traj = run_graph(
    graph, {"order_id": "1234"},
    cassette="tests/cassettes/refund_happy_path.yaml",
    mode="record",
    resume=[True],  # supplies the human-in-the-loop approval the graph pauses for
)

assert_path(traj, ["router", "lookup_order", "human_approval", "refund"])
assert_tool_called(traj, "get_order", args_match={"order_id": "1234"})

Change mode="record" to mode="replay" on a later run and the exact same assertions pass with zero real LLM or tool calls — proven in this repo's own test suite by patching the real underlying LangChain methods to raise if they're ever actually reached.

The CLI, against a real exported trace and a real judge:

# A production trace export -> a cassette + a generated pytest file
graphtrace from-trace prod_export.json --target my_app.graph:build_graph

# Score an LLM-as-judge against a human-labelled set (real agreement %, real Cohen's kappa)
graphtrace calibrate --rubric refund_reply

# Every test's trajectory, judge verdicts, and cost/latency totals -> one static HTML page
pytest --gt-mode=replay --gt-report=reports/graphtrace.html

Supported frameworks

Framework Status
LangGraph ✅ Built (v0.1)
CrewAI Planned — v0.4
AutoGen Planned — v0.4

The recording layer is built behind a FrameworkRunner protocol specifically so CrewAI/AutoGen support (v0.4) is a new package later, not a rewrite of this one — see Multi-framework support.

Installation

Not yet published to PyPI — install from source:

git clone https://github.com/devbyanoop/graphtrace.git
cd graphtrace
python -m venv .venv
source .venv/bin/activate   # Windows (Git Bash): source .venv/Scripts/activate

pip install -e ".[dev]"

See Installation for the full breakdown, including the docs extra for building the documentation site locally.

Quickstart

The bundled demo agent needs no vector database, API key, or setup of your own:

pytest tests/test_demo_agent.py -v

Full walkthrough — building a Trajectory by hand, running it against the real demo agent, and what happens on an unresolved interrupt — in Quickstart.

Pointing this at your own LangGraph agent is a matter of calling run_graph(your_compiled_graph, your_inputs, cassette=...) in your own test, not a framework migration.

Documentation

Full guide (core concepts, every assertion, recording & replay, judge & calibration, trace-to-test, report & CI, configuration, the CLI, the roadmap) lives under docs/ — build it locally with mkdocs serve, or browse the Markdown directly on GitHub.

Project status

v0.1 is complete — 222 tests pass, full regression. The core Trajectory model, the full 12-function assertion API, the real LangGraph recording layer (including subgraphs), record/replay cassettes, the judge contract with calibration (verified against a real live model), trace-to-test from a production export, a real graphtrace CLI, the HTML report, and CI are all built and verified — not just against mocks and hand-built fixtures, but against real upstream sources (confirmed real litellm/Groq calls, the real openinference-semantic-conventions source, a real wheel build in a genuinely isolated clean venv). Beyond the bundled demo agent, graphtrace has also been run against two real, official external LangGraph apps — langchain-ai/langgraph-swarm-py and langchain-ai/deepagents — across 25 real scenarios spanning ten distinct categories (handoff, delegation, permissions, safety, and more), which found and fixed four real bugs this project's own demo agent never could have surfaced. See Roadmap & status for the full, honest account of each one. v0.2 (security test pack, observability export, cut-point replay, statistical live-mode verification) and v0.4 (CrewAI/AutoGen support) are designed but not started.

Contributing

Issues and PRs welcome. See Contributing for how the test suite and docs policy work.

License

Apache License 2.0 — see LICENSE.

Copyright 2026 Anoop Singh.

Metadata

Release files for graphtrace 0.1.0

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

Source distribution (sdist)

Source distribution for graphtrace 0.1.0
File Size Uploaded Provenance
graphtrace-0.1.0.tar.gz 166.5 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for graphtrace 0.1.0
File Interpreter ABI Platform
graphtrace-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 244.7 kB

Release files / graphtrace-0.1.0.tar.gz

Download URL graphtrace-0.1.0.tar.gz
Size 166.5 kB
Tags Source
SHA-256 checksum
How to use checksums
28d565e4a83d2d801ee67c13cd3bc0ce5c000f41a4ff0fafe1043732e3236ff0
BLAKE2b-256 checksum
How to use checksums
07bd6c8c4be44f73b33e19affb5f1f22e5f8880c0e44061807377006fadfbb01
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.

Transparency log

Release files / graphtrace-0.1.0-py3-none-any.whl

Download URL graphtrace-0.1.0-py3-none-any.whl
Size 78.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c9193149a8e7b49eaf54e6a059de77a58440afff80f03594861a65876b877837
BLAKE2b-256 checksum
How to use checksums
801f294c3af1c1ff722f5d9e2668cae7768ba3f75fc9d9154373fbf56f3db77b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.

Transparency log

Security for graphtrace 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for graphtrace-0.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files Full provenance

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