Class: LLM::Agent
- Inherits:
-
Object
- Object
- LLM::Agent
- Defined in:
- lib/llm/agent.rb
Overview
LLM::Agent provides a class-level DSL for defining reusable, preconfigured assistants with defaults for model, tools, schema, and instructions.
It wraps the same stateful runtime surface as
LLM::Context: message history, usage, persistence,
streaming parameters, and provider-backed requests still flow through
an underlying context. The defining behavior of an agent is that it
automatically resolves pending tool calls for you during talk and
respond, instead of leaving tool loops to the caller.
Notes:
- Instructions are injected once unless a system message is already present.
- An agent automatically executes tool loops (unlike LLM::Context).
- The automatic tool loop enables the wrapped context's
guardby default. The built-in LLM::LoopGuard detects repeated tool-call patterns and blocks stuck execution before more tool work is queued. - The default tool attempt budget is
25. After that, the agent sends advisory tool errors back through the model and keeps the loop in-band. Settool_attempts: nilto disable that advisory behavior. - Tool loop execution can be configured with
concurrency :call,:thread,:task,:fiber, or:ractor.
Instance Attribute Summary collapse
-
#llm ⇒ LLM::Provider
readonly
Returns a provider.
Class Method Summary collapse
-
.tools(*tools, &block) ⇒ Array<LLM::Function>
Set or get the default tools.
-
.skills(*skills, &block) ⇒ Array<String>?
Set or get the default skills.
-
.schema(schema = nil, &block) ⇒ #to_json?
Set or get the default schema.
-
.instructions(instructions = nil) ⇒ String?
Set or get the default instructions.
-
.concurrency(concurrency = nil) ⇒ Symbol, ...
Set or get the tool execution concurrency.
-
.tracer(tracer = nil, &block) ⇒ LLM::Tracer, ...
Set or get the default tracer.
-
.stream(stream = nil, &block) ⇒ Object, ...
Set or get the default stream.
-
.confirm(*tool_names, &block) ⇒ Array<String>, ...
Set or get the tool names that require confirmation before they can run.
-
.model(model = nil, &block) ⇒ String?
Set or get the default model.
Instance Method Summary collapse
-
#on_tool_confirmation(fn, strategy) ⇒ LLM::Function::Return
This method is called when confirmation is required before a tool can run.
-
#initialize(llm, params = {}) ⇒ Agent
constructor
A new instance of Agent.
-
#talk(prompt, params = {}) ⇒ LLM::Response
Maintain a conversation via the chat completions API.
- #ask(prompt, params = {}) ⇒ Object
- #messages ⇒ LLM::Buffer<LLM::Message>
- #functions ⇒ Array<LLM::Function>
- #returns ⇒ Array<LLM::Function::Return>
- #wait ⇒ Array<LLM::Function::Return>
- #usage ⇒ LLM::Object
-
#interrupt! ⇒ nil
(also: #cancel!)
Interrupt the active request, if any.
- #prompt(&b) ⇒ LLM::Prompt (also: #build_prompt)
-
#image_url(url) ⇒ LLM::Object
Returns a tagged object.
-
#local_file(path) ⇒ LLM::Object
Returns a tagged object.
-
#remote_file(res) ⇒ LLM::Object
Returns a tagged object.
-
#tracer ⇒ LLM::Tracer
Returns an LLM tracer.
-
#stream ⇒ LLM::Stream, ...
Returns a stream object, or nil.
-
#model ⇒ String
Returns the model an Agent is actively using.
- #mode ⇒ Symbol
-
#concurrency ⇒ Symbol, ...
Returns the configured tool execution concurrency.
- #cost ⇒ LLM::Cost
- #context_window ⇒ Integer
- #params ⇒ Hash
- #to_h ⇒ Hash
- #to_json ⇒ String
- #inspect ⇒ String
- #serialize(**kw) (also: #save)
- #deserialize(**kw) ⇒ Object (also: #restore)
Constructor Details
#initialize(llm, params = {}) ⇒ Agent
Returns a new instance of Agent.
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 |
# File 'lib/llm/agent.rb', line 208 def initialize(llm, params = {}) @llm = llm fields = %i[model skills schema tracer stream tools concurrency instructions confirm] fields_ivar = %i[tracer concurrency instructions confirm] fields.each do |field| resolvable = params.key?(field) ? params.delete(field) : self.class.public_send(field) resolve_symbol = !%i[concurrency].include?(field) resolved = resolvable != nil ? resolve_option(self, resolvable, resolve_symbol:) : resolvable resolved = [*resolved].map(&:to_s) if field == :confirm && resolved if field == :model params[field] = resolved unless resolved.nil? || params.key?(field) elsif resolved && !fields_ivar.include?(field) params[field] ||= resolved elsif fields_ivar.include?(field) instance_variable_set(:"@#{field}", resolved) end end @ctx = LLM::Context.new(llm, {guard: true}.merge(params)) end |
Instance Attribute Details
#llm ⇒ LLM::Provider (readonly)
Returns a provider
43 44 45 |
# File 'lib/llm/agent.rb', line 43 def llm @llm end |
Class Method Details
.tools(*tools, &block) ⇒ Array<LLM::Function>
Set or get the default tools
62 63 64 65 |
# File 'lib/llm/agent.rb', line 62 def self.tools(*tools, &block) return @tools || [] if tools.empty? && !block @tools = block || tools.flatten end |
.skills(*skills, &block) ⇒ Array<String>?
Set or get the default skills
73 74 75 76 77 78 79 80 |
# File 'lib/llm/agent.rb', line 73 def self.skills(*skills, &block) return @skills if skills.empty? && !block if skills.size == 1 and skills.grep(Symbol).any? @skills = skills.first else @skills = block || skills.flatten end end |
.schema(schema = nil, &block) ⇒ #to_json?
Set or get the default schema
88 89 90 91 |
# File 'lib/llm/agent.rb', line 88 def self.schema(schema = nil, &block) return @schema if schema.nil? && !block @schema = block || schema end |
.instructions(instructions = nil) ⇒ String?
Set or get the default instructions
99 100 101 102 |
# File 'lib/llm/agent.rb', line 99 def self.instructions(instructions = nil) return @instructions if instructions.nil? @instructions = instructions end |
.concurrency(concurrency = nil) ⇒ Symbol, ...
Set or get the tool execution concurrency.
119 120 121 122 |
# File 'lib/llm/agent.rb', line 119 def self.concurrency(concurrency = nil) return @concurrency if concurrency.nil? @concurrency = concurrency end |
.tracer(tracer = nil, &block) ⇒ LLM::Tracer, ...
Set or get the default tracer.
When a block is provided, it is stored and evaluated lazily against the agent instance during initialization so it can build a tracer from the resolved provider.
139 140 141 142 |
# File 'lib/llm/agent.rb', line 139 def self.tracer(tracer = nil, &block) return @tracer if tracer.nil? && !block @tracer = block || tracer end |
.stream(stream = nil, &block) ⇒ Object, ...
Set or get the default stream.
When a block is provided, it is stored and evaluated lazily against the agent instance during initialization so it can build a fresh stream for each agent.
159 160 161 162 |
# File 'lib/llm/agent.rb', line 159 def self.stream(stream = nil, &block) return @stream if stream.nil? && !block @stream = block || stream end |
.confirm(*tool_names, &block) ⇒ Array<String>, ...
Set or get the tool names that require confirmation before they can run.
When a single Symbol is given, it is stored as-is and resolved at initialization time by calling the method with that name on the agent instance. This allows dynamic tool confirmation lists.
185 186 187 188 189 190 191 192 |
# File 'lib/llm/agent.rb', line 185 def self.confirm(*tool_names, &block) return @confirm if tool_names.empty? && !block if tool_names.size == 1 && tool_names.grep(Symbol).any? @confirm = tool_names.first else @confirm = block || tool_names.flatten.map(&:to_s) end end |
.model(model = nil, &block) ⇒ String?
Set or get the default model
51 52 53 54 |
# File 'lib/llm/agent.rb', line 51 def self.model(model = nil, &block) return @model if model.nil? && !block @model = block || model end |
Instance Method Details
#on_tool_confirmation(fn, strategy) ⇒ LLM::Function::Return
This method is called when confirmation is required before a tool can run.
432 433 434 |
# File 'lib/llm/agent.rb', line 432 def on_tool_confirmation(fn, strategy) fn.cancel end |
#talk(prompt, params = {}) ⇒ LLM::Response
Maintain a conversation via the chat completions API. This method immediately sends a request to the LLM and returns the response.
244 245 246 |
# File 'lib/llm/agent.rb', line 244 def talk(prompt, params = {}) run_loop(prompt, params, :talk) end |
#ask(prompt, params = {}) ⇒ Object
250 251 252 |
# File 'lib/llm/agent.rb', line 250 def ask(prompt, params = {}) run_loop(prompt, params, :ask) end |
#functions ⇒ Array<LLM::Function>
262 263 264 |
# File 'lib/llm/agent.rb', line 262 def functions @tracer ? @llm.with_tracer(@tracer) { @ctx.functions } : @ctx.functions end |
#returns ⇒ Array<LLM::Function::Return>
269 270 271 |
# File 'lib/llm/agent.rb', line 269 def returns @ctx.returns end |
#wait ⇒ Array<LLM::Function::Return>
276 277 278 |
# File 'lib/llm/agent.rb', line 276 def wait(...) @tracer ? @llm.with_tracer(@tracer) { @ctx.wait(...) } : @ctx.wait(...) end |
#interrupt! ⇒ nil Also known as: cancel!
Interrupt the active request, if any.
289 290 291 |
# File 'lib/llm/agent.rb', line 289 def interrupt! @ctx.interrupt! end |
#prompt(&b) ⇒ LLM::Prompt Also known as: build_prompt
298 299 300 |
# File 'lib/llm/agent.rb', line 298 def prompt(&b) @ctx.prompt(&b) end |
#image_url(url) ⇒ LLM::Object
Returns a tagged object
308 309 310 |
# File 'lib/llm/agent.rb', line 308 def image_url(url) @ctx.image_url(url) end |
#local_file(path) ⇒ LLM::Object
Returns a tagged object
317 318 319 |
# File 'lib/llm/agent.rb', line 317 def local_file(path) @ctx.local_file(path) end |
#remote_file(res) ⇒ LLM::Object
Returns a tagged object
326 327 328 |
# File 'lib/llm/agent.rb', line 326 def remote_file(res) @ctx.remote_file(res) end |
#tracer ⇒ LLM::Tracer
Returns an LLM tracer
333 334 335 |
# File 'lib/llm/agent.rb', line 333 def tracer @tracer || @ctx.tracer end |
#stream ⇒ LLM::Stream, ...
Returns a stream object, or nil
340 341 342 |
# File 'lib/llm/agent.rb', line 340 def stream @ctx.stream end |
#model ⇒ String
Returns the model an Agent is actively using
347 348 349 |
# File 'lib/llm/agent.rb', line 347 def model @ctx.model end |
#mode ⇒ Symbol
353 354 355 |
# File 'lib/llm/agent.rb', line 353 def mode @ctx.mode end |
#concurrency ⇒ Symbol, ...
Returns the configured tool execution concurrency.
360 361 362 |
# File 'lib/llm/agent.rb', line 360 def concurrency @concurrency end |
#context_window ⇒ Integer
374 375 376 |
# File 'lib/llm/agent.rb', line 374 def context_window @ctx.context_window end |
#params ⇒ Hash
381 382 383 |
# File 'lib/llm/agent.rb', line 381 def params @ctx.params end |
#to_h ⇒ Hash
388 389 390 |
# File 'lib/llm/agent.rb', line 388 def to_h @ctx.to_h end |
#to_json ⇒ String
394 395 396 |
# File 'lib/llm/agent.rb', line 394 def to_json(...) LLM.json.dump(to_h, ...) end |
#inspect ⇒ String
400 401 402 403 |
# File 'lib/llm/agent.rb', line 400 def inspect "#<#{LLM::Utils.object_id(self)} " \ "@llm=#{@llm.class}, @mode=#{mode.inspect}, @messages=#{.inspect}>" end |
#serialize(**kw) Also known as: save
This method returns an undefined value.
408 409 410 |
# File 'lib/llm/agent.rb', line 408 def serialize(**kw) @ctx.serialize(**kw) end |
#deserialize(**kw) ⇒ Object Also known as: restore
416 417 418 |
# File 'lib/llm/agent.rb', line 416 def deserialize(**kw) @ctx.deserialize(**kw) end |