Skip to content

Commit 7ba636d

Browse files
SergeyMenshykhCopilotrogerbarreto
authored
.NET: Support Agent Skills (#4122)
* support agent skills * make the new agent skill provider experimental * Fix file encoding: add UTF-8 BOM to .cs files Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix final newline and simplify new expressions Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix broken links in Agent Skills sample README Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add null check for skillPaths parameter Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Normalize references * normilize skill path * address comments regarding symlink check * address comments * fix failing test + regex improvements * small optimizations and improvments * address pr review comments * Update dotnet/src/Microsoft.Agents.AI/Skills/FileAgentSkillsProvider.cs Co-authored-by: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com> * address pr review comments * address pr review comments --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com>
1 parent 44aec20 commit 7ba636d

18 files changed

Lines changed: 1776 additions & 1 deletion

File tree

dotnet/agent-framework-dotnet.slnx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,10 @@
9696
<Project Path="samples/GettingStarted/Agents/Agent_Step19_Declarative/Agent_Step19_Declarative.csproj" />
9797
<Project Path="samples/GettingStarted/Agents/Agent_Step20_AdditionalAIContext/Agent_Step20_AdditionalAIContext.csproj" />
9898
</Folder>
99+
<Folder Name="/Samples/GettingStarted/AgentSkills/">
100+
<File Path="samples/GettingStarted/AgentSkills/README.md" />
101+
<Project Path="samples/GettingStarted/AgentSkills/Agent_Step01_BasicSkills/Agent_Step01_BasicSkills.csproj" />
102+
</Folder>
99103
<Folder Name="/Samples/GettingStarted/DeclarativeAgents/">
100104
<Project Path="samples/GettingStarted/DeclarativeAgents/ChatClient/DeclarativeChatClientAgents.csproj" />
101105
</Folder>
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFrameworks>net10.0</TargetFrameworks>
6+
7+
<Nullable>enable</Nullable>
8+
<ImplicitUsings>enable</ImplicitUsings>
9+
<NoWarn>$(NoWarn);MAAI001</NoWarn>
10+
</PropertyGroup>
11+
12+
<ItemGroup>
13+
<PackageReference Include="Azure.AI.OpenAI" />
14+
<PackageReference Include="Azure.Identity" />
15+
</ItemGroup>
16+
17+
<ItemGroup>
18+
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.OpenAI\Microsoft.Agents.AI.OpenAI.csproj" />
19+
</ItemGroup>
20+
21+
<!-- Copy skills directory to output -->
22+
<ItemGroup>
23+
<None Include="skills\**\*.*">
24+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
25+
</None>
26+
</ItemGroup>
27+
28+
</Project>
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
3+
// This sample demonstrates how to use Agent Skills with a ChatClientAgent.
4+
// Agent Skills are modular packages of instructions and resources that extend an agent's capabilities.
5+
// Skills follow the progressive disclosure pattern: advertise -> load -> read resources.
6+
//
7+
// This sample includes the expense-report skill:
8+
// - Policy-based expense filing with references and assets
9+
10+
using Azure.AI.OpenAI;
11+
using Azure.Identity;
12+
using Microsoft.Agents.AI;
13+
using OpenAI.Responses;
14+
15+
// --- Configuration ---
16+
string endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT")
17+
?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
18+
string deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
19+
20+
// --- Skills Provider ---
21+
// Discovers skills from the 'skills' directory and makes them available to the agent
22+
var skillsProvider = new FileAgentSkillsProvider(skillPath: Path.Combine(AppContext.BaseDirectory, "skills"));
23+
24+
// --- Agent Setup ---
25+
AIAgent agent = new AzureOpenAIClient(new Uri(endpoint), new DefaultAzureCredential())
26+
.GetResponsesClient(deploymentName)
27+
.AsAIAgent(new ChatClientAgentOptions
28+
{
29+
Name = "SkillsAgent",
30+
ChatOptions = new()
31+
{
32+
Instructions = "You are a helpful assistant.",
33+
},
34+
AIContextProviders = [skillsProvider],
35+
});
36+
37+
// --- Example 1: Expense policy question (loads FAQ resource) ---
38+
Console.WriteLine("Example 1: Checking expense policy FAQ");
39+
Console.WriteLine("---------------------------------------");
40+
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.");
41+
Console.WriteLine($"Agent: {response1.Text}\n");
42+
43+
// --- Example 2: Filing an expense report (multi-turn with template asset) ---
44+
Console.WriteLine("Example 2: Filing an expense report");
45+
Console.WriteLine("---------------------------------------");
46+
AgentSession session = await agent.CreateSessionAsync();
47+
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.",
48+
session);
49+
Console.WriteLine($"Agent: {response2.Text}\n");
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Agent Skills Sample
2+
3+
This sample demonstrates how to use **Agent Skills** with a `ChatClientAgent` in the Microsoft Agent Framework.
4+
5+
## What are Agent Skills?
6+
7+
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:
8+
9+
1. **Advertise**: Skills are advertised with name + description (~100 tokens per skill)
10+
2. **Load**: Full instructions are loaded on-demand via `load_skill` tool
11+
3. **Resources**: References and other files loaded via `read_skill_resource` tool
12+
13+
## Skills Included
14+
15+
### expense-report
16+
Policy-based expense filing with spending limits, receipt requirements, and approval workflows.
17+
- `references/POLICY_FAQ.md` — Detailed expense policy Q&A
18+
- `assets/expense-report-template.md` — Submission template
19+
20+
## Project Structure
21+
22+
```
23+
Agent_Step01_BasicSkills/
24+
├── Program.cs
25+
├── Agent_Step01_BasicSkills.csproj
26+
└── skills/
27+
└── expense-report/
28+
├── SKILL.md
29+
├── references/
30+
│ └── POLICY_FAQ.md
31+
└── assets/
32+
└── expense-report-template.md
33+
```
34+
35+
## Running the Sample
36+
37+
### Prerequisites
38+
- .NET 10.0 SDK
39+
- Azure OpenAI endpoint with a deployed model
40+
41+
### Setup
42+
1. Set environment variables:
43+
```bash
44+
export AZURE_OPENAI_ENDPOINT="https://your-endpoint.openai.azure.com/"
45+
export AZURE_OPENAI_DEPLOYMENT_NAME="gpt-4o-mini"
46+
```
47+
48+
2. Run the sample:
49+
```bash
50+
dotnet run
51+
```
52+
53+
### Examples
54+
55+
The sample runs two examples:
56+
57+
1. **Expense policy FAQ** — Asks about tip reimbursement; the agent loads the expense-report skill and reads the FAQ resource
58+
2. **Filing an expense report** — Multi-turn conversation to draft an expense report using the template asset
59+
60+
## Learn More
61+
62+
- [Agent Skills Specification](https://agentskills.io/)
63+
- [Microsoft Agent Framework Documentation](../../../../../docs/)
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
---
2+
name: expense-report
3+
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.
4+
metadata:
5+
author: contoso-finance
6+
version: "2.1"
7+
---
8+
9+
# Expense Report
10+
11+
## Categories and Limits
12+
13+
| Category | Limit | Receipt | Approval |
14+
|---|---|---|---|
15+
| Meals — solo | $50/day | >$25 | No |
16+
| Meals — team/client | $75/person | Always | Manager if >$200 total |
17+
| Lodging | $250/night | Always | Manager if >3 nights |
18+
| Ground transport | $100/day | >$15 | No |
19+
| Airfare | Economy | Always | Manager; VP if >$1,500 |
20+
| Conference/training | $2,000/event | Always | Manager + L&D |
21+
| Office supplies | $100 | Yes | No |
22+
| Software/subscriptions | $50/month | Yes | Manager if >$200/year |
23+
24+
## Filing Process
25+
26+
1. Collect receipts — must show vendor, date, amount, payment method.
27+
2. Categorize per table above.
28+
3. Use template: [assets/expense-report-template.md](assets/expense-report-template.md).
29+
4. For client/team meals: list attendee names and business purpose.
30+
5. Submit — auto-approved if <$500; manager if $500–$2,000; VP if >$2,000.
31+
6. Reimbursement: 10 business days via direct deposit.
32+
33+
## Policy Rules
34+
35+
- Submit within 30 days of transaction.
36+
- Alcohol is never reimbursable.
37+
- Foreign currency: convert to USD at transaction-date rate; note original currency and amount.
38+
- Mixed personal/business travel: only business portion reimbursable; provide comparison quotes.
39+
- Lost receipts (>$25): file Lost Receipt Affidavit from Finance. Max 2 per quarter.
40+
- 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.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Expense Report Template
2+
3+
| Date | Category | Vendor | Description | Amount (USD) | Original Currency | Original Amount | Attendees | Business Purpose | Receipt Attached |
4+
|------|----------|--------|-------------|--------------|-------------------|-----------------|-----------|------------------|------------------|
5+
| | | | | | | | | | Yes or No |
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Expense Policy — Frequently Asked Questions
2+
3+
## Meals
4+
5+
**Q: Can I expense coffee or snacks during the workday?**
6+
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.
7+
8+
**Q: What if a team dinner exceeds the per-person limit?**
9+
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.
10+
11+
**Q: Do I need to list every attendee?**
12+
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.
13+
14+
## Travel
15+
16+
**Q: Can I book a premium economy or business class flight?**
17+
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.
18+
19+
**Q: What about ride-sharing (Uber/Lyft) vs. rental cars?**
20+
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.
21+
22+
**Q: Are tips reimbursable?**
23+
A: Tips up to 20% are reimbursable for meals, taxi/ride-share, and hotel housekeeping. Tips above 20% require justification.
24+
25+
## Lodging
26+
27+
**Q: What if the $250/night limit isn't enough for the city I'm visiting?**
28+
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.
29+
30+
**Q: Can I stay with friends/family instead and get a per-diem?**
31+
A: No. Contoso reimburses actual lodging costs only, not per-diems.
32+
33+
## Subscriptions and Software
34+
35+
**Q: Can I expense a personal productivity tool?**
36+
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.
37+
38+
**Q: What about annual subscriptions?**
39+
A: Annual subscriptions over $200 require manager approval before purchase. Submit the approval email with your expense report.
40+
41+
## Receipts and Documentation
42+
43+
**Q: My receipt is faded/damaged. What do I do?**
44+
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.
45+
46+
**Q: Do I need a receipt for parking meters or tolls?**
47+
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.
48+
49+
## Approval and Reimbursement
50+
51+
**Q: My manager is on leave. Who approves my report?**
52+
A: Expense reports can be approved by your skip-level manager or any manager designated as an alternate approver in the expense system.
53+
54+
**Q: Can I submit expenses from a previous quarter?**
55+
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.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# AgentSkills Samples
2+
3+
Samples demonstrating Agent Skills capabilities.
4+
5+
| Sample | Description |
6+
|--------|-------------|
7+
| [Agent_Step01_BasicSkills](Agent_Step01_BasicSkills/) | Using Agent Skills with a ChatClientAgent, including progressive disclosure and skill resources |

dotnet/samples/GettingStarted/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@ of the agent framework.
1818
|[Agent With Anthropic](./AgentWithAnthropic/README.md)|Getting started with agents using Anthropic Claude|
1919
|[Workflow](./Workflows/README.md)|Getting started with Workflow|
2020
|[Model Context Protocol](./ModelContextProtocol/README.md)|Getting started with Model Context Protocol|
21+
|[Agent Skills](./AgentSkills/README.md)|Getting started with Agent Skills|

dotnet/src/Microsoft.Agents.AI/Microsoft.Agents.AI.csproj

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22

33
<PropertyGroup>
44
<IsReleaseCandidate>true</IsReleaseCandidate>
5-
<NoWarn>$(NoWarn);MEAI001</NoWarn>
5+
<NoWarn>$(NoWarn);MEAI001;MAAI001</NoWarn>
66
</PropertyGroup>
77

88
<PropertyGroup>
99
<InjectSharedThrow>true</InjectSharedThrow>
10+
<InjectSharedDiagnosticIds>true</InjectSharedDiagnosticIds>
1011
<InjectDiagnosticClassesOnLegacy>true</InjectDiagnosticClassesOnLegacy>
12+
<InjectExperimentalAttributeOnLegacy>true</InjectExperimentalAttributeOnLegacy>
1113
<InjectTrimAttributesOnLegacy>true</InjectTrimAttributesOnLegacy>
1214
<InjectIsExternalInitOnLegacy>true</InjectIsExternalInitOnLegacy>
1315
</PropertyGroup>

0 commit comments

Comments
 (0)