مهارات الوكيل

مهارات العامل هي حزم محمولة من التعليمات والبرامج النصية والموارد التي تمنح الوكلاء قدرات متخصصة وخبرة في المجال. تتبع المهارات مواصفات مفتوحة وتنفذ نمط كشف تدريجي حتى يقوم الوكلاء بتحميل السياق الذي يحتاجون إليه فقط، عندما يحتاجون إليه.

استخدم مهارات العامل عندما تريد:

  • خبرة مجال الحزمة - التقاط المعرفة المتخصصة (سياسات المصروفات، سير العمل القانوني، مسارات تحليل البيانات) كحزم قابلة لإعادة الاستخدام وقابلة للنقل.
  • توسيع قدرات الوكيل - منح الوكلاء قدرات جديدة دون تغيير تعليماتهم الأساسية.
  • ضمان التناسق - تحويل المهام متعددة الخطوات إلى مهام سير عمل قابلة للتكرار وقابلة للتدقيق.
  • تمكين إمكانية التشغيل التفاعلي - أعد استخدام نفس المهارة عبر منتجات مختلفة متوافقة مع مهارات العامل.

هيكل المهارات

المهارة هي دليل يحتوي على SKILL.md ملف بدلائل فرعية اختيارية للموارد:

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

SKILL.md يجب أن يحتوي الملف على خريطة YAML الأمامية متبوعة بمحتوى 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"
---
الحقل مطلوب Description
name Yes بحد أقصى 64 حرفا. الحروف الصغيرة والأرقام والشرطات فقط. يجب ألا تبدأ أو تنتهي بشرطة أو تحتوي على شرطات متتالية. يجب أن يتطابق مع اسم الدليل الأصل.
description Yes ما تفعله المهارة ومتى تستخدمها. بحد أقصى 1024 حرفا. يجب أن تتضمن الكلمات الأساسية التي تساعد الوكلاء على تحديد المهام ذات الصلة.
license No اسم الترخيص أو الإشارة إلى ملف ترخيص مرفق.
compatibility No 500 حرف كحد أقصى. يشير إلى متطلبات البيئة (المنتج المقصود، وحزم النظام، والوصول إلى الشبكة، وما إلى ذلك).
metadata No تعيين قيمة المفتاح العشوائي لبيانات التعريف الإضافية.
allowed-tools No قائمة محددة بمسافات للأدوات المعتمدة مسبقا التي قد تستخدمها المهارة. تجريبي - قد يختلف الدعم بين تطبيقات الوكيل.

يجب أن تستخدم أسماء الحقول ذات المستوى الأعلى التي تم التعرف عليها التدقيق الإملائي بالأحرف الصغيرة الموضحة في الجدول ويمكن أن تظهر مرة واحدة فقط. YAML غير صحيح أو حقول مكررة تم التعرف عليها أو غلاف حقل غير صحيح أو مجموعة حيث من المتوقع أن يمنع حقل عددي المهارة من التحميل. يتم تجاهل حقول المستوى الأعلى غير المعروفة للتوافق مع إعادة التوجيه.

تعامل metadata Python أحمال أرشيف MCP والمستندة إلى الملفات المفاتيح كسلاسل حساسة لحالة الأحرف. يحتفظ التكرار الدقيق بالقيمة الصالحة الأولى ويسجل تحذيرا. يتم تخطي إدخالات بيانات التعريف غير الصالحة، بما في ذلك المجموعات المتداخلة، مع تحذير بدلا من منع المهارة من التحميل.

يحتوي نص markdown بعد الواجهة الأمامية على إرشادات المهارة - إرشادات خطوة بخطوة، أو أمثلة على المدخلات والمخرجات، أو حالات الحافة الشائعة، أو أي محتوى يساعد العامل على تنفيذ المهمة. احتفظ ب SKILL.md أقل من 500 سطر وانقل المواد المرجعية التفصيلية لفصل الملفات.

الكشف التدريجي

تستخدم مهارات العامل نمط كشف تدريجي من أربع مراحل لتقليل استخدام السياق:

  1. الإعلان (~100 رمز مميز لكل مهارة) - يتم إدخال أسماء المهارة والأوصاف في مطالبة النظام في بداية كل تشغيل، حتى يعرف العامل المهارات المتوفرة.
  2. تحميل (< يوصى باستخدام 5000 رمز مميز) - عندما تتطابق المهمة مع مجال المهارة، يستدعي load_skill العامل الأداة لاسترداد نص SKILL.md الكامل مع إرشادات مفصلة.
  3. قراءة الموارد (حسب الحاجة) - يستدعي read_skill_resource العامل الأداة لجلب الملفات التكميلية (المراجع والقوالب والأصول) فقط عند الحاجة.
  4. تشغيل البرامج النصية (حسب الحاجة) - يستدعي run_skill_script العامل الأداة لتنفيذ البرامج النصية المجمعة بمهارة.

يحافظ هذا النمط على نافذة سياق العامل الهزيلة مع منحه إمكانية الوصول إلى معرفة المجال العميقة عند الطلب.

Note

load_skill يتم الإعلان عنه دائما. read_skill_resource يتم الإعلان عنه فقط عندما يكون لمهارة واحدة على الأقل موارد. run_skill_script يتم الإعلان عنه فقط عندما تحتوي مهارة واحدة على الأقل على برامج نصية.

توفير المهارات للوكيل

