Skip to main content

Local-first AI debugging tool for capture, replay, diff, and explanation.

Project description

Notrix Trax

Debug non-deterministic AI workflows — deterministically.

Trace what happened. Diff what changed. Replay where it broke.

pip install notrix-trax

Why debugging AI systems is broken

You changed nothing. But your AI system behaves differently.

  • different answer
  • different retrieval
  • different agent path

Why?

Logs tell you what ran. They don’t tell you:

  • what actually changed
  • where the divergence happened
  • why the outcome is different

AI systems are non-deterministic and structurally opaque.

Debugging them shouldn’t be.


What Trax Does

Trax converts raw execution signals into a canonical execution graph — a structured, provider-agnostic DAG of steps and edges with stable identity across runs.

From that graph, Notrix trax provides four core operations:

Operation What it answers
inspect What happened in this run, structurally?
diff What changed between run A and run B?
replay Can I simulate replay of the relevant part, safely?
explain What is the evidence-grounded explanation for this failure?

Every insight is derived from the same canonical graph. Nothing is inferred from display hierarchy or log ordering.


When to use Trax

Use Trax if:

  • your LLM output changed and you don’t know why
  • retrieval returns different documents
  • agent behavior is inconsistent

Not for:

  • metrics dashboards
  • latency monitoring

What you get

  • Deterministic execution graph
  • Step-level diff between runs
  • Replay from failure point
  • Evidence-grounded explanations

All derived from the same canonical structure.


Trax vs Observability Tools

Feature Notrix Trax Observability tools
Structural diff
Replay simulation
Failure explanation
Logs / traces

Quickstart

python examples/hero_diff_replay.py

trax list
trax inspect <run_id>
trax diff <run_a> <run_b>
trax explain <run_id>
trax replay <run_id> --start-at step_4 --stop-at step_8

Trax stores metadata in local SQLite and artifacts on the filesystem (TRAX_HOME, default: ~/.trax). No external services required.


Hero Example

Two runs of your RAG pipeline return different answers. You want to know exactly where they diverged.

trax diff run_1 run_2

See the difference immediately

trax diff screenshot

trax explain run_2

trax explain screenshot

Structural, grounded, reproducible.


Capture

Drop-in adapters

from trax.adapters.openai import traced_chat
from trax.adapters.retrieval import traced_retrieval

docs = traced_retrieval(
    query="what is trax?",
    top_k=2,
    backend="simple_vector",
    retrieve=lambda **_: [{"id": "doc-1", "text": "Trax debugs AI runs."}],
)

response = traced_chat(
    model="gpt-4.1-mini",
    messages=[{"role": "user", "content": "Summarize Trax."}],
    call=lambda **_: {"output_text": "Trax is a local-first AI debugger."},
)

Manual SDK

from trax import run, step, traced_step

@traced_step("prepare", attributes={"semantic_type": "transform"})
def prepare_question(text: str) -> dict[str, str]:
    return {"normalized_question": text.strip().lower()}

with run("my-flow", input={"question": "What does Trax do?"}):
    question = prepare_question("What does Trax do?")
    with step("answer", input=question, attributes={"semantic_type": "llm"}) as s:
        s.set_output({"answer": "Trax debugs AI workflows locally."})

LangGraph (first-class support)

Invocation-level and node-level tracing with no dependency on internal callbacks. Works with real compiled graphs.

from trax.langgraph import traced_invoke
from langgraph.graph import StateGraph

graph = StateGraph(MyState)
# ... define nodes and edges ...
compiled = graph.compile()

result = traced_invoke(compiled, {"question": "What does Trax do?"})

CLI Reference

trax list                              # list all captured runs
trax inspect <run_id>                  # inspect a run's canonical graph
trax diff <run_id_1> <run_id_2>        # structural diff between two runs
trax replay <run_id>                   # simulate replay of a run under persisted safety policy
trax replay <run_id> --start-at <step> --stop-at <step>  # partial replay
trax explain <run_id>                  # evidence-grounded failure explanation
trax import-otel trace.json            # import an OpenTelemetry trace

