Module: RubyLLM::Agents::DSL::Reliability

Included in:
BaseAgent
Defined in:
lib/ruby_llm/agents/dsl/reliability.rb

Overview

Reliability DSL for retries, fallbacks, and circuit breakers.

This module provides configuration methods for reliability features that can be mixed into any agent class.

Examples:

Block-style configuration

class MyAgent < RubyLLM::Agents::BaseAgent
  extend DSL::Reliability

  reliability do
    retries max: 3, backoff: :exponential
    fallback_models "gpt-4o-mini"
    total_timeout 30
    circuit_breaker errors: 5, within: 60
  end
end

Individual method configuration

class MyAgent < RubyLLM::Agents::BaseAgent
  extend DSL::Reliability

  retries max: 3
  fallback_models "gpt-4o-mini", "gpt-3.5-turbo"
end

Defined Under Namespace

Classes: OnFailureBuilder, ReliabilityBuilder

Reliability DSL collapse

Instance Method Details

#circuit_breaker(errors: nil, within: nil, cooldown: nil) ⇒ Hash?

Configures circuit breaker for this agent

Examples:

circuit_breaker errors: 10, within: 60, cooldown: 300

Parameters:

  • errors (Integer) (defaults to: nil)

    Number of errors to trigger open state

  • within (Integer) (defaults to: nil)

    Rolling window in seconds

  • cooldown (Integer) (defaults to: nil)

    Cooldown period in seconds when open

Returns:

  • (Hash, nil)

    The current circuit breaker configuration



202
203
204
205
206
207
208
209
210
# File 'lib/ruby_llm/agents/dsl/reliability.rb', line 202

def circuit_breaker(errors: nil, within: nil, cooldown: nil)
  if errors || within || cooldown
    @circuit_breaker_config ||= {errors: 10, within: 60, cooldown: 300}
    @circuit_breaker_config[:errors] = errors if errors
    @circuit_breaker_config[:within] = within if within
    @circuit_breaker_config[:cooldown] = cooldown if cooldown
  end
  @circuit_breaker_config || inherited_circuit_breaker_config
end

#circuit_breaker_configHash?

Returns the circuit breaker configuration

Returns:

  • (Hash, nil)

    The circuit breaker configuration



215
216
217
# File 'lib/ruby_llm/agents/dsl/reliability.rb', line 215

def circuit_breaker_config
  @circuit_breaker_config || inherited_circuit_breaker_config
end

#fallback_models(*models) ⇒ Array<String>

Sets or returns fallback models to try when primary model fails

Examples:

fallback_models "gpt-4o-mini", "gpt-3.5-turbo"

Parameters:

  • models (Array<String>)

    Model identifiers to use as fallbacks

Returns:

  • (Array<String>)

    The current fallback models



153
154
155
156
# File 'lib/ruby_llm/agents/dsl/reliability.rb', line 153

def fallback_models(*models)
  @fallback_models = models.flatten if models.any?
  @fallback_models || inherited_fallback_models || []
end

#fallback_provider(provider = nil, **options) ⇒ Array<Hash>

Sets or returns fallback providers to try when primary provider fails

Used primarily by audio agents (Speaker, Transcriber) that may need to fall back to a different provider entirely.

Examples:

fallback_provider :openai, voice: "nova"

Parameters:

  • provider (Symbol) (defaults to: nil)

    The provider to fall back to

  • options (Hash)

    Provider-specific options (e.g., voice:, model:)

Returns:

  • (Array<Hash>)

    The current fallback providers



168
169
170
171
172
173
174
# File 'lib/ruby_llm/agents/dsl/reliability.rb', line 168

def fallback_provider(provider = nil, **options)
  if provider
    @fallback_providers ||= []
    @fallback_providers << {provider: provider, **options}
  end
  @fallback_providers || inherited_fallback_providers || []
end

#fallback_providersArray<Hash>

Returns the fallback providers list

Returns:

  • (Array<Hash>)

    The fallback providers



179
180
181
# File 'lib/ruby_llm/agents/dsl/reliability.rb', line 179

def fallback_providers
  @fallback_providers || inherited_fallback_providers || []
end

#non_fallback_errors(*error_classes) ⇒ Array<Class>?

Sets or returns additional error classes that should never trigger fallback

Examples:

non_fallback_errors MyValidationError, MySchemaError

Parameters:

  • error_classes (Array<Class>)

    Error classes that should fail immediately

Returns:

  • (Array<Class>, nil)

    The current non-fallback error classes



236
237
238
239
# File 'lib/ruby_llm/agents/dsl/reliability.rb', line 236

def non_fallback_errors(*error_classes)
  @non_fallback_errors = error_classes.flatten if error_classes.any?
  @non_fallback_errors || inherited_non_fallback_errors
end

#on_failure { ... } ⇒ void

This method returns an undefined value.

Alias for reliability with clearer intent-revealing name

Configures what happens when an LLM call fails. This is the preferred method in the simplified DSL.

Examples:

on_failure do
  retry times: 3, backoff: :exponential
  fallback to: ["gpt-4o-mini", "gpt-3.5-turbo"]
  circuit_breaker after: 5, cooldown: 5.minutes
  timeout 30.seconds
end

Yields:

  • Block containing failure handling configuration



76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/ruby_llm/agents/dsl/reliability.rb', line 76

