Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Agentkunskaper är portabla paket med instruktioner, skript och resurser som ger agenter specialiserade funktioner och domänexpertis. Färdigheter följer en öppen specifikation och implementerar ett progressivt avslöjandemönster så att agenter bara läser in den kontext de behöver, när de behöver den.
Använd agentkunskaper när du vill:
- Expertkunskaper om paketdomäner – Samla in specialiserad kunskap (kostnadsprinciper, juridiska arbetsflöden, pipelines för dataanalys) som återanvändbara, portabla paket.
- Utöka agentfunktioner – Ge agenter nya förmågor utan att ändra sina grundläggande instruktioner.
- Säkerställa konsekvens – Omvandla flerstegsaktiviteter till repeterbara, granskningsbara arbetsflöden.
- Aktivera samverkan – Återanvänd samma kunskaper i olika Agent Skills-kompatibla produkter.
Kompetensstruktur
En färdighet är en katalog som innehåller en SKILL.md fil med valfria underkataloger för resurser:
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
SKILL.md-format
Filen SKILL.md måste innehålla YAML-frontmatter följt av markdown-innehåll:
---
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"
---
| Fält | Krävs | Description |
|---|---|---|
name |
Ja | Max 64 tecken. Endast gemener, siffror och bindestreck. Får inte starta eller sluta med ett bindestreck eller innehålla bindestreck i följd. Måste matcha det överordnade katalognamnet. |
description |
Ja | Vad skickligheten gör och när du ska använda den. Max 1 024 tecken. Bör innehålla nyckelord som hjälper agenter att identifiera relevanta uppgifter. |
license |
Nej. | Licensnamn eller referens till en paketerad licensfil. |
compatibility |
Nej. | Max 500 tecken. Anger miljökrav (avsedd produkt, systempaket, nätverksåtkomst osv.). |
metadata |
Nej. | Godtycklig nyckelvärdesmappning för ytterligare metadata. |
allowed-tools |
Nej. | Utrymmesavgränsad lista över förgodkända verktyg som färdigheten kan använda. Experimentell – stödet kan variera mellan agentimplementeringar. |
Markdown-brödtexten efter frontmattern innehåller kunskapsinstruktionerna – stegvis vägledning, exempel på indata och utdata, vanliga gränsfall eller innehåll som hjälper agenten att utföra uppgiften. Behåll SKILL.md under 500 rader och flytta detaljerat referensmaterial till separata filer.
Progressivt avslöjande
Agentkunskaper använder ett progressivt avslöjandemönster i fyra steg för att minimera kontextanvändningen:
- Annonsering (cirka 100 token per färdighet) – Färdighetsnamn och beskrivningar infogas i systemprompten i början av varje körning, så att agenten vet vilka färdigheter som är tillgängliga.
-
Läs in (< 5 000 token rekommenderas) - När en uppgift matchar en färdighetsdomän anropar agenten verktyget
load_skillför att hämta hela innehållet i SKILL.md med detaljerade instruktioner. -
Läs resurser (efter behov) – Agenten
read_skill_resourceanropar verktyget för att hämta tilläggsfiler (referenser, mallar, tillgångar) endast när det behövs. -
Kör skript (efter behov) – Agenten
run_skill_scriptanropar verktyget för att köra skript som paketeras med en färdighet.
Det här mönstret håller agentens kontextfönster snålt samtidigt som det får åtkomst till djup domänkunskap på begäran.
Anmärkning
load_skill annonseras alltid.
read_skill_resource annonseras endast när minst en färdighet har resurser.
run_skill_script annonseras endast när minst en färdighet har skript.
Tillhandahålla kunskaper till en agent
Att arbeta med färdigheter omfattar tre byggstenar:
-
Provider -
AgentSkillsProvider(C#) ellerSkillsProvider(Python) är en kontextprovider som exponerar färdigheter för en agent. Den annonserar de tillgängliga färdigheterna i systemprompten och registrerar de verktyg som agenten använder för att läsa in färdigheter, läsa resurser och köra skript. -
Källor – en källa tillhandahåller kunskaper till leverantören. Kunskaper kan komma från flera källtyper:
-
Filbaserad – kunskaper som identifieras från
SKILL.mdfiler i filsystemkataloger. -
Koddefinierade – färdigheter som definieras direkt i koden med
AgentInlineSkill(C#) ellerInlineSkill(Python). -
Klassbaserad – kunskaper inkapslade i en klass som härleds från
AgentClassSkill<T>(C#) ellerClassSkill(Python). -
MCP-baserad – kunskaper som identifieras från MCP-servrar (Model Context Protocol) via
UseMcpSkills(C#) ellerMCPSkillsSource(Python).
-
Filbaserad – kunskaper som identifieras från
-
Builder -
AgentSkillsProviderBuilder(C#) monterar flera källor i en enda provider och tillämpar aggregering, deduplicering, cachelagring och valfri filtrering. I Python skapar du källklasser somAggregatingSkillsSource,FilteringSkillsSourceochDeduplicatingSkillsSourcedirekt.
I följande avsnitt visas hur du skapar kunskaper för varje källtyp och sedan hur du kombinerar källor och konstruerar en provider från dem.
Filbaserade kunskaper
Skapa en AgentSkillsProvider som pekar på en mapp som innehåller dina kompetenser och lägg till den i agentens kontexthanterare. Skicka ett skript för att aktivera körning av filbaserade skript som finns i kunskapskataloger:
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);
Varning
DefaultAzureCredential är praktiskt för utveckling men kräver noggrant övervägande i produktion. I produktion bör du överväga att använda en specifik autentiseringsuppgift (t.ex. ManagedIdentityCredential) för att undvika problem med svarstid, oavsiktlig avsökning av autentiseringsuppgifter och potentiella säkerhetsrisker från reservmekanismer.
Flera kompetenskataloger
Du kan peka providern till en enda överordnad katalog – varje underkatalog som innehåller en SKILL.md identifieras automatiskt som en färdighet:
var skillsProvider = new AgentSkillsProvider(
Path.Combine(AppContext.BaseDirectory, "all-skills"));
Eller skicka en lista över sökvägar för att söka i flera rotkataloger:
var skillsProvider = new AgentSkillsProvider(
[
Path.Combine(AppContext.BaseDirectory, "company-skills"),
Path.Combine(AppContext.BaseDirectory, "team-skills"),
]);
Leverantören söker djupt upp till två nivåer.
Anpassa resurs- och skriptidentifiering
Som standard identifierar leverantören resurser med tilläggen .md, .json, .yaml, .yml, .csv, .xml och .txt samt skript med tilläggen .py, .js, .sh, .ps1, .cs och .csx. Den söker i upp till två nivåer djupt inom varje kunskapskatalog. Använd AgentFileSkillsSourceOptions för att ändra dessa standardvärden:
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 och ScriptFilter får en AgentFileSkillFilterContext med färdighetsnamnet och filens relativa sökväg, så att du kan begränsa filer baserat på plats, namngivningskonvention eller anpassad logik.
Skriptkörning
Skicka SubprocessScriptRunner.RunAsync som skriptkörare för att aktivera körning av filbaserade skript:
var skillsProvider = new AgentSkillsProvider(
Path.Combine(AppContext.BaseDirectory, "skills"),
SubprocessScriptRunner.RunAsync);
SubprocessScriptRunner.RunAsync motsvarar ungefär följande:
// 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();
}
Körprogrammet kör varje identifierat skript som en lokal underprocess. Filbaserade skript förväntar sig argument som en JSON-matris med strängar – varje matriselement blir ett positionellt kommandoradsargument.
Varning
SubprocessScriptRunner
tillhandahålls endast i demonstrationssyfte. För produktionsanvändning bör du överväga att lägga till:
- Sandbox-miljö (till exempel containrar eller isolerade körningsmiljöer)
- Resursgränser (CPU, minne, tidsgräns för väggklocka)
- Indataverifiering och tillåten lista över körbara skript
- Strukturerad loggning och revisionsspår
Filbaserade kunskaper
Använd SkillsProvider.from_paths()-fabriken för att upptäcka färdigheter från kataloger som innehåller SKILL.md-filer och lägg till leverantören i agentens kontextleverantörer:
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],
)
Flera kompetenskataloger
Du kan peka providern till en enda överordnad katalog – varje underkatalog som innehåller en SKILL.md identifieras automatiskt som en färdighet:
skills_provider = SkillsProvider.from_paths(
skill_paths=Path(__file__).parent / "all-skills"
)
Eller skicka en lista över sökvägar för att söka i flera rotkataloger:
skills_provider = SkillsProvider.from_paths(
skill_paths=[
Path(__file__).parent / "company-skills",
Path(__file__).parent / "team-skills",
]
)
Leverantören söker djupt upp till två nivåer.
Anpassa resurs- och skriptidentifiering
Som standard identifieras resurser från references/ och assets/ underkataloger och skript från scripts/, enligt agentskills.io-specifikationen. Identifierade resurstillägg är .md, .json, .yaml, .yml, .csv, .xmloch .txt. Den söker i upp till två nivåer djupt inom varje kunskapskatalog. Använd resource_extensions, script_extensions, search_depth, resource_filteroch script_filter för att anpassa identifiering:
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/"),
)
Predikaten resource_filter och script_filter får kunskapsnamnet och filens relativa sökväg, så att du kan begränsa filer efter plats, namngivningskonvention eller någon anpassad logik. Använd "." för att inkludera filer på kunskapsrotsnivå utöver underkataloger.
Skriptkörning
Om du vill aktivera körning av filbaserade skript skickar du ett script_runner till SkillsProvider.from_paths(). Alla synkrona eller asynkrona anropbara SkillScriptRunner som uppfyller protokollet kan användas:
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,
)
Köraren tar emot de lösta argumenten FileSkill, FileSkillScript och ett valfritt args. Filbaserade skript förväntar sig argument som en JSON-matris med strängar – varje matriselement blir ett positionellt kommandoradsargument. Skript upptäcks automatiskt från .py-filer i underkatalogen scripts/ i varje kunskapskatalog.
Varning
Löparen ovan tillhandahålls endast i demonstrationssyfte. För produktionsanvändning bör du överväga att lägga till:
- Sandbox-miljö (till exempel containrar,
seccompellerfirejail) - Resursgränser (CPU, minne, tidsgräns för väggklocka)
- Indataverifiering och tillåten lista över körbara skript
- Strukturerad loggning och revisionsspår
Anmärkning
Om filbaserade färdigheter med skript tillhandahålls men ingen script_runner har angetts, genererar SkillsProvider ett fel när man försöker köra skriptet.
Filbaserade kunskaper
Go-agenter stöder färdigheter genom paketet agent/skills. Färdigheterna följer samma mönster för progressivt avslöjande: annonsera –> läsa in –> läsa resurser –> köra skript.
Identifiera färdigheter från SKILL.md filer på disken och registrera kompetensprovidern som en agentkontextprovider:
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},
},
})
Koddefinierade kunskaper
Förutom filbaserade kunskaper som identifieras från SKILL.md filer kan du definiera kunskaper helt och hållet i kod med hjälp av AgentInlineSkill. Koddefinierade kunskaper är användbara när:
- Kunskapsinnehåll genereras dynamiskt (till exempel läsning från en databas eller miljö).
- Du vill behålla kunskapsdefinitioner tillsammans med programkoden som använder dem.
- Du behöver resurser som kör logik vid lästid i stället för att hantera statiska filer.
- Skilldefinitioner måste skapas vid körning utifrån data - till exempel genom att skapa en anpassad skill för varje användarsession utifrån användarens roll eller behörigheter.
- En kunskap måste stänga över anropsplatstillstånd (lokala variabler, stängningar) i stället för att lösa tjänster från en DI-container.
Grundläggande kodfärdighet
Skapa en AgentInlineSkill med namn, beskrivning och instruktioner. Koppla resurser med hjälp av .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);
Dynamiska resurser
Skicka en fabriksdelegat till .AddResource() för att beräkna innehållet under körning. Ombudet anropas varje gång agenten läser resursen:
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)");
Koddefinierade skript
Använd .AddScript() för att registrera en delegat som ett körbart skript. Koddefinierade skript körs i processen som direkta delegatanrop. Ingen skriptlöpare behövs. Ombudets typade parametrar konverteras automatiskt till ett JSON-schema som agenten använder för att skicka 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);
Anmärkning
Om du vill kombinera koddefinierade kunskaper med filbaserade eller klassbaserade färdigheter i en enda provider kan du använda AgentSkillsProviderBuilder – se Leverantörskonstruktion.
Förutom filbaserade kunskaper som identifieras från SKILL.md filer kan du definiera färdigheter helt i Python kod med hjälp av InlineSkill. Koddefinierade kunskaper är användbara när:
- Kunskapsinnehåll genereras dynamiskt (till exempel läsning från en databas eller miljö).
- Du vill behålla kunskapsdefinitioner tillsammans med programkoden som använder dem.
- Du behöver resurser som kör logik vid lästid i stället för att hantera statiska filer.
- Skilldefinitioner måste skapas vid körning utifrån data - till exempel genom att skapa en anpassad skill för varje användarsession utifrån användarens roll eller behörigheter.
- En kunskap måste stänga över anropsplatstillstånd (lokala variabler, stängningar) i stället för att lösa tjänster via
**kwargs.
Grundläggande kodfärdighet
Skapa en InlineSkill instans med ett SkillFrontmatter (som innehåller namn och beskrivning) och instruktionsinnehåll. Du kan också koppla InlineSkillResource instanser med statiskt innehåll:
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)
Dynamiska resurser
Använd dekoratören @skill.resource för att registrera en funktion som en resurs. Funktionen anropas varje gång agenten läser resursen, så att den kan returnera up-to-date-data. Funktioner för både synkronisering och asynkronisering stöds:
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)"
När dekoratören används utan argument (@skill.resource) blir funktionsnamnet resursnamnet och dokumentsträngen blir beskrivningen. Använd @skill.resource(name="...", description="...") för att ange dem explicit.
Koddefinierade skript
Använd dekoratören @skill.script för att registrera en funktion som ett körbart skript på en färdighet. Koddefinierade skript körs i processen och kräver ingen skriptkörare. Funktioner för både synkronisering och asynkronisering stöds:
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})
När dekoratören används utan argument (@skill.script) blir funktionsnamnet skriptnamnet och docstring blir beskrivningen. Funktionens inskrivna parametrar konverteras automatiskt till ett JSON-schema som agenten använder för att skicka argument.
Förutom filbaserade kunskaper som identifieras från SKILL.md filer kan du definiera färdigheter helt i Go-kod:
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 läser bara in kunskapsinstruktionerna när agenten anropar load_skill. Skript får positionsbaserade strängargument i CLI-stil, till exempel ["26.2", "1.60934"], och kan tolka dessa argument på vilket sätt skriptet än behöver.
Tips/Råd
Se kunskapsexemplen för fullständiga körbara exempel.
Klassbaserade kunskaper
Med klassbaserade kunskaper kan du paketera alla kunskapskomponenter – namn, beskrivning, instruktioner, resurser och skript – i en enda C#-klass. Detta gör dem enkla att paketera och distribuera som NuGet-paket – team kan skapa och skicka färdigheter oberoende av varandra, och konsumenterna lägger till dem med dotnet add package och ett enda .UseSkill() anrop. Härled från AgentClassSkill<T> (var T är din klass) och kommentera sedan egenskaper med [AgentSkillResource] och metoder med [AgentSkillScript] för automatisk identifiering:
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 });
}
}
Registrera den klassbaserade färdigheten med AgentSkillsProvider:
var skill = new UnitConverterSkill();
var skillsProvider = new AgentSkillsProvider(skill);
[AgentSkillResource] När attributet tillämpas på en egenskap eller metod används dess returvärde som resursinnehåll när agenten läser resursen – använd en metod när innehållet behöver beräknas vid lästid. När [AgentSkillScript] tillämpas på en metod anropas metoden när agenten anropar skriptet. Använd [Description] från System.ComponentModel för att beskriva varje resurs och skript för agenten.
Anmärkning
AgentClassSkill<T> stöder också att åsidosätta Resources och Scripts som samlingar för scenarier där attributbaserad upptäckt inte är lämplig.
Klassbaserade kunskaper
Med klassbaserade kunskaper kan du paketera alla kunskapskomponenter – namn, beskrivning, instruktioner, resurser och skript – i en enda Python-klass. Detta gör dem enkla att paketera och distribuera som PyPI-paket – team kan skapa och skicka färdigheter oberoende av varandra, och konsumenterna lägger till dem med pip install och ett enda SkillsProvider() anrop. Underklassen ClassSkillanvänder sedan dekoratörerna @ClassSkill.resource och @ClassSkill.script för automatisk identifiering:
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})
Registrera den klassbaserade färdigheten med SkillsProvider:
from agent_framework import SkillsProvider
skill = UnitConverterSkill()
skills_provider = SkillsProvider(skill)
När @ClassSkill.resource används som en bar dekoratör (inga argument) blir metodnamnet resursnamnet (med understreck konverterade till bindestreck) och dokumentsträngen blir beskrivningen. Använd @ClassSkill.resource(name="...", description="...") för att ange dem explicit. Samma mönster gäller för @ClassSkill.script.
Resurser kan definieras som antingen vanliga metoder eller @property beskrivningar. När du använder @propertyplacerar du @property först och @ClassSkill.resource tvåa. Resursreturvärden cachelagras efter första åtkomsten.
Anmärkning
ClassSkill stöder också att man uttryckligen åsidosätter egenskaperna resources och scripts för att returnera InlineSkillResource- och InlineSkillScript-instanser direkt, för scenarier där dekoratorbaserad upptäckt inte passar.
MCP-baserade färdigheter
Anmärkning
MCP-baserade kunskaper kräver Microsoft.Agents.AI.Mcp NuGet-paketet. MCP-kompetens-API:et är experimentellt och kan ändras i framtida versioner.
Kunskaper kan identifieras från MCP-servrar (Model Context Protocol) som exponerar kunskapsresurser under skill:// URI-schemat. MCP-servern annonserar färdigheter via ett skill://index.json identifieringsdokument och ramverket hämtar kunskapsinnehåll på begäran.
MCP-baserade kunskaper stöder två indexinmatningstyper:
-
skill-md– SkillensSKILL.mdoch syskonresurser hämtas vid behov från MCP-servern. -
archive- Kunskapen distribueras som ett enda paketerat arkiv (ZIP, TAR eller gzip-komprimerad TAR) som laddas ned och packas upp lokalt.
Grundläggande användning
UseMcpSkills Använd tilläggsmetoden på AgentSkillsProviderBuilder för att lägga till en MCP-kompetenskälla:
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);
Kunskaper av arkivtyp
För färdigheter av typen arkiv använder du AgentMcpSkillsSourceOptions (från paketet Microsoft.Agents.AI.Mcp) för att konfigurera extraheringsbeteendet:
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 exponerar följande egenskaper för att styra arkivextrahering:
-
ArchiveSkillsDirectory– Baskatalog för extraherade arkiv. Är som standard en unik underkatalog under den aktuella arbetskatalogen, som genereras för varje källinstans för att förhindra kollisioner mellan flera källor. -
ArchiveResourceExtensions– Tillåtna tillägg för resurser i extraherade arkiv. Standardvärdet är.md,.json,.yaml,.yml,.csv,.xml, ..txt -
ArchiveResourceSearchDepth– Hur djupt du söker efter resurser i varje extraherad kompetenskatalog. Standardinställningen är2. -
ArchiveMaxFileCount- Maximalt antal filer per arkiv. Arkiv som överskrider denna gräns ignoreras. Standardinställningen är20. -
ArchiveMaxSizeBytes– Maximal nedladdningsstorlek per arkiv. Standardinställningen är1 MB. -
ArchiveMaxUncompressedSizeBytes- Maximal total okomprimerad storlek per arkiv. Standardinställningen är1 MB.
Viktigt!
Skript som paketerats i arkivtypskunskaper körs aldrig. Detta är en avsiktlig säkerhetsåtgärd – körbart innehåll från fjärranslutna MCP-servrar kräver uttryckligt förtroende.
MCP-baserade färdigheter
Anmärkning
MCP-baserade kunskaper är experimentella och kan ändras i framtida versioner. Att använda MCPSkillsSource genererar en FutureWarning bakom funktionsflaggan MCP_SKILLS.
Kunskaper kan identifieras från MCP-servrar (Model Context Protocol) som exponerar kunskapsresurser under skill:// URI-schemat. MCP-servern annonserar färdigheter via ett skill://index.json identifieringsdokument och ramverket hämtar varje färdighets SKILL.md brödtext på begäran via resources/read.
Omslut en MCP ClientSession i MCPSkillsSource och skicka den till 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("...")
Anmärkning
Python-MCPSkillsSourceen stöder endast skill-md indexposter (indexposter av andra typer hoppas tyst över). Till skillnad från den .NET implementeringen stöder den inte arkivtypskunskaper. Om skill://index.json är frånvarande, oläsbar, tom eller inte kan parsas returnerar källan en tom lista.
Viktigt!
En extern MCP-server styr vilket kunskapsinnehåll – inklusive instruktioner och skript som agenten kan köra – når agenten. Anslut MCPSkillsSource endast till servrar som du har kontrollerat och litar på och behandla deras svar som ej betrodda indata.
Kunskapskällor
En AgentSkillsProvider hämtar kunskaper från en eller flera källor – objekt som implementerar AgentSkillsSource. Källor delas in i två kategorier: slutkällor som upptäcker eller innehåller färdigheter (till exempel AgentFileSkillsSource för filbaserade färdigheter), och dekoratörer som transformerar utdata från en annan källa (aggregering, deduplicering, cachelagring och filtrering). Du kan också skapa en anpassad källa.
Varje källa implementerar en enda metod – GetSkillsAsync(AgentSkillsSourceContext context, CancellationToken cancellationToken = default). Innehåller AgentSkillsSourceContext information om den aktuella begäran:
-
Agent– den instans somAIAgentbegär kunskaper. -
Session– denAgentSessionsom är associerad med anropet, ellernullnär det inte finns någon session.
Den här kontexten är tillgänglig i hela källpipelinen, så ett FilteringAgentSkillsSource predikat eller en anpassad källa kan basera sin logik på den, till exempel returnera en annan uppsättning kunskaper beroende på den begärande agenten.
Lövkällor
AgentFileSkillsSource
Upptäcker kunskaper från SKILL.md-filer på disk. Accepterar en eller flera katalogsökvägar, en valfri skriptlöpare och valfritt AgentFileSkillsSourceOptions (dokumenterat i Filbaserade kunskaper).
var source = new AgentFileSkillsSource(
[Path.Combine(AppContext.BaseDirectory, "skills")],
scriptRunner: SubprocessScriptRunner.RunAsync,
options: new AgentFileSkillsSourceOptions { SearchDepth = 3 });
AgentInMemorySkillsSource
Omsluter AgentSkill instanser (koddefinierade eller klassbaserade) i minnet.
var source = new AgentInMemorySkillsSource([volumeConverterSkill, temperatureConverter]);
Kombinatorer
AggregatingAgentSkillsSource
Kombinerar flera källor till en. Färdigheter returneras i registreringsordning utan att deduplicering eller filtrering tillämpas.
var aggregated = new AggregatingAgentSkillsSource([fileSource, inMemorySource]);
Decorators
Dekoratörer omsluter en inre källa och transformerar dess utdata. De kan kedjas ihop för att skapa en pipeline.
DeduplicatingAgentSkillsSource
Tar bort dubbletter av kunskapsnamn (skiftlägesokänsligt, första förekomst vinner). Dubletter loggas på varningsnivå.
var deduplicated = new DeduplicatingAgentSkillsSource(innerSource);
CachingAgentSkillsSource
Cachelagrar kunskapslistan som returneras av den inre källan. Samtidiga anropare serialiseras per cachenyckel, så endast en hämtning körs i taget. Accepterar valfritt CachingAgentSkillsSourceOptions:
-
RefreshInterval(TimeSpan?) – Cachelagrade resultat upphör att gälla efter det här intervallet och den inre källan anropas igen. Närnull(standardvärdet) upphör cachelagrade resultat aldrig att gälla. -
CacheIsolationKeySelector(Func<AgentSkillsSourceContext, string?>?) – returnerar en cachenyckel för att isolera cachelagrade resultat efter kontext (till exempel per klient). Närnulldelar alla anropare en enda cache-bucket.
var cached = new CachingAgentSkillsSource(innerSource, new CachingAgentSkillsSourceOptions
{
RefreshInterval = TimeSpan.FromMinutes(5)
});
FilteringAgentSkillsSource
Tillämpar ett predikat för att inkludera eller exkludera färdigheter. Predikatet tar emot färdigheten och en AgentSkillsSourceContext.
var filtered = new FilteringAgentSkillsSource(
innerSource,
(skill, context) => skill.Frontmatter.Name != "experimental-skill");
Anpassade källor
När de inbyggda källorna inte täcker ditt scenario implementerar du ditt eget. Underklass AgentSkillsSource för en lövkälla (en som genererar kunskaper från ett nytt ursprung, till exempel en databas eller fjärrtjänst) eller underklass DelegatingAgentSkillsSource för en dekoratör som transformerar en annan källas utdata.
Lövkälla
Härled från AgentSkillsSource och implementera GetSkillsAsync. Med AgentSkillsSourceContext argumentet kan källan anpassa resultatet till den aktuella begäran, till exempel genom att returnera en annan uppsättning kunskaper beroende på den begärande agenten. Åsidosätt Dispose(bool) om källan äger resurser som en klient eller anslutning.
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);
}
}
Anpassad dekoratör
Härled från DelegatingAgentSkillsSource, anropa InnerSource.GetSkillsAsyncoch transformera eller observera resultatet. Det här är samma mönster som de inbyggda cachelagrings-, deduplicerings- och filtreringsdekoratörerna använder. Till exempel en dekoratör som registrerar hur många färdigheter som returnerades per begäran utan att ändra resultatet:
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;
}
}
Båda de anpassade källorna kan skickas direkt till AgentSkillsProvider eller kapslas in i en större pipeline, precis som de inbyggda källorna.
Leverantörskonstruktion
AgentSkillsProvider är den komponent som exponerar kunskaper för en agent. Den omsluter en eller flera källor och registrerar verktygen load_skill, read_skill_resourceoch run_skill_script . Det finns tre sätt att skapa ett:
-
AgentSkillsProviderBuilder– består av flera kunskapstyper i en provider med automatisk aggregering, deduplicering, cachelagring och valfri filtrering. Bäst för scenarier som kombinerar filbaserade, koddefinierade, klassbaserade och MCP-baserade kunskaper. -
Direkt källsammansättning – konstruera källpipelinen själv med hjälp av de offentliga
AgentSkillsSourceklasserna. Ingen automatisk cachelagring eller deduplicering tillämpas – du styr hela pipelinen. Bäst när du behöver kontroll över ordning, villkorsstyrd logik eller anpassat dekoratörsbeteende. - Bekvämlighetskonstruktorer – skapa en provider direkt från en filsökväg eller kunskapsinstanser. Tillämpar automatiskt deduplicering och cachelagring. Bäst för scenarier med en enda källa.
Använda AgentSkillsProviderBuilder
Använd AgentSkillsProviderBuilder när du behöver något av följande:
-
Blandade kunskapstyper – kombinera filbaserade, koddefinierade (
AgentInlineSkill), klassbaserade (AgentClassSkill) och MCP-baserade färdigheter i en enda provider. - Kunskapsfiltrering – inkludera eller exkludera färdigheter med hjälp av ett predikat.
Blandade kunskapstyper
Kombinera flera färdighetstyper i en leverantör genom att kedja UseFileSkill, UseSkill, UseMcpSkills och 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();
Färdighetsfiltrering
Använd UseFilter för att endast inkludera de färdigheter som uppfyller dina kriterier – till exempel för att läsa in färdigheter från en delad katalog men exkludera experimentella:
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();
Skapa källor direkt
När byggaren inte erbjuder den kontroll du behöver skapar du källklasser själv och skickar den resulterande pipelinen till AgentSkillsProvider. Se Kunskapskällor för den fullständiga listan över tillgängliga källor och deras alternativ.
I följande exempel skapar du en jämförbar pipeline med flera källor, men du får uttrycklig kontroll över varje dekoratör:
// 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);
Anmärkning
När ownsSource är true, kasseras även hela källpipelinen när providern kasseras. Ange det till false om du hanterar källlivscykeln själv.
Bekvämlighetskonstruktorer
För scenarier med en enda källa använder du konstruktorerna AgentSkillsProvider direkt. Dessa tillämpar automatiskt deduplicering och cachelagring utan att en byggare eller manuell källsammansättning krävs.
Från en filsökväg:
var skillsProvider = new AgentSkillsProvider(
Path.Combine(AppContext.BaseDirectory, "skills"),
scriptRunner: SubprocessScriptRunner.RunAsync);
Från kunskapsinstanser:
var skillsProvider = new AgentSkillsProvider(volumeConverterSkill, temperatureConverter);
Kunskapskällor
En SkillsProvider hämtar kunskaper från en eller flera källor – objekt som härleds från SkillsSource. Källor delas in i två kategorier: slutkällor som upptäcker eller innehåller färdigheter (till exempel FileSkillsSource för filbaserade färdigheter), och dekoratörer som transformerar utdata från en annan källa (aggregering, deduplicering, cachelagring och filtrering). Du kan också skapa en anpassad källa.
Varje källa implementerar en enda metod – async def get_skills(self, context: SkillsSourceContext) -> list[Skill]. Innehåller SkillsSourceContext information om den aktuella begäran:
-
agent- agenten (SupportsAgentRun) begär kompetens. -
session– denAgentSessionsom är associerad med anropet, ellerNonenär det inte finns någon session.
Den här kontexten flödar genom hela källpipelinen, så att ett FilteringSkillsSource predikat eller en anpassad källa kan basera sin logik på den, till exempel returnera en annan uppsättning kunskaper beroende på den begärande agenten.
Lövkällor
-
FileSkillsSource– identifierar kunskaper frånSKILL.mdfiler på disk. Accepterar en eller flera katalogsökvägar, en valfriscript_runneroch upptäcktsalternativ (resource_extensions,script_extensions,search_depth,resource_filter,script_filter) som dokumenteras i Filbaserade kunskaper. -
InMemorySkillsSource– omsluterSkillinstanser (koddefinierade eller klassbaserade) i minnet. -
MCPSkillsSource– identifierar färdigheter från en MCP-server (se MCP-baserade färdigheter).
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])
Kombinator
AggregatingSkillsSource kombinerar flera källor till en. Färdigheter returneras i registreringsordning utan att deduplicering eller filtrering tillämpas.
from agent_framework import AggregatingSkillsSource
aggregated = AggregatingSkillsSource([file_source, in_memory_source])
Decorators
Dekoratörer omsluter en inre källa och transformerar dess utdata. De kan kedjas ihop för att skapa en pipeline.
-
DeduplicatingSkillsSource- tar bort dubbletter av kunskapsnamn (skiftlägesokänsligt, första förekomst vinner). Dubletter loggas på varningsnivå. -
CachingSkillsSource– cachelagrar kunskapslistan som returneras av den inre källan. Samtidiga anropare för samma cachenyckel delar en enda hämtning under flygning, så den inre källan efterfrågas högst en gång per nyckel. Accepterar två valfria nyckelordsargument:-
refresh_interval(timedelta | None) – när den anges behandlas en cachelagrad lista som inaktuell när den är äldre än intervallet, så nästa anrop frågar den inre källan igen. NärNone(standardvärdet) upphör cachelagrade resultat aldrig att gälla. Användbart för inre källor vars kunskaper ändras under processlivslängden, till exempelMCPSkillsSource. -
cache_isolation_key_selector(Callable[[SkillsSourceContext], str | None]) – härleder en cachenyckel från kontexten för att isolera cachelagrade resultat (till exempel per agent eller klientorganisation). Nycklar bör ha låg kardinalitet och vara stabila. När du returnerarNone(eller lämnar denNone) används en enda delad cache-bucket.
-
-
FilteringSkillsSource- tillämpar ett predikat för att inkludera eller exkludera färdigheter. Predikatet tar emot färdigheten och enSkillsSourceContext: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",
)
Anpassade källor
När de inbyggda källorna inte täcker ditt scenario implementerar du ditt eget. Underklass SkillsSource för en lövkälla (en som genererar kunskaper från ett nytt ursprung, till exempel en databas eller fjärrtjänst) eller underklass DelegatingSkillsSource för en dekoratör som transformerar en annan källas utdata.
Lövkälla
Härled från SkillsSource och implementera get_skills. Med SkillsSourceContext argumentet kan källan anpassa resultatet till den aktuella begäran, till exempel genom att returnera en annan uppsättning kunskaper beroende på den begärande agenten:
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)
Anpassad dekoratör
Härled från DelegatingSkillsSource, anropa self.inner_source.get_skills(context)och transformera eller observera resultatet. Det här är samma mönster som de inbyggda cachelagrings-, deduplicerings- och filtreringsdekoratörerna använder. Till exempel en dekoratör som loggar hur många färdigheter som returnerades per begäran utan att ändra resultatet:
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
Båda de anpassade källorna kan skickas direkt till SkillsProvider eller kapslas in i en större pipeline, precis som de inbyggda källorna.
Leverantörskonstruktion
SkillsProvider är den komponent som exponerar kunskaper för en agent. Den omsluter en eller flera källor och registrerar verktygen load_skill, read_skill_resourceoch run_skill_script . Det finns tre sätt att skapa ett:
-
Från färdighetsinstanser – skicka med en enda
Skilleller en sekvens av färdigheter till konstruktorn. Bäst för koddefinierade och klassbaserade kunskaper. Tillämpar automatiskt deduplicering och cachelagring. -
Från filsökvägar - använd
SkillsProvider.from_paths()fabriksmetoden. Bäst för filbaserade kunskaper med en enda källa. Tillämpar automatiskt deduplicering och cachelagring. -
Direkt källsammansättning – konstruera källpipelinen själv med hjälp av de offentliga
SkillsSourceklasserna och skicka den till konstruktorn. Du styr hela pipelinen. Bäst när du behöver kontroll över ordning, villkorsstyrd logik, cachelagringsnycklar eller anpassat dekoratörsbeteende.
Från kunskapsinstanser
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])
Från filsökvägar
from pathlib import Path
from agent_framework import SkillsProvider
skills_provider = SkillsProvider.from_paths(
skill_paths=Path(__file__).parent / "skills",
script_runner=my_runner,
)
Skapa källor direkt
När du behöver fullständig kontroll skapar du källklasser själv och skickar den resulterande pipelinen till SkillsProvider. Se Kunskapskällor för den fullständiga listan över tillgängliga källor och deras alternativ.
Exemplet nedan skapar en pipeline med flera källor med explicit kontroll över varje dekoratör. I exemplet används platshållarobjekt:
-
volume_converter_skill- valfriInlineSkillinstans, byggd enligt Koddefinierade kunskaper. -
temperature_converter_skill– valfriClassSkill-instans, byggd enligt beskrivningen i Klassbaserade färdigheter. -
my_runner– enSkillScriptRunneranropsbar, definierad enligt beskrivningen i Skriptkörning.
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)
Viktigt!
Ett SkillsSource som tillhandahålls av anroparen används som det är: det dedupliceras inte automatiskt och omges inte av ett CachingSkillsSource. Att automatiskt cachelagra en kontextmedveten källa i en enda delad bucket kan leda till att en agents eller tenants färdigheter återanvänds för en annan. Skriv DeduplicatingSkillsSource och CachingSkillsSource (valfritt med en cache_isolation_key_selector) själv när du behöver dem. Automatisk deduplicering och cachelagring gäller endast när du skickar kunskaper eller filsökvägar direkt (alternativ 1 och 2 ovan).
Blandade kunskapstyper
Kombinera filbaserade, koddefinierade och klassbaserade kunskaper i en provider med hjälp av 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]),
])
)
)
Färdighetsfiltrering
Använd FilteringSkillsSource för att styra vilka kunskaper agenten ser. Predikatet tar emot varje Skill och SkillsSourceContext, och returnerar True för att ta med färdigheten. Om du till exempel vill ladda in färdigheter från en delad katalog men dölja en experimentell sådan:
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",
)
)
)
Beteende för cachelagring
Som standard omsluter byggverktyget källpipelinen med en CachingAgentSkillsSource som cachelagrar listan över färdigheter som returneras av de underliggande källorna. När färdigheterna har fastställts vid den första begäran återanvänder efterföljande begäranden den cachelagrade listan utan att göra en ny förfrågan till källorna. Om du vill inaktivera cachelagring (till exempel under utveckling när kunskapsdefinitioner ändras ofta) använder du DisableCaching() på byggaren:
var skillsProvider = new AgentSkillsProviderBuilder()
.UseFileSkill(Path.Combine(AppContext.BaseDirectory, "skills"))
.UseFileScriptRunner(SubprocessScriptRunner.RunAsync)
.DisableCaching()
.Build();
Anmärkning
Det är användbart att inaktivera cachelagring under utvecklingen när kunskapsinnehållet ändras ofta. I produktion lämnar du cachelagring aktiverat (standard) för bättre prestanda.
Beteende för cachelagring
Som standardinställning cachelagras verktyg och instruktioner efter den första byggningen. Ange disable_caching=True för att framtvinga en ombyggnad för varje anrop:
skills_provider = SkillsProvider.from_paths(
skill_paths=Path(__file__).parent / "skills",
disable_caching=True,
)
disable_caching finns också tillgänglig på SkillsProvider konstruktorn för koddefinierade och klassbaserade färdigheter.
Om du vill behålla cachelagring aktiverad men upptäcka kompetenser på nytt med jämna mellanrum (till exempel när en filbaserad källa eller MCP-källa ändras under processens livslängd) anger du cache_refresh_interval. Den inbyggda cachen behandlas som inaktuell när den är äldre än intervallet, så nästa körning frågar källan igen:
from datetime import timedelta
skills_provider = SkillsProvider.from_paths(
skill_paths=Path(__file__).parent / "skills",
cache_refresh_interval=timedelta(minutes=5),
)
cache_refresh_interval påverkar endast den cache som leverantören bygger upp internt (från skills eller filsökvägar); det ignoreras när disable_caching=True och har ingen effekt på SkillsSource som tillhandahålls av anroparen (skapa din egen CachingSkillsSource med en refresh_interval för detta).
Anmärkning
Det är användbart att inaktivera cachelagring under utvecklingen när kunskapsinnehållet ändras ofta. I produktion lämnar du cachelagring aktiverat (standard) för bättre prestanda.
Godkännande av verktyg
Alla verktyg som exponeras av AgentSkillsProvider (load_skill, read_skill_resource, run_skill_script) kräver godkännande som standard. När ett verktygsanrop kräver godkännande pausar agenten och returnerar en ToolApprovalRequestContent i stället för att köra det direkt. Använd UseToolApproval mellanprogram med regler för automatiskt godkännande för att selektivt kringgå frågor om betrodda åtgärder:
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();
Så här godkänner du alla kunskapsverktyg automatiskt, inklusive skriptkörning:
.UseToolApproval(new ToolApprovalAgentOptions
{
AutoApprovalRules = [AgentSkillsProvider.AllToolsAutoApprovalRule],
})
Inaktivera godkännande för specifika verktyg
Använd AgentSkillsProviderOptions för att inaktivera godkännande för enskilda verktyg och ta bort dem helt från godkännandeflödet:
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
});
När vissa verktyg kräver godkännande och andra inte har samma svar kan modellen anropa båda typerna samtidigt. Ange EnableNonApprovalRequiredFunctionBypassing så att godkännandefria verktyg körs omedelbart medan användaren endast uppmanas att ange de återstående verktygen:
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();
Hantera begäranden om godkännande
När verktygen kräver godkännande (och ingen regel för automatiskt godkännande matchar) returnerar ToolApprovalRequestContent agenten objekt som måste godkännas eller avvisas innan du fortsätter:
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();
}
Information om skriptfel
Som standard, när körningen av ett kompetensskript misslyckas, vidarebefordras undantaget till den underliggande FunctionInvokingChatClient. Om dess IncludeDetailedErrors egenskap är inställd truepå vidarebefordras undantagsmeddelandet till modellen, vilket gör att den kan korrigeras själv genom att försöka igen med olika argument:
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());
Om du inte kan konfigurera FunctionInvokingChatClient direkt anger du AgentSkillsProviderOptions.IncludeDetailedErrors i stället. Detta fångar undantaget på kompetensprovidernivå och returnerar felmeddelandet direkt till modellen:
var skillsProvider = new AgentSkillsProvider(
Path.Combine(AppContext.BaseDirectory, "skills"),
SubprocessScriptRunner.RunAsync,
options: new AgentSkillsProviderOptions
{
IncludeDetailedErrors = true,
});
Varning
Båda metoderna kan avslöja rå information om undantag för modellen. Undantagsmeddelanden kan innehålla känslig information, till exempel anslutningssträngar, filsökvägar eller interna tjänstnamn. Om kunskaper eller skript kommer från källor som inte är betrodda kan dessutom ett skadligt utformat skript utlösa ett undantag vars meddelande bäddar in en nyttolast för promptinmatning.
Alla verktyg som exponeras av SkillsProvider (load_skill, read_skill_resourceoch run_skill_script) kräver godkännande som standard. När ett verktygsanrop kräver godkännande pausar agenten och returnerar förfrågningar om godkännande via result.user_input_requests i stället för att utföra det direkt. Du godkänner eller avvisar varje begäran med request.to_function_approval_response(approved=...) och skickar tillbaka svaren:
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)
När ett verktygsanrop avvisas (approved=False) informeras agenten om att användaren har avböjt och kan svara därefter.
Automatisk godkännande av betrodda verktyg
I stället för att fråga efter varje anrop installerar du ToolApprovalMiddleware med någon av de statiska regler för automatiskt godkännande som exponeras av SkillsProvider. På så sätt kan skrivskyddade verktyg köras automatiskt medan du fortfarande uppmanar till skriptkörning:
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],
)
Två regler är tillgängliga:
-
SkillsProvider.read_only_tools_auto_approval_rule– godkänner endast verktyg med endast läsåtkomst (load_skill,read_skill_resource) men begär fortfarande bekräftelse förrun_skill_script. -
SkillsProvider.all_tools_auto_approval_rule- godkänner varje kunskapsverktyg, inklusiverun_skill_script(ingen manuell godkännandeloop behövs).
Båda reglerna avvisar alla anrop med ett server_label, så att de förblir begränsade till den här providerns lokala verktyg och godkänner aldrig automatiskt ett värdbaserat verktyg med samma namn. Reglerna gäller endast för verktyg som fortfarande kräver godkännande – verktyg som valts bort via argumenten disable_*_approval nedan körs utan godkännande oavsett.
Inaktivera godkännande för specifika verktyg
För betrodda färdigheter skickar du disable_load_skill_approval, disable_read_skill_resource_approval och/eller disable_run_skill_script_approval för att helt undanta enskilda verktyg från godkännandeflödet (de registreras med 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
)
Dessa argument är också tillgängliga för SkillsProvider.from_paths().
Varning
Inaktivera endast godkännande eller automatisk godkännande av skriptkörning för kunskaper och skript från källor som du litar på. Kunskapsinstruktioner matas in i agentens kontext och run_skill_script kör kod som tillhandahålls av källan.
Anpassad systemuppmaning
Som standard matar kompetensprovidern in en systemprompt som visar tillgängliga färdigheter och instruerar agenten att använda load_skill och read_skill_resource. Du kan anpassa den här uppmaningen:
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.
"""
});
Anmärkning
Den anpassade mallen måste innehålla {skills} som platshållare för den genererade kompetenslistan. Literala klammerparenteser måste vara undantagna som {{ och }}.
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}"
),
)
Anmärkning
Den anpassade mallen måste innehålla platshållaren {skills} för den genererade kompetenslistan. Den kan valfritt innehålla platshållarna {resource_instructions} (verktygstips för resursverktyg) och {runner_instructions} (verktygstips för skriptverktyg); när de förekommer fylls de med inbyggd vägledning, och när de utelämnas återges de helt enkelt inte (motsvarande verktyg är fortfarande registrerade). Literala klammerparenteser måste vara undantagna som {{ och }}.
Mata in tjänster och körningsargument
Resurser för färdigheter och skriptfunktioner kan ta emot extern applikationskontext som tillhandahålls under körning.
Kompetensresurs och skriptdelegater kan deklarera en IServiceProvider parameter som Agent Framework matar in automatiskt. På så sätt kan kunskaper lösa registrerade programtjänster på begäran.
Inställningar
Registrera dina programtjänster och skicka den skapade IServiceProvider till agenten via parametern 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);
Koddefinierade kunskaper med DI
Deklarera IServiceProvider som en parameter i AddResource- eller AddScript-delegerade – ramverket identifierar och injicerar den automatiskt när agenten läser en resurs eller kör ett 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);
});
Klassbaserade kunskaper med DI
Kommentera metoder med [AgentSkillResource] eller [AgentSkillScript] deklarera en IServiceProvider parameter – ramverket identifierar dessa medlemmar via reflektion och matar in tjänstleverantören automatiskt:
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);
}
}
Tips/Råd
Klassbaserade färdigheter kan också lösa beroenden via konstruktorn. Registrera kunskapsklassen ServiceCollection i och lös den från containern i stället för att anropa new direkt:
services.AddSingleton<WeightConverterSkill>();
var weightSkill = serviceProvider.GetRequiredService<WeightConverterSkill>();
Detta är användbart när själva kunskapsklassen behöver inmatade tjänster utöver vad resursen och skriptdelegaterna använder.
Resurs- och skriptfunktioner som accepterar **kwargs för att automatiskt ta emot runtime-nyckelordsargument som skickas till agent.run(). På så sätt kan kunskapsfunktioner komma åt programkontexten – till exempel konfiguration, användaridentitet eller tjänstklienter – utan att hårdkoda dem i kunskapsdefinitionen.
Skicka körningsargument
Skicka function_invocation_kwargs till agent.run() för att ange keyword-argument som ramverket vidarebefordrar till resurs- och skriptfunktioner.
response = await agent.run(
"How many kilometers is 26.2 miles?",
function_invocation_kwargs={"precision": 2, "user_id": "alice"},
)
Koddefinierade kunskaper med kwargs
När en resursfunktion deklarerar **kwargs, vidarebefordrar ramverket környckelordsargumenten varje gång agenten läser resursen.
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}"
Resursfunktioner utan **kwargs anropas utan argument och tar inte emot körningskontext.
När en skriptfunktion deklarerar **kwargs, vidarebefordrar ramverket nyckelorden för körarguments tillsammans med dem som agenten tillhandahåller:
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})
Agenten tillhandahåller value och factor via verktygsanropet args. Programmet tillhandahåller precision via function_invocation_kwargs. Skriptfunktioner utan **kwargs tar bara emot de argument som tillhandahålls av agenten.
Klassbaserade kunskaper med kwargs
Klassbaserade färdighetsmetoder kan också acceptera **kwargs för att ta emot körningsargument. Mönstret fungerar på samma sätt – deklarera **kwargs på resursmetoder eller skriptmetoder:
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})
Metodtips för säkerhet
Agentkunskaper bör behandlas som all kod från tredje part som du tar med dig till ditt projekt. Eftersom kunskapsinstruktioner matas in i agentens kontext – och färdigheter kan inkludera skript – är det viktigt att tillämpa samma granskningsnivå och styrningsnivå som du skulle ha på ett beroende med öppen källkod.
-
Granska före användning – Läs allt kunskapsinnehåll (
SKILL.md, skript och resurser) innan du distribuerar. Kontrollera att ett skripts faktiska beteende matchar dess angivna avsikt. Sök efter instruktioner som försöker kringgå säkerhetsriktlinjer, exfiltera data eller ändra agentkonfigurationsfiler. - Källförtroende – Installera endast kunskaper från betrodda författare eller granskade interna deltagare. Föredrar färdigheter med tydlig härkomst, versionskontroll och aktivt underhåll. Håll utkik efter typokvatterade kunskapsnamn som efterliknar populära paket.
- Sandbox-miljö – Kör färdigheter som innehåller körbara skript i isolerade miljöer. Begränsa åtkomsten till filsystem, nätverk och systemnivå till endast det som krävs för kunskapen. Kräv explicit användarbekräftelse innan du kör potentiellt känsliga åtgärder.
- Granskning och loggning – Registrera vilka kunskaper som läses in, vilka resurser som läses och vilka skript som körs. Detta ger dig en spårningslogg för att spåra agentbeteendet tillbaka till specifikt kunskapsinnehåll om något går fel.
När du ska använda kunskaper jämfört med arbetsflöden
Agentkunskaper och Agent Framework-arbetsflöden utökar båda vad agenter kan göra, men de fungerar på fundamentalt olika sätt. Välj den metod som bäst matchar dina krav:
- Kontroll – Med en färdighet bestämmer AI:n hur instruktionerna ska köras. Detta är idealiskt när du vill att agenten ska vara kreativ eller anpassningsbar. Med ett arbetsflöde definierar du uttryckligen exekveringsvägen. Använd arbetsflöden när du behöver deterministiskt, förutsägbart beteende.
- Resiliens - En färdighet körs under en enda agentomgång. Om något misslyckas måste hela åtgärden utföras på nytt. Arbetsflöden stöder kontrollpunkter, så att de kan återupptas från det senaste lyckade steget efter ett fel. Välj arbetsflöden när kostnaden för att köra hela processen på nytt är hög.
- Sidoeffekter – Funktioner är lämpliga när åtgärder är idempotenta eller innebär låg risk. Föredra arbetsflöden när steg ger biverkningar (skicka e-post, debitera betalningar) som inte bör upprepas vid återförsök.
- Komplexitet – Färdigheter är bäst för fokuserade uppgifter med en enda domän som en agent kan hantera. Arbetsflöden passar bättre för affärsprocesser i flera steg som samordnar flera agenter, mänskliga godkännanden eller externa systemintegreringar.
Tips/Råd
Som tumregel: Om du vill att AI:n ska ta reda på hur du utför en uppgift använder du en färdighet. Om du behöver garantera vilka steg som körs och i vilken ordning använder du ett arbetsflöde.