Building Simple Tools
Outline
Now that you understand how to define tools and their parameters, let's get hands-on by building a couple of simple, practical tools. These examples will solidify your understanding of the tool()
decorator and parameter handling.
By the end of this module, you will be able to:
Build simple Opal tools that perform basic operations.
Implement conditional logic and optional parameters in tool functions.
Apply basic error handling and validation to make tools more reliable.
The "Greeting" Tool (Revisited and Enhanced)
We've already seen a basic version of this. Let's ensure it's fully functional and demonstrates good practices. This tool will take a person's name and an optional language, returning a personalized greeting.
Tool Definition (src/tools/GreetingTool.ts
)
import { tool, ParameterType } from '@optimizely-opal/opal-tools-sdk';
interface GreetingParams {
name: string;
language?: 'en' | 'es' | 'fr'; // Enforce specific languages
addExclamation?: boolean;
}
@tool({
name: 'greet_person',
description: 'Generates a personalized greeting for a person in a specified language.',
parameters: [
{
name: 'name',
type: ParameterType.String,
description: 'The name of the person to greet.',
required: true
},
{
name: 'language',
type: ParameterType.String,
description: 'Optional language for the greeting (e.g., "en", "es", "fr"). Defaults to "en".',
required: false,
enum: ['en', 'es', 'fr'] // Restrict to these options
},
{
name: 'addExclamation',
type: ParameterType.Boolean,
description: 'Set to true to add an exclamation mark to the greeting. Defaults to false.',
required: false
}
]
})
export class GreetingTool {
async execute(params: GreetingParams) {
const { name, language = 'en', addExclamation = false } = params;
let greetingPhrase: string;
switch (language) {
case 'es':
greetingPhrase = '¡Hola';
break;
case 'fr':
greetingPhrase = 'Bonjour';
break;
case 'en':
default:
greetingPhrase = 'Hello';
break;
}
const punctuation = addExclamation ? '!' : '.';
return {
greeting: `${greetingPhrase}, ${name}${punctuation}`,
languageUsed: language
};
}
}
Integration (src/index.ts
or src/main.ts
): Remember to import and register your new tool in your main application file:
// ... other imports
import { GreetingTool } from './tools/GreetingTool'; // Adjust path as needed
const opalToolsService = new OpalToolsService();
opalToolsService.registerTool(GreetingTool);
// ... register other tools
app.use(opalToolsService.getExpressMiddleware());
// ... rest of your Express app setup
The "Current Date" Tool
This tool will return the current date and time, with an optional format parameter. This demonstrates handling optional parameters and basic date manipulation.
Tool Definition (src/tools/CurrentDateTool.ts
):
import { tool, ParameterType } from '@optimizely-opal/opal-tools-sdk';
interface CurrentDateParams {
format?: 'YYYY-MM-DD' | 'MM/DD/YYYY HH:mm' | 'full'; // Specific format options
timezone?: string; // e.g., 'America/New_York'
}
@tool({
name: 'get_current_date',
description: 'Returns the current date and time, with optional formatting and timezone.',
parameters: [
{
name: 'format',
type: ParameterType.String,
description: 'Optional format string. "YYYY-MM-DD", "MM/DD/YYYY HH:mm", or "full". Defaults to "full".',
required: false,
enum: ['YYYY-MM-DD', 'MM/DD/YYYY HH:mm', 'full']
},
{
name: 'timezone',
type: ParameterType.String,
description: 'Optional IANA timezone string (e.g., "America/New_York"). Defaults to UTC.',
required: false
}
]
})
export class CurrentDateTool {
async execute(params: CurrentDateParams) {
const { format = 'full', timezone } = params;
const now = new Date();
let formattedDate: string;
const options: Intl.DateTimeFormatOptions = {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false, // Use 24-hour format
timeZone: timezone || 'UTC'
};
switch (format) {
case 'YYYY-MM-DD':
formattedDate = new Intl.DateTimeFormat('en-CA', { // en-CA gives YYYY-MM-DD
year: 'numeric', month: '2-digit', day: '2-digit', timeZone: timezone || 'UTC'
}).format(now);
break;
case 'MM/DD/YYYY HH:mm':
formattedDate = new Intl.DateTimeFormat('en-US', {
year: 'numeric', month: '2-digit', day: '2-digit',
hour: '2-digit', minute: '2-digit', hour12: false, timeZone: timezone || 'UTC'
}).format(now);
break;
case 'full':
default:
formattedDate = now.toLocaleString('en-US', options);
break;
}
return {
currentDateTime: formattedDate,
timestampUTC: now.toISOString(), // Always provide ISO string for consistency
requestedFormat: format,
usedTimezone: timezone || 'UTC'
};
}
}
Integration (src/index.ts
or src/main.ts
):
// ... other imports
import { CurrentDateTool } from './tools/CurrentDateTool'; // Adjust path as needed
const opalToolsService = new OpalToolsService();
opalToolsService.registerTool(GreetingTool); // Already registered
opalToolsService.registerTool(CurrentDateTool); // Register the new tool
// ... rest of your Express app setup
Interactive Exercise: Temperature Converter Tool
Now it's your turn! Build a tool that converts temperatures between Celsius and Fahrenheit. This will involve taking a temperature
(number) and a unit
(string: "C" or "F") as parameters and returning the converted temperature along with the original and converted units.
Requirements:
- Tool Name:
convert_temperature
- Description: Converts a temperature between Celsius and Fahrenheit.
- Parameters:
-
temperature
(Type:Number
, Required:true
, Description: "The temperature value to convert.") -
unit
(Type:String
, Required:true
, Description: "The unit of the input temperature ('C' for Celsius, 'F' for Fahrenheit).", Enum:['C', 'F']
)
-
- Output: An object containing the original temperature and unit, and the converted temperature and unit.
- Error Handling: If an invalid unit is provided, return an informative error message.
- Tool Name:
Hints:
- Conversion formulas:
- Celsius to Fahrenheit:
(C * 9/5) + 32
- Fahrenheit to Celsius:
(F - 32) * 5/9
- Celsius to Fahrenheit:
- Use
ParameterType.Number
for the temperature. - Use
ParameterType.String
with anenum
for the unit. - Implement
try...catch
or conditional logic to handle invalid unit inputs.
- Conversion formulas:
Take your time to implement this tool in a new file (e.g., src/tools/TemperatureConverterTool.ts
) and register it in your main application file. Test it using your API testing tool (Postman/Insomnia) by sending requests to <a href="http://localhost:3000/tools/convert_temperature">http://localhost:3000/tools/convert_temperature</a>
.