// Copyright (c) Microsoft. All rights reserved. using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text.Json; 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 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 called. /// Calls made after that point will not be reflected in the generated /// content. 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 readonly JsonSerializerOptions? _serializerOptions; 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. /// /// Optional applied by default to all scripts and delegate resources /// added to this skill. Individual and /// calls can override this default. When , is used. /// public AgentInlineSkill(AgentSkillFrontmatter frontmatter, string instructions, JsonSerializerOptions? serializerOptions = null) { this.Frontmatter = Throw.IfNull(frontmatter); this._instructions = Throw.IfNullOrWhitespace(instructions); this._serializerOptions = serializerOptions; } /// /// 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. /// /// Optional applied by default to all scripts and delegate resources /// added to this skill. Individual and /// calls can override this default. When , is used. /// public AgentInlineSkill( string name, string description, string instructions, string? license = null, string? compatibility = null, string? allowedTools = null, AdditionalPropertiesDictionary? metadata = null, JsonSerializerOptions? serializerOptions = null) : this( new AgentSkillFrontmatter(name, description, compatibility) { License = license, AllowedTools = allowedTools, Metadata = metadata, }, instructions, serializerOptions) { } /// public override AgentSkillFrontmatter Frontmatter { get; } /// public override ValueTask GetContentAsync(CancellationToken cancellationToken = default) { return new(this._cachedContent ??= AgentInlineSkillContentBuilder.Build(this.Frontmatter.Name, this.Frontmatter.Description, this._instructions, this._resources, this._scripts)); } /// public override ValueTask GetResourceAsync(string name, CancellationToken cancellationToken = default) { var resource = this._resources?.FirstOrDefault(r => r.Name == name); return new(resource); } /// public override ValueTask GetScriptAsync(string name, CancellationToken cancellationToken = default) { var script = this._scripts?.FirstOrDefault(s => s.Name == name); return new(script); } /// /// 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. /// /// Optional for this resource's delegate marshaling. /// When , the skill-level default (if any) is used; otherwise is used. /// /// This instance, for chaining. public AgentInlineSkill AddResource(string name, Delegate method, string? description = null, JsonSerializerOptions? serializerOptions = null) { (this._resources ??= []).Add(new AgentInlineSkillResource(name, method, description, serializerOptions ?? this._serializerOptions)); 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. /// /// Optional for this script's delegate marshaling. /// When , the skill-level default (if any) is used; otherwise is used. /// /// This instance, for chaining. public AgentInlineSkill AddScript(string name, Delegate method, string? description = null, JsonSerializerOptions? serializerOptions = null) { (this._scripts ??= []).Add(new AgentInlineSkillScript(name, method, description, serializerOptions ?? this._serializerOptions)); return this; } }