Tool Definition in C#
Outline
In this lesson, we'll focus on the practical aspects of defining your custom tools using the OptimizelyOpal.OpalToolsSDK
. We'll cover the syntax for applying the [Tool]
attribute, how to structure your tool methods to accept parameters using C# models, and how to define parameter schemas.
By the end of this module, you will be able to:
- Define and register custom Opal tools using C# attributes
- Structure tool methods to accept and validate various types of parameters using .NET models.
- Define parameter schemas and metadata using attributes
Using the [Tool]
Attribute to Mark a Method as an Opal Tool
As introduced in the previous lesson, the [Tool]
attribute is how you tell the SDK that a particular static method should be exposed as an Opal tool.
Basic Structure:
using OptimizelyOpal.OpalToolsSDK.Attributes;
using OptimizelyOpal.OpalToolsSDK.Models; // For ParameterType if needed
// Define a parameter model (POCO)
public class MyToolParams
{
public string InputString { get; set; }
public int InputNumber { get; set; } = 0; // Parameter with a default value
}
public static class MyOpalTools
{
[Tool(name: "my_csharp_tool", description: "A simple C# tool example.")]
public static object MyCSharpToolFunction(MyToolParams parameters)
{
// Your tool's logic goes here
Console.WriteLine($"Tool executed with string: {parameters.InputString}, number: {parameters.InputNumber}");
var result = $"Processed: {parameters.InputString} and {parameters.InputNumber * 2}";
return new { status = "success", output = result };
}
}
-
name
(string): A crucial identifier. It should be unique within your tool service and descriptive, often usingsnake_case
. This is what Opal's AI will use to refer to your tool. -
description
(string): A human-readable explanation of the tool's purpose. It's used in the Opal UI. Make it clear and concise. - Method Signature: The static method's parameters (e.g.,
MyToolParams parameters
) are automatically used by the SDK to generate the tool's schema. - Return Value: The method should return an
object
that can be serialized to JSON as the response Opal receives. Anonymous objects (new { ... }
) or custom classes are common.
Structuring Your Tool Methods to Accept Parameters
When Opal invokes your tool, it sends the input data as a JSON object in the request body. The SDK, in conjunction with ASP.NET Core's model binding, automatically parses this and passes it to your tool method.
Using POCOs for Parameters: For tools with any parameters, it's best practice to define a dedicated C# class (a POCO - Plain Old CLR Object) to represent the input parameters. This provides strong typing and clear structure.
// Define a class for the tool's parameters
public class GreetPersonParams
{
public string PersonName { get; set; } // Property names will be mapped from JSON
public string Language { get; set; } = "en"; // Optional parameter with default
public bool IncludeEmoji { get; set; } = false;
}
public static class GreeterTools
{
[Tool(name: "greet_person", description: "Generates a personalized greeting.")]
public static object GreetPersonTool(GreetPersonParams parameters)
{
string greetingText;
switch (parameters.Language)
{
case "es":
greetingText = $"¡Hola, {parameters.PersonName}!";
break;
case "fr":
greetingText = $"Bonjour, {parameters.PersonName}!";
break;
case "en":
default:
greetingText = $"Hello, {parameters.PersonName}!";
break;
}
var emoji = parameters.IncludeEmoji ? " 👋" : "";
return new
{
greeting = greetingText + emoji,
languageUsed = parameters.Language,
personGreeted = parameters.PersonName
};
}
}
Defining Parameter Schemas
The SDK automatically generates the parameters
array in the manifest based on your C# method's arguments and their types. Attributes like [Description]
from System.ComponentModel
can be used on properties within your parameter models to provide richer metadata for the Opal UI.
using System.ComponentModel; // For [Description] attribute
public class DetailedGreetingParams
{
[Description("The name of the person to greet. This is a mandatory field.")]
public string Name { get; set; }
[Description("Optional language for the greeting. Choose from English (en), Spanish (es), or French (fr). Defaults to English.")]
public string Language { get; set; } = "en"; // The SDK will infer enum from usage or you can specify in Tool attribute if needed
}
public static class DetailedGreeterTools
{
[Tool(name: "detailed_greet_person", description: "Generates a personalized greeting with more options.")]
public static object DetailedGreetPersonTool(DetailedGreetingParams parameters)
{
// ... logic similar to above ...
return new { /* ... */ };
}
}
Key Takeaways:
- The
[Tool]
attribute is your primary interface for defining tools in C#. - Static methods are used for tool implementation.
- C# POCOs (Plain Old CLR Objects) are crucial for defining tool parameters, enabling automatic schema generation and validation.
- Your tool method should return an
object
that can be serialized to JSON.