Aracı Becerileri

Aracı Becerileri , aracılara özel özellikler ve etki alanı uzmanlığı sağlayan taşınabilir yönergeler, betikler ve kaynak paketleridir. Beceriler açık belirtimi izler ve aşamalı bir açıklama deseni uygular, böylece aracılar ihtiyaç duyduklarında yalnızca ihtiyaç duydukları bağlamı yükler.

Aşağıdaki durumlarda Aracı Becerileri'ni kullanın:

  • Paket etki alanı uzmanlığı - Özel bilgileri (gider ilkeleri, yasal iş akışları, veri analizi işlem hatları) yeniden kullanılabilir, taşınabilir paketler olarak yakalayın.
  • Aracı özelliklerini genişletme - Aracılara temel yönergelerini değiştirmeden yeni yetenekler verin.
  • Tutarlılığı sağlama - Çok adımlı görevleri yinelenebilir, denetlenebilir iş akışlarına dönüştürün.
  • Birlikte çalışabilirliği etkinleştirme - Farklı Aracı Becerileri uyumlu ürünlerde aynı beceriyi yeniden kullanma.

Beceri yapısı

Beceri, kaynaklar için isteğe bağlı alt dizinleri olan bir SKILL.md dosya içeren dizindir:

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 biçimi

Dosyada SKILL.md YAML frontmatter ve ardından markdown içeriği bulunmalıdır:

---
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"
---
Veri Alanı Gerekli Description
name Evet En fazla 64 karakter. Yalnızca küçük harfler, sayılar ve kısa çizgiler. Kısa çizgiyle başlamamalı veya bitmemelidir veya ardışık kısa çizgi içermemelidir. Üst dizin adıyla eşleşmelidir.
description Evet Becerinin ne yaptığı ve ne zaman kullanılacağı. En fazla 1024 karakter. Aracıların ilgili görevleri tanımlamalarına yardımcı olan anahtar sözcükler içermelidir.
license Hayı Paketlenmiş bir lisans dosyasına lisans adı veya başvurusu.
compatibility Hayı En fazla 500 karakter. Ortam gereksinimlerini (hedeflenen ürün, sistem paketleri, ağ erişimi vb.) gösterir.
metadata Hayı Ek meta veriler için rastgele anahtar-değer eşlemesi.
allowed-tools Hayı Becerinin kullanabileceği önceden onaylanan araçların yer sınırlandırılmış listesi. Deneysel - destek aracı uygulamaları arasında farklılık gösterebilir.

Ön bilgi bölümünden sonraki Markdown gövdesi, beceri talimatlarını içerir: adım adım yönlendirmeler, girdi ve çıktı örnekleri, yaygın uç durumlar veya ajanın görevi yerine getirmesine yardımcı olan herhangi bir içerik. SKILL.md 500 satırdan az olacak şekilde tutun ve ayrıntılı başvuru malzemelerini ayrı dosyalara taşıyın.

Aşamalı açıklama

Aracı Becerileri, bağlam kullanımını en aza indirmek için dört aşamalı kademeli bir açıklama modeli kullanır.

  1. Tanıtma (beceri başına yaklaşık 100 belirteç) - Beceri adları ve açıklamaları, her çalıştırmanın başlangıcında sistem istemine eklenir, böylece aracı hangi becerilerin kullanılabilir olduğunu bilir.
  2. Yükleme (< 5000 token önerilir) - Bir görev, bir becerinin uzmanlık alanıyla eşleştiğinde ajan, ayrıntılı yönergeler içeren SKILL.md dosyasının tam içeriğini almak için load_skill aracını çağırır.
  3. Kaynakları okuyun (gerektiğinde) - Ajan, ek dosyaları (referanslar, şablonlar, varlıklar) yalnızca gerektiğinde getirmek için read_skill_resource aracını çağırır.
  4. Betikleri çalıştırma (gerektiğinde) - Aracı, bir beceriyle birlikte gelen betikleri yürütmek için run_skill_script aracını çağırır.

Bu desen, aracıya isteğe bağlı derin etki alanı bilgilerine erişim sağlarken bağlam penceresinin yalın kalmasını sağlar.

Uyarı

load_skill her zaman reklam edilir. read_skill_resource yalnızca en az bir beceri kaynağı olduğunda tanıtılır. run_skill_script yalnızca en az bir beceride betik olduğunda tanıtılır.

Bir temsilciye beceri sağlama

Becerilerle çalışmak üç yapı taşları içerir:

  • Sağlayıcı - AgentSkillsProvider (C#) veya SkillsProvider (Python), becerileri bir aracıya sunan bir bağlam sağlayıcısıdır. Sistem isteminde kullanılabilir becerileri duyurur ve aracının becerileri yüklemek, kaynakları okumak ve betikleri çalıştırmak için kullandığı araçları kaydeder.
  • Kaynaklar - kaynak sağlayıcıya beceri sağlar. Beceriler çeşitli kaynak türlerinden gelebilir:
    • Dosya tabanlı - dosya sistemi dizinlerindeki dosyalardan SKILL.md bulunan beceriler.
    • Kod tanımlı - (C#) veya AgentInlineSkill (Python) kullanarak InlineSkill kodda satır içinde tanımlanan beceriler.
    • Sınıf tabanlı - (C#) veya AgentClassSkill<T> (Python) türetilen ClassSkill bir sınıfta kapsüllenen beceriler.
    • MCP tabanlı - (C#) veya UseMcpSkills (Python) aracılığıyla MCPSkillsSource MCP (Model Bağlam Protokolü) sunucularından bulunan beceriler.
  • Oluşturucusu - AgentSkillsProviderBuilder (C#), birden çok kaynağı tek bir sağlayıcıda bir araya getirerek toplama, yinelenenleri kaldırma, önbelleğe alma ve isteğe bağlı filtreleme uygular. Python’da, AggregatingSkillsSource, FilteringSkillsSource ve DeduplicatingSkillsSource gibi kaynak sınıflarını doğrudan oluşturun.

Aşağıdaki bölümlerde, her kaynak türü için becerilerin nasıl oluşturulacağı, ardından kaynakların nasıl birleştirildiği ve onlardan bir sağlayıcının nasıl oluşturulacağı gösterilmektedir.

Dosya tabanlı beceriler

Becerilerinizi içeren bir dizine işaret eden bir AgentSkillsProvider dizin oluşturun ve bunu aracının bağlam sağlayıcılarına ekleyin. Beceri dizinlerinde bulunan dosya tabanlı betiklerin yürütülmesini etkinleştirmek için bir betik çalıştırıcısı geçirin:

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);

Uyarı

DefaultAzureCredential geliştirme için uygundur ancak üretimde dikkatli bir şekilde dikkate alınması gerekir. Üretimde gecikme sorunları, istenmeyen kimlik bilgisi yoklama ve geri dönüş mekanizmalarından kaynaklanan olası güvenlik risklerini önlemek için belirli bir kimlik bilgisi (ör ManagedIdentityCredential. ) kullanmayı göz önünde bulundurun.

Birden çok beceri dizini

Sağlayıcıyı tek bir ana dizine yönlendirebilirsiniz - SKILL.md içeren her alt dizin otomatik olarak bir beceri olarak keşfedilir:

var skillsProvider = new AgentSkillsProvider(
    Path.Combine(AppContext.BaseDirectory, "all-skills"));

Veya birden çok kök dizinde arama yapmak için yolların listesini geçirin:

var skillsProvider = new AgentSkillsProvider(
    [
        Path.Combine(AppContext.BaseDirectory, "company-skills"),
        Path.Combine(AppContext.BaseDirectory, "team-skills"),
    ]);

Sağlayıcı en fazla iki seviye derinliğine kadar arama yapar.

Kaynak ve betik bulmayı özelleştirme

Varsayılan olarak, sağlayıcı .md, .json, .yaml, .yml, .csv, .xml ve .txt uzantılarına sahip kaynakları ve .py, .js, .sh, .ps1, .cs ve .csx uzantılarına sahip betikleri tanır. Her beceri dizininde en fazla iki düzey arar. Şu varsayılanları değiştirmek için kullanın AgentFileSkillsSourceOptions :

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 ve ScriptFilter, beceri adını ve dosyanın göreli yolunu içeren bir AgentFileSkillFilterContext alır; bu da dosyaları konuma, adlandırma kuralına veya herhangi bir özel mantığa göre kısıtlamanıza olanak tanır.

Betiğin yürütülmesi

Dosya tabanlı betiklerin yürütülmesini etkinleştirmek için SubprocessScriptRunner.RunAsync öğesini betik çalıştırıcısı olarak iletin:

var skillsProvider = new AgentSkillsProvider(
    Path.Combine(AppContext.BaseDirectory, "skills"),
    SubprocessScriptRunner.RunAsync);

SubprocessScriptRunner.RunAsync kabaca aşağıdakine eşdeğerdir:

// 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();
}

Çalıştırıcı, bulunan her betiği yerel bir alt işlem olarak çalıştırır. Dosya tabanlı betikler, argümanları dizelerden oluşan bir JSON dizisi olarak bekler - her dizi öğesi konumsal bir komut satırı argümanına dönüşür.

Uyarı

SubprocessScriptRunner yalnızca tanıtım amacıyla sağlanır. Üretim kullanımı için şunları eklemeyi göz önünde bulundurun:

  • Korumalı alan (Sandbox) (örneğin, kapsayıcılar veya yalıtılmış çalışma ortamları)
  • Kaynak sınırları (CPU, bellek, duvar saati zaman aşımı)
  • Giriş doğrulama ve yürütülebilir betiklerin izin listesi
  • Yapılandırılmış günlük kaydı ve denetim izleri

Dosya tabanlı beceriler

SkillsProvider.from_paths() factory’yi, SKILL.md dosyalarını içeren dizinlerdeki becerileri keşfetmek için kullanın ve sağlayıcıyı ajanın bağlam sağlayıcılarına ekleyin:

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],
)

Birden çok beceri dizini

Sağlayıcıyı tek bir ana dizine yönlendirebilirsiniz - SKILL.md içeren her alt dizin otomatik olarak bir beceri olarak keşfedilir:

skills_provider = SkillsProvider.from_paths(
    skill_paths=Path(__file__).parent / "all-skills"
)

Veya birden çok kök dizinde arama yapmak için yolların listesini geçirin:

skills_provider = SkillsProvider.from_paths(
    skill_paths=[
        Path(__file__).parent / "company-skills",
        Path(__file__).parent / "team-skills",
    ]
)

Sağlayıcı en fazla iki seviye derinliğine kadar arama yapar.

Kaynak ve betik bulmayı özelleştirme

Varsayılan olarak, kaynaklar references/ ve assets/ alt dizinlerinden, betikler ise scripts/ dizininden agentskills.io belirtimine göre bulunur. Tanınan kaynak uzantıları , , .md, .json, .yaml, .yml, .csvve .xml'dir.txt. Her beceri dizininde en fazla iki düzey arar. Bulmayı özelleştirmek için , resource_extensionsscript_extensions, , search_depthve resource_filter kullanınscript_filter:

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/"),
)

