Writing Tool Schemas for GPT-5
Introduction & Goals
Welcome to your first lesson in developing GPT-5 agents with tool integration! In this lesson, you'll learn the foundational skill of preparing function schemas that enable GPT-5 to understand and request the use of your custom tools through a process called function calling.
By the end of this lesson, you'll understand how to write Ruby methods in functions.rb and create JSON schemas in schemas.json that describe these methods to GPT-5. You'll also learn how to wire everything together in main.rb using a tool registry that maps schema names to Ruby Method objects. These schemas are the bridge that allows GPT-5 to understand what your methods do and how to call them, even though GPT-5 never sees your actual Ruby code. This foundational step is essential before you can build a complete GPT-5 agent system that can execute tools and use their results.
How GPT-5 Uses Tools Through Function Calling
Function calling is the mechanism that allows GPT-5 to use external tools and capabilities beyond text generation. Here is how the process works conceptually:
- You provide
GPT-5withfunction schemas(JSONdescriptions of your tools). GPT-5analyzes user requests and determines if any of your tools would be helpful.- If
GPT-5decides a tool is needed, it responds with a function call that includes the function name and specific arguments. - Your system receives this
function call, looks up the correspondingRubymethod in yourtool registry, and executes it with the provided arguments. - Your system sends the method result back to
GPT-5. GPT-5incorporates this result into its response to the user or decides to use additional tools if needed.
The key insight is that GPT-5 only sees the schemas (JSON descriptions), never your actual Ruby code. The schemas must contain all the information GPT-5 needs to understand what each tool does and how to use it correctly. This separation means you can organize your Ruby methods however you like — GPT-5 relies entirely on the schema descriptions to make decisions about tool usage.
In this lesson, we'll focus on preparing the schemas, creating the tool registry, and verifying that your local tool dispatch works correctly. This prepares you for integrating with the OpenAI Responses API's tool-calling capabilities in future lessons.
Writing Ruby Tool Methods
When creating tool methods for GPT-5 agents, your Ruby methods serve two purposes: they contain the actual logic that will be executed, and they provide the foundation for creating accurate schemas. While GPT-5 never sees these methods directly, writing them clearly helps you create better schema descriptions.
In your functions.rb file, you can define your tool methods:
You will notice # frozen_string_literal: true at the top of our Ruby files. This pragma freezes string literals written in that file, such as "hello", which can improve performance and memory usage. It does not make every Ruby String object immutable: for example, strings created with String.new or mutable copies created with dup can still be modified. While not strictly necessary for tool integrations, this pragma is a best practice in modern Ruby development.
This method uses keyword arguments (denoted by the : after each parameter name like a: and b:). Keyword arguments are particularly well-suited for tool integration because GPT-5 sends arguments as a JSON object with named fields, which maps naturally to Ruby keyword arguments. This makes calling the method dynamic and explicit, with each argument paired with its parameter name.
Remember that GPT-5 will only see the schema you create, not this Ruby code. The method's clarity and well-named parameters are for your benefit when translating it into a schema that GPT-5 can understand.
Creating JSON Schemas for Single Functions
JSON schemas are the structured descriptions that tell GPT-5 exactly what each tool does and how to use it. These schemas are the only information GPT-5 receives about your tools, making them crucial for successful function calling.
Each schema contains several essential components that GPT-5 uses to understand your tool:
- The
typefield is always"function"for function tools (the OpenAI Responses API supports several tool kinds, and we use thefunctionkind here). - The
namefield identifies the tool and should be descriptive to helpGPT-5understand what the tool does and when to use it. While it doesn't necessarily need to match yourRubymethod name, keeping them consistent helps maintain clarity in your code. - The
descriptiontellsGPT-5what the tool does and when to use it. - The
parameterssection describes the arguments usingJSON Schemaformat, where each property represents a method parameter with its data type and description. - The
requiredarray lists which parameters are mandatory. - The
additionalProperties: falsefield is a strictness flag that preventsGPT-5from sending unexpected fields — a best practice for reliable tool calling.
While we use "number" for our math tools, JSON Schema supports several other data types you might need for different tools, such as "string" for text, "integer" for whole numbers, "boolean" for true/false values, and "array" for lists of items.
GPT-5 uses this schema information to decide when to use your tool and what arguments to provide. If the descriptions are unclear or incomplete, GPT-5 may use the tool incorrectly or not at all.
Building Multiple Tool Schemas
Real GPT-5 agents typically have access to multiple tools, each described by its own schema. Let's create a second method and organize our methods in a dedicated file. In your functions.rb file, you can collect your tool methods:
Organizing your methods in a separate file keeps your code organized and makes it easy to require them when needed with require_relative "functions". Each method follows the same pattern with keyword arguments, providing consistency across your tool collection.
Organizing Multiple Schemas in JSON Format
Just as you organize your Ruby methods in functions.rb, you can organize your corresponding schemas in a schemas.json file. This creates a clean separation between your implementation and the descriptions that GPT-5 will see:
When GPT-5 receives this array of schemas, it can analyze user requests and select the most appropriate tool. For example, if a user asks "What's 5 plus 3?", GPT-5 would choose sum_numbers. If they ask "What's 4 times 7?", GPT-5 would choose multiply_numbers. The clear descriptions in each schema help GPT-5 make these decisions accurately.
Function-to-Schema Mapping
After organizing your methods in functions.rb and schemas in schemas.json, you need to load both and create a mapping that connects them. This creates two essential components: the schemas that you provide to GPT-5, and the mapping that you use to execute methods when GPT-5 requests them.
In your main.rb file:
The tool_schemas variable contains the parsed JSON array that you'll provide to GPT-5 — this is how GPT-5 learns about your available tools and their capabilities. The tools Hash is your internal mapping that you use to execute the correct Ruby method when GPT-5 requests a tool by name.
This mapping must be precise — the keys in your tools Hash must exactly match the name fields in your schemas. If there is a mismatch, your system will not be able to execute the method when GPT-5 requests it.
Notice that we use method(:sum_numbers) to obtain a Method object. The :sum_numbers syntax (with a leading colon) creates a Ruby symbol, which is a lightweight, immutable string commonly used for naming things like methods or hash keys. Passing this symbol to the method function allows us to store a reference to the method that can be called later with .call(...). This pattern is essential for dynamically dispatching tool requests.
For example, when GPT-5 analyzes a user request and decides to use the "sum_numbers" tool with arguments {"a": 10, "b": 5}, the process works like this:
GPT-5references thetool_schemasto understand available tools.GPT-5sends you afunction callfor"sum_numbers"with the arguments.- You look up
"sum_numbers"in yourtoolsHash. - You execute
tools["sum_numbers"].call(a: 10, b: 5), which calls your actualsum_numbersmethod. - You return the result back to
GPT-5.
GPT-5 only sees the tool_schemas, while the tools Hash is your internal system for translating GPT-5's requests into actual method calls.
Verifying Your Tool Schemas
Before using your tool schemas with GPT-5, it is important to verify they are structured correctly and contain all necessary information. In your main.rb file, you can add:
This displays your tool definitions in a formatted way, allowing you to review each schema's structure:
Review this output to ensure your schemas have clear descriptions, correct parameter types, and complete required field lists. These details are crucial since GPT-5 depends entirely on this schema information to use your tools correctly.
Testing Your Function Mapping
With your schemas verified and mapping in place, you can test that your system can successfully execute tools based on their names. In your main.rb file, add:
Running ruby main.rb produces:
This confirms your method mapping works correctly and your system can execute tools by name using the .call method on Method objects, passing keyword arguments. When GPT-5 requests tool usage through function calling, you'll receive the tool name and arguments from GPT-5, then use this mapping to look up and call the corresponding Ruby method yourself, before sending the result back to GPT-5.
Summary & Next Steps
You've now learned the essential process of preparing tools for GPT-5 agents through function calling. This involves writing well-structured Ruby methods in functions.rb, creating detailed JSON schemas in schemas.json that describe these methods to GPT-5, and setting up a mapping system in main.rb using a Hash that connects schema names to Method objects.
Remember the key separation: GPT-5 only sees the schemas and uses them to make tool selection decisions and provide arguments. Your Ruby methods and Hash-based registry handle the actual execution. The quality of your schemas directly impacts how effectively GPT-5 can use your tools.
You've verified that your schemas are well-formed and that your local tool dispatch mechanism works correctly. This foundation — prepared schemas and a working tool registry — sets you up for integrating with the OpenAI Responses API's tool-calling capabilities in future lessons.
In the upcoming practice exercises, you'll apply these concepts to create your own tool methods and schemas, building toward the point where you can integrate these prepared tools with GPT-5 for powerful agent capabilities.