يتضمن العمل مع المهارات ثلاث كتل بناء:

  • الموفر - AgentSkillsProvider (C#) أو SkillsProvider (Python) هو موفر سياق يعرض المهارات للعامل. يعلن عن المهارات المتاحة في موجه النظام ويسجل الأدوات التي يستخدمها العامل لتحميل المهارات وقراءة الموارد وتشغيل البرامج النصية.
  • المصادر - مصدر يوفر المهارات للموفر. يمكن أن تأتي المهارات من عدة أنواع من المصادر:
    • المستندة إلى الملفات - المهارات المكتشفة من SKILL.md الملفات في دلائل نظام الملفات.
    • التعليمات البرمجية المعرفة - المهارات المعرفة المضمنة في التعليمات البرمجية باستخدام AgentInlineSkill (C#) أو InlineSkill (Python).
    • المستندة إلى الفئة - المهارات المغلفة في فئة مشتقة من AgentClassSkill<T> (C#) أو ClassSkill (Python).
    • المستندة إلى MCP - المهارات المكتشفة من خوادم MCP (بروتوكول سياق النموذج) عبر UseMcpSkills (C#) أو MCPSkillsSource (Python).
  • منشئ - AgentSkillsProviderBuilder (C#) تجميع مصادر متعددة في موفر واحد، وتطبيق التجميع، وإلغاء التكرار، والتخزين المؤقت، والتصفية الاختيارية. في Python، قم بإنشاء فئات المصدر مثل AggregatingSkillsSourceو FilteringSkillsSourceو DeduplicatingSkillsSource مباشرة.

توضح الأقسام التالية كيفية إنشاء مهارات من كل نوع مصدر، ثم كيفية دمج المصادر وإنشاء موفر منها.

استخدام مهارات العامل مع Harness Agent

باستخدام وكيل عادي، قم بإنشاء موفر مهارات، وإضافته إلى موفري سياق العامل، وإنشاء برنامج وسيط للموافقة على الأدوات عند الحاجة. يمكن ل Harness Agent إنشاء الموفر أو تضمينه كجزء من الإعداد القياسي الخاص به.

HarnessAgent يتضمن AgentSkillsProvider بشكل افتراضي ويكتشف المهارات المستندة إلى الملفات من Directory.GetCurrentDirectory(). لاستخدام مصدر مختلف، قم بتعيين HarnessAgentOptions.AgentSkillsSource:

using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;

AIAgent agent = chatClient.AsHarnessAgent(new HarnessAgentOptions
{
    AgentSkillsSource = new AgentFileSkillsSource(
        Path.Combine(AppContext.BaseDirectory, "skills")),
    ToolApprovalAgentOptions = new ToolApprovalAgentOptions
    {
        // Auto-approve load_skill and read_skill_resource, but not run_skill_script.
        AutoApprovalRules = [AgentSkillsProvider.ReadOnlyToolsAutoApprovalRule],
    },
    ChatOptions = new ChatOptions
    {
        Instructions = "Use the available skills when they match the task.",
    },
});

DisableAgentSkillsProvider يقيم افتراضيا إلى false. قم بتعيينه إلى true لإزالة الموفر المضمن. AgentSkillsSource يستبدل مصدر الدليل الحالي الافتراضي، ولكنه لا يعرض AgentSkillsProviderOptions. إذا كنت بحاجة إلى خيارات الموفر مثل DisableLoadSkillApproval، ف قم بتعطيل الموفر المضمن وأضف المكون AgentSkillsProvider من خلال HarnessAgentOptions.AIContextProviders.

لتشغيل البرامج النصية من المهارات المستندة إلى الملفات، مرر مفوضا AgentFileSkillScriptRunner كوسيطة المنشئ الثانية AgentFileSkillsSource . بدون مشغل، يفشل تنفيذ البرنامج النصي عند الطلب.

تتطلب جميع أدوات المهارات الثلاث الموافقة بشكل افتراضي. يتم تمكين البرنامج الوسيط للموافقة على أداة harness بشكل افتراضي، ولكن خياراته الافتراضية لا توافق تلقائيا على أي أداة. استخدم AgentSkillsProvider.ReadOnlyToolsAutoApprovalRule أو AgentSkillsProvider.AllToolsAutoApprovalRule فقط لمصادر المهارات التي تثق بها.

مهارات العامل هي الاشتراك في create_harness_agent. تمرير skills_paths للاكتشاف المستند إلى الملفات:

from pathlib import Path

from agent_framework import SkillsProvider, create_harness_agent

agent = create_harness_agent(
    client=client,
    agent_instructions="Use the available skills when they match the task.",
    skills_paths=Path(__file__).parent / "skills",
    # Auto-approve load_skill and read_skill_resource, but not run_skill_script.
    auto_approval_rules=[SkillsProvider.read_only_tools_auto_approval_rule],
)

session = agent.create_session()
result = await agent.run("Use the appropriate skill for this task.", session=session)

skills_paths يقبل واحدا str أو Path، أو تسلسلا منها. عندما يكون None كل من skills_provider و skills_paths (الإعدادات الافتراضية)، لا يضيف SkillsProviderالتسخير . يمكنك دمج كلا المعلمتين لتضمين المهارات المعرفة من التعليمات البرمجية والمستندة إلى الملفات.

يتم skills_paths إنشاء الاختصار SkillsProvider.from_paths() بدون script_runner. إذا كانت المهارات المستندة إلى الملفات تحتاج إلى تنفيذ البرامج النصية، فبادر بإنشاء الموفر بنفسك مع SkillsProvider.from_paths(..., script_runner=...) وتمريره من خلال skills_provider.

تتطلب جميع أدوات المهارات الثلاث الموافقة بشكل افتراضي. نظرا لتثبيت التسخير ToolApprovalMiddleware بشكل افتراضي، قم بتمرير جلسة عمل على كل تشغيل واستخدام auto_approval_rules لنهج الموافقة الموثوق بها للقراءة فقط أو جميع الأدوات.

لا يتوفر حاليا تسخير Go المحزم. سجل موفر مهارات Go في agent.Config.ContextProviders وقم بإنشاء برنامج وسيط للموافقة مباشرة.

المهارات المستندة إلى الملفات

AgentSkillsProvider أنشئ دليلا يشير إلى دليل يحتوي على مهاراتك، وأضفه إلى موفري سياق العامل. قم بتمرير مشغل البرنامج النصي لتمكين تنفيذ البرامج النصية المستندة إلى الملفات الموجودة في دلائل المهارات:

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

تحذير

DefaultAzureCredential مناسب للتنمية ولكنه يتطلب دراسة متأنية في الإنتاج. في الإنتاج، ضع في اعتبارك استخدام بيانات اعتماد محددة (على سبيل المثال، ManagedIdentityCredential) لتجنب مشكلات زمن الانتقال، وبحث بيانات الاعتماد غير المقصودة، والمخاطر الأمنية المحتملة من الآليات الاحتياطية.

دلائل مهارات متعددة

يمكنك توجيه الموفر إلى دليل أصل واحد - يتم اكتشاف كل دليل فرعي يحتوي على SKILL.md كمهارة تلقائيا:

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

أو قم بتمرير قائمة المسارات للبحث في دلائل جذر متعددة:

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

يبحث الموفر حتى مستويين عميقين.

تخصيص اكتشاف الموارد والبرامج النصية

بشكل افتراضي، يتعرف الموفر على الموارد ذات الملحقات .mdو .yaml.xml.csv.yml.jsonو .txt البرامج النصية مع الملحقات .pyو..csx.js.sh.ps1.cs يبحث ما يصل إلى مستويين في عمق كل دليل مهارة. استخدم 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 وتلقي ScriptFilterAgentFileSkillFilterContext مع اسم المهارة والمسار النسبي للملف، مما يتيح لك تقييد الملفات حسب الموقع أو اصطلاح التسمية أو أي منطق مخصص.

تنفيذ البرنامج النصي

مرر SubprocessScriptRunner.RunAsync كمشغل البرنامج النصي لتمكين تنفيذ البرامج النصية المستندة إلى الملف:

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

SubprocessScriptRunner.RunAsync يعادل تقريبا ما يلي:

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

يشغل المشغل كل برنامج نصي مكتشف ك معالجة فرعية محلية. تتوقع البرامج النصية المستندة إلى الملفات وسيطات كصفيف JSON من السلاسل - يصبح كل عنصر صفيف وسيطة سطر أوامر موضعية.

تحذير

SubprocessScriptRunner يتم توفيره لأغراض العرض التوضيحي فقط. لاستخدام الإنتاج، ضع في اعتبارك إضافة:

  • بيئة الاختبار المعزولة (على سبيل المثال، الحاويات أو بيئات التنفيذ المعزولة)
  • حدود الموارد (وحدة المعالجة المركزية والذاكرة ومهلة ساعة الحائط)
  • التحقق من صحة الإدخال وإدراج النصوص القابلة للتنفيذ
  • سجلات التسجيل والتدقيق المنظمة

المهارات المستندة إلى الملفات

SkillsProvider.from_paths() استخدم المصنع لاكتشاف المهارات من الدلائل التي تحتوي على SKILL.md ملفات، وإضافة الموفر إلى موفري سياق العامل:

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

دلائل مهارات متعددة

يمكنك توجيه الموفر إلى دليل أصل واحد - يتم اكتشاف كل دليل فرعي يحتوي على SKILL.md كمهارة تلقائيا:

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

أو قم بتمرير قائمة المسارات للبحث في دلائل جذر متعددة:

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

يبحث الموفر حتى مستويين عميقين.

تخصيص اكتشاف الموارد والبرامج النصية

بشكل افتراضي، يتم اكتشاف الموارد من references/ الدلائل الفرعية والدلائل assets/ الفرعية والبرامج النصية من scripts/، وفقا للمواصفات agentskills.io. ملحقات الموارد المعترف بها هي .mdو .json.yamlو .ymlو .csv.xmlو..txt يبحث ما يصل إلى مستويين في عمق كل دليل مهارة. استخدم resource_extensionsو script_extensionssearch_depthresource_filterو و script_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 تتلقى دالات التقييم و script_filter اسم المهارة والمسار النسبي للملف، مما يتيح لك تقييد الملفات حسب الموقع أو اصطلاح التسمية أو أي منطق مخصص. يستخدم "." لتضمين الملفات على مستوى جذر المهارة بالإضافة إلى الدلائل الفرعية.

تنفيذ البرنامج النصي

لتمكين تنفيذ البرامج النصية المستندة إلى الملف، مرر script_runner إلى SkillsProvider.from_paths(). يمكن استخدام أي مزامنة أو غير متزامنة تفي بالبروتوكول SkillScriptRunner :

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

يتلقى المشغل الوسيطة التي تم حلها FileSkillFileSkillScriptو و و اختياريةargs. تتوقع البرامج النصية المستندة إلى الملفات وسيطات كصفيف JSON من السلاسل - يصبح كل عنصر صفيف وسيطة سطر أوامر موضعية. يتم اكتشاف البرامج النصية تلقائيا من .py الملفات الموجودة scripts/ في الدليل الفرعي لكل دليل مهارة.

للوصول إلى قيم وقت تشغيل المضيف، أضف معلمة مشغل واحدة قابلة للربط بالكلمة الأساسية مشروحة مباشرة ك FunctionInvocationContext أو FunctionInvocationContext | None. يجب أن تحتوي المعلمة على قيمة افتراضية ويجب ألا تحل محل المعلمات الموجودة skillأو scriptأو .args جعله الكلمة الأساسية فقط هو الشكل الموصى به. يقوم الموفر بإدخال السياق، ولكنه لا يضيف قيمه إلى وسيطات العملية الفرعية أو البيئة.

تحذير

يتم توفير المشغل أعلاه لأغراض العرض التوضيحي فقط. لاستخدام الإنتاج، ضع في اعتبارك إضافة:

  • وضع الحماية (على سبيل المثال، الحاويات أو seccompأو firejail)
  • حدود الموارد (وحدة المعالجة المركزية والذاكرة ومهلة ساعة الحائط)
  • التحقق من صحة الإدخال وإدراج النصوص القابلة للتنفيذ
  • سجلات التسجيل والتدقيق المنظمة

Note

إذا تم توفير المهارات المستندة إلى الملفات مع البرامج النصية ولكن لم يتم تعيينها script_runner ، SkillsProvider يثير خطأ عند محاولة تنفيذ البرنامج النصي.

المهارات المستندة إلى الملفات

يدعم وكلاء Go المهارات من خلال الحزمة agent/skills . تتبع المهارات نفس نمط الكشف التدريجي: الإعلان -> التحميل -> قراءة الموارد -> تشغيل البرامج النصية.

اكتشف المهارات من SKILL.md الملفات على القرص وسجل موفر المهارات كموفر سياق عامل:

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

المهارات المعرفة بالتعليمات البرمجية

بالإضافة إلى المهارات المستندة إلى الملفات المكتشفة من SKILL.md الملفات، يمكنك تحديد المهارات بالكامل في التعليمات البرمجية باستخدام AgentInlineSkill. تكون المهارات المعرفة بالتعليمات البرمجية مفيدة عندما:

  • يتم إنشاء محتوى المهارة ديناميكيا (على سبيل المثال، القراءة من قاعدة بيانات أو بيئة).
  • تريد الاحتفاظ بتعريفات المهارة جنبا إلى جنب مع التعليمات البرمجية للتطبيق التي تستخدمها.
  • تحتاج إلى موارد تنفذ المنطق في وقت القراءة بدلا من تقديم الملفات الثابتة.
  • يجب إنشاء تعريفات المهارة في وقت التشغيل من البيانات - على سبيل المثال، إنشاء مهارة مخصصة لكل جلسة عمل مستخدم استنادا إلى دورهم أو أذوناتهم.
  • تحتاج المهارة إلى الإغلاق عبر حالة موقع الاتصال (المتغيرات المحلية والإغلاقات) بدلا من حل الخدمات من حاوية DI.

مهارة التعليمات البرمجية الأساسية

AgentInlineSkill إنشاء باسم ووصف وتعليمات. إرفاق الموارد باستخدام .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);

الموارد الديناميكية

قم بتمرير مفوض المصنع لحساب .AddResource() المحتوى في وقت التشغيل. يتم استدعاء المفوض في كل مرة يقرأ فيها العامل المورد:

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

البرامج النصية المعرفة بواسطة التعليمات البرمجية

استخدم .AddScript() لتسجيل مفوض كبرنامج نصي قابل للتنفيذ. يتم تشغيل البرامج النصية المعرفة بالتعليمات البرمجية أثناء المعالجة كمكالمات تفويض مباشرة. لا يلزم تشغيل البرنامج النصي. يتم تحويل المعلمات التي تمت كتابتها للمفوض تلقائيا إلى مخطط JSON يستخدمه العامل لتمرير الوسيطات:

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

Note

لدمج المهارات المعرفة بالتعليمات البرمجية مع المهارات المستندة إلى الملفات أو المستندة إلى الفئة في موفر واحد، استخدم AgentSkillsProviderBuilder - راجع إنشاء الموفر.

بالإضافة إلى المهارات المستندة إلى الملفات المكتشفة من SKILL.md الملفات، يمكنك تحديد المهارات بالكامل في التعليمات البرمجية Python باستخدام InlineSkill. تكون المهارات المعرفة بالتعليمات البرمجية مفيدة عندما:

  • يتم إنشاء محتوى المهارة ديناميكيا (على سبيل المثال، القراءة من قاعدة بيانات أو بيئة).
  • تريد الاحتفاظ بتعريفات المهارة جنبا إلى جنب مع التعليمات البرمجية للتطبيق التي تستخدمها.
  • تحتاج إلى موارد تنفذ المنطق في وقت القراءة بدلا من تقديم الملفات الثابتة.
  • يجب إنشاء تعريفات المهارة في وقت التشغيل من البيانات - على سبيل المثال، إنشاء مهارة مخصصة لكل جلسة عمل مستخدم استنادا إلى دورهم أو أذوناتهم.
  • تحتاج المهارة إلى الإغلاق عبر حالة موقع الاتصال (المتغيرات المحلية والإغلاقات) بدلا من حل الخدمات من خلال **kwargs.

مهارة التعليمات البرمجية الأساسية

إنشاء مثيل InlineSkill مع SkillFrontmatter (يحتوي على الاسم والوصف) ومحتوى التعليمات. إرفاق مثيلات مع محتوى ثابت اختياريا 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)

الموارد الديناميكية

@skill.resource استخدم مصمم الديكور لتسجيل دالة كمورد. يتم استدعاء الدالة في كل مرة يقرأ فيها العامل المورد، حتى يتمكن من إرجاع بيانات up-to-date. يتم دعم كل من وظائف المزامنة وغير المتزامنة:

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

عند استخدام مصمم الديكور بدون وسيطات (@skill.resource)، يصبح اسم الدالة اسم المورد ويصبح docstring هو الوصف. استخدم @skill.resource(name="...", description="...") لتعيينها بشكل صريح.

البرامج النصية المعرفة بواسطة التعليمات البرمجية

@skill.script استخدم مصمم الديكور لتسجيل دالة كبرنامج نصي قابل للتنفيذ على مهارة. تعمل البرامج النصية المعرفة بالتعليمات البرمجية قيد التشغيل ولا تتطلب مشغل برنامج نصي. يتم دعم كل من وظائف المزامنة وغير المتزامنة:

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

عند استخدام مصمم الديكور بدون وسيطات (@skill.script)، يصبح اسم الدالة اسم البرنامج النصي ويصبح docstring هو الوصف. يتم تحويل المعلمات التي تكتبها الدالة تلقائيا إلى مخطط JSON يستخدمه العامل لتمرير الوسيطات.

بالإضافة إلى المهارات المستندة إلى الملفات المكتشفة من SKILL.md الملفات، يمكنك تحديد المهارات بالكامل في التعليمات البرمجية Go:

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 تحميل إرشادات المهارة فقط عندما يستدعي load_skillالعامل . تتلقى البرامج النصية وسيطات سلسلة نمط CLI الموضعية، على سبيل المثال ["26.2", "1.60934"]، ويمكن تحليل هذه الوسيطات كيفما يتطلب البرنامج النصي.

Tip

راجع أمثلة المهارات للحصول على عينات كاملة قابلة للتشغيل.

المهارات المستندة إلى الفصل الدراسي

تتيح لك المهارات المستندة إلى الفئة تجميع جميع مكونات المهارات - الاسم والوصف والتعليمات والموارد والبرامج النصية - في فئة C# واحدة. وهذا يجعلها سهلة الحزم والتوزيع كحزم NuGet - يمكن للفرق تأليف المهارات وشحنها بشكل مستقل، ويضيفها المستهلكون مع dotnet add package ومكالمة واحدة .UseSkill() . اشتق من AgentClassSkill<T> (حيث T هي الفئة الخاصة بك)، ثم قم بتعليق الخصائص مع [AgentSkillResource] وأساليب مع [AgentSkillScript] للاكتشاف التلقائي:

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

تسجيل المهارة المستندة إلى الفئة مع AgentSkillsProvider:

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

عند تطبيق السمة [AgentSkillResource] على خاصية أو أسلوب، يتم استخدام القيمة المرجعة الخاصة بها كمحتوى المورد عندما يقرأ العامل المورد - استخدم أسلوبا عندما يحتاج المحتوى إلى حساب في وقت القراءة. عند [AgentSkillScript] تطبيقه على أسلوب، يتم استدعاء الأسلوب عندما يستدعي العامل البرنامج النصي. استخدم [Description] من System.ComponentModel لوصف كل مورد وبرنامج نصي للعامل.

Note

AgentClassSkill<T> يدعم أيضا التجاوز Resources و Scripts كمجموعات للسيناريوهات التي لا يتناسب فيها الاكتشاف المستند إلى السمات.

المهارات المستندة إلى الفصل الدراسي

تتيح لك المهارات المستندة إلى الفئة تجميع جميع مكونات المهارات - الاسم والوصف والإرشادات والموارد والبرامج النصية - في فئة Python واحدة. وهذا يجعلها سهلة الحزم والتوزيع كحزم PyPI - يمكن للفرق تأليف المهارات وشحنها بشكل مستقل، ويضيفها المستهلكون مع pip install ومكالمة واحدة SkillsProvider() . الفئة ClassSkillالفرعية @ClassSkill.resource ، ثم استخدم مزخرفات و @ClassSkill.script للاكتشاف التلقائي:

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

تسجيل المهارة المستندة إلى الفئة مع SkillsProvider:

from agent_framework import SkillsProvider

skill = UnitConverterSkill()
skills_provider = SkillsProvider(skill)

عندما @ClassSkill.resource يتم تطبيقه كمزخرف عاري (بدون وسيطات)، يصبح اسم الأسلوب اسم المورد (مع تحويل تسطير أسفل السطر إلى واصلات) ويصبح docstring هو الوصف. استخدم @ClassSkill.resource(name="...", description="...") لتعيينها بشكل صريح. ينطبق نفس النمط على @ClassSkill.script.

يمكن تعريف الموارد إما على أنها أساليب عادية أو @property واصفات. عند استخدام @property، ضع الأول @property والثاني @ClassSkill.resource . يتم تخزين قيم إرجاع الموارد مؤقتا بعد الوصول الأول.

Note

ClassSkill يدعم أيضا بشكل صريح تجاوز resources خصائص و scripts للإرجاع InlineSkillResource والمثيلات InlineSkillScript مباشرة، للسيناريوهات التي لا يتناسب فيها الاكتشاف المستند إلى مصمم الديكور.

المهارات المستندة إلى MCP

Note

تتطلب المهارات المستندة إلى MCP حزمة Microsoft.Agents.AI.Mcp NuGet. تعد واجهة برمجة تطبيقات مهارات MCP تجريبية وقد تتغير في الإصدارات المستقبلية.

يمكن اكتشاف المهارات من خوادم MCP (بروتوكول سياق النموذج) التي تعرض موارد المهارة ضمن skill:// نظام URI. يعلن خادم MCP عن المهارات عبر skill://index.json مستند اكتشاف، ويجلب إطار العمل محتوى المهارات عند الطلب.

تدعم المهارات المستندة إلى MCP نوعين من إدخال الفهرس:

  • skill-md - يتم جلب موارد المهارة SKILL.md والأشقاء عند الطلب من خادم MCP.
  • archive - يتم توزيع المهارة كأرشيف ZIP يقوم إطار العمل بتنزيله وفك حزمه محليا.

الاستخدام الأساسي

استخدم أسلوب AgentSkillsProviderBuilder الامتداد UseMcpSkills لإضافة مصدر مهارات MCP:

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

مهارات من نوع الأرشيف

بالنسبة لمهارات نوع الأرشيف، استخدم AgentMcpSkillsSourceOptions (من الحزمة Microsoft.Agents.AI.Mcp ) لتكوين سلوك الاستخراج:

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 يعرض الخصائص التالية للتحكم في استخراج الأرشيف:

  • ArchiveSkillsDirectory - الدليل الأساسي للمحفوظات المستخرجة. الإعدادات الافتراضية لدليل فرعي فريد ضمن دليل العمل الحالي، يتم إنشاؤه لكل مثيل مصدر لمنع التصادم بين مصادر متعددة.
  • ArchiveResourceExtensions - الملحقات المسموح بها للموارد في الأرشيفات المستخرجة. الإعدادات الافتراضية ل .md، .json، .yaml، .yml، .csv، .xml. .txt
  • ArchiveResourceSearchDepth - مدى عمق البحث عن الموارد داخل كل دليل مهارة مستخرج. تتغير افتراضيا إلى 2.
  • ArchiveMaxFileCount - الحد الأقصى للملفات لكل أرشيف. يتم تخطي الأرشيفات التي تتجاوز هذا الحد. تتغير افتراضيا إلى 20.
  • ArchiveMaxSizeBytes - الحد الأقصى لحجم التنزيل لكل أرشيف. تتغير افتراضيا إلى 1 MB.
  • ArchiveMaxUncompressedSizeBytes - الحد الأقصى للحجم الإجمالي غير المضغوط لكل أرشيف. تتغير افتراضيا إلى 1 MB.

إذا تم حل العديد من أعضاء الأرشيف إلى نفس الملف المستخرج، يحتفظ إطار عمل العامل بمحتوى العضو الأول، ويتخطى فيما بعد اصطدم الأعضاء بتحذير، ويستمر في اكتشاف المهارات.

Important

لا يتم تنفيذ البرامج النصية المجمعة في مهارات نوع الأرشيف أبدا. هذا مقياس أمان متعمد - يتطلب المحتوى القابل للتنفيذ من خوادم MCP البعيدة ثقة صريحة.

المهارات المستندة إلى MCP

Note

المهارات المستندة إلى MCP تجريبية وقد تتغير في الإصدارات المستقبلية. يؤدي استخدام MCPSkillsSource إلى FutureWarning إصدار تحت علامة الميزة MCP_SKILLS .

يمكنك اكتشاف المهارات من خوادم MCP (بروتوكول سياق النموذج) التي تعرض موارد المهارة ضمن skill:// نظام URI. يعلن خادم MCP عن المهارات من خلال skill://index.json مستند اكتشاف. يدعم skill-md Python الإدخالات التي تم جلبها عند الطلب من خلال resources/read الإدخالات المقدمة archive كملفات ZIP.

التفاف MCP ClientSession في MCPSkillsSource وتمريره إلى SkillsProvider:

import os
from agent_framework import Agent, MCPSkillsSource, SkillsProvider, ToolApprovalMiddleware
from agent_framework.foundry import FoundryChatClient
from azure.identity import AzureCliCredential
from mcp.client.session import ClientSession
from mcp.client.streamable_http import streamable_http_client

mcp_url = os.environ["MCP_SKILLS_SERVER_URL"]

# Connect to the MCP server over streamable HTTP
async with streamable_http_client(url=mcp_url) as (read, write, _), ClientSession(read, write) as session:
    await session.initialize()

    # MCPSkillsSource reads skill://index.json and creates one skill per
    # supported 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("...")

لإدخالات الأرشيف، استخدم application/zip نوع وسائط أو لاحقة .zip عنوان URL. يتخطى إطار عمل العامل تنسيقات TAR .tar.gz.tgzو غيرها من تنسيقات الأرشيف على أنها غير معتمدة بحيث لا يزال بإمكان إدخالات الفهرس المتبقية تحميلها. إعادة حزم المهارات الحالية غير الرمز البريدي ك ZIP؛ لا يلزم إجراء أي تغيير في التعليمات البرمجية من جانب المتصل.

عندما يوفر digestإدخال أرشيف ، يجب استخدامه sha256: متبوعا ب 64 حرفا سداسيا عشريا صغيرا. يتحقق إطار عمل العامل من الملخص مقابل وحدات بايت الأرشيف التي تم فك ترميزها قبل الاستخراج. يتخطى ملخص غير صحيح أو غير متطابق هذا الأرشيف دون حظر الإدخالات الأخرى. يسمح بملخص محذف أو خال. ينطبق التحقق من الملخص فقط على archive الإدخالات، وليس skill-md الإدخالات أو مواردها الداعمة. يثبت ملخص المطابقة التناسق مع الفهرس، وليس أن خادم MCP جدير بالثقة.

MCPSkillsSource يستخرج محتوى ZIP في الذاكرة. archive_* استخدم خيارات الدالة الإنشائية لتقييد ملحقات الموارد وعمق البحث وعدد الملفات وحجم التنزيل والحجم الإجمالي غير المضغوط. تتوفر البرامج النصية في أرشيفات MCP فقط كموارد للقراءة فقط ولا يتم كشفها أبدا كنصوص قابلة للتشغيل.

تتم تسوية مسارات عضو الأرشيف ومقارنتها بشكل غير حساس لحالة الأحرف، ومطابقة البحث عن الموارد. إذا حل عدة أعضاء إلى نفس المسار، يحتفظ Agent Framework بالهجاء والمحتوى الخاصين بالعضو الأول، ويسجل تحذيرا، ويستمر في تحميل محتوى الأرشيف المتبقي.

Note

إذا كان skill://index.json غير موجود أو غير قابل للقراءة أو فارغا أو فشل في التحليل، يقوم المصدر بإرجاع قائمة فارغة. يتخطى إطار عمل العامل أنواع إدخال الفهرس بخلاف skill-md و archive.

Important

يتحكم خادم MCP الخارجي في محتوى المهارة - بما في ذلك الإرشادات والبرامج النصية التي قد يقوم العامل بتشغيلها - يصل إلى العامل. اتصل فقط بالخوادم MCPSkillsSource التي قمت بفحصها والثقة بها، واتعامل مع استجاباتها على أنها إدخال غير موثوق به.

مصادر المهارات

يسترد AgentSkillsProvider المهارات من مصدر واحد أو أكثر - الكائنات التي تنفذ AgentSkillsSource. وتنقسم المصادر إلى فئتين: المصادر الطرفية التي تكتشف المهارات أو تحتفظ بها (مثل AgentFileSkillsSource المهارات المستندة إلى الملفات)، والمزخرفات التي تحول ناتج مصدر آخر (التجميع وإلغاء التكرار والتخزين المؤقت والتصفية). يمكنك أيضا إنشاء مصدر مخصص.

ينفذ كل مصدر أسلوبا واحدا - GetSkillsAsync(AgentSkillsSourceContext context, CancellationToken cancellationToken = default). يحمل AgentSkillsSourceContext معلومات حول الطلب الحالي:

  • Agent - المثيل الذي AIAgent يطلب المهارات.
  • Session AgentSession- المقترنة بالادعاء، أو null عند عدم وجود جلسة عمل.

يتوفر هذا السياق في جميع أنحاء البنية الأساسية لبرنامج ربط العمليات التجارية المصدر، لذلك FilteringAgentSkillsSource يمكن للمسند أو المصدر المخصص أن يستند إلى منطقه - على سبيل المثال، إرجاع مجموعة مختلفة من المهارات اعتمادا على العامل الطالب.

مصادر طرفية

AgentFileSkillsSource

يكتشف المهارات من SKILL.md الملفات على القرص. يقبل مسار دليل واحد أو أكثر، ومشغل برنامج نصي اختياري، واختياري AgentFileSkillsSourceOptions (موثق في المهارات المستندة إلى الملف).

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

AgentInMemorySkillsSource

AgentSkill يلتف المثيلات (المعرفة بواسطة التعليمات البرمجية أو المستندة إلى الفئة) في الذاكرة.

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

أداة الجمع

AggregatingAgentSkillsSource

يجمع بين مصادر متعددة في مصدر واحد. يتم إرجاع المهارات في ترتيب التسجيل مع عدم تطبيق إلغاء التكرار أو التصفية.

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

Decorators

تقوم مصممات الديكور بتغليف مصدر داخلي وتحويل مخرجاته. يمكن ربطها لبناء البنية الأساسية لبرنامج ربط العمليات التجارية.

DeduplicatingAgentSkillsSource

يزيل أسماء المهارات المكررة (يربح التكرار الأول غير حساس لحالة الأحرف). يتم تسجيل التكرارات عند مستوى التحذير.

var deduplicated = new DeduplicatingAgentSkillsSource(innerSource);

CachingAgentSkillsSource

تخزين قائمة المهارات التي تم إرجاعها بواسطة المصدر الداخلي مؤقتا. يتم تسلسل المتصلين المتزامنين لكل مفتاح ذاكرة تخزين مؤقت بحيث يتم تشغيل إحضار واحد فقط في كل مرة. يقبل اختياري CachingAgentSkillsSourceOptions:

  • RefreshInterval (TimeSpan?) - عند التعيين، تنتهي صلاحية النتائج المخزنة مؤقتا بعد هذا الفاصل الزمني وإعادة استدعاء المصدر الداخلي. عندما null (الافتراضي)، لا تنتهي صلاحية النتائج المخزنة مؤقتا.
  • CacheIsolationKeySelector (Func<AgentSkillsSourceContext, string?>?) - إرجاع مفتاح ذاكرة التخزين المؤقت لعزل النتائج المخزنة مؤقتا حسب السياق (على سبيل المثال، لكل مستأجر). عندما null، يشارك جميع المتصلين مستودع ذاكرة تخزين مؤقت واحد.
var cached = new CachingAgentSkillsSource(innerSource, new CachingAgentSkillsSourceOptions
{
    RefreshInterval = TimeSpan.FromMinutes(5)
});

FilteringAgentSkillsSource

يطبق دالة تقييم لتضمين المهارات أو استبعادها. يتلقى التقييم المهارة و AgentSkillsSourceContext.

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

المصادر المخصصة

عندما لا تغطي المصادر المضمنة السيناريو الخاص بك، قم بتنفيذ الخاص بك. فئة AgentSkillsSource فرعية لمصدر طرفي (فئة تنتج مهارات من أصل جديد مثل قاعدة بيانات أو خدمة بعيدة)، أو فئة DelegatingAgentSkillsSource فرعية لمصمم يقوم بتحويل إخراج مصدر آخر.

مصدر طرفي

اشتق من AgentSkillsSource ونفذ GetSkillsAsync. AgentSkillsSourceContext تسمح الوسيطة للمصدر بتخصيص نتيجته للطلب الحالي - على سبيل المثال، إرجاع مجموعة مختلفة من المهارات اعتمادا على العامل الطالب. تجاوز 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);
    }
}