resource_filter ve script_filter önkoşulları, beceri adını ve dosyanın göreli yolunu alır ve dosyaları konuma, adlandırma kuralına veya herhangi bir özel mantığa göre kısıtlamanızı sağlar. Alt dizinlere ek olarak beceri kök düzeyinde dosyaları dahil etmek için kullanın "." .

Betiğin yürütülmesi

Dosya tabanlı betiklerin yürütülmesini etkinleştirmek için script_runner'yı SkillsProvider.from_paths()'ye geçirin. Protokolü karşılayan herhangi bir senkron veya asenkron çağrılabilir SkillScriptRunner kullanılabilir:

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,
)

Çalıştırıcı, çözümlenmiş FileSkill, FileSkillScript ve isteğe bağlı bir args bağımsız değişkenini alır. Dosya tabanlı betikler, argümanları dizelerden oluşan bir JSON dizisi olarak bekler - her dizi öğesi konumsal bir komut satırı argümanına dönüşür. Betikler, her beceri dizininin .py alt dizinindeki scripts/ dosyalarından otomatik olarak keşfedilir.

Uyarı

Yukarıdaki runner sadece gösterim amacıyla sunulmaktadır. Üretim kullanımı için şunları eklemeyi göz önünde bulundurun:

  • Sanallaştırma (örneğin, kapsayıcılar, seccomp, veya firejail)
  • Kaynak sınırları (CPU, bellek, duvar saati zaman aşımı)
  • Giriş doğrulama ve yürütülebilir betiklerin izin listesi
  • Yapılandırılmış günlük kaydı ve denetim izleri

Uyarı

Betik içeren dosya tabanlı beceriler sağlanmış ancak script_runner ayarlanmamışsa, betik yürütme girişiminde bulunulduğunda SkillsProvider hata verir.

Dosya tabanlı beceriler

Go aracıları, becerileri agent/skills paketi aracılığıyla destekler. Beceriler aynı aşamalı açıklama desenini izler: reklam -> yük -> kaynakları okuma -> betikleri çalıştırma.

Disk üzerindeki dosyalardan SKILL.md becerileri keşfedin ve beceri sağlayıcısını aracı bağlam sağlayıcısı olarak kaydedin:

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},
    },
})

Kod tanımlı beceriler

Dosya tabanlı becerilere, SKILL.md dosyalarından elde edilenler de dahil olmak üzere, AgentInlineSkill kullanarak kodda becerileri tamamen tanımlayabilirsiniz. Kod tanımlı beceriler aşağıdaki durumlarda kullanışlıdır:

  • Beceri içeriği dinamik olarak oluşturulur (örneğin, bir veritabanından veya ortamdan okuma).
  • Beceri tanımlarını, bunları kullanan uygulama koduyla birlikte tutmak istiyorsunuz.
  • Statik dosyalara hizmet etmek yerine okuma zamanında mantık yürüten kaynaklara ihtiyacınız vardır.
  • Beceri tanımlarının çalışma zamanında verilerden oluşturulması gerekir; örneğin, her kullanıcı oturumu için rollerine veya izinlerine göre kişiselleştirilmiş bir beceri oluşturma.
  • Bir becerinin, hizmetleri DI kapsayıcısından çözmek yerine çağrı noktasındaki durumu kapsaması (yerel değişkenler, closure’lar) gerekir.

Temel kod becerisi

Ad, açıklama ve yönergeler içeren bir AgentInlineSkill oluşturun. Kaynakları .AddResource() kullanarak ekleme:

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);

Dinamik kaynaklar

Çalışma zamanında içeriği hesaplamak için .AddResource()'a bir fabrika vekili geçirin. Temsilci, aracı kaynağı her okuduğunda çağrılır:

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)");

Kod tanımlı betikler

.AddScript() bir temsilciyi yürütülebilir bir script olarak kaydetmek için kullanın. Kod tanımlı betikler, doğrudan temsilci çağrıları olarak aynı işlem içinde çalışır. Betik çalıştırıcısı gerekmiyor. Temsilcinin türü belirtilen parametreleri, aracının bağımsız değişkenleri geçirmek için kullandığı bir JSON Şemasına otomatik olarak dönüştürülür:

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);

Uyarı

Kod tanımlı becerileri tek bir sağlayıcıda dosya tabanlı veya sınıf tabanlı becerilerle birleştirmek için bkz AgentSkillsProviderBuilder . Sağlayıcı oluşturma.

SKILL.md dosyalarından bulunan dosya tabanlı becerilere ek olarak, InlineSkill kullanarak becerileri tamamen Python kodda tanımlayabilirsiniz. Kod tanımlı beceriler aşağıdaki durumlarda kullanışlıdır:

  • Beceri içeriği dinamik olarak oluşturulur (örneğin, bir veritabanından veya ortamdan okuma).
  • Beceri tanımlarını, bunları kullanan uygulama koduyla birlikte tutmak istiyorsunuz.
  • Statik dosyalara hizmet etmek yerine okuma zamanında mantık yürüten kaynaklara ihtiyacınız vardır.
  • Beceri tanımlarının çalışma zamanında verilerden oluşturulması gerekir; örneğin, her kullanıcı oturumu için rollerine veya izinlerine göre kişiselleştirilmiş bir beceri oluşturma.
  • Bir becerinin, hizmetleri aracılığıyla çözmek yerine **kwargs (yerel değişkenler, closure'lar) kapsaması gerekir.

Temel kod becerisi

Adı ve açıklamayı içeren bir InlineSkill ile yönerge içeriğine sahip bir SkillFrontmatter örneği oluşturun. İsteğe bağlı olarak statik içeriğe sahip örnekler ekleyin InlineSkillResource :

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)

Dinamik kaynaklar

İşlevi bir kaynak olarak kaydetmek için @skill.resource dekoratörünü kullanın. İşlev, aracı her seferinde kaynağı okuduğunda çağrılır, bu sayede güncel verileri döndürebilir. Senkron ve asenkron fonksiyonlar desteklenir.

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)"

Dekoratör bağımsız değişken olmadan kullanıldığında ()@skill.resource işlev adı kaynak adı, docstring ise açıklama olur. Bunları açıkça ayarlamak için kullanın @skill.resource(name="...", description="...") .

Kod tanımlı betikler

@skill.script dekoratörü kullanarak bir işlevi, bir beceri üzerinde yürütülebilir bir betik olarak kaydedin. Kod tanımlı betikler işlem içinde çalışır ve bir betik çalıştırıcısı gerektirmez. Senkron ve asenkron fonksiyonlar desteklenir.

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})

Dekoratör, bağımsız değişken olmadan (@skill.script) kullanıldığında, işlev adı betik adı, docstring ise açıklama olur. İşlevin yazılan parametreleri otomatik olarak aracının bağımsız değişkenleri geçirmek için kullandığı bir JSON Şemasına dönüştürülür.

SKILL.md dosyalarından keşfedilen dosya tabanlı becerilere ek olarak, becerileri tamamen Go kodunda tanımlayabilirsiniz:

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, beceri yönergelerini yalnızca ajan load_skill öğesini çağırdığında yükler. Betikler, örneğin ["26.2", "1.60934"] gibi CLI tarzı konumsal dize argümanları alır ve bu argümanları betiğin gerektirdiği şekilde ayrıştırabilir.

Tip

Çalıştırılabilir örneklerin tamamı için beceri örneklerine bakın.

Sınıf tabanlı beceriler

Sınıf tabanlı beceriler, ad, açıklama, yönergeler, kaynaklar ve betikler gibi tüm beceri bileşenlerini tek bir C# sınıfında paketlemenizi sağlar. Bu sayede NuGet paketleri olarak paketleme ve dağıtma kolaylaşır. Ekipler becerileri bağımsız olarak yazabilir ve gönderebilir ve tüketiciler bunları tek dotnet add package bir çağrıyla .UseSkill() ekleyebilir. AgentClassSkill<T> öğesinden türetin (sizin sınıfınız T olduğunda), ardından otomatik keşif için özelliklere [AgentSkillResource] ve yöntemlere [AgentSkillScript] ile açıklama ekleyin.

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 });
    }
}

Sınıf tabanlı beceriyi AgentSkillsProvider ile kaydedin:

var skill = new UnitConverterSkill();
var skillsProvider = new AgentSkillsProvider(skill);

[AgentSkillResource] Öznitelik bir özelliğe veya yönteme uygulandığında, dönüş değeri aracı kaynağı okuduğunda kaynak içeriği olarak kullanılır; içeriğin okuma zamanında hesaplanması gerektiğinde bir yöntem kullanın. [AgentSkillScript] bir metoda uygulandığında, aracı betiği çağırdığında yöntem çağrılır. Her bir kaynağı ve scripti tanımlamak için [Description] öğesini System.ComponentModel kullanın.

Uyarı

AgentClassSkill<T> ayrıca öznitelik tabanlı bulmanın uymadığı durumlar için Resources ve Scripts'yi koleksiyonlar olarak geçersiz kılmayı destekler.

Sınıf tabanlı beceriler

Sınıf tabanlı beceriler, ad, açıklama, yönergeler, kaynaklar ve betikler gibi tüm beceri bileşenlerini tek bir Python sınıfında paketlemenizi sağlar. Bu sayede PyPI paketleri olarak paketlenebilir ve dağıtılabilirler. Ekipler becerileri bağımsız olarak yazabilir ve gönderebilir ve tüketiciler bunları tek pip install bir çağrıyla SkillsProvider() ekleyebilir. ClassSkill sınıfından türetin, ardından otomatik keşif için @ClassSkill.resource ve @ClassSkill.script dekoratörlerini kullanın:

import json
from textwrap import dedent
from agent_framework import ClassSkill, SkillFrontmatter

class UnitConverterSkill(ClassSkill):
    """A unit-converter skill defined as a Python class."""

    def __init__(self) -> None:
        super().__init__(
            frontmatter=SkillFrontmatter(
                name="unit-converter",
                description=(
                    "Convert between common units using a multiplication factor. "
                    "Use when asked to convert miles, kilometers, pounds, or kilograms."
                ),
            ),
        )

    @property
    def instructions(self) -> str:
        return dedent("""\
            Use this skill when the user asks to convert between units.

            1. Review the conversion-table resource to find the correct factor.
            2. Use the convert script, passing the value and factor from the table.
            3. Present the result clearly with both units.
        """)

    @property
    @ClassSkill.resource
    def conversion_table(self) -> str:
        """Lookup table of multiplication factors for common unit conversions."""
        return dedent("""\
            # Conversion Tables
            Formula: **result = value × factor**
            | From       | To         | Factor   |
            |------------|------------|----------|
            | miles      | kilometers | 1.60934  |
            | kilometers | miles      | 0.621371 |
            | pounds     | kilograms  | 0.453592 |
            | kilograms  | pounds     | 2.20462  |
        """)

    @ClassSkill.script(name="convert", description="Multiplies a value by a conversion factor.")
    def convert_units(self, value: float, factor: float) -> str:
        """Convert a value using a multiplication factor."""
        result = round(value * factor, 4)
        return json.dumps({"value": value, "factor": factor, "result": result})

Sınıf tabanlı beceriyi SkillsProvider ile kaydedin:

from agent_framework import SkillsProvider

skill = UnitConverterSkill()
skills_provider = SkillsProvider(skill)

@ClassSkill.resource, argümansız bir çıplak dekoratör olarak uygulandığında, yöntem adı kaynak adına dönüşür (alt çizgiler kısa çizgilere dönüştürülerek) ve docstring açıklama olarak kullanılır. Bunları açıkça ayarlamak için kullanın @ClassSkill.resource(name="...", description="...") . Aynı desen için @ClassSkill.scriptde geçerlidir.

Kaynaklar normal yöntemler veya @property tanımlayıcılar olarak tanımlanabilir. @property kullanırken, önce @property, ardından @ClassSkill.resource yerleştirin. Kaynak dönüş değerleri ilk erişimden sonra önbelleğe alınır.

Uyarı

ClassSkill, dekoratör tabanlı keşfin uygun olmadığı senaryolar için, resources ve scripts özelliklerinin doğrudan InlineSkillResource ve InlineSkillScript örnekleri döndürecek şekilde açıkça geçersiz kılınmasını da destekler.

MCP tabanlı beceriler

Uyarı

MCP tabanlı yetenekler Microsoft.Agents.AI.Mcp NuGet paketini gerektirir. MCP becerileri API'si deneyseldir ve gelecek sürümlerde değişebilir.

Beceriler, URI şeması altında skill:// beceri kaynaklarını kullanıma sunan MCP (Model Bağlam Protokolü) sunucularından bulunabilir. MCP sunucusu bir skill://index.json bulma belgesi aracılığıyla becerileri tanıtıyor ve çerçeve, beceri içeriğini isteğe bağlı olarak getiriyor.

MCP tabanlı beceriler iki dizin giriş türünü destekler:

  • skill-md - Beceri SKILL.md ve eşdüzey kaynaklar MCP sunucusundan isteğe bağlı olarak getirilir.
  • archive - Beceri, yerel olarak indirilip paketlenen tek bir paketlenmiş arşiv (ZIP, TAR veya gzip sıkıştırılmış TAR) olarak dağıtılır.

