Skip to main content

Record, replay, and diff AI agent executions. Local-first.

Project description

TraceFlowLens

Record, replay, and diff AI agent executions, local-first.

Why

AI agents fail non-deterministically and the failure is hard to reproduce. TraceFlowLens records every model call, tool call, and error to a local SQLite file as your agent runs. Replay re-runs your own code, answering every recorded call with the saved output, so you can reproduce a failure exactly and prove a fix.

Install

pip install traceflowlens

Requires Python 3.11 or later. Zero runtime dependencies.

Quickstart

The script below runs without any AI SDK installed. FakeClient stands in for a real openai.OpenAI() or anthropic.Anthropic() client.

import traceflowlens as tfl


# Stand-in for a real OpenAI or Anthropic client (no SDK required).
class _FakeResponse:
    def __init__(self, content):
        self._content = content

    def model_dump(self):
        return {"choices": [{"message": {"content": self._content, "role": "assistant"}}]}


class _FakeCompletions:
    def create(self, **kwargs):
        return _FakeResponse("Hello from the fake model.")


class _FakeChat:
    def __init__(self):
        self.completions = _FakeCompletions()


class FakeClient:
    """Minimal stand-in for openai.OpenAI() with chat.completions.create support."""

    def __init__(self):
        self.chat = _FakeChat()


def run_agent(ctx, client):
    wrapped = ctx.wrap(client)
    response = wrapped.chat.completions.create(
        model="fake-model-v1",
        messages=[{"role": "user", "content": "Hello"}],
    )

    with ctx.step("tool_call", "web_search", inputs={"query": "TraceFlowLens"}) as step:
        step.set_output({"results": ["https://example.com"]})

    ctx.log_step(
        "custom",
        "agent_decision",
        inputs={"candidates": 3},
        outputs={"chosen": 0},
    )
    return response


client = FakeClient()

# Record
with tfl.record("my-run") as trace:
    trace_id = trace.trace_id
    run_agent(trace, client)

print(f"Recorded trace: {trace_id}")

# Replay
with tfl.replay(trace_id) as session:
    run_agent(session, client)

print(f"Replay complete: {session.result}")

Wrapping real clients

Call trace.wrap(client) to get a recording proxy. The proxy intercepts the supported methods and records each call as a step.

import openai
import anthropic
import traceflowlens as tfl

openai_client = openai.OpenAI()
anthropic_client = anthropic.Anthropic()

with tfl.record("my-run") as trace:
    oai = trace.wrap(openai_client)
    ant = trace.wrap(anthropic_client)

    # Intercepted and recorded:
    oai.chat.completions.create(model="gpt-4o", messages=[...])
    oai.responses.create(model="gpt-4o", input="Hello")
    ant.messages.create(model="claude-sonnet-4-6", max_tokens=1024, messages=[...])

Supported methods:

  • OpenAI: chat.completions.create, responses.create
  • Anthropic: messages.create

Sync only. Passing stream=True raises StreamingNotSupportedError. Calling any other method passes through to the real client with a one-time warning.

During replay, use session.wrap(client) in exactly the same way. The proxy intercepts the same methods and returns the recorded outputs without calling the real API.

Replay semantics

Replay matches recorded steps in strict sequence order by kind and name. Any call-order change raises ReplayDivergence at the first divergence point, carrying the exact position, what was expected, and what was received. That pinpoint is the debugging value: the divergence tells you exactly where your fix changed behavior.

Input drift (different arguments to the same call) is recorded on ReplayResult.input_drift but is not fatal by default. Pass strict_inputs=True to tfl.replay(...) to raise ReplayDivergence on any input change.

For model calls from the OpenAI or Anthropic SDKs, replay reconstructs the typed response object using model_validate. If the SDK is not installed or the saved data no longer validates, ReplayReconstructionError is raised. Pass allow_degraded=True to get a raw dict instead of an error.

Replay never writes to the recording.

CLI

The tfl command operates on the local database. Default path: ./traceflowlens.db. Override with --db PATH.

tfl list                      List all traces (id, name, status, started_at, step count).
tfl show TRACE_ID             Show trace header and step table with DEGRADED flags.
tfl replay TRACE_ID           Print a replay readiness report (not re-execution).
tfl diff TRACE_A TRACE_B      Print a step-by-step structural diff of two traces.
tfl delete TRACE_ID [--yes]   Delete a trace; prompts for confirmation without --yes.

Note: tfl replay prints a readiness report. Actual replay is done via the library: with traceflowlens.replay(trace_id) as session:.

Data

Traces are stored in a local SQLite file (./traceflowlens.db by default). Override the path with the db_path parameter on tfl.record(...) and tfl.replay(...), or with --db on the CLI.

Full inputs and outputs are recorded by design. Nothing leaves your machine.

Scope (v1)

TraceFlowLens v1 is sync only. Async is not supported. Streaming is not supported. There are no framework adapters (LangChain, LangGraph, CrewAI, etc.) and no hosted service. These are current facts about this release, not items on a roadmap.

Versioning

Current version: 0.1.0. TraceFlowLens follows SemVer. Before 1.0, minor version increments may include breaking changes.

License

MIT

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

traceflowlens-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.

traceflowlens-0.1.0-py3-none-any.whl (21.3 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: traceflowlens-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.12.3

File hashes

Hashes for traceflowlens-0.1.0.tar.gz
Algorithm Hash digest
SHA256 314b5029b30274c7166fdcdaa8459152d80eec246d844b496cf6fe865a8abdcb
MD5 2a9384a7e00398736a2011c119ba9d08
BLAKE2b-256 144642f3fbdd4381ccbc46ac4a65408ecea9fd25b80ef0b3731852fa276caef1

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for traceflowlens-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e790604d2097968ffdc37dc78d602e0ae61b36ce202ada71552fe153c593c41a
MD5 7eb0135b2b74ccad3cba90a25133912a
BLAKE2b-256 500bfbb2434ca72e73bc6785ec2bc3d9fe09e0a4e6c94691d41a5aad9c1a22bb

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