Compartilhar via


Habilidades do Agente

As Habilidades do Agente são pacotes portáteis de instruções, scripts e recursos que fornecem aos agentes recursos especializados e experiência de domínio. As habilidades seguem uma especificação aberta e implementam um padrão de divulgação progressiva para que os agentes carreguem apenas o contexto necessário, quando precisarem.

Use as habilidades do agente quando quiser:

  • Empacotar expertise em domínio – Capturar conhecimento especializado (políticas de despesas, fluxos de trabalho legais, pipelines de análise de dados) como pacotes reutilizáveis e portáteis.
  • Estender as funcionalidades do agente – dê aos agentes novas habilidades sem alterar suas instruções principais.
  • Garantir a consistência – transforme tarefas de várias etapas em fluxos de trabalho repetíveis e auditáveis.
  • Habilitar a interoperabilidade — reutilize a mesma habilidade em diferentes produtos compatíveis com habilidades do agente.

Estrutura de habilidades

Uma habilidade é um diretório que contém um SKILL.md arquivo com subdiretórios opcionais para recursos:

expense-report/
├── SKILL.md                          # Required — frontmatter + instructions
├── scripts/
│   └── validate.py                   # Executable code agents can run
├── references/
│   └── POLICY_FAQ.md                 # Reference documents loaded on demand
└── assets/
    └── expense-report-template.md    # Templates and static resources

formato SKILL.md

O SKILL.md arquivo deve conter o frontmatter YAML seguido pelo conteúdo de markdown:

---
name: expense-report
description: File and validate employee expense reports according to company policy. Use when asked about expense submissions, reimbursement rules, or spending limits.
license: Apache-2.0
compatibility: Requires python3
metadata:
  author: contoso-finance
  version: "2.1"
---
Campo Obrigatório DESCRIÇÃO
name Yes Máximo de 64 caracteres. Letras minúsculas, números e hifens somente. Não deve iniciar ou terminar com um hífen ou conter hifens consecutivos. Deve corresponder ao nome do diretório pai.
description Yes O que a habilidade faz e quando usá-la. Máximo de 1024 caracteres. Deve incluir palavras-chave que ajudam os agentes a identificar tarefas relevantes.
license Não Nome da licença ou referência a um arquivo de licença empacotado.
compatibility Não Máximo de 500 caracteres. Indica os requisitos de ambiente (produto pretendido, pacotes do sistema, acesso à rede etc.).
metadata Não Mapeamento arbitrário de chave-valor para metadados adicionais.
allowed-tools Não Lista delimitada por espaço de ferramentas pré-aprovadas que a habilidade pode usar. Experimental – o suporte pode variar entre implementações de agente.

O corpo em linguagem de marcação (markdown) após o frontmatter contém instruções sobre como usar a habilidade – orientação passo a passo, exemplos de entradas e saídas, casos extremos comuns ou qualquer conteúdo que ajude o agente a executar a tarefa. Mantenha SKILL.md com menos de 500 linhas e transfira o material detalhado de referência para arquivos separados.

Divulgação progressiva

As Habilidades do Agente usam um padrão de divulgação progressiva de quatro estágios para minimizar o uso de contexto:

  1. Anuncie (aproximadamente 100 tokens por habilidade) — nomes de habilidade e descrições são injetados no prompt do sistema no início de cada execução, para que o agente saiba quais habilidades estão disponíveis.
  2. Carregar (< 5000 tokens recomendados) — Quando uma tarefa corresponde ao domínio de uma habilidade, o agente chama a ferramenta load_skill para recuperar o conteúdo completo do documento SKILL.md com instruções detalhadas.
  3. Ler recursos (conforme necessário) — O agente chama a read_skill_resource ferramenta para buscar arquivos suplementares (referências, modelos, ativos) somente quando necessário.
  4. Executar scripts (conforme necessário) — O agente chama a run_skill_script ferramenta para executar scripts agrupados com uma habilidade.

Esse padrão mantém a janela de contexto do agente enxuta, dando-lhe acesso ao conhecimento profundo do domínio sob demanda.