Temel kullanım

Bir MCP beceri kaynağı eklemek için UseMcpSkills üzerinde AgentSkillsProviderBuilder uzantı yöntemini kullanın:

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);

Arşiv türü becerileri

Arşiv türü beceriler için, ayıklama davranışını yapılandırmak üzere AgentMcpSkillsSourceOptions paketinden Microsoft.Agents.AI.Mcp kullanın:

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 arşiv ayıklamayı denetlemek için aşağıdaki özellikleri kullanıma sunar:

  • ArchiveSkillsDirectory - Ayıklanan arşivler için ana dizin. Varsayılan olarak, birden çok kaynak arasında çakışmayı önlemek için her kaynak örneği için oluşturulan, geçerli çalışma dizini altında benzersiz bir alt dizin kullanılır.
  • ArchiveResourceExtensions - Arşivlerden çıkarılan kaynaklar için izin verilen uzantılar. Varsayılan olarak .md, , .json, .yaml, .yml, .csv, .xml, .txt.
  • ArchiveResourceSearchDepth - Çıkarılan her beceri dizini içinde kaynakların ne kadar derinlikte aranacağı. Varsayılan değer 2’dır.
  • ArchiveMaxFileCount - Arşiv başına en fazla dosya sayısı. Bu sınırı aşan arşivler atlanır. Varsayılan değer 20’dır.
  • ArchiveMaxSizeBytes - Arşiv başına maksimum indirme boyutu. Varsayılan değer 1 MB’dır.
  • ArchiveMaxUncompressedSizeBytes - Arşiv başına toplam sıkıştırılmamış boyut. Varsayılan değer 1 MB’dır.

Important

Arşiv türü becerileriyle paketlenen betikler hiçbir zaman yürütülemez. Bu kasıtlı bir güvenlik önlemidir- uzak MCP sunucularından yürütülebilir içerik için açık güven gerekir.

MCP tabanlı beceriler

Uyarı

MCP tabanlı beceriler deneyseldir ve gelecek sürümlerde değişebilir. MCPSkillsSource özellik bayrağı altında, FutureWarning kullanımı bir MCP_SKILLS oluşturur.

Beceriler, URI şeması altında skill:// beceri kaynaklarını kullanıma sunan MCP (Model Bağlam Protokolü) sunucularından bulunabilir. MCP sunucusu, skill://index.json keşif belgesi aracılığıyla becerilerin duyurusunu yapar ve çerçeve, her becerinin SKILL.md içeriğini gerektiğinde resources/read aracılığıyla alır.

Bir MCP'yi ClientSession içine MCPSkillsSource sarın ve bunu SkillsProvider'ye iletin:

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("...")

Uyarı

Python MCPSkillsSource yalnızca skill-md dizin girdilerini destekler (başka bir türdeki dizin girişleri sessizce atlanır). .NET uygulamasından farklı olarak arşiv türü becerilerini desteklemez. Yoksa, okunamıyorsa, boşsa veya ayrıştırılamıyorsa skill://index.json , kaynak boş bir liste döndürür.

Important

Dış MCP sunucusu, aracının çalıştırabileceği yönergeler ve betikler dahil olmak üzere hangi beceri içeriğinin aracıya ulaştığını denetler. Yalnızca izlediğiniz ve güvendiğiniz sunuculara bağlanın MCPSkillsSource ve yanıtlarını güvenilmeyen giriş olarak değerlendirin.

Beceri kaynakları

AgentSkillsProvider, bir veya daha fazla kaynaktan becerileri alır - AgentSkillsSource uygulayan nesneler. Kaynaklar iki kategoriye ayrılır: becerileri keşfeden veya barındıran yaprak kaynaklar (dosya tabanlı beceriler gibi AgentFileSkillsSource ) ve başka bir kaynağın çıkışını dönüştüren dekoratörler (toplama, yinelenenleri kaldırma, önbelleğe alma ve filtreleme). Özel bir kaynak da oluşturabilirsiniz.

Her kaynak tek bir yöntem uygular - GetSkillsAsync(AgentSkillsSourceContext context, CancellationToken cancellationToken = default). geçerli AgentSkillsSourceContext istek hakkında bilgi taşır:

  • Agent - beceri talep eden AIAgent örneği.
  • Session - çağrıyla ilişkili AgentSession veya oturum olmadığında null.

Bu bağlam, kaynak işlem hattı boyunca kullanılabilir; bu nedenle bir FilteringAgentSkillsSource yüklem veya özel bir kaynak mantığını buna dayandırabilir; örneğin, isteği yapan aracıya bağlı olarak farklı bir beceri kümesi döndürebilir.

Yaprak kaynaklar

AgentFileSkillsSource

Diskteki SKILL.md dosyalarından becerileri algılar. Bir veya daha fazla dizin yolunu, isteğe bağlı bir betik yürütücüsünü ve AgentFileSkillsSourceOptions içinde belgelenen isteğe bağlı öğesini kabul eder.

var source = new AgentFileSkillsSource(
    [Path.Combine(AppContext.BaseDirectory, "skills")],
    scriptRunner: SubprocessScriptRunner.RunAsync,
    options: new AgentFileSkillsSourceOptions { SearchDepth = 3 });

AgentInMemorySkillsSource

Kodla tanımlanan veya sınıf tabanlı AgentSkill örnekleri bellekte sarar.

var source = new AgentInMemorySkillsSource([volumeConverterSkill, temperatureConverter]);

Birleştiriciler

AggregatingAgentSkillsSource

Birden çok kaynağı tek bir kaynakta birleştirir. Beceriler, kayıt sırasına göre döndürülür; herhangi bir tekilleştirme veya filtreleme uygulanmaz.

var aggregated = new AggregatingAgentSkillsSource([fileSource, inMemorySource]);

Decorators

Dekoratörler bir iç kaynağı sarar ve çıktısını dönüştürür. İşlem hattı oluşturmak için zincirlenebilirler.

DeduplicatingAgentSkillsSource

Yinelenen beceri adlarını kaldırır (büyük/küçük harfe duyarsız, ilk oluşum kazanır). Yinelenenler uyarı düzeyinde kaydedilir.

var deduplicated = new DeduplicatingAgentSkillsSource(innerSource);

CachingAgentSkillsSource

İç kaynak tarafından döndürülen beceri listesini önbelleğe alır. Eşzamanlı çağrılar, her bir önbellek anahtarı için sıraya alınır; böylece aynı anda yalnızca bir alma işlemi gerçekleştirilir. İsteğe bağlı CachingAgentSkillsSourceOptions öğesini kabul eder:

  • RefreshInterval (TimeSpan?) - ayarlandığında, önbelleğe alınan sonuçların süresi bu aralık sonrasında dolar ve iç kaynak yeniden çağrılır. null olduğunda (varsayılan), önbelleğe alınan sonuçların süresi asla dolmaz.
  • CacheIsolationKeySelector (Func<AgentSkillsSourceContext, string?>?) - önbelleğe alınan sonuçları bağlama göre (örneğin, kiracı başına) yalıtmak için bir önbellek anahtarı döndürür. null olduğunda, tüm çağıranlar tek bir önbellek kovasını paylaşır.
var cached = new CachingAgentSkillsSource(innerSource, new CachingAgentSkillsSourceOptions
{
    RefreshInterval = TimeSpan.FromMinutes(5)
});

FilteringAgentSkillsSource

Becerileri dahil etmek veya dışlamak için bir koşul uygular. Yüklem, beceriyi ve bir AgentSkillsSourceContext alır.

var filtered = new FilteringAgentSkillsSource(
    innerSource,
    (skill, context) => skill.Frontmatter.Name != "experimental-skill");

Özel kaynaklar

Yerleşik kaynaklar senaryonuzu kapsamadığında kendi senaryonuzu uygulayın. Yaprak kaynağın alt sınıfı AgentSkillsSource (veritabanı veya uzak hizmet gibi yeni bir kaynaktan beceri üreten kaynak) veya başka bir kaynağın çıkışını dönüştüren bir dekoratör için alt sınıf DelegatingAgentSkillsSource .

Yaprak kaynak

