# Using Skills in Microsoft Agent Framework – C#

> Source: <https://dev.to/chatri_ngambenchawongpi/using-skills-in-microsoft-agent-framework-c-85g>
> Published: 2026-09-30 09:38:00+00:00

Welcome to today’s post! This blog series dives into the Microsoft Agent Framework and my recent speaking session at Build.AI 2026.

For Thai Version: [ลองใช้ Microsoft Agent Framework – Agent Skills](https://naiwaen.debuggingsoft.com/2026/09/using-skill-in-microsoft-agent-framework-with-csharp-th/)

This feature has been around for quite some time—I actually started playing with it during the Songkran holiday. Lately, I’ve been thinking about how models like Claude or Hermes are integrating Skill.md files, and I wondered: Can the Microsoft Agent Framework do this too?

Spoiler alert: Yes, it can! That’s what inspired this little experiment with 'Cat' / Claude (lol).

## 
  
  
  Here’s what this blog will cover:

## 
  
  
  Recap Microsoft Agent Framework

Microsoft Agent Framework (MAF) is a NuGet library designed to make building AI Agents across the .NET, Python, and Golang (preview) stacks easier and more streamlined. It supports everything from straightforward chat interactions and workflow automation, to building Harness Agents with built-in Memory and Tools Approval management.

However, for this specific blog post, the spotlight will be focus on Skills.

## 
  
  
  What is a Skill?

A "Skill" is essentially a focused set of capabilities extracted into concise prompts, accompanied by supporting scripts that enable the LLM to invoke them. Currently, these are mostly written in Python. I did experiment with C# Script, but it still comes with quite a few limitations at the moment.

Example: expense-report , Skill Structure explain below

## 
  
  
  Skill vs. Workflow

| Aspect | When to use a Skill | When to use a Workflow | 
| Control | You want the AI to make its own decisions; it's flexible and creative. | You need a strictly deterministic  execution path. | 
| Resilience | If it fails, you can simply retry the entire turn. | It requires checkpoints to resume from the last step, which is crucial when re-running the whole process is too costly. | 
| Side Effects | Operations are idempotent or low-risk; repeating them yields the exact same result. | It involves real side effects (e.g., sending emails, processing payments) that cannot be safely retried.. | 
| Complexity | Single-domain tasks that a single agent can easily handle. | Multi-step business processes involving multiple agents, human approvals, or external systems. | 

## 
  
  
  How to MAF Select Skills (Progressive Disclosure)

Based on the SKILL.md file, which defines what a specific Skill does, the MAF-Agent Skills framework follows a 4-step selection and execution process:

1. 
**Advertise (~100 tokens per skill):** The framework looks at the Skill names and descriptions, injecting them into the system prompt to inform the LLM about the available capabilities.
2. 
**Load (< 5000 tokens recommended):** If a Skill matches the LLM's requirements, MAF loads and reads the entire SKILL.md file. It is highly recommended to keep the size of this file under 5,000 tokens.
3. 
**Read resources:** Once the LLM selects a Skill and determines that it needs related reference materials, MAF invokes the read_skill_resource function to fetch them for context.
4. 
**Run scripts:** Similarly, if the LLM decides that a script needs to be executed, MAF calls the run_skill_script function to run it, captures the output, and feeds the results back to the Agent.

## 
  
  
  Understanding Agent Skills in the Microsoft Agent Framework

In MAF, there are four distinct types of Skills: File-based skills, Class-based skills, Code-defined skills, and MCP-based skills.

### 
  
  
  - File-based skills

For this part, we prepare the SKILL.md file following the standard Agent Skills structure. On the coding side within MAF, there are a few key components to pay attention to:

- AgentFileSkillsSourceOptions – This defines how Skills are loaded and specifies the supported file formats.
- AgentSkillsProvider – This is responsible for loading the Skills into the agent. If your Skill includes scripts, you also need to configure which class handles script execution via the scriptRunner / UseFileScriptRunner.

**One thing to note:** if you read the official MAF documentation, it recommends using [SubprocessScriptRunner. However, this class is not built-in to the framework](https://github.com/microsoft/agent-framework/blob/main/dotnet/samples/02-agents/AgentSkills/SubprocessScriptRunner.cs). I actually had to copy the implementation and use it in my own project as well.

### 
  
  
  - Class-based skills

If you have a class that you want the AI to interact with, you can decorate it with attributes—such as name, description, instructions, resources, and scripts—to turn the entire class into a Skill. Alternatively, it can act as a Driver to invoke related Services or Business Logic.

MAF conveniently provides AgentClassSkill for you to inherit from. On top of that, Skills can be distributed via NuGet packages, making it super easy for consumers to just add a reference and start using them right away.

The code snippet below shows an example of a Skill designed to read a Gitea repository. I'll use it to break down the components of AgentClassSkill:

- AgentSkillFrontmatter – Defines the Skill's Name and Description, essentially telling the AI what this Skill can do.
- Instructions – Contains the pre-written prompts. Tip: If the instructions get too lengthy, it's better to offload them into an AgentSkillResource.
- AgentSkillResource – Provides supplementary context about tools, or can even act as a lookup table.
- AgentSkillScript – Defines the specific methods that the Agent is allowed to call and execute.

Actually, if you've ever used Semantic Kernel before, you'll find that Class-based skills are quite similar to [KernelFunction](https://devblogs.microsoft.com/agent-framework/transforming-semantic-kernel-functions/)

### 
  
  
  - Code-defined skills

This one is conceptually similar to Class-based skills, but with a key difference: you can create Skills dynamically at runtime. Some common use cases include:

- 
**Personalizing per user session** – Tailor the Skill's behavior based on the current user's context.
- 
**Reading values from env/DB in real-time** – Or embedding logic directly at the call-site instead of relying on static files.
- 
**Using values from Local Variables** – Effectively creating closures over call-site state.

From my perspective, there's another big advantage: if you already have existing Method or Function implementations, wrapping them with AgentInlineSkill lets you turn them into Skills with minimal refactoring

Now, in the ExtractAsync / DescribeStatusAsync methods, you can simply implement your own custom logic

Before we move on, let's do a quick recap—even I got a bit confused myself 555

- 
**Class-based skills:** Use these when your Skill requires complex DB connections, needs Services injected via the Constructor, or demands a clear structure for better Testability and Reusability.
- 
**Code-defined skills:** Ideal for when a Skill needs to be generated dynamically at runtime (e.g., the Skill structure changes based on data in the DB), is extremely lightweight, or requires direct access to Local Variables/Closures.

### 
  
  
  - MCP-based skills

This feature consists of two main parts: the MCP Server (via the ModelContextProtocol.AspNetCore NuGet package) and the MCP Client (via the Microsoft.Agents.AI.Mcp NuGet package)

📌 **MCP Server** – Exposes a URL scheme like skill://index.json and supports two operational modes:

| Format | Behavior | Use Case | 
| skill-md | The MCP Server allows the Agent to fetch the SKILL.md file and related resources on demand. If additional resources are needed , the Agent will trigger further requests sequentially. | Ideal for Agents to pull the latest Skills individually (one by one). | 
| archive | The MCP Server allows fetching all Skills bundled together in .zip, .tar, or .tar.gz formats. | Perfect for syncing and distributing groups of Skills to AI Agents (e.g., Skills for Finance, Customer Support, Data Operations, Dev, etc.). | 

📌 **MCP Client** – Instantiate the mcpClient to establish a connection and invoke the skills.

- When fetching Skills via the Archive method, the Client must also pass AgentMcpSkillsSourceOptions to specify the search scope. Additionally, if a Skill contains scripts, MAF explicitly warns that 'Archive scripts are never executed.

### 
  
  
  Recap What types of MAF skills are available to use? Here are the options:

- 
**File-based skills:** For this approach, we prepare a SKILL.md file following the Agent Skills structure, then configure it using AgentFileSkillsSourceOptions or AgentSkillsProvider to load and use them.
- 
**Class-based skills:** Similar to file-based skills, but implemented as C# classes. You extend the AgentClassSkill base class and override AgentSkillFrontmatter (which includes the skill name, description, instructions, resources, and scripts).
- 
**Code-defined skills:** Similar to class-based skills, but created dynamically at runtime. This allows us to adjust skill properties like names, descriptions, or instructions on the fly based on the user. For instance, in a room-booking skill, we can inject personalized data such as user preferences and past responses directly into it.
- 
**MCP-based skills:** Enables direct skill execution from an MCP Server. This supports Ad-Hoc mode for real-time invocation, as well as Archive mode, which shares skills so agents can download them to their local environment.

## 
  
  
  Using Agent Skills + Harness Agents

So we know MAF offers four Skill types: File-based, Class-based, Code-defined, and MCP-based. The next step is writing code to load and expose these capabilities to the Agent + LLM. Here's a sample implementation

Since some Skills interact with the environment, simply creating a regular Agent isn't enough. Instead, we bring in the Harness Agent to help manage this, specifically leveraging its Approval mechanism. This requires two essential configuration components:

- UseOptions – Allows you to toggle approval requirements for specific Skill operations:
  - DisableLoadSkillApproval
  - DisableReadSkillResourceApproval
  - DisableRunSkillScriptApproval
- ToolApprovalAgentOptions

So instead of a plain ChatClient with just AsAIAgent, we'll wrap it with the Harness Agent.

Switch it over to AsHarnessAgent. For this, I've created a Helper method to build the Harness Agent, which takes three key parameters: skillsProvider, instructions, and ToolApprovalAgentOptions.

Oh, and one more thing—when creating the Agent, don't forget to pass in the LoggerFactory so that MAF can write logs

In my session, I showcased two Demo Apps:

## 
  
  
  Sample App - gitea-aihook

💡 [gitea-aihook](https://github.com/pingkunga/gitea-aihook) – Right before Songkran, I wanted to build a GitHub Copilot Review-style experience for Gitea. I built it with .NET 10 + WebAPI, and it can be triggered via Webhooks or Gitea Actions to summarize PRs—flagging anything reviewers should pay attention to. It ships with 4 Skills.

- 
[review](https://github.com/pingkunga/gitea-aihook/tree/feature/add_skill/GiteaAiSummarizerNET/Templates/Skills/review) – A file-based Skill + script (impact_graph) used to analyze git diffs and identify potential impact areas in the system (e.g., Symbols / APIs) before letting the AI summarize the PR.
- 
[security-checker](https://github.com/pingkunga/gitea-aihook/tree/feature/add_skill/GiteaAiSummarizerNET/Templates/Skills/security-checker) – A file-based Skill that detects hardcoded secrets/API keys, and checks authentication/encryption issues. Though honestly, this should probably be implemented as a script instead.
- 
[style-guard](https://github.com/pingkunga/gitea-aihook/tree/feature/add_skill/GiteaAiSummarizerNET/Templates/Skills/security-checker) – A file-based Skill that checks code style, complexity, and naming conventions.
- 
[gitea-tools](https://giteaaisummarizernet/Services/GiteaSkill.cs) – A custom Class-based Skill (GiteaSkill : AgentClassSkill) that exposes 3 tools/functions for the Agent to call the Gitea API: get_issue / get_issue_comments / search_code.

Oh, and while I was preparing for the presentation, I happened to check and realized [Gitea actually has MCP support!](https://gitea.com/gitea/gitea-mcp) So we could potentially just use the MCP instead of having to build a custom class skill.

## 
  
  
  Sample App - MyFinanceWithAgentSkill

💡 The second one ([MyFinanceWithAgentSkill](https://github.com/pingkunga/dotnet_conf26_FinAgentAppWithSkill)) – I went back to review the Agent Skill documentation and noticed it covers Harness / Code-defined skills and MCP-based skills. So I built a simple finance management app on .NET 10 + Blazor Server (Interactive Server) with [MudBlazor](https://mudblazor.com/). The main features demonstrate each type of Skill from the Microsoft Agent Framework end-to-end in real-world scenarios:

- 
[Transactions + Budgeting](https://github.com/pingkunga/dotnet_conf26_FinAgentAppWithSkill/blob/main/src/FinanceApp.Skills/Budgeting/BudgetSkill.cs) &[Exchange Rate](https://github.com/pingkunga/dotnet_conf26_FinAgentAppWithSkill/blob/main/src/FinanceApp.Skills/ExchangeRates/ExchangeRateSkill.cs) – Class-based AgentClassSkill (record expenses, check budget status, transfer budgets between categories)
- 
[Receipt OCR](https://github.com/pingkunga/dotnet_conf26_FinAgentAppWithSkill/blob/main/src/FinanceApp.Skills/ReceiptOcr/ReceiptOcrSkillFactory.cs) – Inline AgentInlineSkill that processes one receipt file per session without needing to reset the ongoing chat
- 
[Saving-Calculator](https://github.com/pingkunga/dotnet_conf26_FinAgentAppWithSkill/tree/main/skills/savings-calculator) /[Savings Goals](https://github.com/pingkunga/dotnet_conf26_FinAgentAppWithSkill/tree/main/skills/savings-goals) – File-based SKILL.md + references/ + Python (compound interest calculations)
- 
[Monthly Summary](https://github.com/pingkunga/dotnet_conf26_FinAgentAppWithSkill/blob/main/src/FinanceApp.McpServer/MonthlySummaryResourceHandlers.cs) /[Goals Progress](https://github.com/pingkunga/dotnet_conf26_FinAgentAppWithSkill/blob/main/src/FinanceApp.McpServer/GoalsProgressResourceHandlers.cs) – MCP-based via HTTP service + JWT bearer, which invokes Skills and provides resources such as reference documents or calculation APIs hosted on the MCP Server
- 
[Emergency Fund / Debt Payoff](https://github.com/pingkunga/dotnet_conf26_FinAgentAppWithSkill/tree/main/src/FinanceApp.McpServer/skills) – MCP-based via HTTP service + JWT 
bearer, demonstrating the Archive Mode example where Skills are shared for the Agent to pull down and run locally

Here are the main screens:

- 
**Chat Interface** – Features real-time streaming, Markdown rendering via[Markdig](https://github.com/xoofx/markdig) , and Approve/Reject prompts handled by the Harness agent for run_skill_script executions.
- 
**Agent Activity Log** – Displays real-time activity chips tracking Skill executions.
- 
**Standard CRUD Modules** – For managing Receipts, Goals, Transactions, and Budgets.
- 
**User Management via ASP.NET Core Identity** – This includes per-user configuration settings. Since constantly prompting users to click "Approve" can get annoying, I added AutoApproveWrites and AutoApproveExecuteScript flags for each user. These flags automatically bypass the approval prompts before load_skill and read_skill_resource are executed.

## 
  
  
  Security Best Practices

- 
**Review Before Use:** Skills often contain executable scripts, so always review the code before running them.
- 
**Trust the Source:** Only fetch Skills from trusted sources. Beware of "typosquatted" Skill names (e.g., rnicrosoft vs. microsoft).
- 
**Pin Versions & Verify Integrity:** Always pin specific versions and verify the integrity of Skills fetched from an MCP Server.
- 
**Sandboxing:** Since Skills can execute scripts, they should run in an isolated environment. Combine this with the Harness Agent's approval mechanism for an extra layer of safety.
- 
**Apply Least Privilege:** Grant only the minimum permissions necessary for a Skill to function.
- 
**Treat Skill Content as Untrusted Input:** Always sanitize and validate any data or parameters passed into a Skill.
- 
**Keep Secrets Out of Skills:** Never hardcode secrets within a Skill. If a Skill needs to handle sensitive data, thoroughly review its internal scripts to ensure it isn't exfiltrating data.
- 
**Never Embed Credentials:** Inject credentials at runtime instead (e.g., passing a per-user JWT to the MCP server). You can see an example of this in the provided code.
- 
**Approval Gates:** Always enforce Human-in-the-Loop (HITL) for high-risk actions.
- 
**Audit and Logging:** Maintain strict logs of exactly what Skills and resources are loaded and executed.

## 
  
  
  Closing Thoughts

Finally, thank you to everyone who attended the session! If you missed any details during the presentation, feel free to refer back to this blog.

As for the Sample Apps, if time permits, I plan to write a follow-up blog post to dive deeper into all the available resources and code. Stay tuned!

## 
  
  
  Reference
