Module: RubyLLM::Agents::DSL::Base

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

Overview

Base DSL available to all agents.

Provides common configuration methods that every agent type needs:

  • model: The LLM model to use

  • system: System instructions

  • user: The user prompt (string with placeholders)

  • assistant: Assistant prefill (string with optional placeholders)

  • description: Human-readable description

  • timeout: Request timeout

  • returns: Structured output schema

Two levels for defining prompts:

  • Class-level string/heredoc for static content

  • Instance method override for dynamic content

Examples:

Template agent (structured input via .call)

class SearchAgent < RubyLLM::Agents::BaseAgent
  model "gpt-4o"
  system "You are a helpful search assistant."
  user "Search for: {query} (limit: {limit})"
  assistant '{"results":['

  param :limit, default: 10  # Override auto-detected param

  returns do
    array :results do
      string :title
      string :url
    end
  end
end

Conversational agent (freeform input via .ask)

class RubyExpert < RubyLLM::Agents::BaseAgent
  model "gpt-4o"
  system "You are a senior Ruby developer."
end

RubyExpert.ask("What is metaprogramming?")

Dashboard-overridable settings

class SupportAgent < RubyLLM::Agents::BaseAgent
  model "gpt-4o", overridable: true        # can be changed from the dashboard
  temperature 0.7, overridable: true        # can be changed from the dashboard
  timeout 30                                # locked to code value
end

Dynamic prompts with method overrides

class SmartAgent < RubyLLM::Agents::BaseAgent
  def system_prompt
    "You are helping #{company.name}. Today is #{Date.today}."
  end

  def user_prompt
    "Question: #{params[:question]}"
  end
end

Constant Summary collapse

PLACEHOLDER_PATTERN =

Regex pattern to extract placeholder parameters from prompt strings

/\{(\w+)\}/

Configuration DSL collapse

Dashboard Override Support collapse

Instance Method Details

#active_overridesHash{String => Object}

Returns the currently active dashboard overrides for this agent

Only returns overrides for fields that are declared overridable.

Returns:

  • (Hash{String => Object})

    Active override values



331
332
333
334
335
336
# File 'lib/ruby_llm/agents/dsl/base.rb', line 331

def active_overrides
  return {} unless overridable?

  raw = load_overrides
  raw.select { |field, _| overridable_fields.include?(field.to_sym) }
end

#assistant(text = nil) ⇒ String?

Sets the assistant prefill string

The assistant prefill is sent as the last message with the “assistant” role, priming the model to continue from that point. Useful for:

  • Forcing output format (e.g., starting with “for JSON)

  • Steering the response style

