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
A named agent uses its conventional template automatically when it exists, even without calling this method. 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 118 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 848 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 161 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 147 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 134 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 1175
Delegates to Chat#add_message. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1001
Delegates to Chat#after_fallback. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 977
Delegates to Chat#after_message. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 989
Delegates to Chat#after_tool_result. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1013
Delegates to Chat#approve. See that method for arguments and return values.
# File lib/ruby_llm/agent.rb, line 1199
Delegates to Chat#ask, routing exceptions through the handlers declared with ::rescue_from.
# File lib/ruby_llm/agent.rb, line 1219
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 1163
Delegates to Chat#awaiting_approval?. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 995
Delegates to Chat#before_fallback. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 971
Delegates to Chat#before_message. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 965
Delegates to Chat#before_request. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 983
Delegates to Chat#before_tool_call. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1025
Delegates to Chat#cache_until_here. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1091
Delegates to Chat#caching. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1007
Delegates to Chat#cancel. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1157
Delegates to Chat#cancelled?. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1097
Delegates to Chat#citations. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1260 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 1103
Delegates to Chat#compaction. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1206
Delegates to Chat#complete, routing exceptions through the handlers declared with ::rescue_from.
Source
# File lib/ruby_llm/agent.rb, line 1151
Delegates to Chat#complete?. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1085
Delegates to Chat#concurrency. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1109
Delegates to Chat#context. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1187
Delegates to Chat#cost. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1247
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 1019
Delegates to Chat#deny. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1145
Delegates to Chat#each. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1115
Delegates to Chat#end_user. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1121
Delegates to Chat#fallbacks. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1226
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 1073
Delegates to Chat#headers. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1139
Returns Chat#max_output_tokens from the wrapped chat.
Source
# File lib/ruby_llm/agent.rb, line 1043
Delegates to Chat#messages. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1031
Delegates to Chat#model. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1169
Delegates to Chat#pending_approvals. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1037
Delegates to Chat#provider. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1067
Delegates to Chat#provider_options. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1193
Delegates to Chat#render. See that method for arguments and return values.
# File lib/ruby_llm/agent.rb, line 1271 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 1233
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 1213
Delegates to Chat#say, the alias for Chat#ask, with ::rescue_from handling.
Source
# File lib/ruby_llm/agent.rb, line 1079
Delegates to Chat#schema. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1055
Delegates to Chat#server_tools. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1240
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 1127
Delegates to Chat#thinking. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1181
Delegates to Chat#tokens. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1061
Delegates to Chat#tool_options. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 1049
Delegates to Chat#tools. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 929
Delegates to Chat#with_caching. See that method for arguments and return values.
# File lib/ruby_llm/agent.rb, line 911
Delegates to Chat#with_citations. See that method for arguments and return values.
# File lib/ruby_llm/agent.rb, line 923
Delegates to Chat#with_compaction. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 935
Delegates to Chat#with_context. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 917
Delegates to Chat#with_end_user. See that method for arguments and return values.
# File lib/ruby_llm/agent.rb, line 959
Delegates to Chat#with_fallbacks. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 947
Delegates to Chat#with_headers. See that method for arguments and return values.
# File lib/ruby_llm/agent.rb, line 863
Delegates to Chat#with_instructions. See that method for arguments and return values.
# File lib/ruby_llm/agent.rb, line 899
Delegates to Chat#with_max_output_tokens. See that method for arguments and return values.
# File lib/ruby_llm/agent.rb, line 887
Delegates to Chat#with_model. See that method for arguments and return values.
# File lib/ruby_llm/agent.rb, line 941
Delegates to Chat#with_provider_options. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 953
Delegates to Chat#with_schema. See that method for arguments and return values.
# File lib/ruby_llm/agent.rb, line 875
Delegates to Chat#with_server_tools. See that method for arguments and return values.
# File lib/ruby_llm/agent.rb, line 893
Delegates to Chat#with_temperature. See that method for arguments and return values.
# File lib/ruby_llm/agent.rb, line 905
Delegates to Chat#with_thinking. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 881
Delegates to Chat#with_tool_options. See that method for arguments and return values.
Source
# File lib/ruby_llm/agent.rb, line 869
Delegates to Chat#with_tools. See that method for arguments and return values.