Class: LLM::Agent

Inherits:
Object
  • Object
show all
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 only on the first request.

  • An agent automatically executes tool loops (unlike LLM::Context).

  • Tool loop execution can be configured with ‘concurrency :call`, `:thread`, `:task`, or `:fiber`.

Examples:

class SystemAdmin < LLM::Agent
  model "gpt-4.1-nano"
  instructions "You are a Linux system admin"
  tools Shell
  schema Result
end

llm = LLM.openai(key: ENV["KEY"])
agent = SystemAdmin.new(llm)
agent.talk("Run 'date'")

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(llm, params = {}) ⇒ Agent

Returns a new instance of Agent.

Parameters:

  • provider (LLM::Provider)

    A provider

  • params (Hash) (defaults to: {})

    The parameters to maintain throughout the conversation. Any parameter the provider supports can be included and not only those listed here.

Options Hash (params):

  • :model (String)

    Defaults to the provider’s default model

  • :tools (Array<LLM::Function>, nil)

    Defaults to nil

  • :schema (#to_json, nil)

    Defaults to nil

  • :concurrency (Symbol, nil)

    Defaults to the agent class concurrency



109
110
111
112
113
114
# File 'lib/llm/agent.rb', line 109

def initialize(llm, params = {})
  defaults = {model: self.class.model, tools: self.class.tools, schema: self.class.schema}.compact
  @concurrency = params.delete(:concurrency) || self.class.concurrency
  @llm = llm
  @ctx = LLM::Context.new(llm, defaults.merge(params))
end

Instance Attribute Details

#llmLLM::Provider (readonly)

Returns a provider

Returns:



37
38
39
# File 'lib/llm/agent.rb', line 37

def llm
  @llm
end

Class Method Details

.concurrency(concurrency = nil) ⇒ Symbol?

Set or get the tool execution concurrency.

Parameters:

  • concurrency (Symbol, nil) (defaults to: nil)

    Controls how pending tool loops are executed:

    • ‘:call`: sequential calls

    • ‘:thread`: concurrent threads

    • ‘:task`: concurrent async tasks

    • ‘:fiber`: concurrent raw fibers

Returns:

  • (Symbol, nil)


93
94
95
96
# File 'lib/llm/agent.rb', line 93

def self.concurrency(concurrency = nil)
  return @concurrency if concurrency.nil?
  @concurrency = concurrency
end

.instructions(instructions = nil) ⇒ String?

Set or get the default instructions

Parameters:

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

    The system instructions

Returns:

  • (String, nil)

    Returns the current instructions when no argument is provided



78
79
80
81
# File 'lib/llm/agent.rb', line 78

def self.instructions(instructions = nil)
  return @instructions if instructions.nil?
  @instructions = instructions
end

.model(model = nil) ⇒ String?

Set or get the default model

Parameters:

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

    The model identifier

Returns:

  • (String, nil)

    Returns the current model when no argument is provided



45
46
47
48
# File 'lib/llm/agent.rb', line 45

def self.model(model = nil)
  return @model if model.nil?
  @model = model
end

.schema(schema = nil) ⇒ #to_json?

Set or get the default schema

Parameters:

  • schema (#to_json, nil) (defaults to: nil)

    The schema

Returns:

  • (#to_json, nil)

    Returns the current schema when no argument is provided



67
68
69
70
# File 'lib/llm/agent.rb', line 67

def self.schema(schema = nil)
  return @schema if schema.nil?
  @schema = schema
end

.tools(*tools) ⇒ Array<LLM::Function>

Set or get the default tools

Parameters:

Returns:

  • (Array<LLM::Function>)

    Returns the current tools when no argument is provided



56
57
58
59
# File 'lib/llm/agent.rb', line 56

def self.tools(*tools)
  return @tools || [] if tools.empty?
  @tools = tools.flatten
end

Instance Method Details

#callObject

Returns:

See Also:



188
189
190
# File 'lib/llm/agent.rb', line 188

def call(...)
  @ctx.call(...)
end

#concurrencySymbol?

Returns the configured tool execution concurrency.

Returns:

  • (Symbol, nil)


272
273
274
# File 'lib/llm/agent.rb', line 272

def concurrency
  @concurrency
end

#context_windowInteger

Returns:

  • (Integer)

See Also:



286
287
288
# File 'lib/llm/agent.rb', line 286

def context_window
  @ctx.context_window
end

#costLLM::Cost

Returns:

See Also:



279
280
281
# File 'lib/llm/agent.rb', line 279

def cost
  @ctx.cost
end

#deserialize(**kw) ⇒ LLM::Context Also known as: restore

Parameters:

  • path (String, nil)

    The path to a JSON file

  • string (String, nil)

    A raw JSON string

  • data (Hash, nil)

    A parsed context payload

Returns:



321
322
323
# File 'lib/llm/agent.rb', line 321

def deserialize(**kw)
  @ctx.deserialize(**kw)
end

#functionsArray<LLM::Function>

Returns:



174
175
176
# File 'lib/llm/agent.rb', line 174

def functions
  @ctx.functions
end

#image_url(url) ⇒ LLM::Object

Returns a tagged object

Parameters:

  • url (String)

    The URL

Returns:



227
228
229
# File 'lib/llm/agent.rb', line 227

def image_url(url)
  @ctx.image_url(url)
end

#inspectString

Returns:

  • (String)


305
306
307
308
# File 'lib/llm/agent.rb', line 305

def inspect
  "#<#{self.class.name}:0x#{object_id.to_s(16)} " \
  "@llm=#{@llm.class}, @mode=#{mode.inspect}, @messages=#{messages.inspect}>"
end

#interrupt!nil Also known as: cancel!

Interrupt the active request, if any.

Returns:

  • (nil)


208
209
210
# File 'lib/llm/agent.rb', line 208

def interrupt!
  @ctx.interrupt!
end

#local_file(path) ⇒ LLM::Object

Returns a tagged object

Parameters:

  • path (String)

    The path

Returns:



236
237
238
# File 'lib/llm/agent.rb', line 236

def local_file(path)
  @ctx.local_file(path)
end

#messagesLLM::Buffer<LLM::Message>



168
169
170
# File 'lib/llm/agent.rb', line 168

def messages
  @ctx.messages
end

#modeSymbol

Returns:

  • (Symbol)


265
266
267
# File 'lib/llm/agent.rb', line 265

def mode
  @ctx.mode
end

#modelString

Returns the model an Agent is actively using

Returns:

  • (String)


259
260
261
# File 'lib/llm/agent.rb', line 259

def model
  @ctx.model
end

#prompt(&b) ⇒ LLM::Prompt Also known as: build_prompt

Parameters:

  • b (Proc)

    A block that composes messages. If it takes one argument, it receives the prompt object. Otherwise it runs in prompt context.

Returns:

See Also:



217
218
219
# File 'lib/llm/agent.rb', line 217

def prompt(&b)
  @ctx.prompt(&b)
end

#remote_file(res) ⇒ LLM::Object

Returns a tagged object

Parameters:

Returns:



245
246
247
# File 'lib/llm/agent.rb', line 245

def remote_file(res)
  @ctx.remote_file(res)
end

#respond(prompt, params = {}) ⇒ LLM::Response

Note:

Not all LLM providers support this API

Maintain a conversation via the responses API. This method immediately sends a request to the LLM and returns the response.

Examples:

llm = LLM.openai(key: ENV["KEY"])
agent = LLM::Agent.new(llm)
res = agent.respond("What is the capital of France?")
puts res.output_text

Parameters:

  • params (Hash) (defaults to: {})

    The params passed to the provider, including optional :stream, :tools, :schema etc.

  • prompt (String)

    The input prompt to be completed

Options Hash (params):

  • :tool_attempts (Integer)

    The maxinum number of tool call iterations (default 10)

Returns:

  • (LLM::Response)

    Returns the LLM’s response for this turn.

Raises:



155
156
157
158
159
160
161
162
163
164
# File 'lib/llm/agent.rb', line 155

def respond(prompt, params = {})
  max = Integer(params.delete(:tool_attempts) || 10)
  res = @ctx.respond(apply_instructions(prompt), params)
  max.times do
    break if @ctx.functions.empty?
    res = @ctx.respond(call_functions, params)
  end
  raise LLM::ToolLoopError, "pending tool calls remain" unless @ctx.functions.empty?
  res
end

#returnsArray<LLM::Function::Return>

Returns:

See Also:



181
182
183
# File 'lib/llm/agent.rb', line 181

def returns
  @ctx.returns
end

#serialize(**kw) ⇒ void Also known as: save

This method returns an undefined value.



313
314
315
# File 'lib/llm/agent.rb', line 313

def serialize(**kw)
  @ctx.serialize(**kw)
end

#talk(prompt, params = {}) ⇒ LLM::Response Also known as: chat

Maintain a conversation via the chat completions API. This method immediately sends a request to the LLM and returns the response.

Examples:

llm = LLM.openai(key: ENV["KEY"])
agent = LLM::Agent.new(llm)
response = agent.talk("Hello, what is your name?")
puts response.choices[0].content

Parameters:

  • params (Hash) (defaults to: {})

    The params passed to the provider, including optional :stream, :tools, :schema etc.

  • prompt (String)

    The input prompt to be completed

Options Hash (params):

  • :tool_attempts (Integer)

    The maxinum number of tool call iterations (default 10)

Returns:

  • (LLM::Response)

    Returns the LLM’s response for this turn.

Raises:



129
130
131
132
133
134
135
136
137
138
# File 'lib/llm/agent.rb', line 129

def talk(prompt, params = {})
  max = Integer(params.delete(:tool_attempts) || 10)
  res = @ctx.talk(apply_instructions(prompt), params)
  max.times do
    break if @ctx.functions.empty?
    res = @ctx.talk(call_functions, params)
  end
  raise LLM::ToolLoopError, "pending tool calls remain" unless @ctx.functions.empty?
  res
end

#to_hHash

Returns:

  • (Hash)

See Also:



293
294
295
# File 'lib/llm/agent.rb', line 293

def to_h
  @ctx.to_h
end

#to_jsonString

Returns:

  • (String)


299
300
301
# File 'lib/llm/agent.rb', line 299

def to_json(...)
  to_h.to_json(...)
end

#tracerLLM::Tracer

Returns an LLM tracer

Returns:



252
253
254
# File 'lib/llm/agent.rb', line 252

def tracer
  @ctx.tracer
end

#usageLLM::Object

Returns:



201
202
203
# File 'lib/llm/agent.rb', line 201

def usage
  @ctx.usage
end

#waitArray<LLM::Function::Return>

Returns:

See Also:



195
196
197
# File 'lib/llm/agent.rb', line 195

def wait(...)
  @ctx.wait(...)
end