🤖AI Agents Guide
TutorialsComparisonsReviewsExamplesIntegrationsUse CasesTemplatesGlossary
Get Started
🤖AI Agents Guide

Your comprehensive resource for understanding, building, and implementing AI Agents.

Learn

  • Tutorials
  • Glossary
  • Use Cases
  • Examples

Compare

  • Tool Comparisons
  • Reviews
  • Integrations
  • Templates

Company

  • About
  • Contact
  • Privacy Policy

© 2026 AI Agents Guide. All rights reserved.

Home/Tutorials/Build an AI Agent with Semantic Kernel
advanced38 min read

Build an AI Agent with Semantic Kernel

Step-by-step guide to building a production AI agent using Microsoft Semantic Kernel for Python, with native plugins, the Planner for automatic function orchestration, and Azure OpenAI integration for enterprise deployments.

Scrabble tiles spelling the word genni on a wooden table
Photo by Markus Winkler on Unsplash
By AI Agents Guide Team•February 28, 2026

Table of Contents

  1. What You'll Learn
  2. Prerequisites
  3. Step 1: Project Setup
  4. Step 2: Configure the Kernel
  5. Step 3: Create a Native Plugin
  6. Step 4: Create a Semantic Plugin
  7. Step 5: Build the Agent with Chat History
  8. Step 6: Using the Stepwise Planner
  9. What's Next
  10. Frequently Asked Questions
a computer chip with the letter a on it
Photo by Mohamed Nohassi on Unsplash

Build an AI Agent with Microsoft Semantic Kernel

Microsoft Semantic Kernel is an enterprise-grade open-source SDK for integrating AI models into production applications. It is the framework powering Copilot across Microsoft 365, Bing, and Azure — meaning it is battle-tested at scale in ways most frameworks are not.

Semantic Kernel's core philosophy is that AI should be a plugin in your existing software stack, not the reverse. It provides a kernel orchestration layer, a plugin system for wrapping existing code as AI-callable functions, and a Planner that lets the model dynamically chain plugins to accomplish goals.

In this tutorial you will build an enterprise HR assistant that combines a semantic (prompt-based) plugin for policy lookup, a native (Python function) plugin for database queries, and the Function Calling Stepwise Planner to orchestrate them automatically.

What You'll Learn#

  • How to install Semantic Kernel and configure it with OpenAI or Azure OpenAI
  • How to create native plugins from Python classes and functions
  • How to create semantic plugins from prompt templates
  • How to use the Stepwise Planner for automatic goal decomposition
  • How to configure kernel memory and chat history for multi-turn conversations
  • How to deploy against Azure OpenAI for enterprise compliance

Prerequisites#

  • Python 3.10 or higher installed
  • An OpenAI API key, OR an Azure OpenAI deployment (endpoint + API key + deployment name)
  • Basic understanding of AI agents and agent frameworks
  • Comfort with Python classes and decorators

Step 1: Project Setup#

mkdir semantic-kernel-demo && cd semantic-kernel-demo
python -m venv .venv && source .venv/bin/activate

# Core Semantic Kernel package
pip install semantic-kernel python-dotenv

# Optional: Azure OpenAI support is included in the base package

Create .env:

# For standard OpenAI
OPENAI_API_KEY=sk-...

# For Azure OpenAI (comment out the above and uncomment below)
# AZURE_OPENAI_API_KEY=...
# AZURE_OPENAI_ENDPOINT=https://your-resource.openai.azure.com/
# AZURE_OPENAI_DEPLOYMENT=gpt-4o

Step 2: Configure the Kernel#

The Kernel is the central orchestrator in Semantic Kernel. Everything — plugins, memory, AI services — is registered on it.

# kernel_setup.py
import os
from dotenv import load_dotenv
import semantic_kernel as sk
from semantic_kernel.connectors.ai.open_ai import OpenAIChatCompletion, AzureChatCompletion
from semantic_kernel.connectors.ai.function_choice_behavior import FunctionChoiceBehavior
from semantic_kernel.connectors.ai.open_ai.prompt_execution_settings.open_ai_prompt_execution_settings import (
    OpenAIChatPromptExecutionSettings,
)

