Documentation

LangChain integration

AuditTrail traces LangChain apps through per-event callback handlers: every LLM call, tool invocation and chain becomes a span in the decision DAG, with token/cost accounting and constitutional rule evaluation.

There are three honest paths, depending on your language and where your agent runs relative to the AuditTrail server. Pick the row that matches:

Your setupUse
LangChain-JS / LangGraph-JS, any deploymentthe TypeScript callback handler (below) — streams spans over HTTP
Python + LangGraphrun_langgraph — one call emits the whole graph over HTTP
Python LangChain, agent on a different machine than AuditTrailthe OpenTelemetry path via OpenLLMetry — zero AuditTrail SDK
Python LangChain, agent co-hosted with a self-hosted AuditTrailthe embedded Python handler (below)

TypeScript / LangChain-JS

The TS SDK ships a duck-typed BaseCallbackHandler that carries LangChain's runId/parentRunId chain into the AuditTrail span tree and batch-flushes over HTTP:

ts
import { ChatOpenAI } from "@langchain/openai";
import { AuditTrailClient, AuditTrailCallbackHandler } from "@audittrail/sdk";
 
const audit = new AuditTrailClient({
  baseUrl: "https://your-audittrail-host",
  apiKey: process.env.AUDITTRAIL_API_KEY,   // sk-at-... from /profile → API Keys
});
 
const model = new ChatOpenAI({
  callbacks: [new AuditTrailCallbackHandler(audit)],
});

That's the whole integration — chains, agents, tools and retrievers all emit spans through the handler. The SDK has no runtime dependency on @langchain/core; it's shape-compatible with whatever version you run. (The SDK builds from packages/sdk-typescript in the repo — registry publishing is tracked for launch.)

Python, embedded (self-host)

The Python AuditTrailCallbackHandler is part of the in-process tracer: it emits into the same buffer as the @traceable decorator, which flushes directly to the AuditTrail database. That makes it the right tool when your agent runs inside your self-hosted AuditTrail environment (same process or same deployment with DB access) — and the wrong tool for a remote agent, where nothing would carry the spans across the network.

bash
cd apps/api && pip install -e ".[agent]"   # installs langchain-core alongside
python
from audittrail.callback_handler import AuditTrailCallbackHandler
from audittrail.traceable import traceable
 
@traceable(span_type="agent", name="handle_ticket")
async def handle_ticket(text: str) -> str:
    return await chain.ainvoke(
        {"input": text},
        config={"callbacks": [AuditTrailCallbackHandler()]},
    )

The handler reuses the ambient trace started by @traceable, so all LangChain activity lands under one root span; pass AuditTrailCallbackHandler(trace_id=...) to pin it explicitly.

Python, remote

For a Python LangChain agent talking to a remote AuditTrail server:

Gotchas

  • The Python handler is async (AsyncCallbackHandler) — use ainvoke/astream; sync invoke paths won't fire it.
  • Importing audittrail.callback_handler without langchain-core installed raises a clear ImportError pointing at the [agent] extra — it never fails silently at runtime.
  • Cost estimates come from the model-pricing catalog (~3k known models, operator-overridable via rules/pricing.yaml); unknown models fall back to the default rate.