مصمم الديكور المخصص

اشتق من DelegatingAgentSkillsSourceالنتيجة واستدعها InnerSource.GetSkillsAsyncوقم بتحويلها أو ملاحظتها. هذا هو نفس النمط الذي يستخدمه التخزين المؤقت المضمن، وإلغاء التكرار، وتصفية مصممي الديكور. على سبيل المثال، مصمم يسجل عدد المهارات التي تم إرجاعها لكل طلب دون تغيير النتيجة:

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

يمكن تمرير كلا المصدرين المخصصين مباشرة AgentSkillsProvider أو متداخلين داخل مسار أكبر، تماما مثل المصادر المضمنة.

بناء الموفر

AgentSkillsProvider هو المكون الذي يعرض المهارات للوكيل. وهو يلتف على مصدر واحد أو أكثر ويسجل load_skillread_skill_resourceالأدوات و وrun_skill_script. هناك ثلاث طرق لإنشاء واحدة:

  1. AgentSkillsProviderBuilder - يقوم بإنشاء أنواع مهارات متعددة في موفر واحد مع التجميع التلقائي وإلغاء التكرار والتخزين المؤقت والتصفية الاختيارية. الأفضل للسيناريوهات التي تجمع بين المهارات المستندة إلى الملفات والمعرفة بالتعليمات البرمجية والمستندة إلى الفئة والمهارات المستندة إلى MCP.
  2. تكوين المصدر المباشر - إنشاء البنية الأساسية لبرنامج ربط العمليات التجارية المصدر بنفسك باستخدام الفئات العامة AgentSkillsSource . لا يتم تطبيق التخزين المؤقت التلقائي أو إلغاء التكرار - يمكنك التحكم في البنية الأساسية لبرنامج ربط العمليات التجارية الكاملة. الأفضل عندما تحتاج إلى التحكم في الترتيب أو المنطق الشرطي أو سلوك مصمم الديكور المخصص.
  3. المنشئات الملائمة - إنشاء موفر من مسار ملف أو مثيل (مثيلات) مهارة مباشرة. تطبيق إلغاء التكرار والتخزين المؤقت تلقائيا. الأفضل للسيناريوهات أحادية المصدر.

