Class: LLM::Tool

Inherits:
Object
  • Object
show all
Extended by:
Function::Registry, Param
Defined in:
lib/llm/tool.rb,
lib/llm/tools/ls.rb,
lib/llm/tools/rg.rb,
lib/llm/tools/git.rb,
lib/llm/tools/pwd.rb,
lib/llm/tool/param.rb,
lib/llm/tools/chdir.rb,
lib/llm/tools/mkdir.rb,
lib/llm/tools/shell.rb,
lib/llm/tools/utils.rb,
lib/llm/tools/which.rb,
lib/llm/tools/read_file.rb,
lib/llm/tools/swap_text.rb,
lib/llm/tools/write_file.rb

Overview

The LLM::Tool class represents a local tool that can be called by an LLM. Under the hood, it is a wrapper around LLM::Function but allows the definition of a function (also known as a tool) as a class.

Examples:

Declarative form (preferred)

class ReadFile < LLM::Tool
  name "read-file"
  description "Read a file from disk"
  parameter :path, String, "The filename or path"
  required %i[path]

  def call(path:)
    {contents: File.read(path)}
  end
end

Block-form DSL (also supported)

class RunCommand < LLM::Tool
  name "run-command"
  description "Runs a shell command"
  params do |schema|
    schema.object(command: schema.string.required)
  end

  def call(command:)
    {success: Kernel.system(command)}
  end
end

See Also:

Direct Known Subclasses

Chdir, Git, Ls, Mkdir, Pwd, ReadFile, Rg, Shell, SwapText, Which, WriteFile

Defined Under Namespace

Modules: Param, Utils Classes: Chdir, Git, Ls, Mkdir, Pwd, ReadFile, Rg, Shell, SwapText, Which, WriteFile

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Param

defaults, param, required

Methods included from Function::Registry

clear_registry!, extended, find_by_name, lock, register, registry, registry_key, tool_name, unregister

Class Method Details

.a2a(a2a, skill) ⇒ Class<LLM::Tool>

Returns a subclass of LLM::Tool

Parameters:

Returns:

  • (Class<LLM::Tool>)

    Returns a subclass of LLM::Tool



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/llm/tool.rb', line 86

def self.a2a(a2a, skill)
  name = skill.name.gsub(" ", "-")
  Class.new(LLM::Tool) do
    name(name)
    description(skill.description)
    parameter :input, String, "The input string"
    required %i[input]

    define_singleton_method(:inspect) do
      "<#{LLM::Utils.object_id(self)} name=#{name} (a2a)>"
    end
    singleton_class.alias_method :to_s, :inspect

    define_singleton_method(:a2a?) do
      true
    end

    define_method(:call) do |input:|
      res = a2a.send_message(input)
      {task: res}
    end
  end
end

.a2a?Boolean

Returns true if the tool is an A2A tool

Returns:

  • (Boolean)


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

def self.a2a?
  false
end

.clear_registry!void

This method returns an undefined value.

Clear the registry



113
114
115
116
117
118
# File 'lib/llm/tool.rb', line 113

def self.clear_registry!
  lock do
    @__registry.each_value { LLM::Function.unregister(_1.function) }
    super
  end
end

.description(desc = nil) ⇒ String

Returns (or sets) the tool description

Parameters:

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

    The tool description

Returns:

  • (String)


183
184
185
186
187
# File 'lib/llm/tool.rb', line 183

def self.description(desc = nil)
  lock do
    desc ? function.description(desc) : function.description
  end
end

.find_by_name!(name) ⇒ Class<LLM::Tool>

Finds a registered tool by name.

Parameters:

  • name (String)

Returns:

Raises:



175
176
177
# File 'lib/llm/tool.rb', line 175

def self.find_by_name!(name)
  find_by_name(name) || raise(LLM::NoSuchToolError, "no such tool #{name.inspect}")
end

.functionObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



201
202
203
204
205
# File 'lib/llm/tool.rb', line 201

def self.function
  lock do
    @function ||= LLM::Function.new(nil)
  end
end

.inherited(tool) ⇒ void

This method returns an undefined value.

Registers the tool as a function when inherited

Parameters:

  • tool (Class)

    The subclass



