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

# Logging

> Learn about using the Galileo LangChain and LangGraph logging integration to log agent traces

{/*<!-- markdownlint-enable MD044 -->*/}

The Galileo LangChain integration allows you to automatically log all LangChain and LangGraph interactions with LLMs, including prompts, responses, and performance metrics. The Galileo SDK has a custom callback that is passed to LangChain or LangGraph.

<CardGroup cols={2}>
  <Card title="GalileoCallback - Python" icon="python" horizontal href="/sdk-api/python/reference/handlers/langchain/handler">
    The Python Galileo Synchronous LangChain SDK reference.
  </Card>

  <Card title="GalileoAsyncCallback - Python" icon="python" horizontal href="/sdk-api/python/reference/handlers/langchain/async_handler">
    The Python Galileo Asynchronous LangChain SDK reference.
  </Card>

  <Card title="GalileoCallback - TypeScript" icon="js" horizontal href="/sdk-api/typescript/reference/README/classes/GalileoCallback">
    The TypeScript Galileo LangChain SDK reference.
  </Card>
</CardGroup>

## Basic usage

The integration is based on the `GalileoCallback` class, which implements LangChain's callback interface. To use it, create an instance of the callback and pass it to your LangChain components:

<CodeGroup>
  ```python Python theme={null}
  from galileo.handlers.langchain import GalileoCallback
  from langchain_openai import ChatOpenAI
  from langchain_core.messages import HumanMessage

  # Create a callback handler
  callback = GalileoCallback()

  # Initialize the LLM with the callback
  llm = ChatOpenAI(model="gpt-4o", temperature=0.7, callbacks=[callback])

  # Create a message with the user's query
  messages = [
      HumanMessage(content="What is LangChain and how is it used with OpenAI?")
  ]

  # Make the API call
  response = llm.invoke(messages)

  print(response.content)
  ```

  ```typescript TypeScript theme={null}
  import { GalileoCallback } from "galileo";
  import { ChatOpenAI } from "@langchain/openai";

  // Create a callback handler
  const callback = new GalileoCallback();

  // Initialize the LLM with the callback
  const llm = new ChatOpenAI({
    model: "gpt-4o",
    temperature: 0.7,
    callbacks: [callback]
  });

  // Make the LLM call
  const response = await llm.invoke(
      "What is LangChain and how is it used with OpenAI?"
  );

  console.log(response.content);
  ```
</CodeGroup>

The `GalileoCallback` captures various LangChain events, including:

* LLM starts and completions
* Chat model interactions
* Chain executions
* Tool calls
* Retriever operations
* Agent actions

For each of these events, the callback logs relevant information to Galileo, such as:

* Input prompts and messages
* Output responses
* Model information
* Timing data
* Token usage
* Error information (if any)

The GalileoCallback automatically handles nested chains and agents, creating a hierarchical trace that reflects the structure of your LangChain application.

### Asynchronous callbacks

In Python, there are separate callbacks for synchronous and asynchronous code. If you are using the asynchronous LangChain or LangGraph API, use the [`GalileoAsyncCallback` callback handler](/sdk-api/python/reference/handlers/langchain/async_handler).
In TypeScript, the standard `GalileoCallback` handles async natively — no separate class is needed.

<CodeGroup>
  ```python Python theme={null}
  import asyncio
  from galileo.handlers.langchain import GalileoAsyncCallback
  from langchain_openai import ChatOpenAI
  from langchain_core.messages import HumanMessage

  # Create a callback handler
  callback = GalileoAsyncCallback()

  # Initialize the LLM with the callback
  llm = ChatOpenAI(model="gpt-4o", temperature=0.7, callbacks=[callback])

  # Create a message with the user's query
  messages = [
      HumanMessage(content="What is LangChain and how is it used with OpenAI?")
  ]

  async def main():
      # Make the API call
      response = await llm.ainvoke(messages)
      print(response.content)

  asyncio.run(main())
  ```

  ```typescript TypeScript theme={null}
  import { GalileoCallback } from "galileo";
  import { ChatOpenAI } from "@langchain/openai";
  import { HumanMessage } from "@langchain/core/messages";

  // Create a callback handler
  // In the TypeScript SDK, GalileoCallback handles async natively —
  // there is no separate async class
  const callback = new GalileoCallback();

  // Initialize the LLM with the callback
  const llm = new ChatOpenAI({
    model: "gpt-4o",
    temperature: 0.7,
    callbacks: [callback],
  });

  // Create a message with the user's query
  const messages = [
    new HumanMessage("What is LangChain and how is it used with OpenAI?"),
  ];

  // Make the async API call
  const response = await llm.invoke(messages);

  console.log(response.content);
  ```