استخدام AgentSkillsProviderBuilder

استخدم AgentSkillsProviderBuilder عندما تحتاج إلى أي مما يلي:

  • أنواع المهارات المختلطة - الجمع بين المهارات المستندة إلى الملفات والمعرفة بالتعليمات البرمجية (AgentInlineSkill) والمستندة إلى الفئة (AgentClassSkill) والمهارات المستندة إلى MCP في موفر واحد.
  • تصفية المهارات - قم بتضمين المهارات أو استبعادها باستخدام دالة تقييم.

أنواع المهارات المختلطة

اجمع بين أنواع المهارات المتعددة في موفر واحد عن طريق تسلسل UseFileSkillو UseSkillUseMcpSkillsو وUseFileScriptRunner:

var skillsProvider = new AgentSkillsProviderBuilder()
    .UseFileSkill(Path.Combine(AppContext.BaseDirectory, "skills"))  // file-based skills
    .UseSkill(volumeConverterSkill)                                  // AgentInlineSkill
    .UseSkill(temperatureConverter)                                  // AgentClassSkill
    .UseMcpSkills(mcpClient)                                         // MCP-based skills
    .UseFileScriptRunner(SubprocessScriptRunner.RunAsync)            // runner for file scripts
    .Build();

تصفية المهارات

