Module: RubyLLM::Agents

Defined in:
lib/ruby_llm/agents.rb,
lib/ruby_llm/agents/dsl.rb,
lib/ruby_llm/agents/tool.rb,
lib/ruby_llm/agents/routing.rb,
lib/ruby_llm/agents/tracker.rb,
lib/ruby_llm/agents/dsl/base.rb,
lib/ruby_llm/agents/pipeline.rb,
lib/ruby_llm/agents/core/base.rb,
lib/ruby_llm/agents/base_agent.rb,
lib/ruby_llm/agents/core/errors.rb,
lib/ruby_llm/agents/dsl/caching.rb,
lib/ruby_llm/agents/core/version.rb,
lib/ruby_llm/agents/image/editor.rb,
lib/ruby_llm/agents/rails/engine.rb,
lib/ruby_llm/agents/results/base.rb,
lib/ruby_llm/agents/stream_event.rb,
lib/ruby_llm/agents/tool_context.rb,
lib/ruby_llm/agents/track_report.rb,
app/models/ruby_llm/agents/tenant.rb,
lib/ruby_llm/agents/audio/speaker.rb,
lib/ruby_llm/agents/dsl/knowledge.rb,
lib/ruby_llm/agents/dsl/queryable.rb,
lib/ruby_llm/agents/eval/eval_run.rb,
lib/ruby_llm/agents/text/embedder.rb,
lib/ruby_llm/agents/image/analyzer.rb,
lib/ruby_llm/agents/image/pipeline.rb,
lib/ruby_llm/agents/image/upscaler.rb,
lib/ruby_llm/agents/image/variator.rb,
lib/ruby_llm/agents/routing/result.rb,
lib/ruby_llm/agents/core/llm_tenant.rb,
lib/ruby_llm/agents/dsl/reliability.rb,
lib/ruby_llm/agents/eval/eval_suite.rb,
lib/ruby_llm/agents/image/generator.rb,
app/models/ruby_llm/agents/execution.rb,
lib/ruby_llm/agents/eval/eval_result.rb,
lib/ruby_llm/agents/image/editor/dsl.rb,
lib/ruby_llm/agents/pipeline/builder.rb,
lib/ruby_llm/agents/pipeline/context.rb,
lib/ruby_llm/agents/audio/transcriber.rb,
lib/ruby_llm/agents/core/deprecations.rb,
lib/ruby_llm/agents/image/transformer.rb,
lib/ruby_llm/agents/pipeline/executor.rb,
lib/ruby_llm/agents/results/trackable.rb,
lib/ruby_llm/agents/core/configuration.rb,
lib/ruby_llm/agents/image/analyzer/dsl.rb,
lib/ruby_llm/agents/image/pipeline/dsl.rb,
lib/ruby_llm/agents/image/upscaler/dsl.rb,
lib/ruby_llm/agents/image/variator/dsl.rb,
lib/ruby_llm/agents/pricing/data_store.rb,
lib/ruby_llm/agents/audio/speech_client.rb,
lib/ruby_llm/agents/core/base/callbacks.rb,
lib/ruby_llm/agents/providers/inception.rb,
app/models/ruby_llm/agents/tenant_budget.rb,
lib/ruby_llm/agents/audio/speech_pricing.rb,
lib/ruby_llm/agents/core/instrumentation.rb,
app/models/ruby_llm/agents/agent_override.rb,
app/models/ruby_llm/agents/tool_execution.rb,
lib/ruby_llm/agents/image/transformer/dsl.rb,
lib/ruby_llm/agents/results/speech_result.rb,
lib/ruby_llm/agents/routing/class_methods.rb,
lib/ruby_llm/agents/image/editor/execution.rb,
app/models/ruby_llm/agents/execution/scopes.rb,
app/models/ruby_llm/agents/execution_detail.rb,
app/models/ruby_llm/agents/tenant/trackable.rb,
app/services/ruby_llm/agents/agent_registry.rb,
lib/ruby_llm/agents/image/generator/pricing.rb,
lib/ruby_llm/agents/pricing/litellm_adapter.rb,
lib/ruby_llm/agents/pricing/portkey_adapter.rb,
app/models/ruby_llm/agents/execution/metrics.rb,
app/models/ruby_llm/agents/tenant/budgetable.rb,
app/models/ruby_llm/agents/tenant/resettable.rb,
lib/ruby_llm/agents/image/analyzer/execution.rb,
lib/ruby_llm/agents/image/background_remover.rb,
lib/ruby_llm/agents/image/pipeline/execution.rb,
lib/ruby_llm/agents/image/upscaler/execution.rb,
lib/ruby_llm/agents/image/variator/execution.rb,
lib/ruby_llm/agents/pipeline/middleware/base.rb,
lib/ruby_llm/agents/pricing/helicone_adapter.rb,
lib/ruby_llm/agents/pricing/ruby_llm_adapter.rb,
lib/ruby_llm/agents/providers/inception/chat.rb,
lib/ruby_llm/agents/results/embedding_result.rb,
lib/ruby_llm/agents/image/generator/templates.rb,
lib/ruby_llm/agents/pipeline/middleware/cache.rb,
lib/ruby_llm/agents/results/image_edit_result.rb,
app/helpers/ruby_llm/agents/application_helper.rb,
app/models/ruby_llm/agents/execution/analytics.rb,
lib/ruby_llm/agents/infrastructure/reliability.rb,
lib/ruby_llm/agents/pipeline/middleware/budget.rb,
lib/ruby_llm/agents/pipeline/middleware/tenant.rb,
lib/ruby_llm/agents/pricing/llmpricing_adapter.rb,
lib/ruby_llm/agents/pricing/openrouter_adapter.rb,
lib/ruby_llm/agents/providers/inception/models.rb,
app/models/ruby_llm/agents/execution/replayable.rb,
app/models/ruby_llm/agents/tenant/incrementable.rb,
lib/ruby_llm/agents/audio/transcription_pricing.rb,
lib/ruby_llm/agents/image/transformer/execution.rb,
lib/ruby_llm/agents/infrastructure/cache_helper.rb,
lib/ruby_llm/agents/image/background_remover/dsl.rb,
lib/ruby_llm/agents/infrastructure/alert_manager.rb,
lib/ruby_llm/agents/infrastructure/retention_job.rb,
lib/ruby_llm/agents/providers/inception/registry.rb,
lib/ruby_llm/agents/results/image_upscale_result.rb,
lib/ruby_llm/agents/results/transcription_result.rb,
app/controllers/concerns/ruby_llm/agents/sortable.rb,
app/controllers/ruby_llm/agents/agents_controller.rb,
lib/ruby_llm/agents/infrastructure/budget_tracker.rb,
lib/ruby_llm/agents/results/image_analysis_result.rb,
lib/ruby_llm/agents/results/image_pipeline_result.rb,
app/controllers/ruby_llm/agents/tenants_controller.rb,
lib/ruby_llm/agents/infrastructure/attempt_tracker.rb,
lib/ruby_llm/agents/infrastructure/circuit_breaker.rb,
lib/ruby_llm/agents/results/image_transform_result.rb,
lib/ruby_llm/agents/results/image_variation_result.rb,
app/controllers/concerns/ruby_llm/agents/filterable.rb,
app/controllers/ruby_llm/agents/requests_controller.rb,
lib/ruby_llm/agents/audio/elevenlabs/model_registry.rb,
lib/ruby_llm/agents/pipeline/middleware/reliability.rb,
lib/ruby_llm/agents/results/image_generation_result.rb,
app/controllers/concerns/ruby_llm/agents/paginatable.rb,
app/controllers/ruby_llm/agents/analytics_controller.rb,
app/controllers/ruby_llm/agents/dashboard_controller.rb,
lib/ruby_llm/agents/infrastructure/budget/forecaster.rb,
lib/ruby_llm/agents/providers/inception/capabilities.rb,
app/controllers/ruby_llm/agents/executions_controller.rb,
lib/ruby_llm/agents/results/background_removal_result.rb,
lib/ruby_llm/agents/image/background_remover/execution.rb,
lib/ruby_llm/agents/image/concerns/image_operation_dsl.rb,
lib/ruby_llm/agents/infrastructure/budget/budget_query.rb,
lib/ruby_llm/agents/infrastructure/execution_logger_job.rb,
lib/ruby_llm/agents/pipeline/middleware/instrumentation.rb,
app/controllers/ruby_llm/agents/system_config_controller.rb,
lib/ruby_llm/agents/audio/speaker/active_storage_support.rb,
lib/ruby_llm/agents/infrastructure/budget/spend_recorder.rb,
lib/ruby_llm/agents/infrastructure/budget/config_resolver.rb,
lib/ruby_llm/agents/image/generator/active_storage_support.rb,
lib/ruby_llm/agents/image/concerns/image_operation_execution.rb