How It Works

Trax builds a canonical execution graph — not a trace, not a log, not a span tree.

Capture → Collect → Normalize → Graph → Diff / Detect / Replay → Explain

The key properties that make this useful for debugging:

Stable step identity. The same logical step normalizes to the same canonical meaning across runs. This makes structural diffing possible — you're comparing the same thing, not two different representations of it.

Edge-driven structure. Relationships between steps are derived from persisted graph edges and deterministic fallback rules. There are no implicit structural relationships from display hierarchy.

Provider-agnostic adapters. Different framework or provider integrations emit signals that normalize into the same canonical step model, so diffs and replay stay meaningful across tool boundaries.

Display hierarchy is not structure. Scope hints and nesting from adapters are stored as metadata only. They influence how things look, not how the graph is built.


Core Concepts

Concept Definition
Run A single captured execution instance
Step A canonical, normalized unit of work (e.g., llm:call, retrieval:query)
Edge A directional canonical relationship between steps
Artifact Input/output data associated with a step
Failure A detected issue localized to a specific step in the graph

Step names follow the format <domain>:<operation>. Current surfaced domains include llm, retrieval, tool, agent, reasoning, transform, io, rerank, and unknown.


Examples

Example What it demonstrates
examples/basic_capture.py Minimal manual SDK capture
examples/rag_failure/ Retrieval divergence across two runs
examples/agent_loop/ Structural path divergence in an agent loop
examples/langgraph_basic.py Real LangGraph execution with node-level tracing
python examples/hero_diff_replay.py

Development

git clone https://github.com/notrix-dev/notrix-trax.git
cd notrix-trax
pip install -e .
pip install -r requirements.txt
pytest

See CONTRIBUTING.md for how to build adapters, improve the core system, or contribute to the spec.


Project Structure

trax/
  adapters/       # capture layer — framework integrations
  normalize/      # canonical step meaning
  graph/          # structural edge construction and validation
  replay/         # deterministic replay engine
  diff/           # two-run structural comparison
  detect/         # single-run failure detection
  cli/            # projection layer

docs/             # system and subsystem specifications
examples/         # runnable demos

Spec-Driven Design

Trax is architecture-first. The system behavior is defined in a set of layered specifications:

  • docs/system-spec.md — authoritative system contract
  • docs/spec-graph.md — canonical graph model
  • docs/spec-normalizer.md — step semantics and naming
  • docs/spec-diff-detect.md — diff and detect contract
  • docs/spec-replay.md — replay contract
  • docs/spec-adapter.md — adapter contract

If you want to understand why the system is designed the way it is, the specs are the place to start.


License

Apache License 2.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

notrix_trax-0.1.0.tar.gz (54.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

notrix_trax-0.1.0-py3-none-any.whl (56.6 kB view details)

Uploaded Python 3

File details

Details for the file notrix_trax-0.1.0.tar.gz.

File metadata

  • Download URL: notrix_trax-0.1.0.tar.gz
  • Upload date:
  • Size: 54.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.3

File hashes

Hashes for notrix_trax-0.1.0.tar.gz
Algorithm Hash digest
SHA256 adce30ba48d9aa880e66c56ce8f38a411eac21e54e33a1b1e8541dd45e3db996
MD5 fb8730fa478a2d10e3f489a5d0eea153
BLAKE2b-256 6b8d62b5a6af989203c8c57fc0b731c217bc900417208caff9b9107e0308c146

See more details on using hashes here.

File details

Details for the file notrix_trax-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: notrix_trax-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 56.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.3

File hashes

Hashes for notrix_trax-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b77ec9b7b7028eada9a651a10636fe586e424538a93dbbad646c2f92b539762b
MD5 79c2f811fa4f7dd583aa9a9348d9f38a
BLAKE2b-256 6ea0be611eb4cd49dd3e3013a5bbcdf0ea4fe2cb0eb4d60cf43805fbb8d5091a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page