'den AgentSkillsSource türetin ve uygulayın GetSkillsAsync. AgentSkillsSourceContext bağımsız değişkeni, kaynağın sonucunu geçerli isteğe göre uyarlamasına olanak tanır; örneğin, istekte bulunan aracıya bağlı olarak farklı bir beceri kümesi döndürür. Kaynak bir istemci veya bağlantı gibi kaynaklara sahipse geçersiz kılın Dispose(bool) .

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);
    }
}

Özel dekoratör

DelegatingAgentSkillsSource öğesinden türetin, InnerSource.GetSkillsAsync öğesini çağırın ve sonucu dönüştürün veya gözlemleyin. Bu, yerleşik önbelleğe alma, yinelenenleri kaldırma ve filtreleme dekoratörlerinin kullandığı aynı kalıptır. Örneğin, sonucu değiştirmeden istek başına kaç becerinin döndürüldüğünü kaydeden bir dekoratör:

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;
    }
}

Her iki özel kaynak da doğrudan AgentSkillsProvider öğesine geçirilebilir veya yerleşik kaynaklarda olduğu gibi daha büyük bir işlem hattı içine yerleştirilebilir.

Sağlayıcı oluşturma

AgentSkillsProvider, becerileri bir aracıya sunan bileşendir. Bir veya daha fazla kaynağı sarar ve load_skill, read_skill_resource ve run_skill_script araçlarını kaydeder. Oluşturmanın üç yolu vardır:

  1. AgentSkillsProviderBuilder - otomatik toplama, yinelenenleri kaldırma, önbelleğe alma ve isteğe bağlı filtreleme ile birden çok beceri türünü tek bir sağlayıcıda oluşturur. Dosya tabanlı, kod tanımlı, sınıf tabanlı ve MCP tabanlı becerileri birleştiren senaryolar için en iyi yöntemdir.
  2. Doğrudan kaynak oluşturma - genel AgentSkillsSource sınıfları kullanarak kaynak işlem hattını kendiniz oluşturun. Otomatik önbelleğe alma veya yinelenenleri kaldırma uygulanmaz; işlem hattının tamamını siz denetlersiniz. Sıralama, koşullu mantık veya özel dekoratör davranışı üzerinde denetime ihtiyacınız olduğunda en iyi yöntemdir.
  3. Kolaylık oluşturucuları - doğrudan bir dosya yolundan veya beceri örneklerinden bir sağlayıcı oluşturun. Yinelenenleri kaldırma ve önbelleğe alma işlemini otomatik olarak uygular. Tek kaynaklı senaryolar için en iyi.

AgentSkillsProviderBuilder Kullanımı

Aşağıdakilerden herhangi birine ihtiyacınız olduğunda kullanın AgentSkillsProviderBuilder :

  • Karma beceri türleri : Dosya tabanlı, kod tanımlı (), sınıf tabanlı (AgentInlineSkillAgentClassSkill ) ve MCP tabanlı becerileri tek bir sağlayıcıda birleştirin.
  • Beceri filtreleme - koşul kullanarak becerileri dahil etme veya hariç tutma.

Karma beceri türleri

UseFileSkill, UseSkill, UseMcpSkills ve UseFileScriptRunner öğelerini zincirleyerek bir sağlayıcıda birden çok beceri türünü birleştirin:

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();

Beceri filtreleme

Yalnızca ölçütlerinize uyan becerileri dahil etmek için kullanın UseFilter . Örneğin, paylaşılan bir dizinden beceri yüklemek ancak deneysel olanları hariç tutmak için:

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();

Kaynakları doğrudan oluşturma

Oluşturucu gereksinim duyduğunuz denetimi sunmadığında, kaynak sınıflarını kendiniz oluşturun ve ortaya çıkan işlem hattını AgentSkillsProvider öğesine geçirin. Kullanılabilir kaynakların ve bunlara ilişkin seçeneklerin tam listesi için Beceri kaynakları bölümüne bakın.

Aşağıdaki örnek, benzer bir çok kaynaklı işlem hattı oluşturur, ancak her dekoratörü açıkça denetlemenizi sağlar:

// 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);

Uyarı

ownsSource true olduğunda, sağlayıcının bertaraf edilmesi kaynak işlem hattının tamamının da bertaraf edilmesine neden olur. Kaynak yaşam döngüsünü kendiniz yönetiyorsanız, bunu false olarak ayarlayın.

Kolaylık oluşturucuları

Tek kaynaklı senaryolar için oluşturucuları doğrudan kullanın AgentSkillsProvider . Bunlar, bir builder ya da kaynakların manuel olarak birleştirilmesini gerektirmeden, yinelenen verilerin kaldırılmasını ve önbelleğe alınmasını otomatik olarak sağlar.

Dosya yolundan:

var skillsProvider = new AgentSkillsProvider(
    Path.Combine(AppContext.BaseDirectory, "skills"),
    scriptRunner: SubprocessScriptRunner.RunAsync);

Beceri örneklerinden:

var skillsProvider = new AgentSkillsProvider(volumeConverterSkill, temperatureConverter);

Beceri kaynakları

SkillsProvider, bir veya daha fazla kaynaktan becerileri alır; bunlar SkillsSource'den türetilen nesnelerdir. Kaynaklar iki kategoriye ayrılır: becerileri keşfeden veya barındıran yaprak kaynaklar (dosya tabanlı beceriler gibi FileSkillsSource ) ve başka bir kaynağın çıkışını dönüştüren dekoratörler (toplama, yinelenenleri kaldırma, önbelleğe alma ve filtreleme). Özel bir kaynak da oluşturabilirsiniz.

Her kaynak tek bir yöntem uygular - async def get_skills(self, context: SkillsSourceContext) -> list[Skill]. geçerli SkillsSourceContext istek hakkında bilgi taşır:

  • agent - beceri talep eden aracı (SupportsAgentRun).
  • session - çağrıyla ilişkili AgentSession veya oturum olmadığında None.

Bu bağlam, tüm kaynak işlem hattı boyunca aktarılır; bu nedenle bir FilteringSkillsSource yüklem veya özel bir kaynak, mantığını buna dayandırabilir; örneğin, istekte bulunan temsilciye bağlı olarak farklı bir beceri kümesi döndürebilir.

Yaprak kaynaklar

  • FileSkillsSource - disk üzerindeki dosyalardan SKILL.md becerileri bulur. Bir veya daha fazla dizin yolunu, isteğe bağlı script_runner öğesini ve resource_extensions bölümünde belgelenen keşif seçeneklerini (script_extensions, search_depth, resource_filter, script_filter, ) kabul eder.
  • InMemorySkillsSource - Skill örneklerini (kodla tanımlanmış veya sınıf tabanlı) bellekte sarar.
  • MCPSkillsSource - bir MCP sunucusundan becerileri bulur (bkz. MCP tabanlı beceriler).
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])

Birleştirici

AggregatingSkillsSource birden çok kaynağı tek bir kaynakta birleştirir. Beceriler, kayıt sırasına göre döndürülür; herhangi bir tekilleştirme veya filtreleme uygulanmaz.

from agent_framework import AggregatingSkillsSource

aggregated = AggregatingSkillsSource([file_source, in_memory_source])

Decorators

Dekoratörler bir iç kaynağı sarar ve çıktısını dönüştürür. İşlem hattı oluşturmak için zincirlenebilirler.

  • DeduplicatingSkillsSource - Yinelenen beceri adlarını kaldırır (büyük/küçük harfe duyarsız, ilk oluşum kazanır). Yinelenenler uyarı düzeyinde kaydedilir.
  • CachingSkillsSource - iç kaynak tarafından döndürülen beceri listesini önbelleğe alır. Aynı önbellek anahtarı için aynı anda çağrı yapanlar, devam eden tek bir getirme işlemini paylaşır; bu nedenle alttaki kaynak her anahtar için en fazla bir kez sorgulanır. İki isteğe bağlı anahtar sözcük argümanını kabul eder:
    • refresh_interval (timedelta | None) - ayarlandığında, önbelleğe alınmış bir liste, aralıktan eski olduğunda eski olarak kabul edilir, bu nedenle sonraki çağrı iç kaynağı yeniden sorgular. None olduğunda (varsayılan), önbelleğe alınan sonuçların süresi asla dolmaz. gibi işlem ömrü MCPSkillsSourceboyunca becerileri değişen iç kaynaklar için kullanışlıdır.
    • cache_isolation_key_selector (Callable[[SkillsSourceContext], str | None]) - önbelleğe alınan sonuçları yalıtmak için bağlamdan bir önbellek anahtarı türetir (örneğin, aracı veya kiracı başına). Anahtarlar düşük kardinaliteli ve kararlı olmalıdır. None değerini döndürmek (veya onu None olarak bırakmak), tek bir paylaşılan önbellek bölmesi kullanır.
  • FilteringSkillsSource - becerileri dahil etmek veya dışlamak için bir koşul uygular. Yüklem, beceriyi ve bir SkillsSourceContext alır: 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",
)

Özel kaynaklar

Yerleşik kaynaklar senaryonuzu kapsamadığında kendi senaryonuzu uygulayın. Yaprak kaynağın alt sınıfı SkillsSource (veritabanı veya uzak hizmet gibi yeni bir kaynaktan beceri üreten kaynak) veya başka bir kaynağın çıkışını dönüştüren bir dekoratör için alt sınıf DelegatingSkillsSource .

Yaprak kaynak

'den SkillsSource türetin ve uygulayın get_skills. SkillsSourceContext bağımsız değişkeni, kaynağın sonucunu geçerli isteğe göre uyarlamasına olanak tanır; örneğin, istekte bulunan aracıya bağlı olarak farklı bir beceri kümesi döndürür:

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)

Özel dekoratör

DelegatingSkillsSource öğesinden türetin, self.inner_source.get_skills(context) öğesini çağırın ve sonucu dönüştürün veya gözlemleyin. Bu, yerleşik önbelleğe alma, yinelenenleri kaldırma ve filtreleme dekoratörlerinin kullandığı aynı kalıptır. Örneğin, sonucu değiştirmeden istek başına kaç beceri döndürüldüğünü günlüğe yazan bir dekoratör:

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

Her iki özel kaynak da doğrudan SkillsProvider öğesine geçirilebilir veya yerleşik kaynaklarda olduğu gibi daha büyük bir işlem hattı içine yerleştirilebilir.

Sağlayıcı oluşturma

SkillsProvider, becerileri bir aracıya sunan bileşendir. Bir veya daha fazla kaynağı sarar ve load_skill, read_skill_resource ve run_skill_script araçlarını kaydeder. Oluşturmanın üç yolu vardır:

  1. Beceri örneklerinden - oluşturucuya tek bir Skill veya bir beceri dizisi geçirin. Kod tanımlı ve sınıf tabanlı beceriler için en iyi yöntemdir. Yinelenenleri kaldırma ve önbelleğe alma işlemini otomatik olarak uygular.
  2. Dosya yollarından - SkillsProvider.from_paths() fabrika yöntemini kullanın. Tek kaynak dosya tabanlı beceriler için en iyi yöntemdir. Yinelenenleri kaldırma ve önbelleğe alma işlemini otomatik olarak uygular.
  3. Doğrudan kaynak oluşturma - ortak SkillsSource sınıfları kullanarak kaynak işlem hattını kendiniz oluşturun ve oluşturucuya geçirin. İşlem hattının tamamını siz denetlersiniz. Sıralama, koşullu mantık, önbelleğe alma anahtarları veya özel dekoratör davranışı üzerinde denetime ihtiyacınız olduğunda en iyi seçenektir.

Beceri örneklerinden

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])

Dosya yollarından

from pathlib import Path
from agent_framework import SkillsProvider

skills_provider = SkillsProvider.from_paths(
    skill_paths=Path(__file__).parent / "skills",
    script_runner=my_runner,
)

Kaynakları doğrudan oluşturma

Tam denetime ihtiyaç duyduğunuzda, kaynak sınıflarını kendiniz oluşturun ve ortaya çıkan işlem hattını SkillsProvider öğesine iletin. Kullanılabilir kaynakların ve bunlara ilişkin seçeneklerin tam listesi için Beceri kaynakları bölümüne bakın.

Aşağıdaki örnek, her dekoratör için doğrudan denetim sağlayan çok kaynaklı bir işlem hattı oluşturur. Örnekte yer tutucu nesneler kullanılır:

  • volume_converter_skill- InlineSkill gösterildiği gibi oluşturulan herhangi bir örnek.
  • temperature_converter_skill- ClassSkill gösterildiği gibi oluşturulan herhangi bir örnek.
  • my_runner - SkillScriptRunnerbölümünde gösterildiği gibi tanımlanan bir çağrılabilir öğe.
from pathlib import Path
from agent_framework import (
    AggregatingSkillsSource,
    CachingSkillsSource,
    DeduplicatingSkillsSource,
    FileSkillsSource,
    InMemorySkillsSource,
    SkillsProvider,
)

# 1. Create the leaf sources
file_source = FileSkillsSource(Path(__file__).parent / "skills", script_runner=my_runner)
in_memory_source = InMemorySkillsSource([volume_converter_skill, temperature_converter_skill])

# 2. Aggregate them, then add deduplication and caching decorators
aggregated = AggregatingSkillsSource([file_source, in_memory_source])
deduplicated = DeduplicatingSkillsSource(aggregated)
cached = CachingSkillsSource(deduplicated)

# 3. Create the provider from the composed pipeline
skills_provider = SkillsProvider(cached)

Important

Çağıran tarafından sağlanan SkillsSource, olduğu gibi kullanılır: otomatik olarak yinelenenler ayıklanmaz veya bir CachingSkillsSource içine sarılmaz. Bağlama duyarlı bir kaynağın tek bir paylaşılan kapsayıcıda otomatik olarak önbelleğe alınması, bir ajanın veya kiracının becerilerini başka bir ajan ya da kiracı için tekrar oynatabilir. Bunlara ihtiyaç duyduğunuzda, DeduplicatingSkillsSource ve CachingSkillsSource öğelerini (isteğe bağlı olarak cache_isolation_key_selector ile) kendiniz oluşturun. Otomatik yineleme kaldırma ve önbelleğe alma işlemi yalnızca becerileri veya dosya yollarını doğrudan ilettiğinizde uygulanır (yukarıdaki 1 ve 2 numaralı seçeneklerde olduğu gibi).

Karma beceri türleri

kullanarak AggregatingSkillsSourcedosya tabanlı, kod tanımlı ve sınıf tabanlı becerileri tek bir sağlayıcıda birleştirin:

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]),
        ])
    )
)

Beceri filtreleme

Ajanın hangi becerileri göreceğini kontrol etmek için FilteringSkillsSource kullanın. Yüklem, her bir Skill ile SkillsSourceContext öğesini alır ve becerinin dahil edilmesi için True döndürür. Örneğin, becerileri paylaşılan bir dizinden yüklemek ancak deneysel olanı gizlemek için:

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",
        )
    )
)

Önbelleğe alma davranışı

Varsayılan olarak oluşturucu, kaynak işlem hattını altta yatan kaynaklar tarafından döndürülen beceri listesini önbelleğe alan bir CachingAgentSkillsSource ile sarar. İlk istekte beceriler çözümlendikten sonra, sonraki istekler kaynakları yeniden sorgulamadan önbelleğe alınan listeyi yeniden kullanır. Önbelleğe almayı devre dışı bırakmak için (örneğin, beceri tanımları sık değiştiğinde geliştirme sırasında), oluşturucuda kullanın DisableCaching() :

var skillsProvider = new AgentSkillsProviderBuilder()
    .UseFileSkill(Path.Combine(AppContext.BaseDirectory, "skills"))
    .UseFileScriptRunner(SubprocessScriptRunner.RunAsync)
    .DisableCaching()
    .Build();

Uyarı

Beceri içeriği sık sık değiştiğinde geliştirme sırasında önbelleğe almayı devre dışı bırakmak yararlıdır. Üretimde, daha iyi performans için önbelleğe almayı etkin (varsayılan) bırakın.

Önbelleğe alma davranışı

