This guide demonstrates how to integrate Microsoft’s Semantic Kernel SDK with the ABP.io framework. It includes a wrapper implementation to help you create AI-powered plugins for your ABP application services in a clean, modular way.
🏗️ Architecture Overview
The solution consists of two primary modules:
WafiOpenAISemanticKernelModule
Core module that provides integration with Semantic Kernel.WafiSmartHRAIPluginModule
Sample implementation module demonstrating how to create AI plugins for business entities.
⚙️ Implementation Steps
Follow these steps to integrate Semantic Kernel into your ABP application.
🔹 Step 1: Add the Package to Your HttpApi Project
- Add the Semantic Kernel wrapper package:
dotnet add YourApp.HttpApi.csproj package Wafi.Abp.OpenAISemanticKernel
- Add the module dependency and configure Semantic Kernel options:
This connects your ABP module with the Semantic Kernel framework and sets up OpenAI credentials.
[DependsOn(
// your existing dependencies
typeof(WafiOpenAISemanticKernelModule)
)]
public class YourAppHttpApiModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
Configure<WafiOpenAISemanticKernelOptions>(options =>
{
options.ModelId = configuration.GetValue<string>("SemanticKernel:OpenAI:ModelId");
options.ApiKey = configuration.GetValue<string>("SemanticKernel:OpenAI:ApiKey");
});
}
}
Add the following configuration to your appsettings.json:
{
"SemanticKernel": {
"OpenAI": {
"ApiKey": "your-openai-key",
"ModelId": "gpt-4"
}
}
}
✅ This exposes the
/api/OpenAISemanticKernel/ai/ask
endpoint automatically, which the chat interface will use to interact with Semantic Kernel.
Step 2: Implement a Chat Interface
In your Web project, create a chat interface to interact with the /ai/ask
API. You can refer to the host/Wafi.SmartHR.Web
project for a sample implementation.

🔹 Step 3: Build Plugins to Connect ABP Services with Semantic Kernel
1. Add dependencies to the plugin project:
dotnet add package Wafi.Abp.OpenAISemanticKernel
dotnet add reference ../YourApp.Application/YourApp.Application.csproj
Add this to your plugin module class:
[DependsOn(typeof(YourAppApplicationModule))]
public class YourAppAIPluginModule : AbpModule
{
// ...
}
2. Create AI Plugins for Your Entities
Each plugin class should clearly describe what the AI will get when calling its methods.
📄 Example: YourEntityPlugin.cs
public class YourEntityPlugin : ApplicationService, ITransientDependency
{
private readonly IYourEntityAppService _entityService;
private readonly IAuthorizationService _authorizationService;
public YourEntityPlugin(
IYourEntityAppService entityService,
IAuthorizationService authorizationService)
{
_entityService = entityService;
_authorizationService = authorizationService;
}
[KernelFunction]
[Description("Search for entities by name or any relevant property using a keyword or phrase")]
public async Task<string> SearchEntitiesAsync(string filter)
{
if (!await _authorizationService.IsGrantedAsync(YourPermissions.Default))
{
return "You are not authorized to access this data";
}
var entities = await _entityService.GetListAsync(filter);
if (entities is null || entities.Items.Count == 0)
{
return $"No entities found for filter '{filter}'";
}
return JsonSerializer.Serialize(entities);
}
}
🧠 Be sure to give a meaningful
[Description]
so that the AI knows exactly what this method does.
3. Create a Plugin Provider
Create a provider class to register your plugin with Semantic Kernel. This is a crucial step that makes your plugin discoverable by the AI system.
using Wafi.Abp.OpenAISemanticKernel.Plugins;
using YourApp.AI.Plugin.YourEntities;
namespace YourApp.AI.Plugin
{
public class YourEntityPluginProvider : SemanticPluginProviderBase<YourEntityPlugin>, IWafiPluginProvider
{
public YourEntityPluginProvider(YourEntityPlugin plugin) : base(plugin) { }
public override string Name => "Your Plugin Name";
}
}
🔐 Authorization
All requests are protected by ABP’s permission system. If a user doesn’t have the required permissions, they will receive an appropriate message:
⚠️ You are not authorized to access this data.
The authorization check is performed in each plugin method:
if (!await _authorizationService.IsGrantedAsync(YourPermissions.Default))
{
return "You are not authorized to access this data";
}
✅ Final Outcome
After completing these steps, your ABP application will have a fully functioning AI assistant powered by Semantic Kernel.

The AI interface can be accessed through the /askai
endpoint in your web application. When users send questions to this endpoint, the system:
- Processes the natural language query
- Determines which registered plugins can fulfill the request
- Calls the appropriate application services through the plugins
- Returns formatted results to the user
Example 1: Employee List Query
Request:
POST /askai
Content-Type: application/json
{
"question": "Give me the list of employees"
}
Response:
Here is the list of employees: John Doe – Email: john.doe@example.com – Phone: 1234567890 – Date of Birth: January 1, 1990 – Joining Date: January 1, 2020 – Total Leave Days: 20 – Remaining Leave Days: 20. Jane Smith – Email: jane.smith@example.com – Phone: 0987654321 – Date of Birth: February 1, 1991 – Joining Date: February 1, 2021 – Total Leave Days: 20 – Remaining Leave Days: 15
Example 2: Leave Records Query
Request:
POST /askai
Content-Type: application/json
{
"question": "Give me the list of employee leave records"
}
Response:
Here is the list of employee leave records: John Doe – Annual leave from January 1 to January 5, 2025 (5 days) – Sick leave from March 15 to March 16, 2025 (2 days)\n – Personal leave from June 1 to June 3, 2025 (3 days) Jane Smith – Sick leave from February 1 to February 3, 2025 (3 days) – Annual leave from July 1 to July 10, 2025 (10 days)”
📚 Additional Resources
For a deeper understanding of the module’s implementation, architecture decisions, and advanced customization options, see: