Skip to main content
This is a Custom Integration library. If you’re using LiveKit, use the built-in LangChain / LangGraph observability support in the Tuner LiveKit plugin instead.

What it does

Every call has two layers:
  • Voice layer: STT hears the user and TTS speaks the reply (your transport). You already track this.
  • Brain layer: LangGraph decides which step runs next, and LangChain runs the LLM and tools inside each step. This is invisible unless you instrument it.
tuner-langchain makes the brain layer visible. Instead of hand-wrapping every node and tool, you attach one callback handler to graph.invoke(). It records node transitions, timing, and tool calls automatically. At hang-up you format those events and include them in your Create Call payload.
The library owns brain-layer tracing. You still own the voice transport and the API POST.

How it works

Three pieces do the work. A simple way to picture them:
  1. Handler (TunerLangGraphHandler or TunerLangChainHandler): a LangChain callback. You pass it to invoke() and never call its methods yourself.
  2. Accumulator (TunerAccumulator): one per call. It stores every event the brain layer produced. Read it back with get_invocations().
  3. Segment builder (segments_from_invocation()): converts one turn’s events into Tuner transcript rows, with timestamps as milliseconds since call start.
One handler sees both frameworks. LangGraph is built on LangChain, so a single handler on graph.invoke() captures the graph’s nodes and the LLM/tool calls nested inside them, with no extra wiring per LLM.

Install

Requires Python ≥ 3.10 and langchain-core ≥ 1.0 (langgraph ≥ 1.0 for graphs). Pin a version in production. See the package on PyPI.

The flow

You touch the library at three moments in a call: set up once, attach the handler on every turn, then format and send when the call ends.
1

Set up once per call

Create one accumulator (the notebook) and one handler (the ears).
2

Attach the handler on every turn

Pass the handler in config each time you run the graph or chain. This is the only wiring you add.
3

Format and send when the call ends

Turn the captured events into transcript rows, merge them with your own voice turns, and POST.
Then include transcript in your Create Call request.

Data privacy

By default the library forwards prompts, inputs, and tool payloads. To keep sensitive data out, pass a CaptureConfig to the accumulator:
Tool error output is always captured, regardless of tool_outputs. Errors aren’t treated as sensitive and are needed for debugging.

Public API


Minimal starter


Next steps

Custom Integration

Create Call API Reference