Observability#
KodeAgent includes built-in support for observability through platforms such as Langfuse and LangSmith. Hierarchical tracing is integrated into both ReActAgent and CodeActAgent, providing complete observability into their decision-making and execution loops.
Key Features
✅ Hierarchical Tracing: Traces, spans, and generations properly nested.
✅ Backend Integrations: Direct support for Langfuse and LangSmith.
✅ Graceful Degradation: No-op mode when tracing is disabled (default).
✅ Zero Breaking Changes: Fully backward compatible.
Enabling Observability#
By default, both ReActAgent and CodeActAgent have observability disabled (using a no-op tracer). To enable observability, set the tracing_type parameter when initializing the agent.
ⓘ NOTE:
While
langfuseis included with KodeAgent by default,langsmithis not and must be installed separately usingpip install langsmith.
from kodeagent import ReActAgent, CodeActAgent
from kodeagent.tools import calculator
# Enable Langfuse tracing
agent = ReActAgent(
name='Simple agent',
model_name='gemini/gemini-2.5-flash-lite',
tools=[calculator],
tracing_type='langfuse',
)
# Enable LangSmith tracing
agent = CodeActAgent(
name='Simple agent',
model_name='gemini/gemini-2.5-flash-lite',
tools=[calculator],
tracing_type='langsmith',
)
Configuration#
Ensure the relevant environment variables are set for your chosen platform:
Langfuse:
export LANGFUSE_PUBLIC_KEY='your_public_key'
export LANGFUSE_SECRET_KEY='your_secret_key'
export LANGFUSE_HOST='https://api.langfuse.com'
LangSmith:
export LANGCHAIN_TRACING_V2='true'
export LANGCHAIN_API_KEY='your_api_key'
export LANGCHAIN_PROJECT='your_project_name' # Optional
Viewing Traces#
Once observability is enabled, all agent interactions will be traced and sent to the configured backend (Langfuse or LangSmith). You can log in to your Langfuse dashboard (or LangSmith dashboard) to view detailed traces of each agent run, including:
Agent Decisions: See each thought, action, and observation made by the agent.
Tool Usage: Monitor which tools were invoked and their outputs (or what code was written).
Plan and Observations: Review the agent’s plan progress and observations made during the task.
Performance Metrics: Analyze response times and resource usage.
To view the traces:
Go to https://cloud.langfuse.com (or https://smith.langchain.com)
Find trace by agent class name
Expand to see hierarchical trace tree
A screenshot of a sample trace in Langfuse:
A screenshot of a sample trace in LangSmith:
Trace Hierarchy#
The resulting trace hierarchy looks like this:
Agent.run() [root trace]
├── plan_creation [span]
│ └── (LLM call via ku.call_llm with component_name='Planner.create')
├── [iterations...]
│ ├── think [span] (for ReAct) or think_code [span] (for CodeAct)
│ ├── act [span]
│ ├── plan_update [span]
│ │ └── (LLM call via ku.call_llm with component_name='Planner.update')
│ └── observe [span]
│ └── (LLM call via ku.call_llm with component_name='Observer')
└── post_run [span] (if implemented)
Tracer Module#
Key Classes:
AbstractObservation- Universal observation interfaceAbstractTracerManager- Universal manager interfaceNoOpObservation- No-op observation implementationNoOpTracerManager- No-op manager implementationLangfuseTracerManager- Langfuse integrationLangSmithTracerManager- LangSmith integrationLangSmithObservation- LangSmith-specific observation wrapper
Architecture#
AbstractObservation (interface)
├── NoOpObservation (no-op impl)
├── Langfuse objects (referenced directly)
└── LangSmithObservation (wraps RunTree)
AbstractTracerManager (interface)
├── NoOpTracerManager (no-op impl)
├── LangfuseTracerManager (Langfuse impl)
└── LangSmithTracerManager (LangSmith impl)
Tracing Concepts Mapping#
The following table summarizes how OpenTelemetry (OTel) concepts map to the underlying SDK methods and KodeAgent’s internal tracer.
OTel Concept |
Langfuse SDK |
LangSmith SDK |
KodeAgent Tracer ( |
|---|---|---|---|
Trace (Root) |
|
|
|
Span (Sub-node) |
|
|
|
Generation (LLM) |
|
|
|
Event / Update |
|
|
|
End / Finalize |
|
|
|
Flush / Sync |
|
|
|
LangSmith Implementation Details#
The LangSmithTracerManager requires a few extra steps to ensure traces are recorded reliably. Unlike the Langfuse SDK which often handles background syncing transparently, the LangSmith implementation explicitly calls RunTree.post() upon creation to initialize the run in the backend. During finalization in the end() method, it calls both RunTree.end() to record the outputs and RunTree.patch() to send the final state. Finally, the flush() method is used to ensure all buffered runs are transmitted before the process exits.