Skip to main content
Open In ColabOpen on GitHub

How to attach callbacks to a runnable

Prerequisites

This guide assumes familiarity with the following concepts:

If you are composing a chain of runnables and want to reuse callbacks across multiple executions, you can attach callbacks with the .with_config() method. This saves you the need to pass callbacks in each time you invoke the chain.

important

with_config() binds a configuration which will be interpreted as runtime configuration. So these callbacks will propagate to all child components.

Here's an example:

from typing import Any, Dict, List

from langchain_anthropic import ChatAnthropic
from langchain_core.callbacks import BaseCallbackHandler
from langchain_core.messages import BaseMessage
from langchain_core.outputs import LLMResult
from langchain_core.prompts import ChatPromptTemplate


class LoggingHandler(BaseCallbackHandler):
def on_chat_model_start(
self, serialized: Dict[str, Any], messages: List[List[BaseMessage]], **kwargs
) -> None:
print("Chat model started")

def on_llm_end(self, response: LLMResult, **kwargs) -> None:
print(f"Chat model ended, response: {response}")

def on_chain_start(
self, serialized: Dict[str, Any], inputs: Dict[str, Any], **kwargs
) -> None:
print(f"Chain {serialized.get('name')} started")

def on_chain_end(self, outputs: Dict[str, Any], **kwargs) -> None:
print(f"Chain ended, outputs: {outputs}")


callbacks = [LoggingHandler()]
llm = ChatAnthropic(model="claude-3-7-sonnet-20250219")
prompt = ChatPromptTemplate.from_template("What is 1 + {number}?")

chain = prompt | llm

chain_with_callbacks = chain.with_config(callbacks=callbacks)

chain_with_callbacks.invoke({"number": "2"})
Error in LoggingHandler.on_chain_start callback: AttributeError("'NoneType' object has no attribute 'get'")
``````output
Chain ChatPromptTemplate started
Chain ended, outputs: messages=[HumanMessage(content='What is 1 + 2?', additional_kwargs={}, response_metadata={})]
Chat model started
Chat model ended, response: generations=[[ChatGeneration(text='The sum of 1 + 2 is 3.', message=AIMessage(content='The sum of 1 + 2 is 3.', additional_kwargs={}, response_metadata={'id': 'msg_01F1qPrmBD9igfzHdqVipmKX', 'model': 'claude-3-7-sonnet-20250219', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 16, 'output_tokens': 17, 'server_tool_use': None, 'service_tier': 'standard'}, 'model_name': 'claude-3-7-sonnet-20250219'}, id='run--71edddf3-2474-42dc-ad43-fadb4882c3c8-0', usage_metadata={'input_tokens': 16, 'output_tokens': 17, 'total_tokens': 33, 'input_token_details': {'cache_read': 0, 'cache_creation': 0}}))]] llm_output={'id': 'msg_01F1qPrmBD9igfzHdqVipmKX', 'model': 'claude-3-7-sonnet-20250219', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 16, 'output_tokens': 17, 'server_tool_use': None, 'service_tier': 'standard'}, 'model_name': 'claude-3-7-sonnet-20250219'} run=None type='LLMResult'
Chain ended, outputs: content='The sum of 1 + 2 is 3.' additional_kwargs={} response_metadata={'id': 'msg_01F1qPrmBD9igfzHdqVipmKX', 'model': 'claude-3-7-sonnet-20250219', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 16, 'output_tokens': 17, 'server_tool_use': None, 'service_tier': 'standard'}, 'model_name': 'claude-3-7-sonnet-20250219'} id='run--71edddf3-2474-42dc-ad43-fadb4882c3c8-0' usage_metadata={'input_tokens': 16, 'output_tokens': 17, 'total_tokens': 33, 'input_token_details': {'cache_read': 0, 'cache_creation': 0}}
AIMessage(content='The sum of 1 + 2 is 3.', additional_kwargs={}, response_metadata={'id': 'msg_01F1qPrmBD9igfzHdqVipmKX', 'model': 'claude-3-7-sonnet-20250219', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 16, 'output_tokens': 17, 'server_tool_use': None, 'service_tier': 'standard'}, 'model_name': 'claude-3-7-sonnet-20250219'}, id='run--71edddf3-2474-42dc-ad43-fadb4882c3c8-0', usage_metadata={'input_tokens': 16, 'output_tokens': 17, 'total_tokens': 33, 'input_token_details': {'cache_read': 0, 'cache_creation': 0}})

The bound callbacks will run for all nested module runs.

Next steps​

You've now learned how to attach callbacks to a chain.

Next, check out the other how-to guides in this section, such as how to pass callbacks in at runtime.