145
146
147
148
149
150
151
# File 'lib/llm/tool.rb', line 145

def self.inherited(tool)
  LLM.lock(:inherited) do
    tool.instance_eval { @__monitor ||= Monitor.new }
    tool.function.define(tool)
    LLM::Tool.register(tool) unless tool.mcp? || tool.a2a?
  end
end

.mcp(mcp, tool) ⇒ Class<LLM::Tool>

Returns a subclass of LLM::Tool

Parameters:

  • mcp (LLM::MCP)

    The MCP client that will execute the tool call

  • tool (Hash)

    A tool (as a raw Hash)

Returns:

  • (Class<LLM::Tool>)

    Returns a subclass of LLM::Tool



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/llm/tool.rb', line 58

def self.mcp(mcp, tool)
  Class.new(LLM::Tool) do
    name tool["name"]
    description tool["description"]
    params { tool["inputSchema"] || {type: "object", properties: {}} }

    define_singleton_method(:inspect) do
      "<#{LLM::Utils.object_id(self)} name=#{tool["name"]} (mcp)>"
    end
    singleton_class.alias_method :to_s, :inspect

    define_singleton_method(:mcp?) do
      true
    end

    define_method(:call) do |**args|
      mcp.call_tool(tool["name"], args)
    end
  end
end

.mcp?Boolean

Returns true if the tool is an MCP tool

Returns:

  • (Boolean)


210
211
212
# File 'lib/llm/tool.rb', line 210

def self.mcp?
  false
end

.name(name = nil) ⇒ String

Returns (or sets) the tool name

Parameters:

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

    The tool name

Returns:

  • (String)


157
158
159
160
161
# File 'lib/llm/tool.rb', line 157

def self.name(name = nil)
  lock do
    name ? function.name(name) : function.name
  end
end

.params {|schema| ... } ⇒ LLM::Schema

Returns (or sets) tool parameters

Yield Parameters:

  • schema (LLM::Schema)

    The schema object to define parameters

Returns:



193
194
195
196
197
# File 'lib/llm/tool.rb', line 193

def self.params(&)
  lock do
    function.tap { _1.params(&) }
  end
end

.register(tool) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Registers a tool and its function.

Parameters:



124
125
126
127
# File 'lib/llm/tool.rb', line 124

def self.register(tool)
  super
  LLM::Function.register(tool.function)
end

.registryArray<Class<LLM::Tool>>

Returns all registered tool classes with definitions.

Returns:



166
167
168
# File 'lib/llm/tool.rb', line 166

def self.registry
  super.select(&:name)
end

.skill?Boolean

Returns true if the tool is a skill

Returns:

  • (Boolean)


224
225
226
# File 'lib/llm/tool.rb', line 224

def self.skill?
  false
end

.unregister(tool) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Unregister a tool from the registry

Parameters:



133
134
135
136
137
138
139
# File 'lib/llm/tool.rb', line 133

def self.unregister(tool)
  lock do
    LLM::Function.unregister(tool.function)
    super
    tool
  end
end

Instance Method Details

#a2a?Boolean

Returns true if the tool is an A2A tool

Returns:

  • (Boolean)


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

def a2a?
  self.class.a2a?
end

#functionLLM::Function

Returns a function bound to this tool instance.

Returns:



231
232
233
# File 'lib/llm/tool.rb', line 231

def function
  @function ||= self.class.function.dup.tap { _1.define(self) }
end

#mcp?Boolean

Returns true if the tool is an MCP tool

Returns:

  • (Boolean)


238
239
240
# File 'lib/llm/tool.rb', line 238

def mcp?
  self.class.mcp?
end

#on_cancelnil

Called when an in-flight tool run is cancelled.

Returns:

  • (nil)


266
267
268
# File 'lib/llm/tool.rb', line 266

def on_cancel
  on_interrupt
end

#on_interruptnil

Called when an in-flight tool run is interrupted. Tools can override this to implement cooperative cleanup.

Returns:

  • (nil)


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

def on_interrupt
end

#skill?Boolean

Returns true if the tool is a skill

Returns:

  • (Boolean)


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

def skill?
  self.class.skill?
end