Skip to content

Supervise LangChain and LangGraph agents

Trace LangChain chains and LangGraph graphs with OpenInference: each invocation becomes a run with its model calls, token counts, tool calls and graph steps.

Set it up

Recommended path: OpenTelemetry, with OpenInference's LangChain instrumentation. You need an agent credential from Dashboard, Agents: one credential per agent.

1. Install the instrumentation and an OTLP exporter

Shell
pip install openinference-instrumentation-langchain opentelemetry-sdk opentelemetry-exporter-otlp-proto-http

2. Point the exporter at Toolcaise

Environment
export TOOLCAISE_AGENT_TOKEN=...   # the agent's credential from Dashboard, Agents
export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://toolcaise.com/api/v1/otlp/v1/traces
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer%20$TOOLCAISE_AGENT_TOKEN"
export OTEL_EXPORTER_OTLP_COMPRESSION=gzip
export OTEL_METRICS_EXPORTER=none OTEL_LOGS_EXPORTER=none
# Keep prompts and outputs out of the export. Toolcaise never reads them either way.
export OPENINFERENCE_HIDE_INPUTS=true OPENINFERENCE_HIDE_OUTPUTS=true

3. Instrument before you build your chain or graph

LangChainInstrumentor hooks langchain-core, so it covers LangChain chains and agents and LangGraph graphs alike.

Python
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter

# Endpoint, credential and compression come from the OTEL_ environment variables above.
provider = TracerProvider()
provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter()))
trace.set_tracer_provider(provider)
from openinference.instrumentation.langchain import LangChainInstrumentor

LangChainInstrumentor().instrument(tracer_provider=provider)

# Build and invoke your chain or graph exactly as before, for example:
# graph = builder.compile()
# graph.invoke({"messages": [("user", "Summarise today's incidents")]})

Then run the agent as usual. Its runs appear in the dashboard as soon as their first report arrives.

What Toolcaise receives

How it arrives
RunsEach trace is one run. It is created when the first span arrives and completed, or failed, when the trace's root span ends.
Model callsLLM spans become model spans with the model name and the prompt and completion token counts the instrumentation reports (llm.token_count.*).
Tool callsTOOL spans become tool spans with the tool's name.
StepsChain, graph-node, retriever and agent spans become steps, so a LangGraph run shows its nodes in order.
FailuresA failed span in the trace adds an event that carries only the exception type, never its message.
Agent detailsservice.name, service.version and host.name describe the agent.

What this path does not give you:

  • Pause, cancel and approvals: OpenTelemetry only reports. Use the SDK's checkpoint() and guarded_action() for decisions.
  • Cost: Toolcaise does not price tokens on this path, and stores cost only when the instrumentation reports llm.cost.total.

Everything here is reported by your agent or its framework and stored as agent-reported. Prompts, completions and tool arguments are never read: the OpenTelemetry endpoint reads only an allow-list of attributes, and the SDK sends metadata only.

Other ways

Approvals and pauses: the SDK around the invocation

Wrap the call in a Toolcaise run and guard consequential tools. This reports a run of its own next to the trace's run; Toolcaise does not merge the two.

Python
from toolcaise_agent import Toolcaise

toolcaise = Toolcaise()

@tool
def send_invoice(customer_id: str, amount: float) -> str:
    """Send an invoice."""
    return toolcaise.guarded_action(
        f"Send an invoice for {amount:.2f}",
        {"customer": customer_id, "amount": amount},
        lambda approved: billing.send(approved["customer"], approved["amount"]),
    )

with toolcaise.run("billing-agent"):
    graph.invoke({"messages": [("user", "Invoice this month's customers")]})

Not recommended: LangSmith's OpenTelemetry mode

LangSmith can export OpenTelemetry too, but it labels retriever runs as embeddings and prompt-template runs as chat, so Toolcaise would count them as model calls.

Caveats

  • OpenInference captures prompts and outputs by default. The OPENINFERENCE_HIDE_ variables above stop that; OpenInference's configuration specification says they hide content, not token counts, but we have not run that combination end to end.
  • The TracerProvider flushes queued spans when the process exits normally; a process that is killed can lose its last few seconds of spans.
  • A trace whose root span belongs to another service never completes here, and its run is flagged as stalled after 30 minutes without updates.

What was checked

Checked on 2026-09-22 against openinference-instrumentation-langchain 0.1.76 (its source and documentation), langchain 1.4 and langgraph 1.2. Toolcaise's OTLP ingest was tested with real OpenInference output; this LangChain setup itself was not run end to end.

Reference: SDKs, HTTP API, and the OpenTelemetry endpoint's limits and answers.