> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Callbacks

> Explains LangChain callbacks, using built-in and custom handlers to capture lifecycle events for logging, observability, telemetry, debugging, and production best practices.

All right — we are now at the third demo where

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/Xqjckn2TzkOV2Gz2/images/LangChain/Tips-Tricks-and-Resources/Callbacks/demo-callbacks-blue-gradient-slide.jpg?fit=max&auto=format&n=Xqjckn2TzkOV2Gz2&q=85&s=6c5afb3db14b69b19aa034b766734973" alt="The image is a slide with the word &#x22;Demo&#x22; on the left and &#x22;Callbacks&#x22; on a blue gradient shape on the right." width="1920" height="1080" data-path="images/LangChain/Tips-Tricks-and-Resources/Callbacks/demo-callbacks-blue-gradient-slide.jpg" />
</Frame>

In this lesson we’ll explain what callbacks are in LangChain, why they matter for observability and production systems, and how to use built-in and custom handlers to capture lifecycle events from chains and LLM calls.

## Minimal LangChain example

This minimal program creates an LLM chain that formats a prompt and invokes an LLM:

```python theme={null}
from langchain.prompts import ChatPromptTemplate
from langchain.chat_models import ChatOpenAI
from langchain.chains import LLMChain

llm = ChatOpenAI()
prompt = ChatPromptTemplate.from_messages(
    [
        ("system", "You are a {subject} teacher"),
        ("human", "Tell me about {concept}")
    ]
)
chain = LLMChain(llm=llm, prompt=prompt)

chain.invoke({"subject": "physics", "concept": "galaxy"})
```

A typical result returned by the chain might look like this (JSON-style):

```json theme={null}
{
  "subject": "physics",
  "concept": "galaxy",
  "text": "A galaxy is a vast system of stars, gas, dust, and dark matter bound together by gravity. It is the basic building block of the universe, containing billions to trillions of stars, as well as planets, nebulae, and other celestial objects.\n\nGalaxies come in different shapes and sizes, including spiral, elliptical, and irregular types. Our Milky Way is a spiral galaxy that contains hundreds of billions of stars. Galaxies often group into clusters and provide important clues about the structure and evolution of the universe."
}
```

## What are callbacks and why use them?

A callback is a function or handler that the LangChain runtime invokes at specific lifecycle events — for example when a prompt is formatted, when an LLM call starts or ends, when a chain begins or finishes, or when tools are invoked. Callbacks allow you to:

* Record runtime events (console, files, or structured logs).
* Route events to observability systems (Datadog, Splunk, CloudWatch, etc.).
* Transform or post-process outputs (HTML, structured JSON).
* Aggregate metrics and implement custom telemetry.
* Debug and trace execution across chains and tools.

Example uses:

* Print LLM/chains events to stdout while developing.
* Save inputs/outputs into structured logs for later analysis.
* Emit metrics for latency, token usage, or error rates.

## Built-in stdout handler example

This example imports and uses the built-in StdOutCallbackHandler to print lifecycle messages to the console. Note how we pass the handler via the `callbacks` parameter to the chain.

```python theme={null}
from langchain.prompts import ChatPromptTemplate
from langchain.chat_models import ChatOpenAI
from langchain.chains import LLMChain
from langchain.callbacks.stdout import StdOutCallbackHandler

# Create the handler and the chain
handler = StdOutCallbackHandler()

llm = ChatOpenAI()
prompt = ChatPromptTemplate.from_messages(
    [
        ("system", "You are a {subject} teacher"),
        ("human", "Tell me about {concept}")
    ]
)
chain = LLMChain(llm=llm, prompt=prompt, callbacks=[handler])

# Invoke the chain
chain.invoke({"subject": "physics", "concept": "galaxy"})
```

When you run this, the stdout handler prints debug-like lifecycle messages to standard output. Example console output (truncated for brevity):