</CodeGroup>

## Use a custom logger

When initializing the `GalileoCallback`, you can optionally specify a Galileo logger instance, either by creating a new logger, or by using the current logger from the Galileo context:

<CodeGroup>
  ```python Python theme={null}
  from galileo import GalileoLogger
  from galileo.handlers.langchain import GalileoCallback

  # Create a custom logger
  logger = GalileoLogger(project="my-project", log_stream="my-log-stream")

  # Create a callback with the custom logger
  callback = GalileoCallback(
      galileo_logger=logger,  # Optional custom logger
      start_new_trace=True,   # Whether to start a new trace for each chain
      flush_on_chain_end=True # Whether to flush traces when chains end
  )
  ```

  ```typescript TypeScript theme={null}
  import { GalileoCallback, GalileoLogger, flush } from "galileo";
  import { ChatOpenAI } from "@langchain/openai";

  // Create a custom logger
  const logger = new GalileoLogger({
    projectName: "my-project",
    logStreamName: "my-log-stream"
  });

  // Create a callback with the custom logger
  const callback = new GalileoCallback(
    logger, // Optional custom logger
    true,   // Whether to start a new trace for each chain
    true, // Whether to flush traces when chains end
  );
  ```
</CodeGroup>

This is particularly useful if you want to call your LangChain code from inside a function [decorated with the `log` decorator](/sdk-api/logging/log-decorator/log-decorator), or from inside an [experiment](/sdk-api/third-party-integrations/langchain/experiments).

### Session and trace support

Every time you invoke a chain or an LLM call, a new session and trace is created. If you want to manually manage sessions or traces, you can do this using by passing a Galileo logger instance to the callback.

To add the chain or LLM call invocation as a new trace to an existing session, create the session first using the logger instance that was used to create the callback:

<CodeGroup>
  ```python Python theme={null}
  from galileo import GalileoLogger
  from galileo.handlers.langchain import GalileoCallback

  # Create a custom logger
  logger = GalileoLogger(project="my-project", log_stream="my-log-stream")

  # Create a callback with the custom logger
  callback = GalileoCallback(
      galileo_logger=logger
  )

  # Create a new session
  logger.start_session(name="My new session")
  ```

  ```typescript TypeScript theme={null}
  import { GalileoCallback, GalileoLogger } from "galileo";

  // Create a custom logger
  const logger = new GalileoLogger({
    projectName: "my-project",
    logStreamName: "my-log-stream"
  });

  // Create a callback with the custom logger
  const callback = new GalileoCallback(
    logger,
  );

  // Create a new session
  logger.startSession({ name: "My new session" })
  ```
</CodeGroup>

To add the chain or LLM call invocation to an existing trace, ensure the trace is started, and set the `start_new_trace` parameter to `False` (Python) or `false` (TypeScript).

<CodeGroup>
  ```python Python theme={null}
  from galileo import GalileoLogger
  from galileo.handlers.langchain import GalileoCallback

  # Create a custom logger
  logger = GalileoLogger(project="my-project", log_stream="my-log-stream")

  # Create a callback with the custom logger
  callback = GalileoCallback(
      galileo_logger=logger,
      start_new_trace=False
  )

  # Create a new session
  logger.start_session(name="My new session")

  # Add a trace and a span
  logger.start_trace("My trace")
  logger.add_workflow_span("Crew workflow")
  ```

  ```typescript TypeScript theme={null}
  import { GalileoCallback, GalileoLogger } from "galileo";

  // Create a custom logger
  const logger = new GalileoLogger({
    projectName: "my-project",
    logStreamName: "my-log-stream"
  });

  // Create a callback with the custom logger
  const callback = new GalileoCallback(
    logger,
    false,
  );

  // Create a new session
  logger.startSession({ name: "My new session" })

  // Add a trace and a span
  logger.startTrace({ input: "User query", name: "My trace" })
  logger.addWorkflowSpan({ input: "User query", name:"Crew workflow" })
  ```
</CodeGroup>

## Use with LangChain chains

You can also use the callback with LangChain chains. Make sure to pass the callback to both the LLM and the chain.

