From 0c810ce434f06561bd0515e80f06962934cb8b33 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 29 Jan 2026 09:59:44 +0000 Subject: [PATCH 1/6] Initial plan From 74ce68fe0ca735b56b3dccd6481af64ab6e1bf14 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 29 Jan 2026 10:24:18 +0000 Subject: [PATCH 2/6] Add Claude Skills sample and integration tests for Anthropic - Add Agent_Anthropic_Step04_UsingSkills sample demonstrating pptx skill usage - Add integration tests for skills functionality - Update README.md with new sample reference - Update solution file to include new sample project Co-authored-by: rogerbarreto <19890735+rogerbarreto@users.noreply.github.com> --- dotnet/agent-framework-dotnet.slnx | 1 + .../Agent_Anthropic_Step04_UsingSkills.csproj | 15 +++ .../Program.cs | 82 ++++++++++++++++ .../README.md | 89 +++++++++++++++++ .../AgentWithAnthropic/README.md | 1 + .../AnthropicSkillsIntegrationTests.cs | 98 +++++++++++++++++++ 6 files changed, 286 insertions(+) create mode 100644 dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/Agent_Anthropic_Step04_UsingSkills.csproj create mode 100644 dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/Program.cs create mode 100644 dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/README.md create mode 100644 dotnet/tests/AnthropicChatCompletion.IntegrationTests/AnthropicSkillsIntegrationTests.cs diff --git a/dotnet/agent-framework-dotnet.slnx b/dotnet/agent-framework-dotnet.slnx index 280632bc4b..5415de9dc0 100644 --- a/dotnet/agent-framework-dotnet.slnx +++ b/dotnet/agent-framework-dotnet.slnx @@ -131,6 +131,7 @@ + diff --git a/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/Agent_Anthropic_Step04_UsingSkills.csproj b/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/Agent_Anthropic_Step04_UsingSkills.csproj new file mode 100644 index 0000000000..09359c5e78 --- /dev/null +++ b/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/Agent_Anthropic_Step04_UsingSkills.csproj @@ -0,0 +1,15 @@ + + + + Exe + net10.0 + + enable + enable + + + + + + + diff --git a/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/Program.cs b/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/Program.cs new file mode 100644 index 0000000000..d423dcc83e --- /dev/null +++ b/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/Program.cs @@ -0,0 +1,82 @@ +// Copyright (c) Microsoft. All rights reserved. + +// This sample demonstrates how to use Anthropic-managed Skills with an AI agent. +// Skills are pre-built capabilities provided by Anthropic that can be used with the Claude API. +// This sample shows how to use the pptx skill to create PowerPoint presentations. + +using Anthropic; +using Anthropic.Models.Beta; +using Anthropic.Models.Beta.Messages; +using Anthropic.Services; +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; + +string apiKey = Environment.GetEnvironmentVariable("ANTHROPIC_API_KEY") ?? throw new InvalidOperationException("ANTHROPIC_API_KEY is not set."); +string model = Environment.GetEnvironmentVariable("ANTHROPIC_MODEL") ?? "claude-sonnet-4-20250514"; + +// Define the pptx skill configuration once to avoid duplication +BetaSkillParams pptxSkill = new() +{ + Type = BetaSkillParamsType.Anthropic, + SkillID = "pptx", + Version = "latest" +}; + +// Create an agent with the pptx skill enabled using the AsAITool extension method. +// Skills require the beta API and specific beta flags to be enabled. +AIAgent agent = new AnthropicClient { APIKey = apiKey } + .Beta + .AsAIAgent( + model: model, + instructions: "You are a helpful agent for creating PowerPoint presentations.", + tools: [pptxSkill.AsAITool()], + clientFactory: (chatClient) => chatClient + .AsBuilder() + .ConfigureOptions( + options => options.RawRepresentationFactory = (_) => new MessageCreateParams() + { + Model = options.ModelId ?? model, + MaxTokens = options.MaxOutputTokens ?? 20000, + Messages = [], + // Enable extended thinking for better reasoning when creating presentations + Thinking = new BetaThinkingConfigParam(new BetaThinkingConfigEnabled(budgetTokens: 10000)), + // Enable the skills-2025-10-02 beta flag for skills support + Betas = [AnthropicBeta.Skills2025_10_02], + // Configure the container with the pptx skill + Container = new BetaContainerParams() { Skills = [pptxSkill] } + }) + .Build()); + +Console.WriteLine("Creating a presentation about renewable energy...\n"); + +// Run the agent with a request to create a presentation +AgentResponse response = await agent.RunAsync("Create a simple 3-slide presentation about renewable energy sources. Include a title slide, a slide about solar energy, and a slide about wind energy."); + +Console.WriteLine("#### Agent Response ####"); +Console.WriteLine(response.Text); + +// Display any reasoning/thinking content +List reasoningContents = response.Messages.SelectMany(m => m.Contents.OfType()).ToList(); +if (reasoningContents.Count > 0) +{ + Console.WriteLine("\n#### Agent Reasoning ####"); + Console.WriteLine($"\e[92m{string.Join("\n", reasoningContents.Select(c => c.Text))}\e[0m"); +} + +// Display any hosted file content that was generated +List dataContents = response.Messages.SelectMany(m => m.Contents.OfType()).ToList(); +if (dataContents.Count > 0) +{ + Console.WriteLine("\n#### Generated Files ####"); + foreach (DataContent content in dataContents) + { + Console.WriteLine($"- MediaType: {content.MediaType}, HasData: {!content.Data.IsEmpty}"); + } +} + +Console.WriteLine("\nToken usage:"); +Console.WriteLine($"Input: {response.Usage?.InputTokenCount}, Output: {response.Usage?.OutputTokenCount}"); +if (response.Usage?.AdditionalCounts is not null) +{ + Console.WriteLine($"Additional: {string.Join(", ", response.Usage.AdditionalCounts)}"); +} diff --git a/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/README.md b/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/README.md new file mode 100644 index 0000000000..beb50925b5 --- /dev/null +++ b/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/README.md @@ -0,0 +1,89 @@ +# Using Anthropic Skills with agents + +This sample demonstrates how to use Anthropic-managed Skills with AI agents. Skills are pre-built capabilities provided by Anthropic that can be used with the Claude API. + +## What this sample demonstrates + +- Creating an AI agent with Anthropic Claude Skills support +- Using the `BetaSkillParams.AsAITool()` extension method to add skills as tools +- Configuring beta flags required for skills +- Using the pptx skill to create PowerPoint presentations +- Handling agent responses with generated content + +## Prerequisites + +Before you begin, ensure you have the following prerequisites: + +- .NET 10.0 SDK or later +- Anthropic API key configured +- Access to Anthropic Claude models with Skills support + +**Note**: This sample uses Anthropic Claude models with Skills. Skills are a beta feature and require specific beta flags. For more information, see [Anthropic documentation](https://docs.anthropic.com/). + +Set the following environment variables: + +```powershell +$env:ANTHROPIC_API_KEY="your-anthropic-api-key" # Replace with your Anthropic API key +$env:ANTHROPIC_MODEL="your-anthropic-model" # Replace with your Anthropic model (e.g., claude-sonnet-4-20250514) +``` + +## Run the sample + +Navigate to the AgentWithAnthropic sample directory and run: + +```powershell +cd dotnet\samples\GettingStarted\AgentWithAnthropic +dotnet run --project .\Agent_Anthropic_Step04_UsingSkills +``` + +## Available Anthropic Skills + +Anthropic provides several managed skills that can be used with the Claude API: + +- `pptx` - Create PowerPoint presentations +- Other skills may be available depending on your API access + +You can list available skills using the Anthropic SDK: + +```csharp +var skills = await client.Beta.Skills.List( + new SkillListParams { Source = "anthropic", Betas = [AnthropicBeta.Skills2025_10_02] }); +foreach (var skill in skills.Data) +{ + Console.WriteLine($"{skill.Source}: {skill.ID} (version: {skill.LatestVersion})"); +} +``` + +## Expected behavior + +The sample will: + +1. Create an agent with Anthropic Claude Skills enabled (pptx skill) +2. Run the agent with a request to create a presentation +3. Display the agent's response text +4. Display any reasoning/thinking content +5. Display information about any generated files +6. Display token usage statistics + +## Code highlights + +The key part of this sample is defining the skill configuration and adding it as an AI tool: + +```csharp +// Define the pptx skill configuration once to avoid duplication +BetaSkillParams pptxSkill = new() +{ + Type = BetaSkillParamsType.Anthropic, + SkillID = "pptx", + Version = "latest" +}; + +// Add to tools array +tools: [pptxSkill.AsAITool()] +``` + +And configuring the container with skills in the raw representation: + +```csharp +Container = new BetaContainerParams() { Skills = [pptxSkill] } +``` diff --git a/dotnet/samples/GettingStarted/AgentWithAnthropic/README.md b/dotnet/samples/GettingStarted/AgentWithAnthropic/README.md index 44c15b384b..345c25142f 100644 --- a/dotnet/samples/GettingStarted/AgentWithAnthropic/README.md +++ b/dotnet/samples/GettingStarted/AgentWithAnthropic/README.md @@ -29,6 +29,7 @@ To use Anthropic with Azure Foundry, you can check the sample [AgentProviders/Ag |[Running a simple agent](./Agent_Anthropic_Step01_Running/)|This sample demonstrates how to create and run a basic agent with Anthropic Claude| |[Using reasoning with an agent](./Agent_Anthropic_Step02_Reasoning/)|This sample demonstrates how to use extended thinking/reasoning capabilities with Anthropic Claude agents| |[Using function tools with an agent](./Agent_Anthropic_Step03_UsingFunctionTools/)|This sample demonstrates how to use function tools with an Anthropic Claude agent| +|[Using Skills with an agent](./Agent_Anthropic_Step04_UsingSkills/)|This sample demonstrates how to use Anthropic-managed Skills (e.g., pptx) with an Anthropic Claude agent| ## Running the samples from the console diff --git a/dotnet/tests/AnthropicChatCompletion.IntegrationTests/AnthropicSkillsIntegrationTests.cs b/dotnet/tests/AnthropicChatCompletion.IntegrationTests/AnthropicSkillsIntegrationTests.cs new file mode 100644 index 0000000000..35785d317a --- /dev/null +++ b/dotnet/tests/AnthropicChatCompletion.IntegrationTests/AnthropicSkillsIntegrationTests.cs @@ -0,0 +1,98 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System.Threading.Tasks; +using AgentConformance.IntegrationTests.Support; +using Anthropic; +using Anthropic.Models.Beta; +using Anthropic.Models.Beta.Messages; +using Anthropic.Models.Beta.Skills; +using Anthropic.Services; +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; +using Shared.IntegrationTests; + +namespace AnthropicChatCompletion.IntegrationTests; + +/// +/// Integration tests for Anthropic Skills functionality. +/// These tests are designed to be run locally with a valid Anthropic API key. +/// +public sealed class AnthropicSkillsIntegrationTests +{ + // All tests for Anthropic are intended to be ran locally as the CI pipeline for Anthropic is not setup. + private const string SkipReason = "Integrations tests for local execution only"; + + private static readonly AnthropicConfiguration s_config = TestConfiguration.LoadSection(); + + [Fact(Skip = SkipReason)] + public async Task CreateAgentWithPptxSkillAsync() + { + // Arrange + AnthropicClient anthropicClient = new() { APIKey = s_config.ApiKey }; + string model = s_config.ChatModelId; + + // Define the pptx skill configuration once to avoid duplication + BetaSkillParams pptxSkill = new() + { + Type = BetaSkillParamsType.Anthropic, + SkillID = "pptx", + Version = "latest" + }; + + // Create an agent with the pptx skill using AsAITool extension method + ChatClientAgent agent = anthropicClient.Beta.AsAIAgent( + model: model, + instructions: "You are a helpful agent for creating PowerPoint presentations.", + tools: [pptxSkill.AsAITool()], + clientFactory: (chatClient) => chatClient + .AsBuilder() + .ConfigureOptions( + options => options.RawRepresentationFactory = (_) => new MessageCreateParams() + { + Model = options.ModelId ?? model, + MaxTokens = options.MaxOutputTokens ?? 20000, + Messages = [], + Thinking = new BetaThinkingConfigParam(new BetaThinkingConfigEnabled(budgetTokens: 10000)), + Betas = [AnthropicBeta.Skills2025_10_02], + Container = new BetaContainerParams() { Skills = [pptxSkill] } + }) + .Build()); + + // Act + AgentResponse response = await agent.RunAsync( + "Create a simple 2-slide presentation: a title slide and one content slide about AI."); + + // Assert + Assert.NotNull(response); + Assert.NotNull(response.Text); + Assert.NotEmpty(response.Text); + } + + [Fact(Skip = SkipReason)] + public async Task ListAnthropicManagedSkillsAsync() + { + // Arrange + AnthropicClient anthropicClient = new() { APIKey = s_config.ApiKey }; + + // Act - List available Anthropic-managed skills + SkillListPageResponse skills = await anthropicClient.Beta.Skills.List( + new SkillListParams { Source = "anthropic", Betas = [AnthropicBeta.Skills2025_10_02] }); + + // Assert + Assert.NotNull(skills); + Assert.NotNull(skills.Data); + + // Check that the pptx skill is available + bool hasPptxSkill = false; + foreach (var skill in skills.Data) + { + if (skill.ID == "pptx") + { + hasPptxSkill = true; + break; + } + } + + Assert.True(hasPptxSkill, "Expected pptx skill to be available"); + } +} From 8ba1f324475693a0787064189e8f435f248d51aa Mon Sep 17 00:00:00 2001 From: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com> Date: Thu, 29 Jan 2026 14:00:21 +0000 Subject: [PATCH 3/6] Simplify Anthropic Skills sample with AsAITool and add file download --- .../Program.cs | 109 +++++++++++++----- .../README.md | 64 +++++++--- .../AnthropicSkillsIntegrationTests.cs | 20 +--- 3 files changed, 128 insertions(+), 65 deletions(-) diff --git a/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/Program.cs b/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/Program.cs index d423dcc83e..7f78a04ebb 100644 --- a/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/Program.cs +++ b/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/Program.cs @@ -2,19 +2,49 @@ // This sample demonstrates how to use Anthropic-managed Skills with an AI agent. // Skills are pre-built capabilities provided by Anthropic that can be used with the Claude API. -// This sample shows how to use the pptx skill to create PowerPoint presentations. +// This sample shows how to: +// 1. List available Anthropic-managed skills +// 2. Use the pptx skill to create PowerPoint presentations +// 3. Download and save generated files using Anthropic; +using Anthropic.Core; using Anthropic.Models.Beta; +using Anthropic.Models.Beta.Files; using Anthropic.Models.Beta.Messages; +using Anthropic.Models.Beta.Skills; using Anthropic.Services; using Microsoft.Agents.AI; using Microsoft.Extensions.AI; string apiKey = Environment.GetEnvironmentVariable("ANTHROPIC_API_KEY") ?? throw new InvalidOperationException("ANTHROPIC_API_KEY is not set."); -string model = Environment.GetEnvironmentVariable("ANTHROPIC_MODEL") ?? "claude-sonnet-4-20250514"; +// Skills require Claude 4.5 models (Sonnet 4.5, Haiku 4.5, or Opus 4.5) +string model = Environment.GetEnvironmentVariable("ANTHROPIC_MODEL") ?? "claude-sonnet-4-5-20250929"; -// Define the pptx skill configuration once to avoid duplication +// Create the Anthropic client +AnthropicClient anthropicClient = new() { APIKey = apiKey }; + +// List available Anthropic-managed skills (optional - API may not be available in all regions) +Console.WriteLine("Available Anthropic-managed skills:"); +try +{ + SkillListPageResponse skills = await anthropicClient.Beta.Skills.List( + new SkillListParams { Source = "anthropic", Betas = [AnthropicBeta.Skills2025_10_02] }); + + foreach (var skill in skills.Data) + { + Console.WriteLine($" {skill.Source}: {skill.ID} (version: {skill.LatestVersion})"); + } +} +catch (Exception ex) +{ + Console.WriteLine($" (Skills listing not available: {ex.Message})"); +} + +Console.WriteLine(); + +// Define the pptx skill - the SDK handles all beta flags and container configuration automatically +// when using AsAITool(), so no manual RawRepresentationFactory configuration is needed. BetaSkillParams pptxSkill = new() { Type = BetaSkillParamsType.Anthropic, @@ -22,30 +52,27 @@ Version = "latest" }; -// Create an agent with the pptx skill enabled using the AsAITool extension method. -// Skills require the beta API and specific beta flags to be enabled. -AIAgent agent = new AnthropicClient { APIKey = apiKey } - .Beta - .AsAIAgent( - model: model, - instructions: "You are a helpful agent for creating PowerPoint presentations.", - tools: [pptxSkill.AsAITool()], - clientFactory: (chatClient) => chatClient - .AsBuilder() - .ConfigureOptions( - options => options.RawRepresentationFactory = (_) => new MessageCreateParams() - { - Model = options.ModelId ?? model, - MaxTokens = options.MaxOutputTokens ?? 20000, - Messages = [], - // Enable extended thinking for better reasoning when creating presentations - Thinking = new BetaThinkingConfigParam(new BetaThinkingConfigEnabled(budgetTokens: 10000)), - // Enable the skills-2025-10-02 beta flag for skills support - Betas = [AnthropicBeta.Skills2025_10_02], - // Configure the container with the pptx skill - Container = new BetaContainerParams() { Skills = [pptxSkill] } - }) - .Build()); +// Create an agent with the pptx skill enabled. +// Skills require extended thinking and higher max tokens for complex file generation. +// The SDK's AsAITool() handles beta flags and container config automatically. +ChatClientAgent agent = anthropicClient.Beta.AsAIAgent( + model: model, + instructions: "You are a helpful agent for creating PowerPoint presentations.", + tools: [pptxSkill.AsAITool()], + clientFactory: (chatClient) => chatClient + .AsBuilder() + .ConfigureOptions(options => + { + options.RawRepresentationFactory = (_) => new MessageCreateParams() + { + Model = model, + MaxTokens = 20000, + Messages = [], + Thinking = new BetaThinkingConfigParam( + new BetaThinkingConfigEnabled(budgetTokens: 10000)) + }; + }) + .Build()); Console.WriteLine("Creating a presentation about renewable energy...\n"); @@ -63,14 +90,32 @@ Console.WriteLine($"\e[92m{string.Join("\n", reasoningContents.Select(c => c.Text))}\e[0m"); } -// Display any hosted file content that was generated -List dataContents = response.Messages.SelectMany(m => m.Contents.OfType()).ToList(); -if (dataContents.Count > 0) +// Collect generated files from CodeInterpreterToolResultContent outputs +List hostedFiles = response.Messages + .SelectMany(m => m.Contents.OfType()) + .Where(c => c.Outputs is not null) + .SelectMany(c => c.Outputs!.OfType()) + .ToList(); + +if (hostedFiles.Count > 0) { Console.WriteLine("\n#### Generated Files ####"); - foreach (DataContent content in dataContents) + foreach (HostedFileContent file in hostedFiles) { - Console.WriteLine($"- MediaType: {content.MediaType}, HasData: {!content.Data.IsEmpty}"); + Console.WriteLine($" FileId: {file.FileId}"); + + // Download the file using the Anthropic Files API + using HttpResponse fileResponse = await anthropicClient.Beta.Files.Download( + file.FileId, + new FileDownloadParams { Betas = ["files-api-2025-04-14"] }); + + // Save the file to disk + string fileName = $"presentation_{file.FileId.Substring(0, 8)}.pptx"; + using FileStream fileStream = File.Create(fileName); + Stream contentStream = await fileResponse.ReadAsStream(); + await contentStream.CopyToAsync(fileStream); + + Console.WriteLine($" Saved to: {fileName}"); } } diff --git a/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/README.md b/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/README.md index beb50925b5..826437f22b 100644 --- a/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/README.md +++ b/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/README.md @@ -4,10 +4,10 @@ This sample demonstrates how to use Anthropic-managed Skills with AI agents. Ski ## What this sample demonstrates -- Creating an AI agent with Anthropic Claude Skills support -- Using the `BetaSkillParams.AsAITool()` extension method to add skills as tools -- Configuring beta flags required for skills +- Listing available Anthropic-managed skills +- Creating an AI agent with Anthropic Claude Skills support using the simplified `AsAITool()` approach - Using the pptx skill to create PowerPoint presentations +- Downloading and saving generated files to disk - Handling agent responses with generated content ## Prerequisites @@ -18,7 +18,7 @@ Before you begin, ensure you have the following prerequisites: - Anthropic API key configured - Access to Anthropic Claude models with Skills support -**Note**: This sample uses Anthropic Claude models with Skills. Skills are a beta feature and require specific beta flags. For more information, see [Anthropic documentation](https://docs.anthropic.com/). +**Note**: This sample uses Anthropic Claude models with Skills. Skills are a beta feature. For more information, see [Anthropic documentation](https://docs.anthropic.com/). Set the following environment variables: @@ -41,13 +41,16 @@ dotnet run --project .\Agent_Anthropic_Step04_UsingSkills Anthropic provides several managed skills that can be used with the Claude API: - `pptx` - Create PowerPoint presentations -- Other skills may be available depending on your API access +- `xlsx` - Create Excel spreadsheets +- `docx` - Create Word documents +- `pdf` - Create and analyze PDF documents You can list available skills using the Anthropic SDK: ```csharp -var skills = await client.Beta.Skills.List( +SkillListPageResponse skills = await anthropicClient.Beta.Skills.List( new SkillListParams { Source = "anthropic", Betas = [AnthropicBeta.Skills2025_10_02] }); + foreach (var skill in skills.Data) { Console.WriteLine($"{skill.Source}: {skill.ID} (version: {skill.LatestVersion})"); @@ -58,19 +61,21 @@ foreach (var skill in skills.Data) The sample will: -1. Create an agent with Anthropic Claude Skills enabled (pptx skill) -2. Run the agent with a request to create a presentation -3. Display the agent's response text -4. Display any reasoning/thinking content -5. Display information about any generated files +1. List all available Anthropic-managed skills +2. Create an agent with the pptx skill enabled +3. Run the agent with a request to create a presentation +4. Display the agent's response text +5. Download any generated files and save them to disk 6. Display token usage statistics ## Code highlights -The key part of this sample is defining the skill configuration and adding it as an AI tool: +### Simplified skill configuration + +The Anthropic SDK handles all beta flags and container configuration automatically when using `AsAITool()`: ```csharp -// Define the pptx skill configuration once to avoid duplication +// Define the pptx skill BetaSkillParams pptxSkill = new() { Type = BetaSkillParamsType.Anthropic, @@ -78,12 +83,37 @@ BetaSkillParams pptxSkill = new() Version = "latest" }; -// Add to tools array -tools: [pptxSkill.AsAITool()] +// Create an agent - the SDK handles beta flags automatically! +ChatClientAgent agent = anthropicClient.Beta.AsAIAgent( + model: model, + instructions: "You are a helpful agent for creating PowerPoint presentations.", + tools: [pptxSkill.AsAITool()]); ``` -And configuring the container with skills in the raw representation: +**Note**: No manual `RawRepresentationFactory`, `Betas`, or `Container` configuration is needed. The SDK automatically adds the required beta headers (`skills-2025-10-02`, `code-execution-2025-08-25`) and configures the container with the skill. + +### Handling generated files + +Generated files are returned as `HostedFileContent` within `CodeInterpreterToolResultContent`: ```csharp -Container = new BetaContainerParams() { Skills = [pptxSkill] } +// Collect generated files from response +List hostedFiles = response.Messages + .SelectMany(m => m.Contents.OfType()) + .Where(c => c.Outputs is not null) + .SelectMany(c => c.Outputs!.OfType()) + .ToList(); + +// Download and save each file +foreach (HostedFileContent file in hostedFiles) +{ + using HttpResponse fileResponse = await anthropicClient.Beta.Files.Download( + file.FileId, + new FileDownloadParams { Betas = ["files-api-2025-04-14"] }); + + string fileName = $"presentation_{file.FileId[..8]}.pptx"; + await using FileStream fileStream = File.Create(fileName); + Stream contentStream = await fileResponse.ReadAsStream(); + await contentStream.CopyToAsync(fileStream); +} ``` diff --git a/dotnet/tests/AnthropicChatCompletion.IntegrationTests/AnthropicSkillsIntegrationTests.cs b/dotnet/tests/AnthropicChatCompletion.IntegrationTests/AnthropicSkillsIntegrationTests.cs index 35785d317a..8ee73d9fb2 100644 --- a/dotnet/tests/AnthropicChatCompletion.IntegrationTests/AnthropicSkillsIntegrationTests.cs +++ b/dotnet/tests/AnthropicChatCompletion.IntegrationTests/AnthropicSkillsIntegrationTests.cs @@ -31,7 +31,7 @@ public async Task CreateAgentWithPptxSkillAsync() AnthropicClient anthropicClient = new() { APIKey = s_config.ApiKey }; string model = s_config.ChatModelId; - // Define the pptx skill configuration once to avoid duplication + // Define the pptx skill - the SDK handles all beta flags and container configuration automatically BetaSkillParams pptxSkill = new() { Type = BetaSkillParamsType.Anthropic, @@ -39,24 +39,12 @@ public async Task CreateAgentWithPptxSkillAsync() Version = "latest" }; - // Create an agent with the pptx skill using AsAITool extension method + // Create an agent with the pptx skill using simplified AsAITool() approach + // No RawRepresentationFactory or manual beta configuration needed! ChatClientAgent agent = anthropicClient.Beta.AsAIAgent( model: model, instructions: "You are a helpful agent for creating PowerPoint presentations.", - tools: [pptxSkill.AsAITool()], - clientFactory: (chatClient) => chatClient - .AsBuilder() - .ConfigureOptions( - options => options.RawRepresentationFactory = (_) => new MessageCreateParams() - { - Model = options.ModelId ?? model, - MaxTokens = options.MaxOutputTokens ?? 20000, - Messages = [], - Thinking = new BetaThinkingConfigParam(new BetaThinkingConfigEnabled(budgetTokens: 10000)), - Betas = [AnthropicBeta.Skills2025_10_02], - Container = new BetaContainerParams() { Skills = [pptxSkill] } - }) - .Build()); + tools: [pptxSkill.AsAITool()]); // Act AgentResponse response = await agent.RunAsync( From 04784f5500fd718eb0f22526794604fd0341526f Mon Sep 17 00:00:00 2001 From: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com> Date: Thu, 29 Jan 2026 14:17:12 +0000 Subject: [PATCH 4/6] Remove excessive comments from integration tests --- .../AnthropicSkillsIntegrationTests.cs | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/dotnet/tests/AnthropicChatCompletion.IntegrationTests/AnthropicSkillsIntegrationTests.cs b/dotnet/tests/AnthropicChatCompletion.IntegrationTests/AnthropicSkillsIntegrationTests.cs index 8ee73d9fb2..9d9c11f3c7 100644 --- a/dotnet/tests/AnthropicChatCompletion.IntegrationTests/AnthropicSkillsIntegrationTests.cs +++ b/dotnet/tests/AnthropicChatCompletion.IntegrationTests/AnthropicSkillsIntegrationTests.cs @@ -31,7 +31,6 @@ public async Task CreateAgentWithPptxSkillAsync() AnthropicClient anthropicClient = new() { APIKey = s_config.ApiKey }; string model = s_config.ChatModelId; - // Define the pptx skill - the SDK handles all beta flags and container configuration automatically BetaSkillParams pptxSkill = new() { Type = BetaSkillParamsType.Anthropic, @@ -39,8 +38,6 @@ public async Task CreateAgentWithPptxSkillAsync() Version = "latest" }; - // Create an agent with the pptx skill using simplified AsAITool() approach - // No RawRepresentationFactory or manual beta configuration needed! ChatClientAgent agent = anthropicClient.Beta.AsAIAgent( model: model, instructions: "You are a helpful agent for creating PowerPoint presentations.", @@ -62,25 +59,13 @@ public async Task ListAnthropicManagedSkillsAsync() // Arrange AnthropicClient anthropicClient = new() { APIKey = s_config.ApiKey }; - // Act - List available Anthropic-managed skills + // Act SkillListPageResponse skills = await anthropicClient.Beta.Skills.List( new SkillListParams { Source = "anthropic", Betas = [AnthropicBeta.Skills2025_10_02] }); // Assert Assert.NotNull(skills); Assert.NotNull(skills.Data); - - // Check that the pptx skill is available - bool hasPptxSkill = false; - foreach (var skill in skills.Data) - { - if (skill.ID == "pptx") - { - hasPptxSkill = true; - break; - } - } - - Assert.True(hasPptxSkill, "Expected pptx skill to be available"); + Assert.Contains(skills.Data, skill => skill.ID == "pptx"); } } From e732af4a462398c92bc3960c57da6bb829ae388d Mon Sep 17 00:00:00 2001 From: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com> Date: Thu, 29 Jan 2026 14:34:57 +0000 Subject: [PATCH 5/6] Update README with correct model name and syntax --- .../Agent_Anthropic_Step04_UsingSkills/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/README.md b/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/README.md index 826437f22b..5d81434fe9 100644 --- a/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/README.md +++ b/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/README.md @@ -24,7 +24,7 @@ Set the following environment variables: ```powershell $env:ANTHROPIC_API_KEY="your-anthropic-api-key" # Replace with your Anthropic API key -$env:ANTHROPIC_MODEL="your-anthropic-model" # Replace with your Anthropic model (e.g., claude-sonnet-4-20250514) +$env:ANTHROPIC_MODEL="your-anthropic-model" # Replace with your Anthropic model (e.g., claude-sonnet-4-5-20250929) ``` ## Run the sample @@ -111,7 +111,7 @@ foreach (HostedFileContent file in hostedFiles) file.FileId, new FileDownloadParams { Betas = ["files-api-2025-04-14"] }); - string fileName = $"presentation_{file.FileId[..8]}.pptx"; + string fileName = $"presentation_{file.FileId.Substring(0, 8)}.pptx"; await using FileStream fileStream = File.Create(fileName); Stream contentStream = await fileResponse.ReadAsStream(); await contentStream.CopyToAsync(fileStream); From 093fdf616e665b0b1a0642fb1f5a88c34dee0a19 Mon Sep 17 00:00:00 2001 From: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com> Date: Wed, 4 Feb 2026 17:30:34 +0000 Subject: [PATCH 6/6] Fix Anthropic SDK 12.3.0 API changes: APIKey->ApiKey, SkillListPageResponse->SkillListPage, Data->Items --- .../Agent_Anthropic_Step04_UsingSkills/Program.cs | 6 +++--- .../Agent_Anthropic_Step04_UsingSkills/README.md | 4 ++-- .../AnthropicSkillsIntegrationTests.cs | 10 +++++----- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/Program.cs b/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/Program.cs index 7f78a04ebb..f67c25214f 100644 --- a/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/Program.cs +++ b/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/Program.cs @@ -22,16 +22,16 @@ string model = Environment.GetEnvironmentVariable("ANTHROPIC_MODEL") ?? "claude-sonnet-4-5-20250929"; // Create the Anthropic client -AnthropicClient anthropicClient = new() { APIKey = apiKey }; +AnthropicClient anthropicClient = new() { ApiKey = apiKey }; // List available Anthropic-managed skills (optional - API may not be available in all regions) Console.WriteLine("Available Anthropic-managed skills:"); try { - SkillListPageResponse skills = await anthropicClient.Beta.Skills.List( + SkillListPage skills = await anthropicClient.Beta.Skills.List( new SkillListParams { Source = "anthropic", Betas = [AnthropicBeta.Skills2025_10_02] }); - foreach (var skill in skills.Data) + foreach (var skill in skills.Items) { Console.WriteLine($" {skill.Source}: {skill.ID} (version: {skill.LatestVersion})"); } diff --git a/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/README.md b/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/README.md index 5d81434fe9..f94b16cac9 100644 --- a/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/README.md +++ b/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/README.md @@ -48,10 +48,10 @@ Anthropic provides several managed skills that can be used with the Claude API: You can list available skills using the Anthropic SDK: ```csharp -SkillListPageResponse skills = await anthropicClient.Beta.Skills.List( +SkillListPage skills = await anthropicClient.Beta.Skills.List( new SkillListParams { Source = "anthropic", Betas = [AnthropicBeta.Skills2025_10_02] }); -foreach (var skill in skills.Data) +foreach (var skill in skills.Items) { Console.WriteLine($"{skill.Source}: {skill.ID} (version: {skill.LatestVersion})"); } diff --git a/dotnet/tests/AnthropicChatCompletion.IntegrationTests/AnthropicSkillsIntegrationTests.cs b/dotnet/tests/AnthropicChatCompletion.IntegrationTests/AnthropicSkillsIntegrationTests.cs index 9d9c11f3c7..a6a96bd234 100644 --- a/dotnet/tests/AnthropicChatCompletion.IntegrationTests/AnthropicSkillsIntegrationTests.cs +++ b/dotnet/tests/AnthropicChatCompletion.IntegrationTests/AnthropicSkillsIntegrationTests.cs @@ -28,7 +28,7 @@ public sealed class AnthropicSkillsIntegrationTests public async Task CreateAgentWithPptxSkillAsync() { // Arrange - AnthropicClient anthropicClient = new() { APIKey = s_config.ApiKey }; + AnthropicClient anthropicClient = new() { ApiKey = s_config.ApiKey }; string model = s_config.ChatModelId; BetaSkillParams pptxSkill = new() @@ -57,15 +57,15 @@ public async Task CreateAgentWithPptxSkillAsync() public async Task ListAnthropicManagedSkillsAsync() { // Arrange - AnthropicClient anthropicClient = new() { APIKey = s_config.ApiKey }; + AnthropicClient anthropicClient = new() { ApiKey = s_config.ApiKey }; // Act - SkillListPageResponse skills = await anthropicClient.Beta.Skills.List( + SkillListPage skills = await anthropicClient.Beta.Skills.List( new SkillListParams { Source = "anthropic", Betas = [AnthropicBeta.Skills2025_10_02] }); // Assert Assert.NotNull(skills); - Assert.NotNull(skills.Data); - Assert.Contains(skills.Data, skill => skill.ID == "pptx"); + Assert.NotNull(skills.Items); + Assert.Contains(skills.Items, skill => skill.ID == "pptx"); } }