Oharra
Baimena behar duzu orria atzitzeko. Direktorioetan saioa has dezakezu edo haiek alda ditzakezu.
Baimena behar duzu orria atzitzeko. Direktorioak alda ditzakezu.
Las aptitudes del agente son paquetes portátiles de instrucciones, scripts y recursos que proporcionan a los agentes funcionalidades especializadas y conocimientos sobre dominios. Las aptitudes siguen una especificación abierta e implementan un patrón de divulgación progresiva para que los agentes carguen solo el contexto que necesitan, cuando lo necesiten.
Utilice habilidades del agente cuando las necesite:
- Empaquetar el dominio de la experiencia: capte conocimientos especializados (políticas de gastos, flujos de trabajo legales, pipelines de análisis de datos) como paquetes reutilizables y portátiles.
- Ampliar las funcionalidades del agente : proporcione nuevas capacidades a los agentes sin cambiar sus instrucciones principales.
- Garantizar la coherencia : convierta las tareas de varios pasos en flujos de trabajo repetibles y auditables.
- Habilitar la interoperabilidad : reutilice la misma aptitud en diferentes productos compatibles con aptitudes del agente.
Estructura de aptitudes
Una aptitud es un directorio que contiene un SKILL.md archivo con subdirectorios opcionales para los 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
El SKILL.md archivo debe contener el frontmatter de YAML seguido del contenido 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 | Obligatorio | Description |
|---|---|---|
name |
Sí | Máximo de 64 caracteres. Solo se permiten letras minúsculas, números y guiones. No debe iniciar ni terminar con un guión o contener guiones consecutivos. Debe coincidir con el nombre del directorio primario. |
description |
Sí | Qué hace la aptitud y cuándo usarla. Máximo de 1024 caracteres. Debe incluir palabras clave que ayuden a los agentes a identificar las tareas pertinentes. |
license |
No | Nombre de licencia o referencia a un archivo de licencia agrupado. |
compatibility |
No | Máximo de 500 caracteres. Indica los requisitos del entorno (producto previsto, paquetes del sistema, acceso a la red, etc.). |
metadata |
No | Mapeo arbitrario de clave-valor para metadatos adicionales. |
allowed-tools |
No | Lista delimitada por espacios de herramientas pre-aprobadas que la habilidad puede usar. Experimental: la compatibilidad puede variar entre las implementaciones del agente. |
El cuerpo de Markdown después de la frontmatter contiene las instrucciones de habilidades, instrucciones paso a paso, ejemplos de entradas y salidas, casos límite comunes o cualquier contenido que ayude al agente a realizar la tarea. Mantenga SKILL.md en menos de 500 líneas y mueva el material de referencia detallado a archivos independientes.
Divulgación progresiva
Las capacidades del agente usan un modelo de revelación progresiva a lo largo de cuatro etapas para reducir al mínimo el uso del contexto.
- Publicidad (~100 tokens por aptitud): los nombres y las descripciones de las aptitudes se insertan en la indicación del sistema al principio de cada ejecución, de modo que el agente sepa qué aptitudes están disponibles.
-
Cargar (< 5000 tokens recomendados): cuando una tarea coincide con el dominio de una aptitud, el agente llama a la
load_skillherramienta para recuperar el cuerpo completo del SKILL.md con instrucciones detalladas. -
Recursos de lectura (según sea necesario): el agente llama a la
read_skill_resourceherramienta para capturar archivos complementarios (referencias, plantillas, recursos) solo cuando sea necesario. -
Ejecutar scripts (según sea necesario): el agente llama a la herramienta
run_skill_scriptpara ejecutar scripts agrupados con una habilidad.
Este patrón mantiene la ventana de contexto del agente ligera al tiempo que proporciona acceso a conocimientos profundos de dominio bajo demanda.
Nota:
load_skill siempre se anuncia.
read_skill_resource se anuncia solo cuando al menos una habilidad tiene recursos.
run_skill_script solo se anuncia cuando al menos una habilidad tiene scripts.
Proporcionar aptitudes a un agente
AgentSkillsProvider (C#) y SkillsProvider (Python) son proveedores de contexto que hacen que las aptitudes estén disponibles para los agentes. Admiten tres orígenes de aptitudes:
-
Basado en archivos: habilidades detectadas a partir de
SKILL.mdarchivos en directorios del sistema de archivos -
Código definido: aptitudes definidas en línea en el código mediante
AgentInlineSkill(C#) oSkill(Python) -
Basado en clases — habilidades encapsuladas en una clase de C# derivada de
AgentClassSkill<T>(solo C#)
Para mezclar varios orígenes en un proveedor, use AgentSkillsProviderBuilder (solo C#, consulte Generador: escenarios avanzados de varios orígenes).
Habilidades basadas en archivos
Cree un AgentSkillsProvider que apunte a un directorio que contenga sus aptitudes y agréguelo a los proveedores de contexto del agente. Pase un ejecutor de scripts para habilitar la ejecución de scripts basados en archivos que se encuentran en directorios de aptitudes:
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);
Advertencia
DefaultAzureCredential es conveniente para el desarrollo, pero requiere una consideración cuidadosa en producción. En producción, considere usar una credencial específica (por ejemplo, ManagedIdentityCredential) para evitar problemas de latencia, sondeos de credenciales no deseados y posibles riesgos de seguridad de los mecanismos de respaldo.
Varios directorios de aptitudes
Puede apuntar el proveedor a un único directorio primario: cada subdirectorio que contiene un SKILL.md se detecta automáticamente como una habilidad:
var skillsProvider = new AgentSkillsProvider(
Path.Combine(AppContext.BaseDirectory, "all-skills"));
O bien, pase una lista de rutas de acceso para buscar varios directorios raíz:
var skillsProvider = new AgentSkillsProvider(
[
Path.Combine(AppContext.BaseDirectory, "company-skills"),
Path.Combine(AppContext.BaseDirectory, "team-skills"),
]);
El proveedor busca hasta dos niveles en profundidad.
Personalización de la detección de recursos
De forma predeterminada, el proveedor reconoce los recursos con extensiones .md, .json, .yaml, .yml, .csv, .xml y .txt en los subdirectorios references y assets. Use AgentFileSkillsSourceOptions para cambiar estos valores predeterminados:
var fileOptions = new AgentFileSkillsSourceOptions
{
AllowedResourceExtensions = [".md", ".txt"],
ResourceDirectories = ["docs", "templates"],
};
var skillsProvider = new AgentSkillsProvider(
Path.Combine(AppContext.BaseDirectory, "skills"),
fileOptions: fileOptions);
Ejecución de scripts
Pase SubprocessScriptRunner.RunAsync como segundo argumento a AgentSkillsProvider para habilitar la ejecución de scripts basados en archivos:
var skillsProvider = new AgentSkillsProvider(
Path.Combine(AppContext.BaseDirectory, "skills"),
SubprocessScriptRunner.RunAsync);
SubprocessScriptRunner.RunAsync es aproximadamente equivalente a lo siguiente:
// 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();
}
El ejecutor ejecuta cada script detectado como un subproceso local y reenvía los argumentos JSON proporcionados por el agente como marcas de línea de comandos.
Advertencia
SubprocessScriptRunner solo se proporciona con fines de demostración. Para su uso en producción, considere la posibilidad de agregar:
- Sandboxing (por ejemplo, contenedores o entornos de ejecución aislados)
- Límites de recursos (CPU, memoria, tiempo de espera del reloj)
- Validación de entrada y lista de permitidos de scripts ejecutables
- Registros estructurados y seguimientos de auditoría
Personalización de la detección de scripts
De forma predeterminada, el proveedor reconoce scripts con extensiones.py, , .js.sh, .ps1, .cs, y .csx en el scripts subdirectorio. Use AgentFileSkillsSourceOptions para cambiar estos valores predeterminados:
Pase AgentFileSkillsSourceOptions al AgentSkillsProvider constructor o al UseFileSkill / UseFileSkills generador:
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 basadas en archivos
Cree un SkillsProvider que apunte a un directorio que contenga sus aptitudes y agréguelo a los proveedores de contexto del 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],
)
Varios directorios de aptitudes
Puede dirigir al proveedor a una sola carpeta principal: cada subcarpeta que contiene un SKILL.md se detecta automáticamente como una habilidad.
skills_provider = SkillsProvider(
skill_paths=Path(__file__).parent / "all-skills"
)
O bien, pase una lista de rutas de acceso para buscar varios directorios raíz:
skills_provider = SkillsProvider(
skill_paths=[
Path(__file__).parent / "company-skills",
Path(__file__).parent / "team-skills",
]
)
El proveedor busca hasta dos niveles en profundidad.
Personalización de la detección de recursos
De forma predeterminada, SkillsProvider reconoce los recursos con extensiones .md, , .json.yaml, .yml, .csv, .xmly .txt. Examina todos los subdirectorios dentro de cada carpeta de aptitudes. Pase resource_extensions para cambiar los tipos de archivo reconocidos:
skills_provider = SkillsProvider(
skill_paths=Path(__file__).parent / "skills",
resource_extensions=(".md", ".txt"),
)
Ejecución de scripts
Para habilitar la ejecución de scripts basados en archivos, pase un script_runner a SkillsProvider. Se puede usar cualquier función que sea una llamada síncrona o asíncrona que satisfaga el protocolo SkillScriptRunner.
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,
)
El corredor recibe el objeto resuelto Skill, SkillScript y un diccionario opcional args. Los scripts basados en archivos se detectan automáticamente a partir de .py archivos en directorios de aptitudes.
Advertencia
El runner arriba solo se proporciona con fines de demostración. Para su uso en producción, considere la posibilidad de agregar:
- Sandboxing (por ejemplo, contenedores,
seccomp, ofirejail) - Límites de recursos (CPU, memoria, tiempo de espera del reloj)
- Validación de entrada y lista de permitidos de scripts ejecutables
- Registros estructurados y seguimientos de auditoría
Nota:
Si se proporcionan habilidades basadas en archivos con scripts, pero no se establece script_runner, SkillsProvider genera un ValueError.
Aptitudes definidas por código
Además de las aptitudes basadas en archivos detectadas a partir de SKILL.md archivos, puede definir aptitudes por completo en el código mediante AgentInlineSkill. Las aptitudes definidas por código son útiles cuando:
- El contenido de la aptitud se genera dinámicamente (por ejemplo, leer desde una base de datos o un entorno).
- Quiere mantener las definiciones de habilidades junto con el código de aplicación que las usa.
- Necesita recursos que ejecuten lógica en tiempo de lectura en lugar de servir archivos estáticos.
Aptitud de código básico
Cree un AgentInlineSkill con un nombre, una descripción e instrucciones. Adjuntar recursos mediante .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
Pase un delegado de fábrica a .AddResource() para calcular el contenido en tiempo de ejecución. El delegado se invoca cada vez que el agente lee el 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 un delegado como un script ejecutable. Los scripts definidos por código se ejecutan en proceso como llamadas de delegado directas. No se necesita ningún ejecutor de scripts. Los parámetros tipados del delegado se convierten automáticamente en un esquema JSON que el agente utiliza para pasar 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);
Nota:
Para combinar aptitudes definidas por código con aptitudes basadas en archivos o basadas en clases en un único proveedor, consulte AgentSkillsProviderBuilderBuilder: escenarios avanzados de varios orígenes.
Además de las competencias basadas en archivos detectadas a partir de SKILL.md, puede definir competencias puramente en código Python. Las aptitudes definidas por código son útiles cuando:
- El contenido de la aptitud se genera dinámicamente (por ejemplo, leer desde una base de datos o un entorno).
- Quiere mantener las definiciones de habilidades junto con el código de aplicación que las usa.
- Necesita recursos que ejecuten lógica en tiempo de lectura en lugar de servir archivos estáticos.
Aptitud de código básico
Cree una Skill instancia con un nombre, una descripción y un contenido de instrucciones. Opcionalmente, adjunte SkillResource instancias con contenido 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 el @skill.resource decorador para registrar una función como un recurso. La función se llama cada vez que el agente lee el recurso, por lo que puede devolver datos actualizados. Se admiten las funciones de sincronización y asincrónica:
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)"
Cuando el decorador se usa sin argumentos (@skill.resource), el nombre de la función se convierte en el nombre del recurso y docstring se convierte en la descripción. Use @skill.resource(name="...", description="...") para establecerlos explícitamente.
Scripts definidos por código
Use el decorador @skill.script para registrar una función como un script ejecutable en una habilidad. Los scripts definidos por código se ejecutan en proceso y no requieren un ejecutor de script. Se admiten las funciones de sincronización y asincrónica:
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})
Cuando el decorador se usa sin argumentos (@skill.script), el nombre de la función se convierte en el nombre del script y docstring se convierte en la descripción. Los parámetros tipificados de la función se convierten automáticamente en un esquema JSON que el agente utiliza para el paso de argumentos.
Combinación de aptitudes basadas en archivos y definidas por código
Pase tanto skill_paths como skills a un solo SkillsProvider. Primero se detectan aptitudes basadas en archivos; si una aptitud definida por código tiene el mismo nombre que una aptitud basada en archivos existente, se omite la aptitud definida por código:
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 basadas en clases
Las aptitudes basadas en clases permiten agrupar todos los componentes de aptitud (nombre, descripción, instrucciones, recursos y scripts) en una sola clase de C#. Derive de AgentClassSkill<T> (donde T es la clase ), anote las propiedades con [AgentSkillResource] y los métodos con [AgentSkillScript] para la detección 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 });
}
}
Registra la habilidad basada en clases con AgentSkillsProvider
var skill = new UnitConverterSkill();
var skillsProvider = new AgentSkillsProvider(skill);
Cuando el [AgentSkillResource] atributo se aplica a una propiedad o método, su valor devuelto se usa como contenido del recurso cuando el agente lee el recurso, use un método cuando el contenido se necesite calcular en tiempo de lectura. Cuando [AgentSkillScript] se aplica a un método, se invoca el método cuando el agente llama al script. Use [Description] desde System.ComponentModel para describir cada recurso y script para el agente.
Nota:
AgentClassSkill<T> también admite la sobrescritura de Resources y Scripts como colecciones para escenarios en los que la detección basada en atributos no es adecuada.
Generador: escenarios avanzados de varios orígenes
Para escenarios sencillos y de origen único, use los AgentSkillsProvider constructores directamente. Use AgentSkillsProviderBuilder cuando necesite cualquiera de las siguientes opciones:
-
Tipos de aptitudes mixtas: combine aptitudes basadas en archivos, definidas por código (
AgentInlineSkill) y basadas en clases (AgentClassSkill) en un único proveedor. - Filtrado de aptitudes : incluya o excluya aptitudes mediante un predicado.
Tipos de aptitudes mixtas
Combina los tres tipos de habilidades de un proveedor mediante el encadenamiento de UseFileSkill, UseSkill y 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();
Filtrado de aptitudes
Use UseFilter para incluir solo las aptitudes que cumplan los criterios, por ejemplo, para cargar aptitudes desde un directorio compartido, pero excluir las experimentales:
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();
Aprobación de scripts
Utiliza AgentSkillsProviderOptions.ScriptApproval para bloquear toda la ejecución de scripts hasta que haya aprobación humana. Cuando está habilitado, el agente pausa y devuelve una solicitud de aprobación en lugar de ejecutarse inmediatamente:
var skillsProvider = new AgentSkillsProvider(
skillPath: Path.Combine(AppContext.BaseDirectory, "skills"),
options: new AgentSkillsProviderOptions
{
ScriptApproval = true,
});
Para habilitar la aprobación de scripts en un proveedor configurado por el generador, use UseScriptApproval:
var skillsProvider = new AgentSkillsProviderBuilder()
.UseFileSkill(Path.Combine(AppContext.BaseDirectory, "skills"))
.UseScriptApproval(true)
.Build();
Use require_script_approval=True en SkillsProvider para controlar toda la ejecución de scripts con aprobación humana. En lugar de ejecutarse inmediatamente, el agente pausa y devuelve solicitudes de aprobación:
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)
Cuando se rechaza un script (approved=False), se informa al agente de que el usuario ha rechazado y que puede responder en consecuencia.
Mensaje del sistema personalizado
De forma predeterminada, el proveedor de aptitudes inserta una solicitud del sistema que enumera las aptitudes disponibles e indica al agente que use load_skill y read_skill_resource. Puede personalizar este mensaje:
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}
"""
});
Nota:
La plantilla personalizada debe contener los marcadores de posición {skills} (lista de habilidades), {resource_instructions} (sugerencia de herramienta de recursos) y {script_instructions} (sugerencia de herramienta de script). Las llaves literales deben ser de escape como {{ y }}.
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."
),
)
Nota:
La plantilla personalizada debe contener un {skills} marcador de posición donde se inserta la lista de aptitudes y un {runner_instructions} marcador de posición donde se insertan instrucciones relacionadas con scripts.
Comportamiento del almacenamiento en caché
De forma predeterminada, las herramientas de aptitud y las instrucciones se almacenan en caché después de la primera compilación. Establezca DisableCaching = true en AgentSkillsProviderOptions para forzar una recompilación en cada invocación:
var skillsProvider = new AgentSkillsProvider(
Path.Combine(AppContext.BaseDirectory, "skills"),
options: new AgentSkillsProviderOptions
{
DisableCaching = true,
});
Nota:
Deshabilitar el almacenamiento en caché es útil durante el desarrollo cuando el contenido de la aptitud cambia con frecuencia. En producción, deje habilitado el almacenamiento en caché (valor predeterminado) para mejorar el rendimiento.
Inserción de dependencia
Los delegados de script y de recursos de aptitud pueden incluir un parámetro IServiceProvider que el Framework del Agente inserta automáticamente. Esto permite que las aptitudes resuelvan los servicios de aplicación , como clientes de base de datos, configuración o lógica empresarial, sin codificarlos de forma rígida en la definición de la aptitud.
Configuración
Registre los servicios de aplicación y pase el compilado IServiceProvider al agente mediante el parámetro services.
using Microsoft.Extensions.DependencyInjection;
// Register application services
ServiceCollection services = new();
services.AddSingleton<ConversionService>();
IServiceProvider serviceProvider = services.BuildServiceProvider();
// Create the agent and pass the service provider
AIAgent agent = new AzureOpenAIClient(new Uri(endpoint), new DefaultAzureCredential())
.GetResponsesClient()
.AsAIAgent(
options: new ChatClientAgentOptions
{
Name = "ConverterAgent",
ChatOptions = new() { Instructions = "You are a helpful assistant." },
AIContextProviders = [skillsProvider],
},
model: deploymentName,
services: serviceProvider);
Aptitudes definidas por código con DI
Declarar IServiceProvider como parámetro en los delegados AddResource o AddScript: el framework lo resuelve e inyecta automáticamente cuando el agente lee un recurso o ejecuta un 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 basadas en clases con inyección de dependencias
Anotación de métodos con [AgentSkillResource] o [AgentSkillScript] y declaración de un IServiceProvider parámetro: el marco detecta estos miembros a través de la reflexión e inserta automáticamente el proveedor de servicios:
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);
}
}
Sugerencia
Las habilidades basadas en clases también pueden resolver las dependencias a través de su constructor. Registre la clase de aptitud en ServiceCollection y la resuelva desde el contenedor en lugar de llamar directamente a new :
services.AddSingleton<WeightConverterSkill>();
var weightSkill = serviceProvider.GetRequiredService<WeightConverterSkill>();
Esto resulta útil cuando la propia clase de habilidad necesita servicios inyectados más allá de aquellos utilizados por los delegados de recursos y scripts.
Las funciones de recursos y scripts que aceptan **kwargs reciben automáticamente los argumentos de palabras clave en tiempo de ejecución que se pasan a agent.run(). Esto permite que las funciones de aptitud accedan al contexto de la aplicación , como la configuración, la identidad del usuario o los clientes de servicio, sin codificarlos de forma rígida en la definición de la aptitud.
Pasar argumentos en tiempo de ejecución
Pase function_invocation_kwargs a agent.run() para proporcionar argumentos de palabra clave que el marco reenvía a las funciones de recurso y script:
response = await agent.run(
"How many kilometers is 26.2 miles?",
function_invocation_kwargs={"precision": 2, "user_id": "alice"},
)
Funciones de recursos con kwargs
Cuando una función de recurso declara **kwargs, el marco reenvía los argumentos de palabra clave en tiempo de ejecución cada vez que el agente lee el 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}"
Las funciones de recursos sin **kwargs se llaman sin argumentos y no reciben contexto en tiempo de ejecución.
Funciones de script con kwargs
Cuando una función de script declara **kwargs, el marco reenvía los argumentos de palabra clave en tiempo de ejecución junto con el args proporcionado por el 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})
El agente proporciona value y factor a través de la llamada a la herramienta args; la aplicación proporciona precision a través de function_invocation_kwargs. Funciones de script sin **kwargs reciben solo los argumentos que el agente proporciona.
Procedimientos recomendados de seguridad
Las habilidades del agente deben tratarse como cualquier código de terceros que incorpore en su proyecto. Dado que las instrucciones de habilidades se insertan en el contexto del agente, y las habilidades pueden incluir scripts, es esencial aplicar el mismo nivel de revisión y gobernanza que aplicaría a una dependencia de código abierto.
-
Revisar antes de usar : lea todo el contenido de las aptitudes (
SKILL.md, scripts y recursos) antes de la implementación. Compruebe que el comportamiento real de un script coincide con su intención indicada. Busque instrucciones adversarias que intenten omitir las directrices de seguridad, exfiltrar datos o modificar archivos de configuración de agentes. - Confianza de origen : instale solo aptitudes de autores de confianza o colaboradores internos examinados. Prefiere aptitudes con un claro origen, control de versiones y mantenimiento activo. Esté atento a los nombres de habilidades suplantados que imitan paquetes de software populares.
- Sandboxing — Ejecute habilidades que incluyan scripts ejecutables en entornos aislados. Limite el acceso del sistema de archivos, la red y el nivel de sistema solo a lo que requiere la aptitud. Requerir confirmación explícita del usuario antes de ejecutar operaciones potencialmente confidenciales.
- Auditoría y registro : registre qué aptitudes se cargan, qué recursos se leen y qué scripts se ejecutan. Esto le proporciona una pista de auditoría para rastrear el comportamiento del agente hasta contenido específico de habilidades si algo sale mal.
Cuándo usar aptitudes frente a flujos de trabajo
Los flujos de trabajo de Agent Skills y Agent Framework amplían lo que pueden hacer los agentes, pero funcionan de maneras fundamentalmente diferentes. Elija el enfoque que mejor se adapte a sus requisitos:
- Control : con una aptitud, la inteligencia artificial decide cómo ejecutar las instrucciones. Esto es ideal cuando quieres que el agente sea creativo o adaptable. Con un flujo de trabajo, se define explícitamente la trayectoria de ejecución. Use flujos de trabajo cuando necesite un comportamiento determinista y predecible.
- Resistencia — Se ejecuta una habilidad dentro de un solo turno de agente. Si se produce un error en algo, se debe reintentar toda la operación. Los flujos de trabajo admiten puntos de control, por lo que pueden reanudarse desde el último paso exitoso después de una falla. Elija flujos de trabajo cuando el costo de volver a ejecutar todo el proceso sea alto.
- Efectos secundarios : las aptitudes son adecuadas cuando las operaciones son idempotentes o de bajo riesgo. Prefiere flujos de trabajo cuando los pasos producen efectos secundarios (enviar correos electrónicos, cobrar pagos) que no deben repetirse en el reintento.
- Complejidad : las aptitudes son las mejores para las tareas centradas y de dominio único que un agente puede controlar. Los flujos de trabajo son más adecuados para los procesos empresariales de varios pasos que coordinan varios agentes, aprobaciones humanas o integraciones de sistemas externos.
Sugerencia
Como regla general: si desea que la inteligencia artificial descubra cómo realizar una tarea, use una aptitud. Si necesita garantizar qué pasos se ejecutan y en qué orden, use un flujo de trabajo.