Module: SwarmSDK::CustomToolRegistry

Defined in:
lib/swarm_sdk/custom_tool_registry.rb

Overview

Registry for user-defined custom tools

Provides a simple way to register custom tools without creating a full plugin. Custom tools are registered globally and available to all agents that request them.

When to Use Custom Tools vs Plugins

Use Custom Tools when:

  • You have simple, stateless tools
  • Tools don't need persistent storage
  • Tools don't need lifecycle hooks
  • Tools don't need system prompt contributions

Use Plugins when:

  • Tools need persistent storage per agent
  • Tools need lifecycle hooks (on_agent_initialized, on_user_message, etc.)
  • Tools need to contribute to system prompts
  • You have a suite of related tools that share configuration

Examples:

Register a simple tool

class WeatherTool < RubyLLM::Tool
  description "Get weather for a city"
  param :city, type: "string", required: true

  def execute(city:)
    "Weather in #{city}: Sunny"
  end
end

SwarmSDK.register_tool(WeatherTool)

Register with explicit name

SwarmSDK.register_tool(:Weather, WeatherTool)

Tool with creation requirements

class AgentAwareTool < RubyLLM::Tool
  def self.creation_requirements
    [:agent_name, :directory]
  end

  def initialize(agent_name:, directory:)
    super()
    @agent_name = agent_name
    @directory = directory
  end

  def execute
    "Agent: #{@agent_name}, Dir: #{@directory}"
  end
end

SwarmSDK.register_tool(AgentAwareTool)

Defined Under Namespace

Classes: NamedToolWrapper

Class Method Summary collapse

Class Method Details

.clearvoid

This method returns an undefined value.

Clear all registered custom tools

Primarily useful for testing.



176
177
178
# File 'lib/swarm_sdk/custom_tool_registry.rb', line 176

def clear
  @tools.clear
end

.create(name, context = {}) ⇒ RubyLLM::Tool

Create a tool instance

Uses the tool's creation_requirements class method (if defined) to determine what parameters to pass to the constructor. The created tool is wrapped with NamedToolWrapper to ensure the registered name is used for tool lookup.

Parameters:

  • name (Symbol, String)

    Tool name

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

    Available context for tool creation

Options Hash (context):

  • :agent_name (Symbol)

    Agent identifier

  • :directory (String)

    Agent's working directory

Returns:

  • (RubyLLM::Tool)

    Instantiated tool (wrapped with registered name)

Raises:



143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/swarm_sdk/custom_tool_registry.rb', line 143

def create(name, context = {})
  name_sym = name.to_sym
  tool_class = @tools[name_sym]

  raise ConfigurationError, "Unknown custom tool: #{name}" unless tool_class

  # Create the tool instance
  tool = if tool_class.respond_to?(:creation_requirements)
    requirements = tool_class.creation_requirements
    params = extract_params(requirements, context, name)
    tool_class.new(**params)
  else
    # No requirements - simple instantiation
    tool_class.new
  end

  # Wrap with NamedToolWrapper to ensure registered name is used
  NamedToolWrapper.new(tool, name_sym)
end

.get(name) ⇒ Class?

Get a registered tool class

Parameters:

  • name (Symbol, String)

    Tool name

Returns:

  • (Class, nil)

    Tool class or nil if not found



120
121
122
# File 'lib/swarm_sdk/custom_tool_registry.rb', line 120

def get(name)
  @tools[name.to_sym]
end

.infer_name(tool_class) ⇒ Symbol

Infer tool name from class name

Examples:

infer_name(WeatherTool) #=> :Weather
infer_name(MyApp::Tools::StockPrice) #=> :StockPrice
infer_name(MyApp::Tools::StockPriceTool) #=> :StockPrice

Parameters:

  • tool_class (Class)

    Tool class

Returns:

  • (Symbol)

    Inferred tool name



189
190
191
192
193
194
195
196
197
# File 'lib/swarm_sdk/custom_tool_registry.rb', line 189

def infer_name(tool_class)
  # Get the class name without module prefix
  class_name = tool_class.name.split("::").last

  # Remove "Tool" suffix if present
  name = class_name.sub(/Tool\z/, "")

  name.to_sym
end

.register(name, tool_class) ⇒ void

This method returns an undefined value.

Register a custom tool

Parameters:

  • name (Symbol)

    Tool name

  • tool_class (Class)

    Tool class (must be a RubyLLM::Tool subclass)

Raises:

  • (ArgumentError)

    If tool_class is not a RubyLLM::Tool subclass

  • (ArgumentError)

    If a tool with the same name is already registered



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

def register(name, tool_class)
  name = name.to_sym

  unless tool_class.is_a?(Class) && tool_class < RubyLLM::Tool
    raise ArgumentError, "Tool class must inherit from RubyLLM::Tool"
  end

  if @tools.key?(name)
    raise ArgumentError, "Custom tool '#{name}' is already registered"
  end

  if PluginRegistry.plugin_tool?(name)
    raise ArgumentError, "Tool '#{name}' is already provided by a plugin"
  end

  if Tools::Registry.exists?(name)
    raise ArgumentError, "Tool '#{name}' is a built-in tool and cannot be overridden"
  end

  @tools[name] = tool_class
end

.registered?(name) ⇒ Boolean

Check if a custom tool is registered

Parameters:

  • name (Symbol, String)

    Tool name

Returns:

  • (Boolean)


112
113
114
# File 'lib/swarm_sdk/custom_tool_registry.rb', line 112

def registered?(name)
  @tools.key?(name.to_sym)
end

.tool_namesArray<Symbol>

Get all registered custom tool names

Returns:

  • (Array<Symbol>)


127
128
129
# File 'lib/swarm_sdk/custom_tool_registry.rb', line 127

def tool_names
  @tools.keys
end

.unregister(name) ⇒ Class?

Unregister a custom tool

Parameters:

  • name (Symbol, String)

    Tool name

Returns:

  • (Class, nil)

    The unregistered tool class, or nil if not found



167
168
169
# File 'lib/swarm_sdk/custom_tool_registry.rb', line 167

def unregister(name)
  @tools.delete(name.to_sym)
end