/ docs · functional specification

The full platform
functional reference.

Every functional area of AI API Mapper documented at implementation depth so architects, security reviewers, and platform engineers can evaluate the product with real technical context.

SDK · .NET

.NET SDK

Purpose

The .NET SDK provides a IAiApiMapperClient abstraction and orchestrator adapters for Microsoft.Extensions.AI, Semantic Kernel, and Azure AI Foundry Agents.

Main Capabilities

  • Singleton client registered via IServiceCollection
  • Automatic MCP session management and tool pagination
  • System prompt and tool list fetching (opt-in in-memory cache via CacheTools / CacheSystemPrompt)
  • Three authentication modes: API key, OAuth2 client credentials, delegated bearer
  • Structured logging via ILogger<ApiMapperClient>
  • Resilience pipeline via Microsoft.Extensions.Http.Resilience
  • Adapters for Microsoft.Extensions.AI, Semantic Kernel 1.73, Azure AI Foundry Agents

Packages

Package Description
CodedProjects.AI.ApiMapper.Client Core client
CodedProjects.AI.ApiMapper.Client.MicrosoftExtensionsAI ME.AI AIFunction adapter
CodedProjects.AI.ApiMapper.Client.SemanticKernel SK KernelPlugin adapter
CodedProjects.AI.ApiMapper.Client.AzureAIFoundry Azure AI Foundry toolset and run loop

Registration

Register the client in Program.cs or Startup.cs. It is registered as a singleton.

builder.Services
    .AddApiMapperClient(opts =>
    {
        opts.BaseUrl               = configuration["ApiMapper:BaseUrl"];
        opts.TenantId              = Guid.Parse(configuration["ApiMapper:TenantId"]);
        opts.ClientId              = "my-app";
        opts.SystemPromptResourceUri = "apimapper://toolsets/system-prompt";
    })
    .WithApiKey(configuration["ApiMapper:ApiKey"]);

See SDK Authentication for OAuth2 and delegated bearer options.

Raw Tool Loop (01-raw-mcp-client)

Fetch the system prompt, load tools, and drive a manual OpenAI tool-call loop.

var systemPrompt = await client.GetSystemPromptAsync();
var tools = await client.GetToolsAsync();

var chatTools = tools.Select(t => ChatTool.CreateFunctionTool(
    t.Name, t.Description, BinaryData.FromObjectAsJson(t.InputSchema))).ToList();

var messages = new List<ChatMessage>
{
    new SystemChatMessage(systemPrompt ?? "You are a helpful assistant."),
    new UserChatMessage(userMessage)
};

while (true)
{
    var response = await openai.CompleteChatAsync(messages,
        new ChatCompletionOptions { Tools = { chatTools } });

    if (response.Value.FinishReason == ChatFinishReason.ToolCalls)
    {
        messages.Add(new AssistantChatMessage(response.Value));
        foreach (var call in response.Value.ToolCalls)
        {
            var args   = JsonSerializer.Deserialize<Dictionary<string, object>>(call.FunctionArguments.ToString());
            var result = await client.InvokeToolAsync(call.FunctionName, args);
            messages.Add(new ToolChatMessage(call.Id, result?.ToText() ?? ""));
        }
        continue;
    }

    Console.WriteLine(response.Value.Content[0].Text);
    break;
}

Microsoft.Extensions.AI (02-microsoft-extensions-ai)

ApiMapperAIFunctionFactory.CreateFunctionsAsync converts tools to AIFunction instances. Pass them to any IChatClient.

var systemPrompt = await client.GetSystemPromptAsync();
var functions    = await ApiMapperAIFunctionFactory.CreateFunctionsAsync(client);

var messages = new List<ChatMessage>
{
    new(ChatRole.System, systemPrompt ?? "You are a helpful assistant."),
    new(ChatRole.User,   userMessage)
};

var options  = new ChatOptions { Tools = [..functions] };
ChatResponse response;

do
{
    response = await chatClient.GetResponseAsync(messages, options);
    messages.AddRange(response.Messages);
}
while (response.FinishReason == ChatFinishReason.ToolCalls);

Console.WriteLine(response.Text);

Semantic Kernel (03-semantic-kernel)

AddApiMapperPluginAsync registers all Runtime tools as a named KernelPlugin with automatic function calling.

await kernel.AddApiMapperPluginAsync(client, "RuntimeTools");

var systemPrompt = await client.GetSystemPromptAsync()
    ?? "You are a helpful assistant.";

var settings = new OpenAIPromptExecutionSettings
{
    ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions
};

var result = await kernel.InvokePromptAsync(
    $"<system>{systemPrompt}</system>\n\n{userMessage}",
    new KernelArguments(settings));

Console.WriteLine(result);

Azure AI Foundry Agents (04-azure-ai-foundry)

ApiMapperFoundryToolset converts tools to Azure AI Agents FunctionToolDefinition instances. AgentRunLoop.RunAsync drives the submit → poll → tool call loop.

var systemPrompt = await client.GetSystemPromptAsync()
    ?? "You are a helpful assistant.";

var toolset = await ApiMapperFoundryToolset.CreateAsync(client);

var agent = await agentsClient.Administration.CreateAgentAsync(
    model:        modelDeployment,
    instructions: systemPrompt,
    tools:        toolset.Definitions);

var thread = await agentsClient.Threads.CreateThreadAsync();
var answer = await AgentRunLoop.RunAsync(agentsClient, agent.Value, thread.Value, toolset, userMessage);
Console.WriteLine(answer);

Logging

The client uses ILogger<ApiMapperClient>. Configure your preferred sink in appsettings.json. Auth headers and secrets are never written to logs.

{
  "Logging": {
    "LogLevel": {
      "CodedProjects.AI.ApiMapper.Client": "Information"
    }
  }
}

Set to Debug to see MCP handshakes, per-tool invocation messages, and cache hits (when caching is explicitly enabled).