Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Umiejętności agenta to przenośne pakiety instrukcji, skryptów i zasobów, które zapewniają agentom wyspecjalizowane możliwości i wiedzę na temat domeny. Umiejętności są zgodne z otwartą specyfikacją i implementują stopniowy wzorzec ujawniania, aby agenty ładowały tylko ten kontekst, którego potrzebują, kiedy jest to potrzebne.
Użyj umiejętności agenta, jeśli chcesz:
- Specjalizacja domenowa w pakietach — Gromadź specjalistyczną wiedzę (zasady wydatków, przepływy pracy prawne, procesy analizy danych) w formie przenośnych pakietów wielokrotnego użytku.
- Rozszerzanie możliwości agenta — udostępniaj agentom nowe możliwości bez zmieniania podstawowych instrukcji.
- Zapewnianie spójności — przekształcanie zadań wieloetapowych w powtarzalne, poddawane inspekcji przepływy pracy.
- Włącz współdziałanie — użyj ponownie tych samych umiejętności w różnych produktach zgodnych z umiejętnościami agenta.
Struktura umiejętności
Umiejętność to katalog zawierający plik SKILL.md z opcjonalnymi podkatalogami na zasoby.
expense-report/
├── SKILL.md # Required — frontmatter + instructions
├── scripts/
│ └── validate.py # Executable code agents can run
├── references/
│ └── POLICY_FAQ.md # Reference documents loaded on demand
└── assets/
└── expense-report-template.md # Templates and static resources
format SKILL.md
Plik SKILL.md musi zawierać frontmatter YAML, po którym następuje zawartość języka Markdown:
---
name: expense-report
description: File and validate employee expense reports according to company policy. Use when asked about expense submissions, reimbursement rules, or spending limits.
license: Apache-2.0
compatibility: Requires python3
metadata:
author: contoso-finance
version: "2.1"
---
| (No changes needed) | Wymagane | Opis |
|---|---|---|
name |
Tak | Maksymalnie 64 znaki. Tylko małe litery, cyfry i łączniki. Nie może rozpoczynać ani kończyć się łącznikiem lub zawierać kolejne łączniki. Nazwa musi odpowiadać nazwie katalogu nadrzędnego. |
description |
Tak | Co robi umiejętność i kiedy należy jej używać. Maksymalna liczba znaków: 1024. Powinny zawierać słowa kluczowe, które ułatwiają agentom identyfikowanie odpowiednich zadań. |
license |
Nie. | Nazwa licencji lub odwołanie do dołączonego pliku licencji. |
compatibility |
Nie. | Maksymalnie 500 znaków. Wskazuje wymagania dotyczące środowiska (zamierzony produkt, pakiety systemowe, dostęp sieciowy itp.). |
metadata |
Nie. | Dowolne mapowanie wartości klucza dla dodatkowych metadanych. |
allowed-tools |
Nie. | Lista zatwierdzonych narzędzi oddzielona spacjami, których może używać ta funkcja. Eksperymentalna — obsługa może się różnić w zależności od implementacji agenta. |
Treść języka Markdown po frontmatterze zawiera instrukcje dotyczące umiejętności — wskazówki krok po kroku, przykłady danych wejściowych i wyjściowych, typowe przypadki brzegowe lub dowolną zawartość, która pomaga agentowi wykonać zadanie. Zachowaj SKILL.md poniżej 500 wierszy i przenieś szczegółowy materiał referencyjny do oddzielnych plików.
Stopniowe ujawnianie
Umiejętności agenta używają czteroetapowego wzorca stopniowego ujawniania, aby zminimalizować użycie kontekstu:
- Reklamuj (ok. 100 tokenów na umiejętność) — nazwy umiejętności i opisy są wstrzykiwane do komendy systemowej na początku każdego przebiegu, dzięki czemu agent wie, jakie umiejętności są dostępne.
-
Załaduj (< zalecane 5000 tokenów) — gdy zadanie pasuje do domeny umiejętności, agent wywołuje
load_skillnarzędzie, aby pobrać pełną treść SKILL.md ze szczegółowymi instrukcjami. -
Odczyt zasobów (zgodnie z potrzebami) — agent wywołuje
read_skill_resourcenarzędzie w celu pobrania dodatkowych plików (odwołań, szablonów, zasobów) tylko wtedy, gdy jest to wymagane. -
Uruchamianie skryptów (zgodnie z potrzebami) — agent wywołuje
run_skill_scriptnarzędzie do wykonywania skryptów powiązanych z umiejętnością.
Ten wzorzec utrzymuje przychylenie okna kontekstowego agenta, jednocześnie zapewniając mu dostęp do głębokiej wiedzy o domenie na żądanie.
Uwaga / Notatka
load_skill jest zawsze reklamowany.
read_skill_resource jest reklamowany tylko wtedy, gdy przynajmniej jedna umiejętność ma zasoby.
run_skill_script jest reklamowany tylko wtedy, gdy co najmniej jedna umiejętność zawiera skrypty.
Zapewnianie umiejętności agentowi
AgentSkillsProvider (C#) i SkillsProvider (Python) to dostawcy kontekstu, którzy udostępniają umiejętności agentom. Obsługują trzy źródła umiejętności:
-
Oparte na plikach — umiejętności wykryte na podstawie
SKILL.mdplików w katalogach systemu plików -
Określony przez kod — umiejętności zdefiniowane bezpośrednio w kodzie przy użyciu
AgentInlineSkill(C#) lubSkill(Python) -
Oparte na klasach — umiejętności hermetyzowane w klasie języka C# pochodzącej tylko z
AgentClassSkill<T>(tylko w języku C#)
Aby połączyć wiele źródeł w jednym dostawcy, użyj polecenia AgentSkillsProviderBuilder (tylko język C# — zobacz Builder: advanced multi-source scenarios (Konstruktor: zaawansowane scenariusze z wieloma źródłami).
Umiejętności oparte na plikach
Utwórz AgentSkillsProvider wskazujący na katalog zawierający twoje umiejętności i dodaj go do elementów dostarczających kontekst agenta. Przekaż moduł uruchamiający skrypt, aby umożliwić wykonywanie skryptów opartych na plikach znajdujących się w katalogach umiejętności:
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);
Ostrzeżenie
DefaultAzureCredential jest wygodne do programowania, ale wymaga starannego rozważenia w środowisku produkcyjnym. W środowisku produkcyjnym rozważ użycie określonego poświadczenia (np. ManagedIdentityCredential), aby uniknąć problemów z opóźnieniami, niezamierzonego sondowania poświadczeń i potencjalnych zagrożeń bezpieczeństwa wynikających z mechanizmów awaryjnych.
Wiele katalogów umiejętności
Możesz wskazać dostawcę do pojedynczego katalogu nadrzędnego — każdy podkatalog zawierający SKILL.md element jest automatycznie wykrywany jako umiejętność:
var skillsProvider = new AgentSkillsProvider(
Path.Combine(AppContext.BaseDirectory, "all-skills"));
Możesz też przekazać listę ścieżek do wyszukiwania wielu katalogów głównych:
var skillsProvider = new AgentSkillsProvider(
[
Path.Combine(AppContext.BaseDirectory, "company-skills"),
Path.Combine(AppContext.BaseDirectory, "team-skills"),
]);
Dostawca wyszukuje do dwóch poziomów głębokości.
Dostosowywanie odnajdywania zasobów
Domyślnie dostawca rozpoznaje zasoby z rozszerzeniami .md, .json, .yaml, .yml, .csv, .xml i .txt w podkatalogach references i assets. Użyj AgentFileSkillsSourceOptions, aby zmienić te wartości domyślne:
var fileOptions = new AgentFileSkillsSourceOptions
{
AllowedResourceExtensions = [".md", ".txt"],
ResourceDirectories = ["docs", "templates"],
};
var skillsProvider = new AgentSkillsProvider(
Path.Combine(AppContext.BaseDirectory, "skills"),
fileOptions: fileOptions);
Wykonywanie skryptu
Przekaż SubprocessScriptRunner.RunAsync jako drugi argument do AgentSkillsProvider, aby umożliwić wykonywanie skryptów plikowych.
var skillsProvider = new AgentSkillsProvider(
Path.Combine(AppContext.BaseDirectory, "skills"),
SubprocessScriptRunner.RunAsync);
SubprocessScriptRunner.RunAsync jest w przybliżeniu równoważne z następującymi elementami:
// Simplified equivalent of what SubprocessScriptRunner.RunAsync does internally
using System.Diagnostics;
using System.Text.Json;
static async Task<string> RunAsync(
AgentFileSkill skill,
AgentFileSkillScript script,
JsonElement? args,
IServiceProvider? serviceProvider)
{
var psi = new ProcessStartInfo("python3")
{
RedirectStandardOutput = true,
UseShellExecute = false,
};
psi.ArgumentList.Add(Path.Combine(skill.Path, script.Path));
if (args is { ValueKind: JsonValueKind.Array } json)
{
foreach (var element in json.EnumerateArray())
{
psi.ArgumentList.Add(element.GetString()!);
}
}
using var process = Process.Start(psi)!;
string output = await process.StandardOutput.ReadToEndAsync();
await process.WaitForExitAsync();
return output.Trim();
}
Uruchamia każdy odnaleziony skrypt jako lokalny podproces. Skrypty bazujące na plikach oczekują, że argumenty będą przekazane jako tablica JSON z ciągami tekstowymi — każdy element tej tablicy staje się pozycyjnym argumentem wiersza poleceń.
Ostrzeżenie
SubprocessScriptRunner jest dostarczany tylko do celów demonstracyjnych. W przypadku użycia w środowisku produkcyjnym rozważ dodanie:
- Sandboxing (na przykład kontenery lub izolowane środowiska uruchomieniowe)
- Limity zasobów (procesor, pamięć, limit czasu zegara)
- Walidacja danych wejściowych i lista dozwolonych skryptów wykonywalnych
- Rejestrowanie strukturalne i dzienniki inspekcji
Dostosowywanie odnajdywania skryptów
Domyślnie dostawca rozpoznaje skrypty z rozszerzeniami .py, .js, .sh, .ps1, .csi .csx w podkatalogu scripts . Użyj AgentFileSkillsSourceOptions, aby zmienić te wartości domyślne:
Przekaż AgentFileSkillsSourceOptions do konstruktora AgentSkillsProvider lub na UseFileSkill / UseFileSkills konstruktora:
var fileOptions = new AgentFileSkillsSourceOptions
{
AllowedScriptExtensions = [".py"],
ScriptDirectories = ["scripts", "tools"],
};
// Via constructor
var skillsProvider = new AgentSkillsProvider(
Path.Combine(AppContext.BaseDirectory, "skills"),
fileOptions: fileOptions);
// Via builder
var skillsProvider = new AgentSkillsProviderBuilder()
.UseFileSkill(Path.Combine(AppContext.BaseDirectory, "skills"), options: fileOptions)
.Build();
Umiejętności oparte na plikach
SkillsProvider Utwórz odnośnik do katalogu zawierającego Twoje umiejętności i dodaj go do kontekstów dostawców agenta.
import os
from pathlib import Path
from agent_framework import SkillsProvider
from agent_framework.openai import OpenAIChatCompletionClient
from azure.identity.aio import AzureCliCredential
# Discover skills from the 'skills' directory
skills_provider = SkillsProvider(
skill_paths=Path(__file__).parent / "skills"
)
# Create an agent with the skills provider
agent = OpenAIChatCompletionClient(
model=os.environ["AZURE_OPENAI_CHAT_COMPLETION_MODEL"],
azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
api_version=os.getenv("AZURE_OPENAI_API_VERSION"),
credential=AzureCliCredential(),
).as_agent(
name="SkillsAgent",
instructions="You are a helpful assistant.",
context_providers=[skills_provider],
)
Wiele katalogów umiejętności
Możesz wskazać dostawcę na jeden folder nadrzędny — każdy podfolder zawierający element SKILL.md jest automatycznie wykrywany jako umiejętność.
skills_provider = SkillsProvider(
skill_paths=Path(__file__).parent / "all-skills"
)
Możesz też przekazać listę ścieżek do wyszukiwania wielu katalogów głównych:
skills_provider = SkillsProvider(
skill_paths=[
Path(__file__).parent / "company-skills",
Path(__file__).parent / "team-skills",
]
)
Dostawca wyszukuje do dwóch poziomów głębokości.
Dostosowywanie odnajdywania zasobów
Domyślnie SkillsProvider rozpoznaje zasoby z rozszerzeniami .md, , .json.yaml, .yml, .csv, .xmli .txt. Skanuje wszystkie podkatalogi w każdym katalogu umiejętności. Przekaż resource_extensions , aby zmienić rozpoznane typy plików:
skills_provider = SkillsProvider(
skill_paths=Path(__file__).parent / "skills",
resource_extensions=(".md", ".txt"),
)
Wykonywanie skryptu
Aby włączyć wykonywanie skryptów opartych na plikach, przekaż element script_runner do SkillsProvider. Każde synchronowe lub asynchroniczne wywołanie, które przestrzega protokołu SkillScriptRunner, można zastosować:
from pathlib import Path
from agent_framework import Skill, SkillScript, SkillsProvider
def my_runner(skill: Skill, script: SkillScript, args: dict | None = None) -> str:
"""Run a file-based script as a subprocess."""
import subprocess, sys
cmd = [sys.executable, str(Path(skill.path) / script.path)]
if args:
for key, value in args.items():
if value is not None:
cmd.extend([f"--{key}", str(value)])
result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
return result.stdout.strip()
skills_provider = SkillsProvider(
skill_paths=Path(__file__).parent / "skills",
script_runner=my_runner,
)
Biegacz otrzymuje rozpoznany Skill, SkillScript, i opcjonalny args słownik. Skrypty oparte na plikach są automatycznie wykrywane z plików .py w katalogach umiejętności.
Ostrzeżenie
Powyższy biegacz jest dostarczany tylko do celów demonstracyjnych. W przypadku użycia w środowisku produkcyjnym rozważ dodanie:
- Sandboxing (na przykład kontenery,
seccomp, lubfirejail) - Limity zasobów (procesor, pamięć, limit czasu zegara)
- Walidacja danych wejściowych i lista dozwolonych skryptów wykonywalnych
- Rejestrowanie strukturalne i dzienniki inspekcji
Uwaga / Notatka
Jeśli dostępne są umiejętności oparte na plikach ze skryptami, ale nie jest ustawione script_runner, SkillsProvider zgłasza element ValueError.
Umiejętności zdefiniowane w kodzie
Oprócz umiejętności opartych na plikach odkrytych z plików SKILL.md, można definiować umiejętności w całości w kodzie za pomocą AgentInlineSkill. Umiejętności zdefiniowane w kodzie są przydatne, gdy:
- Zawartość umiejętności jest generowana dynamicznie (na przykład odczyt z bazy danych lub środowiska).
- Chcesz zachować definicje umiejętności obok kodu aplikacji, który z nich korzysta.
- Potrzebujesz zasobów, które wykonują logikę w czasie odczytu, zamiast obsługiwać pliki statyczne.
Podstawowa umiejętność kodowania
Utwórz element AgentInlineSkill z nazwą, opisem i instrukcjami. Dołączanie zasobów przy użyciu polecenia .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);
Zasoby dynamiczne
Pl-PL: Przekaż delegata fabryki do .AddResource(), aby obliczyć zawartość w czasie wykonywania. Delegat jest wywoływany za każdym razem, gdy agent odczytuje zasób:
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)");
Skrypty zdefiniowane za pomocą kodu
Służy .AddScript() do rejestrowania delegata jako skryptu wykonywalnego. Skrypty zdefiniowane w kodzie są uruchamiane wewnątrz procesu jako bezpośrednie wywołania delegatów. Nie jest wymagany moduł uruchamiający skrypty. Parametry wpisane przez delegata są automatycznie konwertowane na schemat JSON używany przez agenta do przekazywania argumentów:
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);
Uwaga / Notatka
Aby połączyć umiejętności zdefiniowane w kodzie z umiejętnościami opartymi na plikach lub opartymi na klasach w jednym dostawcy, użyj polecenia AgentSkillsProviderBuilder — zobacz Builder: advanced multi-source scenarios (Konstruktor: zaawansowane scenariusze obejmujące wiele źródeł).
Oprócz umiejętności zdefiniowanych na podstawie plików SKILL.md, można całkowicie definiować umiejętności w kodzie Python. Umiejętności zdefiniowane w kodzie są przydatne, gdy:
- Zawartość umiejętności jest generowana dynamicznie (na przykład odczyt z bazy danych lub środowiska).
- Chcesz zachować definicje umiejętności obok kodu aplikacji, który z nich korzysta.
- Potrzebujesz zasobów, które wykonują logikę w czasie odczytu, zamiast obsługiwać pliki statyczne.
Podstawowa umiejętność kodowania
Skill Utwórz wystąpienie z nazwą, opisem i zawartością instrukcji. Opcjonalnie dołącz wystąpienia SkillResource z zawartością statyczną.
from textwrap import dedent
from agent_framework import Skill, SkillResource, SkillsProvider
code_style_skill = Skill(
name="code-style",
description="Coding style guidelines and conventions for the team",
content=dedent("""\
Use this skill when answering questions about coding style,
conventions, or best practices for the team.
"""),
resources=[
SkillResource(
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(skills=[code_style_skill])
Zasoby dynamiczne
Użyj dekoratora @skill.resource , aby zarejestrować funkcję jako zasób. Funkcja jest wywoływana za każdym razem, gdy agent odczytuje zasób, dzięki czemu może zwrócić aktualne dane. Obsługiwane są zarówno funkcje synchronizacji, jak i asynchroniczne:
import os
from agent_framework import Skill
project_info_skill = Skill(
name="project-info",
description="Project status and configuration information",
content="Use this skill for questions about the current project.",
)
@project_info_skill.resource
def environment() -> Any:
"""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() -> Any:
"""Return the team roster."""
return "Alice Chen (Tech Lead), Bob Smith (Backend Engineer)"
Gdy dekorator jest używany bez argumentów (@skill.resource), nazwa funkcji staje się nazwą zasobu, a dokument staje się opisem. Użyj polecenia @skill.resource(name="...", description="...") , aby jawnie je ustawić.
Skrypty zdefiniowane za pomocą kodu
Użyj dekoratora @skill.script, aby zarejestrować funkcję jako skrypt wykonywalny w umiejętności. Skrypty zdefiniowane przez kod są uruchamiane w procesie i nie wymagają funkcji wykonawczej skryptu. Obsługiwane są zarówno funkcje synchronizacji, jak i asynchroniczne:
from agent_framework import Skill
unit_converter_skill = Skill(
name="unit-converter",
description="Convert between common units using a conversion factor",
content="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})
Gdy dekorator jest używany bez argumentów (@skill.script), nazwa funkcji staje się nazwą skryptu, a dokument staje się opisem. Parametry typizowane funkcji są automatycznie konwertowane na schemat JSON używany przez agenta do przekazywania argumentów.
Łączenie umiejętności opartych na plikach i zdefiniowanych w kodzie
Przekaż zarówno skill_paths i skills do jednego SkillsProvider. Najpierw odkrywane są umiejętności oparte na plikach; Jeśli umiejętność zdefiniowana przez kod ma taką samą nazwę jak istniejąca umiejętność oparta na plikach, umiejętności zdefiniowane przez kod są pomijane:
from pathlib import Path
from agent_framework import Skill, SkillsProvider
my_skill = Skill(
name="my-code-skill",
description="A code-defined skill",
content="Instructions for the skill.",
)
skills_provider = SkillsProvider(
skill_paths=Path(__file__).parent / "skills",
skills=[my_skill],
)
Umiejętności oparte na klasie
Umiejętności oparte na klasach umożliwiają łączenie wszystkich składników umiejętności — nazwy, opisu, instrukcji, zasobów i skryptów — w jedną klasę języka C#. Od dziedziczenia z AgentClassSkill<T> (gdzie T jest twoją klasą), następnie dodaj adnotacje do właściwości za pomocą [AgentSkillResource] i metod za pomocą [AgentSkillScript] dla automatycznego odnajdowania:
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 });
}
}
Zarejestruj umiejętności oparte na klasie za pomocą polecenia AgentSkillsProvider:
var skill = new UnitConverterSkill();
var skillsProvider = new AgentSkillsProvider(skill);
[AgentSkillResource] Gdy atrybut jest stosowany do właściwości lub metody, jego wartość zwracana jest używana jako zawartość zasobu, gdy agent odczytuje zasób — użyj metody, gdy zawartość musi być obliczana w czasie odczytu. Kiedy [AgentSkillScript] jest zastosowany do metody, metoda jest wywoływana, gdy agent uruchamia skrypt. Użyj polecenia [Description] , System.ComponentModel aby opisać każdy zasób i skrypt dla agenta.
Uwaga / Notatka
AgentClassSkill<T>Obsługuje również zastępowanie Resources i Scripts jako kolekcji w scenariuszach, w których odnajdywanie oparte na atrybutach nie pasuje.
Konstruktor: zaawansowane scenariusze obejmujące wiele źródeł
W prostych scenariuszach z jednym źródłem używaj bezpośrednio konstruktorów AgentSkillsProvider. Użyj AgentSkillsProviderBuilder, jeśli potrzebujesz dowolnego z następujących:
-
Typy umiejętności mieszanych — łączenie umiejętności opartych na plikach, zdefiniowanych kodowo (
AgentInlineSkill) i opartych na klasach (AgentClassSkill) w jednym dostawcy. - Filtrowanie umiejętności — dołączanie lub wykluczanie umiejętności przy użyciu predykatu.
Mieszane typy umiejętności
Połącz wszystkie trzy typy umiejętności w jednym dostawcy, łącząc UseFileSkill, UseSkill i UseFileScriptRunner.
var skillsProvider = new AgentSkillsProviderBuilder()
.UseFileSkill(Path.Combine(AppContext.BaseDirectory, "skills")) // file-based skills
.UseSkill(volumeConverterSkill) // AgentInlineSkill
.UseSkill(temperatureConverter) // AgentClassSkill
.UseFileScriptRunner(SubprocessScriptRunner.RunAsync) // runner for file scripts
.Build();
Filtrowanie umiejętności
Użyj UseFilter polecenia, aby uwzględnić tylko umiejętności spełniające kryteria — na przykład w celu załadowania umiejętności z udostępnionego katalogu, ale wykluczenia tych eksperymentalnych.
var approvedSkillNames = new HashSet<string> { "expense-report", "code-style" };
var skillsProvider = new AgentSkillsProviderBuilder()
.UseFileSkill(Path.Combine(AppContext.BaseDirectory, "skills"))
.UseFilter(skill => approvedSkillNames.Contains(skill.Frontmatter.Name))
.Build();
Zatwierdzanie skryptu
Użyj AgentSkillsProviderOptions.ScriptApproval, aby ograniczyć wykonywanie wszystkich skryptów do uzyskania zatwierdzenia przez człowieka. Po jego włączeniu agent wstrzymuje działanie i zwraca żądanie zatwierdzenia zamiast wykonywać go natychmiast.
var skillsProvider = new AgentSkillsProvider(
skillPath: Path.Combine(AppContext.BaseDirectory, "skills"),
options: new AgentSkillsProviderOptions
{
ScriptApproval = true,
});
Aby włączyć zatwierdzenie skryptu u dostawcy skonfigurowanego przez konstruktora, użyj polecenia UseScriptApproval:
var skillsProvider = new AgentSkillsProviderBuilder()
.UseFileSkill(Path.Combine(AppContext.BaseDirectory, "skills"))
.UseScriptApproval(true)
.Build();
Użyj require_script_approval=True na SkillsProvider do kontrolowania wykonania wszystkich skryptów wymagających zatwierdzenia przez człowieka. Zamiast natychmiastowego wykonywania agent wstrzymuje się i zwraca żądania zatwierdzenia.
from agent_framework import Agent, Skill, SkillsProvider
# Create provider with approval enabled
skills_provider = SkillsProvider(
skills=[my_skill],
require_script_approval=True,
)
# Run the agent — script calls pause for approval
result = await agent.run("Deploy version 2.5.0 to production", session=session)
# Handle approval requests
while result.user_input_requests:
for request in result.user_input_requests:
print(f"Script: {request.function_call.name}")
print(f"Args: {request.function_call.arguments}")
approval = request.to_function_approval_response(approved=True)
result = await agent.run(approval, session=session)
Gdy skrypt zostanie odrzucony (approved=False), agent zostanie poinformowany, że użytkownik odrzucił i może odpowiednio odpowiedzieć.
Niestandardowy monit systemowy
Domyślnie dostawca umiejętności wprowadza monit systemowy zawierający listę dostępnych umiejętności i instruuje agenta do użycia load_skill i read_skill_resource. Możesz dostosować ten monit:
var skillsProvider = new AgentSkillsProvider(
skillPath: Path.Combine(AppContext.BaseDirectory, "skills"),
options: new AgentSkillsProviderOptions
{
SkillsInstructionPrompt = """
You have skills available. Here they are:
{skills}
{resource_instructions}
{script_instructions}
"""
});
Uwaga / Notatka
Szablon niestandardowy musi zawierać placeholdery {skills} (lista umiejętności), {resource_instructions} (wskazówka narzędzia zasobów) i {script_instructions} (wskazówka narzędzia skryptu). Literalne nawiasy klamrowe muszą być zeskapowane jako {{ i }}.
skills_provider = SkillsProvider(
skill_paths=Path(__file__).parent / "skills",
instruction_template=(
"You have skills available. Here they are:\n{skills}\n"
"Use the `load_skill` function to get skill instructions.\n"
"Use the `read_skill_resource` function to read skill files."
),
)
Uwaga / Notatka
Szablon niestandardowy musi zawierać {skills} symbol zastępczy, w którym jest wstawiona lista umiejętności, oraz {runner_instructions} symbol zastępczy, w którym są wstawione instrukcje dotyczące skryptu.
Zachowanie buforowania
Domyślnie narzędzia i instrukcje umiejętności są buforowane po pierwszej kompilacji. Ustaw DisableCaching = true na AgentSkillsProviderOptions w celu wymuszenia ponownej kompilacji przy każdym uruchomieniu.
var skillsProvider = new AgentSkillsProvider(
Path.Combine(AppContext.BaseDirectory, "skills"),
options: new AgentSkillsProviderOptions
{
DisableCaching = true,
});
Uwaga / Notatka
Wyłączenie buforowania jest przydatne podczas rozwoju, gdy zawartość umiejętności zmienia się często. W środowisku produkcyjnym pozostaw włączone buforowanie (jest to ustawienie domyślne), aby uzyskać lepszą wydajność.
Wstrzykiwanie zależności
Zasób umiejętności i delegaty skryptu mogą zadeklarować parametr IServiceProvider, który jest automatycznie wstrzykiwany przez framework Agent Framework. Dzięki temu można rozwiązywać problemy z usługami aplikacji — takimi jak klienci bazy danych, konfiguracja lub logika biznesowa — bez konieczności kodowania ich w definicji umiejętności.
Konfiguracja
Zarejestruj usługi aplikacji i przekaż skompilowany IServiceProvider agentowi za pomocą 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);
Umiejętności zdefiniowane w kodzie z DI
Zadeklaruj IServiceProvider jako parametr w AddResource elemencie lub AddScript delegacie — platforma rozwiązuje i wstrzykuje to automatycznie, gdy agent odczytuje zasób lub uruchamia skrypt.
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);
});
Umiejętności oparte na klasach z di
Adnotuj metody za pomocą [AgentSkillResource] lub [AgentSkillScript] i zadeklaruj parametr IServiceProvider — framework odnajduje te elementy członkowskie za pomocą refleksji i automatycznie wprowadza dostawcę usług:
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);
}
}
Wskazówka
Umiejętności oparte na klasach mogą również rozwiązywać zależności za pomocą ich konstruktora. Zarejestruj klasę umiejętności w obiekcie ServiceCollection i rozwiąż ją z kontenera zamiast wywoływać new bezpośrednio:
services.AddSingleton<WeightConverterSkill>();
var weightSkill = serviceProvider.GetRequiredService<WeightConverterSkill>();
Jest to przydatne, gdy sama klasa umiejętności potrzebuje wstrzyknięcia usług ponad to, z czego korzystają delegaci zasobów i skryptów.
Funkcje zasobów i skryptów, które akceptują **kwargs, automatycznie odbierają argumenty słów kluczowych podczas uruchomienia przekazane do agent.run(). Dzięki temu funkcje umiejętności uzyskują dostęp do kontekstu aplikacji — takiego jak konfiguracja, tożsamość użytkownika lub klienci usługi — bez konieczności kodowania ich w definicji umiejętności.
Przekazywanie argumentów środowiska uruchomieniowego
Przekaż function_invocation_kwargs do agent.run(), aby przekazać argumenty kluczowe, które platforma dalej przesyła do funkcji zasobów oraz funkcji skryptów.
response = await agent.run(
"How many kilometers is 26.2 miles?",
function_invocation_kwargs={"precision": 2, "user_id": "alice"},
)
Funkcje zasobów z użyciem kwargs
Gdy funkcja zasobu deklaruje **kwargs, platforma przekazuje argumenty słowa kluczowego środowiska uruchomieniowego za każdym razem, gdy agent odczytuje zasób:
from typing import Any
from agent_framework import Skill
project_info_skill = Skill(
name="project-info",
description="Project status and configuration information",
content="Use this skill for questions about the current project.",
)
@project_info_skill.resource(name="environment", description="Current environment configuration")
def environment(**kwargs: Any) -> Any:
"""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}"
Funkcje zasobów bez **kwargs są wywoływane bez argumentów i nie odbierają kontekstu środowiska uruchomieniowego.
Funkcje skryptów za pomocą narzędzia kwargs
Gdy funkcja skryptu deklaruje **kwargs, platforma przekazuje argumenty słów kluczowych w trakcie działania programu wraz z tymi args, które są podane przez agenta.
import json
from typing import Any
from agent_framework import Skill
converter_skill = Skill(
name="unit-converter",
description="Convert between common units using a conversion factor",
content="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 udostępnia value i factor za pośrednictwem wywołania args narzędzia; aplikacja udostępnia precision za pośrednictwem function_invocation_kwargs metody. Funkcje skryptu bez **kwargs odbierają tylko argumenty dostarczone przez agenta.
Najlepsze rozwiązania dotyczące zabezpieczeń
Umiejętności agenta powinny być traktowane jak każdy kod zewnętrzny, który wprowadzasz do projektu. Ponieważ instrukcje dotyczące umiejętności są wstrzykiwane do kontekstu agenta — a umiejętności mogą obejmować skrypty — zastosowanie tego samego poziomu oceny i zarządzania, jakie stosujesz do zależności open source, jest niezbędne.
-
Przejrzyj przed użyciem — Przeczytaj całą zawartość umiejętności (
SKILL.md, skrypty i zasoby) przed wdrożeniem. Sprawdź, czy rzeczywiste zachowanie skryptu jest zgodne z jego deklarowaną intencją. Sprawdź instrukcje niepożądane, które próbują obejść wytyczne dotyczące bezpieczeństwa, eksfiltrować dane lub modyfikować pliki konfiguracji agenta. - Zaufanie do źródła — Instaluj tylko umiejętności od zaufanych autorów lub zweryfikowanych współautorów wewnętrznych. Preferuj umiejętności z wyraźnym pochodzeniem, kontrolą wersji i aktywną konserwacją. Zwróć uwagę na nazwy umiejętności podszywające się pod popularne pakiety.
- Sandboxing — uruchamianie umiejętności zawierających skrypty wykonywalne w izolowanych środowiskach. Ogranicz system plików, sieć i dostęp na poziomie systemu tylko do tego, czego wymaga umiejętność. Wymagaj jawnego potwierdzenia użytkownika przed wykonaniem potencjalnie poufnych operacji.
- Inspekcja i rejestrowanie — rejestruj, które umiejętności są ładowane, które zasoby są odczytywane i które skrypty są wykonywane. Dzięki temu dziennik inspekcji umożliwia śledzenie zachowania agenta z powrotem do określonej zawartości umiejętności, jeśli coś pójdzie nie tak.
Kiedy należy używać umiejętności czy przepływów pracy
Przepływy pracy dotyczące umiejętności agenta i struktury agentów rozszerzają możliwości agentów, ale działają zasadniczo na różne sposoby. Wybierz podejście, które najlepiej odpowiada twoim wymaganiom:
- Kontrola — dzięki umiejętnościom sztuczna inteligencja decyduje o sposobie wykonywania instrukcji. Jest to idealne rozwiązanie, gdy chcesz, aby agent był kreatywny lub adaptacyjny. Za pomocą przepływu pracy jawnie zdefiniujesz ścieżkę wykonywania. Używaj przepływów pracy, gdy potrzebujesz deterministycznego, przewidywalnego zachowania.
- Odporność — umiejętność jest uruchamiana w ramach jednego kroku agenta. Jeśli coś nie powiedzie się, należy ponowić próbę wykonania całej operacji. Przepływy pracy obsługują tworzenie punktów kontrolnych, dzięki czemu mogą być wznawiane od ostatniego pomyślnego kroku po awarii. Wybierz przepływy pracy, gdy koszt ponownego wykonania całego procesu jest wysoki.
- Skutki uboczne — Umiejętności są odpowiednie, gdy operacje są idempotentne lub o niskim ryzyku. Preferuj przepływy pracy, gdy kroki powodują skutki uboczne (wysyłanie wiadomości e-mail, naliczanie opłat), które nie powinny być powtarzane podczas ponawiania próby.
- Złożoność — umiejętności najlepiej nadają się do skoncentrowanych zadań z jedną domeną, które może obsłużyć jeden agent. Przepływy pracy lepiej nadają się do wieloetapowych procesów biznesowych, które koordynują wielu uczestników, zatwierdzenia przez ludzi lub integracje z systemami zewnętrznymi.
Wskazówka
Zasadniczo: jeśli chcesz, aby sztuczna inteligencja dowiedziała się, jak wykonać zadanie, użyj umiejętności. Jeśli musisz zagwarantować, jakie kroki są wykonywane i w jakiej kolejności, użyj przepływu pracy.