LangGraph
Use Confident AI for LLM observability and evals for LangGraph
Overview
LangGraph is a framework for building reactive, multi-agent systems. Confident AI provides a CallbackHandler in both the python and typescript SDKs to trace and evaluate your LangGraph agents automatically.
The callback handler captures the following spans from your LangGraph agent:
- LLM spans — model name, provider, input messages, output content, tool calls made by the model, and token usage
- Tool spans — tool name, input parameters, and output; also aggregated at the trace level as
tools_called - Retriever spans — query input and retrieved document output
- Agent spans — inputs and outputs for the top-level graph (used to set trace-level input/output)
Tracing Quickstart
Install Dependencies
Run the following command to install the required packages:
Python pip install -U deepeval langgraph langchain langchain-openaiTypeScript npm install deepeval langchain @langchain/langgraph @langchain/openai @langchain/coreSetup Confident AI Key
Login to Confident AI using your Confident API key.
export CONFIDENT_API_KEY="<your-confident-api-key>"deepeval loginimport deepeval deepeval.login("<your-confident-api-key>")Configure LangGraph
Provide DeepEval's
CallbackHandlerto your LangGraph agent's invoke method.Python from langchain.agents import create_agent from langchain_openai import ChatOpenAI from deepeval.integrations.langchain import CallbackHandler def get_weather(city: str) -> str: """Returns the weather in a city""" return f"It's always sunny in {city}!" llm = ChatOpenAI(model="gpt-4o-mini") agent = create_agent( model=llm, tools=[get_weather], system_prompt="You are a helpful assistant", ) result = agent.invoke( input={"messages": [{"role": "user", "content": "what is the weather in sf"}]}, config={"callbacks": [CallbackHandler()]}, )TypeScript import { createAgent } from "langchain"; import { ChatOpenAI } from "@langchain/openai"; import { tool } from "@langchain/core/tools"; import { z } from "zod"; import { DeepEvalCallbackHandler } from "deepeval/integrations/langchain"; const getWeather = tool( async ({ city }: { city: string }) => `It's always sunny in ${city}!`, { name: "get_weather", description: "Returns the weather in a city", schema: z.object({ city: z.string() }), }, ); const agent = createAgent({ model: new ChatOpenAI({ model: "gpt-4o-mini" }), tools: [getWeather], systemPrompt: "You are a helpful assistant", }); const result = await agent.invoke( { messages: [{ role: "user", content: "what is the weather in sf" }] }, { callbacks: [new DeepEvalCallbackHandler({})] }, );Run LangGraph
Invoke your agent by executing the script:
python main.pynpx ts-node main.tsYou can directly view the traces on Confident AI by clicking on the link in the output printed in the console.
Trace a LangGraph server deployment
Confident AI allows you to trace your LangGraph applications deployed in a server by passing the CallbackHandler in the exported graph's config and using it in langgraph.json files.
Attach DeepEval to your graph
Attach the
CallbackHandlerto the graph withwith_configand export it. The handler is then applied to every run the server executes.agent.py from langchain.agents import create_agent from langchain_openai import ChatOpenAI from deepeval.integrations.langchain import CallbackHandler def get_weather(city: str) -> str: """Returns the weather in a city""" return f"It's always sunny in {city}!" llm = ChatOpenAI(model="gpt-4o-mini") graph = create_agent( model=llm, tools=[get_weather], system_prompt="You are a helpful assistant", ).with_config(callbacks=[CallbackHandler()])agent.ts import { createAgent } from "langchain"; import { ChatOpenAI } from "@langchain/openai"; import { tool } from "@langchain/core/tools"; import { z } from "zod"; import { DeepEvalCallbackHandler } from "deepeval/integrations/langchain"; const getWeather = tool( async ({ city }: { city: string }) => `It's always sunny in ${city}!`, { name: "get_weather", description: "Returns the weather in a city", schema: z.object({ city: z.string() }), }, ); export const graph = createAgent({ model: new ChatOpenAI({ model: "gpt-4o-mini" }), tools: [getWeather], systemPrompt: "You are a helpful assistant", }).withConfig({ callbacks: [new DeepEvalCallbackHandler({})] });Register the graph in langgraph.json
Point the
graphsentry at the exported graph variable.Python { "dependencies": ["."], "graphs": { "agent": "./agent.py:graph" }, "env": ".env" }TypeScript { "node_version": "20", "dependencies": ["."], "graphs": { "agent": "./agent.ts:graph" }, "env": ".env" }Start the LangGraph server
Run the server. Every request it runs against the graph is traced to Confident AI.
Python pip install -U "langgraph-cli[inmem]" langgraph devTypeScript npx @langchain/langgraph-cli dev
Advanced Features
Set trace attributes
Confident AI's LLM tracing advanced features provide teams with the ability to set certain attributes for each trace when invoking your LangGraph agent.
For example, thread_id and user_id are used to group related traces together, and are useful for chat apps, agents, or any multi-turn interactions. You can learn more about threads here.
You can set these attributes in the CallbackHandler.
result = agent.invoke(
input={"messages": [{"role": "user", "content": "what is the weather in sf"}]},
config={"callbacks": [CallbackHandler(thread_id="123")]},
)const handler = new DeepEvalCallbackHandler({
threadId: "123",
});View Trace Attributes
name / namestr / string
The name of the trace. Learn more.
tags / tagsList[str] / string[]
Tags are string labels that help you group related traces. Learn more.
metadata / metadataDict / Record<string, any>
Attach any metadata to the trace. Learn more.
thread_id / threadIdstr / string
Supply the thread or conversation ID to view and evaluate conversations. Learn more.
user_id / userIdstr / string
Supply the user ID to enable user analytics. Learn more.
test_case_id / testCaseIdstr / string
Attach a test case ID to associate this trace with a specific test case.
turn_id / turnIdstr / string
Supply a turn ID to identify individual turns in a multi-turn conversation.
metrics / metricsList[BaseMetric] / BaseMetric[]
A list of metrics to run against the root span of this trace. Used for offline (development) evaluations.
metric_collection / metricCollectionstr / string
The name of a metric collection on Confident AI to use for online (production) evaluations.
Logging prompts
If you are managing prompts on Confident AI and wish to log them, pass your Prompt object to the language model instance's metadata parameter.
from langchain_openai import ChatOpenAI
from deepeval.prompt import Prompt
prompt = Prompt(alias="<prompt-alias>")
prompt.pull(version="00.00.01")
llm = ChatOpenAI(
model="gpt-4o-mini",
metadata={"prompt": prompt}
)import { ChatOpenAI } from "@langchain/openai";
import { Prompt } from "deepeval";
const prompt = new Prompt({ alias: "<prompt-alias>" });
prompt.pull({ version: "00.00.01" });
const llm = new ChatOpenAI({
model: "gpt-4o-mini",
metadata: {
prompt: prompt,
},
});Evals Usage
Online evals
If your LangGraph agent is in production, and you still want to run evaluations on your traces, use online evals. It lets you run evaluations on all incoming traces on Confident AI's server.
Create metric collection
Create a metric collection on Confident AI with the metrics you wish to use to evaluate your LangGraph agent. Copy the name of the metric collection.
Create metric collection Run evals
Set the
metric_collectionname to evaluate various components of your LangGraph agent.This is the top level component of your LangGraph agent. Also a very ideal component to evaluate with the Task Completion metric.
Python from langchain.agents import create_agent from langchain_openai import ChatOpenAI from deepeval.integrations.langchain import CallbackHandler def get_weather(city: str) -> str: """Returns the weather in a city""" return f"It's always sunny in {city}!" agent = create_agent( model=ChatOpenAI(model="gpt-4o-mini"), tools=[get_weather], system_prompt="You are a helpful assistant", ) result = agent.invoke( input={"messages": [{"role": "user", "content": "what is the weather in sf"}]}, config={ "callbacks": [CallbackHandler(metric_collection="<metric_collection_name>")] }, )TypeScript import { createAgent } from "langchain"; import { ChatOpenAI } from "@langchain/openai"; import { tool } from "@langchain/core/tools"; import { z } from "zod"; import { DeepEvalCallbackHandler } from "deepeval/integrations/langchain"; const getWeather = tool( async ({ city }: { city: string }) => `It's always sunny in ${city}!`, { name: "get_weather", description: "Returns the weather in a city", schema: z.object({ city: z.string() }), }, ); const agent = createAgent({ model: new ChatOpenAI({ model: "gpt-4o-mini" }), tools: [getWeather], systemPrompt: "You are a helpful assistant", }); const result = await agent.invoke( { messages: [{ role: "user", content: "what is the weather in sf" }] }, { callbacks: [ new DeepEvalCallbackHandler({ metricCollection: "<metric_collection_name>" }), ], }, );For LLM spans, you can set the
metric_collectionormetricCollectionname in themetadataparameter of the language model instance.Python from langchain.agents import create_agent from langchain_openai import ChatOpenAI from deepeval.integrations.langchain import CallbackHandler def get_weather(city: str) -> str: """Returns the weather in a city""" return f"It's always sunny in {city}!" llm = ChatOpenAI( model="gpt-4o-mini", metadata={"metric_collection": "<metric_collection_name>"}, ) agent = create_agent( model=llm, tools=[get_weather], system_prompt="You are a helpful assistant", ) result = agent.invoke( input={"messages": [{"role": "user", "content": "what is the weather in sf"}]}, config={"callbacks": [CallbackHandler()]}, )TypeScript import { createAgent } from "langchain"; import { ChatOpenAI } from "@langchain/openai"; import { tool } from "@langchain/core/tools"; import { z } from "zod"; import { DeepEvalCallbackHandler } from "deepeval/integrations/langchain"; const getWeather = tool( async ({ city }: { city: string }) => `It's always sunny in ${city}!`, { name: "get_weather", description: "Returns the weather in a city", schema: z.object({ city: z.string() }), }, ); const llm = new ChatOpenAI({ model: "gpt-4o-mini", metadata: { metricCollection: "<metric_collection_name>" }, }); const agent = createAgent({ model: llm, tools: [getWeather], systemPrompt: "You are a helpful assistant", }); const result = await agent.invoke( { messages: [{ role: "user", content: "what is the weather in sf" }] }, { callbacks: [new DeepEvalCallbackHandler({})] }, );For tool spans, you can set the
metric_collectionparameter of DeepEval's@tooldecorator.from langchain.agents import create_agent from langchain_openai import ChatOpenAI from deepeval.integrations.langchain import CallbackHandler from deepeval.integrations.langchain import tool @tool(metric_collection="<metric_collection_name>") def get_weather(city: str) -> str: """Returns the weather in a city""" return f"It's always sunny in {city}!" agent = create_agent( model=ChatOpenAI(model="gpt-4o-mini"), tools=[get_weather], system_prompt="You are a helpful assistant", ) result = agent.invoke( input={"messages": [{"role": "user", "content": "what is the weather in sf"}]}, config={"callbacks": [CallbackHandler()]}, )from deepeval.tracing import observe from deepeval.integrations.langchain import CallbackHandler @observe(type="tool", metric_collection="<metric_collection_name>") def get_weather(city: str) -> str: """Returns the weather in a city""" return f"It's always sunny in {city}!"
View on Confident AI
You can view the evals on Confident AI by clicking on the link in the output printed in the console.