load_dotenv()


def create_kernel() -> sk.Kernel:
    """Create and configure the Semantic Kernel instance."""
    kernel = sk.Kernel()

    # Choose your AI backend
    if os.getenv("AZURE_OPENAI_API_KEY"):
        service = AzureChatCompletion(
            service_id="chat",
            deployment_name=os.getenv("AZURE_OPENAI_DEPLOYMENT", "gpt-4o"),
            endpoint=os.getenv("AZURE_OPENAI_ENDPOINT"),
            api_key=os.getenv("AZURE_OPENAI_API_KEY"),
        )
    else:
        service = OpenAIChatCompletion(
            service_id="chat",
            ai_model_id="gpt-4o",
            api_key=os.getenv("OPENAI_API_KEY"),
        )

    kernel.add_service(service)
    return kernel

Step 3: Create a Native Plugin#

Native plugins wrap regular Python code as kernel functions that the AI can call. Use the @kernel_function decorator to mark methods as callable tools.

# plugins/hr_plugin.py
import json
from datetime import datetime, date
from semantic_kernel.functions import kernel_function


class HRPlugin:
    """Plugin for querying HR data and employee information."""

    def __init__(self):
        # In production, this would be a database connection
        self._employees = {
            "E001": {
                "name": "Alice Chen",
                "department": "Engineering",
                "title": "Senior AI Engineer",
                "hire_date": "2022-03-15",
                "pto_balance_days": 18,
                "manager_id": "E042",
            },
            "E002": {
                "name": "Bob Martinez",
                "department": "Product",
                "title": "Product Manager",
                "hire_date": "2021-07-01",
                "pto_balance_days": 12,
                "manager_id": "E039",
            },
        }

    @kernel_function(
        name="get_employee_info",
        description="Retrieve an employee's profile, title, department, and PTO balance by employee ID.",
    )
    def get_employee_info(self, employee_id: str) -> str:
        """Look up employee information.

        Args:
            employee_id: The unique employee identifier (e.g., 'E001').
        """
        employee = self._employees.get(employee_id.upper())
        if not employee:
            return json.dumps({"error": f"Employee {employee_id} not found."})
        return json.dumps(employee)

    @kernel_function(
        name="check_pto_availability",
        description="Check if an employee has enough PTO days available for a requested time-off period.",
    )
    def check_pto_availability(self, employee_id: str, days_requested: int) -> str:
        """Check PTO availability for an employee.

        Args:
            employee_id: The employee's ID.
            days_requested: Number of PTO days being requested.
        """
        employee = self._employees.get(employee_id.upper())
        if not employee:
            return json.dumps({"error": f"Employee {employee_id} not found."})

        available = employee["pto_balance_days"]
        approved = days_requested <= available

        return json.dumps({
            "employee_id": employee_id,
            "days_requested": days_requested,
            "days_available": available,
            "approved": approved,
            "message": f"Request {'approved' if approved else 'denied'}. "
                       f"{'Remaining' if approved else 'Shortfall'}: "
                       f"{abs(available - days_requested)} days.",
        })

    @kernel_function(
        name="get_policy",
        description="Retrieve company HR policy text for a given policy category.",
    )
    def get_policy(self, policy_name: str) -> str:
        """Retrieve HR policy text.

        Args:
            policy_name: Policy category (e.g., 'remote_work', 'pto', 'onboarding').
        """
        policies = {
            "pto": "Employees accrue 1.5 PTO days per month. Unused PTO up to 10 days rolls over annually.",
            "remote_work": "Full-time remote is allowed for all roles. Employees must be available 9 AM–3 PM in their local timezone.",
            "onboarding": "New hires complete a 30-day onboarding program including IT setup, product training, and manager 1:1s.",
        }
        return policies.get(policy_name.lower(), f"Policy '{policy_name}' not found. Try: pto, remote_work, onboarding.")