<CodeGroup>
  ```python Python theme={null}
  from galileo.handlers.langchain import GalileoAsyncCallback
  from langchain_openai import ChatOpenAI
  from langchain_core.output_parsers import StrOutputParser
  from langchain_core.prompts import ChatPromptTemplate
  from langchain_core.runnables.config import RunnableConfig

  # Create a callback handler
  callback = GalileoAsyncCallback()

  # Create the model
  llm = ChatOpenAI(model="gpt-4o", temperature=0.7, callbacks=[callback])

  # Create a prompt template
  prompt = ChatPromptTemplate.from_template("Tell me a joke about {topic}")

  # Assemble the chain with the prompt, LLM, and output parser
  chain = prompt | llm | StrOutputParser()

  # Create a configuration for the runnable
  # that includes the callback handler
  config = RunnableConfig(
      callbacks=[callback]
  )

  # Invoke the chain with a topic and configuration
  response = chain.invoke({"topic": "the Roman Empire"},
                          config=config)
  print(response)
  ```

  ```typescript TypeScript theme={null}
  import { GalileoCallback } from "galileo";
  import { ChatOpenAI } from "@langchain/openai";
  import { ChatPromptTemplate } from "@langchain/core/prompts";
  import { StringOutputParser } from "@langchain/core/output_parsers";

  // Create a callback handler
  const callback = new GalileoCallback();

  // Initialize the LLM with the callback
  const llm = new ChatOpenAI({
    model: "gpt-4o",
    temperature: 0.7,
    callbacks: [callback],
  });

  // Create a prompt template
  const prompt = ChatPromptTemplate.fromTemplate(
      "Tell me a joke about {topic}"
  );

  // Assemble the chain with the prompt, LLM, and output parser
  const chain = prompt.pipe(llm).pipe(new StringOutputParser());

  // Invoke the chain with a topic and configuration
  // The callback is passed in the second argument (config)
  const response = await chain.invoke(
      { topic: "the Roman Empire" },
      { callbacks: [callback] }
  );
  console.log(response);
  ```
</CodeGroup>

## Add metadata

You can add custom metadata and tags to your logs by including them in the `metadata` and `tags` parameters of a LangChain runnable configuration when invoking a chain or LLM.

<CodeGroup>
  ```python Python theme={null}
  # Create a configuration for the runnable
  # that includes the callback handler and metadata
  config = RunnableConfig(
      callbacks=[callback],
      metadata={
          "user_id": "user-123",
          "session_id": "session-456",
          "custom_field": "custom value",
      },
      tags=["my-tag"],
  )

  # Invoke the chain with a topic and configuration
  response = chain.invoke({"topic": "the Roman Empire"}, config=config)
  ```

  ```typescript TypeScript theme={null}
  // Invoke the chain with a topic and configuration
  // Metadata and tags are passed via the config object (second argument)
  const response = await chain.invoke(
      { topic: "the Roman Empire" },
      {
          callbacks: [callback],
          metadata: {
              userId: "user-123",
              sessionId: "session-456",
              customField: "custom value",
          },
          tags: ["my-tag"],
      }
  );
  ```
</CodeGroup>

This metadata will be attached to the logs in Galileo, making it easier to filter and analyze your data.

<img src="https://mintcdn.com/v2galileo/z5H2aF3fGcHzIto4/sdk-api/third-party-integrations/langchain/metadata.webp?fit=max&auto=format&n=z5H2aF3fGcHzIto4&q=85&s=12ff45f248f3abab14c215cf138f6aa1" alt="A chain node in a trace with metadata attached" width="1785" height="590" data-path="sdk-api/third-party-integrations/langchain/metadata.webp" />

## Best practices

1. **Pass callbacks consistently**: Make sure to pass the callback to all LangChain components (LLMs, chains, agents, etc.) to ensure complete logging.
2. **Include meaningful metadata**: Add relevant metadata to your invocations to make it easier to filter and analyze your logs.

## Next steps

### Basic logging components

<CardGroup cols={2}>
  <Card title="Galileo logger" icon="code" horizontal href="/sdk-api/logging/galileo-logger">
    Log with full control over sessions, traces, and spans using the Galileo logger.
  </Card>

  <Card title="Log decorator" icon="code" horizontal href="/sdk-api/logging/log-decorator/log-decorator">
    Quickly add logging to your code with the log decorator and wrapper.
  </Card>

  <Card title="Galileo context" icon="code" horizontal href="/sdk-api/logging/galileo-context">
    Manage logging using the Galileo context manager.
  </Card>
</CardGroup>

### Cookbooks

<CardGroup cols={2}>
  <Card title="Monitor LangChain Agents with Galileo" icon="code" horizontal href="/cookbooks/use-cases/agent-langchain">
    Learn how to build and monitor a LangChain AI Agent using Galileo for tracing and observability.
  </Card>

  <Card title="Add evaluations to a multi-agent LangGraph application" icon="code" horizontal href="/cookbooks/use-cases/multi-agent-langgraph/multi-agent-langgraph">
    Learn how to add evaluations to a multi-agent LangGraph chat bot using Galileo
  </Card>
</CardGroup>
