Semantic Kernel Plugins Created: 03 Feb 2026 Updated: 03 Feb 2026

Building Hybrid Plugins in Semantic Kernel

One of the most powerful features of Microsoft Semantic Kernel is the ability to combine native functions (traditional C# code) with semantic functions (AI-powered prompts) into a single, cohesive plugin. This hybrid approach allows developers to leverage the best of both worlds: the precision and performance of native code for deterministic operations, and the flexibility of large language models for complex reasoning tasks.

In this article, we'll build a Smart Document Assistant that demonstrates hybrid plugins through a practical scenario. Our assistant will:

  1. Extract text statistics using native functions (word count, reading time, keyword frequency)
  2. Generate AI-powered summaries and sentiment analysis using semantic functions

Understanding Hybrid Plugins

A hybrid plugin is simply a collection of KernelFunction objects that can originate from different sources:

Function TypeCreated UsingBest For
NativeCreateFunctionFromMethod()Deterministic operations, calculations, I/O
SemanticCreateFunctionFromPrompt()Text generation, analysis, reasoning

Since both types implement KernelFunction, they can be combined into a single list and imported as one plugin using ImportPluginFromFunctions().

The Scenario: Smart Document Assistant

Imagine you're building an application that helps users quickly understand documents. Users can:

  1. Get precise statistics about the document (native)
  2. Extract key topics and themes (semantic)
  3. Generate executive summaries (semantic)
  4. Analyze document sentiment (semantic)

Implementation

Step 1: Define Native Functions

First, let's create our native functions for text analysis:

public class TextAnalysisFunctions
{
public static string AnalyzeTextStatistics(string text)
{
if (string.IsNullOrWhiteSpace(text))
return "No text provided for analysis.";

var words = text.Split([' ', '\n', '\r', '\t'],
StringSplitOptions.RemoveEmptyEntries);
var sentences = text.Split(['.', '!', '?'],
StringSplitOptions.RemoveEmptyEntries);
var paragraphs = text.Split(["\n\n", "\r\n\r\n"],
StringSplitOptions.RemoveEmptyEntries);

int wordCount = words.Length;
int sentenceCount = sentences.Length;
int paragraphCount = paragraphs.Length;
double avgWordsPerSentence = sentenceCount > 0
? Math.Round((double)wordCount / sentenceCount, 1)
: 0;
int estimatedReadingTimeMinutes = (int)Math.Ceiling(wordCount / 200.0);

return $"""
Word Count: {wordCount}
Sentence Count: {sentenceCount}
Paragraph Count: {paragraphCount}
Average Words per Sentence: {avgWordsPerSentence}
Estimated Reading Time: {estimatedReadingTimeMinutes} minute(s)
""";
}

public static string ExtractTopKeywords(string text, int topN = 5)
{
if (string.IsNullOrWhiteSpace(text))
return "No text provided.";

var stopWords = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
"the", "a", "an", "is", "are", "was", "were", "be", "been",
"being", "have", "has", "had", "do", "does", "did", "will",
"would", "could", "should", "may", "might", "must", "shall",
"can", "need", "dare", "ought", "used", "to", "of", "in",
"for", "on", "with", "at", "by", "from", "as", "into", "through",
"during", "before", "after", "above", "below", "between", "under",
"again", "further", "then", "once", "here", "there", "when",
"where", "why", "how", "all", "each", "few", "more", "most",
"other", "some", "such", "no", "nor", "not", "only", "own",
"same", "so", "than", "too", "very", "just", "and", "but",
"if", "or", "because", "until", "while", "this", "that", "these",
"those", "it", "its", "they", "them", "their", "we", "us", "our",
"you", "your", "he", "him", "his", "she", "her", "i", "my", "me"
};

var words = text.ToLower()
.Split([' ', '\n', '\r', '\t', '.', ',', '!', '?', ';', ':', '"', '\'', '(', ')', '[', ']'],
StringSplitOptions.RemoveEmptyEntries)
.Where(w => w.Length > 2 && !stopWords.Contains(w))
.GroupBy(w => w)
.OrderByDescending(g => g.Count())
.Take(topN)
.Select(g => $"{g.Key} ({g.Count()})");

return $"Top {topN} Keywords: {string.Join(", ", words)}";
}
}

Step 2: Define Semantic Function Prompts

Next, create prompts for AI-powered analysis:

var summarizationPrompt = """
You are an expert document summarizer. Your task is to create a concise
executive summary of the provided document.

Guidelines:
- Keep the summary to 3-5 sentences maximum
- Focus on the main points and key takeaways
- Use clear, professional language
- Do not add information not present in the original text

[DOCUMENT START]
{{$document}}
[DOCUMENT END]

Executive Summary:
""";

var sentimentAnalysisPrompt = """
Analyze the sentiment and tone of the following document. Provide:
1. Overall sentiment (Positive/Negative/Neutral)
2. Confidence level (High/Medium/Low)
3. Key emotional indicators found in the text
4. Recommended audience approach based on tone

[DOCUMENT START]
{{$document}}
[DOCUMENT END]

Sentiment Analysis:
""";

var keyTopicsPrompt = """
Extract the main topics and themes from the following document.
Format your response as:
- Main Topic: [primary subject]
- Secondary Topics: [list 2-3 related themes]
- Domain: [business/technical/academic/general]

[DOCUMENT START]
{{$document}}
[DOCUMENT END]

Topics Analysis:
""";

Step 3: Create and Register the Hybrid Plugin

Now, combine everything into a hybrid plugin:

// Create native functions
var statisticsFunction = kernel.CreateFunctionFromMethod(
typeof(TextAnalysisFunctions).GetMethod(nameof(TextAnalysisFunctions.AnalyzeTextStatistics))!,
target: null,
functionName: "AnalyzeStatistics",
description: "Analyzes text and returns word count, sentence count, and reading time."
);

var keywordsFunction = kernel.CreateFunctionFromMethod(
typeof(TextAnalysisFunctions).GetMethod(nameof(TextAnalysisFunctions.ExtractTopKeywords))!,
target: null,
functionName: "ExtractKeywords",
description: "Extracts the most frequently used keywords from the document."
);

// Create semantic functions
var summarizeFunction = kernel.CreateFunctionFromPrompt(
summarizationPrompt,
functionName: "Summarize",
description: "Generates an executive summary of the document using AI."
);

var sentimentFunction = kernel.CreateFunctionFromPrompt(
sentimentAnalysisPrompt,
functionName: "AnalyzeSentiment",
description: "Analyzes the sentiment and tone of the document using AI."
);

var topicsFunction = kernel.CreateFunctionFromPrompt(
keyTopicsPrompt,
functionName: "ExtractTopics",
description: "Identifies main topics and themes in the document using AI."
);

// Combine into hybrid plugin
List<KernelFunction> hybridFunctions =
[
statisticsFunction, // Native
keywordsFunction, // Native
summarizeFunction, // Semantic
sentimentFunction, // Semantic
topicsFunction // Semantic
];

kernel.ImportPluginFromFunctions(
"document_assistant",
"Smart Document Assistant with text analysis and AI-powered insights.",
hybridFunctions
);

Step 4: Using the Hybrid Plugin

Here's how to use the hybrid plugin in practice:

var sampleDocument = """
Artificial Intelligence is transforming the software development landscape
at an unprecedented pace. Companies worldwide are adopting AI-powered tools
to enhance productivity, reduce errors, and accelerate delivery timelines.
The integration of large language models into development workflows has
enabled developers to write code faster, generate documentation automatically,
and identify potential bugs before they reach production. This shift represents
a fundamental change in how software is created and maintained.
However, challenges remain. Security concerns, model accuracy, and the need
for human oversight continue to be important considerations. Organizations
must balance the benefits of AI assistance with appropriate governance and
quality controls.
""";

var arguments = new KernelArguments
{
["document"] = sampleDocument,
["text"] = sampleDocument,
["topN"] = 5
};

// Use native function for statistics
var stats = await kernel.InvokeAsync("document_assistant", "AnalyzeStatistics", arguments);
Console.WriteLine($"📊 Document Statistics:\n{stats}\n");

// Use native function for keywords
var keywords = await kernel.InvokeAsync("document_assistant", "ExtractKeywords", arguments);
Console.WriteLine($"🔑 {keywords}\n");

// Use semantic function for summary
var summary = await kernel.InvokeAsync("document_assistant", "Summarize", arguments);
Console.WriteLine($"📝 AI Summary:\n{summary}\n");

// Use semantic function for sentiment
var sentiment = await kernel.InvokeAsync("document_assistant", "AnalyzeSentiment", arguments);
Console.WriteLine($"💭 Sentiment Analysis:\n{sentiment}\n");

Expected Output

📊 Document Statistics:
Word Count: 156
Sentence Count: 8
Paragraph Count: 3
Average Words per Sentence: 19.5
Estimated Reading Time: 1 minute(s)

🔑 Top 5 Keywords: software (2), development (2), code (2), ai-powered (2), productivity (1)

📝 AI Summary:
AI is rapidly transforming software development, with companies adopting AI-powered
tools to boost productivity and accelerate delivery. Large language models are enabling
faster coding, automatic documentation, and early bug detection. Despite these advances,
organizations must address security concerns and maintain human oversight while balancing
AI benefits with proper governance.

💭 Sentiment Analysis:
1. Overall Sentiment: Positive with cautious undertones
2. Confidence Level: High
3. Key Emotional Indicators: optimism ("transforming", "enhance"), caution ("challenges remain", "concerns")
4. Recommended Audience Approach: Present as opportunity with acknowledged risks

Advanced Usage: Orchestrating Hybrid Functions

You can also orchestrate hybrid functions within a single prompt:

var orchestrationPrompt = """
You are a document analysis assistant. Generate a comprehensive report.

Document Statistics (from analysis):
{{AnalyzeStatistics $document}}

Keywords Found:
{{ExtractKeywords $document}}

Based on the above metrics and the document content, provide your assessment
of the document's readability and target audience.
""";

var report = await kernel.InvokePromptAsync(orchestrationPrompt, arguments);

Benefits of Hybrid Plugins

Benefit - Description
PerformanceNative functions execute instantly for deterministic operations
Cost EfficiencyReduce API calls by handling simple tasks locally
ReliabilityNative functions provide consistent, testable results
FlexibilityAI handles complex reasoning that would be difficult to code
MaintainabilitySingle plugin interface regardless of function type

Best Practices

  1. Use native functions for:
  2. Mathematical calculations
  3. Data transformations
  4. File I/O operations
  5. Validation logic
  6. Performance-critical operations
  7. Use semantic functions for:
  8. Text summarization
  9. Sentiment analysis
  10. Content generation
  11. Complex reasoning
  12. Pattern recognition in unstructured data
  13. Design considerations:
  14. Keep function responsibilities clear and focused
  15. Use descriptive names and descriptions for discoverability
  16. Consider caching semantic function results for repeated queries
  17. Implement proper error handling in native functions
Share this lesson: