class RubyLLM::Agent
An Agent is a reusable chat configuration defined as a class. Subclasses declare a model, instructions, tools, and other settings once, then build configured chats wherever they are needed.
class SupportAgent < RubyLLM::Agent model "gpt-5.6-luna" instructions "You are a concise support assistant." tools SearchDocs, LookupAccount end SupportAgent.new.ask "How do I reset my API key?"
::chat returns a configured Chat. When ::chat_model names an ActiveRecord chat class, ::create, ::create!, and ::find return configured records of that class instead.
Configuration that depends on runtime state goes in blocks or lambdas. They are evaluated when a chat is built, with chat and any declared ::inputs available as methods:
class WorkAssistant < RubyLLM::Agent inputs :workspace instructions { "You are helping #{workspace.name}" } end WorkAssistant.chat(workspace: workspace)
Agent instances delegate Chat’s conversation API (ask, complete, with_tools, and so on) to the wrapped chat, which is available via chat. Direct transcript replacement stays on the wrapped chat because Rails-backed chat models own their message association. Agents are enumerable over their messages.
Attributes
Public Class Methods
# File lib/ruby_llm/agent.rb, line 294 def caching(enabled = true, **options, &block) # rubocop:disable Metrics/PerceivedComplexity, Style/OptionalBooleanParameter return caching(**enabled.transform_keys(&:to_sym), **options, &block) if enabled.is_a?(Hash) raise ArgumentError, 'caching accepts false or caching options' unless [true, false].include?(enabled) raise ArgumentError, 'caching accepts options or a block, not both' if options.any? && block raise ArgumentError, 'caching false does not accept options or a block' if !enabled && (options.any? || block) @caching = block || (enabled ? options : false) end
Enables prompt caching for chats this agent builds, applied via Chat#with_caching. With no options, the provider’s default behavior applies. Pass false to stop RubyLLM from sending cache controls. A provider may still cache prompts implicitly. A block defers evaluation until the chat is built. Accepts keywords or an options Hash.
caching caching false caching ttl: "1h" caching { { ttl: workspace.cache_ttl } }
Source
# File lib/ruby_llm/agent.rb, line 474 def chat(**kwargs) input_values, chat_options = partition_inputs(kwargs) chat = build_chat(inputs: input_values, options: chat_options) apply_configuration(chat, input_values:, persist_instructions: true) chat end
Builds a Chat configured with this agent’s declarations and returns it. Keywords matching declared ::inputs become runtime inputs; the rest are forwarded to RubyLLM.chat.
chat = WorkAssistant.chat chat.ask "Hello"
Source
# File lib/ruby_llm/agent.rb, line 381 def chat_model(value = nil) return @chat_model if value.nil? @chat_model = value remove_instance_variable(:@resolved_chat_model) if instance_variable_defined?(:@resolved_chat_model) end
Sets the ActiveRecord chat class this agent creates and finds, activating Rails mode (::create, ::create!, ::find, and ::sync_instructions). Accepts the class or its name as a string. Called with no argument, returns the configured value.
chat_model Chat
Source
# File lib/ruby_llm/agent.rb, line 277 def citations(value = true) # rubocop:disable Style/OptionalBooleanParameter raise ArgumentError, 'citations accepts true or false' unless [true, false].include?(value) @citations = value end
Enables citations for chats this agent builds, applied via Chat#with_citations. Pass false to disable them.
citations citations false
Source
# File lib/ruby_llm/agent.rb, line 248 def compaction(options = {}) options = {} if options == true unless options == false || options.is_a?(Hash) raise ArgumentError, 'compaction accepts true, false, or compaction options' end @compaction = options end
Enables context compaction for chats this agent builds, applied via Chat#with_compaction. With no options, the provider’s own defaults apply. Pass false to disable it.
compaction compaction false compaction at: 50_000
Source
# File lib/ruby_llm/agent.rb, line 368 def context(value = nil) return @context if value.nil? @context = value end
Sets a Context whose configuration chats this agent builds should use, applied via Chat#with_context. Called with no argument, returns the configured context.
Source
# File lib/ruby_llm/agent.rb, line 488 def create(**kwargs) with_rails_chat_record(:create, **kwargs) end
Creates a ::chat_model record, applies this agent’s configuration to it, and returns it. Keywords matching declared ::inputs become runtime inputs; the rest are forwarded to the model’s create.
chat = WorkAssistant.create(user: current_user)
Raises ArgumentError if ::chat_model is not configured.
Source
# File lib/ruby_llm/agent.rb, line 497 def create!(**kwargs) with_rails_chat_record(:create!, **kwargs) end
Like ::create, but calls the model’s create!, raising if the record is invalid.
chat = WorkAssistant.create!(user: current_user)
# File lib/ruby_llm/agent.rb, line 265 def end_user(value = nil, &block) return @end_user if value.nil? && !block_given? @end_user = block || value end
Sets the safety identifier for chats this agent builds, applied via Chat#with_end_user. A block defers evaluation until the chat is built, so the id can come from the agent’s inputs. Called with no arguments, returns the configured value.
end_user "tenant-42" end_user { workspace.public_id }
# File lib/ruby_llm/agent.rb, line 351 def fallbacks(*models, **options) return @fallbacks || [] if models.empty? && options.empty? raise ArgumentError, 'To set fallback options, provide at least one fallback model' if models.empty? @fallbacks = models.flatten.compact @fallback_options = options end
Sets fallback models for chats this agent builds, applied via Chat#with_fallbacks. Called with no arguments, returns the configured models.
fallbacks "gpt-4.1-mini", "claude-haiku-4-5" fallbacks "gpt-4.1-mini", on: [RubyLLM::RateLimitError]
Source
# File lib/ruby_llm/agent.rb, line 508 def find(id, **kwargs) raise ArgumentError, 'chat_model must be configured to use find' unless resolved_chat_model input_values, = partition_inputs(kwargs) record = resolved_chat_model.find(id) apply_configuration(record, input_values:, persist_instructions: false) record end
Finds the ::chat_model record with id and applies this agent’s configuration at runtime, without persisting instructions. Returns the record.
chat = WorkAssistant.find(params[:id])
Raises ArgumentError if ::chat_model is not configured.
Source
# File lib/ruby_llm/agent.rb, line 320 def headers(**headers, &block) return @headers || {} if headers.empty? && !block_given? @headers = block_given? ? block : headers end
Sets custom HTTP headers for chats this agent builds, applied via Chat#with_headers. A block defers evaluation until the chat is built. Called with no arguments, returns the configured value.
Source
# File lib/ruby_llm/agent.rb, line 395 def inputs(*names) return @input_names || [] if names.empty? @input_names = names.flatten.map(&:to_sym) end
# File lib/ruby_llm/agent.rb, line 185 def instructions(text = nil, append: false, persist: true, cache_until_here: false, **prompt_locals, &block) return instruction_declarations if text.nil? && prompt_locals.empty? && !block_given? (@instruction_declarations ||= []) << { value: block || text || { prompt: 'instructions', locals: prompt_locals }, append: append, persist: persist, cache_until_here: cache_until_here } end
Adds system instructions for chats this agent builds. Accepts a string, a block evaluated when the chat is built, or keyword locals for the agent’s conventional prompt template (for a WorkAssistant agent, app/prompts/work_assistant/instructions.txt.erb). Multiple declarations are applied in order.
instructions "You are a helpful assistant." instructions { "You are helping #{workspace.name}" } instructions display_name: -> { chat.user.display_name_or_email } instructions append: true, persist: false do "Today is #{Date.current}" end
The class’s own declarations take precedence over its conventional template. Inherited declarations are used only when neither exists. In Rails mode, declarations persist when the record is created unless persist: false; ::find always reapplies them without rewriting history. Called with no arguments, returns the declarations.
# File lib/ruby_llm/agent.rb, line 214 PASSTHROUGH_OPTIONS.each do |option| define_method(option) do |value = nil| return instance_variable_get(:"@#{option}") if value.nil? instance_variable_set(:"@#{option}", value) end end
Caps the number of tokens chats this agent builds may generate. Called with no argument, returns the configured value.
max_output_tokens 1000
# File lib/ruby_llm/agent.rb, line 117 def model(model_id = nil, **options, &block) return @chat_kwargs || {} if model_id.nil? && options.empty? && !block_given? model_value = block || model_id options[:model] = model_value unless model_value.nil? @chat_kwargs = options end
Sets the model used by chats this agent builds. Extra options are forwarded to RubyLLM.chat, including provider: to disambiguate the model and protocol: to override its wire protocol. A block picks the model when the chat is built, with the declared ::inputs available as methods. Called with no arguments, returns the configured chat keywords.
model "gpt-5.6-luna" model "gpt-5.6", provider: :openai, protocol: :responses model { quality == :high ? "gpt-5.6" : "gpt-5.6-luna" }
The block runs before the chat exists, so it can read inputs but not chat.
# File lib/ruby_llm/agent.rb, line 849 def initialize(chat: nil, inputs: nil, persist_instructions: true, **kwargs) input_values, chat_options = self.class.partition_inputs(kwargs) input_values = input_values.merge(inputs || {}) @chat = chat || self.class.build_chat(inputs: input_values, options: chat_options) self.class.apply_configuration(@chat, input_values:, persist_instructions:) end
Returns a new agent wrapping chat:, or wrapping a newly built chat when chat: is nil. Applies the agent’s configuration either way. Keywords matching declared inputs (and the inputs: hash) become runtime inputs; the rest are forwarded to RubyLLM.chat when the agent builds its own chat. Pass persist_instructions: false to apply instructions at runtime only, without persisting them on a Rails-backed record.
agent = WorkAssistant.new agent.ask "Hello" record = Chat.find(params[:id]) WorkAssistant.new(chat: record)
# File lib/ruby_llm/agent.rb, line 311 def provider_options(**provider_options, &block) return @provider_options || {} if provider_options.empty? && !block_given? @provider_options = block_given? ? block : provider_options end
Sets options in the provider’s request vocabulary for chats this agent builds, applied via Chat#with_provider_options. A block defers evaluation until the chat is built. Called with no arguments, returns the configured value.
provider_options service_tier: "flex"
# File lib/ruby_llm/agent.rb, line 431 def rescue_from(*exception_classes, with: nil, &block) raise ArgumentError, 'rescue_from needs a handler: pass with: or a block' unless with || block raise ArgumentError, 'rescue_from takes with: or a block, not both' if with && block exception_classes.flatten.each do |exception_class| rescue_handlers << [rescue_handler_key(exception_class), with || block] end end
Registers a handler for exceptions raised by the chat operations of this agent’s instances: ask, say, ask_later, complete, generate, run_tools, step, count_tokens, and compact. Name the handler with with: or pass a block; either runs on the agent instance, so the agent’s chat, inputs, and class name are available for instrumentation.
class ApplicationAgent < RubyLLM::Agent rescue_from RubyLLM::RateLimitError, Faraday::TimeoutError, with: :handle_transient rescue_from RubyLLM::BadRequestError do |error| error_tracker.notify(error) raise end private def handle_transient(error) metrics.increment("llm.api_error", type: "transient") raise end end
Handlers are searched in reverse declaration order, so the last matching one wins. Re-raise inside a handler to let the caller see the exception; otherwise the handler’s return value becomes the operation’s return value. Exceptions no handler matches are re-raised. Subclasses inherit the handlers declared when they are defined.
Exception classes may be named as Strings, which defers constant lookup until an exception is raised.
Source
# File lib/ruby_llm/agent.rb, line 338 def schema(value = nil, &block) return @schema if value.nil? && !block_given? @schema = block_given? ? block : value end
Sets the structured output schema for chats this agent builds, applied via Chat#with_schema. Accepts a schema class, a JSON schema hash, or a block. A plain block is built with the Schematist::Schema DSL; a lambda is evaluated when the chat is built. Called with no arguments, returns the configured value.
schema PersonSchema schema do string :verdict, enum: ["pass", "revise"] string :feedback end
# File lib/ruby_llm/agent.rb, line 160 def server_tools(*tools, **tools_with_options, &block) return @server_tools || [] if tools.empty? && tools_with_options.empty? && !block_given? @server_tools = block_given? ? block : RubyLLM::Tools::ServerTools.normalize(tools, tools_with_options) end
Enables provider-executed tools for chats this agent builds, applied via Chat#with_server_tools. Accepts the same aliases, options, and raw Hashes; a block defers evaluation until the chat is built. Called with no arguments, returns the declared entries.
server_tools :web_search server_tools web_search: { allowed_domains: ["ruby-lang.org"] }
# File lib/ruby_llm/agent.rb, line 526 def sync_instructions(chat_or_id, **kwargs) raise ArgumentError, 'chat_model must be configured to use sync_instructions' unless resolved_chat_model input_values, = partition_inputs(kwargs) record = chat_or_id.is_a?(resolved_chat_model) ? chat_or_id : resolved_chat_model.find(chat_or_id) apply_assume_model_exists(record) apply_protocol(record) apply_context(record) runtime = runtime_context(chat: record, inputs: input_values) apply_instructions( record, runtime, inputs: input_values, persist: true, persistent_only: true ) record end
Re-renders this agent’s instructions and persists them on the given ::chat_model record (or the record found by that id). Keywords matching declared ::inputs become runtime inputs. Returns the record.
WorkAssistant.sync_instructions(chat)
Raises ArgumentError if ::chat_model is not configured.
Source
# File lib/ruby_llm/agent.rb, line 197
Sets the sampling temperature for chats this agent builds. Called with no argument, returns the configured value.
temperature 0.2
# File lib/ruby_llm/agent.rb, line 233 def thinking(enabled = true, **options) # rubocop:disable Style/OptionalBooleanParameter return thinking(**enabled.transform_keys(&:to_sym), **options) if enabled.is_a?(Hash) validate_thinking_options(enabled, options) @thinking = enabled ? options : false end
Enables thinking for chats this agent builds, applied via Chat#with_thinking. With no options, RubyLLM chooses from the model’s registered controls. Accepts keywords or an options Hash. Pass false to disable it. Passing nil raises ArgumentError.
thinking thinking false thinking effort: :low thinking budget: 10_000 thinking display: :summarized
# File lib/ruby_llm/agent.rb, line 146 def tool_options(**options, &block) return @tool_options || {} if options.empty? && !block_given? @tool_options = block_given? ? block : options end
Sets how chats this agent builds use their tools, applied via Chat#with_tool_options. Accepts choice:, calls:, and concurrency:. A block defers evaluation until the chat is built. Called with no arguments, returns the configured options.
tool_options choice: :required, calls: :one
Source
# File lib/ruby_llm/agent.rb, line 133 def tools(*tools, &block) return @tools || [] if tools.empty? && !block_given? @tools = block_given? ? block : tools.flatten end
Declares the tools for chats this agent builds. A block defers construction until the chat is built. Configure how the model uses them with ::tool_options. Called with no arguments, returns the declared tools.
tools SearchDocs, LookupAccount tools { [TodoTool.new(chat: chat)] }
Public Instance Methods
# File lib/ruby_llm/agent.rb, line 1176
Delegates to Chat#add_message. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1002
Delegates to Chat#after_fallback. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 978
Delegates to Chat#after_message. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 990
Delegates to Chat#after_tool_result. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1014
Delegates to Chat#approve. See that method for arguments and return values.
# File lib/ruby_llm/agent.rb, line 1200
Delegates to Chat#ask, routing exceptions through the handlers declared with ::rescue_from.
# File lib/ruby_llm/agent.rb, line 1220
Stages a message through Chat#ask_later without calling the provider. Returns the wrapped chat. Exceptions use ::rescue_from handlers.
Source
# File lib/ruby_llm/agent.rb, line 1164
Delegates to Chat#awaiting_approval?. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 996
Delegates to Chat#before_fallback. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 972
Delegates to Chat#before_message. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 966
Delegates to Chat#before_request. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 984
Delegates to Chat#before_tool_call. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1026
Delegates to Chat#cache_until_here. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1092
Delegates to Chat#caching. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1008
Delegates to Chat#cancel. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1158
Delegates to Chat#cancelled?. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1098
Delegates to Chat#citations. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1261 GUARDED_OPERATIONS.each do |operation| define_method(operation) do |*args, **kwargs, &block| chat.public_send(operation, *args, **kwargs, &block) rescue StandardError => e rescue_with_handler(e) end end
Compacts the model context through Chat#compact and returns its Message. Exceptions use ::rescue_from handlers.
Source
# File lib/ruby_llm/agent.rb, line 1104
Delegates to Chat#compaction. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1207
Delegates to Chat#complete, routing exceptions through the handlers declared with ::rescue_from.
Source
# File lib/ruby_llm/agent.rb, line 1152
Delegates to Chat#complete?. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1086
Delegates to Chat#concurrency. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1110
Delegates to Chat#context. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1188
Delegates to Chat#cost. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1248
Counts request tokens through Chat#count_tokens without generating a response. Returns an Integer. Exceptions use ::rescue_from handlers.
Source
# File lib/ruby_llm/agent.rb, line 1020
Delegates to Chat#deny. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1146
Delegates to Chat#each. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1116
Delegates to Chat#end_user. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1122
Delegates to Chat#fallbacks. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1227
Generates one response through Chat#generate without executing tools. Returns a Message. Exceptions use ::rescue_from handlers.
Source
# File lib/ruby_llm/agent.rb, line 1074
Delegates to Chat#headers. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1140
Returns Chat#max_output_tokens from the wrapped chat.
Source
# File lib/ruby_llm/agent.rb, line 1044
Delegates to Chat#messages. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1032
Delegates to Chat#model. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1170
Delegates to Chat#pending_approvals. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1038
Delegates to Chat#provider. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1068
Delegates to Chat#provider_options. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1194
Delegates to Chat#render. See that method for arguments and return values.
# File lib/ruby_llm/agent.rb, line 1272 def rescue_with_handler(exception) handler = self.class.rescue_handler_for(exception) raise exception unless handler return instance_exec(exception, &handler) unless handler.is_a?(Symbol) handler_method = method(handler) handler_method.arity.zero? ? handler_method.call : handler_method.call(exception) end
Runs the ::rescue_from handler matching exception and returns its value, or re-raises when no handler matches. The chat operations call this for you.
Source
# File lib/ruby_llm/agent.rb, line 1234
Runs pending tools through Chat#run_tools, respecting approval decisions. Returns the wrapped chat. Exceptions use ::rescue_from handlers.
# File lib/ruby_llm/agent.rb, line 1214
Delegates to Chat#say, the alias for Chat#ask, with ::rescue_from handling.
Source
# File lib/ruby_llm/agent.rb, line 1080
Delegates to Chat#schema. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1056
Delegates to Chat#server_tools. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1241
Advances the conversation through Chat#step. Returns a Message or nil when no progress is possible. Exceptions use ::rescue_from handlers.
Source
# File lib/ruby_llm/agent.rb, line 1128
Delegates to Chat#thinking. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1182
Delegates to Chat#tokens. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1062
Delegates to Chat#tool_options. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1050
Delegates to Chat#tools. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 930
Delegates to Chat#with_caching. See that method for arguments and return values.
# File lib/ruby_llm/agent.rb, line 912
Delegates to Chat#with_citations. See that method for arguments and return values.
# File lib/ruby_llm/agent.rb, line 924
Delegates to Chat#with_compaction. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 936
Delegates to Chat#with_context. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 918
Delegates to Chat#with_end_user. See that method for arguments and return values.
# File lib/ruby_llm/agent.rb, line 960
Delegates to Chat#with_fallbacks. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 948
Delegates to Chat#with_headers. See that method for arguments and return values.
# File lib/ruby_llm/agent.rb, line 864
Delegates to Chat#with_instructions. See that method for arguments and return values.
# File lib/ruby_llm/agent.rb, line 900
Delegates to Chat#with_max_output_tokens. See that method for arguments and return values.
# File lib/ruby_llm/agent.rb, line 888
Delegates to Chat#with_model. See that method for arguments and return values.
# File lib/ruby_llm/agent.rb, line 942
Delegates to Chat#with_provider_options. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 954
Delegates to Chat#with_schema. See that method for arguments and return values.
# File lib/ruby_llm/agent.rb, line 876
Delegates to Chat#with_server_tools. See that method for arguments and return values.
# File lib/ruby_llm/agent.rb, line 894
Delegates to Chat#with_temperature. See that method for arguments and return values.
# File lib/ruby_llm/agent.rb, line 906
Delegates to Chat#with_thinking. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 882
Delegates to Chat#with_tool_options. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 870
Delegates to Chat#with_tools. See that method for arguments and return values.