استخدم UseFilter لتضمين المهارات التي تفي بمعاييرك فقط - على سبيل المثال، لتحميل المهارات من دليل مشترك مع استبعاد المهارات التجريبية:

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

إنشاء مصادر مباشرة

عندما لا يقدم المنشئ عنصر التحكم الذي تحتاجه، قم بإنشاء فئات المصدر بنفسك وتمرير البنية الأساسية لبرنامج ربط العمليات التجارية الناتجة إلى AgentSkillsProvider. راجع مصادر المهارات للحصول على القائمة الكاملة للمصادر المتاحة وخياراتها.

ينشئ المثال التالي مسارا قابلا للمقارنة متعدد المصادر، ولكنه يمنحك تحكما صريحا في كل مصمم:

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

Note

عندما ownsSource يكون ، trueيتخلص الموفر أيضا من البنية الأساسية لبرنامج ربط العمليات التجارية المصدر بأكمله. قم بتعيينه إلى false إذا كنت تدير دورة حياة المصدر بنفسك.

منشئات الملاءمة

بالنسبة للسيناريوهات أحادية المصدر، استخدم الدالات AgentSkillsProvider الإنشائية مباشرة. تطبق هذه تلقائيا إلغاء التكرار والتخزين المؤقت دون الحاجة إلى منشئ أو تكوين مصدر يدوي.

من مسار ملف:

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

من مثيلات المهارة:

var skillsProvider = new AgentSkillsProvider(volumeConverterSkill, temperatureConverter);

مصادر المهارات

يسترد SkillsProvider المهارات من مصدر واحد أو أكثر - الكائنات التي تشتق من SkillsSource. وتنقسم المصادر إلى فئتين: المصادر الطرفية التي تكتشف المهارات أو تحتفظ بها (مثل FileSkillsSource المهارات المستندة إلى الملفات)، والمزخرفات التي تحول ناتج مصدر آخر (التجميع وإلغاء التكرار والتخزين المؤقت والتصفية). يمكنك أيضا إنشاء مصدر مخصص.

ينفذ كل مصدر أسلوبا واحدا - async def get_skills(self, context: SkillsSourceContext) -> list[Skill]. يحمل SkillsSourceContext معلومات حول الطلب الحالي:

  • agent - العامل (SupportsAgentRun) الذي يطلب المهارات.
  • session AgentSession- المقترنة بالادعاء، أو None عند عدم وجود جلسة عمل.

يتدفق هذا السياق عبر البنية الأساسية لبرنامج ربط العمليات التجارية المصدر بأكمله، بحيث FilteringSkillsSource يمكن للمسند أو المصدر المخصص أن يستند إلى منطقه - على سبيل المثال، إرجاع مجموعة مختلفة من المهارات اعتمادا على العامل الطالب.

