Documentation

LangGraph integration

LangGraph is AuditTrail's most complete integration: one helper call runs your compiled graph and emits the full span tree — orchestrator root, LLM turns, a grouped tool phase with one span per tool call, and the final response turn — with automatic timing, token and cost accounting.

This is the integration the quickstart's starter template is built on.

Install

From a checkout of the repo:

bash
pip install -e packages/sdk-python

(or start from the pre-wired template on the Quick Start page — Download ZIP, add keys, run.)

One call, whole graph

python
import asyncio
from audittrail import AuditTrailClient
 
async def main() -> None:
    agent = build_graph()   # your compiled LangGraph graph
 
    async with AuditTrailClient(
        api_base="https://your-audittrail-host",
        api_key="sk-at-...",
        agent_name="research-agent",
        environment="development",
    ) as client:
        result = await client.run_langgraph(
            agent,
            inputs={"messages": [("user", prompt)]},
            user_prompt=prompt,
            model="gpt-4o-mini",
        )
 
    print(result.trace_id, result.response, result.tool_calls)
 
asyncio.run(main())

run_langgraph streams agent.astream_events(version="v2") and builds a three-level hierarchy:

agent_orchestrator                 (root agent span)
├── parse_user_intent / chain_of_thought   (LLM spans)
├── execute_tools                          (phase group)
│   ├── web_search                         (tool span)
│   └── calculator                         (tool span)
└── generate_response                      (final LLM turn)

It returns a LangGraphRunResult with trace_id, response, steps, tool_calls, duration_ms, and error — agent exceptions (including GraphRecursionError) are captured into .error and the orchestrator span is always closed, so a failing run still produces a complete, inspectable trace.

Useful knobs:

  • recursion_limit=60 — passed through to LangGraph (its own default of 25 is too low for research-style prompts).
  • on_step=fn — sync or async callable invoked per streamed event, for your own logging without re-parsing the stream.
  • verbose=True — prints a run banner, per-step lines, and the trace URL when the run finishes.

Working examples in the repo

  • examples/langgraph-agent/ — minimal template (the quickstart ZIP).
  • examples/deep-search-agent/ — a real multi-tool research agent: tool definitions + graph wiring + one async with AuditTrailClient block; ~280 lines of actual user code.

Alternative: the callback handler

If you want spans to reflect LangGraph's raw event structure instead of the phase-grouped tree, pass the LangChain callback handler in your graph's config — both approaches share the same ingest pipeline.

Gotchas

  • Your graph must support astream_events(version="v2") (LangGraph ≥ 0.1 compiled graphs do).
  • The client is an async context manager — spans batch-flush on exit; if you construct it without async with, call await client.close().
  • Live streaming: spans appear in the dashboard as the agent runs — open /traces/<trace_id> mid-run and watch the DAG fill in. When the orchestrator span closes, the server broadcasts trace_complete and the status badge flips to Complete without a refresh.