Table of Contents

  1. Model Tools
    1. Tool Arguments Schema
    2. Processing Model Tool Invocations
    3. Model Tool Observations
    4. Using Model Tools
  2. Provider-Managed Tools

Model Tools

Raif supports the creation of custom tools that the LLM can invoke in your tasks, conversations, and agents.

Two example tools are provided:

To create a new model tool, run the generator:

rails generate raif:model_tool GoogleSearch

This will create a new model tool in app/models/raif/model_tools/google_search.rb and a partial in app/views/raif/model_tool_invocations/_google_search.html.erb to display the tool invocation in the conversation interface.

Below is an example of a model tool that executes a Google search and returns the results:

class Raif::ModelTools::GoogleSearch < Raif::ModelTool
  tool_description do
    "Searches Google for the given query and returns the results as JSON."
  end

  tool_arguments_schema do
    string :query, description: "The query to search the web for"
    integer :max_results, description: "The maximum number of results to return"
    boolean :include_images, description: "Whether to include images in the results"
    array :exclude_domains do
      items type: "string"
    end
  end

  class << self
    def observation_for_invocation(tool_invocation)
      return "No results found" unless tool_invocation.result.present?

      JSON.pretty_generate(tool_invocation.result)
    end

    # When your tool is invoked in a Raif::Conversation, should the result be automatically provided back to the model?
    # When true, observation_for_invocation will be used to produce the observation provided to the model
    def triggers_observation_to_model?
      false
    end

    def process_invocation(tool_invocation)
      # tool_invocation.tool_arguments will be a JSON object matching your tool_arguments_schema
      query = tool_invocation.tool_arguments["query"]
      max_results = tool_invocation.tool_arguments["max_results"]
      include_images = tool_invocation.tool_arguments["include_images"]
      exclude_domains = tool_invocation.tool_arguments["exclude_domains"]

      # Assumes your application has a GoogleSearchService that can execute a Google search
      # and return an array of results
      search_results = GoogleSearchService.execute(query: query, max_results: max_results, include_images: include_images, exclude_domains: exclude_domains)

      # Store the results in the tool_invocation
      tool_invocation.update!(result: search_results)
    end
  end

end

Tool Arguments Schema

When the LLM invokes your tool, it will include a JSON object of arguments. You can use the tool_arguments_schema method to define the schema for these arguments. When the model invokes your tool, the arguments it provides will be validated against this schema using JSON::Validator from the json-schema gem.

See JSON Schemas for more information about defining JSON schemas.

Processing Model Tool Invocations

When the LLM invokes your tool, Raif will call your tool’s process_invocation method with a Raif::ModelToolInvocation record as an argument.

You should implement process_invocation to perform whatever actions are appropriate for your tool and store the results in the tool_invocation.result JSON column.

Model Tool Observations

When your tool is being invoked in a conversation or agent, the results of the tool invocation are provided back to the LLM as an observation.

To control the manner in which the result is provided to the LLM, implement the observation_for_invocation method.

Using Model Tools

Raif::Task, Raif::Conversation, and Raif::Agent all have an available_model_tools array to support the use of model tools. To make your tool available to the LLM, all you have to do is include it in the available_model_tools array.

Read more for each:

Provider-Managed Tools

In addition to the ability to create your own model tools, Raif supports provider-managed tools. These are tools that are built into certain LLM providers and run on the provider’s infrastructure:

  • Raif::ModelTools::ProviderManaged::WebSearch - Performs real-time web searches and considers relevant results when generating a response
  • Raif::ModelTools::ProviderManaged::CodeExecution - Executes code in a secure sandboxed environment (e.g. Python)
  • Raif::ModelTools::ProviderManaged::ImageGeneration - Generates images based on text descriptions

Current provider-managed tool support:

Provider Web Search Code Execution Image Generation
OpenAI Responses API
OpenAI Completions API
Anthropic Claude
AWS Bedrock (Claude)
OpenRouter

To use provider-managed tools, include them in the available_model_tools array, just like any other model tool:

# In a conversation
conversation = Raif::Conversation.create!(
  creator: current_user,
  available_model_tools: [
    "Raif::ModelTools::ProviderManaged::WebSearch",
    "Raif::ModelTools::ProviderManaged::CodeExecution"
  ]
)

# In a task definition
class MyTask < Raif::Task
  before_create ->{
    self.available_model_tools = [
      "Raif::ModelTools::ProviderManaged::WebSearch",
      "Raif::ModelTools::ProviderManaged::CodeExecution"
    ]
  }
end

# Or directly in a chat
llm = Raif.llm(:open_ai_responses_gpt_4_1)
model_completion = llm.chat(
  messages: [{ role: "user", content: "What are the latest developments in Ruby on Rails?" }], 
  available_model_tools: ["Raif::ModelTools::ProviderManaged::WebSearch"]
)

Read next: Web Admin