مصادر طرفية

  • FileSkillsSource - يكتشف المهارات من SKILL.md الملفات على القرص. يقبل مسار دليل واحد أو أكثر، خيارات اكتشاف اختيارية script_runner(resource_extensions، script_extensions، search_depth، resource_filter، script_filter) موثقة في المهارات المستندة إلى الملفات.
  • InMemorySkillsSource - يلتف Skill المثيلات (المعرفة من قبل التعليمات البرمجية أو المستندة إلى الفئة) في الذاكرة.
  • MCPSkillsSource - يكتشف المهارات من خادم MCP (راجع المهارات المستندة إلى MCP).
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])

مجمع

AggregatingSkillsSource يجمع بين مصادر متعددة في مصدر واحد. يتم إرجاع المهارات في ترتيب التسجيل مع عدم تطبيق إلغاء التكرار أو التصفية.

from agent_framework import AggregatingSkillsSource

aggregated = AggregatingSkillsSource([file_source, in_memory_source])

Decorators

تقوم مصممات الديكور بتغليف مصدر داخلي وتحويل مخرجاته. يمكن ربطها لبناء البنية الأساسية لبرنامج ربط العمليات التجارية.

  • DeduplicatingSkillsSource - يزيل أسماء المهارات المكررة (غير حساس لحالة الأحرف، يفوز التكرار الأول). يتم تسجيل التكرارات عند مستوى التحذير.
  • CachingSkillsSource - تخزين قائمة المهارات التي تم إرجاعها بواسطة المصدر الداخلي مؤقتا. يشترك المتصلون المتزامنون لنفس مفتاح ذاكرة التخزين المؤقت في إحضار واحد أثناء الطيران، لذلك يتم الاستعلام عن المصدر الداخلي مرة واحدة على الأكثر لكل مفتاح. يقبل وسيطتين اختياريتين للكلمات الأساسية:
    • refresh_interval (timedelta | None) - عند التعيين، يتم التعامل مع القائمة المخزنة مؤقتا على أنها قديمة بمجرد أن تكون أقدم من الفاصل الزمني، لذلك يعيد الاستدعاء التالي الاستعلام عن المصدر الداخلي. عندما None (الافتراضي)، لا تنتهي صلاحية النتائج المخزنة مؤقتا. مفيد للمصادر الداخلية التي تتغير مهاراتها على مدى عمر العملية، مثل MCPSkillsSource.
    • cache_isolation_key_selector (Callable[[SkillsSourceContext], str | None]) - اشتقاق مفتاح ذاكرة التخزين المؤقت من السياق لعزل النتائج المخزنة مؤقتا (على سبيل المثال، لكل عامل أو مستأجر). يجب أن تكون المفاتيح منخفضة العلاقة الأساسية ومستقرة. يستخدم الإرجاع None (أو تركه None) مستودع ذاكرة تخزين مؤقت مشترك واحد.
  • FilteringSkillsSource - يطبق دالة تقييم لتضمين المهارات أو استبعادها. يتلقى التقييم المهارة وSkillsSourceContext: 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",
)

المصادر المخصصة

عندما لا تغطي المصادر المضمنة السيناريو الخاص بك، قم بتنفيذ الخاص بك. فئة SkillsSource فرعية لمصدر طرفي (فئة تنتج مهارات من أصل جديد مثل قاعدة بيانات أو خدمة بعيدة)، أو فئة DelegatingSkillsSource فرعية لمصمم يقوم بتحويل إخراج مصدر آخر.

مصدر طرفي

اشتق من SkillsSource ونفذ get_skills. SkillsSourceContext تسمح الوسيطة للمصدر بتخصيص نتيجته للطلب الحالي - على سبيل المثال، إرجاع مجموعة مختلفة من المهارات اعتمادا على العامل الطالب:

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)

مصمم الديكور المخصص

اشتق من DelegatingSkillsSourceالنتيجة واستدعها self.inner_source.get_skills(context)وقم بتحويلها أو ملاحظتها. هذا هو نفس النمط الذي يستخدمه التخزين المؤقت المضمن، وإلغاء التكرار، وتصفية مصممي الديكور. على سبيل المثال، مصمم يسجل عدد المهارات التي تم إرجاعها لكل طلب دون تغيير النتيجة:

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

يمكن تمرير كلا المصدرين المخصصين مباشرة SkillsProvider أو متداخلين داخل مسار أكبر، تماما مثل المصادر المضمنة.

بناء الموفر

SkillsProvider هو المكون الذي يعرض المهارات للوكيل. وهو يلتف على مصدر واحد أو أكثر ويسجل load_skillread_skill_resourceالأدوات و وrun_skill_script. هناك ثلاث طرق لإنشاء واحدة:

  1. من مثيلات المهارة - مرر مهارات واحدة Skill أو سلسلة من المهارات إلى الدالة الإنشائية. الأفضل للمهارات المعرفة من التعليمات البرمجية والمستندة إلى الفئة. تطبيق إلغاء التكرار والتخزين المؤقت تلقائيا.
  2. من مسارات الملفات - استخدم SkillsProvider.from_paths() المصنع. الأفضل للمهارات المستندة إلى ملف أحادي المصدر. تطبيق إلغاء التكرار والتخزين المؤقت تلقائيا.
  3. تكوين المصدر المباشر - أنشئ البنية الأساسية لبرنامج ربط العمليات التجارية المصدر بنفسك باستخدام الفئات العامة SkillsSource ومررها إلى الدالة الإنشائية. يمكنك التحكم في البنية الأساسية لبرنامج ربط العمليات التجارية الكاملة. الأفضل عندما تحتاج إلى التحكم في الترتيب أو المنطق الشرطي أو مفاتيح التخزين المؤقت أو سلوك مصمم الديكور المخصص.

من مثيلات المهارة

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

من مسارات الملفات

from pathlib import Path
from agent_framework import SkillsProvider

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

إنشاء مصادر مباشرة

عندما تحتاج إلى التحكم الكامل، قم بإنشاء فئات المصدر بنفسك وتمرير البنية الأساسية لبرنامج ربط العمليات التجارية الناتجة إلى SkillsProvider. راجع مصادر المهارات للحصول على القائمة الكاملة للمصادر المتاحة وخياراتها.

ينشئ المثال أدناه البنية الأساسية لبرنامج ربط العمليات التجارية متعددة المصادر مع تحكم صريح في كل مصمم. يستخدم المثال عناصر نائبة:

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

يتم استخدام المتصل الذي يتم توفيره SkillsSourceas-is: لا يتم إلغاء تكراره أو التفافه تلقائيا في CachingSkillsSource. يمكن أن يؤدي التخزين المؤقت التلقائي لمصدر مدرك للسياق في مستودع مشترك واحد إلى إعادة تشغيل مهارات عامل أو مستأجر لعامل آخر. قم بإنشاء DeduplicatingSkillsSource و CachingSkillsSource (اختياريا باستخدام cache_isolation_key_selector) بنفسك عندما تحتاج إليها. ينطبق إلغاء التكرار التلقائي والتخزين المؤقت فقط عند تمرير المهارات أو مسارات الملفات مباشرة (الخياران 1 و2 أعلاه).

أنواع المهارات المختلطة

اجمع بين المهارات المستندة إلى الملفات والمعرفة بالتعليمات البرمجية والمستندة إلى الفئة في موفر واحد باستخدام AggregatingSkillsSource:

from pathlib import Path
from agent_framework import (
    AggregatingSkillsSource,
    DeduplicatingSkillsSource,
    FileSkillsSource,
    InMemorySkillsSource,
    SkillsProvider,
)

temperature_converter_skill = TemperatureConverterSkill()

skills_provider = SkillsProvider(
    DeduplicatingSkillsSource(
        AggregatingSkillsSource([
            FileSkillsSource(
                Path(__file__).parent / "skills",
                script_runner=my_runner,
            ),
            InMemorySkillsSource([volume_converter_skill, temperature_converter_skill]),
        ])
    )
)

تصفية المهارات

استخدم FilteringSkillsSource للتحكم في المهارات التي يراها العامل. تتلقى دالة التقييم كل Skill و SkillsSourceContext، وترجع True لتضمين المهارة. على سبيل المثال، لتحميل المهارات من دليل مشترك ولكن إخفاء دليل تجريبي:

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

سلوك التخزين المؤقت

بشكل افتراضي، يقوم المنشئ بتضمين البنية الأساسية لبرنامج ربط العمليات التجارية المصدر مع CachingAgentSkillsSource الذي يخزن قائمة المهارات التي تم إرجاعها بواسطة المصادر الأساسية مؤقتا. بمجرد حل المهارات عند الطلب الأول، تعيد الطلبات اللاحقة استخدام القائمة المخزنة مؤقتا دون إعادة الاستعلام عن المصادر. لتعطيل التخزين المؤقت (على سبيل المثال، أثناء التطوير عندما تتغير تعريفات المهارات بشكل متكرر)، استخدم DisableCaching() على المنشئ:

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

