Open-Source Wikis

/

LangChain

/

Primitives

/

Callbacks and tracers

langchain-ai/langchain

Callbacks and tracers

The observability backbone. Every Runnable, model, tool, and chain emits events that flow through CallbackManager to registered handlers. Tracers turn those events into the run trees you see in LangSmith. Source: libs/core/langchain_core/callbacks/ and libs/core/langchain_core/tracers/.

Purpose

When a chat model produces a response, that single event has many observers:

  • The agent tracking token usage.
  • The retry handler counting failures.
  • LangSmith logging the input, output, and timing.
  • A user-supplied logger printing to the console.
  • A custom listener feeding metrics to Prometheus.

BaseCallbackHandler defines the events; CallbackManager dispatches them; BaseTracer is a callback handler that builds a tree of runs for export to LangSmith.

Directory layout

libs/core/langchain_core/callbacks/
├── __init__.py
├── base.py                  # BaseCallbackHandler, AsyncCallbackHandler
├── file.py                  # FileCallbackHandler
├── manager.py               # CallbackManager and the dispatch machinery (~90 KB / ~2,800 lines)
├── stdout.py                # StdOutCallbackHandler
├── streaming_stdout.py      # StreamingStdOutCallbackHandler
└── usage.py                 # UsageMetadataCallbackHandler

libs/core/langchain_core/tracers/
├── __init__.py
├── _compat.py
├── _streaming.py
├── base.py                  # BaseTracer (the run-tree builder)
├── context.py               # tracing_v2_enabled context manager
├── core.py
├── evaluation.py
├── event_stream.py          # The astream_events backend (~36 KB)
├── langchain.py             # LangChainTracer (sends to LangSmith)
├── log_stream.py            # RunLog / RunLogPatch event streams
├── memory_stream.py
├── root_listeners.py        # on_start / on_end / on_error listeners
├── run_collector.py         # Collect runs in-memory for tests
├── schemas.py
└── stdout.py                # ConsoleCallbackHandler

Key abstractions

Symbol File Description
BaseCallbackHandler libs/core/langchain_core/callbacks/base.py Methods: on_llm_start, on_llm_new_token, on_llm_end, on_chain_start, on_chain_end, on_tool_start, on_tool_end, on_retriever_start, on_retriever_end, plus *_error and async variants
AsyncCallbackHandler libs/core/langchain_core/callbacks/base.py Async-only handler
CallbackManager, AsyncCallbackManager libs/core/langchain_core/callbacks/manager.py Top-level dispatch; constructed from RunnableConfig.callbacks
CallbackManagerForLLMRun, CallbackManagerForChainRun, CallbackManagerForToolRun, CallbackManagerForRetrieverRun libs/core/langchain_core/callbacks/manager.py Per-run dispatchers handed to _generate, _call, etc.
StdOutCallbackHandler, StreamingStdOutCallbackHandler libs/core/langchain_core/callbacks/stdout.py, streaming_stdout.py Print events to stdout
UsageMetadataCallbackHandler libs/core/langchain_core/callbacks/usage.py Aggregate token usage across a run
BaseTracer libs/core/langchain_core/tracers/base.py Build a tree of runs
LangChainTracer libs/core/langchain_core/tracers/langchain.py Send the tree to LangSmith
ConsoleCallbackHandler libs/core/langchain_core/tracers/stdout.py Pretty-print the run tree
RunLog, RunLogPatch libs/core/langchain_core/tracers/log_stream.py Stream representation used by astream_log
tracing_v2_enabled context manager libs/core/langchain_core/tracers/context.py Force-enable tracing for a code block

How dispatch works

When chain.invoke(input, config) runs:

  1. ensure_config(config) builds a CallbackManager from config["callbacks"] plus globally registered tracers.
  2. manager.on_chain_start(serialized=..., inputs=...) returns a CallbackManagerForChainRun with a run_id.
  3. The chain calls into nested runnables, passing this run manager so child managers inherit the parent run id.
  4. On completion, manager.on_chain_end(outputs) fires.
  5. On error, manager.on_chain_error(error) fires.

For LLMs, the analogous events are on_llm_start, on_llm_new_token (per streaming chunk), on_llm_end, on_llm_error. For tools, on_tool_start / on_tool_end. For retrievers, on_retriever_start / on_retriever_end.

manager.py at ~90 KB is the largest single file outside the runnables core. Most of it is the boilerplate of paired sync/async dispatch methods.

Tracers and LangSmith

LangChainTracer is registered globally when the LANGCHAIN_TRACING_V2 env var is set (or LANGSMITH_TRACING=true). It builds a tree of runs (each run has id, parent_run_id, inputs, outputs, start_time, end_time, error, tags, metadata) and POSTs them to the LangSmith API as a batch. ConsoleCallbackHandler renders the same tree to stdout for local debugging.

tracing_v2_enabled(...) is a context manager that forces tracing on for a code block, regardless of env vars. Useful in tests and notebooks.

astream_events

Runnable.astream_events(input, version="v2") returns an async iterator of typed StreamEvent dicts, one per event in every nested runnable's lifecycle. Internally, it attaches a special tracer that emits an event into a MemoryAsyncStream whenever any callback method fires; the iterator yields from that stream while the underlying chain runs.

This is what powers UIs that show fine-grained progress ("model started", "model token: …", "tool ended").

Globals

libs/core/langchain_core/globals.py exposes module-level toggles:

  • set_debug(True) — register a debug tracer that prints events to stdout.
  • set_verbose(True) — register a less verbose printer.
  • set_llm_cache(...) — global LLM response cache (see caches.py).

These are convenience hooks for development; production code should attach handlers via RunnableConfig.callbacks.

Async vs sync

Every callback method has both sync and async variants. The dispatch managers (CallbackManager, AsyncCallbackManager) call the appropriate variant depending on whether the parent runnable is being invoked sync or async. Handlers that subclass only BaseCallbackHandler get their async event calls fall back to the sync method via a thread executor.

Integration points

  • Every Runnable funnels events through callback managers.
  • LangSmith is the canonical consumer. The langsmith SDK is a direct dependency of langchain-core.
  • langgraph uses the same callback manager so traces span both libraries.
  • Custom integrations (Datadog, OpenTelemetry, Helicone, …) implement BaseCallbackHandler and attach to chains.

Entry points for modification

  • For a new event type, edit BaseCallbackHandler in libs/core/langchain_core/callbacks/base.py, plumb dispatch through manager.py, and add the corresponding handling in BaseTracer.subclass.
  • For a new built-in handler, place it in libs/core/langchain_core/callbacks/ and document its registration pattern.
  • For a new tracer destination, subclass BaseTracer and override _persist_run (the per-run upload hook).

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Callbacks and tracers – LangChain wiki | Factory