Beceri araçları ve yönergeler varsayılan olarak ilk derlemeden sonra önbelleğe alınır. Her çağrıda yeniden derlemeyi zorlamak için disable_caching=True değerini ayarlayın:

skills_provider = SkillsProvider.from_paths(
    skill_paths=Path(__file__).parent / "skills",
    disable_caching=True,
)

disable_caching, kodla tanımlanan ve sınıf tabanlı beceriler için SkillsProvider oluşturucusunda da mevcuttur.

Önbelleğe almayı etkin tutarken becerileri düzenli olarak yeniden keşfetmek için (örneğin, dosya tabanlı veya MCP kaynağı işlemin yaşam döngüsü boyunca değiştiğinde) cache_refresh_interval parametresini geçirin. Yerleşik önbellek, aralıktan eski olduğunda eski olarak kabul edilir, bu nedenle sonraki çalıştırma kaynağı yeniden sorgular:

from datetime import timedelta

skills_provider = SkillsProvider.from_paths(
    skill_paths=Path(__file__).parent / "skills",
    cache_refresh_interval=timedelta(minutes=5),
)

cache_refresh_interval yalnızca sağlayıcının dahili olarak oluşturduğu önbelleği etkiler (yeteneklerden veya dosya yollarından); disable_caching=True olduğunda yok sayılır ve çağıran tarafından sağlanan bir SkillsSource üzerinde hiçbir etkisi yoktur (bunlar için bir CachingSkillsSource ile kendi refresh_interval öğenizi oluşturun).

Uyarı

Beceri içeriği sık sık değiştiğinde geliştirme sırasında önbelleğe almayı devre dışı bırakmak yararlıdır. Üretimde, daha iyi performans için önbelleğe almayı etkin (varsayılan) bırakın.

Araç onayı

AgentSkillsProvider tarafından sunulan tüm araçlar (load_skill, read_skill_resource, run_skill_script) varsayılan olarak onay gerektirir. Bir araç çağrısı onay gerektirdiğinde, aracı duraklar ve hemen yürütmek yerine bir ToolApprovalRequestContent döndürür. Güvenilir işlemlere yönelik istemleri seçmeli olarak atlamak için ara yazılımı otomatik onay kurallarıyla kullanın UseToolApproval :

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();

Komut dosyası yürütme dahil olmak üzere tüm yetenek araçlarını otomatik olarak onaylamak için:

.UseToolApproval(new ToolApprovalAgentOptions
{
    AutoApprovalRules = [AgentSkillsProvider.AllToolsAutoApprovalRule],
})

Belirli araçlar için onayı devre dışı bırakma

Tek tek araçların onayını devre dışı bırakmak ve bunları tamamen onay akışından kaldırmak için kullanın AgentSkillsProviderOptions :

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
    });

Bazı araçlar onay gerektirdiğinde ve diğerleri aynı yanıtta olmadığında model her iki türü de aynı anda çağırabilir. EnableNonApprovalRequiredFunctionBypassing ayarını, onay gerektirmeyen araçlar hemen çalıştırılırken kullanıcıya yalnızca geri kalanlar için istem gösterilecek şekilde yapın:

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();

Onay isteklerini işleme

Araçlar onay gerektirdiğinde (ve hiçbir otomatik onay kuralı eşleşmediğinde), ajan devam etmeden önce onaylanması veya reddedilmesi gereken ToolApprovalRequestContent öğeleri döndürür:

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();
}

Betik hatası ayrıntıları

Varsayılan olarak, bir beceri betiğinin yürütülmesi başarısız olduğunda, özel durum altyapıdaki FunctionInvokingChatClient öğesine yayılır. IncludeDetailedErrors özelliği olarak trueayarlanırsa, özel durum iletisi modele iletilir ve farklı bağımsız değişkenlerle yeniden denenerek kendi kendine düzeltilmesi sağlanır:

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());

Doğrudan yapılandıramıyorsanız FunctionInvokingChatClient , bunun yerine ayarlayın AgentSkillsProviderOptions.IncludeDetailedErrors . Bu, beceri sağlayıcısı düzeyindeki özel durumu yakalar ve hata iletisini doğrudan modele döndürür:

var skillsProvider = new AgentSkillsProvider(
    Path.Combine(AppContext.BaseDirectory, "skills"),
    SubprocessScriptRunner.RunAsync,
    options: new AgentSkillsProviderOptions
    {
        IncludeDetailedErrors = true,
    });

Uyarı

Her iki yaklaşım da ham özel durum ayrıntılarını modele açıklanabilir. Özel durum iletileri bağlantı dizeleri, dosya yolları veya iç hizmet adları gibi hassas bilgiler içerebilir. Ayrıca, beceriler veya betikler güvenilir olmayan kaynaklardan geliyorsa, kötü amaçla hazırlanmış bir betik, iletisine istem enjeksiyonu yükü gömülmüş bir özel durum fırlatabilir.

SkillsProvider tarafından sunulan tüm araçlar (load_skill, read_skill_resource ve run_skill_script) varsayılan olarak onay gerektirir. Bir araç çağrısı onay gerektirdiğinde, aracı hemen yürütmek yerine duraklar ve onay isteklerini result.user_input_requests aracılığıyla iletir. Her isteği request.to_function_approval_response(approved=...) ile onaylar veya reddeder ve yanıtları geri gönderirsiniz:

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)

Bir araç çağrısı reddedildiğinde (approved=False), ajana kullanıcının bunu reddettiği bildirilir ve buna göre yanıt verebilir.

Güvenilir araçları otomatik olarak onaylama

Her çağrı için istemde bulunmak yerine, ToolApprovalMiddleware tarafından sunulan statik otomatik onay kurallarından biriyle SkillsProvider yükleyin. Bu, betiğin yürütülmesi için istemde bulunmaya devam ederken salt okunur araçların otomatik olarak çalışmasına olanak tanır:

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],
)

İki kural kullanılabilir:

  • SkillsProvider.read_only_tools_auto_approval_rule - yalnızca salt okunur araçları (load_skill, read_skill_resource) onaylarken run_skill_script için yine de istemde bulunur.
  • SkillsProvider.all_tools_auto_approval_rule - dahil olmak üzere run_skill_script her beceri aracını onaylar (el ile onay döngüsü gerekmez).

Her iki kural da server_label taşıyan tüm çağrıları reddeder; dolayısıyla bu sağlayıcının yerel araçlarıyla sınırlı kalır ve aynı ada sahip barındırılan bir aracı hiçbir zaman otomatik olarak onaylamaz. Kurallar yalnızca onay gerektirmeye devam eden araçlar için geçerlidir - aşağıdaki disable_*_approval argümanlarıyla devre dışı bırakılan araçlar ise her durumda onay gerekmeksizin çalışır.

Belirli araçlar için onayı devre dışı bırakma

Güvenilir beceriler için, belirli araçları onay akışının tamamen dışında bırakmak üzere disable_load_skill_approval, disable_read_skill_resource_approval ve/veya disable_run_skill_script_approval iletin (bunlar approval_mode="never_require" ile kaydedilir):

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
)

Bu argümanlar SkillsProvider.from_paths() üzerinde de kullanılabilir.

Uyarı

Yalnızca güvendiğiniz kaynaklardan gelen beceri ve betikler için onayı devre dışı bırakın veya betiklerin yürütülmesini otomatik olarak onaylayın. Beceri yönergeleri aracının bağlamlarına eklenir ve run_skill_script kaynak tarafından sağlanan kodu yürütür.

Özel sistem istemi