Note

يعد تعطيل التخزين المؤقت مفيدا أثناء التطوير عندما يتغير محتوى المهارة بشكل متكرر. في الإنتاج، اترك التخزين المؤقت ممكنا (الافتراضي) للحصول على أداء أفضل.

سلوك التخزين المؤقت

بشكل افتراضي، يتم تخزين أدوات المهارة والتعليمات مؤقتا بعد الإنشاء الأول. تعيين disable_caching=True لفرض إعادة بناء على كل استدعاء:

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

disable_caching يتوفر أيضا على الدالة SkillsProvider الإنشائية للمهارات المعرفة من التعليمات البرمجية والمستندة إلى الفئة.

للحفاظ على تمكين التخزين المؤقت ولكن إعادة اكتشاف المهارات بشكل دوري (على سبيل المثال، عندما يتغير مصدر مستند إلى ملف أو MCP على مدى مدة بقاء العملية)، مرر cache_refresh_interval. يتم التعامل مع ذاكرة التخزين المؤقت المضمنة على أنها قديمة بمجرد أن تكون أقدم من الفاصل الزمني، لذلك يقوم التشغيل التالي بإعادة الاستعلام عن المصدر:

from datetime import timedelta

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

cache_refresh_interval يؤثر فقط على ذاكرة التخزين المؤقت التي يبنيها الموفر داخليا (من المهارات أو مسارات الملفات)؛ يتم تجاهله عندما disable_caching=True وليس له أي تأثير على المتصل الذي تم توفيره SkillsSource (قم بإنشاء الخاص بك CachingSkillsSource مع refresh_interval لتلك).

Note

يعد تعطيل التخزين المؤقت مفيدا أثناء التطوير عندما يتغير محتوى المهارة بشكل متكرر. في الإنتاج، اترك التخزين المؤقت ممكنا (الافتراضي) للحصول على أداء أفضل.

الموافقة على الأداة

تتطلب جميع الأدوات التي يعرضها AgentSkillsProvider (load_skill، read_skill_resource، ) run_skill_scriptالموافقة بشكل افتراضي. عندما يتطلب استدعاء الأداة الموافقة، يتوقف العامل مؤقتا ويرجع ToolApprovalRequestContent بدلا من التنفيذ على الفور. استخدم 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();

للموافقة التلقائية على جميع أدوات المهارة بما في ذلك تنفيذ البرنامج النصي:

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

تعطيل الموافقة على أدوات محددة

يستخدم 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
    });

عندما تتطلب بعض الأدوات الموافقة والبعض الآخر لا في نفس الاستجابة، قد يستدعي النموذج كلا النوعين في وقت واحد. قم بتعيين EnableNonApprovalRequiredFunctionBypassing بحيث يتم تنفيذ الأدوات الخالية من الموافقة على الفور بينما تتم مطالبة المستخدم فقط بالأدوات المتبقية:

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

معالجة طلبات الموافقة

عندما تتطلب الأدوات الموافقة (ولا تتطابق قاعدة الموافقة التلقائية)، يقوم العامل بإرجاع ToolApprovalRequestContent العناصر التي يجب الموافقة عليها أو رفضها قبل المتابعة:

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

تفاصيل خطأ البرنامج النصي

بشكل افتراضي، عند فشل تنفيذ برنامج نصي للمهارة، ينتشر الاستثناء إلى الأساسي FunctionInvokingChatClient. إذا تم تعيين الخاصية الخاصة به IncludeDetailedErrors إلى true، تتم إعادة توجيه رسالة الاستثناء إلى النموذج، ما يمكنها من التصحيح الذاتي عن طريق إعادة المحاولة باستخدام وسيطات مختلفة:

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

إذا لم تتمكن من التكوين FunctionInvokingChatClient مباشرة، فقم بتعيين AgentSkillsProviderOptions.IncludeDetailedErrors بدلا من ذلك. يؤدي هذا إلى التقاط الاستثناء على مستوى موفر المهارات وإرجاع رسالة الخطأ مباشرة إلى النموذج:

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

تحذير

قد يكشف أي من النهجين عن تفاصيل الاستثناء الأولية للنموذج. يمكن أن تحتوي رسائل الاستثناء على معلومات حساسة مثل سلاسل الاتصال أو مسارات الملفات أو أسماء الخدمة الداخلية. بالإضافة إلى ذلك، إذا نشأت المهارات أو البرامج النصية من مصادر غير موثوق بها، فقد يطرح البرنامج النصي المصمم بشكل ضار استثناء تتضمن رسالته حمولة حقن المطالبة.

تتطلب جميع الأدوات التي يعرضها SkillsProvider (load_skillو read_skill_resourceو) الموافقة run_skill_scriptبشكل افتراضي. عندما يتطلب استدعاء الأداة الموافقة، يتوقف العامل مؤقتا ويعيد طلبات الموافقة عبر result.user_input_requests بدلا من التنفيذ على الفور. يمكنك الموافقة على كل طلب أو رفضه مع request.to_function_approval_response(approved=...) وإرسال الاستجابات مرة أخرى:

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)

عند رفض استدعاء أداة (approved=False)، يتم إعلام العامل برفض المستخدم ويمكنه الاستجابة وفقا لذلك.

الموافقة التلقائية على الأدوات الموثوق بها

بدلا من المطالبة بكل مكالمة، قم بالتثبيت ToolApprovalMiddleware باستخدام إحدى قواعد الموافقة التلقائية الثابتة التي تعرضها SkillsProvider. يتيح هذا تشغيل أدوات القراءة فقط تلقائيا بينما لا تزال تطالب بتنفيذ البرنامج النصي:

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

تتوفر قاعدتان:

  • SkillsProvider.read_only_tools_auto_approval_rule - يوافق فقط على أدوات القراءة فقط (load_skill، read_skill_resource) بينما لا يزال يطالب ب run_skill_script.
  • SkillsProvider.all_tools_auto_approval_rule - يوافق على كل أداة مهارة، بما في ذلك run_skill_script (لا يلزم وجود حلقة موافقة يدوية).

ترفض كلتا القاعئتين أي استدعاء يحمل server_label، بحيث يظلان محددين النطاق إلى الأدوات المحلية لهذا الموفر ولا يوافقان تلقائيا على أداة مستضافة تحمل الاسم نفسه. تنطبق القواعد فقط على الأدوات التي لا تزال تتطلب الموافقة - يتم تشغيل الأدوات التي تم اختيارها عبر disable_*_approval الوسيطات أدناه دون موافقة بغض النظر عن ذلك.

تعطيل الموافقة على أدوات محددة

بالنسبة للمهارات الموثوق بها، قم بتمرير disable_load_skill_approvaldisable_read_skill_resource_approvalو/أو disable_run_skill_script_approval لاختيار الأدوات الفردية خارج تدفق الموافقة بالكامل (مسجلة مع approval_mode="never_require"):

skills_provider = SkillsProvider(
    deployment_skill,
    disable_load_skill_approval=True,
    disable_read_skill_resource_approval=True,
    # disable_run_skill_script_approval remains False - scripts still require approval
)

تتوفر هذه الوسيطات أيضا في SkillsProvider.from_paths().

تحذير

قم فقط بتعطيل الموافقة أو الموافقة التلقائية على تنفيذ البرنامج النصي للمهارات والبرامج النصية من المصادر التي تثق بها. يتم إدخال إرشادات المهارة في سياق العامل، وتنفيذ run_skill_script التعليمات البرمجية التي يوفرها المصدر.

مطالبة النظام المخصصة

بشكل افتراضي، يقوم موفر المهارات بإدخال مطالبة النظام التي تسرد المهارات المتاحة وترشد العامل إلى استخدام load_skill و read_skill_resource. يمكنك تخصيص هذه المطالبة:

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

Note

يجب أن يحتوي {skills} القالب المخصص على عنصر نائب لقائمة المهارات التي تم إنشاؤها. يجب إلغاء الأقواس الحرفية ك {{ و }}.

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

Note

يجب أن يحتوي القالب المخصص على {skills} العنصر النائب لقائمة المهارات التي تم إنشاؤها. قد يحتوي اختياريا على {resource_instructions} عناصر نائبة (تلميح أداة المورد) و {runner_instructions} (تلميح أداة البرنامج النصي)؛ عندما تكون موجودة، يتم ملؤها بإرشادات مضمنة، وعند حذفها، لا يتم عرضها ببساطة (لا تزال الأدوات المقابلة مسجلة). يجب إلغاء الأقواس الحرفية ك {{ و }}.

إدخال الخدمات ووسيطات وقت التشغيل

يمكن أن تتلقى وظائف مورد المهارة والبرامج النصية سياق تطبيق خارجي تم توفيره في وقت التشغيل.

يمكن لمفوضي موارد المهارة والبرامج النصية الإعلان عن معلمة IServiceProvider يقوم إطار عمل العامل بإدخالها تلقائيا. يتيح هذا للمهارات حل خدمات التطبيقات المسجلة عند الطلب.

الإعداد