Observação

load_skill é sempre anunciado. read_skill_resource é anunciado somente quando pelo menos uma habilidade tem recursos. run_skill_script é anunciado somente quando pelo menos uma habilidade tem scripts.

Fornecendo habilidades a um agente

AgentSkillsProvider (C#) e SkillsProvider (Python) são provedores de contexto que disponibilizam habilidades aos agentes. Eles dão suporte a três fontes de habilidade:

  • Baseado em arquivos – habilidades descobertas a partir de arquivos em diretórios do SKILL.md sistema de arquivos
  • Definido em Código — habilidades definidas diretamente no código usando AgentInlineSkill (C#) ou Skill (Python)
  • Baseado em classe — habilidades encapsuladas em uma classe C# derivada de AgentClassSkill<T> (somente C#)

Para misturar várias fontes em um provedor, use AgentSkillsProviderBuilder (somente C# — consulte Builder: cenários avançados de várias fontes).

Habilidades baseadas em arquivo

Crie um AgentSkillsProvider apontando para um diretório que contenha suas habilidades e adicione-o aos provedores de contexto do agente. Passe um executor de script para habilitar a execução de scripts baseados em arquivo encontrados em diretórios de habilidades:

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

Aviso

DefaultAzureCredential é conveniente para o desenvolvimento, mas requer uma consideração cuidadosa na produção. Em produção, considere o uso de uma credencial específica (por exemplo, ManagedIdentityCredential) para evitar problemas de latência, investigação de credenciais não intencionais e possíveis riscos de segurança de mecanismos de fallback.

Vários diretórios de habilidades

Você pode apontar o provedor para um único diretório pai – cada subdiretório que contém um SKILL.md é descoberto automaticamente como uma habilidade ("skill"):

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

Ou passe uma lista de caminhos para pesquisar vários diretórios raiz:

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

O provedor pesquisa em até dois níveis de profundidade.

Personalizando a descoberta de recursos

Por padrão, o provedor reconhece recursos com extensões .md, .json, .yaml, .yml, .csv, .xml e .txt em subdiretórios references e assets. Use AgentFileSkillsSourceOptions para alterar esses padrões:

var fileOptions = new AgentFileSkillsSourceOptions
{
    AllowedResourceExtensions = [".md", ".txt"],
    ResourceDirectories = ["docs", "templates"],
};

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

Execução do script

Passe SubprocessScriptRunner.RunAsync como o segundo argumento para AgentSkillsProvider habilitar a execução de scripts baseados em arquivos:

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

SubprocessScriptRunner.RunAsync é aproximadamente equivalente ao seguinte:

// Simplified equivalent of what SubprocessScriptRunner.RunAsync does internally
using System.Diagnostics;

static async Task<string> RunAsync(AgentSkill skill, AgentSkillScript script, IDictionary<string, object?>? args)
{
    var psi = new ProcessStartInfo("python3")
    {
        RedirectStandardOutput = true,
        UseShellExecute = false,
    };
    psi.ArgumentList.Add(Path.Combine(skill.Path, script.Path));
    if (args != null)
    {
        foreach (var (key, value) in args)
        {
            if (value is not null)
            {
                psi.ArgumentList.Add($"--{key}");
                psi.ArgumentList.Add(value.ToString()!);
            }
        }
    }
    using var process = Process.Start(psi)!;
    string output = await process.StandardOutput.ReadToEndAsync();
    await process.WaitForExitAsync();
    return output.Trim();
}

O executor executa cada script descoberto como um subprocesso local, encaminhando os argumentos JSON fornecidos pelo agente como sinalizadores de linha de comando.

Aviso

SubprocessScriptRunner é fornecido somente para fins de demonstração. Para uso em produção, considere adicionar:

  • Sandboxing (por exemplo, contêineres ou ambientes de execução isolados)
  • Limites de recursos (CPU, memória, tempo limite do relógio de parede)
  • Validação de entrada e lista de permissões de scripts executáveis
  • Registros e trilhas de auditoria estruturadas

Personalizando a descoberta de script

Por padrão, o provedor reconhece scripts com extensões.py, .js, .sh, , .ps1e .cs.csx no scripts subdiretório. Use AgentFileSkillsSourceOptions para alterar esses padrões:

Passe AgentFileSkillsSourceOptions para o AgentSkillsProvider construtor ou para UseFileSkill / UseFileSkills o construtor:

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

Habilidades baseadas em arquivo

Crie um SkillsProvider apontando para um diretório que contenha suas habilidades e adicione-o aos provedores de contexto do agente.

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

Vários diretórios de habilidades

Você pode apontar o provedor para uma única pasta pai – cada subpasta que contém uma SKILL.md é descoberta automaticamente como uma habilidade:

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

Ou passe uma lista de caminhos para pesquisar vários diretórios raiz:

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

O provedor pesquisa em até dois níveis de profundidade.

Personalizando a descoberta de recursos

Por padrão, SkillsProvider reconhece recursos com extensões.md, , .json.yaml, , .yml, .csv, .xmle .txt. Ele examina todos os subdiretórios dentro de cada pasta de habilidade. Passe resource_extensions para alterar os tipos de arquivo reconhecidos:

skills_provider = SkillsProvider(
    skill_paths=Path(__file__).parent / "skills",
    resource_extensions=(".md", ".txt"),
)

Execução do script

Para habilitar a execução de scripts baseados em arquivo, passe um script_runner para SkillsProvider. Qualquer sincronização ou chamada assíncrona que atenda ao SkillScriptRunner protocolo pode ser usada:

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

O corredor recebe o resolvido Skill, SkillScript, e um dicionário opcional args. Scripts baseados em arquivo são automaticamente descobertos a partir de arquivos .py em diretórios de skills.

Aviso

O executor acima é fornecido somente para fins de demonstração. Para uso em produção, considere adicionar:

  • Sandboxing (por exemplo, contêineres seccomp ou firejail)
  • Limites de recursos (CPU, memória, tempo limite do relógio de parede)
  • Validação de entrada e lista de permissões de scripts executáveis
  • Registros e trilhas de auditoria estruturadas

Observação

Se as habilidades baseadas em arquivos com scripts forem fornecidas, mas não estiver script_runner definido, SkillsProvider gerará um ValueError.

Habilidades definidas por código

Além das habilidades baseadas em arquivo descobertas nos SKILL.md arquivos, você pode definir habilidades inteiramente no código usando AgentInlineSkill. As habilidades definidas por código são úteis quando:

  • O conteúdo da habilidade é gerado dinamicamente (por exemplo, leitura de um banco de dados ou ambiente).
  • Você deseja manter definições de habilidade junto com o código do aplicativo que as usa.
  • Você precisa de recursos que executem a lógica em tempo de leitura em vez de servir arquivos estáticos.

Habilidade básica de código

Crie um AgentInlineSkill com um nome, uma descrição e instruções. Anexar recursos usando .AddResource():

using Microsoft.Agents.AI;

var codeStyleSkill = new AgentInlineSkill(
    name: "code-style",
    description: "Coding style guidelines and conventions for the team",
    instructions: """
        Use this skill when answering questions about coding style, conventions, or best practices for the team.
        1. Read the style-guide resource for the full set of rules.
        2. Answer based on those rules, quoting the relevant guideline where helpful.
        """)
    .AddResource(
        "style-guide",
        """
        # Team Coding Style Guide
        - Use 4-space indentation (no tabs)
        - Maximum line length: 120 characters
        - Use type annotations on all public methods
        """);

var skillsProvider = new AgentSkillsProvider(codeStyleSkill);

Recursos dinâmicos

Passe um delegado de fábrica para .AddResource() calcular o conteúdo em runtime. O delegado é invocado sempre que o agente lê o recurso:

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

Scripts definidos por código

Use .AddScript() para registrar um delegado como um script executável. Scripts definidos por código são executados em processo como chamadas de delegado direto. Nenhum executor de script é necessário. Os parâmetros digitados do delegado são automaticamente convertidos em um esquema JSON que o agente usa para passar argumentos:

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

Observação

Para combinar habilidades definidas por código com habilidades baseadas em arquivo ou baseadas em classe em um único provedor, use AgentSkillsProviderBuilder — consulte Builder: cenários avançados de várias fontes.

Além das habilidades baseadas em arquivo descobertas de arquivos SKILL.md, você pode definir habilidades inteiramente em código Python. As habilidades definidas por código são úteis quando:

  • O conteúdo da habilidade é gerado dinamicamente (por exemplo, leitura de um banco de dados ou ambiente).
  • Você deseja manter definições de habilidade junto com o código do aplicativo que as usa.
  • Você precisa de recursos que executem a lógica em tempo de leitura em vez de servir arquivos estáticos.

Habilidade básica de código

Crie uma Skill instância com um nome, uma descrição e um conteúdo de instrução. Opcionalmente, anexe SkillResource instâncias com conteúdo estático:

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

Recursos dinâmicos

Use o @skill.resource decorador para registrar uma função como um recurso. A função é chamada cada vez que o agente lê o recurso, para que possa retornar dados atualizados. Há suporte para funções de sincronização e assíncronas:

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

Quando o decorador é usado sem argumentos (@skill.resource), o nome da função se torna o nome do recurso e o docstring se torna a descrição. Use @skill.resource(name="...", description="...") para defini-los explicitamente.

Scripts definidos por código

Use o @skill.script decorador para registrar uma função como um script executável em uma habilidade. Scripts definidos por código são executados em processo e não exigem um executor de script. Há suporte para funções de sincronização e assíncronas:

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

Quando o decorador é usado sem argumentos (@skill.script), o nome da função se torna o nome do script e o docstring se torna a descrição. Os parâmetros tipados da função são convertidos automaticamente num esquema JSON que o agente usa para passar argumentos.

Combinando habilidades baseadas em arquivo e definidas por código

Passe ambos skill_paths e skills para um único SkillsProvider. As habilidades baseadas em arquivo são descobertas primeiro; se uma habilidade definida por código tiver o mesmo nome de uma habilidade baseada em arquivo existente, a habilidade definida por código será ignorada:

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

Habilidades baseadas em classe

As habilidades baseadas em classe permitem agrupar todos os componentes de habilidade — nome, descrição, instruções, recursos e scripts — em uma única classe C#. Derivar de AgentClassSkill<T> (onde T é sua classe), em seguida, anotar propriedades com [AgentSkillResource] e métodos com [AgentSkillScript] para descoberta automática.

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

Registre a habilidade baseada em classe com AgentSkillsProvider:

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

Quando o [AgentSkillResource] atributo é aplicado a uma propriedade ou método, seu valor retornado é usado como o conteúdo do recurso quando o agente lê o recurso – use um método quando o conteúdo precisar ser computado em tempo de leitura. Quando [AgentSkillScript] é aplicado a um método, o método é invocado quando o agente chama o script. Use [Description] de System.ComponentModel para descrever cada recurso e script para o agente.

Observação

AgentClassSkill<T> também oferece suporte à substituição de Resources e Scripts como coleções para cenários em que a descoberta baseada em atributos não é adequada.

Gerador: cenários avançados de múltiplas fontes

Para cenários simples de origem única, use os AgentSkillsProvider construtores diretamente. Use AgentSkillsProviderBuilder quando precisar de qualquer um dos seguintes:

  • Tipos de habilidades mistas – combinam habilidades baseadas em arquivo, definidas por código (AgentInlineSkill) e baseadas em classe (AgentClassSkill) em um único provedor.
  • Filtragem de habilidades – incluir ou excluir habilidades usando um predicado.

Tipos de habilidades mistas

Combine todos os três tipos de competência em um provedor encadeando UseFileSkill, UseSkill e 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();

Filtragem de habilidades

Use UseFilter para incluir apenas as habilidades que atendem aos seus critérios , por exemplo, para carregar habilidades de um diretório compartilhado, mas excluir as experimentais:

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

Aprovação de script

Use AgentSkillsProviderOptions.ScriptApproval para bloquear toda a execução de script por trás da aprovação humana. Quando habilitado, o agente pausa e retorna uma solicitação de aprovação em vez de executar imediatamente:

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

Para habilitar a aprovação de script em um provedor configurado pelo construtor, use UseScriptApproval:

var skillsProvider = new AgentSkillsProviderBuilder()
    .UseFileSkill(Path.Combine(AppContext.BaseDirectory, "skills"))
    .UseScriptApproval(true)
    .Build();

Use require_script_approval=True no SkillsProvider para condicionar toda a execução de script à aprovação humana. Em vez de executar imediatamente, o agente pausa e retorna solicitações de aprovação:

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)

Quando um script é rejeitado (approved=False), o agente é informado de que o usuário recusou e pode responder adequadamente.

Prompt personalizado do sistema

Por padrão, o provedor de habilidades injeta um prompt do sistema que lista as habilidades disponíveis e instrui o agente a usar load_skill e read_skill_resource. Você pode personalizar este prompt:

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

Observação

O modelo personalizado deve conter os espaços reservados {skills} (lista de habilidades), {resource_instructions} (dica de ferramenta de recurso) e {script_instructions} (dica de ferramenta de script). Chaves literais devem ser escapadas como {{ e }}.

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

Observação

O modelo personalizado deve conter um {skills} espaço reservado onde a lista de habilidades é inserida e um {runner_instructions} espaço reservado em que as instruções relacionadas ao script são inseridas.

Comportamento de cache

Por padrão, as ferramentas de habilidade e as instruções são armazenadas em cache após o primeiro build. Defina DisableCaching = true em AgentSkillsProviderOptions para forçar uma recompilação a cada invocação:

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

Observação

Desabilitar o cache é útil durante o desenvolvimento quando o conteúdo da habilidade é alterado com frequência. Na produção, deixe o cache habilitado (o padrão) para melhorar o desempenho.

Injeção de dependência

Os representantes de script e recursos de habilidade podem declarar um IServiceProvider parâmetro que o Agent Framework injeta automaticamente. Isso permite que as habilidades resolvam os serviços de aplicativo , como clientes de banco de dados, configuração ou lógica de negócios, sem codificá-los na definição de habilidade.

Configuração

Registre seus serviços de aplicativo e passe o compilado IServiceProvider para o agente por meio do services parâmetro:

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

Habilidades definidas por código com DI

Declare IServiceProvider como um parâmetro em AddResource ou AddScript delegados – ele é resolvido e injetado automaticamente pelo framework quando o agente lê um recurso ou executa um script.

var distanceSkill = new AgentInlineSkill(
    name: "distance-converter",
    description: "Convert between distance units (miles and kilometers).",
    instructions: """
        Use this skill when the user asks to convert between miles and kilometers.
        1. Read the distance-table resource for conversion factors.
        2. Use the convert script to compute the result.
        """)
    .AddResource("distance-table", (IServiceProvider sp) =>
    {
        return sp.GetRequiredService<ConversionService>().GetDistanceTable();
    })
    .AddScript("convert", (double value, double factor, IServiceProvider sp) =>
    {
        return sp.GetRequiredService<ConversionService>().Convert(value, factor);
    });

Habilidades baseadas em classe com DI

Anotar métodos com [AgentSkillResource] ou [AgentSkillScript], e declarar um IServiceProvider parâmetro – a estrutura descobre esses membros por meio de reflexão e injeta o provedor de serviços automaticamente.

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

As habilidades baseadas em classe também podem resolver dependências através de seu construtor. Registre a classe de habilidade no ServiceCollection contêiner e resolva-a em vez de chamar new diretamente:

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

Isso é útil quando a classe de habilidade em si precisa de serviços injetados além do que os delegados de script e de recurso usam.

Funções de recurso e script que aceitam **kwargs recebem automaticamente argumentos de palavra-chave de tempo de execução passados para agent.run(). Isso permite que as funções de habilidade acessem o contexto do aplicativo , como configuração, identidade do usuário ou clientes de serviço, sem codificá-los na definição de habilidade.

Passando argumentos de tempo de execução

Passe function_invocation_kwargs para agent.run() fornecer argumentos de palavra-chave que a estrutura encaminha para funções de recurso e script:

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

Funções de recurso com kwargs

Quando uma função de recurso é declarada **kwargs, a estrutura encaminha os argumentos de palavra-chave de runtime sempre que o agente lê o recurso:

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

As funções de recurso sem **kwargs são chamadas sem argumentos e não recebem contexto de runtime.

Funções de script com kwargs

Quando uma função de script é declarada **kwargs, a estrutura encaminha os argumentos de palavra-chave de runtime junto com o args fornecido pelo agente:

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

O agente fornece value e factor através da chamada de ferramenta args; o aplicativo fornece precision através do function_invocation_kwargs. Funções de script sem **kwargs recebem apenas os argumentos fornecidos pelo agente.

Melhores práticas de segurança

As habilidades do agente devem ser tratadas como qualquer código de terceiros que você colocar em seu projeto. Como as instruções de habilidade são injetadas no contexto do agente – e as habilidades podem incluir scripts – aplicar o mesmo nível de revisão e governança que você faria a uma dependência de software livre é essencial.

  • Revisão antes do uso – leia todo o conteúdo de habilidade (SKILL.md, scripts e recursos) antes da implantação. Verifique se o comportamento real de um script corresponde à sua intenção declarada. Verifique se há instruções adversárias que tentam ignorar diretrizes de segurança, exfiltrar dados ou modificar arquivos de configuração do agente.
  • Confiança de origem – instale apenas habilidades de autores confiáveis ou colaboradores internos examinados. Prefira habilidades com procedência clara, controle de versão e manutenção ativa. Fique atento aos nomes de funcionalidades com erros de digitação que imitam pacotes populares.
  • Sandboxing – Executar habilidades que incluem scripts executáveis em ambientes isolados. Limite o sistema de arquivos, a rede e o acesso no nível do sistema apenas ao que a habilidade exige. Exigir confirmação explícita do usuário antes de executar operações potencialmente confidenciais.
  • Auditoria e registro de logs – registre quais funcionalidades são carregadas, quais recursos são lidos e quais scripts são executados. Isso oferece uma trilha de auditoria para rastrear o comportamento do agente de volta ao conteúdo de habilidade específico se algo der errado.

Quando usar habilidades versus fluxos de trabalho

As habilidades do agente e os fluxos de trabalho do Agent Framework estendem o que os agentes podem fazer, mas funcionam de maneiras fundamentalmente diferentes. Escolha a abordagem que melhor corresponda aos seus requisitos:

  • Controle – Com uma habilidade, a IA decide como executar as instruções. Isso é ideal quando você deseja que o agente seja criativo ou adaptável. Com um fluxo de trabalho, você define explicitamente o caminho de execução. Use fluxos de trabalho quando precisar de um comportamento determinístico e previsível.
  • Resiliência – uma habilidade ocorre em uma única rodada de agente. Se algo falhar, toda a operação deverá ser repetida. Os fluxos de trabalho dão suporte ao ponto de verificação, para que possam ser retomados da última etapa bem-sucedida após uma falha. Escolha fluxos de trabalho quando o custo de executar novamente todo o processo for alto.
  • Efeitos colaterais – as habilidades são adequadas quando as operações são idempotentes ou de baixo risco. Prefira fluxos de trabalho quando as etapas produzem efeitos colaterais (enviar emails, cobrar pagamentos) que não devem ser repetidos na repetição.
  • Complexidade – as habilidades são melhores para tarefas de domínio único e focadas que um agente pode lidar. Os fluxos de trabalho são mais adequados para processos de negócios de várias etapas que coordenam vários agentes, aprovações humanas ou integrações externas do sistema.

Tip

Como regra geral: se você quiser que a IA descubra como realizar uma tarefa, use uma habilidade. Se você precisar garantir quais etapas são executadas e em que ordem, use um fluxo de trabalho.

Próximas etapas