Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Dovednosti agenta jsou přenosné balíčky instrukcí, skriptů a prostředků, které poskytují agentům specializované schopnosti a odborné znalosti domény. Dovednosti dodržují otevřenou specifikaci a implementují model progresivního zpřístupnění, takže agenti načítají jenom kontext, který potřebují, když ho potřebují.
Dovednosti agenta použijte v případech, kdy chcete:
- Znalosti v doméně balíčků – zachytávání specializovaných znalostí (zásady výdajů, právní pracovní postupy, kanály analýzy dat) jako opakovaně použitelné, přenosné balíčky.
- Rozšiřte možnosti agenta – udělte agentům nové schopnosti beze změny základních instrukcí.
- Zajistěte konzistenci – převod vícekrokových úloh na opakovatelné a auditovatelné pracovní postupy.
- Povolte interoperabilitu – znovu používejte stejnou dovednost napříč různými produkty kompatibilními s Agent Skills.
Struktura dovedností
Skill je adresář obsahující SKILL.md soubor s volitelnými podadresáři pro prostředky:
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
formát SKILL.md
Soubor SKILL.md musí obsahovat frontmatter YAML následovaný obsahem markdownu:
---
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"
---
| Obor | Povinné | Description |
|---|---|---|
name |
Ano | Maximálně 64 znaků. Malá písmena, číslice a spojovníky. Nesmí začínat ani končit pomlčkou nebo obsahovat po sobě jdoucí pomlčky. Musí odpovídat názvu nadřazeného adresáře. |
description |
Ano | Co dovednost dělá a kdy ji používat. Maximálně 1024 znaků. Měla by obsahovat klíčová slova, která pomáhají agentům identifikovat relevantní úlohy. |
license |
Ne | Název licence nebo odkaz na soubor sbalené licence. |
compatibility |
Ne | Maximálně 500 znaků. Označuje požadavky na prostředí (zamýšlený produkt, systémové balíčky, přístup k síti atd.). |
metadata |
Ne | Libovolné mapování klíčů a hodnot pro doplňková metadata |
allowed-tools |
Ne | Seznam nástrojů předem schválených ke použití dovedností, oddělený mezerami. Experimentální – podpora se může mezi implementacemi agenta lišit. |
Tělo markdownu po frontmatteru obsahuje pokyny ke dovednostem – podrobné pokyny, příklady vstupů a výstupů, běžné hraniční případy nebo jakýkoli obsah, který pomáhá agentu provádět danou úlohu. Udržujte SKILL.md pod 500 řádků a přesuňte podrobný referenční materiál do samostatných souborů.
Progresivní zveřejnění
Dovednosti agentů používají model postupného zpřístupnění ve čtyřech fázích k minimalizaci využití kontextu:
- Inzerování (~100 tokenů na dovednost) - Názvy dovedností a popisy se vloží do systémové výzvy na začátku každého spuštění, takže agent ví, jaké dovednosti jsou k dispozici.
-
Načítání (< doporučeno: 5000 tokenů) - pokud úkol odpovídá oblasti dovednosti, agent zavolá nástroj
load_skill, aby získal celý obsah souboru SKILL.md s podrobnými pokyny. -
Čtení zdrojů (podle potřeby) – agent používá nástroj
read_skill_resourcek načtení doplňkových souborů (referenčních materiálů, šablon, podkladů) pouze v případě, že je to nutné. -
Spouštět skripty (podle potřeby) - Agent volá nástroj
run_skill_script, aby spustil skripty dodané spolu s dovedností.
Tento vzor udržuje štíhlé kontextové okno agenta, zatímco mu poskytuje přístup k hlubokým znalostem domény na vyžádání.
Poznámka:
load_skill je vždy inzerován.
read_skill_resource je inzerováno pouze pokud alespoň jedna schopnost má prostředky.
run_skill_script inzeruje se pouze v případech, kdy alespoň jedna dovednost obsahuje skripty.
Poskytování dovedností agentovi
Práce s dovednostmi zahrnuje tři stavební bloky:
-
Zprostředkovatel -
AgentSkillsProvider(C#) neboSkillsProvider(Python) je poskytovatel kontextu, který zpřístupňuje dovednosti agentům. Uvádí dostupné dovednosti v systémovém promptu a registruje nástroje, které agent používá k načítání dovedností, čtení zdrojů a spouštění skriptů. -
Zdroje – zdroj poskytuje zprostředkovateli dovednosti. Dovednosti můžou pocházet z několika zdrojových typů:
-
Založené na souborech – dovednosti zjištěné ze
SKILL.mdsouborů v adresářích systému souborů. -
Definované kódem – dovednosti definované v kódu pomocí
AgentInlineSkill(C#) neboInlineSkill(Python). -
Založené na třídách – schopnosti zapouzdřené ve třídě odvozené od
AgentClassSkill<T>(C#) neboClassSkill(Python). -
Založené na MCP – dovednosti zjištěné ze serverů MCP (Model Context Protocol) prostřednictvím
UseMcpSkills(C#) neboMCPSkillsSource(Python).
-
Založené na souborech – dovednosti zjištěné ze
-
Tvůrce -
AgentSkillsProviderBuilder(C#) sestaví více zdrojů do jednoho zprostředkovatele, použije agregaci, odstranění duplicitních dat, ukládání do mezipaměti a volitelné filtrování. V Pythonu přímo sestavte zdrojové třídy, napříkladAggregatingSkillsSource,FilteringSkillsSourceaDeduplicatingSkillsSource.
Následující části ukazují, jak vytvářet dovednosti pro jednotlivé typy zdrojů a poté jak zdroje kombinovat a sestavit z nich poskytovatele.
Dovednosti založené na souborech
Vytvořte AgentSkillsProvider odkaz na adresář obsahující vaše dovednosti a přidejte ho do poskytovatelů kontextu agenta. Předáním spouštěče skriptů povolte spouštění skriptů založených na souborech nalezených v adresářích dovedností:
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);
Výstraha
DefaultAzureCredential je vhodný pro vývoj, ale vyžaduje pečlivé zvážení v produkčním prostředí. V produkčním prostředí zvažte použití konkrétních přihlašovacích údajů (např ManagedIdentityCredential. ) k zabránění problémům s latencí, neúmyslnému testování přihlašovacích údajů a potenciálním bezpečnostním rizikům z náhradních mechanismů.
Více adresářů dovedností
Poskytovatele můžete nasměrovat na jediný nadřazený adresář – každý podadresář obsahující SKILL.md je automaticky rozpoznán jako dovednost:
var skillsProvider = new AgentSkillsProvider(
Path.Combine(AppContext.BaseDirectory, "all-skills"));
Nebo předejte seznam cest pro vyhledávání více kořenových adresářů:
var skillsProvider = new AgentSkillsProvider(
[
Path.Combine(AppContext.BaseDirectory, "company-skills"),
Path.Combine(AppContext.BaseDirectory, "team-skills"),
]);
Poskytovatel prohledává do hloubky až dvou úrovní.
Přizpůsobení zjišťování zdrojů a skriptů
Ve výchozím nastavení poskytovatel rozpoznává prostředky s příponami .md, .json, .yaml, .yml, .csv, .xml a .txt a skripty s příponami .py, .js, .sh, .ps1, .cs a .csx. Prohledává až dvě úrovně hluboko v rámci každého adresáře dovedností. Slouží AgentFileSkillsSourceOptions ke změně těchto výchozích hodnot:
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 a ScriptFilter obdrží AgentFileSkillFilterContext s názvem dovednosti a relativní cestou k souboru, což vám umožní omezit soubory podle umístění, konvence pojmenování nebo jakékoli vlastní logiky.
Spouštění skriptů
Zadejte SubprocessScriptRunner.RunAsync jako spouštěč skriptů, aby bylo možné spouštět skripty uložené v souborech:
var skillsProvider = new AgentSkillsProvider(
Path.Combine(AppContext.BaseDirectory, "skills"),
SubprocessScriptRunner.RunAsync);
SubprocessScriptRunner.RunAsync přibližně odpovídá následujícímu:
// 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();
}
Spouštěč spouští každý zjištěný skript jako místní podproces. Skripty založené na souborech očekávají argumenty jako pole řetězců JSON – každý prvek pole se stane pozičním argumentem příkazového řádku.
Výstraha
SubprocessScriptRunner je k dispozici pouze pro demonstrační účely. Pro použití v produkčním prostředí zvažte přidání:
- Sandboxing (například kontejnery nebo izolovaná spouštěcí prostředí)
- Limity prostředků (procesor, paměť, vypršení časového limitu hodin)
- Ověření vstupu a výpis spustitelných skriptů
- Strukturované protokolování a záznamy auditu
Dovednosti založené na souborech
SkillsProvider.from_paths() Pomocí objektu factory můžete vyhledat dovednosti v adresářích obsahujících soubory SKILL.md a přidejte poskytovatele do seznamu poskytovatelů kontextu agenta:
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],
)
Více adresářů dovedností
Poskytovatele můžete nasměrovat na jediný nadřazený adresář – každý podadresář obsahující SKILL.md je automaticky rozpoznán jako dovednost:
skills_provider = SkillsProvider.from_paths(
skill_paths=Path(__file__).parent / "all-skills"
)
Nebo předejte seznam cest pro vyhledávání více kořenových adresářů:
skills_provider = SkillsProvider.from_paths(
skill_paths=[
Path(__file__).parent / "company-skills",
Path(__file__).parent / "team-skills",
]
)
Poskytovatel prohledává do hloubky až dvou úrovní.
Přizpůsobení zjišťování zdrojů a skriptů
Ve výchozím nastavení se zdroje zjišťují z podadresářů references/ a assets/ a skripty z scripts/, podle specifikace agentskills.io. Rozpoznané přípony prostředků jsou .md, .json, .yaml, .yml, .csv, .xml a .txt. Prohledává až dvě úrovně hluboko v rámci každého adresáře dovedností. Použijte resource_extensions, script_extensions, search_depth, resource_filter a script_filter k přizpůsobení vyhledávání:
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/"),
)
Predikáty resource_filterscript_filter obdrží název dovednosti a relativní cestu k souboru, takže můžete omezit soubory podle umístění, zásady vytváření názvů nebo jakékoli vlastní logiky. Kromě podadresářů se používá "." k zahrnutí souborů na úrovni kořenové dovednosti.
Spouštění skriptů
Pokud chcete povolit spouštění skriptů založených na souborech, předejte script_runner do SkillsProvider.from_paths()souboru . Můžete použít jakoukoli synchronní nebo asynchronní funkci nebo metodu, které splňují SkillScriptRunner protokol:
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,
)
Spouštěč obdrží vyhodnocené argumenty FileSkill, FileSkillScript a volitelný argument args. Skripty založené na souborech očekávají argumenty jako pole řetězců JSON – každý prvek pole se stane pozičním argumentem příkazového řádku. Skripty se automaticky zjistí ze .py souborů v scripts/ podadresáři každého adresáře dovedností.
Výstraha
Výše uvedený běžec je k dispozici pouze pro demonstrační účely. Pro použití v produkčním prostředí zvažte přidání:
- Sandboxing (například kontejnery,
seccompnebofirejail) - Limity prostředků (procesor, paměť, vypršení časového limitu hodin)
- Ověření vstupu a výpis spustitelných skriptů
- Strukturované protokolování a záznamy auditu
Poznámka:
Pokud jsou k dispozici dovednosti založené na souborech se skripty, ale nejsou script_runner nastavené, SkillsProvider vyvolá při pokusu o spuštění skriptu chybu.
Dovednosti založené na souborech
Agenti Go podporují dovednosti prostřednictvím balíčku agent/skills. Dovednosti se řídí stejným vzorem postupného odhalování: nabízet –> načíst –> číst zdroje –> spouštět skripty.
Objevte dovednosti ze SKILL.md souborů na disku a zaregistrujte poskytovatele dovedností jako poskytovatele kontextu agenta:
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},
},
})
Dovednosti definované kódem
Kromě souborových dovedností zjištěných ze SKILL.md souborů můžete definovat dovednosti zcela v kódu pomocí AgentInlineSkill. Dovednosti definované kódem jsou užitečné v následujících případech:
- Obsah dovedností se generuje dynamicky (například čtení z databáze nebo prostředí).
- Chcete zachovat definice dovedností společně s kódem aplikace, který je používá.
- Potřebujete prostředky, které spouští logiku v době čtení, a ne obsluhují statické soubory.
- Definice dovedností je potřeba vytvářet za běhu z dat – například vytvořením přizpůsobené dovednosti pro každou uživatelskou relaci na základě role nebo oprávnění uživatele.
- Dovednost musí uzavírat nad stavem v místě volání (místní proměnné, uzávěry), nikoli získávat služby z kontejneru DI.
Základní dovednosti kódu
Vytvořte název AgentInlineSkill , popis a pokyny. Připojte prostředky pomocí .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);
Dynamické prostředky
Předat delegáta továrny .AddResource(), aby se obsah vypočítal během běhu programu. Delegát se vyvolá pokaždé, když agent přečte zdroj.
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)");
Skripty definované kódem
Slouží .AddScript() k registraci delegáta jako spustitelného skriptu. Skripty definované kódem běží v procesu jako přímá volání delegáta. Není potřeba žádný spouštěč skriptů. Zadané parametry delegáta se automaticky převedou na schéma JSON, které agent používá k předávání argumentů:
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);
Poznámka:
Chcete-li v jednom poskytovateli kombinovat dovednosti definované v kódu s dovednostmi založenými na souborech nebo třídách, použijte AgentSkillsProviderBuilder – viz Vytvoření poskytovatele.
Kromě dovedností založených na souborech zjištěných v souborech SKILL.md můžete definovat dovednosti zcela v kódu Python pomocí InlineSkill. Dovednosti definované kódem jsou užitečné v následujících případech:
- Obsah dovedností se generuje dynamicky (například čtení z databáze nebo prostředí).
- Chcete zachovat definice dovedností společně s kódem aplikace, který je používá.
- Potřebujete prostředky, které spouští logiku v době čtení, a ne obsluhují statické soubory.
- Definice dovedností je potřeba vytvářet za běhu z dat – například vytvořením přizpůsobené dovednosti pro každou uživatelskou relaci na základě role nebo oprávnění uživatele.
- Dovednost musí uzavírat stav v místě volání (místní proměnné, uzávěry), nikoli získávat služby prostřednictvím
**kwargs.
Základní dovednosti kódu
Vytvořte instanci InlineSkill pomocí SkillFrontmatter (obsahujícího název a popis) a obsahu instrukcí. Volitelně připojte InlineSkillResource instance se statickým obsahem:
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)
Dynamické prostředky
Pomocí dekorátoru @skill.resource zaregistrujte funkci jako zdroj. Funkce se volá pokaždé, když agent přečte prostředek, aby mohla vrátit aktuální data. Podporují se synchronizační i asynchronní funkce:
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)"
Když se dekorátor použije bez argumentů (@skill.resource), název funkce se stane názvem prostředku a docstring se stane popisem. Slouží @skill.resource(name="...", description="...") k jejich explicitní nastavení.
Skripty definované kódem
Pomocí dekorátoru @skill.script zaregistrujte funkci jako spustitelný skript pro dovednosti. Skripty definované kódem běží v procesu a nevyžadují spouštěč skriptů. Podporují se synchronizační i asynchronní funkce:
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})
Když se dekorátor použije bez argumentů (@skill.script), název funkce se změní na název skriptu a řetězec docstring se stane popisem. Typové parametry funkce se automaticky převedou na schéma JSON, které agent používá k předávání argumentů.
Kromě souborových dovedností zjištěných ze SKILL.md souborů můžete definovat dovednosti zcela v kódu 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 načte instrukce dovednosti pouze v případech, kdy agent volá load_skill. Skripty přijímají poziční řetězcové argumenty ve stylu CLI, například ["26.2", "1.60934"], a mohou tyto argumenty parsovat libovolným způsobem podle potřeb skriptu.
Návod
Podívejte se na příklady dovedností pro úplné spustitelné ukázky.
Dovednosti dle tříd
Dovednosti založené na třídě umožňují seskupovat všechny komponenty dovedností – název, popis, pokyny, prostředky a skripty – do jedné třídy jazyka C#. Díky tomu se dají snadno zabalit a distribuovat jako balíčky NuGet – týmy můžou vytvářet a dodávat dovednosti nezávisle a uživatelé je přidají s jedním dotnet add package voláním.UseSkill(). Odvozujte z AgentClassSkill<T> třídy (kde T je vaše třída), a pak anotujte vlastnosti s metodami [AgentSkillResource][AgentSkillScript] pro automatické zjišťování:
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 });
}
}
Zaregistrujte dovednost založenou na předmětu pomocí AgentSkillsProvider:
var skill = new UnitConverterSkill();
var skillsProvider = new AgentSkillsProvider(skill);
[AgentSkillResource] Když se atribut použije na vlastnost nebo metodu, jeho návratová hodnota se použije jako obsah prostředku, když agent přečte prostředek – použijte metodu, když se obsah musí vypočítat v době čtení. Metoda je vyvolána, když agent volá skript, pokud je [AgentSkillScript] použit na metodu. Použijte [Description] z System.ComponentModel k popisu jednotlivých prostředků a skriptů pro agenta.
Poznámka:
AgentClassSkill<T> také podporuje přepisování Resources a Scripts jako kolekcí pro situace, kde není zjišťování založené na atributech vhodné.
Dovednosti dle tříd
Dovednosti založené na třídě umožňují seskupovat všechny komponenty dovedností – název, popis, pokyny, prostředky a skripty – do jedné Python třídy. Díky tomu je lze snadno zabalit a distribuovat jako balíčky PyPI – týmy mohou dovednosti vytvářet a vydávat nezávisle a uživatelé je mohou přidávat pomocí pip install a jediného volání SkillsProvider(). Vytvořte podtřídu ClassSkill, potom použijte dekorátory @ClassSkill.resource a @ClassSkill.script pro automatické rozpoznání:
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})
Zaregistrujte dovednost založenou na předmětu pomocí SkillsProvider:
from agent_framework import SkillsProvider
skill = UnitConverterSkill()
skills_provider = SkillsProvider(skill)
Když @ClassSkill.resource se použije jako holý dekorátor (bez argumentů), název metody se změní na název prostředku (s podtržítky převedenými na spojovníky) a řetězec docstring se stane popisem. Slouží @ClassSkill.resource(name="...", description="...") k jejich explicitní nastavení. Stejný vzor platí pro @ClassSkill.script.
Zdroje lze definovat buď jako běžné metody, nebo jako deskriptory @property. Při použití @property umístěte nejprve @property a poté @ClassSkill.resource. Návratové hodnoty prostředků jsou po prvním přístupu ukládány do mezipaměti.
Poznámka:
ClassSkill také podporuje explicitní přepsání vlastností resources a scripts tak, aby přímo vracely instance InlineSkillResource a InlineSkillScript, pro případy, kdy nevyhovuje zjišťování založené na dekorátorech.
Dovednosti založené na MCP
Poznámka:
Dovednosti založené na MCP vyžadují Microsoft.Agents.AI.Mcp balíček NuGet. API dovedností MCP je experimentální a v budoucích vydáních se může změnit.
Dovednosti lze objevit ze serverů MCP (Model Context Protocol), které zpřístupňují zdroje dovedností v rámci schématu URI skill://. Server MCP oznamuje dovednosti prostřednictvím dokumentu zjišťování skill://index.json a rámec načítá obsah dovedností na vyžádání.
Dovednosti založené na MCP podporují dva typy položek indexu:
-
skill-md– Prostředky dovednostiSKILL.mda související prostředky se načítají podle potřeby ze serveru MCP. -
archive- Dovednost se distribuuje jako jeden zabalený archiv (ZIP, TAR nebo gzip-compressed TAR), který se stáhne a rozbalí místně.
Základní použití
Pomocí metody rozšíření UseMcpSkills pro AgentSkillsProviderBuilder přidejte zdroj dovedností 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);
Dovednosti archivního typu
Pro dovednosti typu archiv použijte AgentMcpSkillsSourceOptions (z balíčku Microsoft.Agents.AI.Mcp) ke konfiguraci chování při extrakci:
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 zveřejňuje následující vlastnosti pro řízení extrakce archivu:
-
ArchiveSkillsDirectory- Základní adresář pro extrahované archivy. Ve výchozím nastavení se vygeneruje jedinečný podadresář v aktuálním pracovním adresáři vygenerovaný pro každou zdrojovou instanci, aby nedocházelo ke kolizím mezi více zdroji. -
ArchiveResourceExtensions– Povolená rozšíření pro prostředky v extrahovaných archivech. Výchozí hodnoty:.md,.json,.yaml,.yml,.csv,.xml,.txt. -
ArchiveResourceSearchDepth- Jak hluboko prohledávat zdroje v každém extrahovaném adresáři dovedností. Výchozí hodnota je2. -
ArchiveMaxFileCount- Maximální počet souborů na archiv. Archivy překračující tento limit se přeskočí. Výchozí hodnota je20. -
ArchiveMaxSizeBytes- Maximální velikost stahování na archiv. Výchozí hodnota je1 MB. -
ArchiveMaxUncompressedSizeBytes- Maximální celková nekomprimovaná velikost na archiv. Výchozí hodnota je1 MB.
Important
Skripty, které jsou součástí dovedností archivního typu, se nikdy nespustí. Jedná se o záměrné bezpečnostní opatření – spustitelný obsah ze vzdálených serverů MCP vyžaduje explicitní vztah důvěryhodnosti.
Dovednosti založené na MCP
Poznámka:
Dovednosti založené na MCP jsou experimentální a v budoucích verzích se můžou změnit. Použití MCPSkillsSource vygeneruje FutureWarning při zapnutém příznaku funkce MCP_SKILLS.
Dovednosti lze objevit ze serverů MCP (Model Context Protocol), které zpřístupňují zdroje dovedností v rámci schématu URI skill://. Server MCP oznamuje dovednosti prostřednictvím dokumentu pro zjišťování skill://index.json a framework na vyžádání načítá obsah SKILL.md každé dovednosti prostřednictvím resources/read.
Zabalte MCP ClientSession do MCPSkillsSource a předejte jej do 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("...")
Poznámka:
Python MCPSkillsSource podporuje pouze skill-md položky indexu (položky indexu jakéhokoli jiného typu jsou bezobslužně vynechány). Na rozdíl od implementace .NET nepodporuje dovednosti typu archivace. Pokud skill://index.json chybí, nečitelný, prázdný nebo se nepodaří analyzovat, vrátí zdroj prázdný seznam.
Important
Externí server MCP určuje, jaký obsah dovedností – včetně pokynů a skriptů, které může agent spouštět – se k agentovi dostane. Připojte se MCPSkillsSource pouze k serverům, které jste prověřili a kterým důvěřujete, a jejich odpovědi považujte za nedůvěryhodná vstupní data.
Zdroje dovedností
AgentSkillsProvider načítá dovednosti z jednoho či více zdrojů – objektů, které implementují AgentSkillsSource. Zdroje spadají do dvou kategorií: zdroje typu list , které zjišťují nebo uchovávají dovednosti (například AgentFileSkillsSource pro dovednosti založené na souborech), a dekorátory , které transformují výstup jiného zdroje (agregace, odstranění duplicit, ukládání do mezipaměti a filtrování). Můžete také vytvořit vlastní zdroj.
Každý zdroj implementuje jednu metodu - GetSkillsAsync(AgentSkillsSourceContext context, CancellationToken cancellationToken = default).
AgentSkillsSourceContext obsahuje informace o aktuálním požadavku:
-
AgentAIAgent– instance požadující dovednosti. -
Session–AgentSessionpřidružené k volání nebonull, pokud neexistuje žádná relace.
Tento kontext je k dispozici v rámci zdrojového kanálu, takže FilteringAgentSkillsSource predikát nebo vlastní zdroj může na něm založit svou logiku – například vrácení jiné sady dovedností v závislosti na požadovaném agentovi.
Listové zdroje
AgentFileSkillsSource
Zjišťuje skilly v souborech SKILL.md na disku. Přijímá jednu nebo více cest k adresářům, volitelný spouštěč skriptů a volitelné AgentFileSkillsSourceOptions (zdokumentované v dovednostech založených na souborech).
var source = new AgentFileSkillsSource(
[Path.Combine(AppContext.BaseDirectory, "skills")],
scriptRunner: SubprocessScriptRunner.RunAsync,
options: new AgentFileSkillsSourceOptions { SearchDepth = 3 });
AgentInMemorySkillsSource
Zapouzdří instance AgentSkill (definované v kódu nebo založené na třídách) v paměti.
var source = new AgentInMemorySkillsSource([volumeConverterSkill, temperatureConverter]);
Kombinátory
AggregatingAgentSkillsSource
Kombinuje více zdrojů do jednoho. Dovednosti se vrátí v pořadí registrace bez odstranění duplicitních dat nebo použitého filtrování.
var aggregated = new AggregatingAgentSkillsSource([fileSource, inMemorySource]);
Decorators
Dekorátory obalují vnitřní zdroj a upravují jeho výstup. Lze je řetězit a vytvořit tak rouru.
DeduplicatingAgentSkillsSource
Odstraní duplicitní názvy schopností (bez rozlišení velkých a malých písmen, ponechá se první výskyt). Duplicitní položky se protokolují na úrovni upozornění.
var deduplicated = new DeduplicatingAgentSkillsSource(innerSource);
CachingAgentSkillsSource
Ukládá do mezipaměti seznam dovedností vrácený interním zdrojem. Souběžná volání jsou pro každý klíč mezipaměti zpracovávána sekvenčně, takže v jednu chvíli probíhá pouze jedno načtení. Přijímá volitelné CachingAgentSkillsSourceOptions:
-
RefreshInterval(TimeSpan?) – po nastavení vyprší platnost výsledků uložených v mezipaměti po tomto intervalu a znovu se vyvolá vnitřní zdroj. Je-li nastavena hodnotanull(výchozí nastavení), výsledky uložené v mezipaměti nikdy nevyprší. -
CacheIsolationKeySelector(Func<AgentSkillsSourceContext, string?>?) – vrátí klíč mezipaměti pro izolaci výsledků uložených v mezipaměti podle kontextu (například podle tenanta). Kdyžnullvšichni volající sdílejí jeden kontejner mezipaměti.
var cached = new CachingAgentSkillsSource(innerSource, new CachingAgentSkillsSourceOptions
{
RefreshInterval = TimeSpan.FromMinutes(5)
});
FilteringAgentSkillsSource
Použije predikát pro zahrnutí nebo vyloučení dovedností. Predikát obdrží dovednost a prvek AgentSkillsSourceContext.
var filtered = new FilteringAgentSkillsSource(
innerSource,
(skill, context) => skill.Frontmatter.Name != "experimental-skill");
Vlastní zdroje
Pokud předdefinované zdroje nepokrývají váš scénář, implementujte vlastní. Vytvořte podtřídu AgentSkillsSource pro koncový zdroj (tedy takový, který poskytuje dovednosti z nového zdroje, například z databáze nebo vzdálené služby), nebo podtřídu DelegatingAgentSkillsSource pro dekorátor, který transformuje výstup jiného zdroje.
Zdroj listu
Odvoďte od AgentSkillsSource a implementujte GetSkillsAsync. Argument AgentSkillsSourceContext umožňuje zdroji přizpůsobit jeho výsledek aktuálnímu požadavku – například vrácení jiné sady dovedností v závislosti na žádajícím agentovi. Přepište Dispose(bool), pokud objekt zdroje vlastní prostředky, například klienta nebo připojení.
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);
}
}
Vlastní dekorátor
Odvoďte z DelegatingAgentSkillsSource, zavolejte InnerSource.GetSkillsAsync a transformujte nebo sledujte výsledek. Jde o stejný vzor, jaký používají vestavěné dekorátory pro ukládání do mezipaměti, deduplikaci a filtrování. Například dekorátor, který zaznamenává, kolik dovedností bylo vráceno v rámci každého požadavku, aniž by změnil výsledek:
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;
}
}
Oba vlastní zdroje lze předat přímo do AgentSkillsProvider nebo je vnořit do větší pipeline, stejně jako vestavěné zdroje.
Konstrukce poskytovatele
AgentSkillsProvider je komponenta, která zpřístupňuje dovednosti agentům. Zabalí jeden nebo více zdrojů a zaregistruje load_skill, read_skill_resourcea run_skill_script nástroje. Existují tři způsoby, jak ho vytvořit:
-
AgentSkillsProviderBuilder– sestavuje více typů dovedností do jednoho zprostředkovatele s automatickým agregací, odstraněním duplicitních dat, ukládáním do mezipaměti a volitelným filtrováním. Nejvhodnější pro scénáře, které kombinují dovednosti založené na souborech, definované kódem, založené na třídách a MCP. -
Přímé sestavení zdroje – zdrojový řetězec si sestavte sami pomocí veřejných
AgentSkillsSourcetříd. Nepoužívá se automatické ukládání do mezipaměti ani odstranění duplicitních dat – řídíte celý kanál. Nejlepší volba, když potřebujete řídit pořadí, podmíněnou logiku nebo vlastní chování dekorátoru. - Konstruktory pro pohodlí – vytvořte zprostředkovatele přímo z cesty k souboru nebo instancí dovedností. Automaticky používá deduplikaci a ukládání do mezipaměti. Nejvhodnější pro scénáře s jedním zdrojem.
Použití AgentSkillsProviderBuilder
Použijte AgentSkillsProviderBuilder , když potřebujete některou z následujících možností:
-
Smíšené typy dovedností – kombinují dovednosti založené na souborech, definované kódem (
AgentInlineSkill), třídy (AgentClassSkill) a dovednosti založené na MCP v jednom poskytovateli. - Filtrování dovedností – zahrnutí nebo vyloučení dovedností pomocí predikátu
Typy smíšených dovedností
Kombinujte více typů dovedností v jednom poskytovateli řetězením UseFileSkill, UseSkill, UseMcpSkills a 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();
Filtrování dovedností
Pomocí UseFilter zahrnete pouze dovednosti, které splňují vaše kritéria – například k načtení dovedností ze sdíleného adresáře a vyloučení experimentálních dovedností:
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();
Přímé sestavování zdrojů
Pokud tvůrce nenabízí ovládací prvek, který potřebujete, vytvořte zdrojové třídy sami a předejte výsledný kanál AgentSkillsProvider. Úplný seznam dostupných zdrojů a jejich možností najdete v části Zdroje dovedností .
Následující příklad sestaví srovnatelný kanál z více zdrojů, ale poskytuje vám explicitní kontrolu nad jednotlivými dekorátory:
// 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);
Poznámka:
Pokud je ownsSourcetrue, uvolnění poskytovatele také uvolní celé zdrojové potrubí. Nastavte to na false, pokud životní cyklus prostředku spravujete sami.
Konstruktory pro pohodlí
Pro scénáře s jedním zdrojem použijte AgentSkillsProvider konstruktory přímo. Tyto automaticky uplatňují deduplikaci a ukládání do mezipaměti bez nutnosti nástroje pro sestavení nebo ruční definice zdroje.
Z cesty k souboru:
var skillsProvider = new AgentSkillsProvider(
Path.Combine(AppContext.BaseDirectory, "skills"),
scriptRunner: SubprocessScriptRunner.RunAsync);
Z instancí dovedností:
var skillsProvider = new AgentSkillsProvider(volumeConverterSkill, temperatureConverter);
Zdroje dovedností
A SkillsProvider načítá dovednosti z jednoho nebo více zdrojů - objekty, které jsou odvozeny z SkillsSource. Zdroje spadají do dvou kategorií: zdroje typu list , které zjišťují nebo uchovávají dovednosti (například FileSkillsSource pro dovednosti založené na souborech), a dekorátory , které transformují výstup jiného zdroje (agregace, odstranění duplicit, ukládání do mezipaměti a filtrování). Můžete také vytvořit vlastní zdroj.
Každý zdroj implementuje jednu metodu - async def get_skills(self, context: SkillsSourceContext) -> list[Skill].
SkillsSourceContext obsahuje informace o aktuálním požadavku:
-
agent- agent (SupportsAgentRun) požadující dovednosti. -
session–AgentSessionpřidružené k volání neboNone, pokud neexistuje žádná relace.
Tento kontext prochází celým zdrojovým kanálem, takže FilteringSkillsSource predikát nebo vlastní zdroj může na něm založit svou logiku – například vrácení jiné sady dovedností v závislosti na požadovaném agentovi.
Listové zdroje
-
FileSkillsSource- zjišťuje dovednosti zeSKILL.mdsouborů na disku. Přijímá jednu nebo více cest k adresářům, volitelnéscript_runnera možnosti vyhledávání (resource_extensions,script_extensions,search_depth,resource_filter,script_filter) popsané v dovednostech založených na souborech. -
InMemorySkillsSource– zapouzdřuje instanceSkill(definované v kódu nebo třídní) v paměti. -
MCPSkillsSource– zjišťuje dovednosti ze serveru MCP (viz dovednosti založené na 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])
Kombinátor
AggregatingSkillsSource kombinuje více zdrojů do jednoho. Dovednosti se vrátí v pořadí registrace bez odstranění duplicitních dat nebo použitého filtrování.
from agent_framework import AggregatingSkillsSource
aggregated = AggregatingSkillsSource([file_source, in_memory_source])
Decorators
Dekorátory obalují vnitřní zdroj a upravují jeho výstup. Lze je řetězit a vytvořit tak rouru.
-
DeduplicatingSkillsSource- odebere duplicitní názvy dovedností (nerozlišuje velká a malá písmena, první výskyt vyhrává). Duplicitní položky se protokolují na úrovni upozornění. -
CachingSkillsSource- ukládá seznam dovedností vrácený vnitřním zdrojem. Souběžná volání pro stejný klíč mezipaměti sdílejí jedno probíhající načtení, takže dotaz na vnitřní zdroj se pro každý klíč provede nejvýše jednou. Přijímá dva volitelné argumenty klíčových slov:-
refresh_interval(timedelta | None) – při nastavení se seznam uložený v mezipaměti považuje za zastaralý, jakmile je starší než interval, takže další volání znovu dotazuje vnitřní zdroj. Je-li nastavena hodnotaNone(výchozí nastavení), výsledky uložené v mezipaměti nikdy nevyprší. Vhodné pro interní zdroje, jejichž dovednosti se během životního cyklu procesu mění, napříkladMCPSkillsSource. -
cache_isolation_key_selector(Callable[[SkillsSourceContext], str | None]) – odvozuje klíč mezipaměti z kontextu pro oddělení výsledků v mezipaměti (například podle agenta nebo tenanta). Klíče by měly mít nízkou kardinalitu a být stabilní. Vrácení hodnotyNone(nebo ponecháníNone) používá jeden sdílený segment mezipaměti.
-
-
FilteringSkillsSource- použije predikát pro zahrnutí nebo vyloučení dovedností. Predikát přijímá dovednost aSkillsSourceContext: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",
)
Vlastní zdroje
Pokud předdefinované zdroje nepokrývají váš scénář, implementujte vlastní. Vytvořte podtřídu SkillsSource pro koncový zdroj (tedy takový, který poskytuje dovednosti z nového zdroje, například z databáze nebo vzdálené služby), nebo podtřídu DelegatingSkillsSource pro dekorátor, který transformuje výstup jiného zdroje.
Zdroj listu
Odvoďte od SkillsSource a implementujte get_skills. Argument SkillsSourceContext umožňuje zdroji přizpůsobit jeho výsledek aktuálnímu požadavku – například vrácení jiné sady dovedností v závislosti na žádajícím agentovi:
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)
Vlastní dekorátor
Odvoďte z DelegatingSkillsSource, zavolejte self.inner_source.get_skills(context) a transformujte nebo sledujte výsledek. Jde o stejný vzor, jaký používají vestavěné dekorátory pro ukládání do mezipaměti, deduplikaci a filtrování. Například dekorátor, který zaznamenává, kolik dovedností bylo vráceno v rámci každého požadavku, aniž by měnil výsledek:
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
Oba vlastní zdroje lze předat přímo do SkillsProvider nebo je vnořit do větší pipeline, stejně jako vestavěné zdroje.
Konstrukce poskytovatele
SkillsProvider je komponenta, která zpřístupňuje dovednosti agentům. Zabalí jeden nebo více zdrojů a zaregistruje load_skill, read_skill_resourcea run_skill_script nástroje. Existují tři způsoby, jak ho vytvořit:
-
Z instancí dovedností – předejte konstruktoru jednu
Skillnebo posloupnost dovedností. Nejvhodnější pro dovednosti definované kódem a založené na třídách. Automaticky používá deduplikaci a ukládání do mezipaměti. -
Ze souborových cest – použijte metodu
SkillsProvider.from_paths()factory. Nejvhodnější pro dovednosti založené na souborech s jedním zdrojem. Automaticky používá deduplikaci a ukládání do mezipaměti. -
Přímé sestavení zdroje – sami sestavte zdrojový řetězec pomocí veřejných tříd
SkillsSourcea předejte jej konstruktoru. Řídíte celý řetězec. Nejlepší, když potřebujete mít kontrolu nad řazením, podmíněnou logikou, ukládáním klíčů do mezipaměti nebo vlastním chováním dekorátoru.
Z instancí dovednosti
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])
Podle cest k souborům
from pathlib import Path
from agent_framework import SkillsProvider
skills_provider = SkillsProvider.from_paths(
skill_paths=Path(__file__).parent / "skills",
script_runner=my_runner,
)
Přímé sestavování zdrojů
Pokud potřebujete plnou kontrolu, sestavte si zdrojové třídy sami a výslednou pipeline předejte SkillsProvider. Úplný seznam dostupných zdrojů a jejich možností najdete v části Zdroje dovedností .
Níže uvedený příklad vytvoří pipeline z více zdrojů s explicitní kontrolou každého dekorátoru. Příklad používá zástupné objekty:
-
volume_converter_skill– libovolnáInlineSkillinstance vytvořená podle kódu definovaných dovedností. -
temperature_converter_skill– libovolnáClassSkillinstance vytvořená podle postupu uvedeného v Dovednostech založených na třídách. -
my_runner– volatelná entita, definovanáSkillScriptRunnertak, jak je uvedeno v Provádění skriptu.
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
Objekt SkillsSource, který poskytne volající, se použije beze změn: není automaticky deduplikován ani zabalen do CachingSkillsSource. Automatické ukládání do mezipaměti zdroje s podporou kontextu v jednom sdíleném kontejneru může přehrát dovednosti jednoho agenta nebo tenanta pro jiný. Když je potřebujete, vytvořte si sami DeduplicatingSkillsSource a CachingSkillsSource (volitelně s cache_isolation_key_selector). Automatické odstranění duplicitních dat a ukládání do mezipaměti platí jenom v případech, kdy předáte dovednosti nebo cesty k souborům přímo (možnosti 1 a 2 výše).
Typy smíšených dovedností
Kombinování dovedností založených na souborech, definovaných kódem a tříd v jednom poskytovateli pomocí 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]),
])
)
)
Filtrování dovedností
Pomocí FilteringSkillsSource můžete určit, které dovednosti agent uvidí. Predikát obdrží každý Skill a SkillsSourceContext a vrací True, aby byla dovednost zahrnuta. Například pokud chcete načíst dovednosti ze sdíleného adresáře, ale skrýt experimentální dovednost:
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",
)
)
)
Chování při ukládání do mezipaměti
Ve výchozím nastavení generátor obalí zdrojový kanál zpracování pomocí CachingAgentSkillsSource, která ukládá do mezipaměti seznam dovedností vrácených podkladovými zdroji. Jakmile se dovednosti vyřeší na prvním požadavku, následné žádosti znovu použijí seznam uložený v mezipaměti bez opětovného dotazování zdrojů. Pokud chcete zakázat ukládání do mezipaměti (například při časté změně definic dovedností při vývoji), použijte DisableCaching() v tvůrci:
var skillsProvider = new AgentSkillsProviderBuilder()
.UseFileSkill(Path.Combine(AppContext.BaseDirectory, "skills"))
.UseFileScriptRunner(SubprocessScriptRunner.RunAsync)
.DisableCaching()
.Build();
Poznámka:
Zakázání ukládání do mezipaměti je užitečné při vývoji, když se obsah dovedností často mění. V produkčním prostředí ponechte ukládání do mezipaměti povolené (výchozí) kvůli lepšímu výkonu.
Chování při ukládání do mezipaměti
Standardně se nástroje a pokyny pro dovednosti ukládají po prvním sestavení do mezipaměti. Nastavte disable_caching=True na vynucení opětovného sestavení při každém vyvolání:
skills_provider = SkillsProvider.from_paths(
skill_paths=Path(__file__).parent / "skills",
disable_caching=True,
)
disable_caching je také k dispozici v konstruktoru SkillsProvider pro dovednosti definované kódem a třídy.
Chcete-li ponechat ukládání do mezipaměti povolené, ale pravidelně znovu zjišťovat dostupné dovednosti (například když se za běhu procesu změní zdroj založený na souborech nebo zdroj MCP), předejte cache_refresh_interval. Předdefinovaná mezipaměť se považuje za zastaralou, jakmile je starší než interval, takže další spuštění znovu odešle dotazy na zdroj:
from datetime import timedelta
skills_provider = SkillsProvider.from_paths(
skill_paths=Path(__file__).parent / "skills",
cache_refresh_interval=timedelta(minutes=5),
)
cache_refresh_interval ovlivňuje pouze mezipaměť, kterou poskytovatel interně vytváří (z dovedností nebo cest k souborům); je ignorován, když disable_caching=True, a nemá žádný vliv na SkillsSource, který dodá volající (pro tyto případy si sestavte vlastní CachingSkillsSource s refresh_interval).
Poznámka:
Zakázání ukládání do mezipaměti je užitečné při vývoji, když se obsah dovedností často mění. V produkčním prostředí ponechte ukládání do mezipaměti povolené (výchozí) kvůli lepšímu výkonu.
Schválení nástroje
Všechny nástroje zpřístupněné pomocí AgentSkillsProvider (load_skill, read_skill_resource, run_skill_script) ve výchozím nastavení vyžadují schválení. Když volání nástroje vyžaduje schválení, agent se pozastaví a vrátí ToolApprovalRequestContent místo okamžitého spuštění. Pomocí UseToolApproval middlewaru s pravidly automatického schvalování můžete selektivně obejít výzvy k důvěryhodným operacím:
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();
Automatické schvalování všech nástrojů dovedností, včetně spouštění skriptů:
.UseToolApproval(new ToolApprovalAgentOptions
{
AutoApprovalRules = [AgentSkillsProvider.AllToolsAutoApprovalRule],
})
Zakázání schválení pro konkrétní nástroje
Slouží AgentSkillsProviderOptions k zakázání schvalování jednotlivých nástrojů a jejich odebrání z toku schválení zcela:
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
});
Pokud některé nástroje v rámci téže odpovědi vyžadují schválení a jiné nikoli, model může současně volat oba typy. Nastavte EnableNonApprovalRequiredFunctionBypassing , aby se nástroje bez schválení spouštěly okamžitě, když se uživateli zobrazí výzva pouze pro zbývající nástroje:
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();
Zpracování žádostí o schválení
Pokud nástroje vyžadují schválení (a neodpovídá žádné pravidlo automatického schvalování), agent vrátí položky ToolApprovalRequestContent, které je třeba před pokračováním schválit nebo odmítnout:
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();
}
Podrobnosti o chybě skriptu
Ve výchozím nastavení se při selhání spuštění skriptu dovednosti výjimka propaguje do podkladového FunctionInvokingChatClient. Pokud je jeho vlastnost IncludeDetailedErrors nastavena na true, zpráva o výjimce je předána modelu, což mu umožňuje, aby se sám opravil opakovaným pokusem s jinými argumenty:
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());
Pokud nemůžete konfigurovat FunctionInvokingChatClient přímo, nastavte AgentSkillsProviderOptions.IncludeDetailedErrors místo toho. Tím se zachytí výjimka na úrovni poskytovatele dovedností a vrátí chybovou zprávu přímo do modelu:
var skillsProvider = new AgentSkillsProvider(
Path.Combine(AppContext.BaseDirectory, "skills"),
SubprocessScriptRunner.RunAsync,
options: new AgentSkillsProviderOptions
{
IncludeDetailedErrors = true,
});
Výstraha
Některý z přístupů může modelu zveřejnit nezpracované podrobnosti o výjimce. Zprávy o výjimkách můžou obsahovat citlivé informace, jako jsou připojovací řetězce, cesty k souborům nebo interní názvy služeb. Kromě toho, pokud dovednosti nebo skripty pocházejí z nedůvěryhodných zdrojů, může škodlivě vytvořený skript vyvolat výjimku, jejíž zpráva obsahuje payload útoku typu prompt injection.
Ve výchozím nastavení vyžadují schválení všechny nástroje zpřístupněné prostřednictvím SkillsProvider (load_skill, read_skill_resource a run_skill_script). Když volání nástroje vyžaduje schválení, agent se pozastaví a vrátí požadavky na schválení prostřednictvím result.user_input_requests namísto okamžitého provedení. Každou žádost schválíte nebo zamítnete pomocí request.to_function_approval_response(approved=...) a odešlete odpovědi zpět:
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)
Když je volání nástroje odmítnuto (approved=False), agent je informován, že uživatel odmítl a může odpovídajícím způsobem reagovat.
Automatické schvalování důvěryhodných nástrojů
Namísto výzvy při každém volání nainstalujte ToolApprovalMiddleware s jedním ze statických pravidel automatického schvalování poskytovaných nástrojem SkillsProvider. Nástroje jen pro čtení se tak pustí automaticky, i když se stále zobrazují výzvy ke spuštění skriptu:
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],
)
K dispozici jsou dvě pravidla:
-
SkillsProvider.read_only_tools_auto_approval_rule- schvaluje pouze nástroje jen pro čtení (load_skill,read_skill_resource), přičemž prorun_skill_scriptse stále zobrazí výzva. -
SkillsProvider.all_tools_auto_approval_rule– schválí všechny nástroje dovedností, včetněrun_skill_script(není potřeba žádný ruční schvalovací proces).
Obě pravidla odmítnou všechny volání, které nesou server_labelnázev , takže zůstanou omezené na místní nástroje tohoto poskytovatele a nikdy automaticky neschvalují stejný hostovaný nástroj. Pravidla se vztahují pouze na nástroje, které stále vyžadují schválení – nástroje vyjmuté pomocí níže uvedených argumentů disable_*_approval se bez schválení spustí v každém případě.
Zakázání schválení pro konkrétní nástroje
Pro důvěryhodné dovednosti předejte disable_load_skill_approval, disable_read_skill_resource_approval a/nebo disable_run_skill_script_approval, chcete-li jednotlivé nástroje zcela vyjmout z procesu schvalování (jsou registrovány pomocí 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
)
Tyto argumenty jsou k dispozici také pro SkillsProvider.from_paths().
Výstraha
Schvalování vypněte nebo automatické schvalování spouštění skriptů zapněte pouze u dovedností a skriptů ze zdrojů, kterým důvěřujete. Pokyny ke dovednostem se vloží do kontextu agenta a run_skill_script spustí kód zadaný zdrojem.
Výzva pro přizpůsobený systém
Ve výchozím nastavení poskytovatel dovedností vloží systémovou výzvu, která obsahuje seznam dostupných dovedností a dává agentovi pokyn, aby používal load_skill a read_skill_resource. Tuto výzvu můžete přizpůsobit:
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.
"""
});
Poznámka:
Vlastní šablona musí obsahovat {skills} jako zástupný symbol pro vygenerovaný seznam dovedností. Doslovné složené závorky musí být eskapované jako {{ a }}.
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}"
),
)
Poznámka:
Vlastní šablona musí obsahovat zástupný symbol {skills} pro vygenerovaný seznam dovedností. Může volitelně obsahovat zástupné symboly {resource_instructions} (nápověda k nástroji pro prostředky) a {runner_instructions} (nápověda k nástroji pro skripty); když jsou přítomny, doplní se předdefinovanými pokyny, a když jsou vynechány, jednoduše se nezobrazí (odpovídající nástroje jsou stále zaregistrovány). Doslovné složené závorky musí být eskapované jako {{ a }}.
Vkládání argumentů služeb a modulu runtime
Funkce zdrojů dovedností a skriptů mohou přijímat kontext externí aplikace poskytnutý za běhu.
Delegáti zdrojů dovedností a skriptů mohou deklarovat IServiceProvider parametr, který Agent Framework automaticky vloží. To umožňuje dovednostem vyřešit zaregistrované aplikační služby na vyžádání.
Setup
Zaregistrujte aplikační služby a předávejte sestavený IServiceProvider agentovi prostřednictvím parametru 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);
Dovednosti definované kódem pomocí DI
Deklarujte IServiceProvider jako parametr v delegátech AddResource nebo AddScript – framework ji automaticky rozpozná a vloží, když agent načte prostředek nebo spustí skript:
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);
});
Dovednosti založené na třídách s DI
Opatřete metody pomocí [AgentSkillResource] nebo [AgentSkillScript] a deklarujte parametr IServiceProvider – framework tyto členy rozpozná prostřednictvím reflexe a automaticky injektuje poskytovatele služeb:
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);
}
}
Návod
Dovednosti založené na třídách můžou také řešit závislosti prostřednictvím jejich konstruktoru. Zaregistrujte třídu dovedností v kontejneru ServiceCollection a získejte ji z kontejneru místo přímého volání new.
services.AddSingleton<WeightConverterSkill>();
var weightSkill = serviceProvider.GetRequiredService<WeightConverterSkill>();
To je užitečné, když třída dovedností sama potřebuje vložené služby nad rámec toho, co používají delegáti prostředků a skriptů.
Funkce pro zdroje a skripty, které přijmou **kwargs, automaticky obdrží modulu runtime klíčové argumenty ve formě klíčového slova, předané do agent.run(). Díky tomu budou funkce dovedností přistupovat k kontextu aplikace , jako je konfigurace, identita uživatele nebo klienti služeb, aniž by je pevně zakódovaly do definice dovednosti.
Předávání argumentů modulu runtime
Prostřednictvím function_invocation_kwargs předáte do agent.run() klíčové argumenty, které framework předává funkcím pro prostředky a skripty:
response = await agent.run(
"How many kilometers is 26.2 miles?",
function_invocation_kwargs={"precision": 2, "user_id": "alice"},
)
Dovednosti definované kódem s využitím kwargs
Když funkce prostředku deklaruje **kwargs, architektura předává argumenty klíčového slova modulu runtime pokaždé, když agent přečte prostředek:
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}"
Prostředkové funkce bez **kwargs argumentů se volají bez argumentů a neobdrží žádný kontext za běhu.
Když funkce skriptu deklaruje **kwargs, rámec předá argumenty klíčového slova modulu runtime args spolu s těmi, které poskytl 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})
Agent poskytuje value a factor prostřednictvím volání nástroje; aplikace poskytuje args prostřednictvím precisionfunction_invocation_kwargs. Funkce skriptu bez **kwargs příjmu pouze argumentů zadaných agentem.
Schopnosti založené na třídě s kwargs
Metody dovedností založené na třídách mohou také přijímat **kwargs argumenty modulu runtime. Vzor funguje stejným způsobem – deklarujte **kwargs u metod prostředků nebo metod skriptů:
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})
Osvědčené postupy zabezpečení
Dovednosti agenta by se měly považovat za jakýkoli kód třetí strany, který do projektu přenesete. Vzhledem k tomu, že pokyny ke dovednostem se vloží do kontextu agenta – a dovednosti můžou zahrnovat skripty – použití stejné úrovně kontroly a zásad správného řízení, které byste použili u opensourcové závislosti, je nezbytné.
-
Než začnete používat , přečtěte si veškerý obsah dovedností (
SKILL.mdskripty a prostředky) před nasazením. Ověřte, že skutečné chování skriptu odpovídá jeho zadanému záměru. Zkontrolujte nežádoucí pokyny, které se pokoušejí obejít bezpečnostní pokyny, exfiltrovat data nebo upravit konfigurační soubory agenta. - Důvěryhodnost zdroje – Nainstalujte jenom dovednosti od důvěryhodných autorů nebo prověřených interních přispěvatelů. Preferujte dovednosti s jasnou proveniencem, správou verzí a aktivní údržbou. Podívejte se na překlepové názvy dovedností, které napodobují oblíbené balíčky.
- Sandboxing – Spouštění dovedností, které zahrnují spustitelné skripty v izolovaných prostředích Omezte přístup na úrovni systému souborů, sítě a systému jenom na to, co dovednost vyžaduje. Před spuštěním potenciálně citlivých operací budete vyžadovat explicitní potvrzení uživatele.
- Audit a protokolování – Zaznamenává, které dovednosti jsou načteny, které zdroje jsou čteny a které skripty jsou spuštěny. To vám poskytne záznam auditu, který umožní sledovat chování agenta zpětně k specifickému obsahu dovedností, pokud se něco nepovede.
Kdy používat dovednosti vs. pracovní postupy
Dovednosti agentů a pracovní postupy rámce agenta rozšiřují schopnosti agentů, ale fungují v zásadě různými způsoby. Zvolte přístup, který nejlépe odpovídá vašim požadavkům:
- Řízení – S dovedností se AI rozhodne, jak provést instrukce. To je ideální, když chcete, aby agent byl kreativní nebo adaptivní. V pracovním postupu explicitně definujete cestu provádění. Pracovní postupy používejte v případě, že potřebujete deterministické a předvídatelné chování.
- Odolnost – dovednost probíhá v rámci jednoho tahu agenta. Pokud se něco nepovede, musí se celá operace opakovat. Pracovní postupy podporují checkpointing, takže mohou pokračovat od posledního úspěšného kroku po selhání. Zvolte pracovní postupy, když jsou náklady na opětovné spuštění celého procesu vysoké.
- Vedlejší účinky – Dovednosti jsou vhodné tehdy, když jsou operace idempotentní nebo nízkorizikové. Upřednostňujte pracovní postupy, pokud kroky vytvářejí vedlejší účinky (odesílání e-mailů, účtování plateb), které by se neměly opakovat při opakování.
- Složitost – Dovednosti jsou nejvhodnější pro úlohy zaměřené na jednu doménu, které může jeden agent zpracovat. Pracovní postupy jsou vhodnější pro vícekrokové obchodní procesy, které koordinuje více agentů, schvalování lidí nebo integrace externího systému.
Návod
Obecně platí, že pokud chcete, aby umělé inteligence dokázali zjistit, jak provést úkol, použijte dovednost. Pokud potřebujete zaručit , jaké kroky se provádějí a v jakém pořadí, použijte pracovní postup.