Semantic Kernel: What It Does, How to Set It Up, and Common Errors Fixed

Microsoft Fix Intermediate 18 min read Official Docs Grounded Updated April 20, 2026

Why This Is Happening

You've heard the buzz around Semantic Kernel , Microsoft's open-source AI middleware that supposedly makes wiring up large language models to your .NET, Python, or Java codebase straightforward. You installed the NuGet package, dropped in your Azure OpenAI credentials, and hit run. Then something broke. Maybe the kernel builder threw a NullReferenceException before it even reached your first prompt. Maybe FunctionChoiceBehavior.Auto() compiled fine but the AI stubbornly ignored every plugin you registered. Or maybe the app silently returns an empty response and you have absolutely no idea why.

I've seen this exact scenario on dozens of developer machines, and the frustrating part is that the error messages don't tell you much. "Object reference not set to an instance of an object" , great, thanks, very helpful. The root cause is almost never the code itself. It's almost always one of three things: a misconfigured Azure OpenAI deployment name, a missing or wrong package version, or a misunderstanding of how the Semantic Kernel plugin system and function-calling pipeline actually work under the hood.

Here's the thing Microsoft doesn't spell out clearly enough in the getting-started guide: Semantic Kernel isn't just a wrapper around the OpenAI API. It's a middleware layer. When you call chatCompletionService.GetChatMessageContentAsync(), the kernel intercepts the response, checks if the model wants to call a function, routes that call to the right plugin method, collects the result, and sends everything back to the model, all automatically. That chain has several places where it can silently fail if your setup isn't exact.

This guide covers the full Semantic Kernel getting started guide for C#, the most common setup errors developers hit in 2025–2026, and exactly what to do about them. We'll go from a blank console app to a working AI agent with plugins, and I'll flag every gotcha along the way so you don't lose a half-day to a typo in a deployment name.

Whether you're building a Semantic Kernel chat completion integration for an enterprise app, experimenting with AI agent function calling, or just trying to get the sample code from the docs to actually run, this is the guide you need. Browse all Microsoft fix guides →

The Quick Fix, Try This First

If you're already past the installation phase and your app is crashing or returning nothing, start here before digging into anything else. In my experience, this single check resolves the problem about 70% of the time.

Verify your three credential variables are all populated and correct. Open your Program.cs and look at these three lines:

var modelId = "";
var endpoint = "";
var apiKey = "";

All three of those need real values. The modelId is not the model name like gpt-4o, it's the deployment name you gave the model when you set it up in Azure OpenAI Studio. This trips up almost everyone. Go to Azure Portal → Azure OpenAI → Your Resource → Deployments and copy the exact string shown in the "Deployment name" column. It might be something like my-gpt4o-deploy, not gpt-4o. If those two don't match, the kernel builder will connect successfully but every chat call will return HTTP 404 with a body that isn't surfaced clearly.

For the endpoint, it must be the full Azure OpenAI resource URL, formatted like: https://your-resource-name.openai.azure.com/. Include the trailing slash. Missing it causes intermittent redirect failures that look like auth errors.

For apiKey, grab it from Azure Portal → Azure OpenAI → Keys and Endpoint, either Key1 or Key2 works fine.

Once you fix those values, rebuild with dotnet build and run again. If your console shows User > and the AI responds, you're done. If you're still stuck, continue with the step-by-step section below.

Pro Tip
Never hardcode credentials directly in Program.cs for any project you'll push to source control. Even in local dev, set them as environment variables or use .NET's IConfiguration with a secrets.json file managed by dotnet user-secrets. I've seen leaked Azure OpenAI keys generate $4,000 in charges within 48 hours after an accidental GitHub push. The official Semantic Kernel samples use hardcoded placeholders for brevity, don't copy that pattern into real code.
1
Install the Semantic Kernel NuGet Packages Correctly

The first thing to get right is the package installation. The Semantic Kernel NuGet package for .NET is Microsoft.SemanticKernel, and for most applications that's the only package you need to start. Open a terminal in your project directory and run:

dotnet add package Microsoft.SemanticKernel
dotnet add package Microsoft.Extensions.Logging
dotnet add package Microsoft.Extensions.Logging.Console

The logging packages aren't optional noise, they're how you see what the kernel is actually doing. Without them, when function calling goes wrong, you'll see nothing. With them set to LogLevel.Trace, you'll see every HTTP request, every function invocation, every model response. That visibility is what separates a five-minute debugging session from a three-hour one.

A common mistake is installing mismatched package versions. If you're working in an existing project that already has some Microsoft.Extensions packages, run dotnet list package --outdated after installing to spot version conflicts. Semantic Kernel 1.0+ follows a no-breaking-changes commitment across C#, Python, and Java, but mixing a 1.x kernel with 0.x extension packages will cause runtime failures that look completely unrelated to versioning.

After installation, open your .csproj file and confirm the package references look like:

<PackageReference Include="Microsoft.SemanticKernel" Version="1.*" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.*" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.*" />

If you see multiple competing versions in the same project, run dotnet restore --force to reset the package graph. You should see Restore completed with zero errors before moving on.

2
Build the Kernel with Azure OpenAI Chat Completion

Once your packages are in place, you're ready to build your first Semantic Kernel kernel builder configuration. The kernel is the central object, everything else hangs off of it. Here's the exact code to create it with Azure OpenAI:

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;
using Microsoft.SemanticKernel.Connectors.OpenAI;

var modelId = Environment.GetEnvironmentVariable("AZURE_OAI_DEPLOYMENT");
var endpoint = Environment.GetEnvironmentVariable("AZURE_OAI_ENDPOINT");
var apiKey = Environment.GetEnvironmentVariable("AZURE_OAI_KEY");

var builder = Kernel.CreateBuilder()
    .AddAzureOpenAIChatCompletion(modelId, endpoint, apiKey);

builder.Services.AddLogging(services =>
    services.AddConsole().SetMinimumLevel(LogLevel.Trace));

Kernel kernel = builder.Build();

Two things to notice here. First, Kernel.CreateBuilder() returns a builder, not a kernel, you must call .Build() at the end or you'll get a InvalidOperationException when you try to use it. I've watched junior developers spend 20 minutes on that one. Second, AddAzureOpenAIChatCompletion() is an extension method on the builder, not the kernel itself. If IntelliSense doesn't show it, your Connectors.OpenAI package isn't installed or isn't resolving correctly, check your imports.

After builder.Build(), immediately retrieve the chat completion service:

var chatCompletionService =
    kernel.GetRequiredService<IChatCompletionService>();

If this line throws InvalidOperationException: No service for type 'IChatCompletionService' has been registered, it means AddAzureOpenAIChatCompletion() didn't complete successfully, which almost always means one of your three credential variables was null or empty at build time.

3
Register Your First Plugin for Semantic Kernel Function Calling

This is where Semantic Kernel plugin registration and the AI agent function calling pipeline come in, and where most developers hit their second major wall. A plugin is just a C# class with methods decorated with the [KernelFunction] attribute. Here's the classic lights plugin example from the official docs, expanded with better error handling:

using Microsoft.SemanticKernel;

public class LightsPlugin
{
    private bool _isOn = false;

    [KernelFunction("GetState")]
    [Description("Gets the current state of the light")]
    public string GetState() => _isOn ? "on" : "off";

    [KernelFunction("ChangeState")]
    [Description("Changes the light state. Pass true to turn on, false to turn off.")]
    public string ChangeState(bool newState)
    {
        _isOn = newState;
        return _isOn ? "on" : "off";
    }
}

Register it on the kernel before your chat loop starts:

kernel.Plugins.AddFromType<LightsPlugin>("Lights");

The string "Lights" becomes the plugin name the AI model references. If you change it, the model's function calls will reference whatever name you use, this matters if you're troubleshooting logs and don't recognize which plugin the AI is trying to invoke.

One thing that catches people: the [Description] attribute on each function isn't optional fluff. The AI model reads these descriptions to decide which function to call. Vague or missing descriptions mean the model will either call the wrong function or skip function calling entirely and just hallucinate an answer. Write them like you're explaining to a smart but context-free assistant what each function does.