Overview

Agent framework for building LLM-powered agents with observability

RubyLLM::Agents provides a DSL for creating agents that interact with large language models, with built-in execution tracking, cost monitoring, and a dashboard for observability.

Examples:

Basic configuration

RubyLLM::Agents.configure do |config|
  config.default_model = "gpt-4o"
  config.async_logging = true
end

Creating an agent

class SearchAgent < ApplicationAgent
  model "gpt-4o"
  param :query, required: true

  def user_prompt
    "Search for: #{query}"
  end
end

SearchAgent.call(query: "ruby gems")

See Also:

Defined Under Namespace

Modules: AlertManager, ApplicationHelper, Audio, Budget, BudgetTracker, CacheHelper, CallbacksDSL, CallbacksExecution, Concerns, DSL, Deprecations, Eval, Filterable, Instrumentation, LLMTenant, Paginatable, Pipeline, Pricing, Providers, Reliability, Routing, Sortable, Trackable Classes: AgentOverride, AgentRegistry, AgentsController, AnalyticsController, AttemptTracker, BackgroundRemovalResult, BackgroundRemover, Base, BaseAgent, CachedBackgroundRemovalResult, CachedImageAnalysisResult, CachedImageEditResult, CachedImageGenerationResult, CachedImagePipelineResult, CachedImageTransformResult, CachedImageUpscaleResult, CachedImageVariationResult, CancelledError, CircuitBreaker, Configuration, ConfigurationError, DashboardController, Embedder, EmbeddingResult, Engine, Error, Execution, ExecutionDetail, ExecutionLoggerJob, ExecutionsController, ImageAnalysisResult, ImageAnalyzer, ImageEditResult, ImageEditor, ImageGenerationResult, ImageGenerator, ImagePipeline, ImagePipelineResult, ImageTransformResult, ImageTransformer, ImageUpscaleResult, ImageUpscaler, ImageVariationResult, ImageVariator, ReplayError, RequestsController, Result, RetentionJob, Speaker, SpeechApiError, SpeechResult, StreamEvent, SystemConfigController, Tenant, TenantsController, Tool, ToolContext, ToolExecution, TrackReport, Tracker, Transcriber, TranscriptionResult, UnsupportedProviderError

