Sarıkaya Dev Logo

Build AI‑Enhanced .NET 8 Minimal APIs with Azure OpenAI Function Calling

Mahmut Sarıkaya 4 min read 2 Views 0
Build AI‑Enhanced .NET 8 Minimal APIs with Azure OpenAI Function Calling

Why AI‑Enhanced Minimal APIs Matter

Imagine a web service that can answer natural‑language questions, generate summaries, or even run calculations without a separate microservice layer. In 2024, more than 40% of new .NET projects adopt Minimal APIs because they reduce boilerplate by 60% while keeping full control over the request pipeline. Adding Azure OpenAI turns a simple endpoint into a conversational assistant that can invoke domain‑specific functions on the fly.

Prerequisites and System Requirements

Before writing code, ensure you have the following:

  • .NET 8 SDK (version 8.0.100 or later)
  • Azure subscription with an Azure OpenAI resource (GPT‑4o or gpt‑35‑turbo)
  • Visual Studio 2022 17.9+ or VS Code with C# extension
  • Basic knowledge of JSON schema for function calling

All tools run on Windows 11, macOS Ventura, or Ubuntu 22.04 – no additional runtime is required.

Setting Up .NET 8 and Azure OpenAI

Start a fresh Minimal API project and add the official Azure AI client library. The following terminal commands create the solution, add the NuGet package, and restore dependencies.

dotnet new web -n AiMinimalApi
cd AiMinimalApi
dotnet add package Azure.AI.OpenAI --version 1.2.0

After the restore, open Program.cs and replace its content with the skeleton shown later.

Creating a Minimal API Endpoint

The Minimal API model lets you define routes directly in Program.cs. Below is a fully functional endpoint that receives a user prompt, forwards it to Azure OpenAI, and returns the model’s reply.

using Microsoft.AspNetCore.Builder;<br/>using Microsoft.Extensions.DependencyInjection;<br/>using Azure;<br/>using Azure.AI.OpenAI;<br/>var builder = WebApplication.CreateBuilder(args);<br/>// Register OpenAI client as a singleton<br/>builder.Services.AddSingleton(_ => new OpenAIClient(new Uri(Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT")), new AzureKeyCredential(Environment.GetEnvironmentVariable("AZURE_OPENAI_KEY"))));<br/>var app = builder.Build();<br/>app.MapPost("/chat", async (ChatRequest request, OpenAIClient client) => {<br/>    var messages = new List<ChatMessage> { new ChatMessage(ChatRole.System, "You are a helpful assistant.") , new ChatMessage(ChatRole.User, request.Prompt) };<br/>    var options = new ChatCompletionsOptions(){ DeploymentName = "gpt-4o", Temperature = 0.7M };<br/>    options.Messages.AddRange(messages);<br/>    var response = await client.GetChatCompletionsAsync(options);<br/>    var reply = response.Value.Choices[0].Message.Content;<br/>    return Results.Ok(new { reply });<br/>});<br/>app.Run();<br/>record ChatRequest(string Prompt);

Notice the use of Environment.GetEnvironmentVariable – this keeps secrets out of source control. The endpoint expects a JSON payload like {"prompt":"Explain quantum entanglement"} and returns {"reply":"…"}.

Integrating Function Calling

Function calling lets the model decide when to execute a predefined C# method. Define a JSON schema that describes the function signature, then pass it through the Tools collection of ChatCompletionsOptions. The example below introduces a simple calculator function that adds two numbers.

var calculatorTool = new ChatCompletionsToolDefinition(){<br/>    Type = "function",<br/>    Function = new FunctionDefinition(){<br/>        Name = "add_numbers",<br/>        Description = "Adds two integers and returns the sum.",<br/>        Parameters = BinaryData.FromString(@"{<br/>  \"type\": \"object\",<br/>  \"properties\": {<br/>    \"a\": {\"type\": \"integer\"},<br/>    \"b\": {\"type\": \"integer\"}<br/>  },<br/>  \"required\": [\"a\", \"b\"]<br/>}")<br/>    }<br/>};<br/>options.Tools.Add(calculatorTool);

When the model detects a need for add_numbers, it returns a tool_calls object. Capture that response, invoke the C# method, and feed the result back to the model.

if (response.Value.Choices[0].Message.ToolCalls?.Count > 0){<br/>    var call = response.Value.Choices[0].Message.ToolCalls[0];<br/>    var args = JsonNode.Parse(call.FunctionArguments);<br/>    int a = args["a"].GetValue<int>();<br/>    int b = args["b"].GetValue<int>();<br/>    int sum = a + b;<br/>    var followUp = new ChatMessage(ChatRole.Tool, sum.ToString()){ Name = call.FunctionName };<br/>    options.Messages.Add(followUp);<br/>    var finalResponse = await client.GetChatCompletionsAsync(options);<br/>    return Results.Ok(new { reply = finalResponse.Value.Choices[0].Message.Content });<br/>}

With just a few lines you have a conversational endpoint that can perform calculations, query a database, or call any internal service without exposing those details to the caller.

Testing and Debugging Locally

Run the API with dotnet run and use curl or Postman to send a request:

curl -X POST http://localhost:5000/chat -H "Content-Type: application/json" -d '{"prompt":"What is 23 plus 57?"}'

The response should contain the computed sum, confirming that function calling worked end‑to‑end. If the model returns tool_calls but your C# code does not handle them, check the JSON schema for mismatched property names – a common source of silent failures.

Performance and Cost Tips

Azure OpenAI charges per 1,000 tokens. To keep costs under $5 per month for a low‑traffic API, limit max_tokens to 200 and enable presence_penalty to avoid repetitive prompts. Cache frequent results in an in‑memory MemoryCache to reduce round‑trips. For production, enable AzureMonitor diagnostics on the OpenAIClient to capture latency metrics; typical latency for GPT‑4o is 350 ms on a standard Azure region.

Conclusion

By combining .NET 8 Minimal APIs with Azure OpenAI’s function calling, developers can deliver intelligent services that stay lightweight, secure, and easy to maintain. The pattern scales from a single‑function calculator to complex business workflows, all while keeping the .NET codebase familiar and testable. Start with the skeleton above, extend the function catalog, and watch your API evolve into a truly AI‑augmented platform.

Author: Mahmut Sarıkaya — sarikayadev.com

Sources

  • Microsoft Docs – Azure AI OpenAI Service
  • Microsoft Learn – Build Minimal APIs in .NET 8
  • OpenAI Cookbook – Function Calling Guide
Tags: #dotnet 8 #minimal api #azure openai #function calling #c#
Share:
M

Written by

Mahmut Sarıkaya

Software Developer

Comments

No comments yet. Be the first to share your thoughts!

Leave a Comment

6 + 4 =