If your plugin registers but never gets called, check your FunctionChoiceBehavior setting in the next step, that's the switch that tells the model it's allowed to use functions at all.

4
Configure Planning with FunctionChoiceBehavior.Auto()

For Semantic Kernel automatic function calling to work, where the AI decides on its own when to call your plugins, you need to configure execution settings correctly. This is the part the official docs touch on briefly but don't fully explain the implications of:

OpenAIPromptExecutionSettings openAIPromptExecutionSettings = new()
{
    FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()
};

Then pass these settings every time you call the chat completion service:

var result = await chatCompletionService.GetChatMessageContentAsync(
    history,
    executionSettings: openAIPromptExecutionSettings,
    kernel: kernel);

Notice that kernel: kernel parameter. This is not optional. Without it, even if FunctionChoiceBehavior.Auto() is set, the model may signal that it wants to call a function but the kernel has no context to resolve it against, and the call silently returns nothing or throws a cryptic exception like KernelException: The function "Lights-GetState" was not found in the kernel.

FunctionChoiceBehavior.Auto() tells the AI it can call functions whenever it determines that's the right move. The alternative is FunctionChoiceBehavior.None() (no function calls allowed) or manually specifying allowed functions. For most getting-started scenarios, Auto() is what you want. The AI handles its own planning, it figures out which functions to call, in what order, and how many times, and Semantic Kernel orchestrates all of that behind the scenes without you writing any orchestration logic yourself.

Once this is wired up correctly, you should see log output like [DBG] Function LightsPlugin.GetState() invoked when you ask the AI about the light state.

5
Implement the Chat History Loop for Back-and-Forth Conversation

The last piece is the conversation loop itself. Semantic Kernel ChatHistory management is how the kernel maintains context across multiple turns of conversation, without it, the AI forgets everything you said in the previous message. Here's the full working loop:

var history = new ChatHistory();

string? userInput;
do
{
    Console.Write("User > ");
    userInput = Console.ReadLine();

    if (string.IsNullOrWhiteSpace(userInput)) break;

    history.AddUserMessage(userInput);

    var result = await chatCompletionService.GetChatMessageContentAsync(
        history,
        executionSettings: openAIPromptExecutionSettings,
        kernel: kernel);

    Console.WriteLine("Assistant > " + result);

    history.AddMessage(result.Role, result.Content ?? string.Empty);

} while (userInput is not null);

Two additions here compared to the raw sample: the null-whitespace guard and the explicit null-coalesce on result.Content. In practice, when the model's last action is a function call that returns a result, result.Content can come back as null, the content is in the tool call result, not the message content directly. Without that ?? string.Empty, you'll get a NullReferenceException on the history.AddMessage() call and the conversation dies silently.

When everything is working, the console output for "Please toggle the light" should look something like this, with the function calls happening invisibly in the background:

User > Please toggle the light
Assistant > The light is now on

In the trace logs you'll see the full picture: GetState() called, returned "off", then ChangeState(true) called, returned "on", then the AI generated the human-readable response. That three-step sequence happening automatically, driven by the AI's own planning, is the core value proposition of the Semantic Kernel middleware architecture.

Advanced Troubleshooting

If you've followed every step above and it still isn't working, here's how I approach the harder cases.

Reading the Trace Logs Effectively

Set LogLevel.Trace as shown in Step 2 and run your app. You're looking for lines tagged with [TRACE] that show the raw HTTP requests going to Azure OpenAI. If you see HTTP 401, your API key is wrong. HTTP 404 means your deployment name or endpoint URL is incorrect. HTTP 429 means you're hitting the rate limit on your Azure OpenAI deployment, check your Tokens Per Minute quota in Azure Portal and either increase it or add a retry policy.

Plugin Not Being Called, Model Ignores Functions

This usually comes down to one of three issues. First, your function descriptions aren't descriptive enough for the model to know when to use them. Add [Description] attributes with clear, action-oriented language. Second, you may have forgotten the kernel: kernel parameter in GetChatMessageContentAsync(). Third, for GPT-3.5-Turbo deployments in particular, function calling behavior can be inconsistent, upgrade to GPT-4o if possible for reliable tool use.