Circuit board representing the enterprise plugin architecture of Semantic Kernel

Step 4: Create a Semantic Plugin#

Semantic plugins use prompt templates rather than Python code. They are powerful for tasks like summarization, classification, or tone transformation.

# plugins/writing_plugin.py
from semantic_kernel.functions import KernelFunction
from semantic_kernel.prompt_template import PromptTemplateConfig


POLICY_SUMMARY_TEMPLATE = """
You are an HR communication specialist. Summarize the following policy excerpt in plain,
friendly language suitable for an employee who is unfamiliar with corporate jargon.

Policy Text:
{{$policy_text}}

Target Employee Level: {{$employee_level}}

Write a 2-3 sentence summary that is accurate, encouraging, and uses simple language.
"""


def create_writing_plugin(kernel):
    """Register semantic (prompt-based) functions on the kernel."""
    kernel.add_function(
        plugin_name="WritingPlugin",
        function_name="summarize_policy",
        prompt=POLICY_SUMMARY_TEMPLATE,
        description="Summarize an HR policy in plain language for an employee.",
        template_format="semantic-kernel",
    )

Step 5: Build the Agent with Chat History#

Semantic Kernel provides ChatHistory for managing multi-turn conversations. Combined with function calling, this creates a fully stateful agent loop.

# agent.py
import asyncio
from semantic_kernel.connectors.ai.function_choice_behavior import FunctionChoiceBehavior
from semantic_kernel.connectors.ai.open_ai.prompt_execution_settings.open_ai_prompt_execution_settings import (
    OpenAIChatPromptExecutionSettings,
)
from semantic_kernel.contents import ChatHistory
from kernel_setup import create_kernel
from plugins.hr_plugin import HRPlugin


async def run_hr_assistant():
    kernel = create_kernel()

    # Register the native HR plugin
    kernel.add_plugin(HRPlugin(), plugin_name="HRPlugin")

    # Configure execution settings — enable automatic function calling
    settings = OpenAIChatPromptExecutionSettings(
        service_id="chat",
        max_tokens=2048,
        temperature=0.1,  # Low temperature for factual HR queries
        function_choice_behavior=FunctionChoiceBehavior.Auto(
            filters={"included_plugins": ["HRPlugin"]}
        ),
    )

    # Initialize chat history with system instructions
    chat_history = ChatHistory()
    chat_history.add_system_message(
        """You are a helpful HR assistant. Help employees find information about their
        PTO balances, company policies, and HR processes. Always be accurate and cite
        the data source when providing employee-specific information."""
    )

    chat_service = kernel.get_service(service_id="chat")

    # Multi-turn conversation loop
    print("HR Assistant ready. Type 'quit' to exit.\n")
    while True:
        user_input = input("You: ").strip()
        if user_input.lower() in ("quit", "exit", "q"):
            break
        if not user_input:
            continue

        chat_history.add_user_message(user_input)

        # Get response with automatic function calling
        response = await chat_service.get_chat_message_content(
            chat_history=chat_history,
            settings=settings,
            kernel=kernel,
        )

        assistant_message = str(response)
        chat_history.add_assistant_message(assistant_message)
        print(f"\nAssistant: {assistant_message}\n")


if __name__ == "__main__":
    asyncio.run(run_hr_assistant())

Step 6: Using the Stepwise Planner#

The Stepwise Planner enables the model to autonomously decompose a high-level goal into a sequence of function calls without you specifying the order. It is powerful for complex, multi-step queries.

# planner_demo.py
import asyncio
from semantic_kernel.planners.function_calling_stepwise_planner import (
    FunctionCallingStepwisePlanner,
    FunctionCallingStepwisePlannerOptions,
)
from kernel_setup import create_kernel
from plugins.hr_plugin import HRPlugin