Constant Summary collapse

VERSION =

Current version of the RubyLLM::Agents gem

Returns:

  • (String)

    Semantic version string

"3.13.0"
TenantBudget =
Deprecated.

Use Tenant instead. This class will be removed in a future major version.

TenantBudget is now an alias to Tenant for backward compatibility. All functionality has been moved to the Tenant model with organized concerns.

Examples:

Migration path

# Old usage (still works but emits deprecation warning)
TenantBudget.for_tenant("acme_corp")

# New usage (preferred)
Tenant.for("acme_corp")

See Also:

Tenant

Class Method Summary collapse

Class Method Details

.agentsArray<Hash>

Returns all registered agents with their stats.

Examples:

RubyLLM::Agents.agents
# => [{ name: "ChatAgent", active: true, model: "gpt-4o", ... }]

Returns:

  • (Array<Hash>)

    Agent info with name, model, stats, etc.



315
316
317
# File 'lib/ruby_llm/agents.rb', line 315

def agents
  AgentRegistry.all_with_details
end

.configurationConfiguration

Returns the global configuration instance

Returns:



198
199
200
# File 'lib/ruby_llm/agents.rb', line 198

def configuration
  @configuration ||= Configuration.new
end

.configure {|Configuration| ... } ⇒ void

This method returns an undefined value.

Yields the configuration for modification

Examples:

RubyLLM::Agents.configure do |config|
  config.default_model = "claude-3-sonnet"
end

Yields:



210
211
212
# File 'lib/ruby_llm/agents.rb', line 210

def configure
  yield(configuration)
end

.costs(period: :today, tenant: nil) ⇒ Hash{String => Hash}

Returns cost breakdown by agent for a period.

Examples:

RubyLLM::Agents.costs(period: :this_month)
# => { "ChatAgent" => { cost: 12.50, count: 1000, avg_cost: 0.0125 } }

Parameters:

  • period (Symbol, Range) (defaults to: :today)

    Time period (see #usage)

  • tenant (String, Object, nil) (defaults to: nil)

    Optional tenant filter

Returns:

  • (Hash{String => Hash})

    Agent name => { cost:, count:, avg_cost: }



290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
# File 'lib/ruby_llm/agents.rb', line 290

def costs(period: :today, tenant: nil)
  scope = scope_for_period(Execution, period)
  scope = scope_for_tenant(scope, tenant) if tenant

  scope.group(:agent_type).pluck(
    :agent_type,
    Arel.sql("COUNT(*)"),
    Arel.sql("SUM(total_cost)"),
    Arel.sql("AVG(total_cost)")
  ).each_with_object({}) do |(agent, count, total, avg), hash|
    hash[agent] = {
      cost: total&.to_f&.round(6) || 0,
      count: count,
      avg_cost: avg&.to_f&.round(6) || 0
    }
  end
end

.executionsActiveRecord::Relation

Returns a chainable scope of all executions.

Examples:

Recent successful executions

RubyLLM::Agents.executions.successful.recent(10)

Filter by agent

RubyLLM::Agents.executions.by_agent("ChatAgent").today

Returns:

  • (ActiveRecord::Relation)

    All executions



239
240
241
# File 'lib/ruby_llm/agents.rb', line 239

def executions
  Execution.all
end

.rename_agent(old_name, to:, dry_run: false) ⇒ Hash

Renames an agent in the database, updating execution records and tenant budget configuration keys

Examples:

Rename an agent

RubyLLM::Agents.rename_agent("CustomerSupportAgent", to: "SupportBot")
# => { executions_updated: 1432, tenants_updated: 3 }

Dry run first

RubyLLM::Agents.rename_agent("CustomerSupportAgent", to: "SupportBot", dry_run: true)
# => { executions_affected: 1432, tenants_affected: 3 }

Parameters:

  • old_name (String)

    The previous agent class name

  • to (String)

    The new agent class name

  • dry_run (Boolean) (defaults to: false)

    If true, returns counts without modifying data

Returns:

  • (Hash)

    Summary of affected records

Raises:

  • (ArgumentError)


379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
# File 'lib/ruby_llm/agents.rb', line 379

def rename_agent(old_name, to:, dry_run: false)
  old_name = old_name.to_s
  new_name = to.to_s

  raise ArgumentError, "old_name and new name must be different" if old_name == new_name
  raise ArgumentError, "old_name cannot be blank" if old_name.blank?
  raise ArgumentError, "new name cannot be blank" if new_name.blank?

  execution_scope = Execution.where(agent_type: old_name)
  execution_count = execution_scope.count

  tenant_count = 0
  if defined?(Tenant) && Tenant.table_exists?
    Tenant.find_each do |tenant|
      changed = false
      %w[per_agent_daily per_agent_monthly].each do |field|
        hash = tenant.send(field)
        next unless hash.is_a?(Hash) && hash.key?(old_name)
        changed = true
        break
      end
      tenant_count += 1 if changed
    end
  end

  if dry_run
    {executions_affected: execution_count, tenants_affected: tenant_count}
  else
    executions_updated = execution_scope.update_all(agent_type: new_name)

    tenants_updated = 0
    if defined?(Tenant) && Tenant.table_exists?
      Tenant.find_each do |tenant|
        changed = false
        %w[per_agent_daily per_agent_monthly].each do |field|
          hash = tenant.send(field)
          next unless hash.is_a?(Hash) && hash.key?(old_name)
          hash[new_name] = hash.delete(old_name)
          tenant.send(:"#{field}=", hash)
          changed = true
        end
        if changed
          tenant.save!
          tenants_updated += 1
        end
      end
    end

    {executions_updated: executions_updated, tenants_updated: tenants_updated}
  end
end

.reset_configuration!Configuration

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Resets configuration to defaults

Primarily used for testing to ensure clean state.

Returns:



220
221
222
# File 'lib/ruby_llm/agents.rb', line 220

def reset_configuration!
  @configuration = Configuration.new
end

.tenant_for(tenant) ⇒ RubyLLM::Agents::Tenant?

Returns a tenant’s usage data.

Examples:

tenant = RubyLLM::Agents.tenant_for(current_user)
tenant.cost_today       # => 0.42
tenant.budget_status    # => { enabled: true, enforcement: :soft, ... }

Parameters:

  • tenant (String, Object)

    Tenant ID or object with llm_tenant_id

Returns:



328
329
330
331
332
# File 'lib/ruby_llm/agents.rb', line 328

def tenant_for(tenant)
  Tenant.for(tenant)
rescue
  nil
end

.track(tenant: nil, request_id: nil, tags: {}, **defaults) { ... } ⇒ TrackReport

Wraps a block of agent calls, collecting all Results and returning an aggregated TrackReport.

Shared options (tenant, tags, request_id) are injected into every agent instantiated inside the block unless overridden.

Examples:

Basic usage

report = RubyLLM::Agents.track do
  ChatAgent.call(query: "hello")
  SummaryAgent.call(text: "...")
end
report.total_cost  # => 0.015

With shared tenant

report = RubyLLM::Agents.track(tenant: current_user) do
  AgentA.call(query: "test")
end

Parameters:

  • tenant (Hash, Object, nil) (defaults to: nil)

    Shared tenant for all calls

  • request_id (String, nil) (defaults to: nil)

    Shared request ID (auto-generated if nil)

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

    Tags merged into each execution’s metadata

  • defaults (Hash)

    Additional shared options for agents

Yields:

  • Block containing agent calls to track

Returns:



156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/ruby_llm/agents.rb', line 156

def track(tenant: nil, request_id: nil, tags: {}, **defaults)
  defaults[:tenant] = tenant if tenant
  tracker = Tracker.new(defaults: defaults, request_id: request_id, tags: tags)

  # Stack trackers for nesting support
  previous_tracker = Thread.current[:ruby_llm_agents_tracker]
  Thread.current[:ruby_llm_agents_tracker] = tracker

  started_at = Time.current
  value = nil
  error = nil

  begin
    value = yield
  rescue => e
    error = e
  end

  completed_at = Time.current

  report = TrackReport.new(
    value: value,
    error: error,
    results: tracker.results,
    request_id: tracker.request_id,
    started_at: started_at,
    completed_at: completed_at
  )

  # Bubble results up to parent tracker if nested
  if previous_tracker
    tracker.results.each { |r| previous_tracker << r }
  end

  report
ensure
  Thread.current[:ruby_llm_agents_tracker] = previous_tracker
end

.usage(period: :today, agent: nil, tenant: nil) ⇒ Hash

Returns a usage summary for a given period.

Examples:

Global usage today

RubyLLM::Agents.usage(period: :today)

Per-agent usage

RubyLLM::Agents.usage(period: :this_month, agent: "ChatAgent")

Per-tenant usage

RubyLLM::Agents.usage(period: :this_week, tenant: current_user)

Parameters:

  • period (Symbol, Range) (defaults to: :today)

    :today, :yesterday, :this_week, :this_month, :last_7_days, :last_30_days, or a custom Time range

  • agent (String, Class, nil) (defaults to: nil)

    Optional agent class or name to filter by

  • tenant (String, Object, nil) (defaults to: nil)

    Optional tenant ID or object to filter by

Returns:

  • (Hash)

    Usage summary with keys: :executions, :successful, :failed, :success_rate, :total_cost, :total_tokens, :avg_duration_ms, :avg_cost



261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
# File 'lib/ruby_llm/agents.rb', line 261

def usage(period: :today, agent: nil, tenant: nil)
  scope = scope_for_period(Execution, period)
  scope = scope.by_agent(agent_name_for(agent)) if agent
  scope = scope_for_tenant(scope, tenant) if tenant

  total = scope.count
  successful = scope.successful.count

  {
    executions: total,
    successful: successful,
    failed: scope.failed.count,
    success_rate: total.zero? ? 0.0 : (successful.to_f / total * 100).round(1),
    total_cost: scope.sum(:total_cost),
    total_tokens: scope.sum(:total_tokens),
    avg_duration_ms: scope.average(:duration_ms)&.round,
    avg_cost: total.zero? ? 0 : (scope.sum(:total_cost).to_f / total).round(6)
  }
end