This semantic kernel n4n.ai setup tutorial walks through connecting Microsoft’s Semantic Kernel to an OpenAI-compatible inference gateway. We’ll build a minimal Python project that points the kernel at the gateway endpoint, runs chat completions, defines a small plugin, and streams tokens—without writing any custom retry or routing logic.
Prerequisites
- Python 3.10 or newer
pipand a virtual environment tool- An API key for the gateway (it exposes a single OpenAI-compatible endpoint)
- Familiarity with async/await in Python
Install the SDK inside a clean environment:
python -m venv .venv
source .venv/bin/activate
pip install semantic-kernel python-dotenv
Load credentials from a .env file or export them directly. The gateway expects a bearer token; the base URL is fixed.
export N4N_API_KEY="sk-your-key-here"
export N4N_BASE_URL="https://api.n4n.ai/v1"
If you use python-dotenv, call load_dotenv() at the top of your script.
Step 1: Bootstrap the Kernel
Semantic Kernel decouples your code from a specific provider through service objects. For an OpenAI-compatible backend, use OpenAIChatCompletion and override base_url. The model ID is just a string the gateway maps to a downstream provider.
import os
from semantic_kernel import Kernel
from semantic_kernel.connectors.ai.open_ai import OpenAIChatCompletion
def build_kernel() -> Kernel:
kernel = Kernel()
chat_service = OpenAIChatCompletion(
service_id="gw-chat",
ai_model_id="openai/gpt-4o-mini",
api_key=os.getenv("N4N_API_KEY"),
base_url=os.getenv("N4N_BASE_URL", "https://api.n4n.ai/v1"),
)
kernel.add_chat_service(service_id="gw-chat", service=chat_service)
return kernel
The ai_model_id can be any of the 240+ models the gateway addresses. You are not locked to OpenAI; prefix with the provider slug (e.g., anthropic/claude-3-haiku). The service_id is how you retrieve this service later—keep it stable.
Step 2: Run a single chat completion
Create a chat history and call the service directly. This validates your key and endpoint before layering on abstractions.
import asyncio
from semantic_kernel.contents import ChatHistory
async def main():
kernel = build_kernel()
chat_service = kernel.get_service("gw-chat")
history = ChatHistory()
history.add_user_message("What is the capital of Finland? Reply with one word.")
try:
response = await chat_service.get_chat_message_content(chat_history=history)
print(response.content)
except Exception as e:
print("Request failed:", e)
if __name__ == "__main__":
asyncio.run(main())
Expected output:
Helsinki
A 401 means the env var is missing or wrong. A 404 suggests the base URL is incorrect—remember the gateway exposes a single /v1 endpoint. A 429 indicates rate limiting, which the gateway mitigates via automatic fallback to healthy providers.
Step 3: Semantic functions
The value of Semantic Kernel is composing prompts with code. Define a prompt template as a function and invoke it through the kernel.
from semantic_kernel.functions import KernelFunctionFromPrompt
summarize = KernelFunctionFromPrompt(
function_name="summarize",
prompt="Summarize the following text in 10 words or less:\n{{$input}}",
)
async def run_summary():
kernel = build_kernel()
text = (
"Semantic Kernel is a lightweight SDK that lets you combine AI "
"services with conventional code, planners, and plugins."
)
result = await kernel.invoke(summarize, input=text)
print(result)
asyncio.run(run_summary())
Expected output (exact wording may vary):
Lightweight SDK combining AI services, code, planners, and plugins.
The {{$input}} placeholder is filled from the input argument. You can add more variables and pass them as keyword arguments.
Step 4: Native plugin
Mix deterministic logic with model calls. Decorate a Python method with @kernel_function and register the class.
from semantic_kernel.functions import kernel_function
class MathPlugin:
@kernel_function(name="add", description="Add two integers")
def add(self, a: int, b: int) -> int:
return a + b
@kernel_function(name="multiply", description="Multiply two integers")
def multiply(self, a: int, b: int) -> int:
return a * b
async def call_math():
kernel = build_kernel()
kernel.add_plugin(MathPlugin(), plugin_name="math")
added = await kernel.invoke(kernel.plugins["math"]["add"], a=3, b=4)
multiplied = await kernel.invoke(kernel.plugins["math"]["multiply"], a=3, b=4)
print("add:", added, "multiply:", multiplied)
asyncio.run(call_math())
Output:
add: 7 multiply: 12
Plugins let you expose typed functions to planners or call them directly as shown.
Step 5: Streaming responses
For chat UIs, stream tokens. The service exposes an async generator that yields content chunks.
async def stream_chat():
kernel = build_kernel()
chat_service = kernel.get_service("gw-chat")
history = ChatHistory()
history.add_user_message("Count to 5 slowly.")
full = ""
async for chunk in chat_service.get_streaming_chat_message_content(chat_history=history):
if chunk.content:
print(chunk.content, end="", flush=True)
full += chunk.content
print("\n---")
print("Assembled:", full)
asyncio.run(stream_chat())
You will see tokens printed incrementally rather than one blob. The assembled string matches what a non-streaming call would return.
Step 6: Routing and resilience
This semantic kernel n4n.ai setup tutorial deliberately avoids writing fallback logic. The gateway honors client routing directives via the model string and forwards provider cache-control hints, and it performs automatic fallback when a provider is rate-limited or degraded. Your code just requests anthropic/claude-3-haiku and gets a response or a structured error.
If you need explicit control, register multiple services with different ai_model_id values and select per call:
kernel.add_chat_service(
service_id="haiku",
service=OpenAIChatCompletion(
service_id="haiku",
ai_model_id="anthropic/claude-3-haiku",
api_key=os.getenv("N4N_API_KEY"),
base_url=os.getenv("N4N_BASE_URL"),
),
)
Then kernel.get_service("haiku"). The gateway also respects cache_control markers in the payload, so prompt caching works if the upstream provider supports it.
Step 7: Per-token metering
The gateway returns usage metadata on each response. Semantic Kernel exposes it via the metadata field on the completion object.
response = await chat_service.get_chat_message_content(chat_history=history)
print(response.metadata)
You can pipe this into your own cost tracker. The gateway handles per-token usage metering upstream, so the numbers match your bill.
Troubleshooting
- SSL errors: ensure
requestsandaiohttpare up to date. - Model not found: the gateway maps slugs; check the model ID against the catalog.
- Timeouts: the default SK timeout is 60s. Pass
timeout=120toOpenAIChatCompletionif you expect long generations. - Async context errors: every call must run inside an event loop; use
asyncio.runor a framework that provides one.
Where to go next
You have a working kernel that talks to an OpenAI-compatible gateway, runs prompts, calls native code, and streams. From here, add a planner, or wire the kernel into a FastAPI app. The baseline is intentionally small—expand it with your own plugins and more complex prompt templates.