Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Le competenze dell'agente sono pacchetti portabili di istruzioni, script e risorse che offrono agli agenti funzionalità specializzate e competenze di dominio. Le competenze seguono una specifica aperta e implementano un modello di divulgazione progressiva in modo che gli agenti carichino solo il contesto di cui hanno bisogno, quando necessario.
Usare le competenze dell'agente quando si vuole:
- Confeziona le competenze di dominio - Racchiudi conoscenze specializzate (criteri di spesa, flussi di lavoro legali, pipeline di analisi dei dati) in pacchetti riutilizzabili e portabili.
- Estendere le funzionalità dell'agente : offrire agli agenti nuove capacità senza modificare le istruzioni di base.
- Garantire la coerenza : trasformare le attività in più passaggi in flussi di lavoro ripetibili e controllabili.
- Abilitare l'interoperabilità: riutilizzare la stessa competenza in diversi prodotti compatibili con le competenze dell'agente.
Struttura delle competenze
Un'abilità è una directory contenente un file SKILL.md con sottodirectory facoltative per le risorse.
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
formato SKILL.md
Il SKILL.md file deve contenere il frontmatter YAML seguito dal contenuto 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"
---
| Campo | Obbligatorio | Descrzione |
|---|---|---|
name |
Sì | Massimo 64 caratteri. Solo lettere minuscole, numeri e trattini. Non deve iniziare o terminare con un trattino o contenere trattini consecutivi. Deve corrispondere al nome della directory principale. |
description |
Sì | Cosa fa la competenza e quando usarla. Massimo 1024 caratteri. Deve includere parole chiave che consentono agli agenti di identificare le attività pertinenti. |
license |
NO | Nome della licenza o riferimento a un file di licenza in bundle. |
compatibility |
NO | Massimo 500 caratteri. Indica i requisiti di ambiente (prodotto, pacchetti di sistema, accesso alla rete e così via). |
metadata |
NO | Mappatura chiave-valore arbitraria per metadati aggiuntivi. |
allowed-tools |
NO | Elenco delimitato da spazi di strumenti pre-approvati che l'abilità può utilizzare. Sperimentale: il supporto può variare tra le implementazioni dell'agente. |
Il corpo markdown successivo al frontmatter contiene le istruzioni della skill: una guida dettagliata passo dopo passo, esempi di input e output, casi limite comuni o qualsiasi contenuto che aiuti l'agente a svolgere l'attività. Mantenere SKILL.md sotto 500 righe e spostare materiale di riferimento dettagliato in file separati.
Divulgazione progressiva
Le competenze dell'agente usano un modello di divulgazione progressiva a quattro fasi per ridurre al minimo l'utilizzo del contesto:
- Annuncio (~100 token per competenza): i nomi e le descrizioni delle competenze vengono inseriti nella richiesta di sistema all'inizio di ogni esecuzione, quindi l'agente sa quali competenze sono disponibili.
-
Caricamento (< 5000 token consigliati) - Quando un'attività corrisponde al dominio di un'abilità, l'agente richiama lo strumento
load_skillper recuperare l'intero contenuto di SKILL.md con istruzioni dettagliate. -
Lettura delle risorse (se necessario): l'agente chiama lo
read_skill_resourcestrumento per recuperare file supplementari (riferimenti, modelli, asset) solo quando necessario. -
Esegui script (se necessario) - L'agente chiama lo strumento
run_skill_scriptper eseguire gli script inclusi in una competenza.
Questo modello mantiene snella la finestra di contesto dell'agente, concedendole l'accesso a conoscenze di dominio approfondite su richiesta.
Annotazioni
load_skill è sempre pubblicizzato.
read_skill_resource è pubblicizzato solo quando almeno un'abilità dispone di risorse.
run_skill_script viene annunciato solo quando almeno un'abilità ha script.
Fornire competenze a un agente
AgentSkillsProvider (C#) e SkillsProvider (Python) sono provider di contesto che rendono disponibili competenze agli agenti. Supportano tre origini di competenze:
-
Basato su file : competenze individuate dai
SKILL.mdfile nelle directory del file system -
Code-defined : competenze definite inline nel codice usando
AgentInlineSkill(C#) oInlineSkill(Python) -
Class-based : competenze incapsulate in una classe derivata da
AgentClassSkill<T>(C#) oClassSkill(Python)
Per combinare più origini in un provider, usare AgentSkillsProviderBuilder (C#) o comporre classi di origine, ad esempio AggregatingSkillsSource, FilteringSkillsSource e DeduplicatingSkillsSource (Python): vedere Builder: scenari multiorigine avanzati (C#) o composizione Source: scenari multiorigine avanzati (Python).
Competenze basate sui file
Creare un collegamento a una directory contenente le skill, e aggiungerlo ai fornitori di contesto dell'agente. Passare un esecutore di script per abilitare l'esecuzione di script basati su file presenti nelle directory delle abilità.
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);
Avviso
DefaultAzureCredential è utile per lo sviluppo, ma richiede un'attenta considerazione nell'ambiente di produzione. Nell'ambiente di produzione prendere in considerazione l'uso di credenziali specifiche ,ad esempio ManagedIdentityCredential, per evitare problemi di latenza, probe di credenziali indesiderate e potenziali rischi per la sicurezza dai meccanismi di fallback.
Molteplici directory di competenze
È possibile indirizzare il provider a un'unica directory padre: ogni sottodirectory contenente un SKILL.md viene rilevata automaticamente come skill:
var skillsProvider = new AgentSkillsProvider(
Path.Combine(AppContext.BaseDirectory, "all-skills"));
In alternativa, passare un elenco di percorsi per eseguire ricerche in più directory radice:
var skillsProvider = new AgentSkillsProvider(
[
Path.Combine(AppContext.BaseDirectory, "company-skills"),
Path.Combine(AppContext.BaseDirectory, "team-skills"),
]);
Il provider cerca fino a due livelli di profondità.
Personalizzazione dell'individuazione delle risorse
Per impostazione predefinita, il provider riconosce le risorse con estensioni .md, .json, .yaml, .yml, .csv, .xml e .txt nelle sottodirectory references e assets. Usare AgentFileSkillsSourceOptions per modificare queste impostazioni predefinite:
var fileOptions = new AgentFileSkillsSourceOptions
{
AllowedResourceExtensions = [".md", ".txt"],
ResourceDirectories = ["docs", "templates"],
};
var skillsProvider = new AgentSkillsProvider(
Path.Combine(AppContext.BaseDirectory, "skills"),
fileOptions: fileOptions);
Esecuzione degli script
Passare SubprocessScriptRunner.RunAsync come secondo argomento a AgentSkillsProvider per abilitare l'esecuzione di script basati su file.
var skillsProvider = new AgentSkillsProvider(
Path.Combine(AppContext.BaseDirectory, "skills"),
SubprocessScriptRunner.RunAsync);
SubprocessScriptRunner.RunAsync è approssimativamente equivalente ai seguenti:
// Simplified equivalent of what SubprocessScriptRunner.RunAsync does internally
using System.Diagnostics;
using System.Text.Json;
static async Task<string> RunAsync(
AgentFileSkill skill,
AgentFileSkillScript script,
JsonElement? args,
IServiceProvider? serviceProvider)
{
var psi = new ProcessStartInfo("python3")
{
RedirectStandardOutput = true,
UseShellExecute = false,
};
psi.ArgumentList.Add(Path.Combine(skill.Path, script.Path));
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();
await process.WaitForExitAsync();
return output.Trim();
}
Il runner esegue ogni script individuato come sottoprocesso locale. Gli script basati su file prevedono argomenti come matrice JSON di stringhe. Ogni elemento della matrice diventa un argomento della riga di comando posizionale.
Avviso
SubprocessScriptRunner viene fornito solo a scopo dimostrativo. Per l'uso in produzione, è consigliabile aggiungere:
- Sandboxing (ad esempio, contenitori o ambienti di esecuzione isolati)
- Limiti delle risorse (CPU, memoria, timeout di wall-clock)
- Convalida dell'input e elenco consentito di script eseguibili
- Log strutturati e audit trail
Personalizzazione dell'individuazione di script
Per impostazione predefinita, il provider riconosce gli script con estensioni .py, .js, .sh, .ps1, .cs, e .csx nella sottodirectory scripts. Usare AgentFileSkillsSourceOptions per modificare queste impostazioni predefinite:
Passare AgentFileSkillsSourceOptions al AgentSkillsProvider costruttore o a UseFileSkill / UseFileSkills nel generatore:
var fileOptions = new AgentFileSkillsSourceOptions
{
AllowedScriptExtensions = [".py"],
ScriptDirectories = ["scripts", "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();
Competenze basate sui file
Usare la SkillsProvider.from_paths() factory per individuare le competenze nelle directory contenenti file SKILL.md e aggiungere il provider ai provider di contesto dell'agente:
import os
from pathlib import Path
from agent_framework import Agent, SkillsProvider
from agent_framework.foundry import FoundryChatClient
from azure.identity import AzureCliCredential
# 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],
)
Molteplici directory di competenze
È possibile indirizzare il provider a un'unica directory padre: ogni sottodirectory contenente un SKILL.md viene rilevata automaticamente come skill:
skills_provider = SkillsProvider.from_paths(
skill_paths=Path(__file__).parent / "all-skills"
)
In alternativa, passare un elenco di percorsi per eseguire ricerche in più directory radice:
skills_provider = SkillsProvider.from_paths(
skill_paths=[
Path(__file__).parent / "company-skills",
Path(__file__).parent / "team-skills",
]
)
Il provider cerca fino a due livelli di profondità.
Personalizzazione del rilevamento delle risorse e degli script
Per impostazione predefinita, le risorse vengono individuate nelle sottodirectory references/ e assets/ e gli script da scripts/, secondo la specifica agentskills.io. Le estensioni delle risorse riconosciute sono , , .md, , .json.yaml, e .yml. .csv.xml.txt Usare resource_directories, script_directoriese resource_extensions per personalizzare queste impostazioni predefinite:
skills_provider = SkillsProvider.from_paths(
skill_paths=Path(__file__).parent / "skills",
resource_extensions=(".md", ".txt"),
resource_directories=["docs", "templates"],
script_directories=["scripts", "tools"],
)
Usare "." per includere i file a livello radice della competenza oltre alle sottodirectory.
Esecuzione degli script
Per abilitare l'esecuzione di script basati su file, passare un script_runner a SkillsProvider.from_paths(). È possibile usare qualsiasi funzione o metodo sincrono o asincrono che soddisfi il protocollo SkillScriptRunner:
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'esecutore riceve gli argomenti risolti FileSkill, FileSkillScript e un argomento facoltativo args. Gli script basati su file prevedono argomenti come matrice JSON di stringhe. Ogni elemento della matrice diventa un argomento della riga di comando posizionale. Gli script vengono rilevati automaticamente nei file .py nella sottodirectory scripts/ di ogni skill.
Avviso
Il runner precedente viene fornito solo a scopo dimostrativo. Per l'uso in produzione, è consigliabile aggiungere:
- Sandboxing (ad esempio, contenitori,
seccomp, ofirejail) - Limiti delle risorse (CPU, memoria, timeout di wall-clock)
- Convalida dell'input e elenco consentito di script eseguibili
- Log strutturati e audit trail
Annotazioni
Se vengono fornite skill basate su file con script ma script_runner non è impostato, SkillsProvider genera un errore quando si tenta di eseguire lo script.
Competenze definite dal codice
Oltre alle competenze basate su file individuate dai SKILL.md file, è possibile definire le competenze interamente nel codice usando AgentInlineSkill. Le competenze definite dal codice sono utili quando:
- Il contenuto della competenza viene generato in modo dinamico( ad esempio, la lettura da un database o un ambiente).
- Si vogliono mantenere le definizioni delle competenze insieme al codice dell'applicazione che le usa.
- Sono necessarie risorse che eseguono la logica in fase di lettura anziché gestire i file statici.
- Le definizioni delle competenze devono essere costruite in fase di esecuzione dai dati , ad esempio creando una competenza personalizzata per ogni sessione utente in base al ruolo o alle autorizzazioni.
- Una competenza deve chiudere lo stato del sito di chiamata (variabili locali, chiuse) anziché risolvere i servizi da un contenitore di inserimento delle dipendenze.
Competenza di codice di base
Creare un oggetto AgentInlineSkill con un nome, una descrizione e istruzioni. Collegare le risorse usando .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);
Risorse dinamiche
Passare un delegato factory a .AddResource() per calcolare il contenuto in fase di esecuzione. Il delegato viene richiamato ogni volta che l'agente legge la risorsa:
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)");
Script definiti dal codice
Usare .AddScript() per registrare un delegato come script eseguibile. Gli script definiti dal codice vengono eseguiti in-process come chiamate delegate dirette. Non è necessario alcun esecutore di script. I parametri tipizzati del delegato vengono convertiti automaticamente in uno Schema JSON che l'agente usa per passare gli argomenti.
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);
Annotazioni
Per combinare competenze definite dal codice con competenze basate su file o basate su classi in un singolo provider, usare AgentSkillsProviderBuilder. Vedere Generatore: scenari avanzati con più origini.
Oltre alle competenze basate su file individuate dai file SKILL.md, è possibile definire le competenze interamente nel codice Python usando InlineSkill. Le competenze definite dal codice sono utili quando:
- Il contenuto della competenza viene generato in modo dinamico( ad esempio, la lettura da un database o un ambiente).
- Si vogliono mantenere le definizioni delle competenze insieme al codice dell'applicazione che le usa.
- Sono necessarie risorse che eseguono la logica in fase di lettura anziché gestire i file statici.
- Le definizioni delle competenze devono essere costruite in fase di esecuzione dai dati , ad esempio creando una competenza personalizzata per ogni sessione utente in base al ruolo o alle autorizzazioni.
- Una competenza deve chiudere lo stato del sito di chiamata (variabili locali, chiuse) anziché risolvere i servizi tramite
**kwargs.
Competenza di codice di base
Creare un'istanza InlineSkill con un oggetto SkillFrontmatter (contenente il nome e la descrizione) e il contenuto delle istruzioni. Facoltativamente, allegare InlineSkillResource istanze al contenuto statico:
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)
Risorse dinamiche
Usa il decoratore @skill.resource per registrare una funzione come risorsa. La funzione viene chiamata ogni volta che l'agente legge la risorsa, in modo che possa restituire dati aggiornati. Sono supportate sia le funzioni di sincronizzazione che asincrone:
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)"
Quando l'elemento Decorator viene usato senza argomenti (@skill.resource), il nome della funzione diventa il nome della risorsa e la docstring diventa la descrizione. Usare @skill.resource(name="...", description="...") per impostarli in modo esplicito.
Script definiti dal codice
Usare il decoratore @skill.script per registrare una funzione come script eseguibile in una skill. Gli script definiti dal codice vengono eseguiti in-process e non richiedono uno script runner. Sono supportate sia le funzioni di sincronizzazione che asincrone:
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})
Quando l'elemento Decorator viene usato senza argomenti (@skill.script), il nome della funzione diventa il nome dello script e la docstring diventa la descrizione. I parametri tipizzato della funzione vengono convertiti automaticamente in uno schema JSON usato dall'agente per passare argomenti.
Competenze basate su classi
Le competenze basate su classi consentono di aggregare tutti i componenti della competenza, ovvero nome, descrizione, istruzioni, risorse e script, in una singola classe C#. Questo li rende facili da impacchettare e distribuire come pacchetti NuGet: i team possono creare e distribuire le skill in modo indipendente e gli utenti possono aggiungerle con dotnet add package e una singola chiamata a .UseSkill(). Deriva da AgentClassSkill<T> (dove T è la tua classe), quindi annota le proprietà con [AgentSkillResource] e i metodi con [AgentSkillScript] per l'individuazione automatica.
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 });
}
}
Registrare la competenza basata sulla classe con AgentSkillsProvider:
var skill = new UnitConverterSkill();
var skillsProvider = new AgentSkillsProvider(skill);
Quando l'attributo [AgentSkillResource] viene applicato a una proprietà o a un metodo, il relativo valore restituito viene usato come contenuto della risorsa quando l'agente legge la risorsa. Usare un metodo quando il contenuto deve essere calcolato in fase di lettura. Quando [AgentSkillScript] viene applicato a un metodo, il metodo viene richiamato quando l'agente chiama lo script. Usare [Description] da System.ComponentModel per descrivere ogni risorsa e script per l'agente.
Annotazioni
AgentClassSkill<T> supporta anche l'override Resources e Scripts come raccolte per scenari in cui l'individuazione basata su attributi non è adatta.
Competenze basate su classi
Le competenze basate su classi consentono di aggregare tutti i componenti della competenza, ovvero nome, descrizione, istruzioni, risorse e script, in una singola classe Python. Questo li rende facili da impacchettare e distribuire come pacchetti PyPI: i team possono creare e distribuire competenze in modo indipendente e gli utilizzatori possono aggiungerli con pip install e una sola chiamata a SkillsProvider(). Crea una sottoclasse di ClassSkill, quindi usa i decoratori @ClassSkill.resource e @ClassSkill.script per il rilevamento automatico:
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})
Registrare la competenza basata sulla classe con SkillsProvider:
from agent_framework import SkillsProvider
skill = UnitConverterSkill()
skills_provider = SkillsProvider(skill)
Quando @ClassSkill.resource viene applicato come decoratore senza argomenti, il nome del metodo diventa il nome della risorsa (con i trattini bassi convertiti in trattini) e la docstring diventa la descrizione. Usare @ClassSkill.resource(name="...", description="...") per impostarli in modo esplicito. Lo stesso modello si applica a @ClassSkill.script.
Le risorse possono essere definite come metodi regolari o @property descrittori. Quando si usa @property, posizionare @property per primo e @ClassSkill.resource per secondo. I valori restituiti delle risorse vengono memorizzati nella cache dopo il primo accesso.
Annotazioni
ClassSkill supporta anche la sostituzione esplicita delle proprietà resources e scripts per restituire direttamente istanze di InlineSkillResource e InlineSkillScript, negli scenari in cui il rilevamento basato su decorator non è appropriato.
Generatore: scenari avanzati con più origini
Per scenari di origine singola semplici, usare direttamente i AgentSkillsProvider costruttori. Usare AgentSkillsProviderBuilder quando è necessario uno dei seguenti elementi:
-
Tipi di competenze misti : combinare competenze basate su file, definite dal codice (
AgentInlineSkill) e basate su classi (AgentClassSkill) in un singolo provider. - Filtro delle competenze: includere o escludere competenze usando un predicato.
Tipi di competenze misti
Combinare tutti e tre i tipi di competenza in un provider concatenando UseFileSkill, UseSkille UseFileScriptRunner:
var skillsProvider = new AgentSkillsProviderBuilder()
.UseFileSkill(Path.Combine(AppContext.BaseDirectory, "skills")) // file-based skills
.UseSkill(volumeConverterSkill) // AgentInlineSkill
.UseSkill(temperatureConverter) // AgentClassSkill
.UseFileScriptRunner(SubprocessScriptRunner.RunAsync) // runner for file scripts
.Build();
Filtro delle competenze
Usare UseFilter per includere solo le competenze che soddisfano i criteri, ad esempio per caricare le competenze da una directory condivisa, ma escludere quelle sperimentali:
var approvedSkillNames = new HashSet<string> { "expense-report", "code-style" };
var skillsProvider = new AgentSkillsProviderBuilder()
.UseFileSkill(Path.Combine(AppContext.BaseDirectory, "skills"))
.UseFilter(skill => approvedSkillNames.Contains(skill.Frontmatter.Name))
.Build();
Composizione delle origini: scenari avanzati con origini multiple
Per scenari semplici con una singola competenza o un elenco di competenze, passarli direttamente al SkillsProvider costruttore. Per le competenze basate su file, utilizzare la classe SkillsProvider.from_paths() factory. Per scenari avanzati, comporre classi di origine per controllare l'individuazione, il filtro e la deduplicazione:
-
FileSkillsSource- individua le abilità dai fileSKILL.mdpresenti sul disco. -
InMemorySkillsSource- esegue il wrapping di tutteSkillle istanze (definite dal codice o basate su classi) in memoria. -
AggregatingSkillsSource- combina più origini in una. -
FilteringSkillsSource- applica un predicato per includere o escludere le competenze. -
DeduplicatingSkillsSource- rimuove i nomi delle competenze duplicati (senza distinzione tra maiuscole e minuscole; prevale la prima occorrenza).
Tipi di competenze misti
Combinare competenze basate su file, definite dal codice e basate su classi in un provider usando AggregatingSkillsSource. L'esempio seguente usa oggetti segnaposto:
-
volume_converter_skill- qualsiasi istanza diInlineSkill, creata come illustrato in Skill definite dal codice. -
TemperatureConverterSkill- qualsiasiClassSkillsottoclasse, compilata come illustrato in Competenze basate su classi. -
my_runner- unSkillScriptRunnerrichiamabile, definito come illustrato in Esecuzione dello script.
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]),
])
)
)
Filtro delle competenze
Usa FilteringSkillsSource per controllare quali competenze vede l'agente. Il predicato riceve ogni Skill e restituisce True per includerlo. Ad esempio, per caricare le competenze da una directory condivisa ma nasconderne una sperimentale:
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: skill.frontmatter.name != "experimental-tools",
)
)
)
Approvazione dello script
Usare AgentSkillsProviderOptions.ScriptApproval per controllare tutte le esecuzioni di script previa approvazione umana. Se abilitata, l'agente sospende e restituisce una richiesta di approvazione anziché eseguirlo immediatamente:
var skillsProvider = new AgentSkillsProvider(
skillPath: Path.Combine(AppContext.BaseDirectory, "skills"),
options: new AgentSkillsProviderOptions
{
ScriptApproval = true,
});
Per abilitare l'approvazione degli script in un provider configurato dal generatore, usare UseScriptApproval:
var skillsProvider = new AgentSkillsProviderBuilder()
.UseFileSkill(Path.Combine(AppContext.BaseDirectory, "skills"))
.UseScriptApproval(true)
.Build();
Usare require_script_approval=True su SkillsProvider per limitare tutte le esecuzioni di script soggette ad approvazione umana. Anziché eseguirlo immediatamente, l'agente sospende e restituisce le richieste di approvazione tramite result.user_input_requests:
from textwrap import dedent
from agent_framework import Agent, InlineSkill, 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}"
skills_provider = SkillsProvider(deployment_skill, require_script_approval=True)
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,
)
# Handle approval requests
while result.user_input_requests:
for request in result.user_input_requests:
print(f"Script: {request.function_call.name}")
print(f"Args: {request.function_call.arguments}")
approval = request.to_function_approval_response(approved=True)
result = await agent.run(approval, session=session)
print(result)
Quando uno script viene rifiutato (approved=False), l'agente viene informato che l'utente ha rifiutato e può rispondere di conseguenza.
Richiesta di sistema personalizzata
Per impostazione predefinita, il provider di competenze inserisce un prompt di sistema che elenca le competenze disponibili e indica all'agente di usare load_skill e read_skill_resource. È possibile personalizzare questa richiesta:
var skillsProvider = new AgentSkillsProvider(
skillPath: Path.Combine(AppContext.BaseDirectory, "skills"),
options: new AgentSkillsProviderOptions
{
SkillsInstructionPrompt = """
You have skills available. Here they are:
{skills}
{resource_instructions}
{script_instructions}
"""
});
Annotazioni
Il modello personalizzato deve contenere {skills} (elenco di competenze), {resource_instructions} (suggerimento dello strumento di risorse) e {script_instructions} (suggerimento dello strumento di script) come segnaposto. Le parentesi graffe letterali devono essere precedute da un carattere di escape come {{ e }}.
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}"
),
)
Annotazioni
Il modello personalizzato deve contenere {skills} (elenco di competenze), {resource_instructions} (suggerimento dello strumento di risorse) e {runner_instructions} (suggerimento dello strumento di script) come segnaposto. Le parentesi graffe letterali devono essere precedute da un carattere di escape come {{ e }}.
Comportamento di memorizzazione nella cache
Per impostazione predefinita, gli strumenti e le istruzioni delle competenze vengono memorizzati nella cache dopo la prima compilazione. Imposta DisableCaching = true su AgentSkillsProviderOptions per forzare una ricompilazione a ogni invocazione:
var skillsProvider = new AgentSkillsProvider(
Path.Combine(AppContext.BaseDirectory, "skills"),
options: new AgentSkillsProviderOptions
{
DisableCaching = true,
});
Annotazioni
La disabilitazione della memorizzazione nella cache è utile durante lo sviluppo quando il contenuto delle competenze cambia frequentemente. Nell'ambiente di produzione lasciare abilitata la memorizzazione nella cache (impostazione predefinita) per ottenere prestazioni migliori.
Comportamento di memorizzazione nella cache
Per impostazione predefinita, gli strumenti e le istruzioni delle competenze vengono memorizzati nella cache dopo la prima compilazione. Impostare disable_caching=True per forzare una ricompilazione per ogni chiamata:
skills_provider = SkillsProvider.from_paths(
skill_paths=Path(__file__).parent / "skills",
disable_caching=True,
)
disable_caching è disponibile anche nel SkillsProvider costruttore per le competenze definite dal codice e basate su classi.
Annotazioni
La disabilitazione della memorizzazione nella cache è utile durante lo sviluppo quando il contenuto delle competenze cambia frequentemente. Nell'ambiente di produzione lasciare abilitata la memorizzazione nella cache (impostazione predefinita) per ottenere prestazioni migliori.
Le risorse di abilità e i delegati di script possono dichiarare un parametro IServiceProvider che l'Agent Framework inserisce automaticamente. In questo modo, le competenze consentono di risolvere i servizi dell'applicazione, ad esempio i client di database, la configurazione o la logica di business, senza codificarli nella definizione della competenza.
Setup
Registrare i servizi dell'applicazione e passare l'oggetto compilato IServiceProvider all'agente tramite il services parametro :
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);
Competenze definite dal codice con inserimento delle dipendenze
Dichiarare IServiceProvider come parametro in AddResource o AddScript delegati: il framework risolve e lo inserisce automaticamente quando l'agente legge una risorsa o esegue uno 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);
});
Competenze basate su classi con l'inserimento delle dipendenze
Annotare i metodi con [AgentSkillResource] o [AgentSkillScript] e dichiarare un IServiceProvider parametro: il framework individua questi membri tramite reflection e inserisce automaticamente il provider di servizi:
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);
}
}
Suggerimento
Le competenze basate su classi possono anche risolvere le dipendenze tramite il costruttore. Registrare la classe di competenza in ServiceCollection e risolverla dal contenitore invece di chiamare new direttamente:
services.AddSingleton<WeightConverterSkill>();
var weightSkill = serviceProvider.GetRequiredService<WeightConverterSkill>();
Ciò è utile quando la classe di competenza stessa necessita di servizi inseriti oltre a ciò che usano i delegati di risorse e script.
Funzioni di risorsa e di script che accettano **kwargs ricevono automaticamente gli argomenti di parole chiave a tempo di esecuzione passati a agent.run(). In questo modo, le funzioni della competenza accedono al contesto dell'applicazione, ad esempio configurazione, identità utente o client del servizio, senza codificarli nella definizione della competenza.
Passaggio di argomenti di runtime
Passare function_invocation_kwargs a agent.run() per fornire argomenti di parole chiave inoltrati dal framework alle funzioni di risorsa e script:
response = await agent.run(
"How many kilometers is 26.2 miles?",
function_invocation_kwargs={"precision": 2, "user_id": "alice"},
)
Competenze definite nel codice con kwargs
Quando una funzione di risorsa dichiara **kwargs, il framework inoltra gli argomenti della parola chiave di runtime ogni volta che l'agente legge la risorsa:
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}"
Le funzioni delle risorse senza **kwargs vengono chiamate senza argomenti e non ricevono il contesto di runtime.
Quando una funzione script dichiara **kwargs, il framework inoltra gli argomenti dell'istanza di runtime insieme all'oggetto args fornito dall'agente.
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'agente fornisce value e factor tramite la chiamata argsallo strumento . L'applicazione fornisce precision tramite function_invocation_kwargs. Funzioni script senza **kwargs ricevono solo gli argomenti forniti dall'agente.
Abilità basate su classi con kwargs
I metodi della skill basati su classe possono anche accettare **kwargs per ricevere argomenti di runtime. Il modello funziona allo stesso modo: dichiarare **kwargs nei metodi di risorsa o nei metodi di 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})
Procedure consigliate per la sicurezza
Le competenze dell'agente devono essere considerate come qualsiasi codice di terze parti inserito nel progetto. Poiché le istruzioni sulle competenze vengono inserite nel contesto dell'agente e le competenze possono includere script, l'applicazione dello stesso livello di revisione e governance a una dipendenza open source è essenziale.
-
Esaminare prima di usare: leggere tutto il contenuto delle competenze (
SKILL.md, script e risorse) prima della distribuzione. Verificare che il comportamento effettivo di uno script corrisponda alla finalità dichiarata. Controllare le istruzioni antagoniste che tentano di ignorare le linee guida per la sicurezza, esfiltrare i dati o modificare i file di configurazione dell'agente. - Affidabilità della fonte - Installa solo skill di autori affidabili o di collaboratori interni verificati. Preferisce competenze con chiara provenienza, controllo della versione e manutenzione attiva. Guarda i nomi delle competenze digitati che simulano i pacchetti più diffusi.
- Sandboxing - Esegui abilità che includono script eseguibili in ambienti isolati. Limitare l'accesso a livello di file system, rete e sistema solo a ciò che richiede la competenza. Richiedi conferma esplicita dell'utente prima di eseguire operazioni potenzialmente sensibili.
- Controllo e registrazione : registrare le competenze caricate, quali risorse vengono lette e quali script vengono eseguiti. Questo consente di eseguire un audit trail risalendo al comportamento dell'agente fino al contenuto di competenza specifico, in caso di problemi.
Quando usare competenze e flussi di lavoro
I flussi di lavoro di Agent Skills e Agent Framework estendono entrambe le operazioni che gli agenti possono eseguire, ma funzionano in modi fondamentalmente diversi. Scegliere l'approccio più adatto alle proprie esigenze:
- Controllo : con una competenza, l'intelligenza artificiale decide come eseguire le istruzioni. Questo è ideale quando vuoi che l'agente sia creativo o adattivo. Con un flusso di lavoro, si definisce in modo esplicito il percorso di esecuzione. Usare i flussi di lavoro quando è necessario un comportamento deterministico e prevedibile.
- Resilienza - Un'abilità si esegue all'interno di un singolo turno dell'agente. Se si verifica un errore, è necessario ritentare l'intera operazione. I flussi di lavoro supportano il checkpointing, consentendo di riprendere dall'ultimo passaggio riuscito dopo un errore. Scegliere i flussi di lavoro quando il costo di riesezione dell'intero processo è elevato.
- Effetti collaterali : le competenze sono adatte quando le operazioni sono idempotenti o a basso rischio. Preferisce i flussi di lavoro quando i passaggi producono effetti collaterali (invio di messaggi di posta elettronica, pagamenti in addebito) che non devono essere ripetuti al nuovo tentativo.
- Complessità : le competenze sono ideali per attività incentrate su un singolo dominio che un agente può gestire. I flussi di lavoro sono più adatti per processi aziendali in più passaggi che coordinano più agenti, approvazioni umane o integrazioni di sistemi esterni.
Suggerimento
Come regola generale: se si vuole che l'intelligenza artificiale sia in grado di capire come eseguire un'attività, usare una competenza. Se è necessario garantire quali passaggi eseguire e in quale ordine, usare un flusso di lavoro.