Skip to main content

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 using snake_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.