async def run_planner():
    kernel = create_kernel()
    kernel.add_plugin(HRPlugin(), plugin_name="HRPlugin")

    # Configure planner options
    options = FunctionCallingStepwisePlannerOptions(
        max_iterations=10,
        max_tokens=4096,
    )
    planner = FunctionCallingStepwisePlanner(service_id="chat", options=options)

    # Complex goal that requires multiple tool calls
    goal = (
        "Employee E001 wants to take 5 days of PTO. "
        "Check if they have enough PTO balance, and if approved, "
        "also retrieve the company PTO policy so I can share it with them."
    )

    print(f"Goal: {goal}\n")
    result = await planner.invoke(kernel=kernel, question=goal)

    print("=== Planner Result ===")
    print(result.final_answer)

    print("\n=== Steps Executed ===")
    for i, step in enumerate(result.chat_history.messages, 1):
        if step.role.value == "tool":
            print(f"  Step {i}: Tool call result — {str(step)[:100]}...")


if __name__ == "__main__":
    asyncio.run(run_planner())

What's Next#

You have built an enterprise-ready agent with plugins, semantic templates, and autonomous planning. Next steps:

  • Compare with LangChain: The Semantic Kernel vs LangChain comparison covers when each framework is the better choice
  • Directory entry: See the Semantic Kernel directory entry for advanced features like process frameworks and memory stores
  • OpenAI alternative: Learn building with the OpenAI Agents SDK for a lighter-weight option
  • LangChain tutorial: Explore building with LangChain for the most mature ecosystem
  • Agent glossary: Deepen your understanding of agent frameworks and how they compare

Frequently Asked Questions#

What is the difference between a native plugin and a semantic plugin?

A native plugin wraps Python code — it runs deterministically and can call APIs, databases, or any Python library. A semantic plugin is a prompt template — it uses the AI model itself to process text. Both are registered the same way and are callable by the planner or via function calling.

How does Semantic Kernel differ from LangChain?

Semantic Kernel is designed for enterprise integration with Microsoft's ecosystem (Azure, Office 365, Copilot). It emphasizes the plugin model — wrapping your existing code — and has first-class Azure OpenAI support including managed identity authentication. LangChain has a broader community ecosystem and more integrations, but Semantic Kernel often has simpler, less abstracted APIs for common patterns.

Can I use Semantic Kernel with local models?

Yes. Semantic Kernel supports Ollama and any OpenAI-compatible local endpoint via OpenAIChatCompletion with a custom base_url. For Azure-local scenarios, it also supports Azure OpenAI deployments in sovereign clouds.

What is Process Framework in Semantic Kernel?

Process Framework (introduced in SK v1.x) is a workflow orchestration layer for long-running, stateful business processes. It lets you define multi-step workflows with explicit state machines, error handling, and checkpointing — useful for enterprise workflows that might span hours or days.

Is Semantic Kernel production-ready?

Yes. It is the technology stack powering Microsoft Copilot products used by millions daily. The Python SDK reached v1.0 stability in 2024. Microsoft provides official support, SLAs via Azure, and the framework has been through extensive security review for regulated industries.

Related Tutorials

How to Create a Meeting Scheduling AI Agent

Build an autonomous AI agent to handle meeting scheduling, calendar checks, and bookings intelligently. This step-by-step tutorial covers Python implementation with LangChain, Google Calendar integration, and advanced features like conflict resolution for efficient automation.

How to Manage Multiple AI Agents

Master managing multiple AI agents with this in-depth tutorial. Learn orchestration, state sharing, parallel execution, and scaling using LangGraph and custom tools. From basics to production-ready swarms for complex tasks.

How to Train an AI Agent on Your Own Data

Master training AI agents on custom data with three methods: context stuffing, RAG using vector databases, and fine-tuning. This beginner-to-advanced guide includes step-by-step code examples, pitfalls, and best practices to build knowledgeable agents for your specific needs.

← Back to All Tutorials