```text theme={null}
> Entering new LLMChain chain...
Prompt after formatting:
System: You are a physics teacher
Human: Tell me about galaxy

> Finished chain.
{
  "subject": "physics",
  "concept": "galaxy",
  "text": "A galaxy is a massive, gravitationally bound system that consists of stars, gas, dust, and dark matter. Galaxies come in various shapes and sizes, ranging from small dwarf galaxies to large spiral and elliptical galaxies. Our own Milky Way is a spiral galaxy that contains billions of stars."
}
```

## Key differences and control points

Use the right mechanism depending on environment and goals. The table below summarizes the options and when to use them.

| Option                          | When to use                                                                  | Example / Notes                                                                                                                                                        |
| ------------------------------- | ---------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Global debug                    | Quick development-time debugging                                             | Enables global verbose output; simple but harder to route (`debug=True`)                                                                                               |
| Component-level `verbose`       | Inspect a specific component without changing global behavior                | Use `verbose=True` on the component: `LLMChain(..., verbose=True)`                                                                                                     |
| Callback handlers (recommended) | Production telemetry, structured logs, and routing to observability backends | Pass handlers via `callbacks=[handler]`. Use built-in handlers (e.g., `StdOutCallbackHandler`) or custom handlers to emit JSON, metrics, or push to external services. |

Example combining verbose and callbacks:

```python theme={null}
chain = LLMChain(llm=llm, prompt=prompt, callbacks=[handler], verbose=True)
chain.invoke({"subject": "physics", "concept": "galaxy"})
```

## Creating custom handlers when you need more control

For production use cases you’ll often want to implement a custom callback handler to format events, emit structured JSON, or push telemetry to a remote service. The handler receives lifecycle events and can perform any custom action required by your app.

Skeleton example (implement the methods you need):

```python theme={null}
from langchain.callbacks.base import BaseCallbackHandler

class MyLoggingHandler(BaseCallbackHandler):
    def on_chain_start(self, serialized, inputs, **kwargs):
        # Called when a chain starts
        print("chain started", inputs)

    def on_chain_end(self, outputs, **kwargs):
        # Called when a chain finishes
        # You can format outputs, write to files, or push to a logging backend
        print("chain finished", outputs)

    def on_llm_start(self, serialized, prompts, **kwargs):
        # Called when an LLM call starts
        pass

    def on_llm_end(self, response, **kwargs):
        # Called when the LLM call ends
        pass
```

Integrate your handler by passing it to the chain:

```python theme={null}
handler = MyLoggingHandler()
chain = LLMChain(llm=llm, prompt=prompt, callbacks=[handler])
```

## Best practices

* Use callback handlers for production logging, metrics, and observability.
* Keep stdout handlers for local development or CI debugging.
* Implement only the callback methods you need to minimize overhead.
* Ensure sensitive data (API keys, PII) is redacted before sending logs to third-party systems.
* Combine `verbose` on specific components with callbacks to get granular insight without overwhelming global logging.

<Callout icon="lightbulb" color="#1CB2FE">
  Callbacks are a flexible and powerful mechanism for observability and production-grade telemetry. Prefer callback handlers over global debug for routing structured logs, metrics, or formatted outputs to external systems.
</Callout>

## Summary

* Callbacks are invoked at key lifecycle events during chain execution.
* `StdOutCallbackHandler` is useful for quick, readable runtime output to the console.
* For production use, implement or reuse custom handlers to send structured logs, metrics, or trace data to files or cloud services.
* Combine component `verbose` flags with callbacks for targeted, flexible observability.

## Links and references

* [LangChain Documentation](https://langchain.readthedocs.io/)
* [OpenAI API Documentation](https://platform.openai.com/docs)
* Observability and logging references:
  * [Prometheus](https://prometheus.io/)
  * [OpenTelemetry](https://opentelemetry.io/)
  * [Datadog Logs](https://docs.datadoghq.com/logs/)

Later, we’ll walk through additional resources and practical examples to build production-grade LangChain applications.

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/langchain/module/b5f7771a-fdbc-45b1-a786-6c84bb7ffc76/lesson/4e795ffc-63cb-4935-b04e-fb4911326be5" />
</CardGroup>
