Skip to Content

How do I see which step was slow in an agent built with LangChain?

Rius records every LangChain step as its own span, nested the way your chain or graph runs, so the slow step stands out in the trace. Open the trace in the waterfall or the map view and read the timing of each step. Steps that run outside LangChain’s callbacks need an observe span of your own.

How it works

The LangChain integration hooks LangChain’s callback system, so anything that runs through it is traced without extra code: LCEL chains, agents and LangGraph nodes. It records one span per step, typed by what the step is:

  • Chains arrive as CHAIN spans.
  • Tool invocations arrive as TOOL spans.
  • Retrievers arrive as RETRIEVER spans.
  • Model calls arrive as LLM spans with the model, token usage and messages. Rius computes the cost.

The nesting follows your chain structure, so a trace reads like your execution graph. A parent span covers its children, which lets you tell a slow step from a step that is only waiting on a slow child.

If you also install a client extra such as openai, LangChain’s chat model span wraps the client library’s span. You see the framework step and the client call nested together. Each model call is counted once in tokens and cost, and the LangChain span still shows the run’s total.

What the integration does not see is code that never goes through LangChain’s callbacks, such as a plain Python function you call between chain invocations. That function has no span until you wrap it with observe. A wrapped function you want to appear as a tool gets the TOOL kind. A bare observe makes a CHAIN span named after the function. Only a TOOL span appears when you filter by Tool in the Spans tab.

Set it up

  1. Install the instrumentation next to LangChain. In Python that is pip install "glassflow-rius[langchain]" langchain. The extra installs the instrumentation, not langchain itself. In TypeScript it is npm install @arizeai/openinference-instrumentation-langchain, and you also need @langchain/core, which a LangChain.js app already has.
  2. Call init() once, then build and run your chains exactly as before:
import rius rius.init(api_key="ri_...", service_name="my-agent") # build and run your chains exactly as before
  1. Run one chain that calls a model, then open the trace on the Traces page. The chain’s structure appears as nested spans, with the model call carrying model, tokens and cost.
  2. Find the slow step. In the trace, the waterfall shows the spans as a tree on a timeline, so the longest bar is the slow step. The header gives the duration of the whole trace. Switch to the Map tab and pick the latency lens to see where the time went at a glance. Clicking a node lands you on the tree filtered to that node’s spans.
  3. To compare steps across many runs, open the Spans tab, filter with the All kinds menu to Tool, LLM, Retriever or Chain, and click the Duration header to sort. The slowest steps of that kind come first.
  4. For a step that runs outside LangChain, wrap it with observe so it gets a span, and use the TOOL kind for a tool you trace yourself. The span then sits in the tree with its own timing.

The LangChain integration page covers setup in both languages. The Integrations overview explains how integrations are enabled with init(). Exploring traces covers the waterfall, map and Spans views in detail.

What you get

  • A nested trace that mirrors your chain or graph, with a span for each chain, tool, retriever and model call.
  • Timing for every step, visible as a bar in the waterfall and as a latency lens in the map view.
  • A sortable Duration column on the Spans tab, so you can rank the slowest steps of one kind across all your runs.
  • Token counts and cost on each model call, with a blank cost rather than $0 when a call reports no usage. Costs are list-price estimates in US dollars.
  • A context growth strip above the tree for traces with several model calls. It shows input tokens per call in order, which helps when a step is slow because the prompt keeps growing.
  • Retry chains collapsed into one row, so a step that is slow because it retried reads as one event.

For the wider picture of watching agents after release, see Monitor AI agents in production.

When something else fits

  • If the slow part is code that LangChain does not call through its callbacks, add an observe span around it. The integration alone leaves a gap in the tree.
  • If you want to see which steps are slow across many runs instead of one trace, use the Spans tab sort, or the version comparison on the Agents page, rather than reading single traces.
  • If you need to know a streamed model call’s time to first token, check the span in question, because some streams carry none.

Still stuck? Get help

Last updated on