def on_failure(&block)
  builder = OnFailureBuilder.new
  builder.instance_eval(&block)

  @retries_config = builder.retries_config if builder.retries_config
  @fallback_models = builder.fallback_models_list if builder.fallback_models_list.any?
  @fallback_providers = builder.fallback_providers_list if builder.fallback_providers_list.any?
  @total_timeout = builder.total_timeout_value if builder.total_timeout_value
  @circuit_breaker_config = builder.circuit_breaker_config if builder.circuit_breaker_config
  @retryable_patterns = builder.retryable_patterns_list if builder.retryable_patterns_list
  @non_fallback_errors = builder.non_fallback_errors_list if builder.non_fallback_errors_list
end

#reliability { ... } ⇒ void

This method returns an undefined value.

Configures reliability features using a block syntax

Groups all reliability configuration in a single block for clarity.

Examples:

reliability do
  retries max: 3, backoff: :exponential
  fallback_models "gpt-4o-mini"
  total_timeout 30
  circuit_breaker errors: 5
end

Yields:

  • Block containing reliability configuration



47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/ruby_llm/agents/dsl/reliability.rb', line 47

def reliability(&block)
  builder = ReliabilityBuilder.new
  builder.instance_eval(&block)

  @retries_config = builder.retries_config if builder.retries_config
  @fallback_models = builder.fallback_models_list if builder.fallback_models_list.any?
  @fallback_providers = builder.fallback_providers_list if builder.fallback_providers_list.any?
  @total_timeout = builder.total_timeout_value if builder.total_timeout_value
  @circuit_breaker_config = builder.circuit_breaker_config if builder.circuit_breaker_config
  @retryable_patterns = builder.retryable_patterns_list if builder.retryable_patterns_list
  @non_fallback_errors = builder.non_fallback_errors_list if builder.non_fallback_errors_list
end

#reliability_configHash?

Returns the complete reliability configuration hash

Used by the Reliability middleware to get all settings.

Returns:

  • (Hash, nil)

    The reliability configuration



94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/ruby_llm/agents/dsl/reliability.rb', line 94

def reliability_config
  return nil unless reliability_configured?

  {
    retries: retries_config,
    fallback_models: fallback_models,
    fallback_providers: fallback_providers,
    total_timeout: total_timeout,
    circuit_breaker: circuit_breaker_config,
    retryable_patterns: retryable_patterns,
    non_fallback_errors: non_fallback_errors
  }.compact
end

#reliability_configured?Boolean

Checks if any reliability features are configured

Returns:

  • (Boolean)

    true if reliability is configured



111
112
113
114
115
116
# File 'lib/ruby_llm/agents/dsl/reliability.rb', line 111

def reliability_configured?
  (retries_config && retries_config[:max]&.positive?) ||
    fallback_models.any? ||
    fallback_providers.any? ||
    circuit_breaker_config.present?
end

#retries(max: nil, backoff: nil, base: nil, max_delay: nil, on: nil) ⇒ Hash

Configures retry behavior for this agent

Examples:

retries max: 2, backoff: :exponential

Parameters:

  • max (Integer) (defaults to: nil)

    Maximum number of retry attempts (default: 0)

  • backoff (Symbol) (defaults to: nil)

    Backoff strategy (:constant or :exponential)

  • base (Float) (defaults to: nil)

    Base delay in seconds

  • max_delay (Float) (defaults to: nil)

    Maximum delay between retries

  • on (Array<Class>) (defaults to: nil)

    Error classes to retry on (extends defaults)

Returns:

  • (Hash)

    The current retry configuration



128
129
130
131
132
133
134
135
136
137
138
# File 'lib/ruby_llm/agents/dsl/reliability.rb', line 128

def retries(max: nil, backoff: nil, base: nil, max_delay: nil, on: nil)
  if max || backoff || base || max_delay || on
    @retries_config ||= default_retries_config.dup
    @retries_config[:max] = max if max
    @retries_config[:backoff] = backoff if backoff
    @retries_config[:base] = base if base
    @retries_config[:max_delay] = max_delay if max_delay
    @retries_config[:on] = on if on
  end
  @retries_config || inherited_retry_config || default_retries_config
end

#retries_configHash?

Returns the retry configuration

Returns:

  • (Hash, nil)

    The retry configuration



143
144
145
# File 'lib/ruby_llm/agents/dsl/reliability.rb', line 143

def retries_config
  @retries_config || inherited_retry_config
end

#retryable_patterns(*patterns) ⇒ Array<String>?

Sets or returns additional retryable patterns for error message matching

Examples:

retryable_patterns "custom_error", "another_pattern"

Parameters:

  • patterns (Array<String>)

    Pattern strings to match in error messages

Returns:

  • (Array<String>, nil)

    The current retryable patterns



225
226
227
228
# File 'lib/ruby_llm/agents/dsl/reliability.rb', line 225

def retryable_patterns(*patterns)
  @retryable_patterns = patterns.flatten if patterns.any?
  @retryable_patterns || inherited_retryable_patterns
end

#total_timeout(seconds = nil) ⇒ Integer?

Sets or returns the total timeout for all retry/fallback attempts

Examples:

total_timeout 30

Parameters:

  • seconds (Integer, nil) (defaults to: nil)

    Total timeout in seconds

Returns:

  • (Integer, nil)

    The current total timeout



189
190
191
192
# File 'lib/ruby_llm/agents/dsl/reliability.rb', line 189

def total_timeout(seconds = nil)
  @total_timeout = seconds if seconds
  @total_timeout || inherited_total_timeout
end