Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Les compétences de l’agent sont des packages portables d’instructions, de scripts et de ressources qui donnent aux agents des fonctionnalités spécialisées et une expertise de domaine. Les compétences suivent une spécification ouverte et implémentent un modèle de divulgation progressif afin que les agents chargent uniquement le contexte dont ils ont besoin, quand ils en ont besoin.
Utilisez les compétences de l’agent lorsque vous souhaitez :
- Packager l’expertise métier - Capturez des connaissances spécialisées (politiques de dépenses, flux de travail juridiques, pipelines d’analyse de données) sous forme de modules réutilisables et portables.
- Étendre les fonctionnalités de l’agent : donnez aux agents de nouvelles capacités sans modifier leurs instructions principales.
- Garantir la cohérence - Transformer les tâches en plusieurs étapes en flux de travail reproductibles et auditables.
- Activez l’interopérabilité : réutilisez la même compétence entre différents produits compatibles avec les compétences de l’agent.
Structure des compétences
Une compétence est un répertoire contenant un SKILL.md fichier avec des sous-répertoires facultatifs pour les ressources :
expense-report/
├── SKILL.md # Required - frontmatter + instructions
├── scripts/
│ └── validate.py # Executable code agents can run
├── references/
│ └── POLICY_FAQ.md # Reference documents loaded on demand
└── assets/
└── expense-report-template.md # Templates and static resources
format SKILL.md
Le SKILL.md fichier doit contenir un frontmatter YAML suivi du contenu markdown :
---
name: expense-report
description: File and validate employee expense reports according to company policy. Use when asked about expense submissions, reimbursement rules, or spending limits.
license: Apache-2.0
compatibility: Requires python3
metadata:
author: contoso-finance
version: "2.1"
---
| Champ | Obligatoire | Descriptif |
|---|---|---|
name |
Oui | 64 caractères maximum. Lettres minuscules, chiffres et traits d’union uniquement. Ne doit pas commencer ou se terminer par un trait d’union ou contenir des traits d’union consécutifs. Doit correspondre au nom du répertoire parent. |
description |
Oui | Que fait la compétence et quand l’utiliser. Nombre maximal de 1024 caractères. Doit inclure des mots clés qui aident les agents à identifier les tâches pertinentes. |
license |
Non | Nom de la licence ou référence à un fichier de licence groupé. |
compatibility |
Non | 500 caractères maximum. Indique la configuration requise pour l’environnement (produit prévu, packages système, accès réseau, etc.). |
metadata |
Non | Mappage arbitraire clé-valeur destiné à des métadonnées supplémentaires. |
allowed-tools |
Non | Liste séparée par des espaces des outils pré-approuvés que la capacité peut utiliser. Expérimental : la prise en charge peut varier entre les implémentations de l’agent. |
Le corps Markdown après l’en-tête contient les instructions relatives à la compétence : un guide étape par étape, des exemples d’entrées et de sorties, des cas limites courants ou tout autre contenu aidant l’agent à effectuer la tâche. Conservez moins de 500 lignes et déplacez SKILL.md des documents de référence détaillés vers des fichiers distincts.
Divulgation progressive
Les compétences de l’agent utilisent un modèle de divulgation progressive en quatre étapes pour réduire l’utilisation du contexte :
- Annoncer (~100 jetons par compétence) - Les noms et les descriptions des compétences sont injectés dans le prompt système au début de chaque exécution, afin que l’agent sache quelles compétences sont disponibles.
-
Charger (< 5000 jetons recommandés) : lorsqu’une tâche correspond au domaine d’une compétence, l’agent appelle l’outil
load_skillpour récupérer le corps complet du SKILL.md avec des instructions détaillées. -
Lire les ressources (si nécessaire) : l’agent appelle l’outil
read_skill_resourcepour récupérer des fichiers supplémentaires (références, modèles, ressources) uniquement si nécessaire. -
Exécuter des scripts (si nécessaire) : l’agent appelle l’outil
run_skill_scriptpour exécuter des scripts groupés avec une compétence.
Ce schéma maintient la fenêtre de contexte de l'agent allégée tout en lui donnant accès à une connaissance approfondie du domaine à la demande.
Note
load_skill est toujours annoncé.
read_skill_resource est publié uniquement lorsque au moins une compétence possède des ressources.
run_skill_script est annoncé uniquement quand au moins une compétence possède des scripts.
Fournir des compétences à un agent
L’utilisation de compétences implique trois blocs de construction :
-
Fournisseur -
AgentSkillsProvider(C#) ouSkillsProvider(Python) est un fournisseur de contexte qui expose des compétences à un agent. Il annonce les compétences disponibles dans le prompt système et enregistre les outils utilisés par l'agent pour charger les compétences, lire les ressources et exécuter des scripts. -
Sources : une source fournit des compétences au fournisseur. Les compétences peuvent provenir de plusieurs types sources :
-
Basée sur des fichiers : compétences découvertes à partir de
SKILL.mdfichiers dans les répertoires du système de fichiers. -
Défini dans le code - compétences définies directement dans le code à l’aide de
AgentInlineSkill(C#) ouInlineSkill(Python). -
Basé sur des classes - compétences encapsulées dans une classe dérivant de
AgentClassSkill<T>(C#) ou deClassSkill(Python). -
Basée sur MCP : compétences découvertes à partir de serveurs MCP (Model Context Protocol) via
UseMcpSkills(C#) ouMCPSkillsSource(Python).
-
Basée sur des fichiers : compétences découvertes à partir de
-
Constructeur -
AgentSkillsProviderBuilder(C#) assemble plusieurs sources en un seul fournisseur, en appliquant l’agrégation, la déduplication, la mise en cache et le filtrage facultatif. Dans Python, composez des classes sources telles queAggregatingSkillsSource,FilteringSkillsSourceetDeduplicatingSkillsSourcedirectement.
Les sections suivantes montrent comment créer des compétences de chaque type de source, puis comment combiner des sources et construire un fournisseur à partir d’eux.
Compétences basées sur des fichiers
Créez un AgentSkillsProvider pointant vers un répertoire contenant vos compétences, et ajoutez-le aux fournisseurs de contexte de l’agent. Transmettez un exécuteur de script pour permettre l’exécution de scripts basés sur des fichiers détectés dans les répertoires de compétences :
using Azure.AI.OpenAI;
using Azure.Identity;
using Microsoft.Agents.AI;
using OpenAI.Responses;
string endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT")!;
string deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
// Discover skills from the 'skills' directory
var skillsProvider = new AgentSkillsProvider(
Path.Combine(AppContext.BaseDirectory, "skills"));
// Create an agent with the skills provider
AIAgent agent = new AzureOpenAIClient(new Uri(endpoint), new DefaultAzureCredential())
.GetResponsesClient()
.AsAIAgent(new ChatClientAgentOptions
{
Name = "SkillsAgent",
ChatOptions = new()
{
Instructions = "You are a helpful assistant.",
},
AIContextProviders = [skillsProvider],
},
model: deploymentName);
Avertissement
DefaultAzureCredential est pratique pour le développement, mais nécessite une considération minutieuse en production. En production, envisagez d’utiliser des informations d’identification spécifiques (par exemple ManagedIdentityCredential) pour éviter les problèmes de latence, la détection involontaire des informations d’identification et les risques de sécurité potentiels liés aux mécanismes de secours.
Répertoires de compétences multiples
Vous pouvez pointer le fournisseur vers un répertoire parent unique : chaque sous-répertoire contenant un SKILL.md est automatiquement découvert en tant que compétence :
var skillsProvider = new AgentSkillsProvider(
Path.Combine(AppContext.BaseDirectory, "all-skills"));
Ou passez une liste de chemins pour rechercher dans plusieurs répertoires racine :
var skillsProvider = new AgentSkillsProvider(
[
Path.Combine(AppContext.BaseDirectory, "company-skills"),
Path.Combine(AppContext.BaseDirectory, "team-skills"),
]);
Le fournisseur recherche jusqu’à deux niveaux de profondeur.
Personnalisation des ressources et de la découverte de scripts
Par défaut, le fournisseur reconnaît les ressources ayant les extensions .md, .json, .yaml, .yml, .csv, .xml et .txt, ainsi que les scripts ayant les extensions .py, .js, .sh, .ps1, .cs et .csx. Il recherche jusqu’à deux niveaux au sein de chaque répertoire de compétences. Utilisez cette option AgentFileSkillsSourceOptions pour modifier les valeurs par défaut suivantes :
var fileOptions = new AgentFileSkillsSourceOptions
{
AllowedResourceExtensions = [".md", ".txt"],
AllowedScriptExtensions = [".py"],
SearchDepth = 3, // Search up to 3 levels deep (default is 2)
ResourceFilter = context => context.RelativeFilePath.StartsWith("references/"),
ScriptFilter = context => context.RelativeFilePath.StartsWith("scripts/")
|| context.RelativeFilePath.StartsWith("tools/"),
};
// Via constructor
var skillsProvider = new AgentSkillsProvider(
Path.Combine(AppContext.BaseDirectory, "skills"),
fileOptions: fileOptions);
// Via builder
var skillsProvider = new AgentSkillsProviderBuilder()
.UseFileSkill(Path.Combine(AppContext.BaseDirectory, "skills"), options: fileOptions)
.Build();
ResourceFilter et ScriptFilter reçoivent un AgentFileSkillFilterContext contenant le nom de la compétence et le chemin d’accès relatif du fichier, ce qui vous permet de restreindre les fichiers par emplacement, convention de nommage ou toute logique personnalisée.
Exécution des scripts
Utilisez SubprocessScriptRunner.RunAsync comme exécuteur de scripts pour activer l’exécution de scripts stockés dans des fichiers :
var skillsProvider = new AgentSkillsProvider(
Path.Combine(AppContext.BaseDirectory, "skills"),
SubprocessScriptRunner.RunAsync);
SubprocessScriptRunner.RunAsync équivaut à peu près à ce qui suit :
// Simplified equivalent of what SubprocessScriptRunner.RunAsync does internally
using System.Diagnostics;
using System.Text.Json;
static async Task<object?> RunAsync(
AgentFileSkill skill,
AgentFileSkillScript script,
JsonElement? args,
IServiceProvider? serviceProvider,
CancellationToken cancellationToken)
{
var psi = new ProcessStartInfo("python3")
{
RedirectStandardOutput = true,
UseShellExecute = false,
};
psi.ArgumentList.Add(script.FullPath);
if (args is { ValueKind: JsonValueKind.Array } json)
{
foreach (var element in json.EnumerateArray())
{
psi.ArgumentList.Add(element.GetString()!);
}
}
using var process = Process.Start(psi)!;
string output = await process.StandardOutput.ReadToEndAsync(cancellationToken);
await process.WaitForExitAsync(cancellationToken);
return output.Trim();
}
L’exécuteur exécute chaque script découvert en tant que sous-processus local. Les scripts basés sur des fichiers attendent des arguments sous la forme d’un tableau JSON de chaînes : chaque élément de tableau devient un argument de ligne de commande positionnelle.
Avertissement
SubprocessScriptRunner est fourni uniquement à des fins de démonstration. Pour une utilisation en production, envisagez d’ajouter :
- Sandboxing (par exemple, conteneurs ou environnements d’exécution isolés)
- Limites des ressources (processeur, mémoire, délai d’expiration de l’horloge murale)
- Validation des entrées et liste d'autorisation des scripts exécutables
- Pistes de journalisation et d’audit structurées
Compétences basées sur des fichiers
Utilisez la fabrique SkillsProvider.from_paths() pour découvrir des compétences à partir de répertoires contenant des fichiers SKILL.md, et ajoutez le fournisseur aux fournisseurs de contexte de l’agent :
import os
from pathlib import Path
# Discover skills from the 'skills' directory
skills_provider = SkillsProvider.from_paths(
skill_paths=Path(__file__).parent / "skills",
)
# Create an agent with the skills provider
endpoint = os.environ["FOUNDRY_PROJECT_ENDPOINT"]
deployment = os.environ.get("FOUNDRY_MODEL", "gpt-4o-mini")
client = FoundryChatClient(
project_endpoint=endpoint,
model=deployment,
credential=AzureCliCredential(),
)
agent = Agent(
client=client,
instructions="You are a helpful assistant.",
context_providers=[skills_provider],
)
Répertoires de compétences multiples
Vous pouvez pointer le fournisseur vers un répertoire parent unique : chaque sous-répertoire contenant un SKILL.md est automatiquement découvert en tant que compétence :
skills_provider = SkillsProvider.from_paths(
skill_paths=Path(__file__).parent / "all-skills"
)
Ou passez une liste de chemins pour rechercher dans plusieurs répertoires racine :
skills_provider = SkillsProvider.from_paths(
skill_paths=[
Path(__file__).parent / "company-skills",
Path(__file__).parent / "team-skills",
]
)
Le fournisseur recherche jusqu’à deux niveaux de profondeur.
Personnalisation des ressources et de la découverte de scripts
Par défaut, les ressources sont découvertes à partir des references/assets/ sous-répertoires et des scripts à partir de scripts/, conformément à la spécification agentskills.io. Les extensions de ressources reconnues sont .md, .json.yaml.yml.csv, .xmlet ..txt Il recherche jusqu’à deux niveaux au sein de chaque répertoire de compétences. Utilisez resource_extensions, , script_extensionssearch_depth, resource_filteret script_filter pour personnaliser la découverte :
skills_provider = SkillsProvider.from_paths(
skill_paths=Path(__file__).parent / "skills",
resource_extensions=(".md", ".txt"),
script_extensions=(".py", ".sh"),
search_depth=3, # Search up to 3 levels deep (default is 2)
resource_filter=lambda skill_name, path: path.startswith("references/"),
script_filter=lambda skill_name, path: path.startswith("scripts/"),
)
Les prédicats resource_filter et script_filter reçoivent le nom de la compétence et le chemin d’accès relatif du fichier, ce qui vous permet de restreindre les fichiers en fonction de leur emplacement, de leur convention de nommage ou de toute logique personnalisée. Utilisez "." pour inclure des fichiers au niveau racine de la compétence en plus des sous-répertoires.
Exécution des scripts
Pour activer l’exécution de scripts basés sur des fichiers, passez-à script_runner à SkillsProvider.from_paths(). Toute synchronisation ou appel asynchrone qui satisfait le SkillScriptRunner protocole peut être utilisé :
from pathlib import Path
from agent_framework import FileSkill, FileSkillScript, SkillsProvider
def my_runner(
skill: FileSkill,
script: FileSkillScript,
args: dict | list[str] | None = None,
) -> str:
"""Run a file-based script as a subprocess."""
import subprocess, sys
script_path = Path(script.full_path)
cmd = [sys.executable, str(script_path)]
if isinstance(args, list):
cmd.extend(args)
result = subprocess.run(
cmd, capture_output=True, text=True, timeout=30, cwd=str(script_path.parent)
)
return result.stdout.strip()
skills_provider = SkillsProvider.from_paths(
skill_paths=Path(__file__).parent / "skills",
script_runner=my_runner,
)
L’exécuteur reçoit les arguments résolus FileSkill, FileSkillScript, ainsi qu’un argument facultatif args. Les scripts basés sur des fichiers attendent des arguments sous la forme d’un tableau JSON de chaînes : chaque élément de tableau devient un argument de ligne de commande positionnelle. Les scripts sont automatiquement découverts à partir de .py fichiers dans le scripts/ sous-répertoire de chaque répertoire de compétences.
Avertissement
L'exécuteur ci-dessus est fourni uniquement à des fins de démonstration. Pour une utilisation en production, envisagez d’ajouter :
- Bac à sable (par exemple, conteneurs,
seccomp, oufirejail) - Limites des ressources (processeur, mémoire, délai d’expiration de l’horloge murale)
- Validation des entrées et liste d'autorisation des scripts exécutables
- Pistes de journalisation et d’audit structurées
Note
Si des compétences basées sur des fichiers avec des scripts sont fournies, mais qu’aucune valeur n’est script_runner définie, SkillsProvider déclenche une erreur lors de la tentative d’exécution du script.
Compétences basées sur des fichiers
Les agents Go prennent en charge les compétences via le package agent/skills. Les compétences suivent le même modèle de divulgation progressive : publier -> charger -> lire des ressources -> exécuter des scripts.
Découvrez les compétences à partir de SKILL.md fichiers sur disque et inscrivez le fournisseur de compétences en tant que fournisseur de contexte d’agent :
import (
"os"
"github.com/microsoft/agent-framework-go/agent"
"github.com/microsoft/agent-framework-go/provider/foundryprovider"
"github.com/microsoft/agent-framework-go/agent/skills"
"github.com/microsoft/agent-framework-go/agent/skills/fsskills"
)
skillsRoot, _ := os.OpenRoot("skills")
defer skillsRoot.Close()
skillsProvider := skills.NewContextProvider(skills.ContextProviderOptions{
Sources: []skills.Source{
fsskills.NewSourceOptions(fsskills.SourceOptions{}, skillsRoot.FS()),
},
})
a := foundryprovider.NewAgent(endpoint, token, foundryprovider.ModelDeployment(model), foundryprovider.AgentConfig{
Instructions: "You are a helpful assistant.",
Config: agent.Config{
ContextProviders: []agent.ContextProvider{skillsProvider},
},
})
Compétences définies par le code
En plus des compétences basées sur des fichiers découvertes dans les fichiers SKILL.md, vous pouvez définir des compétences entièrement dans le code à l’aide de AgentInlineSkill. Les compétences définies par le code sont utiles quand :
- Le contenu de compétence est généré dynamiquement (par exemple, lecture à partir d’une base de données ou d’un environnement).
- Vous souhaitez conserver les définitions de compétences en même temps que le code d’application qui les utilise.
- Vous avez besoin de ressources qui exécutent la logique au moment de la lecture plutôt que de servir des fichiers statiques.
- Les définitions de compétence doivent être construites au moment de l’exécution à partir de données , par exemple, en créant une compétence personnalisée pour chaque session utilisateur en fonction de leur rôle ou de leurs autorisations.
- Une compétence doit fermer l’état du site d’appel (variables locales, fermetures) plutôt que de résoudre les services à partir d’un conteneur DI.
Compétence de code de base
Créez un AgentInlineSkill avec un nom, une description et des instructions. Attacher des ressources à l’aide de .AddResource():
using Microsoft.Agents.AI;
var codeStyleSkill = new AgentInlineSkill(
name: "code-style",
description: "Coding style guidelines and conventions for the team",
instructions: """
Use this skill when answering questions about coding style, conventions, or best practices for the team.
1. Read the style-guide resource for the full set of rules.
2. Answer based on those rules, quoting the relevant guideline where helpful.
""")
.AddResource(
"style-guide",
"""
# Team Coding Style Guide
- Use 4-space indentation (no tabs)
- Maximum line length: 120 characters
- Use type annotations on all public methods
""");
var skillsProvider = new AgentSkillsProvider(codeStyleSkill);
Ressources dynamiques
Transmettez un délégué de fabrique à .AddResource() pour calculer le contenu au moment de l’exécution. Le délégué est appelé chaque fois que l’agent lit la ressource :
var projectInfoSkill = new AgentInlineSkill(
name: "project-info",
description: "Project status and configuration information",
instructions: """
Use this skill for questions about the current project.
1. Read the environment resource for deployment configuration details.
2. Read the team-roster resource for information about team members.
""")
.AddResource("environment", () =>
{
string env = Environment.GetEnvironmentVariable("APP_ENV") ?? "development";
string region = Environment.GetEnvironmentVariable("APP_REGION") ?? "us-east-1";
return $"Environment: {env}, Region: {region}";
})
.AddResource(
"team-roster",
"Alice Chen (Tech Lead), Bob Smith (Backend Engineer)");
Scripts définis par le code
Utilisez .AddScript() pour inscrire un délégué en tant que script exécutable. Les scripts définis par le code s’exécutent dans le même processus comme des appels de délégués directs. Aucun exécuteur de script n’est nécessaire. Les paramètres typés du délégué sont automatiquement convertis en schéma JSON que l’agent utilise pour passer des arguments :
using System.Text.Json;
var unitConverterSkill = new AgentInlineSkill(
name: "unit-converter",
description: "Convert between common units using a conversion factor",
instructions: """
Use this skill when the user asks to convert between units.
1. Review the conversion-table resource to find the correct factor.
2. Use the convert script, passing the value and factor from the table.
3. Present the result clearly with both units.
""")
.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 |
""")
.AddScript("convert", (double value, double factor) =>
{
double result = Math.Round(value * factor, 4);
return JsonSerializer.Serialize(new { value, factor, result });
});
var skillsProvider = new AgentSkillsProvider(unitConverterSkill);
Note
Pour combiner des compétences définies par le code avec des compétences basées sur des fichiers ou basées sur des classes dans un seul fournisseur, utilisez AgentSkillsProviderBuilder : consultez La construction du fournisseur.
En plus des compétences basées sur des fichiers découvertes à partir de fichiers SKILL.md, vous pouvez définir des compétences entièrement dans Python code à l’aide de InlineSkill. Les compétences définies par le code sont utiles quand :
- Le contenu de compétence est généré dynamiquement (par exemple, lecture à partir d’une base de données ou d’un environnement).
- Vous souhaitez conserver les définitions de compétences en même temps que le code d’application qui les utilise.
- Vous avez besoin de ressources qui exécutent la logique au moment de la lecture plutôt que de servir des fichiers statiques.
- Les définitions de compétence doivent être construites au moment de l’exécution à partir de données , par exemple, en créant une compétence personnalisée pour chaque session utilisateur en fonction de leur rôle ou de leurs autorisations.
- Une compétence doit capturer l’état du site d’appel (variables locales, fermetures) au lieu de résoudre les services via
**kwargs.
Compétence de code de base
Créez une instance de InlineSkill avec un SkillFrontmatter (contenant le nom et la description) et un contenu d’instruction. Attachez éventuellement des InlineSkillResource instances avec du contenu statique :
from textwrap import dedent
from agent_framework import InlineSkill, InlineSkillResource, SkillFrontmatter, SkillsProvider
code_style_skill = InlineSkill(
frontmatter=SkillFrontmatter(
name="code-style",
description="Coding style guidelines and conventions for the team",
),
instructions=dedent("""\
Use this skill when answering questions about coding style,
conventions, or best practices for the team.
"""),
resources=[
InlineSkillResource(
name="style-guide",
content=dedent("""\
# Team Coding Style Guide
- Use 4-space indentation (no tabs)
- Maximum line length: 120 characters
- Use type annotations on all public functions
"""),
),
],
)
skills_provider = SkillsProvider(code_style_skill)
Ressources dynamiques
Utilisez le @skill.resource décorateur pour inscrire une fonction en tant que ressource. La fonction est appelée chaque fois que l’agent lit la ressource, afin qu’elle puisse retourner des données up-to-date. Les fonctions de synchronisation et asynchrone sont prises en charge :
import os
from agent_framework import InlineSkill, SkillFrontmatter
project_info_skill = InlineSkill(
frontmatter=SkillFrontmatter(
name="project-info",
description="Project status and configuration information",
),
instructions="Use this skill for questions about the current project.",
)
@project_info_skill.resource
def environment() -> str:
"""Get current environment configuration."""
env = os.environ.get("APP_ENV", "development")
region = os.environ.get("APP_REGION", "us-east-1")
return f"Environment: {env}, Region: {region}"
@project_info_skill.resource(name="team-roster", description="Current team members")
def get_team_roster() -> str:
"""Return the team roster."""
return "Alice Chen (Tech Lead), Bob Smith (Backend Engineer)"
Lorsque le décorateur est utilisé sans arguments (@skill.resource), le nom de la fonction devient le nom de la ressource et la documentation devient la description. Permet @skill.resource(name="...", description="...") de les définir explicitement.
Scripts définis par le code
Utilisez le décorateur @skill.script pour enregistrer une fonction en tant que script exécutable sur une fonctionnalité. Les scripts définis par le code s’exécutent en cours et ne nécessitent pas d’exécuteur de script. Les fonctions de synchronisation et asynchrone sont prises en charge :
from agent_framework import InlineSkill, SkillFrontmatter
unit_converter_skill = InlineSkill(
frontmatter=SkillFrontmatter(
name="unit-converter",
description="Convert between common units using a conversion factor",
),
instructions="Use the convert script to perform unit conversions.",
)
@unit_converter_skill.script(name="convert", description="Convert a value: result = value × factor")
def convert_units(value: float, factor: float) -> str:
"""Convert a value using a multiplication factor."""
import json
result = round(value * factor, 4)
return json.dumps({"value": value, "factor": factor, "result": result})
Lorsque le décorateur est utilisé sans arguments (@skill.script), le nom de la fonction devient le nom du script et la documentation devient la description. Les paramètres typés de la fonction sont automatiquement convertis en schéma JSON que l’agent utilise pour passer des arguments.
En plus des compétences basées sur des fichiers découvertes à partir de SKILL.md fichiers, vous pouvez définir des compétences entièrement dans le code Go :
skill := &skills.Skill{
Frontmatter: skills.Frontmatter{
Name: "unit-converter",
Description: "Convert between common units using a multiplication factor.",
},
GetContent: func(context.Context) (string, error) {
return "Use this skill when the user asks to convert between units.", nil
},
Resources: []skills.Resource{
{
Name: "conversion-table",
Description: "Lookup table of multiplication factors.",
Read: func(context.Context) (any, error) {
return conversionTable, nil
},
},
},
Scripts: []skills.Script{
{
Name: "convert",
Description: "Multiplies a value by a conversion factor. Pass value and factor as positional string arguments: [\"<value>\", \"<factor>\"].",
Run: func(_ context.Context, _ *skills.Skill, args []string) (any, error) {
if len(args) != 2 {
return nil, fmt.Errorf("expected value and factor")
}
value, err := strconv.ParseFloat(args[0], 64)
if err != nil {
return nil, err
}
factor, err := strconv.ParseFloat(args[1], 64)
if err != nil {
return nil, err
}
return map[string]any{
"value": value,
"factor": factor,
"result": value * factor,
}, nil
},
},
},
}
provider := skills.NewContextProvider(skills.ContextProviderOptions{
Skills: []*skills.Skill{skill},
})
GetContent charge les instructions de compétence uniquement lorsque l’agent appelle load_skill. Les scripts reçoivent des arguments de chaîne positionnels, de type CLI, par exemple ["26.2", "1.60934"], et peuvent analyser ces arguments comme le script l’exige.
Conseil / Astuce
Consultez les exemples de compétences pour obtenir des exemples exécutables complets.
Compétences par classe
Les compétences basées sur des classes vous permettent de regrouper tous les composants de compétence ( nom, description, instructions, ressources et scripts) dans une seule classe C#. Cela facilite leur empaquetage et leur distribution en tant que packages NuGet : les équipes peuvent créer et expédier des compétences indépendamment, et les consommateurs les ajoutent avec dotnet add package et un seul .UseSkill() appel. Dérivez de AgentClassSkill<T> (où T est votre classe), puis annotez les propriétés avec [AgentSkillResource] et les méthodes avec [AgentSkillScript] pour une découverte automatique.
using System.ComponentModel;
using System.Text.Json;
using Microsoft.Agents.AI;
internal sealed class UnitConverterSkill : AgentClassSkill<UnitConverterSkill>
{
public override AgentSkillFrontmatter Frontmatter { get; } = new(
"unit-converter",
"Convert between common units using a multiplication factor. Use when asked to convert miles, kilometers, pounds, or kilograms.");
protected override string Instructions => """
Use this skill when the user asks to convert between units.
1. Review the conversion-table resource to find the correct factor.
2. Use the convert script, passing the value and factor from the table.
3. Present the result clearly with both units.
""";
[AgentSkillResource("conversion-table")]
[Description("Lookup table of multiplication factors for common unit conversions.")]
public string ConversionTable => """
# 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 |
""";
[AgentSkillScript("convert")]
[Description("Multiplies a value by a conversion factor and returns the result as JSON.")]
private static string ConvertUnits(double value, double factor)
{
double result = Math.Round(value * factor, 4);
return JsonSerializer.Serialize(new { value, factor, result });
}
}
Inscrivez la compétence basée sur la classe avec AgentSkillsProvider:
var skill = new UnitConverterSkill();
var skillsProvider = new AgentSkillsProvider(skill);
Lorsque l’attribut [AgentSkillResource] est appliqué à une propriété ou à une méthode, sa valeur de retour est utilisée comme contenu de ressource lorsque l’agent lit la ressource : utilisez une méthode lorsque le contenu doit être calculé au moment de la lecture. Lorsqu’elle [AgentSkillScript] est appliquée à une méthode, la méthode est appelée lorsque l’agent appelle le script. Utilisez [Description] de System.ComponentModel pour décrire chaque ressource et script pour l'agent.
Note
AgentClassSkill<T> prend également en charge le remplacement de Resources et des collections Scripts pour les scénarios où la découverte basée sur des attributs ne convient pas.
Compétences par classe
Les compétences basées sur des classes vous permettent de regrouper tous les composants de compétence ( nom, description, instructions, ressources et scripts) dans une classe Python unique. Cela permet de les empaqueter et de distribuer facilement en tant que packages PyPI : les équipes peuvent créer et expédier des compétences indépendamment, et les consommateurs les ajoutent avec pip install et un seul SkillsProvider() appel. Sous-classez ClassSkill, puis utilisez les décorateurs @ClassSkill.resource et @ClassSkill.script pour permettre la découverte automatique :
import json
from textwrap import dedent
from agent_framework import ClassSkill, SkillFrontmatter
class UnitConverterSkill(ClassSkill):
"""A unit-converter skill defined as a Python class."""
def __init__(self) -> None:
super().__init__(
frontmatter=SkillFrontmatter(
name="unit-converter",
description=(
"Convert between common units using a multiplication factor. "
"Use when asked to convert miles, kilometers, pounds, or kilograms."
),
),
)
@property
def instructions(self) -> str:
return dedent("""\
Use this skill when the user asks to convert between units.
1. Review the conversion-table resource to find the correct factor.
2. Use the convert script, passing the value and factor from the table.
3. Present the result clearly with both units.
""")
@property
@ClassSkill.resource
def conversion_table(self) -> str:
"""Lookup table of multiplication factors for common unit conversions."""
return dedent("""\
# 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 |
""")
@ClassSkill.script(name="convert", description="Multiplies a value by a conversion factor.")
def convert_units(self, value: float, factor: float) -> str:
"""Convert a value using a multiplication factor."""
result = round(value * factor, 4)
return json.dumps({"value": value, "factor": factor, "result": result})
Inscrivez la compétence basée sur la classe avec SkillsProvider:
from agent_framework import SkillsProvider
skill = UnitConverterSkill()
skills_provider = SkillsProvider(skill)
Lorsque @ClassSkill.resource est appliqué comme décorateur brut (sans argument), le nom de la méthode devient le nom de la ressource (avec les traits de soulignement remplacés par des traits d’union) et la docstring devient la description. Permet @ClassSkill.resource(name="...", description="...") de les définir explicitement. Le même modèle s’applique à @ClassSkill.script.
Les ressources peuvent être définies en tant que méthodes @property ou descripteurs standard. Lorsque vous utilisez @property, placez @property en premier et @ClassSkill.resource en second. Les valeurs de retour de ressource sont mises en cache après le premier accès.
Note
ClassSkill prend également en charge le remplacement explicite des propriétés resources et scripts afin de renvoyer directement des instances de InlineSkillResource et InlineSkillScript, dans les scénarios où la découverte par décorateur ne convient pas.
Compétences basées sur MCP
Note
Les compétences basées sur MCP nécessitent le Microsoft.Agents.AI.Mcp package NuGet. L’API de compétences MCP est expérimentale et peut changer dans les futures versions.
Les compétences peuvent être découvertes à partir de serveurs MCP (Model Context Protocol) qui exposent des ressources de compétence sous le schéma d’URI skill:// . Le serveur MCP publie des compétences via un skill://index.json document de découverte et l’infrastructure extrait le contenu des compétences à la demande.
Les compétences basées sur MCP prennent en charge deux types d’entrée d’index :
-
skill-md: la ressourceSKILL.mdde la compétence et les ressources homologues sont récupérées à la demande depuis le serveur MCP. -
archive- La compétence est distribuée en tant qu’archive empaquetée unique (ZIP, TAR ou tar compressé par gzip) téléchargée et décompressée localement.
Utilisation de base
Utilisez la méthode d’extension UseMcpSkills sur AgentSkillsProviderBuilder pour ajouter une source de compétences MCP :
using Microsoft.Agents.AI;
using ModelContextProtocol.Client;
// Connect to the MCP server
await using McpClient client = await McpClient.CreateAsync(
new StdioClientTransport(new()
{
Name = "skills-server",
Command = "dotnet",
Arguments = [skillsServerPath, "--server"],
}));
// Build a skills provider that discovers skills over MCP
var skillsProvider = new AgentSkillsProviderBuilder()
.UseMcpSkills(client)
.Build();
// Create an agent with the MCP skills
AIAgent agent = new AzureOpenAIClient(new Uri(endpoint), new DefaultAzureCredential())
.GetResponsesClient()
.AsAIAgent(new ChatClientAgentOptions
{
Name = "SkillsAgent",
ChatOptions = new()
{
Instructions = "You are a helpful assistant. Use available skills to answer the user.",
},
AIContextProviders = [skillsProvider],
},
model: deploymentName);
Compétences de type archivage
Pour les compétences de type archive, utilisez AgentMcpSkillsSourceOptions (du package Microsoft.Agents.AI.Mcp) pour configurer le comportement d’extraction :
var skillsProvider = new AgentSkillsProviderBuilder()
.UseMcpSkills(client, new AgentMcpSkillsSourceOptions
{
ArchiveSkillsDirectory = Path.Combine(AppContext.BaseDirectory, "extracted-skills"),
ArchiveMaxFileCount = 50,
ArchiveMaxSizeBytes = 2 * 1024 * 1024, // 2 MB
})
.Build();
AgentMcpSkillsSourceOptions expose les propriétés suivantes pour contrôler l’extraction d’archive :
-
ArchiveSkillsDirectory- Répertoire de base pour les archives extraites. Par défaut, un sous-répertoire unique est créé dans le répertoire de travail actuel, pour chaque instance source, afin d’éviter les collisions entre plusieurs sources. -
ArchiveResourceExtensions- Extensions autorisées pour les ressources dans les archives extraites. Par défaut :.md,.json,.yaml,.yml,.csv,.xml,.txt. -
ArchiveResourceSearchDepth- Jusqu’à quelle profondeur rechercher des ressources dans chaque répertoire de compétences extrait. La valeur par défaut est2. -
ArchiveMaxFileCount- Nombre maximal de fichiers par archive. Les archives dépassant cette limite sont ignorées. La valeur par défaut est20. -
ArchiveMaxSizeBytes- Taille de téléchargement maximale par archive. La valeur par défaut est1 MB. -
ArchiveMaxUncompressedSizeBytes- Taille totale totale non compressée par archive. La valeur par défaut est1 MB.
Important
Les scripts regroupés dans les compétences de type archive ne sont jamais exécutés. Il s’agit d’une mesure de sécurité délibérée : le contenu exécutable des serveurs MCP distants nécessite une approbation explicite.
Compétences basées sur MCP
Note
Les compétences basées sur MCP sont expérimentales et peuvent changer dans les futures versions. L’utilisation de MCPSkillsSource génère un FutureWarning derrière le flag de fonctionnalité MCP_SKILLS.
Les compétences peuvent être découvertes à partir de serveurs MCP (Model Context Protocol) qui exposent des ressources de compétence sous le schéma d’URI skill:// . Le serveur MCP annonce des compétences via un document de découverte skill://index.json, et le framework récupère à la demande le corps SKILL.md de chaque compétence via resources/read.
Encapsulez un MCP ClientSession dans MCPSkillsSource et passez-le à SkillsProvider:
import os
from agent_framework import Agent, MCPSkillsSource, SkillsProvider, ToolApprovalMiddleware
from agent_framework.foundry import FoundryChatClient
from azure.identity import AzureCliCredential
from mcp.client.session import ClientSession
from mcp.client.streamable_http import streamable_http_client
mcp_url = os.environ["MCP_SKILLS_SERVER_URL"]
# Connect to the MCP server over streamable HTTP
async with streamable_http_client(url=mcp_url) as (read, write, _), ClientSession(read, write) as session:
await session.initialize()
# MCPSkillsSource reads skill://index.json and creates one skill per
# skill-md entry; SKILL.md bodies are fetched on demand.
skills_provider = SkillsProvider(MCPSkillsSource(client=session))
client = FoundryChatClient(
project_endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"],
model=os.environ.get("FOUNDRY_MODEL", "gpt-4o-mini"),
credential=AzureCliCredential(),
)
async with Agent(
client=client,
instructions="You are a helpful assistant. Use available skills to answer the user.",
context_providers=[skills_provider],
middleware=[ToolApprovalMiddleware(auto_approval_rules=[SkillsProvider.all_tools_auto_approval_rule])],
) as agent:
response = await agent.run("...")
Note
MCPSkillsSource Python prend uniquement en charge les entrées d’index skill-md (les entrées d’index de tout autre type sont ignorées sans avertissement). Contrairement à l’implémentation .NET, elle ne prend pas en charge les compétences de type archive. Si skill://index.json est absent, illisible, vide ou ne peut pas être analysé, la source renvoie une liste vide.
Important
Un serveur MCP externe contrôle quel contenu de compétences — y compris les instructions et les scripts que l’agent peut exécuter — parvient à l’agent. Connectez-vous MCPSkillsSource uniquement aux serveurs que vous avez vérifiés et approuvés, et traitez leurs réponses comme une entrée non approuvée.
Sources de compétence
Un AgentSkillsProvider récupère des compétences à partir d’une ou plusieurs sources - objets qui implémentent AgentSkillsSource. Les sources appartiennent à deux catégories : les sources feuilles qui découvrent ou contiennent des compétences (comme AgentFileSkillsSource pour les compétences basées sur des fichiers) et des décorateurs qui transforment la sortie d’une autre source (agrégation, déduplication, mise en cache et filtrage). Vous pouvez également créer une source personnalisée.
Chaque source implémente une méthode unique - GetSkillsAsync(AgentSkillsSourceContext context, CancellationToken cancellationToken = default). Il AgentSkillsSourceContext contient des informations sur la requête actuelle :
-
Agent- l’instanceAIAgentdemandant des compétences. -
Session- leAgentSessionassocié à l’invocation, ounulllorsqu’il n’y a pas de session.
Ce contexte est disponible tout au long du pipeline source. Ainsi, un prédicat FilteringAgentSkillsSource ou une source personnalisée peuvent s’appuyer dessus dans leur logique, par exemple pour renvoyer un ensemble de compétences différent selon l’agent demandeur.
Sources terminales
AgentFileSkillsSource
Découvre les compétences à partir des fichiers SKILL.md présents sur le disque. Accepte un ou plusieurs chemins d’accès de répertoire, un exécuteur de script facultatif et facultatif AgentFileSkillsSourceOptions (documenté dans les compétences basées sur des fichiers).
var source = new AgentFileSkillsSource(
[Path.Combine(AppContext.BaseDirectory, "skills")],
scriptRunner: SubprocessScriptRunner.RunAsync,
options: new AgentFileSkillsSourceOptions { SearchDepth = 3 });
AgentInMemorySkillsSource
Encapsule en mémoire les instances AgentSkill (définies dans le code ou basées sur des classes).
var source = new AgentInMemorySkillsSource([volumeConverterSkill, temperatureConverter]);
Combinateurs
AggregatingAgentSkillsSource
Combine plusieurs sources en une seule. Les compétences sont retournées dans l’ordre d’inscription sans déduplication ni filtrage appliqué.
var aggregated = new AggregatingAgentSkillsSource([fileSource, inMemorySource]);
Décorateurs
Les décorateurs encapsulent une source interne et transforment sa sortie. Ils peuvent être chaînés pour créer un pipeline.
DeduplicatingAgentSkillsSource
Supprime les noms de compétences en double (sans tenir compte de la casse, la première occurrence est conservée). Les doublons sont consignés au niveau d'avertissement.
var deduplicated = new DeduplicatingAgentSkillsSource(innerSource);
CachingAgentSkillsSource
Met en cache la liste des compétences retournée par la source interne. Les appelants simultanés sont sérialisés par clé de cache afin qu’une seule extraction s’exécute à la fois. Accepte CachingAgentSkillsSourceOptions en option :
-
RefreshInterval(TimeSpan?) - lorsqu’elle est définie, les résultats mis en cache expirent après cet intervalle et la source interne est de nouveau invoquée. Quandnull(valeur par défaut), les résultats mis en cache n’expirent jamais. -
CacheIsolationKeySelector(Func<AgentSkillsSourceContext, string?>?) : retourne une clé de cache pour isoler les résultats mis en cache par contexte (par exemple, par locataire). Quandnull, tous les appelants partagent un seul compartiment de cache.
var cached = new CachingAgentSkillsSource(innerSource, new CachingAgentSkillsSourceOptions
{
RefreshInterval = TimeSpan.FromMinutes(5)
});
FilteringAgentSkillsSource
Applique un prédicat pour inclure ou exclure des compétences. Le prédicat reçoit la compétence et un AgentSkillsSourceContext.
var filtered = new FilteringAgentSkillsSource(
innerSource,
(skill, context) => skill.Frontmatter.Name != "experimental-skill");
Sources personnalisées
Lorsque les sources intégrées ne couvrent pas votre scénario, implémentez vos propres sources. Sous-classe AgentSkillsSource pour une source feuille (une qui produit des compétences à partir d’une nouvelle origine telle qu’une base de données ou un service distant), ou sous-classe DelegatingAgentSkillsSource pour un décorateur qui transforme la sortie d’une autre source.
Source de feuille
Dérivez de AgentSkillsSource et implémentez GetSkillsAsync. L’argument AgentSkillsSourceContext permet à la source d’adapter son résultat à la requête actuelle, par exemple, de retourner un ensemble différent de compétences en fonction de l’agent demandeur. Remplacez Dispose(bool) si la source possède des ressources telles qu’un client ou une connexion.
public sealed class TenantSkillsSource : AgentSkillsSource
{
private readonly ISkillStore _store;
public TenantSkillsSource(ISkillStore store)
{
_store = store;
}
public override async Task<IList<AgentSkill>> GetSkillsAsync(
AgentSkillsSourceContext context,
CancellationToken cancellationToken = default)
{
// Use the requesting agent to decide which skills to load.
var tenantId = context.Agent.Name ?? "default";
return await _store.GetSkillsForTenantAsync(tenantId, cancellationToken);
}
}
Décorateur personnalisé
Dérivez de DelegatingAgentSkillsSource, appelez InnerSource.GetSkillsAsyncet transformez ou observez le résultat. Il s’agit du même modèle que celui utilisé par les décorateurs intégrés de mise en cache, de déduplication et de filtrage. Par exemple, un décorateur qui enregistre le nombre de compétences retournées par requête sans modifier le résultat :
public sealed class MetricsAgentSkillsSource : DelegatingAgentSkillsSource
{
private readonly ILogger<MetricsAgentSkillsSource> _logger;
public MetricsAgentSkillsSource(
AgentSkillsSource innerSource,
ILogger<MetricsAgentSkillsSource> logger)
: base(innerSource)
{
_logger = logger;
}
public override async Task<IList<AgentSkill>> GetSkillsAsync(
AgentSkillsSourceContext context,
CancellationToken cancellationToken = default)
{
var skills = await base.GetSkillsAsync(context, cancellationToken);
_logger.LogInformation(
"Returned {SkillCount} skills to agent {AgentName}.",
skills.Count,
context.Agent.Name);
return skills;
}
}
Les deux sources personnalisées peuvent être transmises directement à AgentSkillsProvider ou imbriquées dans un pipeline plus vaste, tout comme les sources intégrées.
Construction du fournisseur
AgentSkillsProvider est le composant qui expose les compétences à un agent. Il encapsule une ou plusieurs sources et enregistre les outils load_skill, read_skill_resource et run_skill_script. Il existe trois façons de créer un :
-
AgentSkillsProviderBuilder- compose plusieurs types de compétences en un seul fournisseur avec agrégation automatique, déduplication, mise en cache et filtrage facultatif. Idéal pour les scénarios qui combinent des compétences basées sur des fichiers, définies par le code, basées sur des classes et MCP. -
Composition directe de la source - construisez vous-même le pipeline de la source à l’aide des classes publiques
AgentSkillsSource. Aucune mise en cache ou déduplication automatique n’est appliquée. Vous contrôlez le pipeline complet. Mieux quand vous avez besoin de contrôler l’ordre, la logique conditionnelle ou le comportement de décorateur personnalisé. - Constructeurs pratiques : créez un fournisseur directement à partir d’un chemin d’accès de fichier ou d’une ou plusieurs instances de compétence. Applique automatiquement la déduplication et la mise en cache. Idéal pour les scénarios à source unique.
Utilisation de AgentSkillsProviderBuilder
Utilisez AgentSkillsProviderBuilder quand vous avez besoin de l’un des éléments suivants :
-
Types de compétences mixtes : combinez des compétences basées sur des fichiers, définies par le code (
AgentInlineSkill), basées sur des classes (AgentClassSkill) et MCP dans un seul fournisseur. - Filtrage des compétences : inclure ou exclure des compétences à l’aide d’un prédicat.
Types de compétences mixtes
Combinez plusieurs types de compétences dans un fournisseur en chaînant UseFileSkill, UseSkill, UseMcpSkillset UseFileScriptRunner:
var skillsProvider = new AgentSkillsProviderBuilder()
.UseFileSkill(Path.Combine(AppContext.BaseDirectory, "skills")) // file-based skills
.UseSkill(volumeConverterSkill) // AgentInlineSkill
.UseSkill(temperatureConverter) // AgentClassSkill
.UseMcpSkills(mcpClient) // MCP-based skills
.UseFileScriptRunner(SubprocessScriptRunner.RunAsync) // runner for file scripts
.Build();
Filtrage des compétences
Utilisez cette option UseFilter pour inclure uniquement les compétences qui répondent à vos critères , par exemple, pour charger des compétences à partir d’un répertoire partagé, mais exclure celles expérimentales :
var approvedSkillNames = new HashSet<string> { "expense-report", "code-style" };
var skillsProvider = new AgentSkillsProviderBuilder()
.UseFileSkill(Path.Combine(AppContext.BaseDirectory, "skills"))
.UseFilter((skill, context) => approvedSkillNames.Contains(skill.Frontmatter.Name))
.Build();
Composer directement des sources
Lorsque le générateur n’offre pas le contrôle dont vous avez besoin, composez vous-même des classes source et transmettez le pipeline obtenu à AgentSkillsProvider. Consultez les sources de compétence pour obtenir la liste complète des sources disponibles et leurs options.
L'exemple suivant crée un pipeline multi-source comparable, mais vous donne un contrôle explicite sur chaque décorateur :
// 1. Create the leaf sources
var fileSource = new AgentFileSkillsSource(
[Path.Combine(AppContext.BaseDirectory, "skills")],
SubprocessScriptRunner.RunAsync);
var inMemorySource = new AgentInMemorySkillsSource(
[volumeConverterSkill, temperatureConverter]);
// 2. Aggregate them into one source
var aggregated = new AggregatingAgentSkillsSource([fileSource, inMemorySource]);
// 3. Add deduplication and caching decorators
var deduplicated = new DeduplicatingAgentSkillsSource(aggregated);
var cached = new CachingAgentSkillsSource(deduplicated);
// 4. Create the provider, transferring source ownership
var skillsProvider = new AgentSkillsProvider(
cached,
options: new AgentSkillsProviderOptions(),
ownsSource: true);
Note
Lorsque ownsSource est true, l’élimination du fournisseur entraîne également celle de l’intégralité du pipeline source. Définissez-la sur false si vous gérez vous-même le cycle de vie de la source.
Constructeurs de commodité
Pour les scénarios à source unique, utilisez directement les AgentSkillsProvider constructeurs. Celles-ci appliquent automatiquement la déduplication et la mise en cache sans nécessiter de composition de source manuelle ou de générateur.
À partir d’un chemin d’accès au fichier :
var skillsProvider = new AgentSkillsProvider(
Path.Combine(AppContext.BaseDirectory, "skills"),
scriptRunner: SubprocessScriptRunner.RunAsync);
À partir d'instances de compétences :
var skillsProvider = new AgentSkillsProvider(volumeConverterSkill, temperatureConverter);
Sources de compétence
Un SkillsProvider récupère des compétences à partir d’une ou de plusieurs sources - des objets dérivés de SkillsSource. Les sources appartiennent à deux catégories : les sources feuilles qui découvrent ou contiennent des compétences (comme FileSkillsSource pour les compétences basées sur des fichiers) et des décorateurs qui transforment la sortie d’une autre source (agrégation, déduplication, mise en cache et filtrage). Vous pouvez également créer une source personnalisée.
Chaque source implémente une méthode unique - async def get_skills(self, context: SkillsSourceContext) -> list[Skill]. Il SkillsSourceContext contient des informations sur la requête actuelle :
-
agent- l’agent (SupportsAgentRun) demandant des compétences. -
session- leAgentSessionassocié à l’invocation, ouNonelorsqu’il n’y a pas de session.
Ce contexte transite par l’ensemble du pipeline source, de sorte qu’un prédicat FilteringSkillsSource ou une source personnalisée puisse fonder sa logique sur ce contexte, par exemple en renvoyant un ensemble de compétences différent selon l’agent demandeur.
Sources terminales
-
FileSkillsSource- détecte les compétences à partir des fichiersSKILL.mdsur le disque. Accepte un ou plusieurs chemins d’accès de répertoire, une option facultativescript_runneret des options de découverte (resource_extensions,script_extensions,search_depth,resource_filter,script_filter) documentées dans les compétences basées sur des fichiers. -
InMemorySkillsSource- encapsule lesSkillinstances (définies par le code ou basées sur des classes) en mémoire. -
MCPSkillsSource- découvre les compétences à partir d’un serveur MCP (voir compétences basées sur MCP).
from pathlib import Path
from agent_framework import FileSkillsSource, InMemorySkillsSource
file_source = FileSkillsSource(Path(__file__).parent / "skills", script_runner=my_runner)
in_memory_source = InMemorySkillsSource([volume_converter_skill, temperature_converter_skill])
combinateur
AggregatingSkillsSource combine plusieurs sources en une seule. Les compétences sont retournées dans l’ordre d’inscription sans déduplication ni filtrage appliqué.
from agent_framework import AggregatingSkillsSource
aggregated = AggregatingSkillsSource([file_source, in_memory_source])
Décorateurs
Les décorateurs encapsulent une source interne et transforment sa sortie. Ils peuvent être chaînés pour créer un pipeline.
-
DeduplicatingSkillsSource- supprime les noms de compétences en double (sans distinction entre majuscules et minuscules, la première occurrence est conservée). Les doublons sont consignés au niveau d'avertissement. -
CachingSkillsSource- met en cache la liste des compétences retournée par la source interne. Les appels simultanés pour une même clé de cache partagent une seule récupération en cours, de sorte que la source sous-jacente n’est interrogée qu’une seule fois au maximum par clé. Accepte deux arguments de mot clé facultatifs :-
refresh_interval(timedelta | None) : lorsqu’elle est définie, une liste mise en cache est traitée comme obsolète une fois qu’elle est antérieure à l’intervalle, de sorte que l’appel suivant interroge à nouveau la source interne. QuandNone(valeur par défaut), les résultats mis en cache n’expirent jamais. Utile pour les sources internes dont les compétences changent au cours de la durée de vie du processus, telles queMCPSkillsSource. -
cache_isolation_key_selector(Callable[[SkillsSourceContext], str | None]) : dérive une clé de cache du contexte pour isoler les résultats mis en cache (par exemple, par agent ou locataire). Les clés doivent être à faible cardinalité et stables. RenvoyerNone(ou le laisser àNone) utilise un cache partagé unique.
-
-
FilteringSkillsSource- applique un prédicat pour inclure ou exclure des compétences. Le prédicat reçoit la compétence et unSkillsSourceContext:Callable[[Skill, SkillsSourceContext], bool].
from datetime import timedelta
from agent_framework import (
CachingSkillsSource,
DeduplicatingSkillsSource,
FilteringSkillsSource,
)
deduplicated = DeduplicatingSkillsSource(aggregated)
cached = CachingSkillsSource(
deduplicated,
refresh_interval=timedelta(minutes=5),
cache_isolation_key_selector=lambda context: context.agent.name,
)
filtered = FilteringSkillsSource(
cached,
predicate=lambda skill, context: skill.frontmatter.name != "experimental-skill",
)
Sources personnalisées
Lorsque les sources intégrées ne couvrent pas votre scénario, implémentez vos propres sources. Sous-classe SkillsSource pour une source feuille (une qui produit des compétences à partir d’une nouvelle origine telle qu’une base de données ou un service distant), ou sous-classe DelegatingSkillsSource pour un décorateur qui transforme la sortie d’une autre source.
Source de feuille
Dérivez de SkillsSource et implémentez get_skills. L’argument SkillsSourceContext permet à la source d’adapter son résultat à la requête actuelle , par exemple, de retourner un ensemble différent de compétences en fonction de l’agent demandeur :
from agent_framework import Skill, SkillsSource, SkillsSourceContext
class TenantSkillsSource(SkillsSource):
def __init__(self, store: "SkillStore") -> None:
self._store = store
async def get_skills(self, context: SkillsSourceContext) -> list[Skill]:
# Use the requesting agent to decide which skills to load.
tenant_id = context.agent.name or "default"
return await self._store.get_skills_for_tenant(tenant_id)
Décorateur personnalisé
Dérivez de DelegatingSkillsSource, appelez self.inner_source.get_skills(context)et transformez ou observez le résultat. Il s’agit du même modèle que celui utilisé par les décorateurs intégrés de mise en cache, de déduplication et de filtrage. Par exemple, un décorateur qui enregistre le nombre de compétences retournées par requête sans modifier le résultat :
import logging
from agent_framework import DelegatingSkillsSource, Skill, SkillsSourceContext
logger = logging.getLogger(__name__)
class MetricsSkillsSource(DelegatingSkillsSource):
async def get_skills(self, context: SkillsSourceContext) -> list[Skill]:
skills = await self.inner_source.get_skills(context)
logger.info("Returned %d skills to agent %s.", len(skills), context.agent.name)
return skills
Les deux sources personnalisées peuvent être transmises directement à SkillsProvider ou imbriquées dans un pipeline plus vaste, tout comme les sources intégrées.
Construction du fournisseur
SkillsProvider est le composant qui expose les compétences à un agent. Il encapsule une ou plusieurs sources et enregistre les outils load_skill, read_skill_resource et run_skill_script. Il existe trois façons de créer un :
-
À partir d’instances de compétences - passez au constructeur une unique
Skillou une séquence de compétences. Idéal pour les compétences définies par le code et basées sur des classes. Applique automatiquement la déduplication et la mise en cache. -
À partir de chemins de fichiers, utilisez la fabrique
SkillsProvider.from_paths(). Idéal pour les compétences basées sur des fichiers à source unique. Applique automatiquement la déduplication et la mise en cache. -
Composition directe de la source - construisez vous-même le pipeline de source à l’aide des classes publiques
SkillsSourceet passez-le au constructeur. Vous contrôlez le pipeline complet. Mieux quand vous avez besoin de contrôler l’ordre, la logique conditionnelle, les clés de mise en cache ou le comportement de décorateur personnalisé.
À partir des instances de compétence
from agent_framework import SkillsProvider
# Single skill or a list of skills - deduplicated and cached automatically.
skills_provider = SkillsProvider(volume_converter_skill)
skills_provider = SkillsProvider([volume_converter_skill, temperature_converter_skill])
À partir des chemins d’accès aux fichiers
from pathlib import Path
from agent_framework import SkillsProvider
skills_provider = SkillsProvider.from_paths(
skill_paths=Path(__file__).parent / "skills",
script_runner=my_runner,
)
Composer directement des sources
Lorsque vous avez besoin d’un contrôle total, composez vous-même des classes source et transmettez le pipeline résultant à SkillsProvider. Consultez les sources de compétence pour obtenir la liste complète des sources disponibles et leurs options.
L’exemple ci-dessous construit un pipeline multi-source permettant un contrôle explicite de chaque décorateur. L’exemple utilise des objets fictifs :
-
volume_converter_skill- n’importe quelleInlineSkillinstance, générée comme indiqué dans les compétences définies par le code. -
temperature_converter_skill- n’importe quelleClassSkillinstance, générée comme indiqué dans les compétences basées sur la classe. -
my_runner- unSkillScriptRunnerappelable, tel que défini dans Exécution du script.
from pathlib import Path
from agent_framework import (
AggregatingSkillsSource,
CachingSkillsSource,
DeduplicatingSkillsSource,
FileSkillsSource,
InMemorySkillsSource,
SkillsProvider,
)
# 1. Create the leaf sources
file_source = FileSkillsSource(Path(__file__).parent / "skills", script_runner=my_runner)
in_memory_source = InMemorySkillsSource([volume_converter_skill, temperature_converter_skill])
# 2. Aggregate them, then add deduplication and caching decorators
aggregated = AggregatingSkillsSource([file_source, in_memory_source])
deduplicated = DeduplicatingSkillsSource(aggregated)
cached = CachingSkillsSource(deduplicated)
# 3. Create the provider from the composed pipeline
skills_provider = SkillsProvider(cached)
Important
Un SkillsSource fourni par l’appelant est utilisé tel quel : il n’est pas automatiquement dédupliqué ni encapsulé dans un CachingSkillsSource. La mise en cache automatique d’une source sensible au contexte dans un unique bucket partagé pourrait réutiliser les compétences d’un agent ou d’un locataire pour un autre agent ou locataire. Composez DeduplicatingSkillsSource et CachingSkillsSource (éventuellement avec un cache_isolation_key_selector) vous-même lorsque vous en avez besoin. La déduplication et la mise en cache automatiques s’appliquent uniquement lorsque vous transmettez directement des compétences ou des chemins d’accès aux fichiers (options 1 et 2 ci-dessus).
Types de compétences mixtes
Combinez des compétences basées sur des fichiers, définies dans le code et basées sur des classes au sein d’un fournisseur à l’aide de AggregatingSkillsSource :
from pathlib import Path
from agent_framework import (
AggregatingSkillsSource,
DeduplicatingSkillsSource,
FileSkillsSource,
InMemorySkillsSource,
SkillsProvider,
)
temperature_converter_skill = TemperatureConverterSkill()
skills_provider = SkillsProvider(
DeduplicatingSkillsSource(
AggregatingSkillsSource([
FileSkillsSource(
Path(__file__).parent / "skills",
script_runner=my_runner,
),
InMemorySkillsSource([volume_converter_skill, temperature_converter_skill]),
])
)
)
Filtrage des compétences
Utilisez FilteringSkillsSource pour contrôler les compétences auxquelles l’agent a accès. Le prédicat reçoit chaque Skill et le SkillsSourceContext, et renvoie True pour inclure la compétence. Par exemple, pour charger des compétences à partir d’un répertoire partagé, mais masquer un répertoire expérimental :
from pathlib import Path
from agent_framework import (
DeduplicatingSkillsSource,
FileSkillsSource,
FilteringSkillsSource,
SkillsProvider,
)
skills_provider = SkillsProvider(
DeduplicatingSkillsSource(
FilteringSkillsSource(
FileSkillsSource(Path(__file__).parent / "skills"),
predicate=lambda skill, context: skill.frontmatter.name != "experimental-tools",
)
)
)
Comportement de mise en cache
Par défaut, le générateur encapsule le pipeline de sources dans un CachingAgentSkillsSource qui met en cache la liste des compétences renvoyées par les sources sous-jacentes. Une fois les compétences résolues lors de la première requête, les requêtes suivantes réutilisent la liste mise en cache sans interroger de nouveau les sources. Pour désactiver la mise en cache (par exemple, pendant le développement, lorsque les définitions des compétences changent fréquemment), utilisez DisableCaching() sur le générateur :
var skillsProvider = new AgentSkillsProviderBuilder()
.UseFileSkill(Path.Combine(AppContext.BaseDirectory, "skills"))
.UseFileScriptRunner(SubprocessScriptRunner.RunAsync)
.DisableCaching()
.Build();
Note
La désactivation de la mise en cache est utile pendant le développement lorsque le contenu des compétences change fréquemment. En production, laissez la mise en cache activée (valeur par défaut) pour améliorer les performances.
Comportement de mise en cache
Par défaut, les outils de compétence et les instructions sont mis en cache après la première génération. Définissez disable_caching=True pour forcer une reconstruction à chaque appel :
skills_provider = SkillsProvider.from_paths(
skill_paths=Path(__file__).parent / "skills",
disable_caching=True,
)
disable_caching est également disponible sur le constructeur SkillsProvider pour les compétences définies par le code et basées sur des classes.
Pour maintenir la mise en cache activée tout en redécouvrant régulièrement les compétences (par exemple, lorsqu’une source basée sur un fichier ou une source MCP change pendant la durée de vie du processus), transmettez cache_refresh_interval. Le cache intégré est traité comme obsolète une fois qu’il est antérieur à l’intervalle, de sorte que l’exécution suivante réexécute la source :
from datetime import timedelta
skills_provider = SkillsProvider.from_paths(
skill_paths=Path(__file__).parent / "skills",
cache_refresh_interval=timedelta(minutes=5),
)
cache_refresh_interval affecte uniquement le cache que le fournisseur génère en interne (à partir de compétences ou de chemins de fichiers) ; il est ignoré lorsque disable_caching=True et n’a aucun effet sur un SkillsSource fourni par l’appelant (pour cela, composez votre propre CachingSkillsSource avec un refresh_interval).
Note
La désactivation de la mise en cache est utile pendant le développement lorsque le contenu des compétences change fréquemment. En production, laissez la mise en cache activée (valeur par défaut) pour améliorer les performances.
Approbation de l’outil
Tous les outils exposés par AgentSkillsProvider (load_skill, read_skill_resource, run_skill_script) nécessitent l’approbation par défaut. Lorsqu’un appel d’outil nécessite une approbation, l’agent se met en pause et retourne un ToolApprovalRequestContent au lieu de l’exécuter immédiatement. Utilisez un UseToolApproval intergiciel avec des règles d’approbation automatique pour contourner de manière sélective les invites pour les opérations approuvées :
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
var skillsProvider = new AgentSkillsProvider(
Path.Combine(AppContext.BaseDirectory, "skills"),
SubprocessScriptRunner.RunAsync);
AIAgent agent = new AzureOpenAIClient(new Uri(endpoint), new DefaultAzureCredential())
.GetResponsesClient()
.AsAIAgent(new ChatClientAgentOptions
{
Name = "SkillsAgent",
ChatOptions = new() { Instructions = "You are a helpful assistant." },
AIContextProviders = [skillsProvider],
},
model: deploymentName)
.AsBuilder()
.UseToolApproval(new ToolApprovalAgentOptions
{
// Auto-approve read-only skill tools (load_skill, read_skill_resource).
// run_skill_script still requires explicit user approval.
AutoApprovalRules = [AgentSkillsProvider.ReadOnlyToolsAutoApprovalRule],
})
.Build();
Pour approuver automatiquement tous les outils de compétence, notamment l’exécution de script :
.UseToolApproval(new ToolApprovalAgentOptions
{
AutoApprovalRules = [AgentSkillsProvider.AllToolsAutoApprovalRule],
})
Désactivation de l’approbation pour des outils spécifiques
Permet AgentSkillsProviderOptions de désactiver l’approbation des outils individuels, en les supprimant entièrement du flux d’approbation :
var skillsProvider = new AgentSkillsProvider(
Path.Combine(AppContext.BaseDirectory, "skills"),
SubprocessScriptRunner.RunAsync,
options: new AgentSkillsProviderOptions
{
DisableLoadSkillApproval = true,
DisableReadSkillResourceApproval = true,
// DisableRunSkillScriptApproval remains false - scripts still require approval
});
Lorsque certains outils nécessitent une approbation et que d’autres ne sont pas dans la même réponse, le modèle peut appeler les deux types simultanément. Définissez EnableNonApprovalRequiredFunctionBypassing pour que les outils ne nécessitant pas d’approbation s’exécutent immédiatement, tandis que l’utilisateur n’est sollicité que pour les autres :
AIAgent agent = new AzureOpenAIClient(new Uri(endpoint), new DefaultAzureCredential())
.GetResponsesClient()
.AsAIAgent(new ChatClientAgentOptions
{
Name = "SkillsAgent",
ChatOptions = new() { Instructions = "You are a helpful assistant." },
AIContextProviders = [skillsProvider],
EnableNonApprovalRequiredFunctionBypassing = true,
},
model: deploymentName)
.AsBuilder()
.UseToolApproval()
.Build();
Gestion des demandes d’approbation
Lorsque les outils nécessitent une approbation (et qu’aucune règle d’approbation automatique ne correspond), l’agent retourne ToolApprovalRequestContent les éléments qui doivent être approuvés ou rejetés avant de continuer :
AgentSession session = await agent.CreateSessionAsync();
AgentResponse response = await agent.RunAsync("Convert 26.2 miles to kilometers", session);
List<ToolApprovalRequestContent> approvalRequests = response.Messages
.SelectMany(m => m.Contents)
.OfType<ToolApprovalRequestContent>()
.ToList();
while (approvalRequests.Count > 0)
{
List<ChatMessage> userInputResponses = approvalRequests
.ConvertAll(request =>
{
var toolCall = (FunctionCallContent)request.ToolCall;
Console.WriteLine($"Approve {toolCall.Name}? (Y/N)");
bool approved = Console.ReadLine()?.Equals("Y", StringComparison.OrdinalIgnoreCase) ?? false;
return new ChatMessage(ChatRole.User, [request.CreateResponse(approved)]);
});
response = await agent.RunAsync(userInputResponses, session);
approvalRequests = response.Messages
.SelectMany(m => m.Contents)
.OfType<ToolApprovalRequestContent>()
.ToList();
}
Détails de l’erreur de script
Par défaut, lorsqu’une exécution de script de compétence échoue, l’exception se propage au sous-jacent FunctionInvokingChatClient. Si la propriété IncludeDetailedErrors est définie sur true, le message d’exception est transmis au modèle, ce qui lui permet de se corriger en réessayant avec des arguments différents :
AIAgent agent = new AzureOpenAIClient(new Uri(endpoint), new DefaultAzureCredential())
.GetResponsesClient()
.AsAIAgent(
options: new ChatClientAgentOptions
{
Name = "SkillsAgent",
ChatOptions = new()
{
Instructions = "You are a helpful assistant.",
},
AIContextProviders = [skillsProvider],
},
model: deploymentName,
clientFactory: client => client
.AsBuilder()
.UseFunctionInvocation(configure: (c) => c.IncludeDetailedErrors = true)
.Build());
Si vous ne pouvez pas configurer FunctionInvokingChatClient directement, définissez AgentSkillsProviderOptions.IncludeDetailedErrors à la place. Cela intercepte l’exception au niveau du fournisseur de compétences et retourne directement le message d’erreur au modèle :
var skillsProvider = new AgentSkillsProvider(
Path.Combine(AppContext.BaseDirectory, "skills"),
SubprocessScriptRunner.RunAsync,
options: new AgentSkillsProviderOptions
{
IncludeDetailedErrors = true,
});
Avertissement
L’une ou l’autre approche peut divulguer des détails d’exception bruts au modèle. Les messages d’exception peuvent contenir des informations sensibles telles que des chaînes de connexion, des chemins d’accès de fichier ou des noms de service internes. De plus, si des compétences ou des scripts proviennent de sources non fiables, un script malveillant pourrait lever une exception dont le message contient une charge utile d'injection de prompt.
Tous les outils exposés par SkillsProvider (load_skill, read_skill_resourceet run_skill_script) nécessitent l’approbation par défaut. Lorsqu’un appel d’outil nécessite une approbation, l’agent se met en pause et renvoie les demandes d’approbation via result.user_input_requests plutôt que de les exécuter immédiatement. Vous approuvez ou rejetez chaque demande avec request.to_function_approval_response(approved=...) et renvoyez les réponses :
from textwrap import dedent
from agent_framework import Agent, Content, InlineSkill, Message, SkillFrontmatter, SkillsProvider
deployment_skill = InlineSkill(
frontmatter=SkillFrontmatter(
name="deployment",
description="Tools for deploying application versions to production",
),
instructions=dedent("""\
Use this skill when the user asks to deploy an application.
Run the deploy script with the version and environment parameters.
"""),
)
@deployment_skill.script
def deploy(version: str, environment: str = "staging") -> str:
"""Deploy the application to the specified environment."""
return f"Deployed version {version} to {environment}"
# All skill tools require approval by default.
skills_provider = SkillsProvider(deployment_skill)
async with Agent(
client=client,
instructions="You are a deployment assistant.",
context_providers=[skills_provider],
) as agent:
# Use a session so the agent retains context across approval round-trips
session = agent.create_session()
result = await agent.run("Deploy version 2.5.0 to production", session=session)
# Collect a response for every request and send them in one run so the
# loop always makes progress.
while result.user_input_requests:
approval_responses: list[Content] = []
for request in result.user_input_requests:
if request.function_call is None:
approval_responses.append(request.to_function_approval_response(approved=False))
continue
print(f"Approve {request.function_call.name}? Args: {request.function_call.arguments}")
# In a real application, prompt the user here.
approval_responses.append(request.to_function_approval_response(approved=True))
result = await agent.run(Message(role="user", contents=approval_responses), session=session)
print(result)
Lorsqu’un appel d’outil est rejeté (approved=False), l’agent est informé que l’utilisateur a refusé et peut répondre en conséquence.
Approbation automatique des outils approuvés
Au lieu de demander une confirmation pour chaque appel, installez ToolApprovalMiddleware avec l’une des règles statiques d’approbation automatique proposées par SkillsProvider. Cela permet aux outils en lecture seule de s’exécuter automatiquement tout en invitant à exécuter des scripts :
from agent_framework import Agent, SkillsProvider, ToolApprovalMiddleware
skills_provider = SkillsProvider(deployment_skill)
# Auto-approve read-only skill tools (load_skill, read_skill_resource).
# run_skill_script still requires explicit approval via result.user_input_requests.
approval_middleware = ToolApprovalMiddleware(
auto_approval_rules=[SkillsProvider.read_only_tools_auto_approval_rule],
)
agent = Agent(
client=client,
instructions="You are a deployment assistant.",
context_providers=[skills_provider],
middleware=[approval_middleware],
)
Deux règles sont disponibles :
-
SkillsProvider.read_only_tools_auto_approval_rule- approuve uniquement les outils en lecture seule (load_skill,read_skill_resource) tout en demandantrun_skill_script. -
SkillsProvider.all_tools_auto_approval_rule- approuve chaque outil de compétence, y comprisrun_skill_script(aucune boucle d’approbation manuelle nécessaire).
Les deux règles rejettent tout appel comportant un server_label, ce qui les limite aux outils locaux de ce fournisseur et les empêche de ne jamais approuver automatiquement un outil hébergé portant le même nom. Les règles s’appliquent uniquement aux outils qui nécessitent encore une approbation ; les outils exclus via les arguments disable_*_approval ci-dessous s’exécutent sans approbation dans tous les cas.
Désactivation de l’approbation pour des outils spécifiques
Pour les compétences de confiance, indiquez disable_load_skill_approval, disable_read_skill_resource_approval et/ou disable_run_skill_script_approval pour exclure complètement certains outils individuels du flux d’approbation (ils sont enregistrés avec approval_mode="never_require") :
skills_provider = SkillsProvider(
deployment_skill,
disable_load_skill_approval=True,
disable_read_skill_resource_approval=True,
# disable_run_skill_script_approval remains False - scripts still require approval
)
Ces arguments sont également disponibles sur SkillsProvider.from_paths().
Avertissement
Ne désactivez l’approbation, ou n’approuvez automatiquement l’exécution des scripts, que pour les skills et les scripts provenant de sources auxquelles vous faites confiance. Les instructions de compétence sont injectées dans le contexte de l’agent et run_skill_script exécute le code fourni par la source.
Prompt système personnalisé
Par défaut, le fournisseur de compétences injecte une invite système qui répertorie les compétences disponibles et indique à l’agent d’utiliser load_skill et read_skill_resource. Vous pouvez personnaliser cette invite :
var skillsProvider = new AgentSkillsProvider(
skillPath: Path.Combine(AppContext.BaseDirectory, "skills"),
options: new AgentSkillsProviderOptions
{
SkillsInstructionPrompt = """
You have skills available. Here they are:
{skills}
When a task matches a skill, use load_skill to retrieve instructions,
then read_skill_resource for referenced resources, and run_skill_script for scripts.
"""
});
Note
Le modèle personnalisé doit contenir {skills} comme espace réservé pour la liste des compétences générées. Les accolades littérales doivent être échappées en utilisant {{ et }}.
skills_provider = SkillsProvider.from_paths(
skill_paths=Path(__file__).parent / "skills",
instruction_template=(
"You have skills available. Here they are:\n{skills}\n"
"{resource_instructions}\n"
"{runner_instructions}"
),
)
Note
Le modèle personnalisé doit contenir l’espace {skills} réservé pour la liste des compétences générées. Il peut éventuellement contenir les espaces réservés {resource_instructions} (indication pour l’outil de ressource) et {runner_instructions} (indication pour l’outil de script) ; lorsqu’ils sont présents, ils sont remplacés par des indications intégrées et, lorsqu’ils sont omis, ils ne sont tout simplement pas affichés (les outils correspondants restent enregistrés). Les accolades littérales doivent être échappées en utilisant {{ et }}.
Injection de services et d'arguments d'exécution
Les fonctions de ressource de compétence et de script peuvent recevoir le contexte d’application externe fourni au moment de l’exécution.
Les délégués de ressources de compétence et de script peuvent déclarer un paramètre IServiceProvider que le cadre de l'agent injecte automatiquement. Cela permet aux compétences de résoudre à la demande les services d'application enregistrés.
Paramétrage
Inscrivez vos services d’application et transmettez l’élément IServiceProvider construit à l’agent via le paramètre services :
using Microsoft.Extensions.DependencyInjection;
// Register application services
ServiceCollection services = new();
services.AddSingleton<ConversionService>();
IServiceProvider serviceProvider = services.BuildServiceProvider();
// Create the agent and pass the service provider
AIAgent agent = new AzureOpenAIClient(new Uri(endpoint), new DefaultAzureCredential())
.GetResponsesClient()
.AsAIAgent(
options: new ChatClientAgentOptions
{
Name = "ConverterAgent",
ChatOptions = new() { Instructions = "You are a helpful assistant." },
AIContextProviders = [skillsProvider],
},
model: deploymentName,
services: serviceProvider);
Compétences définies par le code avec DI
Déclarez IServiceProvider en tant que paramètre dans AddResource ou AddScript délégués : l’infrastructure résout et l’injecte automatiquement lorsque l’agent lit une ressource ou exécute un script :
var distanceSkill = new AgentInlineSkill(
name: "distance-converter",
description: "Convert between distance units (miles and kilometers).",
instructions: """
Use this skill when the user asks to convert between miles and kilometers.
1. Read the distance-table resource for conversion factors.
2. Use the convert script to compute the result.
""")
.AddResource("distance-table", (IServiceProvider sp) =>
{
return sp.GetRequiredService<ConversionService>().GetDistanceTable();
})
.AddScript("convert", (double value, double factor, IServiceProvider sp) =>
{
return sp.GetRequiredService<ConversionService>().Convert(value, factor);
});
Compétences basées sur des classes avec DI
Annoter les méthodes avec [AgentSkillResource] ou [AgentSkillScript] déclarer un IServiceProvider paramètre : l’infrastructure découvre ces membres via la réflexion et injecte automatiquement le fournisseur de services :
internal sealed class WeightConverterSkill : AgentClassSkill<WeightConverterSkill>
{
public override AgentSkillFrontmatter Frontmatter { get; } = new(
"weight-converter",
"Convert between weight units (pounds and kilograms).");
protected override string Instructions => """
Use this skill when the user asks to convert between pounds and kilograms.
1. Read the weight-table resource for conversion factors.
2. Use the convert script to compute the result.
""";
[AgentSkillResource("weight-table")]
[Description("Lookup table of multiplication factors for weight conversions.")]
private static string GetWeightTable(IServiceProvider serviceProvider)
{
return serviceProvider.GetRequiredService<ConversionService>().GetWeightTable();
}
[AgentSkillScript("convert")]
[Description("Multiplies a value by a conversion factor and returns the result as JSON.")]
private static string Convert(double value, double factor, IServiceProvider serviceProvider)
{
return serviceProvider.GetRequiredService<ConversionService>().Convert(value, factor);
}
}
Conseil / Astuce
Les compétences basées sur des classes peuvent également résoudre les dépendances par le biais de leur constructeur. Inscrivez la classe de compétence dans le ServiceCollection conteneur et résolvez-la à partir du conteneur au lieu d’appeler new directement :
services.AddSingleton<WeightConverterSkill>();
var weightSkill = serviceProvider.GetRequiredService<WeightConverterSkill>();
Cela est utile lorsque la classe de compétences elle-même a besoin de services injectés au-delà de ce que les délégués de ressource et de script utilisent.
Les fonctions de ressource et de script qui acceptent **kwargs reçoivent automatiquement les arguments de mots-clés d'exécution passés à agent.run(). Cela permet aux fonctions de compétence d’accéder au contexte d’application ( configuration, identité utilisateur ou clients de service) sans les coder en dur dans la définition de compétence.
Passage d’arguments d’exécution
Transmettez function_invocation_kwargs à agent.run() pour fournir des arguments nommés que le framework transfère aux fonctions de ressource et de script :
response = await agent.run(
"How many kilometers is 26.2 miles?",
function_invocation_kwargs={"precision": 2, "user_id": "alice"},
)
Compétences définies par le code avec kwargs
Lorsqu’une fonction de ressource déclare **kwargs, l’infrastructure transfère les arguments de mot clé runtime chaque fois que l’agent lit la ressource :
import os
from typing import Any
from agent_framework import InlineSkill, SkillFrontmatter
project_info_skill = InlineSkill(
frontmatter=SkillFrontmatter(
name="project-info",
description="Project status and configuration information",
),
instructions="Use this skill for questions about the current project.",
)
@project_info_skill.resource(name="environment", description="Current environment configuration")
def environment(**kwargs: Any) -> str:
"""Return environment config, optionally scoped to a user."""
user_id = kwargs.get("user_id", "anonymous")
env = os.environ.get("APP_ENV", "development")
return f"Environment: {env}, Caller: {user_id}"
Les fonctions de ressource sans **kwargs sont appelées sans arguments et ne reçoivent pas de contexte d’exécution.
Lorsqu’une fonction de script déclare **kwargs, l’infrastructure transfère les arguments de mot clé runtime en même temps que ceux args fournis par l’agent :
import json
from typing import Any
from agent_framework import InlineSkill, SkillFrontmatter
converter_skill = InlineSkill(
frontmatter=SkillFrontmatter(
name="unit-converter",
description="Convert between common units using a conversion factor",
),
instructions="Use the convert script to perform unit conversions.",
)
@converter_skill.script(name="convert", description="Convert a value: result = value × factor")
def convert_units(value: float, factor: float, **kwargs: Any) -> str:
"""Convert a value using a multiplication factor.
Args:
value: The numeric value to convert (provided by the agent).
factor: Conversion factor (provided by the agent).
**kwargs: Runtime keyword arguments from agent.run().
"""
precision = kwargs.get("precision", 4)
result = round(value * factor, precision)
return json.dumps({"value": value, "factor": factor, "result": result})
L’agent fournit value et factor par le biais de l’appel argsd’outil ; l’application fournit precision via function_invocation_kwargs. Les fonctions de script sans **kwargs recevoir uniquement les arguments fournis par l’agent.
Compétences basées sur les classes avec kwargs
Les méthodes de compétence basées sur des classes peuvent également prendre **kwargs pour recevoir des arguments d’exécution. Le modèle fonctionne de la même façon : déclarez **kwargs sur les méthodes de ressource ou les méthodes de script :
from typing import Any
from agent_framework import ClassSkill, SkillFrontmatter
class WeightConverterSkill(ClassSkill):
def __init__(self) -> None:
super().__init__(
frontmatter=SkillFrontmatter(
name="weight-converter",
description="Convert between weight units (pounds and kilograms).",
),
)
@property
def instructions(self) -> str:
return "Use this skill to convert between pounds and kilograms."
@ClassSkill.resource(name="weight-table")
def get_weight_table(self, **kwargs: Any) -> str:
"""Weight conversion factors, scoped to caller context."""
user_id = kwargs.get("user_id", "anonymous")
return f"Weight table for {user_id}: | lbs | kg | 0.453592 |"
@ClassSkill.script(name="convert")
def convert(self, value: float, factor: float, **kwargs: Any) -> str:
"""Convert a weight value."""
import json
precision = kwargs.get("precision", 4)
result = round(value * factor, precision)
return json.dumps({"value": value, "factor": factor, "result": result})
Bonnes pratiques de sécurité
Les compétences de l’agent doivent être traitées comme tout code tiers que vous apportez dans votre projet. Étant donné que les instructions de compétence sont injectées dans le contexte de l’agent , et que les compétences peuvent inclure des scripts, l’application du même niveau de révision et de gouvernance que vous feriez à une dépendance open source est essentielle.
-
Passez en revue avant d’utiliser : lisez tout le contenu des compétences (
SKILL.md, les scripts et les ressources) avant de déployer. Vérifiez que le comportement réel d’un script correspond à son intention indiquée. Recherchez les instructions contradictoires qui tentent de contourner les instructions de sécurité, d’exfiltrer les données ou de modifier les fichiers de configuration de l’agent. - Approbation de la source : installez uniquement les compétences des auteurs approuvés ou des contributeurs internes approuvés. Préférez les compétences avec une provenance claire, un contrôle de version et une maintenance active. Surveillez les noms de compétences typosquattés qui imitent les packages populaires.
- Sandboxing : exécutez des compétences qui incluent des scripts exécutables dans des environnements isolés. Limitez l’accès au système de fichiers, au réseau et au niveau du système uniquement à ce dont la compétence a besoin. Exiger une confirmation explicite de l’utilisateur avant d’exécuter des opérations potentiellement sensibles.
- Audit et journalisation : enregistrez les compétences chargées, les ressources lues et les scripts exécutés. Cela vous donne une piste d’audit pour tracer le comportement de l’agent vers un contenu de compétence spécifique si quelque chose ne va pas.
Quand utiliser des compétences et des workflows
Les compétences de l'agent et les flux de travail du cadre de l'agent étendent tous deux les capacités des agents, mais ils fonctionnent de manière fondamentalement différente. Choisissez l’approche qui correspond le mieux à vos besoins :
- Contrôle - Avec une compétence, l’IA décide comment exécuter les instructions. C’est idéal lorsque vous souhaitez que l’agent soit créatif ou adaptatif. Avec un flux de travail, vous définissez explicitement le chemin d’exécution. Utilisez des flux de travail quand vous avez besoin d’un comportement déterministe et prévisible.
- Résilience : uUne compétence s’exécute pendant un seul tour de l’agent. En cas d’échec, l’opération entière doit être retentée. Les flux de travail prennent en charge les points de contrôle, afin qu’ils puissent reprendre à partir de la dernière étape réussie après un échec. Choisissez des flux de travail lorsque le coût de réexécution de l’ensemble du processus est élevé.
- Effets secondaires : les compétences conviennent lorsque les opérations sont idempotentes ou à faible risque. Préférez les flux de travail lorsque les étapes produisent des effets secondaires (envoi d’e-mails, paiements de facturation) qui ne doivent pas être répétés lors de nouvelles tentatives.
- Complexité : les compétences sont les meilleures pour les tâches prioritaires et à domaine unique qu’un agent peut gérer. Les flux de travail sont mieux adaptés aux processus métier en plusieurs étapes qui coordonnent plusieurs agents, approbations humaines ou intégrations de système externe.
Conseil / Astuce
En règle générale : si vous souhaitez que l’IA détermine comment accomplir une tâche, utilisez une compétence. Si vous devez garantir les étapes qui s’exécutent et dans quel ordre, utilisez un flux de travail.