class Tool
A Tool is a Pipeline configured for tool execution. The terminal app does the work; middleware wraps it with concerns like file mutation queueing, snapshotting, validation, logging.
Coexists with Brute::Tools::* (which inherit from RubyLLM::Tool). Use Brute::Tool when you want middleware. Use RubyLLM::Tool subclasses for simple cases.
Usage:
read = Brute::Tool.new(
name: "read",
description: "Read a file's contents",
params: file_path: { type: "string", required: true },
) do
use Brute::Middleware::Tool::ValidateParams
run ->(env) {
env[:result] = File.read(File.expand_path(env[:arguments][:file_path]))
}
end
read.call(file_path: "lib/brute.rb")
Definitions
def call(events: NullSink.new, **arguments)
Execute the tool. Arguments come in as kwargs; result is whatever the terminal app puts into env[:result].
Implementation
def call(events: NullSink.new, **arguments)
env = {
name: @name,
arguments: arguments,
result: nil,
events: events,
metadata: {},
}
super(env)
env[:result]
end
def to_ruby_llm
Adapter so the LLM can call this tool through ruby_llm. ToolCall middleware checks for to_ruby_llm and uses it if present.
Implementation
def to_ruby_llm
tool = self
Class.new(RubyLLM::Tool) do
description tool.description
tool.params.each { |k, opts| param k, **opts }
define_method(:name) { tool.name }
define_method(:execute) { |**args| tool.call(**args) }
end.new
end