Tracer
Introduction
Overview
Tracers let you observe what the runtime is doing. They hook into requests, tool calls, compactions, and other events. Debug a misbehaving agent, monitor request latency, or export spans to an observability backend. A provider-wide tracer intercepts every request through that provider. An agent-local tracer only covers requests made by that agent.
How it works
When you want to observe runtime events, subclass
LLM::Tracer
and implement the hooks you need.
The built-in tracers include LLM::Tracer::Logger (writes to
stdout or a file) and LLM::Tracer::Telemetry (exports spans
via OTLP for OpenTelemetry).
Why would I use it?
Tracers give you visibility into what the runtime is doing. Debug a misbehaving agent by tracing every request it makes. Monitor request latency and token usage across providers. Export spans to OpenTelemetry for integration with existing observability pipelines.
Notes
The tracer is extensible. You can implement custom hooks for any runtime event. The scope can be an individual agent or every request a provider makes.
Provider
Overview
A provider-wide tracer intercepts every request made through that provider. All agents sharing the same provider share the same tracer. Use this to trace at the infrastructure level without configuring each agent individually.
How it works
When you want every request through a provider to be traced, set the tracer on the provider directly. Every request made through that provider, regardless of which agent initiates it, flows through the same tracer hooks. The provider holds a reference to the tracer and passes it to every new context it creates. This ensures consistent observability without configuring each agent individually.
llm = LLM.deepseek(key: ENV["KEY"])
llm.tracer = LLM::Tracer::Logger.new(llm, io: $stdout)
Why would I use it?
A provider-wide tracer captures every request at the infrastructure level. All agents sharing the same provider share the same tracer.
Notes
The tracer can also write to a file: LLM::Tracer::Logger.new(llm,
path: "deepseek.log").
Agent
Overview
An agent-local tracer only covers requests made by that agent.
Attach it via LLM::Agent.new(llm, tracer: ...) and it follows
that agent wherever it goes. Different agents can have different
tracers.
How it works
When you want a tracer for a specific agent, pass it to the agent on creation. Only requests made by that agent flow through the tracer, leaving other agents on the same provider unaffected.
llm = LLM.deepseek(key: ENV["KEY"])
agent = LLM::Agent.new(llm, tracer: LLM::Tracer::Logger.new(llm, io: $stdout))
Why would I use it?
Agent-local tracers let each agent log differently. One agent might log to stdout, another to a file, a third to OpenTelemetry.
Notes
The tracer can also write to a file: LLM::Tracer::Logger.new(llm,
path: "deepseek-agent.log").