n4nAI

Switching Semantic Kernel from Azure OpenAI to n4n.ai

A practical migration tutorial for engineers: repoint Semantic Kernel's OpenAI connector to n4n.ai, verify model behavior, and drop Azure-specific dependencies.

n4n Team4 min read789 words

Audio narration

Coming soon — every post will get a voice note here.

If you’re running Semantic Kernel against Azure OpenAI and need to switch semantic kernel azure openai n4n.ai, the work is mostly a configuration swap. Semantic Kernel’s OpenAI connector speaks the standard OpenAI HTTP contract, so pointing it at an OpenAI-compatible gateway requires no changes to your plugins, prompt templates, or function-calling logic. This guide gives you ordered steps to cut over cleanly and verify the result.

Step 1: Audit your existing Azure OpenAI integration

Before changing anything, capture how your kernel is built. A typical Python setup looks like this:

import os
from semantic_kernel import Kernel
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion

kernel = Kernel()
kernel.add_service(
    AzureChatCompletion(
        deployment_name="gpt-4o",
        endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
        api_key=os.environ["AZURE_OPENAI_API_KEY"],
    )
)

Note three things: the deployment_name (Azure’s alias for a model), the endpoint host, and the auth key. Azure couples a deployment to a specific model version and region. You’ll replace all three. If you also use embeddings, find AzureTextEmbedding and record its deployment name.

Review any plugins that hard-code the deployment string. Semantic Kernel lets you pass service_id when registering; if your code references kernel.get_service("azure-gpt4o"), you’ll need to update those identifiers after the swap.

Step 2: Upgrade Semantic Kernel and OpenAI client

Make sure you’re on a recent release. The OpenAI connector stabilized in 1.x and properly supports custom base URLs via an injected client.

pip install --upgrade semantic-kernel openai

Check the version:

python -c "import semantic_kernel; print(semantic_kernel.__version__)"

Anything >= 1.10 handles async OpenAI clients and base-URL overrides without monkey-patching. If you’re still on 0.x, the class names differ and you should upgrade first—the migration below assumes 1.x APIs.

Step 3: Repoint the chat service to the OpenAI-compatible endpoint

Create an AsyncOpenAI client with the new base URL and hand it to OpenAIChatCompletion. This is the core of the switch semantic kernel azure openai n4n.ai move:

import os
from openai import AsyncOpenAI
from semantic_kernel import Kernel
from semantic_kernel.connectors.ai.open_ai import OpenAIChatCompletion

client = AsyncOpenAI(
    api_key=os.environ["N4N_API_KEY"],
    base_url="https://api.n4n.ai/v1",
)

kernel = Kernel()
kernel.add_service(
    OpenAIChatCompletion(
        ai_model_id="gpt-4o",
        async_client=client,
    )
)

The endpoint exposes a single OpenAI-compatible surface that addresses 240+ models, so ai_model_id is the raw model name rather than an Azure deployment alias. You can swap "gpt-4o" for "claude-3-5-sonnet" or any other supported ID without creating new resources. The auth header format is identical to OpenAI’s (Authorization: Bearer), so your key handling stays the same.

Step 4: Map model IDs and environment variables

Azure deployments obscure the underlying model. Build a small translation layer if you have multiple services or tests that reference old aliases:

MODEL_MAP = {
    "azure-gpt4o": "gpt-4o",
    "azure-gpt35": "gpt-3.5-turbo",
}

def build_kernel(model_alias: str) -> Kernel:
    client = AsyncOpenAI(
        api_key=os.environ["N4N_API_KEY"],
        base_url="https://api.n4n.ai/v1",
    )
    kernel = Kernel()
    kernel.add_service(
        OpenAIChatCompletion(
            ai_model_id=MODEL_MAP[model_alias],
            async_client=client,
        )
    )
    return kernel

Delete AZURE_OPENAI_ENDPOINT and AZURE_OPENAI_API_KEY from your environment files. If you use a .env file, replace those lines with N4N_API_KEY=.... For container deployments, update the secret references in your Helm chart or Terraform so no stale Azure creds linger.

Step 5: Preserve streaming and function calling

Semantic Kernel’s higher-level APIs (invoke, invoke_stream, function plugins) don’t care which backend serves the tokens. Existing code keeps working:

from semantic_kernel.connectors.ai.open_ai import OpenAIChatPromptExecutionSettings

settings = OpenAIChatPromptExecutionSettings(
    temperature=0.2,
    tool_choice="auto",
)

