Tool¶
Callable function that robots can use to interact with external systems.
Class: RobotLab::Tool < RubyLLM::Tool¶
RobotLab::Tool inherits from RubyLLM::Tool, adding a robot: constructor parameter and a Tool.create factory for dynamic tools.
Subclass Pattern¶
class GetWeather < RobotLab::Tool
description "Get weather for a location"
param :location, type: "string", desc: "City name or zip code"
param :unit, type: "string", desc: "Temperature unit", required: false
def execute(location:, unit: "celsius")
WeatherService.current(location, unit: unit)
end
end
Factory Pattern¶
tool = RobotLab::Tool.create(
name: "get_weather",
description: "Get current weather for a location",
parameters: {
type: "object",
properties: {
location: { type: "string", description: "City name" }
},
required: ["location"]
}
) { |args| WeatherService.current(args[:location]) }
Constructor¶
Parameters:
| Name | Type | Description |
|---|---|---|
robot |
Robot, nil |
The owning robot instance |
Class Methods¶
Tool.create¶
Factory for dynamic tools (MCP wrappers, inline tools).
Parameters:
| Name | Type | Description |
|---|---|---|
name |
String, Symbol |
Tool identifier |
description |
String |
What the tool does |
parameters |
Hash |
JSON Schema parameter definition |
mcp |
String |
MCP server name |
robot |
Robot |
Owning robot instance |
&handler |
Block |
Receives args hash, returns result |
Inherited DSL (from RubyLLM::Tool)¶
description¶
param¶
class MyTool < RobotLab::Tool
param :name, type: "string", desc: "User's name"
param :age, type: "integer", desc: "User's age", required: false
end
execute¶
halt¶
Stop the tool use loop from within execute:
with_params¶
Set provider-specific parameters:
Attributes¶
robot¶
Read/write accessor for the owning robot. Set via constructor or assigned later.
mcp¶
The MCP server name, set via Tool.create(mcp: "server_name").
Methods¶
name¶
Returns the tool name. For subclasses, derived from the class name (CamelCase to snake_case). For created tools, returns the explicit name.
mcp?¶
Whether this is an MCP-provided tool.
call¶
Inherited from RubyLLM::Tool. Converts string keys to symbols and calls execute(**args).
params_schema¶
Inherited. Returns the JSON Schema for tool parameters.
provider_params¶
Inherited. Returns provider-specific parameters (e.g., { strict: true }).
to_h¶
Hash representation with :name, :description, :mcp.
to_json¶
JSON representation.
to_json_schema¶
JSON Schema representation for LLM function calling. Returns { name:, description:, parameters: }.
Robot-Aware Tools¶
Tools that modify their owning robot use the robot accessor:
class AdjustTemperature < RobotLab::Tool
description "Adjust the robot's creativity level"
param :level, type: "number", desc: "Temperature from 0.0 to 1.0"
def execute(level:)
robot.with_temperature(level)
"Temperature adjusted to #{level}"
end
end
# Pass robot: self when constructing
robot = RobotLab.build(
name: "creative_bot",
system_prompt: "You are creative.",
local_tools: [AdjustTemperature.new(robot: self)]
)
Parameter Types¶
String¶
Integer¶
Number (Float)¶
Boolean¶
Required vs Optional¶
Parameters are required by default. Mark optional with required: false:
param :query, type: "string", desc: "Search query" # required
param :limit, type: "integer", desc: "Max results", required: false # optional
Built-in: AskUser¶
RobotLab::AskUser is a built-in tool that lets a robot ask the user a question via the terminal. The LLM decides when human input is needed and calls this tool.
Class: RobotLab::AskUser < RobotLab::Tool¶
class RobotLab::AskUser < RobotLab::Tool
description "Ask the user a question and wait for their typed response"
param :question, type: "string", desc: "The question to ask the user"
param :choices, type: "array", desc: "Optional list of choices to present", required: false
param :default, type: "string", desc: "Default value if user presses Enter", required: false
end
Parameters¶
| Name | Type | Required | Description |
|---|---|---|---|
question |
String |
Yes | The question to display |
choices |
Array |
No | Numbered choices to present |
default |
String |
No | Value returned when user presses Enter without typing |
IO Resolution¶
The tool reads input and writes output using the owning robot's input/output accessors:
robot.input/robot.outputif set- Falls back to
$stdin/$stdout
Terminal Output¶
Usage¶
robot = RobotLab.build(
name: "interviewer",
system_prompt: "Interview the user about their project needs. Use ask_user to gather information.",
local_tools: [RobotLab::AskUser]
)
robot.run("Find out what the user wants to build")
Testing with StringIO¶
robot = RobotLab::Robot.new(name: "bot", template: :assistant)
robot.input = StringIO.new("Ruby\n")
robot.output = StringIO.new
tool = RobotLab::AskUser.new(robot: robot)
result = tool.call("question" => "Pick a language:", "choices" => ["Ruby", "Python"])
# => "Ruby"
Choice Mapping¶
When choices are provided, the user can type either:
- A number (e.g.,
2) — mapped to the corresponding choice text - Text (e.g.,
Python) — returned as-is
Out-of-range numbers are returned as-is (the LLM can re-ask if needed).