Event Streaming

Purpose and Scope

Event streaming is the part of LangChain that turns long-running model and agent work into incremental application updates. Instead of waiting for a complete response, an application can receive tokens, tool progress, final answers, or structured runtime events while the run is still active. In the Python sources for this page, the most concrete public surfaces are callback handlers: one family writes streamed model output to standard output, another exposes an asynchronous iterator for application code, and an internal tracer protocol marks handlers used by higher-level stream log and stream event implementations.

Sources: libs/core/langchain_core/callbacks/streaming_stdout.py, libs/core/langchain_core/tracers/_streaming.py

The important distinction is between token streaming and event streaming. Token streaming is the classic callback path where language models invoke a handler for each new token or content block. Event streaming is broader: modern agent runtimes can expose typed projections for messages, tool calls, values, lifecycle updates, tasks, and nested subagent activity. The supplied Python sources show the callback layer that receives streaming signals and the marker class that lets newer stream event implementations opt into content-block lifecycle events rather than only legacy token chunks.

Sources: libs/core/langchain_core/callbacks/streaming_stdout.py, libs/core/langchain_core/tracers/_streaming.py

Relevant Source Files

  • libs/core/langchain_core/callbacks/streaming_stdout.py — defines the core synchronous stdout streaming callback handler used when an LLM supports streaming tokens or content blocks.
  • libs/core/langchain_core/tracers/_streaming.py — defines internal streaming callback protocols and the v2 marker used by stream log and stream event implementations.
  • libs/langchain/langchain_classic/callbacks/streaming_aiter.py — defines an async iterator callback handler that queues incoming tokens and yields them to application code.
  • libs/langchain/langchain_classic/callbacks/streaming_aiter_final_only.py — specializes the async iterator handler so only the final answer portion is yielded after a configurable prefix is detected.
  • libs/langchain/langchain_classic/callbacks/streaming_stdout_final_only.py — specializes stdout streaming so intermediate agent reasoning is suppressed and only the final answer is printed.
  • libs/langchain/langchain_classic/callbacks/streaming_stdout.py — re-exports the core stdout streaming handler from the classic package namespace.

Core Primitives

The core primitive is a callback handler method invoked by the runtime as work progresses. In the stdout handler, most lifecycle methods are intentionally empty, but on_llm_new_token writes the received token or content block list to sys.stdout and flushes immediately. That makes the handler useful for command-line demos, notebooks, and debugging sessions where visibility matters more than buffering or UI control. The docstring explicitly warns that this path only works with models that support streaming, so attaching the handler to a non-streaming model should not be treated as a guarantee of incremental output.

Sources: libs/core/langchain_core/callbacks/streaming_stdout.py

For application servers, the async iterator handler is often the more reusable primitive. It owns an asyncio.Queue for token strings and an asyncio.Event that marks completion. The model callback adds non-empty tokens to the queue, while end and error callbacks set the completion event. Consumers call aiter() and receive an asynchronous stream that can be bridged to WebSockets, server-sent events, terminal UIs, or background task processors. The source includes an important concurrency caveat: using one handler instance for two parallel LLM runs will not behave as expected.

Sources: libs/langchain/langchain_classic/callbacks/streaming_aiter.py

System-to-Code Mapping

LangChain keeps the compatibility layer small. The classic stdout module simply re-exports StreamingStdOutCallbackHandler from langchain_core.callbacks, which lets older import paths continue to work while the implementation lives in core. The final-only stdout handler subclasses that core implementation and overrides the token callback to delay output until a configured answer prefix appears. The final-only async handler follows the same idea but queues the final-answer tokens instead of writing them. This mapping matters when migrating code: choose the core handler for raw token visibility and a final-only classic handler when agent scratchpad output should stay hidden.

Sources: libs/langchain/langchain_classic/callbacks/streaming_stdout.py, libs/langchain/langchain_classic/callbacks/streaming_stdout_final_only.py, libs/langchain/langchain_classic/callbacks/streaming_aiter_final_only.py

The internal tracer file connects callback streaming to event-style APIs. _StreamingCallbackHandler is a runtime-checkable protocol with tap_output_aiter and tap_output_iter, both keyed by a run identifier. These hooks let stream log and asynchronous stream event implementations observe intermediate iterator output without changing the object that originally produced it. _V2StreamingCallbackHandler is deliberately a concrete marker class rather than an empty protocol, because an empty runtime-checkable protocol would match every object and accidentally route all calls through the v2 event generator.

