Tracers receive execution spans from the agent loop — LLM calls, tool executions, sub-agent delegations — and forward them to your observability backend. You can attach one tracer or several; when you provide multiple, NexAU automatically wraps them in a CompositeTracer so every span fans out to all backends.
Langfuse setup
Add a tracers list to your agent YAML. Use ${env.VAR_NAME} to read secrets from environment variables.# agent.yaml
name: traced_agent
llm_config:
model: gpt-4o-mini
tracers:
- import: nexau.archs.tracer.adapters.langfuse:LangfuseTracer
params:
public_key: ${env.LANGFUSE_PUBLIC_KEY}
secret_key: ${env.LANGFUSE_SECRET_KEY}
host: https://cloud.langfuse.com
tools: []
Set your keys as environment variables before running the agent:export LANGFUSE_PUBLIC_KEY="pk-lf-..."
export LANGFUSE_SECRET_KEY="sk-lf-..."
Pass tracer instances directly when constructing AgentConfig. This is useful for tests or custom runners that don’t use YAML files.from nexau.archs.main_sub.agent import Agent
from nexau.archs.main_sub.config import AgentConfig
from nexau.archs.tracer.adapters.langfuse import LangfuseTracer
from nexau.archs.main_sub.agent_context import GlobalStorage
tracer = LangfuseTracer(
public_key="pk-lf-...",
secret_key="sk-lf-...",
host="https://cloud.langfuse.com",
)
agent_config = AgentConfig(
name="traced_agent",
llm_config={"model": "gpt-4o-mini"},
tools=[],
tracers=[tracer],
)
agent = Agent(config=agent_config, global_storage=GlobalStorage())
Multiple tracers
List more than one entry under tracers to send spans to multiple backends simultaneously. NexAU creates a CompositeTracer automatically — no extra code required.
tracers:
- import: nexau.archs.tracer.adapters.langfuse:LangfuseTracer
params:
public_key: ${env.LANGFUSE_PUBLIC_KEY}
secret_key: ${env.LANGFUSE_SECRET_KEY}
host: https://cloud.langfuse.com
- import: mypkg.telemetry:ConsoleTracer
Every span produced by the agent is forwarded to both LangfuseTracer and ConsoleTracer.
The tracer is stored in global_storage under the key "tracer". You can retrieve it anywhere you have access to global_storage — including tools, hooks, and custom execution components.
from nexau.archs.tracer.core import SpanType
tracer = global_storage.get("tracer")
if tracer:
span = tracer.start_span("my_tool", SpanType.TOOL)
# ... do work ...
tracer.end_span(span, outputs={"result": "done"})
If no tracer is configured, global_storage.get("tracer") returns None. Guard with if tracer: before calling span methods.
The tracer is written into the root GlobalStorage when the agent is constructed, so any sub-agent created through delegation automatically observes the same tracer without any additional wiring.