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 # ConsoleCallbackHandlerKey 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:
ensure_config(config)builds aCallbackManagerfromconfig["callbacks"]plus globally registered tracers.manager.on_chain_start(serialized=..., inputs=...)returns aCallbackManagerForChainRunwith arun_id.- The chain calls into nested runnables, passing this run manager so child managers inherit the parent run id.
- On completion,
manager.on_chain_end(outputs)fires. - 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 (seecaches.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
langsmithSDK is a direct dependency oflangchain-core. langgraphuses the same callback manager so traces span both libraries.- Custom integrations (Datadog, OpenTelemetry, Helicone, …) implement
BaseCallbackHandlerand attach to chains.
Entry points for modification
- For a new event type, edit
BaseCallbackHandlerinlibs/core/langchain_core/callbacks/base.py, plumb dispatch throughmanager.py, and add the corresponding handling inBaseTracer.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
BaseTracerand override_persist_run(the per-run upload hook).
Related
- primitives/runnables — what fires these events
- primitives/language-models — the heaviest event emitter
- features/middleware — agent middleware that observes the same events at the agent level
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.