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
-
.concurrency(concurrency = nil) ⇒ Symbol, ...
Set or get the tool execution concurrency.
-
.confirm(*tool_names, &block) ⇒ Array<String>, ...
Set or get the tool names that require confirmation before they can run.
-
.instructions(instructions = nil) ⇒ String?
Set or get the default instructions.
-
.model(model = nil, &block) ⇒ String?
Set or get the default model.
-
.schema(schema = nil, &block) ⇒ #to_json?
Set or get the default schema.
-
.skills(*skills, &block) ⇒ Array<String>?
Set or get the default skills.
-
.stream(stream = nil, &block) ⇒ Object, ...
Set or get the default stream.
-
.tools(*tools, &block) ⇒ Array<LLM::Function>
Set or get the default tools.
-
.tracer(tracer = nil, &block) ⇒ LLM::Tracer, ...
Set or get the default tracer.
Instance Method Summary collapse
- #ask(prompt, params = {}) ⇒ Object
-
#concurrency ⇒ Symbol, ...
Returns the configured tool execution concurrency.
- #context_window ⇒ Integer
- #cost ⇒ LLM::Cost
- #deserialize(**kw) ⇒ Object (also: #restore)
- #functions ⇒ Array<LLM::Function>
-
#image_url(url) ⇒ LLM::Object
Returns a tagged object.
-
#initialize(llm, params = {}) ⇒ Agent
constructor
A new instance of Agent.
- #inspect ⇒ String
-
#interrupt! ⇒ nil
(also: #cancel!)
Interrupt the active request, if any.
-
#local_file(path) ⇒ LLM::Object
Returns a tagged object.
- #messages ⇒ LLM::Buffer<LLM::Message>
- #mode ⇒ Symbol
-
#model ⇒ String
Returns the model an Agent is actively using.
-
#on_tool_confirmation(fn, strategy) ⇒ LLM::Function::Return
This method is called when confirmation is required before a tool can run.
- #params ⇒ Hash
- #prompt(&b) ⇒ LLM::Prompt (also: #build_prompt)
-
#remote_file(res) ⇒ LLM::Object
Returns a tagged object.
-
#repl ⇒ void
Start a minimalist repl that can interact with the agent and its current state.
- #returns ⇒ Array<LLM::Function::Return>
- #serialize(**kw) ⇒ void (also: #save)
-
#stream ⇒ LLM::Stream, ...
Returns a stream object, or nil.
-
#talk(prompt, params = {}) ⇒ LLM::Response
Maintain a conversation via the chat completions API.
- #to_h ⇒ Hash
- #to_json ⇒ String
-
#tracer ⇒ LLM::Tracer
Returns an LLM tracer.
- #tracer=(other) ⇒ void
- #usage ⇒ LLM::Object
- #wait ⇒ Array<LLM::Function::Return>
Constructor Details
#initialize(llm, params = {}) ⇒ Agent
Returns a new instance of Agent.
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 |
# File 'lib/llm/agent.rb', line 212 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
.concurrency(concurrency = nil) ⇒ Symbol, ...
Set or get the tool execution concurrency.
123 124 125 126 |
# File 'lib/llm/agent.rb', line 123 def self.concurrency(concurrency = nil) return @concurrency if concurrency.nil? @concurrency = concurrency 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.
189 190 191 192 193 194 195 196 |
# File 'lib/llm/agent.rb', line 189 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 |
.instructions(instructions = nil) ⇒ String?
Set or get the default instructions
103 104 105 106 |
# File 'lib/llm/agent.rb', line 103 def self.instructions(instructions = nil) return @instructions if instructions.nil? @instructions = instructions 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 |
.schema(schema = nil, &block) ⇒ #to_json?
Set or get the default schema
92 93 94 95 |
# File 'lib/llm/agent.rb', line 92 def self.schema(schema = nil, &block) return @schema if schema.nil? && !block @schema = block || schema end |
.skills(*skills, &block) ⇒ Array<String>?
Set or get the default skills
77 78 79 80 81 82 83 84 |
# File 'lib/llm/agent.rb', line 77 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 |
.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.
163 164 165 166 |
# File 'lib/llm/agent.rb', line 163 def self.stream(stream = nil, &block) return @stream if stream.nil? && !block @stream = block || stream end |
.tools(*tools, &block) ⇒ Array<LLM::Function>
Set or get the default tools
62 63 64 65 66 67 68 69 |
# File 'lib/llm/agent.rb', line 62 def self.tools(*tools, &block) return @tools || [] if tools.empty? && !block if tools.size == 1 and tools.grep(Symbol).any? @tools = tools.first else @tools = block || tools.flatten end 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.
143 144 145 146 |
# File 'lib/llm/agent.rb', line 143 def self.tracer(tracer = nil, &block) return @tracer if tracer.nil? && !block @tracer = block || tracer end |
Instance Method Details
#ask(prompt, params = {}) ⇒ Object
254 255 256 |
# File 'lib/llm/agent.rb', line 254 def ask(prompt, params = {}) run_loop(prompt, params, :ask) end |
#concurrency ⇒ Symbol, ...
Returns the configured tool execution concurrency.
373 374 375 |
# File 'lib/llm/agent.rb', line 373 def concurrency @concurrency end |
#context_window ⇒ Integer
387 388 389 |
# File 'lib/llm/agent.rb', line 387 def context_window @ctx.context_window end |
#deserialize(**kw) ⇒ Object Also known as: restore
440 441 442 |
# File 'lib/llm/agent.rb', line 440 def deserialize(**kw) @ctx.deserialize(**kw) end |
#functions ⇒ Array<LLM::Function>
266 267 268 |
# File 'lib/llm/agent.rb', line 266 def functions @tracer ? @llm.with_tracer(@tracer) { @ctx.functions } : @ctx.functions end |
#image_url(url) ⇒ LLM::Object
Returns a tagged object
312 313 314 |
# File 'lib/llm/agent.rb', line 312 def image_url(url) @ctx.image_url(url) end |
#inspect ⇒ String
424 425 426 427 |
# File 'lib/llm/agent.rb', line 424 def inspect "#<#{LLM::Utils.object_id(self)} " \ "@llm=#{@llm.class}, @mode=#{mode.inspect}, @messages=#{.inspect}>" end |
#interrupt! ⇒ nil Also known as: cancel!
Interrupt the active request, if any.
293 294 295 |
# File 'lib/llm/agent.rb', line 293 def interrupt! @ctx.interrupt! end |
#local_file(path) ⇒ LLM::Object
Returns a tagged object
321 322 323 |
# File 'lib/llm/agent.rb', line 321 def local_file(path) @ctx.local_file(path) end |
#mode ⇒ Symbol
366 367 368 |
# File 'lib/llm/agent.rb', line 366 def mode @ctx.mode end |
#model ⇒ String
Returns the model an Agent is actively using
360 361 362 |
# File 'lib/llm/agent.rb', line 360 def model @ctx.model end |
#on_tool_confirmation(fn, strategy) ⇒ LLM::Function::Return
This method is called when confirmation is required before a tool can run.
456 457 458 |
# File 'lib/llm/agent.rb', line 456 def on_tool_confirmation(fn, strategy) fn.cancel end |
#params ⇒ Hash
405 406 407 |
# File 'lib/llm/agent.rb', line 405 def params @ctx.params end |
#prompt(&b) ⇒ LLM::Prompt Also known as: build_prompt
302 303 304 |
# File 'lib/llm/agent.rb', line 302 def prompt(&b) @ctx.prompt(&b) end |
#remote_file(res) ⇒ LLM::Object
Returns a tagged object
330 331 332 |
# File 'lib/llm/agent.rb', line 330 def remote_file(res) @ctx.remote_file(res) end |
#repl ⇒ void
This method returns an undefined value.
Start a minimalist repl that can interact with the agent and its current state. This method requires the 'curses' gem to be installed and available to require.
397 398 399 400 |
# File 'lib/llm/agent.rb', line 397 def repl require_relative "repl" unless defined?(::LLM::Repl) LLM::Repl.new(self).start end |
#returns ⇒ Array<LLM::Function::Return>
273 274 275 |
# File 'lib/llm/agent.rb', line 273 def returns @ctx.returns end |
#serialize(**kw) ⇒ void Also known as: save
This method returns an undefined value.
432 433 434 |
# File 'lib/llm/agent.rb', line 432 def serialize(**kw) @ctx.serialize(**kw) end |
#stream ⇒ LLM::Stream, ...
Returns a stream object, or nil
353 354 355 |
# File 'lib/llm/agent.rb', line 353 def stream @ctx.stream 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.
248 249 250 |
# File 'lib/llm/agent.rb', line 248 def talk(prompt, params = {}) run_loop(prompt, params, :talk) end |
#to_h ⇒ Hash
412 413 414 |
# File 'lib/llm/agent.rb', line 412 def to_h @ctx.to_h end |
#to_json ⇒ String
418 419 420 |
# File 'lib/llm/agent.rb', line 418 def to_json(...) LLM.json.dump(to_h, ...) end |
#tracer ⇒ LLM::Tracer
Returns an LLM tracer
337 338 339 |
# File 'lib/llm/agent.rb', line 337 def tracer @tracer || @ctx.tracer end |
#tracer=(other) ⇒ void
This method returns an undefined value.
345 346 347 348 |
# File 'lib/llm/agent.rb', line 345 def tracer=(other) @ctx.tracer = other @tracer = other end |
#wait ⇒ Array<LLM::Function::Return>
280 281 282 |
# File 'lib/llm/agent.rb', line 280 def wait(...) @tracer ? @llm.with_tracer(@tracer) { @ctx.wait(...) } : @ctx.wait(...) end |