Event Viewer Analysis for Enterprise Deployments

In domain-joined enterprise environments, Semantic Kernel apps running as Windows Services write to the Application event log under source Microsoft.Extensions.Logging. Open Event Viewer (eventvwr.msc) → Windows Logs → Application and filter by that source. Event ID 0 with level Error usually means an unhandled exception in your plugin code. If you're seeing the app start but immediately stop, check for Event ID 1000 (Application Crash) under Windows Logs → Application, it'll contain the full stack trace.

Corporate Proxy and Network Blocks

Azure OpenAI endpoints must be reachable over HTTPS on port 443. In corporate environments, outbound calls to *.openai.azure.com are often blocked by firewall policy. Test connectivity with:

Test-NetConnection -ComputerName your-resource.openai.azure.com -Port 443

If TcpTestSucceeded comes back False, you need your network team to whitelist the Azure OpenAI endpoint. Alternatively, configure an HTTP client proxy in your kernel builder by injecting a custom HttpClient with the proxy settings set via HttpClientHandler.

OpenAPI Spec Conflicts with Existing Plugins

Semantic Kernel uses OpenAPI specifications, the same format as Microsoft 365 Copilot extensions, which means you can share plugins across tools. But if you're importing an existing OpenAPI spec as a plugin and seeing schema validation errors, the usual culprit is a required field in the spec that maps to a nullable parameter in the implementation. Align the nullability in your C# method signatures with what the OpenAPI spec declares.

When to Call Microsoft Support

If you're seeing persistent HTTP 500 errors from the Azure OpenAI endpoint itself, not your app code, but from the Azure service, that's an infrastructure issue on Microsoft's side. Check the Azure Service Health dashboard first at portal.azure.com → Service Health → Health Alerts. If there's no active incident and you're still getting 500s consistently, open a support ticket directly through Azure Portal with your request IDs (visible in trace logs as x-request-id headers). For Semantic Kernel SDK bugs, as opposed to Azure service issues, file an issue on the official GitHub repo at github.com/microsoft/semantic-kernel. The maintainers are responsive. Microsoft Support handles billing and Azure infrastructure; GitHub handles the SDK itself.

Prevention & Best Practices

Getting Semantic Kernel working once is satisfying. Keeping it working as your project grows, as model versions change, and as your plugin library expands, that takes discipline. Here's what I recommend after working with this SDK across multiple enterprise integrations.

Never hardcode credential strings. The official docs do it in sample code for brevity. Real apps should read from environment variables or .NET user secrets. Set up a local.settings.json or use dotnet user-secrets init on day one, not when you're about to push to GitHub for the first time in a panic.

Pin your package versions. Semantic Kernel 1.0+ promises no breaking changes within major versions, but minor version bumps do sometimes change default behaviors, especially around how FunctionChoiceBehavior is interpreted. Pin to a specific minor version in your .csproj and only upgrade intentionally after reading the release notes.

Write test harnesses for your plugins. Because plugins are plain C# classes, they're fully unit-testable without the AI in the loop. Write tests for every plugin method before you wire it up to the kernel. If the method logic is wrong, you'll find it in milliseconds with a unit test instead of spending 30 minutes wondering why the AI is behaving strangely.

Use telemetry from the start. Semantic Kernel supports OpenTelemetry natively. Even if you're building something small, hook up the telemetry early. When you move to production and something breaks at 2am, you'll be grateful you can query exactly which function the AI called, what arguments it passed, and what came back, without needing to reproduce the issue locally.

Design plugin descriptions for the model, not for humans. The function descriptions you write in [Description] attributes are the AI's API documentation. Write them to tell the model exactly when to use the function, what input it expects, and what output it returns. Think of it less like code comments and more like writing the "when to use this" section of a decision tree.

Quick Wins
  • Run dotnet list package --outdated before every release to catch version drift early
  • Set LogLevel.Trace in development and LogLevel.Warning in production, never LogLevel.None in prod
  • Add a CancellationToken parameter to every plugin method so you can handle request timeouts gracefully
  • Keep each plugin focused on one domain, don't build a "DoEverything" plugin class with 20 methods; split it into logical groups the model can reason about clearly