async def run():
    result = await kernel.invoke(
        prompt="Summarize the Q3 infra incident in 3 bullets.",
        settings=settings,
    )
    print(result)

Streaming requires no extra flags:

async for chunk in kernel.invoke_stream(prompt="Draft a rollback plan"):
    print(chunk, end="")

If you previously relied on Azure’s response_format for JSON mode, the OpenAI-compatible gateway passes it through. Test both streaming and non-streaming paths before declaring success. Function calling with @kernel_function decorators behaves identically because the wire format is the OpenAI schema.

Step 6: Verify the migration

Write a throwaway script that exercises the exact model ID and a known prompt:

import asyncio
import os
from semantic_kernel import Kernel
from openai import AsyncOpenAI
from semantic_kernel.connectors.ai.open_ai import OpenAIChatCompletion

async def main():
    client = AsyncOpenAI(
        api_key=os.environ["N4N_API_KEY"],
        base_url="https://api.n4n.ai/v1",
    )
    kernel = Kernel()
    kernel.add_service(
        OpenAIChatCompletion(ai_model_id="gpt-4o", async_client=client)
    )
    resp = await kernel.invoke(prompt="Reply with the single word: OK")
    assert "OK" in str(resp), f"Unexpected response: {resp}"
    print("Verification passed")

asyncio.run(main())

Run it with a real key:

N4N_API_KEY=sk-... python verify_switch.py

A clean pass means tokens flowed end to end. Check your metering dashboard to confirm per-token usage is recorded against the expected model. If you see 401, your key is wrong; 404 means the model ID isn’t supported at that endpoint; 429 means upstream rate limits—handle with retry backoff.

Step 7: Remove Azure-only dependencies

Uninstall the Azure SDK if nothing else needs it:

pip uninstall azure-identity azure-ai-openai

Grep your codebase for AzureChatCompletion and AzureOpenAITextEmbedding. Replace embeddings similarly:

from semantic_kernel.connectors.ai.open_ai import OpenAITextEmbedding

kernel.add_service(
    OpenAITextEmbedding(
        ai_model_id="text-embedding-3-small",
        async_client=client,
    )
)

If you use Semantic Kernel’s planning libraries (e.g., FunctionCallingStepwisePlanner), they only depend on the service interface, so no changes are required there.

Step 8: .NET equivalent

For C# teams, the same swap applies. Replace AddAzureOpenAIChatCompletion with AddOpenAIChatCompletion and set BaseAddress:

using Microsoft.SemanticKernel;

var builder = Kernel.CreateBuilder();
builder.AddOpenAIChatCompletion(
    modelId: "gpt-4o",
    apiKey: Environment.GetEnvironmentVariable("N4N_API_KEY"),
    httpClient: new HttpClient { BaseAddress = new Uri("https://api.n4n.ai/v1") }
);
var kernel = builder.Build();

The Microsoft.SemanticKernel.Connectors.OpenAI package already supports custom base addresses; no Azure package is needed post-migration.

Pitfalls and opinions

  • Don’t keep both clients in production. Dual-write branches rot. Cut over atomically behind a config flag if you must canary, but delete the Azure path within a sprint.
  • Model behavior differs across providers. Even with the same model ID, system prompt handling and tokenizers vary. Run your eval suite, not just a smoke test.
  • Cache keys. If you used Azure’s x-ms-useragent or regional pinning, those hints are meaningless at the new endpoint. The gateway forwards provider cache-control hints, so set cache_control on messages as you would with OpenAI.
  • Rate limits. Azure limits are per-deployment; the gateway aggregates upstream quotas. Expect different 429 shapes. Configure AsyncOpenAI with max_retries and exponential backoff.
  • Logging. Azure SDK logs differ from OpenAI’s. Update your log filters so 4xx errors from the new endpoint aren’t swallowed by old Azure-specific handlers.

Final check

After the cutover is complete, your kernel construction should contain zero Azure* imports. Your prompts, plugins, and planners stay untouched. That’s the payoff of building against the OpenAI abstraction in Semantic Kernel rather than the cloud-specific one. Run your full integration test suite once more, then decommission the Azure resource to stop billing.

Tagssemantic-kernelazure-openain4n-aimigration

Written by

n4n Team

The team building n4n — a single OpenAI-compatible API in front of 240+ models, with automatic fallback, load balancing and pay-per-token metering.

More from n4n Team →

All semantic kernel getting started with n4n.ai posts →