Supports {placeholder syntax for parameter interpolation.

Examples:

Force JSON output

assistant '{"category":'

With placeholders

assistant "Results for {query}:"

Parameters:

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

    The assistant prefill text

Returns:

  • (String, nil)

    The current assistant configuration



191
192
193
194
195
196
197
# File 'lib/ruby_llm/agents/dsl/base.rb', line 191

def assistant(text = nil)
  if text
    @assistant_template = text
    auto_register_params_from_template(text)
  end
  @assistant_template || inherited_or_default(:assistant_config, nil)
end

#assistant_configString?

Returns the assistant prefill configuration

Returns:

  • (String, nil)

    The assistant template, or nil



202
203
204
# File 'lib/ruby_llm/agents/dsl/base.rb', line 202

def assistant_config
  @assistant_template || inherited_or_default(:assistant_config, nil)
end

#cache_prompts(value = nil) ⇒ Boolean

Enables Anthropic prompt caching for this agent

When enabled, adds cache_control breakpoints to the system prompt and the last tool definition so Anthropic caches them across multi-turn agent loops. This reduces input token costs by ~90% on subsequent calls within the same cache window (~5 minutes).

Only takes effect when the resolved model is served by Anthropic. Non-Anthropic models silently ignore this setting.

Examples:

class BuildAgent < ApplicationAgent
  cache_prompts true
  system "You are a build assistant."
  tools BuildTool, TestTool, DeployTool
end

Parameters:

  • value (Boolean, nil) (defaults to: nil)

    Whether to enable prompt caching

Returns:

  • (Boolean)

    The current setting



256
257
258
259
260
261
# File 'lib/ruby_llm/agents/dsl/base.rb', line 256

def cache_prompts(value = nil)
  @cache_prompts = value unless value.nil?
  return @cache_prompts if defined?(@cache_prompts) && !@cache_prompts.nil?

  inherited_or_default(:cache_prompts, false)
end

#clear_override_cache!void

This method returns an undefined value.

Clears the in-memory override cache so the next access reloads from DB

Called automatically by AgentOverride after_save/after_destroy callbacks.



343
344
345
# File 'lib/ruby_llm/agents/dsl/base.rb', line 343

def clear_override_cache!
  @_override_cache = nil
end

#description(value = nil) ⇒ String?

Sets or returns the description for this agent class

Useful for documentation and tool registration.

Examples:

description "Searches the knowledge base for relevant documents"

Parameters:

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

    The description text

Returns:

  • (String, nil)

    The current description



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

def description(value = nil)
  @description = value if value
  @description || inherited_or_default(:description, nil)
end

#model(value = nil, overridable: nil) ⇒ String

Sets or returns the LLM model for this agent class

Examples:

model "gpt-4o"

Dashboard-overridable

model "gpt-4o", overridable: true

Parameters:

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

    The model identifier to set

  • overridable (Boolean, nil) (defaults to: nil)

    When true, this field can be changed from the dashboard

Returns:

  • (String)

    The current model setting



79
80
81
82
83
84
85
# File 'lib/ruby_llm/agents/dsl/base.rb', line 79

def model(value = nil, overridable: nil)
  @model = value if value
  register_overridable(:model) if overridable
  base = @model || inherited_or_default(:model, default_model)

  apply_override(:model, base)
end

#overridable?Boolean

Returns true if any field is overridable from the dashboard

Returns:

  • (Boolean)


322
323
324
# File 'lib/ruby_llm/agents/dsl/base.rb', line 322

def overridable?
  overridable_fields.any?
end

#overridable_fieldsArray<Symbol>

Returns which fields are overridable for this agent

Returns:

  • (Array<Symbol>)

    The list of overridable field names



313
314
315
316
317
# File 'lib/ruby_llm/agents/dsl/base.rb', line 313

def overridable_fields
  own = @overridable_fields || []
  inherited = superclass.respond_to?(:overridable_fields) ? superclass.overridable_fields : []
  (own + inherited).uniq
end

#prompt(template = nil) ⇒ String?

Deprecated.

Use ‘user` instead.

Backward-compatible alias for ‘user`

Parameters:

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

    Prompt template with placeholder syntax

Returns:

  • (String, nil)

    The current prompt configuration



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

def prompt(template = nil)
  if template
    Deprecations.warn(
      "`prompt` is deprecated. Use `user` instead (e.g., `user \"#{template.truncate(40)}\"`).",
      caller
    )
    @user_template = template
    auto_register_params_from_template(template)
  end
  @user_template || inherited_or_default(:user_config, nil)
end

#returns(&block) ⇒ RubyLLM::Schema?

Alias for schema with a clearer name

Defines the structured output schema for this agent. This is the preferred method for defining schemas in the simplified DSL.

Examples:

returns do
  string :summary, "A brief summary"
  array :insights, of: :string, description: "Key insights"
  number :confidence, "Confidence score from 0 to 1"
end

Parameters:

  • block (Proc)

    Block passed to RubyLLM::Schema.create

Returns:

  • (RubyLLM::Schema, nil)

    The current schema setting



302
303
304
# File 'lib/ruby_llm/agents/dsl/base.rb', line 302

def returns(&block)
  schema(&block)
end

#schema(value = nil, &block) ⇒ Hash, ...

Sets or returns the response schema for structured output

Accepts a hash (JSON Schema), a block (passed to RubyLLM::Schema.create), or any object that responds to ‘to_json_schema`.

Examples:

With a block (recommended)

schema do
  string :name, description: "The user's name"
  integer :age, description: "The user's age"
end

With a hash

schema type: "object", properties: { name: { type: "string" } }

Parameters:

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

    The schema to set

  • block (Proc, nil)

    Block passed to RubyLLM::Schema.create

Returns:

  • (Hash, RubyLLM::Schema, nil)

    The current schema setting



278
279
280
281
282
283
284
285
# File 'lib/ruby_llm/agents/dsl/base.rb', line 278

def schema(value = nil, &block)
  if value
    @schema = value
  elsif block
    @schema = RubyLLM::Schema.create(&block)
  end
  @schema || inherited_or_default(:schema, nil)
end

#system(text = nil) ⇒ String?

Sets the system prompt/instructions

When a string is provided, placeholder syntax is supported for parameter interpolation, same as the ‘user` DSL.

Examples:

Static system prompt

system "You are a helpful assistant. Be concise and accurate."

With placeholders

system "You are helping {user_name} with their {task}."

Dynamic system prompt (method override)

def system_prompt
  "You are helping #{user_name}. Today is #{Date.today}."
end

Parameters:

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

    System instructions for the LLM

Returns:

  • (String, nil)

    The current system prompt



158
159
160
161
162
163
164
# File 'lib/ruby_llm/agents/dsl/base.rb', line 158

def system(text = nil)
  if text
    @system_template = text
    auto_register_params_from_template(text)
  end
  @system_template || inherited_or_default(:system_config, nil)
end

#system_configString?

Returns the system prompt configuration

Returns:

  • (String, nil)

    The system template, or nil



169
170
171
# File 'lib/ruby_llm/agents/dsl/base.rb', line 169

def system_config
  @system_template || inherited_or_default(:system_config, nil)
end

#timeout(value = nil, overridable: nil) ⇒ Integer

Sets or returns the timeout in seconds for LLM requests

Examples:

timeout 30

Dashboard-overridable

timeout 30, overridable: true

Parameters:

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

    Timeout in seconds

  • overridable (Boolean, nil) (defaults to: nil)

    When true, this field can be changed from the dashboard

Returns:

  • (Integer)

    The current timeout setting



228
229
230
231
232
233
234
# File 'lib/ruby_llm/agents/dsl/base.rb', line 228

def timeout(value = nil, overridable: nil)
  @timeout = value if value
  register_overridable(:timeout) if overridable
  base = @timeout || inherited_or_default(:timeout, default_timeout)

  apply_override(:timeout, base)
end

#user(template = nil) ⇒ String?

Sets the user prompt template

When a string is provided, placeholder syntax is used to interpolate parameters. Parameters are automatically registered (as required) unless already defined with ‘param`.

Examples:

With template string (parameters auto-detected)

user "Search for: {query} in {category}"
# Automatically registers :query and :category as required params

Multi-line with heredoc

user <<~S
  Search for: {query}
  Category: {category}
  Limit: {limit}
S

Parameters:

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

    Prompt template with placeholder syntax

Returns:

  • (String, nil)

    The current user prompt configuration



107
108
109
110
111
112
113
# File 'lib/ruby_llm/agents/dsl/base.rb', line 107

def user(template = nil)
  if template
    @user_template = template
    auto_register_params_from_template(template)
  end
  @user_template || inherited_or_default(:user_config, nil)
end

#user_configString?

Returns the user prompt configuration

Returns:

  • (String, nil)

    The user template, or nil



118
119
120
# File 'lib/ruby_llm/agents/dsl/base.rb', line 118

def user_config
  @user_template || inherited_or_default(:user_config, nil)
end