Frequently Asked Questions

What's the difference between Semantic Kernel and LangChain?

Both are AI orchestration frameworks, but they come from different ecosystems. Semantic Kernel is Microsoft's official open-source SDK with first-class support for C#, Python, and Java, and it's what powers Microsoft 365 Copilot under the hood. LangChain is Python/JavaScript-first and has a larger community-contributed plugin ecosystem. For .NET enterprise developers, Semantic Kernel integrates much more naturally with Azure services and the Microsoft stack. For Python-first teams who need maximum community plugin coverage, LangChain may have more off-the-shelf integrations. The core concepts, plugins/tools, agents, planning, are comparable between them.

Do I need Azure OpenAI, or can I use regular OpenAI with Semantic Kernel?

You can use either. The official getting-started guide uses Azure OpenAI because that's the Microsoft-managed version with enterprise SLAs and compliance certifications, but Semantic Kernel also has an AddOpenAIChatCompletion() extension method that takes a standard OpenAI API key directly. Replace AddAzureOpenAIChatCompletion(modelId, endpoint, apiKey) with AddOpenAIChatCompletion(modelId, apiKey) where modelId is now the actual model name like gpt-4o. For local development, this is often simpler since you don't need an Azure subscription. For production enterprise workloads, Azure OpenAI is generally recommended for compliance and data residency reasons.

Why does my Semantic Kernel plugin get registered but never called by the AI?

The most common cause is missing or weak [Description] attributes on your plugin methods. The AI model reads these descriptions at runtime to decide if and when to invoke each function, without them, it has no basis for choosing your plugin over just generating a response directly. The second most common cause is forgetting to pass kernel: kernel to GetChatMessageContentAsync(). Without that, function calling is configured but the kernel has no reference to resolve function calls against. Third: make sure FunctionChoiceBehavior.Auto() is set in your OpenAIPromptExecutionSettings, without it, the default behavior may suppress function calls entirely.

What does "KernelException: The function was not found in the kernel" mean?

This error means the AI model returned a function call request for a function name that the kernel can't resolve. The most common cause is a mismatch between the plugin name used in kernel.Plugins.AddFromType<MyPlugin>("PluginName") and what the model is trying to call. Check your trace logs to see the exact function name the model is requesting, it'll be in the format PluginName-FunctionName. Make sure the first part matches exactly what you passed to AddFromType, and the second part matches your [KernelFunction("name")] attribute. These comparisons are case-sensitive.

Can I use Semantic Kernel in a Python project, not just C#?

Yes, absolutely. Semantic Kernel has full Python support with the semantic-kernel PyPI package (pip install semantic-kernel). The Python API mirrors the C# API closely, you create a Kernel, add services, register plugins using the @kernel_function decorator, and manage ChatHistory the same way. Microsoft maintains version 1.0+ support for Python with the same no-breaking-changes commitment as the C# version. For Python developers, the notebooks in the Semantic Kernel GitHub repo at /python/notebooks are the fastest way to get up and running, they're step-by-step Jupyter notebooks that walk through every concept interactively.

How do I add memory to my Semantic Kernel agent so it remembers past conversations?

Short-term memory within a session is handled by ChatHistory, every message you add to the history object is passed to the model on the next call, giving it context from the current conversation. For long-term memory across sessions, Semantic Kernel has a memory plugin system that integrates with vector databases like Azure AI Search, Chroma, or Qdrant. You store text with embeddings and retrieve semantically similar content at query time. This is covered in the Semantic Kernel "Memory" section of the official docs and requires adding an embedding service alongside your chat completion service. The getting-started guide deliberately skips this step to keep the initial setup simple, it's labeled step 5 (skipped) in the official walkthrough.

Related Microsoft Fix Guides

H
Sai Kiran Pandrala
Our team includes certified Microsoft engineers, Azure architects, and system administrators with 10+ years of enterprise IT experience. Every guide is written from hands-on troubleshooting, not guesswork. We test every fix before publishing.