تسجيل خدمات التطبيق الخاصة بك وتمرير بنيت IServiceProvider إلى العامل عبر المعلمة 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);

المهارات المعرفة بالتعليمات البرمجية باستخدام DI

الإعلان IServiceProvider كمعلمة في AddResource أو AddScript المفوضين - يحل إطار العمل ويضخه تلقائيا عندما يقرأ العامل موردا أو يقوم بتشغيل برنامج نصي:

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

إضافة تعليق توضيحي للأساليب مع [AgentSkillResource] أو [AgentSkillScript] الإعلان عن معلمة IServiceProvider - يكتشف إطار العمل هؤلاء الأعضاء عبر الانعكاس ويضخ موفر الخدمة تلقائيا:

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

يمكن للمهارات المستندة إلى الفئة أيضا حل التبعيات من خلال الدالة الإنشائية الخاصة بها. تسجيل فئة المهارة في ServiceCollection وحلها من الحاوية بدلا من الاتصال new مباشرة:

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

وهذا مفيد عندما تحتاج فئة المهارة نفسها إلى خدمات محاقرة تتجاوز ما يستخدمه مفوضو الموارد والبرامج النصية.

وظائف الموارد التي تقبل **kwargs تلقي وسيطات الكلمة الأساسية لوقت التشغيل الذي يوفره المضيف التي تم تمريرها إلى agent.run(). بالنسبة إلى البرامج النصية، تفضل إدخال FunctionInvocationContext عندما يجب أن تظل قيم المضيف منفصلة عن الوسيطات التي يوفرها النموذج. تستمر دالات البرنامج النصي الموجودة التي تقبل **kwargs في دمج قيم وقت التشغيل مع الإدخالات من التعيين المقدم args من النموذج، لذلك لا تتعامل مع قيمة في البرنامج النصي **kwargs كدليل على أن المضيف قدمها.

تمرير وسيطات وقت التشغيل

مرر function_invocation_kwargs إلى agent.run() لتوفير وسيطات الكلمة الأساسية التي يقوم إطار العمل بإعادة توجيهها إلى وظائف الموارد والبرامج النصية:

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

استخدام سياق استدعاء لقيم المضيف فقط

أعلن عن معلمة FunctionInvocationContext نصية واحدة قابلة للربط بالكلمة الأساسية لتلقي استدعاء الحالي. المعلمة مخفية من مخطط البرنامج النصي، لذلك لا يمكن للنموذج توفيره.

import json

from agent_framework import (
    FunctionInvocationContext,
    InlineSkill,
    SkillFrontmatter,
)

converter_skill = InlineSkill(
    frontmatter=SkillFrontmatter(
        name="unit-converter",
        description="Convert units with a supplied conversion factor.",
    ),
    instructions="Use the convert script to perform unit conversions.",
)


@converter_skill.script(name="convert")
def convert_units(
    value: float,
    factor: float,
    *,
    ctx: FunctionInvocationContext,
) -> str:
    precision = ctx.kwargs["precision"]
    result = round(value * factor, precision)
    return json.dumps({"value": value, "factor": factor, "result": result})

يمكنك اختيار اسم المعلمة. قم بتعليقه مباشرة ك FunctionInvocationContext أو FunctionInvocationContext | None. لا يتعرف إطار العمل على برامج تضمين بيانات التعريف مثل Annotated[...] إدخال السياق. الاشتراك في عمليات التنفيذ المخصصة SkillScript.run() باستخدام نفس التعليق التوضيحي على أسلوبها run() . تحتفظ التطبيقات غير المشروحة بالسلوك الحالي لتلقي قيم وقت تشغيل المضيف كوسيطات كلمات أساسية فردية.

المهارات المعرفة بالتعليمات البرمجية باستخدام الكوارس

عندما تعلن **kwargsدالة مورد ، يقوم إطار العمل بإعادة توجيه وسيطات الكلمة الأساسية لوقت التشغيل في كل مرة يقرأ فيها العامل المورد:

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 وسيطات ولا تتلقى سياق وقت التشغيل.

عندما تعلن دالة **kwargsالبرنامج النصي ، يقوم إطار العمل بإعادة توجيه وسيطات الكلمة الأساسية لوقت التشغيل جنبا إلى جنب مع التي args يوفرها العامل:

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: Additional values from tool-call args or agent.run().
    """
    precision = kwargs.get("precision", 4)
    result = round(value * factor, precision)
    return json.dumps({"value": value, "factor": factor, "result": result})

يوفر value العامل ومن factor خلال استدعاء argsالأداة ؛ يوفر precision التطبيق من خلال function_invocation_kwargs. يمكن أيضا ربط الإدخالات غير المعلنة في التعيين الذي يوفره args النموذج ب **kwargs. تتلقى دالات البرنامج النصي دون **kwargs وسيطاتها المعلنة التي يوفرها العامل فقط.

المهارات المستندة إلى الفصل الدراسي مع الكوارس

يمكن أن تقبل **kwargsأساليب المهارة المستندة إلى الفئة أيضا . تنطبق نفس قواعد وسيطة المورد والبرنامج النصي.

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

أفضل الممارسات الأمنية

يجب التعامل مع مهارات العامل مثل أي تعليمة برمجية لجهة خارجية تجلبها إلى مشروعك. نظرا لأن تعليمات المهارة يتم إدخالها في سياق العامل - ويمكن أن تتضمن المهارات برامج نصية - فإن تطبيق نفس مستوى المراجعة والحوكمة الذي تريده على تبعية مفتوحة المصدر أمر ضروري.

  • المراجعة قبل الاستخدام - قراءة جميع محتويات المهارة (SKILL.mdوالبرامج النصية والموارد) قبل النشر. تحقق من أن السلوك الفعلي للبرنامج النصي يطابق هدفه المعلن. تحقق من الإرشادات المتطفلة التي تحاول تجاوز إرشادات الأمان أو تسرب البيانات أو تعديل ملفات تكوين العامل.
  • ثقة المصدر - قم بتثبيت المهارات فقط من الكتاب الموثوق بهم أو المساهمين الداخليين الذين تم فحصهم. تفضل المهارات ذات المصدر الواضح والتحكم في الإصدار والصيانة النشطة. شاهد أسماء المهارات المطبعية التي تحاكي الحزم الشائعة.
  • بيئة الاختبار المعزولة - تشغيل المهارات التي تتضمن البرامج النصية القابلة للتنفيذ في بيئات معزولة. تقييد الوصول إلى نظام الملفات والشبكة والوصول على مستوى النظام إلى ما تتطلبه المهارة فقط. تتطلب تأكيدا صريحا من المستخدم قبل تنفيذ العمليات الحساسة المحتملة.
  • التدقيق والتسجيل - سجل المهارات التي يتم تحميلها، والموارد التي تتم قراءتها، وأي البرامج النصية يتم تنفيذها. يمنحك هذا مسار تدقيق لتتبع سلوك العامل مرة أخرى إلى محتوى مهارة محدد إذا حدث خطأ ما.

متى تستخدم المهارات مقابل مهام سير العمل

تعمل مهام سير عمل Agent Skills و Agent Framework على توسيع ما يمكن للوكلاء القيام به، لكنهم يعملون بطرق مختلفة بشكل أساسي. اختر النهج الذي يطابق متطلباتك على أفضل نحو:

  • التحكم - باستخدام مهارة، يقرر الذكاء الاصطناعي كيفية تنفيذ التعليمات. يعد هذا مثاليا عندما تريد أن يكون العامل مبدعا أو متكيفا. باستخدام سير العمل، يمكنك تعريف مسار التنفيذ بشكل صريح. استخدم مهام سير العمل عندما تحتاج إلى سلوك محدد يمكن التنبؤ به.
  • المرونة - تعمل المهارة ضمن دور وكيل واحد. إذا فشل شيء ما، يجب إعادة محاولة العملية بأكملها. تدعم مهام سير العمل نقاط التحقق، بحيث يمكن استئنافها من الخطوة الناجحة الأخيرة بعد الفشل. اختر مهام سير العمل عندما تكون تكلفة إعادة تنفيذ العملية بأكملها عالية.
  • الآثار الجانبية - المهارات مناسبة عندما تكون العمليات متكررة أو منخفضة المخاطر. يفضل مهام سير العمل عندما تنتج الخطوات تأثيرات جانبية (إرسال رسائل البريد الإلكتروني، دفع الدفعات) التي يجب عدم تكرارها عند إعادة المحاولة.
  • التعقيد - المهارات هي الأفضل للمهام المركز عليها والمجال الواحد التي يمكن لعامل واحد التعامل معها. تعد مهام سير العمل أكثر ملاءمة لعمليات الأعمال متعددة الخطوات التي تنسق عوامل متعددة أو موافقات بشرية أو تكاملات النظام الخارجي.

Tip

كقاعدة عامة: إذا كنت تريد أن يكتشف الذكاء الاصطناعي كيفية إنجاز مهمة، فاستخدم مهارة. إذا كنت بحاجة إلى ضمان تنفيذ الخطوات وب أي ترتيب، فاستخدم سير عمل.

الخطوات التالية