Splunk Agent Observability Instrumentation for LangChain Apps
Add the LangChain Callback
Galileo’s GalileoCallback is a standard LangChain callback handler. When you attach it to a
LangChain or LangGraph run, it automatically captures prompts, responses, model names, token usage,
timing, and the nesting of each step.
Because the travel planner is a LangGraph workflow, you don’t need to edit every node. Instead, pass a single callback in the run config when the compiled graph is streamed. Splunk Agent Observability then records one trace per request, with a nested LLM span for each agent node (coordinator, flight, hotel, activity, and synthesizer).
Import the callback
Add the callback import alongside the other LangChain imports in main.py:
from galileo.handlers.langchain import GalileoCallbackAttach the callback to the graph run config
In plan_travel_internal(), create a callback and attach it to the run config passed to compiled_app.stream(...). The existing code should look something like this:
for step in compiled_app.stream(initial_state, config):
node_name, node_state = next(iter(step.items()))
final_state = node_stateUpdate it to build a config that includes the Galileo callback (merging it with any existing config the app already passes). This passes the execution of each node in the agent to Splunk Agent Observability:
# One callback per request keeps each travel plan in its own trace.
callback = GalileoCallback()
run_config = {**config, "callbacks": [callback]}
for step in compiled_app.stream(initial_state, run_config):
node_name, node_state = next(iter(step.items()))
final_state = node_statePassing the callback at the graph level means it propagates to every node’s llm.invoke(...) call automatically. No further instrumentation is needed.
Where do you attach the GalileoCallback in a LangGraph workflow?
Async workflows
compiled_app.astream(...)), use
GalileoAsyncCallback instead of GalileoCallback. The travel planner runs synchronously, so
GalileoCallback is correct here.