Sources: libs/core/langchain_core/tracers/_streaming.py

Execution Flow

A simple synchronous flow starts when an LLM or chat model begins. The stdout handler has lifecycle methods for model start, model end, model error, chain start, chain end, tool start, agent action, tool end, tool error, and text events, but its visible behavior is concentrated in the new-token callback. Every received token is converted to a string, written, and flushed. This immediate flush is what gives the user the feeling of a live response. It also means stdout streaming is side-effect-oriented; if the application needs to store, transform, filter, or multiplex events, prefer an iterator or event feed.

Sources: libs/core/langchain_core/callbacks/streaming_stdout.py

The asynchronous iterator flow separates production from consumption. At model start the handler clears the completion event. As each token arrives, it converts list-style content blocks to a string and enqueues the result when it is not empty. The iterator waits on two futures at once: the queue getter and the completion event. If a token arrives first, it yields the token; if completion wins, it breaks. The implementation cancels the unused task each loop, which prevents the waiting operation from accumulating in normal single-run usage.

Sources: libs/langchain/langchain_classic/callbacks/streaming_aiter.py

Final-Only Streaming

Final-only streaming is designed for agent patterns where the model may produce intermediate reasoning, tool-selection text, or other scratchpad content before the answer users should see. Both final-only handlers maintain a sliding window of the last tokens with the same length as answer_prefix_tokens. The default prefix is Final, Answer, and :. When strip_tokens is enabled, whitespace and newline differences are ignored for prefix comparison. Once the prefix is detected, the handler flips answer_reached and begins forwarding subsequent tokens through stdout or the async queue.

Sources: libs/langchain/langchain_classic/callbacks/streaming_stdout_final_only.py, libs/langchain/langchain_classic/callbacks/streaming_aiter_final_only.py

This design has practical edge cases. If a prompt or agent format does not emit the configured prefix, the final-only handlers will not stream any answer tokens. If stream_prefix is false, the prefix itself is consumed as a delimiter and not shown to the caller; if true, the saved prefix tokens are emitted as soon as the delimiter is recognized. On LLM start, the handlers reset answer state so sequential calls do not inherit the prior run. The async final-only handler only sets its completion event on model end if the answer prefix was actually reached.

Sources: libs/langchain/langchain_classic/callbacks/streaming_stdout_final_only.py, libs/langchain/langchain_classic/callbacks/streaming_aiter_final_only.py

Event Streaming and Runtime Feeds

Official LangChain documentation describes newer event streaming APIs as typed projections rather than one undifferentiated stream of chunks. In agent applications, that means a client can independently consume messages, tool calls, values, custom updates, and subagent activity. The Python tracer marker supports that direction by opting specific handlers into content-block lifecycle events from newer stream event versions instead of v1 token chunks. For server integrations such as an SSE event endpoint, think in terms of channel subscriptions and namespace filters: the stream may include root-agent events, nested subgraph events, tool events, or user-defined custom channels.

Sources: libs/core/langchain_core/tracers/_streaming.py

Compact API Reference

ComponentContractNotes
StreamingStdOutCallbackHandleron_llm_new_token(token, **kwargs)Writes token or content blocks to stdout and flushes immediately.
AsyncIteratorCallbackHandleraiter()Yields queued token strings until the done event is set.
AsyncFinalIteratorCallbackHandleranswer_prefix_tokens, strip_tokens, stream_prefixYields only tokens after the configured final-answer prefix.
FinalStreamingStdOutCallbackHandleranswer_prefix_tokens, strip_tokens, stream_prefixPrints only the final-answer portion to stdout.
_StreamingCallbackHandlertap_output_aiter(run_id, output), tap_output_iter(run_id, output)Internal protocol for stream log and stream event plumbing.
_V2StreamingCallbackHandlermarker base classExplicit opt-in for newer stream event routing and content-block lifecycle handling.

Next Steps

Use stdout streaming when you are building a local development path and want immediate visual feedback. Use the async iterator handler when your application needs to forward model output into another transport. Use final-only handlers when an agent prompt format includes intermediate work that should not be shown to end users. For more complex agent UIs, pair these callback primitives with the broader event-streaming model from the runtime: subscribe by channel, filter by namespace, and keep message, tool, value, and subagent projections separate so each consumer can progress independently.