-
Notifications
You must be signed in to change notification settings - Fork 1.2k
.NET: Support Agent Skills #4122
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
SergeyMenshykh
merged 19 commits into
microsoft:main
from
SergeyMenshykh:support-agent-skills
Feb 20, 2026
+1,776
−1
Merged
Changes from all commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
ffaa098
support agent skills
SergeyMenshykh 7fbb3bd
make the new agent skill provider experimental
SergeyMenshykh ee96900
Fix file encoding: add UTF-8 BOM to .cs files
SergeyMenshykh bc23952
Fix final newline and simplify new expressions
SergeyMenshykh 6b33e22
Fix broken links in Agent Skills sample README
SergeyMenshykh 2db5638
Add null check for skillPaths parameter
SergeyMenshykh 39b183c
Normalize references
SergeyMenshykh 5c30999
normilize skill path
SergeyMenshykh 2b8c0c5
address comments regarding symlink check
SergeyMenshykh 7a39dd0
address comments
SergeyMenshykh 3fcdd26
fix failing test + regex improvements
SergeyMenshykh 0991137
small optimizations and improvments
SergeyMenshykh d9a2a72
Merge branch 'main' into support-agent-skills
SergeyMenshykh b2939f7
address pr review comments
SergeyMenshykh 55dd1e6
Merge branch 'support-agent-skills' of https://github.com/SergeyMensh…
SergeyMenshykh 1ded3af
Update dotnet/src/Microsoft.Agents.AI/Skills/FileAgentSkillsProvider.cs
SergeyMenshykh 03d557e
address pr review comments
SergeyMenshykh f6eb53a
Merge branch 'support-agent-skills' of https://github.com/SergeyMensh…
SergeyMenshykh ad73840
address pr review comments
SergeyMenshykh File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
28 changes: 28 additions & 0 deletions
28
...mples/GettingStarted/AgentSkills/Agent_Step01_BasicSkills/Agent_Step01_BasicSkills.csproj
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
|
|
||
| <PropertyGroup> | ||
| <OutputType>Exe</OutputType> | ||
| <TargetFrameworks>net10.0</TargetFrameworks> | ||
|
|
||
| <Nullable>enable</Nullable> | ||
| <ImplicitUsings>enable</ImplicitUsings> | ||
| <NoWarn>$(NoWarn);MAAI001</NoWarn> | ||
| </PropertyGroup> | ||
|
|
||
| <ItemGroup> | ||
| <PackageReference Include="Azure.AI.OpenAI" /> | ||
| <PackageReference Include="Azure.Identity" /> | ||
| </ItemGroup> | ||
|
|
||
| <ItemGroup> | ||
| <ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.OpenAI\Microsoft.Agents.AI.OpenAI.csproj" /> | ||
| </ItemGroup> | ||
|
|
||
| <!-- Copy skills directory to output --> | ||
| <ItemGroup> | ||
| <None Include="skills\**\*.*"> | ||
| <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> | ||
| </None> | ||
| </ItemGroup> | ||
|
|
||
| </Project> |
49 changes: 49 additions & 0 deletions
49
dotnet/samples/GettingStarted/AgentSkills/Agent_Step01_BasicSkills/Program.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| // Copyright (c) Microsoft. All rights reserved. | ||
|
|
||
| // This sample demonstrates how to use Agent Skills with a ChatClientAgent. | ||
| // Agent Skills are modular packages of instructions and resources that extend an agent's capabilities. | ||
| // Skills follow the progressive disclosure pattern: advertise -> load -> read resources. | ||
| // | ||
| // This sample includes the expense-report skill: | ||
| // - Policy-based expense filing with references and assets | ||
|
|
||
| using Azure.AI.OpenAI; | ||
| using Azure.Identity; | ||
| using Microsoft.Agents.AI; | ||
| using OpenAI.Responses; | ||
|
|
||
| // --- Configuration --- | ||
| string endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") | ||
| ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set."); | ||
| string deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini"; | ||
|
|
||
| // --- Skills Provider --- | ||
| // Discovers skills from the 'skills' directory and makes them available to the agent | ||
| var skillsProvider = new FileAgentSkillsProvider(skillPath: Path.Combine(AppContext.BaseDirectory, "skills")); | ||
|
|
||
| // --- Agent Setup --- | ||
| AIAgent agent = new AzureOpenAIClient(new Uri(endpoint), new DefaultAzureCredential()) | ||
| .GetResponsesClient(deploymentName) | ||
| .AsAIAgent(new ChatClientAgentOptions | ||
| { | ||
| Name = "SkillsAgent", | ||
| ChatOptions = new() | ||
| { | ||
| Instructions = "You are a helpful assistant.", | ||
| }, | ||
| AIContextProviders = [skillsProvider], | ||
| }); | ||
|
|
||
| // --- Example 1: Expense policy question (loads FAQ resource) --- | ||
| Console.WriteLine("Example 1: Checking expense policy FAQ"); | ||
| Console.WriteLine("---------------------------------------"); | ||
| AgentResponse response1 = await agent.RunAsync("Are tips reimbursable? I left a 25% tip on a taxi ride and want to know if that's covered."); | ||
| Console.WriteLine($"Agent: {response1.Text}\n"); | ||
|
|
||
| // --- Example 2: Filing an expense report (multi-turn with template asset) --- | ||
| Console.WriteLine("Example 2: Filing an expense report"); | ||
| Console.WriteLine("---------------------------------------"); | ||
| AgentSession session = await agent.CreateSessionAsync(); | ||
| AgentResponse response2 = await agent.RunAsync("I had 3 client dinners and a $1,200 flight last week. Return a draft expense report and ask about any missing details.", | ||
| session); | ||
| Console.WriteLine($"Agent: {response2.Text}\n"); |
63 changes: 63 additions & 0 deletions
63
dotnet/samples/GettingStarted/AgentSkills/Agent_Step01_BasicSkills/README.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| # Agent Skills Sample | ||
|
|
||
| This sample demonstrates how to use **Agent Skills** with a `ChatClientAgent` in the Microsoft Agent Framework. | ||
|
|
||
| ## What are Agent Skills? | ||
|
|
||
| Agent Skills are modular packages of instructions and resources that enable AI agents to perform specialized tasks. They follow the [Agent Skills specification](https://agentskills.io/) and implement the progressive disclosure pattern: | ||
|
|
||
| 1. **Advertise**: Skills are advertised with name + description (~100 tokens per skill) | ||
| 2. **Load**: Full instructions are loaded on-demand via `load_skill` tool | ||
| 3. **Resources**: References and other files loaded via `read_skill_resource` tool | ||
|
|
||
| ## Skills Included | ||
|
|
||
| ### expense-report | ||
| Policy-based expense filing with spending limits, receipt requirements, and approval workflows. | ||
| - `references/POLICY_FAQ.md` — Detailed expense policy Q&A | ||
| - `assets/expense-report-template.md` — Submission template | ||
|
|
||
| ## Project Structure | ||
|
|
||
| ``` | ||
| Agent_Step01_BasicSkills/ | ||
| ├── Program.cs | ||
| ├── Agent_Step01_BasicSkills.csproj | ||
| └── skills/ | ||
| └── expense-report/ | ||
| ├── SKILL.md | ||
| ├── references/ | ||
| │ └── POLICY_FAQ.md | ||
| └── assets/ | ||
| └── expense-report-template.md | ||
| ``` | ||
|
|
||
| ## Running the Sample | ||
|
|
||
| ### Prerequisites | ||
| - .NET 10.0 SDK | ||
| - Azure OpenAI endpoint with a deployed model | ||
|
|
||
| ### Setup | ||
| 1. Set environment variables: | ||
| ```bash | ||
| export AZURE_OPENAI_ENDPOINT="https://your-endpoint.openai.azure.com/" | ||
| export AZURE_OPENAI_DEPLOYMENT_NAME="gpt-4o-mini" | ||
| ``` | ||
|
|
||
| 2. Run the sample: | ||
| ```bash | ||
| dotnet run | ||
| ``` | ||
|
|
||
| ### Examples | ||
|
|
||
| The sample runs two examples: | ||
|
|
||
| 1. **Expense policy FAQ** — Asks about tip reimbursement; the agent loads the expense-report skill and reads the FAQ resource | ||
| 2. **Filing an expense report** — Multi-turn conversation to draft an expense report using the template asset | ||
|
|
||
| ## Learn More | ||
|
|
||
| - [Agent Skills Specification](https://agentskills.io/) | ||
| - [Microsoft Agent Framework Documentation](../../../../../docs/) |
40 changes: 40 additions & 0 deletions
40
...tingStarted/AgentSkills/Agent_Step01_BasicSkills/skills/expense-report/SKILL.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| --- | ||
| name: expense-report | ||
| description: File and validate employee expense reports according to Contoso company policy. Use when asked about expense submissions, reimbursement rules, receipt requirements, spending limits, or expense categories. | ||
| metadata: | ||
| author: contoso-finance | ||
| version: "2.1" | ||
| --- | ||
|
|
||
| # Expense Report | ||
|
|
||
| ## Categories and Limits | ||
|
|
||
| | Category | Limit | Receipt | Approval | | ||
| |---|---|---|---| | ||
| | Meals — solo | $50/day | >$25 | No | | ||
| | Meals — team/client | $75/person | Always | Manager if >$200 total | | ||
| | Lodging | $250/night | Always | Manager if >3 nights | | ||
| | Ground transport | $100/day | >$15 | No | | ||
| | Airfare | Economy | Always | Manager; VP if >$1,500 | | ||
| | Conference/training | $2,000/event | Always | Manager + L&D | | ||
| | Office supplies | $100 | Yes | No | | ||
| | Software/subscriptions | $50/month | Yes | Manager if >$200/year | | ||
|
|
||
| ## Filing Process | ||
|
|
||
| 1. Collect receipts — must show vendor, date, amount, payment method. | ||
| 2. Categorize per table above. | ||
| 3. Use template: [assets/expense-report-template.md](assets/expense-report-template.md). | ||
| 4. For client/team meals: list attendee names and business purpose. | ||
| 5. Submit — auto-approved if <$500; manager if $500–$2,000; VP if >$2,000. | ||
| 6. Reimbursement: 10 business days via direct deposit. | ||
|
|
||
| ## Policy Rules | ||
|
|
||
| - Submit within 30 days of transaction. | ||
| - Alcohol is never reimbursable. | ||
| - Foreign currency: convert to USD at transaction-date rate; note original currency and amount. | ||
| - Mixed personal/business travel: only business portion reimbursable; provide comparison quotes. | ||
| - Lost receipts (>$25): file Lost Receipt Affidavit from Finance. Max 2 per quarter. | ||
| - For policy questions not covered above, consult the FAQ: [references/POLICY_FAQ.md](references/POLICY_FAQ.md). Answers should be based on what this document and the FAQ state. |
5 changes: 5 additions & 0 deletions
5
...gent_Step01_BasicSkills/skills/expense-report/assets/expense-report-template.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| # Expense Report Template | ||
|
|
||
| | Date | Category | Vendor | Description | Amount (USD) | Original Currency | Original Amount | Attendees | Business Purpose | Receipt Attached | | ||
| |------|----------|--------|-------------|--------------|-------------------|-----------------|-----------|------------------|------------------| | ||
| | | | | | | | | | | Yes or No | |
55 changes: 55 additions & 0 deletions
55
...tSkills/Agent_Step01_BasicSkills/skills/expense-report/references/POLICY_FAQ.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| # Expense Policy — Frequently Asked Questions | ||
|
|
||
| ## Meals | ||
|
|
||
| **Q: Can I expense coffee or snacks during the workday?** | ||
| A: Daily coffee/snacks under $10 are not reimbursable (considered personal). Coffee purchased during a client meeting or team working session is reimbursable as a team meal. | ||
|
|
||
| **Q: What if a team dinner exceeds the per-person limit?** | ||
| A: The $75/person limit applies as a guideline. Overages up to 20% are accepted with a written justification (e.g., "client dinner at venue chosen by client"). Overages beyond 20% require pre-approval from your VP. | ||
|
|
||
| **Q: Do I need to list every attendee?** | ||
| A: Yes. For client meals, list the client's name and company. For team meals, list all employee names. For groups over 10, you may attach a separate attendee list. | ||
|
|
||
| ## Travel | ||
|
|
||
| **Q: Can I book a premium economy or business class flight?** | ||
| A: Economy class is the standard. Premium economy is allowed for flights over 6 hours. Business class requires VP pre-approval and is generally reserved for flights over 10 hours or medical accommodation. | ||
|
|
||
| **Q: What about ride-sharing (Uber/Lyft) vs. rental cars?** | ||
| A: Use ride-sharing for trips under 30 miles round-trip. Rent a car for multi-day travel or when ride-sharing would exceed $100/day. Always choose the compact/standard category unless traveling with 3+ people. | ||
|
|
||
| **Q: Are tips reimbursable?** | ||
| A: Tips up to 20% are reimbursable for meals, taxi/ride-share, and hotel housekeeping. Tips above 20% require justification. | ||
|
|
||
| ## Lodging | ||
|
|
||
| **Q: What if the $250/night limit isn't enough for the city I'm visiting?** | ||
| A: For high-cost cities (New York, San Francisco, London, Tokyo, Sydney), the limit is automatically increased to $350/night. No additional approval is needed. For other locations where rates are unusually high (e.g., during a major conference), request a per-trip exception from your manager before booking. | ||
|
|
||
| **Q: Can I stay with friends/family instead and get a per-diem?** | ||
| A: No. Contoso reimburses actual lodging costs only, not per-diems. | ||
|
|
||
| ## Subscriptions and Software | ||
|
|
||
| **Q: Can I expense a personal productivity tool?** | ||
| A: Software must be directly related to your job function. Tools like IDE licenses, design software, or project management apps are reimbursable. General productivity apps (note-taking, personal calendar) are not, unless your manager confirms a business need in writing. | ||
|
|
||
| **Q: What about annual subscriptions?** | ||
| A: Annual subscriptions over $200 require manager approval before purchase. Submit the approval email with your expense report. | ||
|
|
||
| ## Receipts and Documentation | ||
|
|
||
| **Q: My receipt is faded/damaged. What do I do?** | ||
| A: Try to obtain a duplicate from the vendor. If not possible, submit a Lost Receipt Affidavit (available from the Finance SharePoint site). You're limited to 2 affidavits per quarter. | ||
|
|
||
| **Q: Do I need a receipt for parking meters or tolls?** | ||
| A: For amounts under $15, no receipt is required — just note the date, location, and amount. For $15 and above, a receipt or bank/credit card statement excerpt is required. | ||
|
|
||
| ## Approval and Reimbursement | ||
|
|
||
| **Q: My manager is on leave. Who approves my report?** | ||
| A: Expense reports can be approved by your skip-level manager or any manager designated as an alternate approver in the expense system. | ||
|
|
||
| **Q: Can I submit expenses from a previous quarter?** | ||
| A: The standard 30-day window applies. Expenses older than 30 days require a written explanation and VP approval. Expenses older than 90 days are not reimbursable except in extraordinary circumstances (extended leave, medical emergency) with CFO approval. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| # AgentSkills Samples | ||
|
|
||
| Samples demonstrating Agent Skills capabilities. | ||
|
|
||
| | Sample | Description | | ||
| |--------|-------------| | ||
| | [Agent_Step01_BasicSkills](Agent_Step01_BasicSkills/) | Using Agent Skills with a ChatClientAgent, including progressive disclosure and skill resources | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| // Copyright (c) Microsoft. All rights reserved. | ||
|
|
||
| using System.Collections.Generic; | ||
| using Microsoft.Shared.Diagnostics; | ||
|
|
||
| namespace Microsoft.Agents.AI; | ||
|
|
||
| /// <summary> | ||
| /// Represents a loaded Agent Skill discovered from a filesystem directory. | ||
| /// </summary> | ||
| /// <remarks> | ||
| /// Each skill is backed by a <c>SKILL.md</c> file containing YAML frontmatter (name and description) | ||
| /// and a markdown body with instructions. Resource files referenced in the body are validated at | ||
| /// discovery time and read from disk on demand. | ||
| /// </remarks> | ||
| internal sealed class FileAgentSkill | ||
| { | ||
| /// <summary> | ||
| /// Initializes a new instance of the <see cref="FileAgentSkill"/> class. | ||
| /// </summary> | ||
| /// <param name="frontmatter">Parsed YAML frontmatter (name and description).</param> | ||
| /// <param name="body">The SKILL.md content after the closing <c>---</c> delimiter.</param> | ||
| /// <param name="sourcePath">Absolute path to the directory containing this skill.</param> | ||
| /// <param name="resourceNames">Relative paths of resource files referenced in the skill body.</param> | ||
| public FileAgentSkill( | ||
| SkillFrontmatter frontmatter, | ||
| string body, | ||
| string sourcePath, | ||
| IReadOnlyList<string>? resourceNames = null) | ||
| { | ||
| this.Frontmatter = Throw.IfNull(frontmatter); | ||
| this.Body = Throw.IfNull(body); | ||
| this.SourcePath = Throw.IfNullOrWhitespace(sourcePath); | ||
| this.ResourceNames = resourceNames ?? []; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Gets the parsed YAML frontmatter (name and description). | ||
| /// </summary> | ||
| public SkillFrontmatter Frontmatter { get; } | ||
|
|
||
| /// <summary> | ||
| /// Gets the SKILL.md body content (without the YAML frontmatter). | ||
| /// </summary> | ||
| public string Body { get; } | ||
|
|
||
| /// <summary> | ||
| /// Gets the directory path where the skill was discovered. | ||
| /// </summary> | ||
| public string SourcePath { get; } | ||
|
|
||
| /// <summary> | ||
| /// Gets the relative paths of resource files referenced in the skill body (e.g., "references/FAQ.md"). | ||
| /// </summary> | ||
| public IReadOnlyList<string> ResourceNames { get; } | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.