Crafting a tool definition is fundamental for extending an LLM agent's abilities and requires clear specifications. Here, the process of creating your first tool definition is outlined. A well-defined tool is the foundation of effective LLM interaction, ensuring the agent understands what the tool does, what information it needs, and what to expect in return.We will focus on the definition aspect here. The actual Python code that implements the tool's logic will be covered in subsequent chapters. For now, our goal is to create a clear contract that an LLM can use.The Anatomy of a Tool DefinitionBefore we start, let's briefly review the main components of a tool definition. These components work together to provide a comprehensive understanding of the tool for the LLM agent.digraph ToolDefinition { rankdir=LR; node [shape=box, style="rounded,filled", fillcolor="#e9ecef", fontname="Arial"]; edge [fontname="Arial"]; ToolDef [label="Complete Tool Definition", fillcolor="#4dabf7", shape=hexagon]; Name [label="Tool Name\n(Unique identifier, e.g., 'get_current_weather')", fillcolor="#a5d8ff"]; Description [label="Purpose Description\n(Clear explanation for the LLM: what it does, when to use it)", fillcolor="#96f2d7"]; InputSchema [label="Input Schema (Parameters)\n(Defines required arguments, data types, and descriptions for each)", fillcolor="#b2f2bb"]; OutputSchema [label="Output Schema (Return Values)\n(Describes the structure and data types of the expected result)", fillcolor="#ffec99"]; ToolDef -> Name [label=" has a"]; ToolDef -> Description [label=" has a"]; ToolDef -> InputSchema [label=" defines"]; ToolDef -> OutputSchema [label=" defines"]; InputSchema -> InputParam1 [label="e.g., city (string, required)\n'The name of the city.'"]; InputSchema -> InputParam2 [label="e.g., unit (string, optional)\n'Temperature unit: Celsius or Fahrenheit.'"]; InputParam1 [shape=note, fillcolor="#ffffff", fontcolor="#343a40"]; InputParam2 [shape=note, fillcolor="#ffffff", fontcolor="#343a40"]; OutputSchema -> OutputField1 [label="e.g., temperature (number)\n'The current temperature value.'"]; OutputSchema -> OutputField2 [label="e.g., condition (string)\n'Textual description of weather.'"]; OutputField1 [shape=note, fillcolor="#ffffff", fontcolor="#343a40"]; OutputField2 [shape=note, fillcolor="#ffffff", fontcolor="#343a40"]; }Components typically found in a tool definition for an LLM agent.Scenario: A Simple Weather Information ToolLet's design a tool that can fetch the current weather for a given location. This is a common and practical example. An LLM agent could use such a tool to answer user queries like "What's the weather like in London?" or "Will I need an umbrella in Paris tomorrow?" (though our first version will stick to current weather).Our tool will need:A clear name.A description that the LLM can understand to decide when to use this tool.A definition of the input parameters (e.g., the city).A definition of what the output will look like (e.g., temperature, conditions).Step 1: Naming Your ToolThe name should be descriptive yet concise. It's often used programmatically, so snake_case or camelCase is common. Let's call our tool: get_current_weather.Step 2: Crafting the DescriptionThe description is primarily for the LLM. It should clearly explain:What the tool does.When it should be used.Any details about its capabilities or limitations.A good description for our get_current_weather tool might be: "Fetches the current weather conditions, including temperature, a brief description, and humidity, for a specified city. Use this tool when a user asks about the weather in a particular location. It can optionally take a state or country code to help disambiguate cities with the same name."Notice how this description guides the LLM on its utility ("when a user asks about the weather") and hints at its parameters.Step 3: Defining Input Parameters (The Input Schema)Tools need inputs to operate. We need to define each parameter the get_current_weather tool expects. For each parameter, we should specify:Name: How the parameter is identified (e.g., city).Type: The data type (e.g., string, number, boolean).Description: A human-readable and LLM-readable explanation of what this parameter is for. This is very important for the LLM to correctly populate the arguments.Required/Optional: Whether the LLM must provide this parameter.Many LLM frameworks use a JSON Schema-like structure for defining parameters. Let's define the inputs for our weather tool:city:Type: stringDescription: "The name of the city for which to retrieve the weather, e.g., 'San Francisco', 'Tokyo'."Required: Yesstate_or_country_code:Type: stringDescription: "Optional. The state abbreviation (e.g., 'CA' for California) or the two-letter ISO country code (e.g., 'GB' for Great Britain) to disambiguate the city name if necessary."Required: NoThis tells the LLM that it absolutely needs a city, but the state_or_country_code is optional and should be used to provide more specific location information if available or needed.Step 4: Defining the Output Structure (The Output Schema)Just as important as defining inputs is defining the structure of the data the tool will return. This helps the LLM (and you, the developer) understand what to expect back from the tool after it executes.For our get_current_weather tool, a successful execution might return:location_found:Type: stringDescription: "The fully resolved location for which weather was found, e.g., 'London, GB'."temperature:Type: number (could be integer or float)Description: "The current temperature."unit:Type: stringDescription: "The unit of temperature provided (e.g., 'Celsius', 'Fahrenheit')."condition:Type: stringDescription: "A brief textual description of the weather conditions (e.g., 'Sunny', 'Cloudy with showers')."humidity_percent:Type: integerDescription: "The current humidity as a percentage (e.g., 65 for 65%)."error:Type: string (or null)Description: "An error message if the weather data could not be retrieved (e.g., 'City not found'). This field will be absent or null if the request was successful."Defining the output, especially including potential error fields, makes the tool more predictable and easier for the LLM agent to handle various outcomes.Step 5: Assembling the Complete Tool DefinitionNow, let's put all these pieces together into a single, structured definition. The exact format can vary depending on the LLM framework you are using (like LangChain, LlamaIndex, or directly with models like OpenAI's GPT). A common approach is a JSON object.Here’s how our get_current_weather tool definition might look:{ "name": "get_current_weather", "description": "Fetches the current weather conditions, including temperature, a brief description, and humidity, for a specified city. Use this tool when a user asks about the weather in a particular location. It can optionally take a state or country code to help disambiguate cities with the same name.", "input_schema": { "type": "object", "properties": { "city": { "type": "string", "description": "The name of the city for which to retrieve the weather, e.g., 'San Francisco', 'Tokyo'." }, "state_or_country_code": { "type": "string", "description": "Optional. The state abbreviation (e.g., 'CA' for California) or the two-letter ISO country code (e.g., 'GB' for Great Britain) to disambiguate the city name if necessary." } }, "required": ["city"] }, "output_schema": { "type": "object", "properties": { "location_found": { "type": "string", "description": "The fully resolved location for which weather was found, e.g., 'London, GB'." }, "temperature": { "type": "number", "description": "The current temperature." }, "unit": { "type": "string", "description": "The unit of temperature provided (e.g., 'Celsius', 'Fahrenheit')." }, "condition": { "type": "string", "description": "A brief textual description of the weather conditions (e.g., 'Sunny', 'Cloudy with showers')." }, "humidity_percent": { "type": "integer", "description": "The current humidity as a percentage (e.g., 65 for 65%)." }, "error": { "type": "string", "description": "An error message if the weather data could not be retrieved (e.g., 'City not found'). This field will be absent or null if the request was successful." } }, "required": ["location_found", "temperature", "unit", "condition", "humidity_percent"] } }Note: Some frameworks might use "parameters" instead of "input_schema". The is the structured definition of inputs and outputs. The required list in the output_schema indicates fields expected upon success; the error field would typically be present only if something went wrong.Why This Definition WorksThis structured definition serves several important purposes:LLM Understanding: The name and description help the LLM identify the right tool for a given user query or task.Argument Formulation: The input_schema, particularly the properties and their individual description fields, allows the LLM to understand what arguments are needed, their types, and how to format them. For example, if a user says "weather in Paris", the LLM knows to extract "Paris" for the city parameter.Output Interpretation: While not all frameworks require a strict output_schema for the LLM's direct use in the same way as an input_schema, defining it is a best practice. It clarifies the contract for the developer implementing the tool and helps in designing how the LLM should process the tool's results. It's also invaluable for testing and validation.From This ExerciseAs you craft your own tool definitions, remember these points derived from our example:Clarity is Essential: Descriptions for the tool itself and its parameters must be unambiguous for the LLM. Think from the LLM's perspective: "If I read this, would I know exactly what to provide and what this tool does?"Be Specific with Types: Using correct data types (string, number, boolean, object, array) helps in validation and ensures the tool receives data in the expected format.Distinguish Required vs. Optional: This helps the LLM formulate valid calls and allows for more flexible tools.Plan for Outputs: Knowing what your tool will return, including potential error states, is as important as defining its inputs.This hands-on exercise in defining a tool lays the groundwork for the next step: implementing the actual logic behind it. With a solid definition, you provide the LLM agent with the necessary information to use your custom capabilities effectively. In the following chapters, we'll explore how to bring these definitions to life with Python code.