Module: Agents::Instrumentation

Defined in:
lib/agents/instrumentation.rb,
lib/agents/instrumentation/constants.rb,
lib/agents/instrumentation/tracing_callbacks.rb

Overview

Optional OpenTelemetry instrumentation for the ai-agents gem. Emits OTel spans for LLM calls, tool executions, and agent handoffs that render correctly in Langfuse and other OTel-compatible backends.

The gem only emits spans — the consumer configures the OTel exporter and provides a tracer. The opentelemetry-api gem is NOT declared as a dependency; consumers must include it in their own bundle.

Examples:

Basic usage

require 'agents/instrumentation'

tracer = OpenTelemetry.tracer_provider.tracer('my_app')
runner = Agents::Runner.with_agents(triage, billing, support)

Agents::Instrumentation.install(runner, tracer: tracer)

With custom trace name

Agents::Instrumentation.install(runner,
  tracer: tracer,
  trace_name: 'customer_support.run'
)

With Langfuse attributes

Agents::Instrumentation.install(runner,
  tracer: tracer,
  span_attributes: { 'langfuse.trace.tags' => ['v2'].to_json },
  attribute_provider: ->(ctx) {
    { 'langfuse.user.id' => ctx.context[:account_id].to_s }
  }
)

Defined Under Namespace

Modules: Constants Classes: TracingCallbacks

Class Method Summary collapse

Class Method Details

.install(runner, tracer:, trace_name: Constants::SPAN_RUN, span_attributes: {}, attribute_provider: nil) ⇒ Agents::AgentRunner?

Install OTel tracing on a runner via callbacks. No-op if opentelemetry-api is not available. Idempotent per runner instance: first install wins.

Session grouping: set ‘context` when calling `runner.run()`. TracingCallbacks automatically reads it per-request and sets `langfuse.session.id`.

Parameters:

  • runner (Agents::AgentRunner)

    The runner to instrument

  • tracer (OpenTelemetry::Trace::Tracer)

    OTel tracer instance

  • trace_name (String) (defaults to: Constants::SPAN_RUN)

    Name for the root span (default: “agents.run”)

  • span_attributes (Hash) (defaults to: {})

    Static attributes applied to the root span

  • attribute_provider (Proc, nil) (defaults to: nil)

    Lambda receiving context_wrapper, returning dynamic attributes

Returns:



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/agents/instrumentation.rb', line 57

def self.install(runner, tracer:, trace_name: Constants::SPAN_RUN, span_attributes: {},
                 attribute_provider: nil)
  return unless otel_available?

  INSTALL_MUTEX.synchronize do
    return runner if instrumentation_installed?(runner)

    callbacks = TracingCallbacks.new(
      tracer: tracer,
      trace_name: trace_name,
      span_attributes: span_attributes,
      attribute_provider: attribute_provider
    )

    register_callbacks(runner, callbacks)
    mark_instrumentation_installed(runner)
  end
  runner
end

.otel_available?Boolean

Check if the opentelemetry-api gem is available.

Returns:

  • (Boolean)

    true if opentelemetry-api can be loaded



102
103
104
105
106
107
# File 'lib/agents/instrumentation.rb', line 102

def self.otel_available?
  require "opentelemetry-api"
  true
rescue LoadError
  false
end