diff --git a/dotnet/agent-framework-dotnet.slnx b/dotnet/agent-framework-dotnet.slnx
index a5b93487b3..df1c91eea4 100644
--- a/dotnet/agent-framework-dotnet.slnx
+++ b/dotnet/agent-framework-dotnet.slnx
@@ -105,6 +105,7 @@
+
diff --git a/dotnet/samples/02-agents/AgentSkills/Agent_Step02_CodeDefinedSkills/Agent_Step02_CodeDefinedSkills.csproj b/dotnet/samples/02-agents/AgentSkills/Agent_Step02_CodeDefinedSkills/Agent_Step02_CodeDefinedSkills.csproj
new file mode 100644
index 0000000000..fd3d71fe7e
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentSkills/Agent_Step02_CodeDefinedSkills/Agent_Step02_CodeDefinedSkills.csproj
@@ -0,0 +1,21 @@
+
+
+
+ Exe
+ net10.0
+
+ enable
+ enable
+ $(NoWarn);MAAI001
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dotnet/samples/02-agents/AgentSkills/Agent_Step02_CodeDefinedSkills/Program.cs b/dotnet/samples/02-agents/AgentSkills/Agent_Step02_CodeDefinedSkills/Program.cs
new file mode 100644
index 0000000000..46c58985fb
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentSkills/Agent_Step02_CodeDefinedSkills/Program.cs
@@ -0,0 +1,90 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+// This sample demonstrates how to define Agent Skills entirely in code using AgentInlineSkill.
+// No SKILL.md files are needed — skills, resources, and scripts are all defined programmatically.
+//
+// Three approaches are shown using a unit-converter skill:
+// 1. Static resources — inline content provided via AddResource
+// 2. Dynamic resources — computed at runtime via a factory delegate
+// 3. Code scripts — executable delegates the agent can invoke directly
+
+using System.Text.Json;
+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";
+
+// --- Build the code-defined skill ---
+var unitConverterSkill = new AgentInlineSkill(
+ name: "unit-converter",
+ description: "Convert between common units using a multiplication factor. Use when asked to convert miles, kilometers, pounds, or kilograms.",
+ instructions: """
+ Use this skill when the user asks to convert between units.
+
+ 1. Review the conversion-table resource to find the factor for the requested conversion.
+ 2. Check the conversion-policy resource for rounding and formatting rules.
+ 3. Use the convert script, passing the value and factor from the table.
+ """)
+ // 1. Static Resource: conversion tables
+ .AddResource(
+ "conversion-table",
+ """
+ # Conversion Tables
+
+ Formula: **result = value × factor**
+
+ | From | To | Factor |
+ |-------------|-------------|----------|
+ | miles | kilometers | 1.60934 |
+ | kilometers | miles | 0.621371 |
+ | pounds | kilograms | 0.453592 |
+ | kilograms | pounds | 2.20462 |
+ """)
+ // 2. Dynamic Resource: conversion policy (computed at runtime)
+ .AddResource("conversion-policy", () =>
+ {
+ const int Precision = 4;
+ return $"""
+ # Conversion Policy
+
+ **Decimal places:** {Precision}
+ **Format:** Always show both the original and converted values with units
+ **Generated at:** {DateTime.UtcNow:O}
+ """;
+ })
+ // 3. Code Script: convert
+ .AddScript("convert", (double value, double factor) =>
+ {
+ double result = Math.Round(value * factor, 4);
+ return JsonSerializer.Serialize(new { value, factor, result });
+ });
+
+// --- Skills Provider ---
+var skillsProvider = new AgentSkillsProvider(unitConverterSkill);
+
+// --- Agent Setup ---
+AIAgent agent = new AzureOpenAIClient(new Uri(endpoint), new DefaultAzureCredential())
+ .GetResponsesClient()
+ .AsAIAgent(new ChatClientAgentOptions
+ {
+ Name = "UnitConverterAgent",
+ ChatOptions = new()
+ {
+ Instructions = "You are a helpful assistant that can convert units.",
+ },
+ AIContextProviders = [skillsProvider],
+ },
+ model: deploymentName);
+
+// --- Example: Unit conversion ---
+Console.WriteLine("Converting units with code-defined skills");
+Console.WriteLine(new string('-', 60));
+
+AgentResponse response = await agent.RunAsync(
+ "How many kilometers is a marathon (26.2 miles)? And how many pounds is 75 kilograms?");
+
+Console.WriteLine($"Agent: {response.Text}");
diff --git a/dotnet/samples/02-agents/AgentSkills/Agent_Step02_CodeDefinedSkills/README.md b/dotnet/samples/02-agents/AgentSkills/Agent_Step02_CodeDefinedSkills/README.md
new file mode 100644
index 0000000000..5b7c8747dd
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentSkills/Agent_Step02_CodeDefinedSkills/README.md
@@ -0,0 +1,52 @@
+# Code-Defined Agent Skills Sample
+
+This sample demonstrates how to define **Agent Skills entirely in code** using `AgentInlineSkill`.
+
+## What it demonstrates
+
+- Creating skills programmatically with `AgentInlineSkill` — no SKILL.md files needed
+- **Static resources** via `AddResource` with inline content
+- **Dynamic resources** via `AddResource` with a factory delegate (computed at runtime)
+- **Code scripts** via `AddScript` with a delegate handler
+- Using the `AgentSkillsProvider` constructor with inline skills
+
+## Skills Included
+
+### unit-converter (code-defined)
+
+Converts between common units using multiplication factors. Defined entirely in C# code:
+
+- `conversion-table` — Static resource with factor table
+- `conversion-policy` — Dynamic resource with formatting rules (generated at runtime)
+- `convert` — Script that performs `value × factor` conversion
+
+## Running the Sample
+
+### Prerequisites
+
+- .NET 10.0 SDK
+- Azure OpenAI endpoint with a deployed model
+
+### Setup
+
+```bash
+export AZURE_OPENAI_ENDPOINT="https://your-endpoint.openai.azure.com/"
+export AZURE_OPENAI_DEPLOYMENT_NAME="gpt-4o-mini"
+```
+
+### Run
+
+```bash
+dotnet run
+```
+
+### Expected Output
+
+```
+Converting units with code-defined skills
+------------------------------------------------------------
+Agent: Here are your conversions:
+
+1. **26.2 miles → 42.16 km** (a marathon distance)
+2. **75 kg → 165.35 lbs**
+```
diff --git a/dotnet/samples/02-agents/AgentSkills/README.md b/dotnet/samples/02-agents/AgentSkills/README.md
index 75b850f077..6011384997 100644
--- a/dotnet/samples/02-agents/AgentSkills/README.md
+++ b/dotnet/samples/02-agents/AgentSkills/README.md
@@ -1,7 +1,24 @@
# AgentSkills Samples
-Samples demonstrating Agent Skills capabilities.
+Samples demonstrating Agent Skills capabilities. Each sample shows a different way to define and use skills.
| Sample | Description |
|--------|-------------|
| [Agent_Step01_FileBasedSkills](Agent_Step01_FileBasedSkills/) | Define skills as `SKILL.md` files on disk with reference documents. Uses a unit-converter skill. |
+| [Agent_Step02_CodeDefinedSkills](Agent_Step02_CodeDefinedSkills/) | Define skills entirely in C# code using `AgentInlineSkill`, with static/dynamic resources and scripts. |
+
+## Key Concepts
+
+### File-Based vs Code-Defined Skills
+
+| Aspect | File-Based | Code-Defined |
+|--------|-----------|--------------|
+| Definition | `SKILL.md` files on disk | `AgentInlineSkill` instances in C# |
+| Resources | All files in skill directory (filtered by extension) | `AddResource` (static value or delegate-backed) |
+| Scripts | Supported via script executor delegate | `AddScript` delegates |
+| Discovery | Automatic from directory path | Explicit via constructor |
+| Dynamic content | No (static files only) | Yes (factory delegates) |
+| Reusability | Copy skill directory | Inline or shared instances |
+
+For single-source scenarios, use the `AgentSkillsProvider` constructors directly. To combine multiple skill types, use the `AgentSkillsProviderBuilder`.
+
diff --git a/dotnet/src/Microsoft.Agents.AI/Skills/AgentInMemorySkillsSource.cs b/dotnet/src/Microsoft.Agents.AI/Skills/AgentInMemorySkillsSource.cs
new file mode 100644
index 0000000000..57c9295c24
--- /dev/null
+++ b/dotnet/src/Microsoft.Agents.AI/Skills/AgentInMemorySkillsSource.cs
@@ -0,0 +1,35 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.Shared.DiagnosticIds;
+using Microsoft.Shared.Diagnostics;
+
+namespace Microsoft.Agents.AI;
+
+///
+/// A skill source that holds instances in memory.
+///
+[Experimental(DiagnosticIds.Experiments.AgentsAIExperiments)]
+internal sealed class AgentInMemorySkillsSource : AgentSkillsSource
+{
+ private readonly List _skills;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The skills to include in this source.
+ public AgentInMemorySkillsSource(IEnumerable skills)
+ {
+ this._skills = Throw.IfNull(skills).ToList();
+ }
+
+ ///
+ public override Task> GetSkillsAsync(CancellationToken cancellationToken = default)
+ {
+ return Task.FromResult>(this._skills);
+ }
+}
diff --git a/dotnet/src/Microsoft.Agents.AI/Skills/AgentSkill.cs b/dotnet/src/Microsoft.Agents.AI/Skills/AgentSkill.cs
index 5f0a66808d..4c5ca8dbc3 100644
--- a/dotnet/src/Microsoft.Agents.AI/Skills/AgentSkill.cs
+++ b/dotnet/src/Microsoft.Agents.AI/Skills/AgentSkill.cs
@@ -12,7 +12,8 @@ namespace Microsoft.Agents.AI;
///
///
/// A skill represents a domain-specific capability with instructions, resources, and scripts.
-/// Concrete implementations include (filesystem-backed).
+/// Concrete implementations include (filesystem-backed)
+/// and (code-defined).
///
///
/// Skill metadata follows the Agent Skills specification.
@@ -35,6 +36,8 @@ public abstract class AgentSkill
///
///
/// For file-based skills this is the raw SKILL.md file content.
+ /// For code-defined skills this is a synthesized XML document
+ /// containing name, description, and body (instructions, resources, scripts).
///
public abstract string Content { get; }
diff --git a/dotnet/src/Microsoft.Agents.AI/Skills/AgentSkillsProvider.cs b/dotnet/src/Microsoft.Agents.AI/Skills/AgentSkillsProvider.cs
index f2f87851c0..70d7939227 100644
--- a/dotnet/src/Microsoft.Agents.AI/Skills/AgentSkillsProvider.cs
+++ b/dotnet/src/Microsoft.Agents.AI/Skills/AgentSkillsProvider.cs
@@ -116,6 +116,38 @@ public AgentSkillsProvider(
{
}
+ ///
+ /// Initializes a new instance of the class
+ /// with one or more inline (code-defined) skills.
+ /// Duplicate skill names are automatically deduplicated (first occurrence wins).
+ ///
+ /// The inline skills to include.
+ public AgentSkillsProvider(params AgentInlineSkill[] skills)
+ : this(skills as IEnumerable)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class
+ /// with inline (code-defined) skills.
+ /// Duplicate skill names are automatically deduplicated (first occurrence wins).
+ ///
+ /// The inline skills to include.
+ /// Optional provider configuration.
+ /// Optional logger factory.
+ public AgentSkillsProvider(
+ IEnumerable skills,
+ AgentSkillsProviderOptions? options = null,
+ ILoggerFactory? loggerFactory = null)
+ : this(
+ new DeduplicatingAgentSkillsSource(
+ new AgentInMemorySkillsSource(Throw.IfNull(skills)),
+ loggerFactory),
+ options,
+ loggerFactory)
+ {
+ }
+
///
/// Initializes a new instance of the class
/// from a custom . Unlike other constructors, this one does not
diff --git a/dotnet/src/Microsoft.Agents.AI/Skills/AgentSkillsProviderBuilder.cs b/dotnet/src/Microsoft.Agents.AI/Skills/AgentSkillsProviderBuilder.cs
index 17d7f2d6f3..8e52cc522e 100644
--- a/dotnet/src/Microsoft.Agents.AI/Skills/AgentSkillsProviderBuilder.cs
+++ b/dotnet/src/Microsoft.Agents.AI/Skills/AgentSkillsProviderBuilder.cs
@@ -13,9 +13,13 @@ namespace Microsoft.Agents.AI;
/// Fluent builder for constructing an backed by a composite source.
///
///
+///
+/// Use this builder to combine multiple skill sources into a single provider:
+///
///
/// var provider = new AgentSkillsProviderBuilder()
/// .UseFileSkills("/path/to/skills")
+/// .UseSkills(myInlineSkill1, myInlineSkill2)
/// .Build();
///
///
@@ -65,6 +69,40 @@ public AgentSkillsProviderBuilder UseFileSkills(IEnumerable skillPaths,
return this;
}
+ ///
+ /// Adds a single skill.
+ ///
+ /// The skill to add.
+ /// This builder instance for chaining.
+ public AgentSkillsProviderBuilder UseSkill(AgentSkill skill)
+ {
+ return this.UseSkills(skill);
+ }
+
+ ///
+ /// Adds one or more skills.
+ ///
+ /// The skills to add.
+ /// This builder instance for chaining.
+ public AgentSkillsProviderBuilder UseSkills(params AgentSkill[] skills)
+ {
+ var source = new AgentInMemorySkillsSource(skills);
+ this._sourceFactories.Add((_, _) => source);
+ return this;
+ }
+
+ ///
+ /// Adds skills from the specified collection.
+ ///
+ /// The skills to add.
+ /// This builder instance for chaining.
+ public AgentSkillsProviderBuilder UseSkills(IEnumerable skills)
+ {
+ var source = new AgentInMemorySkillsSource(skills);
+ this._sourceFactories.Add((_, _) => source);
+ return this;
+ }
+
///
/// Adds a custom skill source.
///
diff --git a/dotnet/src/Microsoft.Agents.AI/Skills/Programmatic/AgentInlineSkill.cs b/dotnet/src/Microsoft.Agents.AI/Skills/Programmatic/AgentInlineSkill.cs
new file mode 100644
index 0000000000..d326a47a59
--- /dev/null
+++ b/dotnet/src/Microsoft.Agents.AI/Skills/Programmatic/AgentInlineSkill.cs
@@ -0,0 +1,215 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Text;
+using System.Text.Json;
+using Microsoft.Extensions.AI;
+using Microsoft.Shared.DiagnosticIds;
+using Microsoft.Shared.Diagnostics;
+
+namespace Microsoft.Agents.AI;
+
+///
+/// A skill defined entirely in code with resources (static values or delegates) and scripts (delegates).
+///
+///
+/// All calls to ,
+/// , and
+/// must be made before the skill's is first accessed.
+/// Calls made after that point will not be reflected in the generated
+/// . In typical usage, this means configuring all
+/// resources and scripts before registering the skill with an
+/// or .
+///
+[Experimental(DiagnosticIds.Experiments.AgentsAIExperiments)]
+public sealed class AgentInlineSkill : AgentSkill
+{
+ private readonly string _instructions;
+ private List? _resources;
+ private List? _scripts;
+ private string? _cachedContent;
+
+ ///
+ /// Initializes a new instance of the class
+ /// with a pre-built .
+ ///
+ /// The skill frontmatter containing name, description, and other metadata.
+ /// Skill instructions text.
+ public AgentInlineSkill(AgentSkillFrontmatter frontmatter, string instructions)
+ {
+ this.Frontmatter = Throw.IfNull(frontmatter);
+ this._instructions = Throw.IfNullOrWhitespace(instructions);
+ }
+
+ ///
+ /// Initializes a new instance of the class
+ /// with all frontmatter properties specified individually.
+ ///
+ /// Skill name in kebab-case.
+ /// Skill description for discovery.
+ /// Skill instructions text.
+ /// Optional license name or reference.
+ /// Optional compatibility information (max 500 chars).
+ /// Optional space-delimited list of pre-approved tools.
+ /// Optional arbitrary key-value metadata.
+ public AgentInlineSkill(
+ string name,
+ string description,
+ string instructions,
+ string? license = null,
+ string? compatibility = null,
+ string? allowedTools = null,
+ AdditionalPropertiesDictionary? metadata = null)
+ : this(
+ new AgentSkillFrontmatter(name, description, compatibility)
+ {
+ License = license,
+ AllowedTools = allowedTools,
+ Metadata = metadata,
+ },
+ instructions)
+ {
+ }
+
+ ///
+ public override AgentSkillFrontmatter Frontmatter { get; }
+
+ ///
+ public override string Content => this._cachedContent ??= this.BuildContent();
+
+ ///
+ public override IReadOnlyList? Resources => this._resources;
+
+ ///
+ public override IReadOnlyList? Scripts => this._scripts;
+
+ ///
+ /// Registers a static resource with this skill.
+ ///
+ /// The resource name.
+ /// The static resource value.
+ /// An optional description of the resource.
+ /// This instance, for chaining.
+ public AgentInlineSkill AddResource(string name, object value, string? description = null)
+ {
+ (this._resources ??= []).Add(new AgentInlineSkillResource(name, value, description));
+ return this;
+ }
+
+ ///
+ /// Registers a dynamic resource with this skill, backed by a C# delegate.
+ /// The delegate's parameters and return type are automatically marshaled via AIFunctionFactory.
+ ///
+ /// The resource name.
+ /// A method that produces the resource value when requested.
+ /// An optional description of the resource.
+ /// This instance, for chaining.
+ public AgentInlineSkill AddResource(string name, Delegate method, string? description = null)
+ {
+ (this._resources ??= []).Add(new AgentInlineSkillResource(name, method, description));
+ return this;
+ }
+
+ ///
+ /// Registers a script with this skill, backed by a C# delegate.
+ /// The delegate's parameters and return type are automatically marshaled via AIFunctionFactory.
+ ///
+ /// The script name.
+ /// A method to execute when the script is invoked.
+ /// An optional description of the script.
+ /// This instance, for chaining.
+ public AgentInlineSkill AddScript(string name, Delegate method, string? description = null)
+ {
+ (this._scripts ??= []).Add(new AgentInlineSkillScript(name, method, description));
+ return this;
+ }
+
+ private string BuildContent()
+ {
+ var sb = new StringBuilder();
+
+ sb.Append($"{EscapeXmlString(this.Frontmatter.Name)}\n")
+ .Append($"{EscapeXmlString(this.Frontmatter.Description)}\n\n")
+ .Append("\n")
+ .Append(EscapeXmlString(this._instructions))
+ .Append("\n");
+
+ if (this.Resources is { Count: > 0 })
+ {
+ sb.Append("\n\n\n");
+ foreach (var resource in this.Resources)
+ {
+ if (resource.Description is not null)
+ {
+ sb.Append($" \n");
+ }
+ else
+ {
+ sb.Append($" \n");
+ }
+ }
+
+ sb.Append("");
+ }
+
+ if (this.Scripts is { Count: > 0 })
+ {
+ sb.Append("\n\n\n");
+ foreach (var script in this.Scripts)
+ {
+ JsonElement? parametersSchema = ((AgentInlineSkillScript)script).ParametersSchema;
+
+ if (script.Description is null && parametersSchema is null)
+ {
+ sb.Append($" \n");
+ }
+ }
+
+ sb.Append("");
+ }
+
+ return sb.ToString();
+ }
+
+ ///
+ /// Escapes XML special characters: always escapes &, <, >,
+ /// ", and '. When is ,
+ /// quotes are left unescaped to preserve readability of embedded content such as JSON.
+ ///
+ /// The string to escape.
+ ///
+ /// When , leaves " and ' unescaped for use in XML element content (e.g., JSON).
+ /// When (default), escapes all XML special characters including quotes.
+ ///
+ private static string EscapeXmlString(string value, bool preserveQuotes = false)
+ {
+ var result = value
+ .Replace("&", "&")
+ .Replace("<", "<")
+ .Replace(">", ">");
+
+ if (!preserveQuotes)
+ {
+ result = result
+ .Replace("\"", """)
+ .Replace("'", "'");
+ }
+
+ return result;
+ }
+}
diff --git a/dotnet/src/Microsoft.Agents.AI/Skills/Programmatic/AgentInlineSkillResource.cs b/dotnet/src/Microsoft.Agents.AI/Skills/Programmatic/AgentInlineSkillResource.cs
new file mode 100644
index 0000000000..38791c3b21
--- /dev/null
+++ b/dotnet/src/Microsoft.Agents.AI/Skills/Programmatic/AgentInlineSkillResource.cs
@@ -0,0 +1,60 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.Extensions.AI;
+using Microsoft.Shared.DiagnosticIds;
+using Microsoft.Shared.Diagnostics;
+
+namespace Microsoft.Agents.AI;
+
+///
+/// A skill resource defined in code, backed by either a static value or a delegate.
+///
+[Experimental(DiagnosticIds.Experiments.AgentsAIExperiments)]
+internal sealed class AgentInlineSkillResource : AgentSkillResource
+{
+ private readonly object? _value;
+ private readonly AIFunction? _function;
+
+ ///
+ /// Initializes a new instance of the class with a static value.
+ /// The value is returned as-is when is called.
+ ///
+ /// The resource name.
+ /// The static resource value.
+ /// An optional description of the resource.
+ public AgentInlineSkillResource(string name, object value, string? description = null)
+ : base(name, description)
+ {
+ this._value = Throw.IfNull(value);
+ }
+
+ ///
+ /// Initializes a new instance of the class with a delegate.
+ /// The delegate is invoked via an each time is called,
+ /// producing a dynamic (computed) value.
+ ///
+ /// The resource name.
+ /// A method that produces the resource value when requested.
+ /// An optional description of the resource.
+ public AgentInlineSkillResource(string name, Delegate method, string? description = null)
+ : base(name, description)
+ {
+ Throw.IfNull(method);
+ this._function = AIFunctionFactory.Create(method, name: this.Name);
+ }
+
+ ///
+ public override async Task