Varsayılan olarak, beceri sağlayıcısı kullanılabilir becerileri listeleyen bir sistem istemi ekler ve aracıya load_skill ve read_skill_resource kullanmasını ister. Bu istemi özelleştirebilirsiniz:

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.
            """
    });

Uyarı

Özel şablon, oluşturulan beceri listesinin yer tutucusu olarak içermelidir {skills} . Değişmez köşeli ayraçlar {{ ve }} olarak kaçınılmalıdır.

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}"
    ),
)

Uyarı

Özel şablon, oluşturulan beceri listesi için {skills} yer tutucusunu içermelidir. İsteğe bağlı olarak {resource_instructions} (kaynak araç ipucu) ve {runner_instructions} (betik araç ipucu) yer tutucularını içerebilir; bunlar mevcut olduğunda yerleşik yönlendirmelerle doldurulur, verilmediklerinde ise yalnızca görüntülenmezler (ilgili araçlar yine de kayıtlıdır). Değişmez köşeli ayraçlar {{ ve }} olarak kaçınılmalıdır.

Hizmetleri ve çalışma zamanı bağımsız değişkenlerini ekleme

Beceri kaynağı işlevleri ve betik işlevleri, çalışma zamanında kendilerine sağlanan harici uygulama bağlamını alabilir.

Beceri kaynağı ve betik temsilcileri, Agent Framework'ün otomatik olarak enjekte ettiği bir IServiceProvider parametresini tanımlayabilir. Bu, becerilerin kayıtlı uygulama hizmetlerini isteğe bağlı olarak çözmelerine olanak tanır.

Kurulum

Uygulama hizmetlerinizi kaydedin ve aracıya IServiceProvider parametresi aracılığıyla derlenmiş services değerini geçirin.

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);

DI ile kod tanımlı beceriler

IServiceProvider öğesini AddResource veya AddScript temsilcilerinde parametre olarak bildirin - aracı bir kaynağı okuduğunda veya bir betiği çalıştırdığında çerçeve bunu otomatik olarak çözümler ve enjekte eder:

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);
    });

DI ile sınıf tabanlı beceriler

Yöntemleri [AgentSkillResource] veya [AgentSkillScript] ile işaretleyin ve bir IServiceProvider parametresi tanımlayın - çerçeve bu üyeleri yansıma yoluyla keşfeder ve hizmet sağlayıcısını otomatik olarak enjekte eder:

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);
    }
}

Tip

Sınıf tabanlı beceriler, bağımlılıkları oluşturucuları aracılığıyla da çözebilir. 'de ServiceCollection beceri sınıfını kaydedin ve doğrudan çağırmak new yerine kapsayıcıdan çözümleyin:

services.AddSingleton<WeightConverterSkill>();
var weightSkill = serviceProvider.GetRequiredService<WeightConverterSkill>();

Beceri sınıfının, kaynak ve betik temsilcileri tarafından kullanılanların ötesinde enjekte edilen hizmetlere ihtiyaç duyduğunda bu, kullanışlıdır.

kabul eden **kwargs kaynak ve betik işlevleri, öğesine agent.run()geçirilen çalışma zamanı anahtar sözcüğü bağımsız değişkenlerini otomatik olarak alır. Bu, beceri işlevlerinin yapılandırma, kullanıcı kimliği veya hizmet istemcileri gibi uygulama bağlamlarına, bunları beceri tanımına sabit kodlamadan erişmesini sağlar.

Çalışma zamanı bağımsız değişkenlerini geçirme

function_invocation_kwargs'u agent.run()'e sağlayın, böylece çerçeve bunları kaynak ve betik işlevlerine anahtar sözcük bağımsız değişkenleri olarak iletebilir.

response = await agent.run(
    "How many kilometers is 26.2 miles?",
    function_invocation_kwargs={"precision": 2, "user_id": "alice"},
)

Kwargs ile kod tanımlı beceriler

Bir kaynak işlevi **kwargs bildirdiğinde, aracı kaynağı her okuduğunda çerçeve, çalışma zamanı sırasındaki anahtar kelime bağımsız değişkenlerini iletir.

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}"

**kwargs olmayan kaynak işlevleri, bağımsız değişken olmadan çağrılır ve çalışma zamanı bağlamı almaz.

Bir betik işlevi **kwargs bildirdiğinde, çerçeve, çalışma zamanı anahtar sözcüğü bağımsız değişkenlerini, aracı tarafından sağlanan args ile birlikte iletir.

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})

Aracı, value ve factorargs araç çağrısı aracılığıyla sağlar; uygulama ise precisionfunction_invocation_kwargs aracılığıyla sağlar. **kwargs olmadan betik işlevleri yalnızca aracı tarafından sağlanan bağımsız değişkenleri alır.

Kwargs ile sınıf tabanlı beceriler

Sınıf tabanlı beceri yöntemleri, çalışma zamanı argümanlarını almak için **kwargs öğesini de alabilir. Örüntü de aynı şekilde çalışır - kaynak yöntemlerinde veya betik yöntemlerinde **kwargs bildirin:

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})

En iyi güvenlik uygulamaları

Aracı Becerileri, projenize getirdiğiniz herhangi bir üçüncü taraf kodu gibi ele alınmalıdır. Beceri yönergeleri aracının bağlamı içine eklendiğinden ve beceriler betikler içerebilir; açık kaynak bağımlılığına uygulayacağınız aynı gözden geçirme ve idare düzeyini uygulamak çok önemlidir.

  • Kullanmadan önce gözden geçirme - Dağıtmadan önce tüm beceri içeriğini (SKILL.md, betikleri ve kaynakları) okuyun. Komut dosyasının gerçek davranışının belirtilen amacıyla eşleştiğini doğrulayın. Güvenlik yönergelerini atlamaya, verileri dışarı aktarmaya veya aracı yapılandırma dosyalarını değiştirmeye çalışan saldırgan yönergeleri denetleyin.
  • Kaynak güveni - Yalnızca güvenilen yazarların veya araştırılan iç katkıda bulunanların becerilerini yükleyin. Net kanıtlanmışlık, sürüm denetimi ve etkin bakım özelliklerine sahip becerileri tercih edin. Popüler paketlerin adlarını taklit ederek onları yanıltıcı şekilde kullanan sahte beceri adlarına dikkat edin.
  • Korumalı Alan - Yürütülebilir betikler içeren becerileri yalıtılmış ortamlarda çalıştırın. Dosya sistemi, ağ ve sistem düzeyinde erişimi yalnızca becerinin gerektirdiğiyle sınırlayın. Hassas olabilecek işlemleri yürütmeden önce açık kullanıcı onayı gerektir.
  • Denetim ve günlük kaydı - Hangi becerilerin yüklendiğini, hangi kaynakların okunduğunu ve hangi betiklerin yürütüldüğünü kaydedin. Bu, bir sorun olması durumunda aracı davranışını belirli beceri içeriğine geri izlemeniz için bir denetim izi sağlar.

Becerilerin ve iş akışlarının ne zaman kullanılacağı

Aracı Becerileri ve Aracı Çerçevesi İş Akışları, aracıların yapabileceklerini genişletir, ancak temelde farklı şekillerde çalışır. Gereksinimlerinize en uygun yaklaşımı seçin:

  • Denetim : Yapay zeka, bir beceriyle yönergelerin nasıl yürütüleceğine karar verir. Bu, aracının yaratıcı veya uyarlamalı olmasını istediğinizde idealdir. bir iş akışıyla, yürütme yolunu açıkça tanımlarsınız. Belirlenimci ve öngörülebilir davranışlara ihtiyaç duyduğunuzda iş akışlarını kullanın.
  • Dayanıklılık - Bir beceri, bir ajanın tek bir dönüşü içinde çalışır. Bir şey başarısız olursa tüm işlem yeniden denenmelidir. İş akışları denetim noktası oluşturmayı desteklediğinden, hatadan sonraki son başarılı adımdan devam edebilir. İşlemin tamamını yeniden yürütme maliyeti yüksek olduğunda iş akışlarını seçin.
  • Yan etkiler - İşlemler etkili veya düşük riskli olduğunda beceriler uygundur. Adımlar tekrar edilmemesi gereken yan etkiler (e-posta gönderme, ödeme alma) oluşturduğunda iş akışlarını tercih edin.
  • Karmaşıklık - Beceriler, tek bir ajanın yürütebileceği, belirli bir alana odaklanan görevler için en uygunudur. İş akışları birden çok aracıyı, insan onayını veya dış sistem tümleştirmesini koordine eden çok adımlı iş süreçleri için daha uygundur.

Tip

Temel bir kural olarak: Yapay zekanın bir görevi nasıl yerine getirdiğini anlanmasını istiyorsanız bir beceri kullanın. Hangi adımların ve hangi sırayla yürütüleceklerini garanti etmeniz gerekiyorsa bir iş akışı kullanın.

Sonraki Adımlar