Semantic Kernel with Caddey

Integrate Caddey tools into a Semantic Kernel C# agent.


Caddey exposes app features as tools, and Semantic Kernel agents can dynamically choose and call these tools via two generic functions: ListCaddeyTools and ExecuteCaddeyTool.

Prerequisites

  • Caddey API key (obtain when you create your Caddey agent)
  • .NET 7.0 SDK and a C# project
  • Semantic Kernel and OpenAI Connector
dotnet add package Microsoft.SemanticKernel
dotnet add package Microsoft.SemanticKernel.Connectors.OpenAI

Security tip: Store secrets in environment variables or user secrets (never commit them).

Approach: Dynamic Tool Loading

Provide two generic skill methods that let the agent fetch and execute Caddey tools at runtime.

using System;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Plugins.Core;

public class CaddeyDynamicSkill
{
    private readonly HttpClient _http = new();
    private readonly string _apiKey;
    private const string BaseUrl = "https://api.caddey.ai";

    public CaddeyDynamicSkill(string apiKey) => _apiKey = apiKey;

    [KernelFunction("ListCaddeyTools")]
    [Description("List Caddey tools with optional pagination and searchTerm (JSON input).")]
    public async Task<string> ListCaddeyToolsAsync(string inputJson)
    {
        var options = string.IsNullOrWhiteSpace(inputJson)
            ? new { pageNumber = 0, pageSize = 20 }
            : JsonSerializer.Deserialize<JsonElement>(inputJson).EnumerateObject()
                .ToDictionary(p => p.Name, p => p.Value);
        var query = new StringBuilder($"pageNumber={options.GetValueOrDefault("pageNumber", 0)}&pageSize={options.GetValueOrDefault("pageSize", 20)}");
        if (options.TryGetValue("searchTerm", out var term))
        {
            query.Append($"&search={Uri.EscapeDataString(term.GetString())}");
        }
        var request = new HttpRequestMessage(HttpMethod.Get, $"{BaseUrl}/tools/query?{query}")
        {
            Headers = { { "X-API-KEY", _apiKey } }
        };
        var response = await _http.SendAsync(request);
        response.EnsureSuccessStatusCode();
        return await response.Content.ReadAsStringAsync();
    }

    [KernelFunction("ExecuteCaddeyTool")]
    [Description("Execute a Caddey tool by ID with JSON input (must include tool_id and input object).")]
    public async Task<string> ExecuteCaddeyToolAsync(string inputJson)
    {
        var doc = JsonDocument.Parse(inputJson).RootElement;
        var toolId = doc.GetProperty("tool_id").GetString();
        var payload = JsonSerializer.Serialize(doc.GetProperty("input").GetRawText());
        var request = new HttpRequestMessage(HttpMethod.Post, $"{BaseUrl}/tools/{toolId}/execute")
        {
            Headers = { { "X-API-KEY", _apiKey } },
            Content = new StringContent(payload, Encoding.UTF8, "application/json")
        };
        var response = await _http.SendAsync(request);
        response.EnsureSuccessStatusCode();
        return await response.Content.ReadAsStringAsync();
    }
}

Register the Skill and Initialize the Agent

var builder = Kernel.Builder;
builder.WithOpenAIChatCompletionService("gpt-4", Environment.GetEnvironmentVariable("OPENAI_API_KEY"));
builder.Plugins.AddFromType<CaddeyDynamicSkill>(
    "Caddey", new object[] { Environment.GetEnvironmentVariable("CADDEY_API_KEY") });

IKernel kernel = builder.Build();

var chat = kernel.ChatCompletion.CreateNewChat(
    "You are an assistant with access to Caddey tools via ListCaddeyTools and ExecuteCaddeyTool.");

var response = await kernel.RunAsync(
    "ListCaddeyTools",
    "{}"  // default: first page, 20 items
);
Console.WriteLine(response);

Using Your Agent

Simply prompt the agent in natural language, and it will pick the appropriate tool under the hood.

Examples:

  • Create a reminder to call Bob tomorrow at 3 PM.
  • Fetch the list of available tools.
  • Send an email to [email protected] with subject “Project Update” and body “The report is ready.”

The agent will automatically invoke the listing or execution of tools as needed.

For additional support, visit the Support Section.