مهام سير العمل التعريفية - نظرة عامة

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

نظرة عامة

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

الفوائد الرئيسية:

  • التنسيق القابل للقراءة: من السهل فهم بناء جملة YAML، حتى لغير المطورين
  • Portable: يمكن مشاركة تعريفات سير العمل وإصدارها وتعديلها دون تغييرات في التعليمات البرمجية
  • التكرار السريع: تعديل سلوك سير العمل عن طريق تحرير ملفات التكوين
  • بنية متسقة: تضمن أنواع الإجراءات المعرفة مسبقا اتباع مهام سير العمل لأفضل الممارسات

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

السيناريو النهج الموصى به
أنماط التنسيق القياسية تصريحي
مهام سير العمل التي تتغير بشكل متكرر تصريحي
يحتاج غير المطورين إلى تعديل مهام سير العمل تصريحي
منطق مخصص معقد برنامجي
أقصى مرونة وتحكم برنامجي
التكامل مع التعليمات البرمجية Python الموجودة برنامجي

بنية YAML الأساسية

تختلف بنية YAML قليلا بين تطبيقات C# Python. راجع الأقسام الخاصة باللغة أدناه للحصول على التفاصيل.

أنواع الأفعال

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

بنية C# YAML

تستخدم مهام سير العمل التعريفية C# بنية تستند إلى المشغل:

#
# Workflow description as a comment
#
kind: Workflow
trigger:

  kind: OnConversationStart
  id: my_workflow
  actions:

    - kind: ActionType
      id: unique_action_id
      displayName: Human readable name
      # Action-specific properties

عناصر البنية

عنصر مطلوب Description
kind Yes يجب أن يكون Workflow
trigger.kind Yes نوع المشغل (عادة OnConversationStart)
trigger.id Yes معرف فريد لسير العمل
trigger.actions Yes قائمة الإجراءات التي يجب تنفيذها

Python بنية YAML

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

name: my-workflow
description: A brief description of what this workflow does

inputs:
  parameterName:
    type: string
    description: Description of the parameter

actions:
  - kind: ActionType
    id: unique_action_id
    displayName: Human readable name
    # Action-specific properties

عناصر البنية

عنصر مطلوب Description
name Yes معرف فريد لسير العمل
description No وصف يمكن للبشر قراءته
inputs No معلمات الإدخال التي يقبلها سير العمل
actions Yes قائمة الإجراءات التي يجب تنفيذها

المتطلبات الأساسية

قبل أن تبدأ، تأكد من أنك تملك:

  • .NET 8.0 أو أحدث
  • مشروع Microsoft Foundry مع عامل واحد على الأقل تم نشره
  • حزم NuGet التالية مثبتة:
dotnet add package Microsoft.Agents.AI.Workflows.Declarative.Foundry --prerelease
  • تقوم الأمثلة في هذه المقالة بتحميل التكوين من أسرار المستخدم ومتغيرات البيئة، والتي تتطلب حزم NuGet التالية:
dotnet add package Microsoft.Extensions.Configuration.EnvironmentVariables
dotnet add package Microsoft.Extensions.Configuration.UserSecrets
  • إذا كنت تنوي إضافة إجراء استدعاء أداة MCP إلى سير العمل الخاص بك، فقم أيضا بتثبيت حزمة NuGet التالية:
dotnet add package Microsoft.Agents.AI.Workflows.Declarative.Mcp --prerelease

أول سير عمل تعريفي

دعونا ننشئ سير عمل بسيطا يحيي المستخدم بناء على إدخاله.

الخطوة 1: إنشاء ملف YAML

إنشاء ملف باسم greeting-workflow.yaml:

#
# This workflow demonstrates a simple greeting based on user input.
# The user's message is captured via System.LastMessage.
#
# Example input: 
# Alice
#
kind: Workflow
trigger:

  kind: OnConversationStart
  id: greeting_workflow
  actions:

    # Capture the user's input from the last message
    - kind: SetVariable
      id: capture_name
      displayName: Capture user name
      variable: Local.userName
      value: =System.LastMessage.Text

    # Set a greeting prefix
    - kind: SetVariable
      id: set_greeting
      displayName: Set greeting prefix
      variable: Local.greeting
      value: Hello

    # Build the full message using an expression
    - kind: SetVariable
      id: build_message
      displayName: Build greeting message
      variable: Local.message
      value: =Concat(Local.greeting, ", ", Local.userName, "!")

    # Send the greeting to the user
    - kind: SendActivity
      id: send_greeting
      displayName: Send greeting to user
      activity: =Local.message

الخطوة 2: تكوين موفر الوكيل

إنشاء تطبيق وحدة تحكم C# لتنفيذ سير العمل. أولا، قم بتكوين موفر العامل الذي يتصل ب Foundry:

using Azure.Identity;
using Microsoft.Agents.AI.Workflows;
using Microsoft.Agents.AI.Workflows.Declarative;
using Microsoft.Extensions.Configuration;

// Load configuration (endpoint should be set in user secrets or environment variables)
IConfiguration configuration = new ConfigurationBuilder()
    .AddUserSecrets<Program>()
    .AddEnvironmentVariables()
    .Build();

string foundryEndpoint = configuration["FOUNDRY_PROJECT_ENDPOINT"] 
    ?? throw new InvalidOperationException("FOUNDRY_PROJECT_ENDPOINT not configured");

// Create the agent provider that connects to Foundry
// WARNING: DefaultAzureCredential is convenient for development but requires 
// careful consideration in production environments.
AzureAgentProvider agentProvider = new(
    new Uri(foundryEndpoint), 
    new DefaultAzureCredential());

الخطوة 3: إنشاء سير العمل وتشغيله

// Define workflow options with the agent provider
DeclarativeWorkflowOptions options = new(agentProvider)
{
    Configuration = configuration,
    // LoggerFactory = loggerFactory, // Optional: Enable logging
    // ConversationId = conversationId, // Optional: Continue existing conversation
};

// Build the workflow from the YAML file
string workflowPath = Path.Combine(AppContext.BaseDirectory, "greeting-workflow.yaml");
Workflow workflow = DeclarativeWorkflowBuilder.Build<string>(workflowPath, options);

Console.WriteLine($"Loaded workflow from: {workflowPath}");
Console.WriteLine(new string('-', 40));

// Create a checkpoint manager (in-memory for this example)
CheckpointManager checkpointManager = CheckpointManager.CreateInMemory();

// Execute the workflow with input
string input = "Alice";
StreamingRun run = await InProcessExecution.RunStreamingAsync(
    workflow, 
    input, 
    checkpointManager);

// Process workflow events
await foreach (WorkflowEvent workflowEvent in run.WatchStreamAsync())
{
    switch (workflowEvent)
    {
        case AgentResponseEvent responseEvent:
            Console.WriteLine($"Response: {responseEvent.Response.Text}");
            break;
        case WorkflowErrorEvent errorEvent:
            Console.WriteLine($"Error: {errorEvent.Data}");
            break;
    }
}

Console.WriteLine("Workflow completed!");

الإخراج المتوقع

Loaded workflow from: C:\path\to\greeting-workflow.yaml
----------------------------------------
Response: Hello, Alice!
Workflow completed!

المفاهيم الأساسية

مساحات أسماء المتغيرات

تستخدم مهام سير العمل التعريفية في C# متغيرات مساحة الاسم لتنظيم الحالة:

مساحة الاسم Description Example
Local.* المتغيرات المحلية لسير العمل Local.message
System.* القيم التي يوفرها النظام System.ConversationId، System.LastMessage

Note

لا تستخدم Workflow.Inputs مهام سير العمل التعريفية C# أو Workflow.Outputs مساحات الأسماء. يتم تلقي الإدخال عبر System.LastMessage ويتم إرسال الإخراج عبر SendActivity الإجراءات.

متغيرات النظام

المتغير Description
System.ConversationId معرف المحادثة الحالي
System.LastMessage أحدث رسالة مستخدم
System.LastMessage.Text المحتوى النصي للرسالة الأخيرة

لغة التعبير

يتم تقييم القيم مسبوقة ب = كتعبيرات باستخدام لغة تعبير PowerFx:

# Literal value (no evaluation)
value: Hello

# Expression (evaluated at runtime)
value: =Concat("Hello, ", Local.userName)

# Access last message text
value: =System.LastMessage.Text

تشمل الوظائف الشائعة:

  • Concat(str1, str2, ...) - سلسلة السلاسل
  • If(condition, trueValue, falseValue) - التعبير الشرطي
  • IsBlank(value) - تحقق مما إذا كانت القيمة فارغة
  • Upper(text) / Lower(text) - تحويل حالة الأحرف
  • Find(searchText, withinText) - البحث عن نص ضمن سلسلة
  • MessageText(message) - استخراج نص من كائن رسالة
  • UserMessage(text) - إنشاء رسالة مستخدم من نص
  • AgentMessage(text) - إنشاء رسالة عامل من النص

خيارات التكوين

DeclarativeWorkflowOptions توفر الفئة تكوينا لتنفيذ سير العمل:

DeclarativeWorkflowOptions options = new(agentProvider)
{
    // Application configuration for variable substitution
    Configuration = configuration,

    // Continue an existing conversation (optional)
    ConversationId = "existing-conversation-id",

    // Enable logging (optional)
    LoggerFactory = loggerFactory,

    // MCP tool handler for InvokeMcpTool actions (optional)
    McpToolHandler = mcpToolHandler,

    // HTTP request handler for HttpRequestAction actions (optional)
    HttpRequestHandler = new DefaultHttpRequestHandler(),

    // PowerFx expression limits (optional)
    MaximumCallDepth = 50,
    MaximumExpressionLength = 10000,

    // Telemetry configuration (optional)
    ConfigureTelemetry = opts => { /* configure telemetry */ },
    TelemetryActivitySource = activitySource,
};

إعداد موفر العامل

يقوم AzureAgentProvider بتوصيل سير العمل الخاص بك بوكلاء Foundry:

using Azure.Identity;
using Microsoft.Agents.AI.Workflows.Declarative;

// Create the agent provider with Azure credentials
AzureAgentProvider agentProvider = new(
    new Uri("https://your-project.api.azureml.ms"), 
    new DefaultAzureCredential())
{
    // Optional: Define functions that agents can automatically invoke
    Functions = [
        AIFunctionFactory.Create(myPlugin.GetData),
        AIFunctionFactory.Create(myPlugin.ProcessItem),
    ],

    // Optional: Allow concurrent function invocation
    AllowConcurrentInvocation = true,

    // Optional: Allow multiple tool calls per response
    AllowMultipleToolCalls = true,
};

تنفيذ سير العمل

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

using Microsoft.Agents.AI.Workflows;
using Microsoft.Agents.AI.Workflows.Checkpointing;

// Create checkpoint manager (choose in-memory or file-based)
CheckpointManager checkpointManager = CheckpointManager.CreateInMemory();
// Or persist to disk:
// var checkpointFolder = Directory.CreateDirectory("./checkpoints");
// var checkpointManager = CheckpointManager.CreateJson(
//     new FileSystemJsonCheckpointStore(checkpointFolder));

// Start workflow execution
StreamingRun run = await InProcessExecution.RunStreamingAsync(
    workflow, 
    input, 
    checkpointManager);

// Process events as they occur
await foreach (WorkflowEvent workflowEvent in run.WatchStreamAsync())
{
    switch (workflowEvent)
    {
        case AgentResponseEvent response:
            Console.WriteLine($"Agent: {response.Response.Text}");
            break;

        case RequestInfoEvent request:
            // Handle external input requests (human-in-the-loop)
            var userInput = await GetUserInputAsync(request);
            await run.SendResponseAsync(request.Request.CreateResponse(userInput));
            break;

        case SuperStepCompletedEvent checkpoint:
            // Checkpoint created - can resume from here if needed
            var checkpointInfo = checkpoint.CompletionInfo?.Checkpoint;
            break;

        case WorkflowErrorEvent error:
            Console.WriteLine($"Error: {error.Data}");
            break;
    }
}

اختيار أحداث الاستجابة التي تريد عرضها

يحتوي دفق أحداث سير العمل على عدة طرق عرض لنفس الإجراء. على سبيل المثال، ينتج عن إجراء نصي SendActivity ما يلي:

Event الغرض
MessageActivityEvent إعلام نشاط يحتوي على نص الرسالة.
AgentResponseUpdateEvent نص AgentResponseUpdate يحتوي على مستهلكي البث.
AgentResponseEvent المكتملة AgentResponse، المتوفرة كإخراج سير العمل.

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

لا SendActivity يوجد إعداد أو Question YAML يحدد AgentResponseEvent بدلا من AgentResponseUpdateEvent. اختر ما يعرضه معالج أحداث C#‎:

  • بالنسبة للاستجابات المكتملة، تعامل مع AgentResponseEvent، كما في المثال أعلاه. لا يزال بإمكانك استخدام RunStreamingAsync لتلقي أحداث سير العمل الأخرى على الفور.
  • لتدفق النص، قم بمعالجة AgentResponseUpdateEvent. لا تقم بإلحاق نص استجابة مكتملة مرة أخرى إذا كانت رسائله متدفقة بالفعل. بالنسبة إلى SendActivity، يشارك التحديث والاستجابة المكتملة معرف الاستجابة ومعرف الرسالة. تعقب معرف المنفذ ومعرف الرسالة عند ربط الرسائل المتدفقة والمكتملة.
  • التعامل RequestInfoEvent بشكل مستقل حتى يتمكن سير العمل من تلقي إدخال خارجي. لا تزيل تصفية نص الاستجابة الحاجة إلى الرد على الطلبات.

عند استخدام workflow.AsAIAgent()، تتحكم الوسيطة includeWorkflowOutputsInResponse في كيفية تضمين مخرجات سير العمل في استجابات العامل. لا يغير الأحداث التي يصدرها إجراء YAML وليس مفتاحا لتعطيل تحديثات الدفق.

استئناف من نقاط التفتيش

يمكن استئناف مهام سير العمل من نقاط التحقق للتسامح مع الخطأ:

// Save checkpoint info when workflow yields
CheckpointInfo? lastCheckpoint = null;

await foreach (WorkflowEvent workflowEvent in run.WatchStreamAsync())
{
    if (workflowEvent is SuperStepCompletedEvent checkpointEvent)
    {
        lastCheckpoint = checkpointEvent.CompletionInfo?.Checkpoint;
    }
}

// Later: Resume from the saved checkpoint
if (lastCheckpoint is not null)
{
    // Recreate the workflow (can be on a different machine)
    Workflow workflow = DeclarativeWorkflowBuilder.Build<string>(workflowPath, options);

    StreamingRun resumedRun = await InProcessExecution.ResumeStreamingAsync(
        workflow, 
        lastCheckpoint, 
        checkpointManager);

    // Continue processing events...
}

AOT ونقاط التفتيش Trim-Aggressive

عند النشر باستخدام AOT الأصلي (dotnet publish -p:PublishAot=true) أو تعطيل System.Text.Jsonالانعكاس الاحتياطي (<JsonSerializerIsReflectionEnabledByDefault>false</JsonSerializerIsReflectionEnabledByDefault>)، يفشل الاستدعاء الافتراضي CheckpointManager.CreateJson(store) عند تثبيت نقطة التحقق أو الإماهة.

حزمة سير العمل التعريفية تشحن مثيلا تم JsonSerializerOptions إنشاؤه من مصدر، DeclarativeWorkflowJsonOptions.Default، يغطي كل نوع حزمة تعريفية يتدفق عبر مسار نقطة التحقق. مررها كوسيطة ثانية إلى CheckpointManager.CreateJson:

using Microsoft.Agents.AI.Workflows.Checkpointing;
using Microsoft.Agents.AI.Workflows.Declarative;

// AOT-safe: type info is resolved via the source-generated JsonSerializerContext,
// so no runtime reflection is required.
CheckpointManager checkpointManager = CheckpointManager.CreateJson(
    store,
    DeclarativeWorkflowJsonOptions.Default);

Note

يعد المرور DeclarativeWorkflowJsonOptions.Defaultآمنا للاستخدام في بيئات غير AOT أيضا. إنها ترقية منسدلة للتطبيقات الممكنة للانعكاس CheckpointManager.CreateJson(store) لا ترى أي تغيير في السلوك. اعتماده دون شروط حتى تستمر نفس التعليمات البرمجية في العمل إذا قمت بالنشر لاحقا باستخدام AOT أو الاقتطاع.

DeclarativeWorkflowJsonOptions تم وضع علامة [Experimental("MAAI001")]. منع التشخيص في موقع المكالمة أو في ملف المشروع:

<PropertyGroup>
  <NoWarn>$(NoWarn);MAAI001</NoWarn>
</PropertyGroup>

تسجيل الأنواع المعرفة من قبل المستخدم

إذا كان إدخال سير العمل أو الحمولات المخصصة ActionExecutorResult.Result أو وسيطات طلب الموافقة غير البدائية هي أنواع معرفة من قبل المستخدم، قم باستنساخ Default وإلحاق محلل المصدر الذي تم إنشاؤه:

// Compose: declarative-package types + your app's source-gen context.
JsonSerializerOptions options = new(DeclarativeWorkflowJsonOptions.Default);
options.TypeInfoResolverChain.Add(MyAppJsonContext.Default);
options.MakeReadOnly();

CheckpointManager checkpointManager = CheckpointManager.CreateJson(store, options);

أين MyAppJsonContext تحدد JsonSerializerContext أنواع تطبيقاتك:

[JsonSourceGenerationOptions(JsonSerializerDefaults.Web)]
[JsonSerializable(typeof(MyWorkflowInput))]
[JsonSerializable(typeof(MyCustomResult))]
internal sealed partial class MyAppJsonContext : JsonSerializerContext;

Tip

للحصول على مثال قابل للتشغيل من طرف إلى طرف — بما في ذلك سير عمل YAML وعامل AzureCliCredentialمدعوم - و"إسقاط خيارات لمشاهدة وضع الفشل" يمكن ملاحظته — راجع AotCheckpointing النموذج في dotnet/samples/03-workflows/Declarative/AotCheckpointing. مجموعات JsonSerializerIsReflectionEnabledByDefault=false العينة .csproj لإعادة إنتاج وضع فشل AOT دون الحاجة إلى نشر AOT الكامل.

مرجع الإجراءات

الإجراءات هي اللبنات الأساسية لسير العمل التعريفي. ينفذ كل إجراء عملية معينة، ويتم تنفيذ الإجراءات بشكل تسلسلي بالترتيب الذي تظهر به في ملف YAML.

بنية الإجراء

تشترك جميع الإجراءات في الخصائص الشائعة:

- kind: ActionType      # Required: The type of action
  id: unique_id         # Optional: Unique identifier for referencing
  displayName: Name     # Optional: Human-readable name for logging
  # Action-specific properties...

إجراءات إدارة المتغيرات

SetVariable

تعيين متغير إلى قيمة محددة.

- kind: SetVariable
  id: set_greeting
  displayName: Set greeting message
  variable: Local.greeting
  value: Hello World

باستخدام تعبير:

- kind: SetVariable
  variable: Local.fullName
  value: =Concat(Local.firstName, " ", Local.lastName)

خصائص:

الخاصية مطلوب Description
variable Yes مسار المتغير (على سبيل المثال، ، Local.name، Workflow.Outputs.result)
value Yes القيمة المراد تعيينها (حرفي أو تعبير)

SetMultipleVariables

تعيين متغيرات متعددة في إجراء واحد.

- kind: SetMultipleVariables
  id: initialize_vars
  displayName: Initialize variables
  variables:
    Local.counter: 0
    Local.status: pending
    Local.message: =Concat("Processing order ", Local.orderId)

خصائص:

الخاصية مطلوب Description
variables Yes خريطة المسارات المتغيرة للقيم

SetTextVariable

تعيين متغير نص إلى قيمة سلسلة محددة.

- kind: SetTextVariable
  id: set_text
  displayName: Set text content
  variable: Local.description
  value: This is a text description

خصائص:

الخاصية مطلوب Description
variable Yes مسار متغير لقيمة النص
value Yes قيمة نصية لتعيينها

إعادة التعيين القابلة للتغيير

مسح قيمة المتغير.

- kind: ResetVariable
  id: clear_counter
  variable: Local.counter

خصائص:

الخاصية مطلوب Description
variable Yes مسار متغير لإعادة التعيين

ClearAllVariables

إعادة تعيين كافة المتغيرات في السياق الحالي.

- kind: ClearAllVariables
  id: clear_all
  displayName: Clear all workflow variables

ParseValue

استخراج البيانات أو تحويلها إلى تنسيق قابل للاستخدام.

- kind: ParseValue
  id: parse_json
  displayName: Parse JSON response
  source: =Local.rawResponse
  variable: Local.parsedData

خصائص:

الخاصية مطلوب Description
source Yes تعبير يرجع القيمة إلى التحليل
variable Yes مسار متغير لتخزين النتيجة التي تم تحليلها

EditTableV2

تعديل البيانات بتنسيق جدول منظم.

- kind: EditTableV2
  id: update_table
  displayName: Update configuration table
  table: Local.configTable
  operation: update
  row:
    key: =Local.settingName
    value: =Local.settingValue

خصائص:

الخاصية مطلوب Description
table Yes مسار متغير إلى الجدول
operation Yes نوع العملية (إضافة، تحديث، حذف)
row Yes بيانات الصف للعملية

إجراءات تدفق التحكم

لو

تنفيذ الإجراءات بشكل مشروط استنادا إلى شرط.

- kind: If
  id: check_age
  displayName: Check user age
  condition: =Local.age >= 18
  then:
    - kind: SendActivity
      activity:
        text: "Welcome, adult user!"
  else:
    - kind: SendActivity
      activity:
        text: "Welcome, young user!"

خصائص:

الخاصية مطلوب Description
condition Yes التعبير الذي يتم تقييمه إلى صواب/خطأ
then Yes الإجراءات التي يجب تنفيذها إذا كان الشرط صحيحا
else No الإجراءات التي يجب تنفيذها إذا كان الشرط خطأ

مجموعة الشروط

تقييم شروط متعددة مثل عبارة تبديل/حالة.

- kind: ConditionGroup
  id: route_by_category
  displayName: Route based on category
  conditions:
    - condition: =Local.category = "electronics"
      id: electronics_branch
      actions:
        - kind: SetVariable
          variable: Local.department
          value: Electronics Team
    - condition: =Local.category = "clothing"
      id: clothing_branch
      actions:
        - kind: SetVariable
          variable: Local.department
          value: Clothing Team
  elseActions:
    - kind: SetVariable
      variable: Local.department
      value: General Support

خصائص:

الخاصية مطلوب Description
conditions Yes قائمة أزواج الشرط/الإجراءات (فوز المطابقة الأولى)
elseActions No الإجراءات إذا لم يتطابق أي شرط

Foreach

يكرر عبر مجموعة.

- kind: Foreach
  id: process_items
  displayName: Process each item
  source: =Local.items
  itemName: item
  indexName: index
  actions:
    - kind: SendActivity
      activity:
        text: '=Concat("Processing item ", index, ": ", item)'

خصائص:

الخاصية مطلوب Description
source Yes تعبير يرجع مجموعة
itemName No اسم المتغير للعنصر الحالي (الافتراضي: item)
indexName No اسم المتغير للفهرس الحالي (الافتراضي: index)
actions Yes الإجراءات التي يجب تنفيذها لكل عنصر

BreakLoop

إنهاء الحلقة الحالية على الفور.

- kind: Foreach
  source: =Local.items
  actions:
    - kind: If
      condition: =item = "stop"
      then:
        - kind: BreakLoop
    - kind: SendActivity
      activity:
        text: =item

ContinueLoop

يتخطى إلى التكرار التالي للحلقة.

- kind: Foreach
  source: =Local.numbers
  actions:
    - kind: If
      condition: =item < 0
      then:
        - kind: ContinueLoop
    - kind: SendActivity
      activity:
        text: '=Concat("Positive number: ", item)'

GotoAction

الانتقال إلى إجراء معين حسب المعرف.

- kind: SetVariable
  id: start_label
  variable: Local.attempts
  value: =Local.attempts + 1

- kind: SendActivity
  activity:
    text: =Concat("Attempt ", Local.attempts)

- kind: If
  condition: =And(Local.attempts < 3, Not(Local.success))
  then:
    - kind: GotoAction
      actionId: start_label

خصائص:

الخاصية مطلوب Description
actionId Yes معرف الإجراء للانتقال إلى

إجراءات الإخراج

نشاط الإرسال

إرسال رسالة إلى المستخدم.

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

- kind: SendActivity
  id: send_welcome
  displayName: Send welcome message
  activity:
    text: "Welcome to our service!"

باستخدام تعبير:

- kind: SendActivity
  activity:
    text: =Concat("Hello, ", Local.userName, "! How can I help you today?")

خصائص:

الخاصية مطلوب Description
activity Yes النشاط المراد إرساله
activity.text Yes نص الرسالة (حرفي أو تعبير)

SendMessage

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

- kind: SendMessage
  id: show_repo_summary
  message: "Fetched repo: visibility={Local.RepoInfo.visibility}, description={Local.RepoInfo.description}"

خصائص:

الخاصية مطلوب Description
message Yes رسالة نصية لإرسالها. استخدم {Variable.Path} العناصر النائبة لتضمين قيم حالة سير العمل.

Note

يدعم SendMessageتنفيذ سير العمل التعريفي C# . استخدم SendActivity لسير العمل Python.

إجراءات استدعاء العامل

استدعاء AzureAgent

استدعاء عامل Foundry.

استدعاء أساسي:

- kind: InvokeAzureAgent
  id: call_assistant
  displayName: Call assistant agent
  agent:
    name: AssistantAgent
  conversationId: =System.ConversationId

مع تكوين الإدخال والإخراج:

- kind: InvokeAzureAgent
  id: call_analyst
  displayName: Call analyst agent
  agent:
    name: AnalystAgent
  conversationId: =System.ConversationId
  input:
    messages: =Local.userMessage
    arguments:
      topic: =Local.topic
  output:
    responseObject: Local.AnalystResult
    messages: Local.AnalystMessages
    autoSend: true

مع التكرار الحلقي الخارجي (يستمر حتى يتم استيفاء الشرط):

- kind: InvokeAzureAgent
  id: support_agent
  agent:
    name: SupportAgent
  input:
    externalLoop:
      when: =Not(Local.IsResolved)
  output:
    responseObject: Local.SupportResult

خصائص:

الخاصية مطلوب Description
agent.name Yes اسم الوكيل المسجل
conversationId No معرف سياق المحادثة
input.messages No الرسائل التي يجب إرسالها إلى العامل
input.arguments No وسيطات إضافية للعامل
input.externalLoop.when No شرط لمتابعة حلقة العامل
output.responseObject No مسار لتخزين استجابة العامل
output.messages No مسار لتخزين رسائل المحادثة
output.autoSend No إرسال استجابة تلقائيا إلى المستخدم

إجراءات الأداة وHTTP

استدعاءFunctionTool

استدعاء أداة دالة مباشرة من سير العمل دون المرور بعامل الذكاء الاصطناعي.

- kind: InvokeFunctionTool
  id: invoke_get_data
  displayName: Get data from function
  functionName: GetUserData
  conversationId: =System.ConversationId
  requireApproval: true
  arguments:
    userId: =Local.userId
  output:
    autoSend: true
    result: Local.UserData
    messages: Local.FunctionMessages

خصائص:

الخاصية مطلوب Description
functionName Yes اسم الدالة التي يجب استدعاؤها
conversationId No معرف سياق المحادثة
requireApproval No ما إذا كنت تريد طلب موافقة المستخدم قبل التنفيذ
arguments No وسيطات لتمريرها إلى الدالة
output.result No مسار لتخزين نتيجة الدالة
output.messages No مسار لتخزين رسائل الدالة
output.autoSend No إرسال النتيجة تلقائيا إلى المستخدم

إعداد C# ل InvokeFunctionTool:

يجب تسجيل الوظائف مع WorkflowRunner أو معالجتها عبر الإدخال الخارجي:

// Define functions that can be invoked
AIFunction[] functions = [
    AIFunctionFactory.Create(myPlugin.GetUserData),
    AIFunctionFactory.Create(myPlugin.ProcessOrder),
];

// Create workflow runner with functions
WorkflowRunner runner = new(functions) { UseJsonCheckpoints = true };
await runner.ExecuteAsync(workflowFactory.CreateWorkflow, input);

InvokeMcpTool

استدعاء أداة على خادم MCP (بروتوكول سياق النموذج).

- kind: InvokeMcpTool
  id: invoke_docs_search
  displayName: Search documentation
  serverUrl: https://learn.microsoft.com/api/mcp
  serverLabel: microsoft_docs
  toolName: microsoft_docs_search
  conversationId: =System.ConversationId
  requireApproval: false
  headers:
    X-Custom-Header: custom-value
  arguments:
    query: =Local.SearchQuery
  output:
    autoSend: true
    result: Local.SearchResults

مع اسم الاتصال للسيناريوهات المستضافة:

- kind: InvokeMcpTool
  id: invoke_hosted_mcp
  serverUrl: https://mcp.ai.azure.com
  toolName: my_tool
  # Connection name is used in hosted scenarios to connect to a ProjectConnectionId in Foundry.
  # Note: This feature is not fully supported yet.
  connection:
    name: my-foundry-connection
  output:
    result: Local.ToolResult

خصائص:

الخاصية مطلوب Description
serverUrl Yes عنوان URL لخادم MCP
serverLabel No تسمية قابلة للقراءة البشرية للخادم
toolName Yes اسم الأداة التي يجب استدعاؤها
conversationId No معرف سياق المحادثة
requireApproval No ما إذا كنت تريد طلب موافقة المستخدم
arguments No وسيطات لتمريرها إلى الأداة
headers No عناوين HTTP المخصصة للطلب
connection.name No الاتصال المسمى للسيناريوهات المستضافة (يتصل ب ProjectConnectionId في Foundry؛ غير مدعوم بالكامل حتى الآن)
output.result No مسار لتخزين نتيجة الأداة
output.messages No مسار لتخزين رسائل النتائج
output.autoSend No إرسال النتيجة تلقائيا إلى المستخدم

إعداد C# ل InvokeMcpTool:

تكوين McpToolHandler في مصنع سير العمل الخاص بك:

using Azure.Core;
using Azure.Identity;
using Microsoft.Agents.AI.Workflows.Declarative;

// Create MCP tool handler with authentication callback
DefaultAzureCredential credential = new();
DefaultMcpToolHandler mcpToolHandler = new(
    httpClientProvider: async (serverUrl, cancellationToken) =>
    {
        if (serverUrl.StartsWith("https://mcp.ai.azure.com", StringComparison.OrdinalIgnoreCase))
        {
            // Acquire token for Azure MCP server
            AccessToken token = await credential.GetTokenAsync(
                new TokenRequestContext(["https://mcp.ai.azure.com/.default"]),
                cancellationToken);

            HttpClient httpClient = new();
            httpClient.DefaultRequestHeaders.Authorization =
                new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token.Token);
            return httpClient;
        }

        // Return null for servers that don't require authentication
        return null;
    });

// Configure workflow factory with MCP handler
WorkflowFactory workflowFactory = new("workflow.yaml", foundryEndpoint)
{
    McpToolHandler = mcpToolHandler
};

HttpRequestAction

يرسل طلب HTTP من خلال المكون IHttpRequestHandler. يتم تحليل استجابات JSON الناجحة قبل التعيين؛ تفشل الاستجابات غير 2xx في الإجراء.

- kind: HttpRequestAction
  id: fetch_repo_info
  method: GET
  url: "https://api.github.com/repos/Microsoft/agent-framework"
  headers:
    Accept: application/vnd.github+json
    User-Agent: agent-framework
  queryParameters:
    per_page: 10
  response: Local.RepoInfo
  responseHeaders: Local.RepoHeaders

خصائص:

الخاصية مطلوب Description
url Yes عنوان URL للطلب المطلق
method No أسلوب HTTP؛ الإعدادات الافتراضية ل GET
headers No رؤوس الطلبات
queryParameters No معلمات الاستعلام الملحقة بعنوان URL
body No نص الطلب؛ استخدام kind: jsonأو rawأو none
requestTimeoutInMilliseconds No مهلة عند الطلب
conversationId No إضافة نص استجابة ناجح إلى المحادثة
response No مسار لتخزين نص الاستجابة الذي تم تحليله
responseHeaders No مسار لتخزين رؤوس الاستجابة

إعداد C# ل HttpRequestAction:

تعيين HttpRequestHandler عند إنشاء سير العمل. استخدم معالجا مخصصا عندما تحتاج إلى إعادة المحاولة، أو قائمة السماح بعنوان URL.

DeclarativeWorkflowOptions options = new(agentProvider)
{
    HttpRequestHandler = new DefaultHttpRequestHandler(),
};

Workflow workflow = DeclarativeWorkflowBuilder.Build<string>("workflow.yaml", options);

إجراءات الإنسان في التكرار الحلقي

سؤال

يسأل المستخدم سؤالا ويخزن الاستجابة.

لتنفيذ سير العمل المباشر، قم بمعالجة السؤال RequestInfoEvent. ExternalInputRequest.AgentResponse يحتوي على المطالبة؛ الخاصية AgentResponse هي حمولة، وليست منفصلة AgentResponseEvent. ExternalInputResponse إرجاع من خلال طلب استئناف سير العمل. autoSend يتحكم الإعداد أدناه في كيفية إضافة الإجابة المقبولة إلى المحادثة، وليس أحداث الاستجابة التي يتم إصدارها.

تستخدم C# وSDKs Python أسماء حقول مختلفة لموجه السؤال. يستخدم هذا المثال أصغر سلوك مشترك: يطلب نصا ويخزن الإجابة في حالة سير العمل.

- kind: Question
  id: ask_name
  displayName: Ask for user name
  property: Local.userName
  prompt:
    kind: Message
    text:
      - "What is your name?"
  entity:
    kind: StringPrebuiltEntity

خصائص:

الخاصية مطلوب Description
prompt Yes قالب النشاط لإرساله كسؤال. استخدم kind: Message مع قائمة text لمطالبات الرسائل.
property Yes مسار لتخزين الاستجابة المستخرجة.
entity Yes نوع الكيان المستخدم لتحليل الاستجابة والتحقق من صحتها. استخدم StringPrebuiltEntity للحصول على إجابات نصية مجانية.
alwaysPrompt No يفرض طرح السؤال حتى عندما يكون للخاصية الهدف قيمة بالفعل.
skipQuestionMode No يتحكم في ما إذا كنت تريد تخطي المطالبة عندما يكون للخاصية الهدف قيمة بالفعل. القيم المدعومة هي AlwaysSkipIfVariableHasValue، SkipOnFirstExecutionIfVariableHasValue، و AlwaysAsk.
repeatCount No الحد الأقصى لعدد الاستجابات غير الصالحة أو غير المعترف بها قبل تخزين defaultValue.
defaultValue No القيمة المراد تخزينها عند repeatCount الوصول إليها دون استجابة صالحة.
defaultValueResponse No قالب نشاط الرسالة لإرساله عند استخدام القيمة الافتراضية.
invalidPrompt No قالب نشاط الرسالة لإرساله عندما لا يتطابق نص الاستجابة مع الكيان المكون.
unrecognizedPrompt No قالب نشاط الرسالة لإرساله عندما لا تحتوي الاستجابة على رسائل.
autoSend No إضافة إجابة صالحة إلى محادثة سير العمل والتحديثات System.LastMessage. تتغير افتراضيا إلى true.

RequestExternalInput

يطلب إدخالا من نظام أو عملية خارجية.

- kind: RequestExternalInput
  id: request_approval
  displayName: Request manager approval
  prompt:
    text: "Please provide approval for this request."
  variable: Local.approvalResult
  default: "pending"

خصائص:

الخاصية مطلوب Description
prompt.text Yes وصف الإدخال المطلوب
variable Yes مسار لتخزين الإدخال
default No القيمة الافتراضية

إجراءات التحكم في سير العمل

EndWorkflow

إنهاء تنفيذ سير العمل.

- kind: EndWorkflow
  id: finish
  displayName: End workflow

EndConversation

إنهاء المحادثة الحالية.

- kind: EndConversation
  id: end_chat
  displayName: End conversation

إنشاء محادثة

إنشاء سياق محادثة جديد.

- kind: CreateConversation
  id: create_new_conv
  displayName: Create new conversation
  conversationId: Local.NewConversationId

خصائص:

الخاصية مطلوب Description
conversationId Yes مسار لتخزين معرف المحادثة الجديد

إجراءات المحادثة (C# فقط)

AddConversationMessage

إضافة رسالة إلى مؤشر ترابط محادثة.

- kind: AddConversationMessage
  id: add_system_message
  displayName: Add system context
  conversationId: =System.ConversationId
  message:
    role: system
    content: =Local.contextInfo

خصائص:

الخاصية مطلوب Description
conversationId Yes معرف المحادثة الهدف
message Yes رسالة لإضافتها
message.role Yes دور الرسالة (النظام، المستخدم، المساعد)
message.content Yes محتوى الرسالة

نسخالرسائل

نسخ الرسائل من محادثة إلى أخرى.

- kind: CopyConversationMessages
  id: copy_context
  displayName: Copy conversation context
  sourceConversationId: =Local.SourceConversation
  targetConversationId: =System.ConversationId
  limit: 10

خصائص:

الخاصية مطلوب Description
sourceConversationId Yes معرف المحادثة المصدر
targetConversationId Yes معرف المحادثة الهدف
limit No الحد الأقصى لعدد الرسائل المراد نسخها

استرداد رسالة الاتصال

استرداد رسالة معينة من محادثة.

- kind: RetrieveConversationMessage
  id: get_message
  displayName: Get specific message
  conversationId: =System.ConversationId
  messageId: =Local.targetMessageId
  variable: Local.retrievedMessage

خصائص:

الخاصية مطلوب Description
conversationId Yes معرف المحادثة
messageId Yes معرف الرسالة المراد استرداده
variable Yes مسار لتخزين الرسالة التي تم استردادها

استرداد رسائل الاتصال

استرداد رسائل متعددة من محادثة.

- kind: RetrieveConversationMessages
  id: get_history
  displayName: Get conversation history
  conversationId: =System.ConversationId
  limit: 20
  newestFirst: true
  variable: Local.conversationHistory

خصائص:

الخاصية مطلوب Description
conversationId Yes معرف المحادثة
limit No الحد الأقصى للرسائل المراد استردادها (افتراضي: 20)
newestFirst No العودة بترتيب تنازلي
after No مؤشر ترقيم الصفحات
before No مؤشر ترقيم الصفحات
variable Yes مسار لتخزين الرسائل التي تم استردادها

مرجع سريع للإجراءات

الإجراء Category C#‎ Python Description
SetVariable المتغير ✅ ✅ تعيين متغير واحد
SetMultipleVariables المتغير ✅ ✅ تعيين متغيرات متعددة
SetTextVariable المتغير ✅ ✅ تعيين متغير نص
ResetVariable المتغير ✅ ✅ مسح متغير
ClearAllVariables المتغير ✅ ✅ مسح كافة المتغيرات
ParseValue المتغير ✅ ✅ تحليل/تحويل البيانات
EditTableV2 المتغير ✅ ✅ تعديل بيانات الجدول
If التحكم في التدفق ✅ ✅ التفرع الشرطي
ConditionGroup التحكم في التدفق ✅ ✅ مفتاح تبديل متعدد الفروع
Foreach التحكم في التدفق ✅ ✅ التكرار عبر المجموعة
BreakLoop التحكم في التدفق ✅ ✅ إنهاء التكرار الحلقي الحالي
ContinueLoop التحكم في التدفق ✅ ✅ التخطي إلى التكرار التالي
GotoAction التحكم في التدفق ✅ ✅ الانتقال إلى الإجراء حسب المعرف
SendActivity الإخرَاج ✅ ✅ إرسال رسالة إلى المستخدم
SendMessage الإخرَاج ✅ ❌ إرسال رسالة نصية مقالب
InvokeAzureAgent وكيل ✅ ✅ استدعاء عامل الذكاء الاصطناعي Azure
InvokeFunctionTool الأداة ✅ ✅ استدعاء الدالة مباشرة
InvokeMcpTool الأداة ✅ ✅ استدعاء أداة خادم MCP
HttpRequestAction HTTP ✅ ✅ استدعاء نقطة نهاية HTTP
Question Human-in-the-Loop ✅ ✅ طرح سؤال على المستخدم
RequestExternalInput Human-in-the-Loop ✅ ✅ طلب إدخال خارجي
EndWorkflow التحكم في سير العمل ✅ ✅ إنهاء سير العمل
EndConversation التحكم في سير العمل ✅ ✅ إنهاء المحادثة
CreateConversation التحكم في سير العمل ✅ ✅ إنشاء محادثة جديدة
AddConversationMessage حوار ✅ ❌ إضافة رسالة إلى مؤشر الترابط
CopyConversationMessages حوار ✅ ❌ نسخ الرسائل
RetrieveConversationMessage حوار ✅ ❌ الحصول على رسالة واحدة
RetrieveConversationMessages حوار ✅ ❌ الحصول على رسائل متعددة

أنماط متقدمة

التزامن متعدد العوامل

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

تمرير العمل من خلال عوامل متعددة في تسلسل.

#
# Sequential agent pipeline for content creation
#
kind: Workflow
trigger:

  kind: OnConversationStart
  id: content_workflow
  actions:

    # First agent: Research
    - kind: InvokeAzureAgent
      id: invoke_researcher
      displayName: Research phase
      conversationId: =System.ConversationId
      agent:
        name: ResearcherAgent

    # Second agent: Write draft
    - kind: InvokeAzureAgent
      id: invoke_writer
      displayName: Writing phase
      conversationId: =System.ConversationId
      agent:
        name: WriterAgent

    # Third agent: Edit
    - kind: InvokeAzureAgent
      id: invoke_editor
      displayName: Editing phase
      conversationId: =System.ConversationId
      agent:
        name: EditorAgent

إعداد C#‎:

using Azure.AI.Projects;
using Azure.AI.Projects.OpenAI;
using Azure.Identity;

// Ensure agents exist in Foundry
AIProjectClient aiProjectClient = new(foundryEndpoint, new DefaultAzureCredential());

await aiProjectClient.CreateAgentAsync(
    agentName: "ResearcherAgent",
    agentDefinition: new DeclarativeAgentDefinition(modelName)
    {
        Instructions = "You are a research specialist..."
    },
    agentDescription: "Research agent for content pipeline");

// Create and run workflow
WorkflowFactory workflowFactory = new("content-pipeline.yaml", foundryEndpoint);
WorkflowRunner runner = new();
await runner.ExecuteAsync(workflowFactory.CreateWorkflow, "Create content about AI");

توجيه العامل الشرطي

توجيه الطلبات إلى عوامل مختلفة بناء على الشروط.

#
# Route to specialized support agents based on category
#
kind: Workflow
trigger:

  kind: OnConversationStart
  id: support_router
  actions:

    # Capture category from user input or set via another action
    - kind: SetVariable
      id: set_category
      variable: Local.category
      value: =System.LastMessage.Text

    - kind: ConditionGroup
      id: route_request
      displayName: Route to appropriate agent
      conditions:
        - condition: =Local.category = "billing"
          id: billing_route
          actions:
            - kind: InvokeAzureAgent
              id: billing_agent
              agent:
                name: BillingAgent
              conversationId: =System.ConversationId
        - condition: =Local.category = "technical"
          id: technical_route
          actions:
            - kind: InvokeAzureAgent
              id: technical_agent
              agent:
                name: TechnicalAgent
              conversationId: =System.ConversationId
      elseActions:
        - kind: InvokeAzureAgent
          id: general_agent
          agent:
            name: GeneralAgent
          conversationId: =System.ConversationId

أنماط تكامل الأدوات

إحضار البيانات مسبقا باستخدام InvokeFunctionTool

إحضار البيانات قبل استدعاء عامل:

#
# Pre-fetch menu data before agent interaction
#
kind: Workflow
trigger:

  kind: OnConversationStart
  id: menu_workflow
  actions:
    # Pre-fetch today's specials
    - kind: InvokeFunctionTool
      id: get_specials
      functionName: GetSpecials
      requireApproval: true
      output:
        autoSend: true
        result: Local.Specials

    # Agent uses pre-fetched data
    - kind: InvokeAzureAgent
      id: menu_agent
      conversationId: =System.ConversationId
      agent:
        name: MenuAgent
      input:
        messages: '=UserMessage("Describe today''s specials: " & Local.Specials)'

تكامل أداة MCP

استدعاء خادم خارجي باستخدام MCP:

#
# Search documentation using MCP
#
kind: Workflow
trigger:

  kind: OnConversationStart
  id: docs_search
  actions:

    - kind: SetVariable
      variable: Local.SearchQuery
      value: =System.LastMessage.Text

    # Search Microsoft Learn
    - kind: InvokeMcpTool
      id: search_docs
      serverUrl: https://learn.microsoft.com/api/mcp
      toolName: microsoft_docs_search
      conversationId: =System.ConversationId
      arguments:
        query: =Local.SearchQuery
      output:
        result: Local.SearchResults
        autoSend: true

    # Summarize results with agent
    - kind: InvokeAzureAgent
      id: summarize
      agent:
        name: SummaryAgent
      conversationId: =System.ConversationId
      input:
        messages: =UserMessage("Summarize these search results")

المتطلبات الأساسية

قبل أن تبدأ، تأكد من أنك تملك:

  • Python 3.10 - 3.13 (Python 3.14 غير مدعومة بعد بسبب توافق PowerFx)
  • حزمة Agent Framework التعريفية المثبتة:
pip install agent-framework-declarative --pre

تسحب هذه الحزمة الأساسي agent-framework-core تلقائيا.

أول سير عمل تعريفي

دعونا ننشئ سير عمل بسيطا يحيي المستخدم بالاسم.

الخطوة 1: إنشاء ملف YAML

إنشاء ملف باسم greeting-workflow.yaml:

name: greeting-workflow
description: A simple workflow that greets the user

inputs:
  name:
    type: string
    description: The name of the person to greet

actions:
  # Set a greeting prefix
  - kind: SetVariable
    id: set_greeting
    displayName: Set greeting prefix
    variable: Local.greeting
    value: Hello

  # Build the full message using an expression
  - kind: SetVariable
    id: build_message
    displayName: Build greeting message
    variable: Local.message
    value: =Concat(Local.greeting, ", ", Workflow.Inputs.name, "!")

  # Send the greeting to the user
  - kind: SendActivity
    id: send_greeting
    displayName: Send greeting to user
    activity:
      text: =Local.message

  # Store the result in outputs
  - kind: SetVariable
    id: set_output
    displayName: Store result in outputs
    variable: Workflow.Outputs.greeting
    value: =Local.message

الخطوة 2: تحميل سير العمل وتشغيله

إنشاء ملف Python لتنفيذ سير العمل:

import asyncio
from pathlib import Path

from agent_framework.declarative import WorkflowFactory


async def main() -> None:
    """Run the greeting workflow."""
    # Create a workflow factory
    factory = WorkflowFactory()

    # Load the workflow from YAML
    workflow_path = Path(__file__).parent / "greeting-workflow.yaml"
    workflow = factory.create_workflow_from_yaml_path(workflow_path)

    print(f"Loaded workflow: {workflow.name}")
    print("-" * 40)

    # Run with a name input
    result = await workflow.run({"name": "Alice"})
    for output in result.get_outputs():
        print(f"Output: {output}")
    for output in result.get_intermediate_outputs():
        print(f"Intermediate: {output}")


if __name__ == "__main__":
    asyncio.run(main())

الإخراج المتوقع

Loaded workflow: greeting-workflow
----------------------------------------
Output: Hello, Alice!

المفاهيم الأساسية

مساحات أسماء المتغيرات

تستخدم مهام سير العمل التعريفية متغيرات مساحة الاسم لتنظيم الحالة:

مساحة الاسم Description Example
Local.* المتغيرات المحلية لسير العمل Local.message
Workflow.Inputs.* معلمات الإدخال Workflow.Inputs.name
Workflow.Outputs.* قيم الإخراج Workflow.Outputs.result
System.* القيم التي يوفرها النظام System.ConversationId

مسارات سمة الكائن

يميز Python مفاتيح القاموس عن سمات الكائن عندما يجتاز مسار الحالة القيم المتداخلة. تحتفظ مفاتيح القاموس بقيمة السلسلة الدقيقة الخاصة بها، ولكن يجب أن يتطابق مقطع سمة الكائن مع [A-Za-z][A-Za-z0-9_]*.

على سبيل المثال، Local.profile.display_name يمكن قراءة سمة كائن عام. Local.profile._private Local.profile.display-name ولا تقم بالوصول إلى سمات الكائن وإرجاع الإعداد الافتراضي للبحث. إذا كان Local.bag قاموسا، Local.bag._private فلا يزال يقرأ مفتاحه _private . تظل UUIDs والأسماء الواصلة والسلاسل غير المنتظمة الأخرى أيضا مفاتيح قاموس صالحة.

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

لغة التعبير

يتم تقييم القيم مسبوقة ب = كتعبيرات:

# Literal value (no evaluation)
value: Hello

# Expression (evaluated at runtime)
value: =Concat("Hello, ", Workflow.Inputs.name)

تشمل الوظائف الشائعة:

  • Concat(str1, str2, ...) - سلسلة السلاسل
  • If(condition, trueValue, falseValue) - التعبير الشرطي
  • IsBlank(value) - تحقق مما إذا كانت القيمة فارغة

حدود اجتياز حالة PowerFx

يتحقق Python من الحالة التعريفية قبل كتابة الحالة واللقطات، وقبل تحويل القيم إلى رموز PowerFx. يتم رفض الهياكل الدورية بدلا من اقتطاعها.

يستخدم كل اجتياز هذه الحدود الثابتة:

  • الحد الأقصى لعمق 64، مع قيمة الجذر في العمق 0.
  • بحد أقصى 10,000 قيمة تمت زيارتها، بما في ذلك الحاويات ومفاتيح التعيين.
  • الحد الأقصى لحجم التجميع 1,048,576 حرف سلسلة وبايت ثنائي.

يتم عد المراجع والأسماء المستعارة المتكررة مرة أخرى في كل مرة يتم اجتيازها. يتم رفع حد الدورة أو تجاوزه ValueError أثناء كتابة الحالة أو اللقطة، أو أثناء تحويل PowerFx. لا تربط حدود الاجتياز هذه تنفيذ تعبير PowerFx أو تعريف التطبيق Python خطافات النسخ أو التحويل.

أنواع الأفعال

تدعم مهام سير العمل التعريفية أنواع الإجراءات المختلفة:

Category الإجرَاءَات
إدارة المتغيرات SetVariable، SetMultipleVariables، ResetVariable
التحكم في التدفق If، ConditionGroup، Foreach، BreakLoop، ، ContinueLoopGotoAction
الإخرَاج SendActivity
استدعاء العامل InvokeAzureAgent
استدعاء الأداة InvokeFunctionTool، InvokeMcpTool
HTTP HttpRequestAction
Human-in-the-Loop Question، RequestExternalInput
التحكم في سير العمل EndWorkflow، EndConversation، CreateConversation

مرجع الإجراءات

الإجراءات هي اللبنات الأساسية لسير العمل التعريفي. ينفذ كل إجراء عملية معينة، ويتم تنفيذ الإجراءات بشكل تسلسلي بالترتيب الذي تظهر به في ملف YAML.

بنية الإجراء

تشترك جميع الإجراءات في الخصائص الشائعة:

- kind: ActionType      # Required: The type of action
  id: unique_id         # Optional: Unique identifier for referencing
  displayName: Name     # Optional: Human-readable name for logging
  # Action-specific properties...

إجراءات إدارة المتغيرات

SetVariable

تعيين متغير إلى قيمة محددة.

- kind: SetVariable
  id: set_greeting
  displayName: Set greeting message
  variable: Local.greeting
  value: Hello World

باستخدام تعبير:

- kind: SetVariable
  variable: Local.fullName
  value: =Concat(Workflow.Inputs.firstName, " ", Workflow.Inputs.lastName)

خصائص:

الخاصية مطلوب Description
variable Yes مسار المتغير (على سبيل المثال، ، Local.name، Workflow.Outputs.result)
value Yes القيمة المراد تعيينها (حرفي أو تعبير)

Note

يدعم SetValue Python أيضا نوع الإجراء، الذي يستخدم path بدلا من variable للخاصية الهدف. يحقق كل من SetVariable (مع variable) و SetValue (مع path) نفس النتيجة. على سبيل المثال:

- kind: SetValue
  id: set_greeting
  path: Local.greeting
  value: Hello World

SetMultipleVariables

تعيين متغيرات متعددة في إجراء واحد.

- kind: SetMultipleVariables
  id: initialize_vars
  displayName: Initialize variables
  variables:
    Local.counter: 0
    Local.status: pending
    Local.message: =Concat("Processing order ", Workflow.Inputs.orderId)

خصائص:

الخاصية مطلوب Description
variables Yes خريطة المسارات المتغيرة للقيم

إعادة التعيين القابلة للتغيير

مسح قيمة المتغير.

- kind: ResetVariable
  id: clear_counter
  variable: Local.counter

خصائص:

الخاصية مطلوب Description
variable Yes مسار متغير لإعادة التعيين

إجراءات تدفق التحكم

لو

تنفيذ الإجراءات بشكل مشروط استنادا إلى شرط.

- kind: If
  id: check_age
  displayName: Check user age
  condition: =Workflow.Inputs.age >= 18
  then:
    - kind: SendActivity
      activity:
        text: "Welcome, adult user!"
  else:
    - kind: SendActivity
      activity:
        text: "Welcome, young user!"

الشروط المتداخلة:

- kind: If
  condition: =Workflow.Inputs.role = "admin"
  then:
    - kind: SendActivity
      activity:
        text: "Admin access granted"
  else:
    - kind: If
      condition: =Workflow.Inputs.role = "user"
      then:
        - kind: SendActivity
          activity:
            text: "User access granted"
      else:
        - kind: SendActivity
          activity:
            text: "Access denied"

خصائص:

الخاصية مطلوب Description
condition Yes التعبير الذي يتم تقييمه إلى صواب/خطأ
then Yes الإجراءات التي يجب تنفيذها إذا كان الشرط صحيحا
else No الإجراءات التي يجب تنفيذها إذا كان الشرط خطأ

مجموعة الشروط

تقييم شروط متعددة مثل عبارة تبديل/حالة.

- kind: ConditionGroup
  id: route_by_category
  displayName: Route based on category
  conditions:
    - condition: =Workflow.Inputs.category = "electronics"
      id: electronics_branch
      actions:
        - kind: SetVariable
          variable: Local.department
          value: Electronics Team
    - condition: =Workflow.Inputs.category = "clothing"
      id: clothing_branch
      actions:
        - kind: SetVariable
          variable: Local.department
          value: Clothing Team
    - condition: =Workflow.Inputs.category = "food"
      id: food_branch
      actions:
        - kind: SetVariable
          variable: Local.department
          value: Food Team
  elseActions:
    - kind: SetVariable
      variable: Local.department
      value: General Support

خصائص:

الخاصية مطلوب Description
conditions Yes قائمة أزواج الشرط/الإجراءات (فوز المطابقة الأولى)
elseActions No الإجراءات إذا لم يتطابق أي شرط

Foreach

يكرر عبر مجموعة.

- kind: Foreach
  id: process_items
  displayName: Process each item
  source: =Workflow.Inputs.items
  itemName: item
  indexName: index
  actions:
    - kind: SendActivity
      activity:
        text: '=Concat("Processing item ", index, ": ", item)'

خصائص:

الخاصية مطلوب Description
source Yes تعبير يرجع مجموعة
itemName No اسم المتغير للعنصر الحالي (الافتراضي: item)
indexName No اسم المتغير للفهرس الحالي (الافتراضي: index)
actions Yes الإجراءات التي يجب تنفيذها لكل عنصر

BreakLoop

إنهاء الحلقة الحالية على الفور.

- kind: Foreach
  source: =Workflow.Inputs.items
  actions:
    - kind: If
      condition: =item = "stop"
      then:
        - kind: BreakLoop
    - kind: SendActivity
      activity:
        text: =item

ContinueLoop

يتخطى إلى التكرار التالي للحلقة.

- kind: Foreach
  source: =Workflow.Inputs.numbers
  actions:
    - kind: If
      condition: =item < 0
      then:
        - kind: ContinueLoop
    - kind: SendActivity
      activity:
        text: '=Concat("Positive number: ", item)'

GotoAction

الانتقال إلى إجراء معين حسب المعرف.

- kind: SetVariable
  id: start_label
  variable: Local.attempts
  value: =Local.attempts + 1

- kind: SendActivity
  activity:
    text: =Concat("Attempt ", Local.attempts)

- kind: If
  condition: =And(Local.attempts < 3, Not(Local.success))
  then:
    - kind: GotoAction
      actionId: start_label

خصائص:

الخاصية مطلوب Description
actionId Yes معرف الإجراء للانتقال إلى

إجراءات الإخراج

نشاط الإرسال

إرسال رسالة إلى المستخدم.

- kind: SendActivity
  id: send_welcome
  displayName: Send welcome message
  activity:
    text: "Welcome to our service!"

باستخدام تعبير:

- kind: SendActivity
  activity:
    text: =Concat("Hello, ", Workflow.Inputs.name, "! How can I help you today?")

خصائص:

الخاصية مطلوب Description
activity Yes النشاط المراد إرساله
activity.text Yes نص الرسالة (حرفي أو تعبير)

في Python، يتم تقييم النص الذي يتم تأليفه الذي يبدأ بالبيانات = وإرساله كبيانات. لا تتم معالجة نتيجة التعبير مرة أخرى للاستيفاء {Variable.Path} . تأليف القالب مباشرة، مثل Hello, {Local.name}!، أو إنشاء السلسلة الكاملة في التعبير، مثل ="Hello, " & Local.name & "!".

إجراءات استدعاء العامل

استدعاء AzureAgent

استدعاء عامل الذكاء الاصطناعي Azure.

استدعاء أساسي:

- kind: InvokeAzureAgent
  id: call_assistant
  displayName: Call assistant agent
  agent:
    name: AssistantAgent
  conversationId: =System.ConversationId

مع تكوين الإدخال والإخراج:

- kind: InvokeAzureAgent
  id: call_analyst
  displayName: Call analyst agent
  agent:
    name: AnalystAgent
  conversationId: =System.ConversationId
  input:
    messages: =Local.userMessage
    arguments:
      topic: =Workflow.Inputs.topic
  output:
    responseObject: Local.AnalystResult
    messages: Local.AnalystMessages
    autoSend: true

مع التكرار الحلقي الخارجي (يستمر حتى يتم استيفاء الشرط):

- kind: InvokeAzureAgent
  id: support_agent
  agent:
    name: SupportAgent
  input:
    externalLoop:
      when: =Not(Local.IsResolved)
  output:
    responseObject: Local.SupportResult

خصائص:

الخاصية مطلوب Description
agent.name Yes اسم الوكيل المسجل
conversationId No معرف سياق المحادثة
input.messages No الرسائل التي يجب إرسالها إلى العامل
input.arguments No الوسيطات التي يجب تقييمها وإضافتها إلى نص إدخال العامل
input.externalLoop.when No شرط لمتابعة حلقة العامل
output.responseObject No مسار لتخزين استجابة العامل
output.messages No مسار لتخزين رسائل المحادثة
output.autoSend No إرسال الاستجابة تلقائيا إلى إخراج سير العمل. يقبل قيمة منطقية أو تعبير ويتم تعيينه افتراضيا = إلى true.

في Python، InvokeAzureAgent يقيم كل قيمة مكونة input.arguments وينسق وسيطات nonempty كخطوطkey: value. إذا قمت بتعيين input.messages، يتبع نص الرسالة التي تم تقييمها أسطر الوسيطة. عندما input.arguments تحتوي على وسيطة واحدة على الأقل وتحذف input.messages، Python تستخدم نص الوسيطة فقط ولا تلحق القيم الاحتياطية من Local.inputأو Local.userInputSystem.LastMessage.Textأو أو Workflow.Inputs.

يتم تقييم output.autoSend Python مقابل حالة سير العمل الحالية قبل كل استدعاء، بما في ذلك عمليات تشغيل التكرار الحلقي الخارجي المستأنفة. تؤدي النتيجة الخاطئة إلى منع إخراج سير العمل التلقائي فقط؛ لا يزال العامل قيد التشغيل، ولا تزال مخرجات الاستجابة والرسائل المكونة مخزنة.

إجراءات الأداة وHTTP

استدعاءFunctionTool

استدعاء وظيفة Python مسجلة مباشرة من سير العمل دون المرور عبر عامل الذكاء الاصطناعي.

- kind: InvokeFunctionTool
  id: invoke_weather
  displayName: Get weather data
  functionName: get_weather
  arguments:
    location: =Local.location
    unit: =Local.unit
  output:
    result: Local.weatherInfo
    messages: Local.weatherToolCallItems
    autoSend: true

خصائص:

الخاصية مطلوب Description
functionName Yes اسم الدالة المسجلة لاستدعاء
arguments No وسيطات لتمريرها إلى الدالة
output.result No مسار لتخزين نتيجة الدالة
output.messages No مسار لتخزين رسائل الدالة
output.autoSend No إرسال النتيجة تلقائيا إلى إخراج سير العمل. يقبل قيمة منطقية أو تعبير ويتم تعيينه افتراضيا = إلى true.

يتم تقييم output.autoSend Python مقابل حالة سير العمل الحالية مباشرة قبل تشغيل الأداة. تؤدي النتيجة الخاطئة إلى منع إخراج سير العمل التلقائي فقط؛ لا تزال الأداة قيد التشغيل، ولا تزال مخرجات النتائج والرسائل المكونة مخزنة. تكتمل الموافقة المرفوضة دون تقييم التعبير.

إعداد Python ل InvokeFunctionTool:

يجب تسجيل الدالات باستخدام WorkflowFactoryregister_tool:

from agent_framework.declarative import WorkflowFactory

# Define your functions
def get_weather(location: str, unit: str = "F") -> dict:
    """Get weather information for a location."""
    # Your implementation here
    return {"location": location, "temp": 72, "unit": unit}

def format_message(template: str, data: dict) -> str:
    """Format a message template with data."""
    return template.format(**data)

# Register functions with the factory
factory = (
    WorkflowFactory()
    .register_tool("get_weather", get_weather)
    .register_tool("format_message", format_message)
)

# Load and run the workflow
workflow = factory.create_workflow_from_yaml_path("workflow.yaml")
result = await workflow.run({"location": "Seattle", "unit": "F"})

InvokeMcpTool

استدعاء أداة على خادم MCP من خلال المكون MCPToolHandler.

- kind: InvokeMcpTool
  id: search_docs
  serverUrl: https://learn.microsoft.com/api/mcp
  serverLabel: microsoft_docs
  toolName: microsoft_docs_search
  arguments:
    query: =Local.searchQuery
  output:
    result: Local.searchResults
    messages: Local.toolMessage
    autoSend: true

خصائص:

الخاصية مطلوب Description
serverUrl Yes عنوان URL لخادم MCP
toolName Yes اسم الأداة على خادم MCP
serverLabel No تسمية خادم قابل للقراءة من قبل الإنسان
arguments No الوسيطات التي تم تمريرها إلى الأداة
headers No عناوين الطلبات؛ يتم تخطي القيم الفارغة
connection.name No الاتصال المسمى للمعالجات المخصصة
conversationId No إضافة إخراج أداة ناجحة إلى المحادثة
requireApproval No طلب الموافقة قبل استدعاء الأداة
output.result No مسار لتخزين إخراج الأداة التي تم تحليلها
output.messages No مسار لتخزين رسالة الأداة
output.autoSend No يصدر إخراج الأداة إلى نتيجة سير العمل؛ الإعدادات الافتراضية ل true

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

إعداد Python ل InvokeMcpTool:

مرر معالج أداة MCP إلى WorkflowFactory. استخدم معالجا مخصصا عندما تحتاج إلى المصادقة أو الاتصالات المدارة أو قائمة السماح بعنوان URL.

from agent_framework.declarative import DefaultMCPToolHandler, WorkflowFactory

factory = WorkflowFactory(mcp_tool_handler=DefaultMCPToolHandler())
workflow = factory.create_workflow_from_yaml_path("workflow.yaml")

client_providerبدون ، DefaultMCPToolHandler يعيد استخدام جلسات عمل MCP من خلال ذاكرة تخزين مؤقت محددة. client_providerمع ، فإنه ينشئ ويغلق أداة MCP منفصلة وجلسة عمل لكل استدعاء، بما في ذلك tools/list، حتى عندما يقوم الموفر بإرجاع نفس العميل أو None. يقوم المعالج بإغلاق عملاء HTTP الاحتياطيين الذين تم إنشاؤهم داخليا، ولكن تظل المثيلات التي يوفرها httpx.AsyncClient المتصل مملوكة للمتصل.

لا تحتفظ الاستدعاءات المدعومة من الموفر بحالة جلسة عمل الخادم. إذا كان سير العمل يتطلب استمرارية جلسة عمل MCP، فنفذ مخصصا MCPToolHandler بمصادقة صريحة وعقد مدة بقاء.

HttpRequestAction

يرسل طلب HTTP من خلال المكون HttpRequestHandler. يتم تحليل استجابات JSON الناجحة قبل التعيين. تفشل الاستجابات غير 2xx في الإجراء. في Python، يتضمن الخطأ عنوان URL للطلب ورمز الحالة ولكنه يحذف نص الاستجابة.

- kind: HttpRequestAction
  id: fetch_repo_info
  method: GET
  url: =Concat("https://api.github.com/repos/", Local.repoName)
  headers:
    Accept: application/vnd.github+json
    User-Agent: agent-framework
  queryParameters:
    per_page: 10
  response: Local.repoInfo
  responseHeaders: Local.repoHeaders

خصائص:

الخاصية مطلوب Description
url Yes عنوان URL للطلب المطلق
method No أسلوب HTTP؛ الإعدادات الافتراضية ل GET
headers No رؤوس الطلبات
queryParameters No معلمات الاستعلام الملحقة بعنوان URL
body No نص الطلب؛ استخدام kind: jsonأو rawأو none
requestTimeoutInMilliseconds No مهلة عند الطلب
connection.name No الاتصال المسمى للمعالجات المخصصة
conversationId No إضافة نص استجابة ناجح إلى المحادثة
response No مسار لتخزين نص الاستجابة الذي تم تحليله
responseHeaders No مسار لتخزين رؤوس الاستجابة

Python الإعداد ل HttpRequestAction:

مرر معالج طلب HTTP إلى WorkflowFactory. استخدم معالجا مخصصا عندما تحتاج إلى المصادقة أو إعادة المحاولة أو قائمة السماح بعنوان URL.

from agent_framework.declarative import DefaultHttpRequestHandler, WorkflowFactory

factory = WorkflowFactory(http_request_handler=DefaultHttpRequestHandler())
workflow = factory.create_workflow_from_yaml_path("workflow.yaml")

يرفض المعالج الافتراضي عناوين URL التي ليست عناوين URL مطلقة ل HTTP أو HTTPS. يقوم بتطبيع عنوان URL وإلحاقه queryParameters بعد أي استعلام موجود مع الحفاظ على ترتيب الاستعلام الحالي ووحدات البايت.

client_provider يتلقى لقطة تمت تسويتهاHttpRequestInfo. تحتوي اللقطة على عنوان URL الذي تم تكوينه في info.url وفارغ info.query_parameters؛ لا يتم تعديل معلومات الطلب الأصلية. لا تزال الإعدادات الافتراضية للعميل المحدد تنطبق. يظل سلوك إعادة التوجيه خاضعا للتحكم في إعداد هذا العميل follow_redirects ، ولا يتم استدعاء الموفر مرة أخرى لوثبة إعادة التوجيه.

يعيد المعالج الافتراضي استخدام عميل HTTP مملوك داخليا، ولكنه لا يستمر في ملفات تعريف الارتباط للاستجابة. إذا كان سير العمل يتطلب ملفات تعريف الارتباط للمصادقة أو استمرارية الجلسة أو ترابط موازن التحميل، فمرر مكونا httpx.AsyncClient من خلال client= أو إرجاع واحد من client_provider=. قم بتحديد نطاق العملاء الحاملين لملفات تعريف الارتباط لأحد العملاء الأساسيين المصادق عليهم وإغلاق العملاء الذين يوفرهم المتصل في التطبيق الخاص بك. تظل رؤوس الطلبات ورؤوس الاستجابة Set-Cookie الصريحة Cookie متوفرة.

إجراءات الإنسان في التكرار الحلقي

سؤال

يسأل المستخدم سؤالا ويخزن الاستجابة.

تستخدم C# وSDKs Python أسماء حقول مختلفة لموجه السؤال. يستخدم هذا القسم أصغر سلوك مشترك: اطلب نصا وقم بتخزين الإجابة في حالة سير العمل.

- kind: Question
  id: ask_name
  displayName: Ask for user name
  question:
    text: "What is your name?"
  property: Local.userName

خصائص:

الخاصية مطلوب Description
question Yes السؤال الذي يجب طرحه. استخدم question.text للنموذج المتداخل أو قيمة سلسلة للنموذج المضغوط.
variable Yes مسار لتخزين الاستجابة. استخدم property كاسم حقل المستوى الأعلى البديل عندما تريد محاذاته مع اسم حقل وجهة C#‎.
default No القيمة الافتراضية المضمنة في بيانات تعريف الطلب للمتصل لتطبيقها.
choices No قائمة الخيارات المضافة لطلب بيانات التعريف. يمكن أن يكون كل اختيار سلسلة أو كائن مع value حقول اختيارية label .
allowFreeText No يشير إلى ما إذا كان يمكن للمتصل قبول النص خارج المكون choices. تتغير افتراضيا إلى true.

يقبل Python أيضا أسماء حقول بديلة للتوافق. استخدم المستوى text الأعلى بدلا من question و defaultValue بدلا من default.

- kind: Question
  id: ask_color
  text: "Choose a color:"
  property: Local.color
  choices:
    - value: red
      label: Red
    - blue
  allowFreeText: false

RequestExternalInput

يطلب إدخالا من نظام أو عملية خارجية.

- kind: RequestExternalInput
  id: request_approval
  displayName: Request manager approval
  prompt:
    text: "Please provide approval for this request."
  variable: Local.approvalResult
  default: "pending"

خصائص:

الخاصية مطلوب Description
prompt.text Yes وصف الإدخال المطلوب
variable Yes مسار لتخزين الإدخال
default No القيمة الافتراضية

إجراءات التحكم في سير العمل

EndWorkflow

إنهاء تنفيذ سير العمل.

- kind: EndWorkflow
  id: finish
  displayName: End workflow

EndConversation

إنهاء المحادثة الحالية.

- kind: EndConversation
  id: end_chat
  displayName: End conversation

إنشاء محادثة

إنشاء سياق محادثة جديد.

- kind: CreateConversation
  id: create_new_conv
  displayName: Create new conversation
  conversationId: Local.NewConversationId

خصائص:

الخاصية مطلوب Description
conversationId Yes مسار لتخزين معرف المحادثة الجديد

مرجع سريع للإجراءات

الإجراء Category Description
SetVariable المتغير تعيين متغير واحد
SetMultipleVariables المتغير تعيين متغيرات متعددة
ResetVariable المتغير مسح متغير
If التحكم في التدفق التفرع الشرطي
ConditionGroup التحكم في التدفق مفتاح تبديل متعدد الفروع
Foreach التحكم في التدفق التكرار عبر المجموعة
BreakLoop التحكم في التدفق إنهاء التكرار الحلقي الحالي
ContinueLoop التحكم في التدفق التخطي إلى التكرار التالي
GotoAction التحكم في التدفق الانتقال إلى الإجراء حسب المعرف
SendActivity الإخرَاج إرسال رسالة إلى المستخدم
InvokeAzureAgent وكيل استدعاء عامل الذكاء الاصطناعي Azure
InvokeFunctionTool الأداة استدعاء الدالة المسجلة
InvokeMcpTool الأداة استدعاء أداة خادم MCP
HttpRequestAction HTTP استدعاء نقطة نهاية HTTP
Question Human-in-the-Loop طرح سؤال على المستخدم
RequestExternalInput Human-in-the-Loop طلب إدخال خارجي
EndWorkflow التحكم في سير العمل إنهاء سير العمل
EndConversation التحكم في سير العمل إنهاء المحادثة
CreateConversation التحكم في سير العمل إنشاء محادثة جديدة

بناء جملة التعبير

تستخدم مهام سير العمل التعريفية لغة تعبير تشبه PowerFx لإدارة الحالة واحسب القيم الديناميكية. يتم تقييم القيم مسبوقة ب = كتعبيرات في وقت التشغيل.

تفاصيل مساحة الاسم المتغيرة

مساحة الاسم Description Access
Local.* المتغيرات المحلية لسير العمل القراءة/الكتابة
Workflow.Inputs.* معلمات الإدخال التي تم تمريرها إلى سير العمل للقراءة فقط
Workflow.Outputs.* القيم التي تم إرجاعها من سير العمل القراءة/الكتابة
System.* القيم التي يوفرها النظام للقراءة فقط
Agent.* النتائج من استدعاءات العامل للقراءة فقط

متغيرات النظام

المتغير Description
System.ConversationId معرف المحادثة الحالي
System.LastMessage أحدث رسالة
System.Timestamp الطابع الزمني الحالي

متغيرات العامل

بعد استدعاء عامل، قم بالوصول إلى بيانات الاستجابة من خلال متغير الإخراج:

actions:
  - kind: InvokeAzureAgent
    id: call_assistant
    agent:
      name: MyAgent
    output:
      responseObject: Local.AgentResult

  # Access agent response
  - kind: SendActivity
    activity:
      text: =Local.AgentResult.text

القيم الحرفية مقابل قيم التعبير

# Literal string (stored as-is)
value: Hello World

# Expression (evaluated at runtime)
value: =Concat("Hello ", Workflow.Inputs.name)

# Literal number
value: 42

# Expression returning a number
value: =Workflow.Inputs.quantity * 2

عمليات السلسلة

Concat

تسلسل سلاسل متعددة:

value: =Concat("Hello, ", Workflow.Inputs.name, "!")
# Result: "Hello, Alice!" (if Workflow.Inputs.name is "Alice")

value: =Concat(Local.firstName, " ", Local.lastName)
# Result: "John Doe" (if firstName is "John" and lastName is "Doe")

IsBlank

تحقق مما إذا كانت القيمة فارغة أو غير معرفة:

condition: =IsBlank(Workflow.Inputs.optionalParam)
# Returns true if the parameter is not provided

value: =If(IsBlank(Workflow.Inputs.name), "Guest", Workflow.Inputs.name)
# Returns "Guest" if name is blank, otherwise returns the name

التعبيرات الشرطية

الدالة If

إرجاع قيم مختلفة استنادا إلى شرط:

value: =If(Workflow.Inputs.age < 18, "minor", "adult")

value: =If(Local.count > 0, "Items found", "No items")

# Nested conditions
value: =If(Workflow.Inputs.role = "admin", "Full access", If(Workflow.Inputs.role = "user", "Limited access", "No access"))

عوامل المقارنة

المشغل Description Example
= يساوي =Workflow.Inputs.status = "active"
<> لا يساوي =Workflow.Inputs.status <> "deleted"
< أقل من =Workflow.Inputs.age < 18
> أكبر من =Workflow.Inputs.count > 0
<= أصغر من أو يساوي =Workflow.Inputs.score <= 100
>= أكبر من أو يساوي =Workflow.Inputs.quantity >= 1

دالات منطقية

# Or - returns true if any condition is true
condition: =Or(Workflow.Inputs.role = "admin", Workflow.Inputs.role = "moderator")

# And - returns true if all conditions are true
condition: =And(Workflow.Inputs.age >= 18, Workflow.Inputs.hasConsent)

# Not - negates a condition
condition: =Not(IsBlank(Workflow.Inputs.email))

العمليات الرياضية

# Addition
value: =Workflow.Inputs.price + Workflow.Inputs.tax

# Subtraction
value: =Workflow.Inputs.total - Workflow.Inputs.discount

# Multiplication
value: =Workflow.Inputs.quantity * Workflow.Inputs.unitPrice

# Division
value: =Workflow.Inputs.total / Workflow.Inputs.count

أمثلة التعبير العملي

تصنيف المستخدم

name: categorize-user
inputs:
  age:
    type: integer
    description: User's age

actions:
  - kind: SetVariable
    variable: Local.age
    value: =Workflow.Inputs.age

  - kind: SetVariable
    variable: Local.category
    value: =If(Local.age < 13, "child", If(Local.age < 20, "teenager", If(Local.age < 65, "adult", "senior")))

  - kind: SendActivity
    activity:
      text: '=Concat("You are categorized as: ", Local.category)'

  - kind: SetVariable
    variable: Workflow.Outputs.category
    value: =Local.category

تحية شرطية

name: smart-greeting
inputs:
  name:
    type: string
    description: User's name (optional)
  timeOfDay:
    type: string
    description: morning, afternoon, or evening

actions:
  # Set the greeting based on time of day
  - kind: SetVariable
    variable: Local.timeGreeting
    value: =If(Workflow.Inputs.timeOfDay = "morning", "Good morning", If(Workflow.Inputs.timeOfDay = "afternoon", "Good afternoon", "Good evening"))

  # Handle optional name
  - kind: SetVariable
    variable: Local.userName
    value: =If(IsBlank(Workflow.Inputs.name), "friend", Workflow.Inputs.name)

  # Build the full greeting
  - kind: SetVariable
    variable: Local.fullGreeting
    value: =Concat(Local.timeGreeting, ", ", Local.userName, "!")

  - kind: SendActivity
    activity:
      text: =Local.fullGreeting

التحقق من صحة الإدخال

name: validate-order
inputs:
  quantity:
    type: integer
    description: Number of items to order
  email:
    type: string
    description: Customer email

actions:
  # Check if inputs are valid
  - kind: SetVariable
    variable: Local.isValidQuantity
    value: =And(Workflow.Inputs.quantity > 0, Workflow.Inputs.quantity <= 100)

  - kind: SetVariable
    variable: Local.hasEmail
    value: =Not(IsBlank(Workflow.Inputs.email))

  - kind: SetVariable
    variable: Local.isValid
    value: =And(Local.isValidQuantity, Local.hasEmail)

  - kind: If
    condition: =Local.isValid
    then:
      - kind: SendActivity
        activity:
          text: "Order validated successfully!"
    else:
      - kind: SendActivity
        activity:
          text: =If(Not(Local.isValidQuantity), "Invalid quantity (must be 1-100)", "Email is required")

أنماط متقدمة

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

التزامن متعدد العوامل

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

تمرير العمل من خلال عوامل متعددة في تسلسل، حيث يعتمد كل عامل على إخراج العامل السابق.

حالة الاستخدام: مسارات إنشاء المحتوى حيث يتعامل المتخصصون المختلفون مع البحث والكتابة والتحرير.

name: content-pipeline
description: Sequential agent pipeline for content creation

kind: Workflow
trigger:
  kind: OnConversationStart
  id: content_workflow
  actions:
    # First agent: Research and analyze
    - kind: InvokeAzureAgent
      id: invoke_researcher
      displayName: Research phase
      conversationId: =System.ConversationId
      agent:
        name: ResearcherAgent

    # Second agent: Write draft based on research
    - kind: InvokeAzureAgent
      id: invoke_writer
      displayName: Writing phase
      conversationId: =System.ConversationId
      agent:
        name: WriterAgent

    # Third agent: Edit and polish
    - kind: InvokeAzureAgent
      id: invoke_editor
      displayName: Editing phase
      conversationId: =System.ConversationId
      agent:
        name: EditorAgent

إعداد Python:

from agent_framework.declarative import WorkflowFactory

# Create factory and register agents
factory = WorkflowFactory()
factory.register_agent("ResearcherAgent", researcher_agent)
factory.register_agent("WriterAgent", writer_agent)
factory.register_agent("EditorAgent", editor_agent)

# Load and run
workflow = factory.create_workflow_from_yaml_path("content-pipeline.yaml")
result = await workflow.run({"topic": "AI in healthcare"})

توجيه العامل الشرطي

توجيه الطلبات إلى عوامل مختلفة استنادا إلى الإدخال أو النتائج المتوسطة.

حالة الاستخدام: أنظمة الدعم التي توجه إلى وكلاء متخصصين استنادا إلى نوع المشكلة.

name: support-router
description: Route to specialized support agents

inputs:
  category:
    type: string
    description: Support category (billing, technical, general)

actions:
  - kind: ConditionGroup
    id: route_request
    displayName: Route to appropriate agent
    conditions:
      - condition: =Workflow.Inputs.category = "billing"
        id: billing_route
        actions:
          - kind: InvokeAzureAgent
            id: billing_agent
            agent:
              name: BillingAgent
            conversationId: =System.ConversationId
      - condition: =Workflow.Inputs.category = "technical"
        id: technical_route
        actions:
          - kind: InvokeAzureAgent
            id: technical_agent
            agent:
              name: TechnicalAgent
            conversationId: =System.ConversationId
    elseActions:
      - kind: InvokeAzureAgent
        id: general_agent
        agent:
          name: GeneralAgent
        conversationId: =System.ConversationId

عامل مع تكرار حلقي خارجي

استمر في تفاعل العامل حتى يتم استيفاء شرط، مثل المشكلة التي يتم حلها.

حالة الاستخدام: دعم المحادثات التي تستمر حتى يتم حل مشكلة المستخدم.

name: support-conversation
description: Continue support until resolved

actions:
  - kind: SetVariable
    variable: Local.IsResolved
    value: false

  - kind: InvokeAzureAgent
    id: support_agent
    displayName: Support agent with external loop
    agent:
      name: SupportAgent
    conversationId: =System.ConversationId
    input:
      externalLoop:
        when: =Not(Local.IsResolved)
    output:
      responseObject: Local.SupportResult

  - kind: SendActivity
    activity:
      text: "Thank you for contacting support. Your issue has been resolved."

أنماط التحكم في التكرار الحلقي

محادثة الوكيل التكراري

إنشاء محادثات ذهابا وإيابا بين الوكلاء باستخدام التكرار المتحكم به.

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

name: student-teacher
description: Iterative learning conversation between student and teacher

kind: Workflow
trigger:
  kind: OnConversationStart
  id: learning_session
  actions:
    # Initialize turn counter
    - kind: SetVariable
      id: init_counter
      variable: Local.TurnCount
      value: 0

    - kind: SendActivity
      id: start_message
      activity:
        text: '=Concat("Starting session for: ", Workflow.Inputs.problem)'

    # Student attempts solution (loop entry point)
    - kind: SendActivity
      id: student_label
      activity:
        text: "\n[Student]:"

    - kind: InvokeAzureAgent
      id: student_attempt
      conversationId: =System.ConversationId
      agent:
        name: StudentAgent

    # Teacher reviews
    - kind: SendActivity
      id: teacher_label
      activity:
        text: "\n[Teacher]:"

    - kind: InvokeAzureAgent
      id: teacher_review
      conversationId: =System.ConversationId
      agent:
        name: TeacherAgent
      output:
        messages: Local.TeacherResponse

    # Increment counter
    - kind: SetVariable
      id: increment
      variable: Local.TurnCount
      value: =Local.TurnCount + 1

    # Check completion conditions
    - kind: ConditionGroup
      id: check_completion
      conditions:
        # Success: Teacher congratulated student
        - condition: =Not(IsBlank(Find("congratulations", Local.TeacherResponse)))
          id: success_check
          actions:
            - kind: SendActivity
              activity:
                text: "Session complete - student succeeded!"
            - kind: SetVariable
              variable: Workflow.Outputs.result
              value: success
        # Continue: Under turn limit
        - condition: =Local.TurnCount < 4
          id: continue_check
          actions:
            - kind: GotoAction
              actionId: student_label
      elseActions:
        # Timeout: Reached turn limit
        - kind: SendActivity
          activity:
            text: "Session ended - turn limit reached."
        - kind: SetVariable
          variable: Workflow.Outputs.result
          value: timeout

حلقات Counter-Based

تنفيذ حلقات العد التقليدية باستخدام المتغيرات و GotoAction.

name: counter-loop
description: Process items with a counter

actions:
  - kind: SetVariable
    variable: Local.counter
    value: 0

  - kind: SetVariable
    variable: Local.maxIterations
    value: 5

  # Loop start
  - kind: SetVariable
    id: loop_start
    variable: Local.counter
    value: =Local.counter + 1

  - kind: SendActivity
    activity:
      text: =Concat("Processing iteration ", Local.counter)

  # Your processing logic here
  - kind: SetVariable
    variable: Local.result
    value: =Concat("Result from iteration ", Local.counter)

  # Check if should continue
  - kind: If
    condition: =Local.counter < Local.maxIterations
    then:
      - kind: GotoAction
        actionId: loop_start
    else:
      - kind: SendActivity
        activity:
          text: "Loop complete!"

الخروج المبكر باستخدام BreakLoop

استخدم BreakLoop للخروج من التكرارات مبكرا عند استيفاء شرط.

name: search-workflow
description: Search through items and stop when found

actions:
  - kind: SetVariable
    variable: Local.found
    value: false

  - kind: Foreach
    source: =Workflow.Inputs.items
    itemName: currentItem
    actions:
      # Check if this is the item we're looking for
      - kind: If
        condition: =currentItem.id = Workflow.Inputs.targetId
        then:
          - kind: SetVariable
            variable: Local.found
            value: true
          - kind: SetVariable
            variable: Local.result
            value: =currentItem
          - kind: BreakLoop

      - kind: SendActivity
        activity:
          text: '=Concat("Checked item: ", currentItem.name)'

  - kind: If
    condition: =Local.found
    then:
      - kind: SendActivity
        activity:
          text: '=Concat("Found: ", Local.result.name)'
    else:
      - kind: SendActivity
        activity:
          text: "Item not found"

أنماط الإنسان في التكرار الحلقي

استطلاع تفاعلي

جمع أجزاء متعددة من المعلومات من المستخدم.

name: customer-survey
description: Interactive customer feedback survey

actions:
  - kind: SendActivity
    activity:
      text: "Welcome to our customer feedback survey!"

  # Collect name
  - kind: Question
    id: ask_name
    question:
      text: "What is your name?"
    variable: Local.userName
    default: "Anonymous"

  - kind: SendActivity
    activity:
      text: =Concat("Nice to meet you, ", Local.userName, "!")

  # Collect rating
  - kind: Question
    id: ask_rating
    question:
      text: "How would you rate our service? (1-5)"
    variable: Local.rating
    default: "3"

  # Respond based on rating
  - kind: If
    condition: =Local.rating >= 4
    then:
      - kind: SendActivity
        activity:
          text: "Thank you for the positive feedback!"
    else:
      - kind: Question
        id: ask_improvement
        question:
          text: "What could we improve?"
        variable: Local.feedback

  # Collect additional feedback
  - kind: RequestExternalInput
    id: additional_comments
    prompt:
      text: "Any additional comments? (optional)"
    variable: Local.comments
    default: ""

  # Summary
  - kind: SendActivity
    activity:
      text: =Concat("Thank you, ", Local.userName, "! Your feedback has been recorded.")

  - kind: SetVariable
    variable: Workflow.Outputs.survey
    value:
      name: =Local.userName
      rating: =Local.rating
      feedback: =Local.feedback
      comments: =Local.comments

سير عمل الموافقة

طلب الموافقة قبل المتابعة في إجراء.

name: approval-workflow
description: Request approval before processing

inputs:
  requestType:
    type: string
    description: Type of request
  amount:
    type: number
    description: Request amount

actions:
  - kind: SendActivity
    activity:
      text: =Concat("Processing ", Workflow.Inputs.requestType, " request for $", Workflow.Inputs.amount)

  # Check if approval is needed
  - kind: If
    condition: =Workflow.Inputs.amount > 1000
    then:
      - kind: SendActivity
        activity:
          text: "This request requires manager approval."

      - kind: Question
        id: get_approval
        question:
          text: =Concat("Do you approve this ", Workflow.Inputs.requestType, " request for $", Workflow.Inputs.amount, "? (yes/no)")
        variable: Local.approved

      - kind: If
        condition: =Local.approved = "yes"
        then:
          - kind: SendActivity
            activity:
              text: "Request approved. Processing..."
          - kind: SetVariable
            variable: Workflow.Outputs.status
            value: approved
        else:
          - kind: SendActivity
            activity:
              text: "Request denied."
          - kind: SetVariable
            variable: Workflow.Outputs.status
            value: denied
    else:
      - kind: SendActivity
        activity:
          text: "Request auto-approved (under threshold)."
      - kind: SetVariable
        variable: Workflow.Outputs.status
        value: auto_approved

التزامن المعقد

سير عمل تذكرة الدعم

مثال شامل يجمع بين أنماط متعددة: توجيه العامل والمنطق الشرطي وإدارة المحادثة.

name: support-ticket-workflow
description: Complete support ticket handling with escalation

kind: Workflow
trigger:
  kind: OnConversationStart
  id: support_workflow
  actions:
    # Initial self-service agent
    - kind: InvokeAzureAgent
      id: self_service
      displayName: Self-service agent
      agent:
        name: SelfServiceAgent
      conversationId: =System.ConversationId
      input:
        externalLoop:
          when: =Not(Local.ServiceResult.IsResolved)
      output:
        responseObject: Local.ServiceResult

    # Check if resolved by self-service
    - kind: If
      condition: =Local.ServiceResult.IsResolved
      then:
        - kind: SendActivity
          activity:
            text: "Issue resolved through self-service."
        - kind: SetVariable
          variable: Workflow.Outputs.resolution
          value: self_service
        - kind: EndWorkflow
          id: end_resolved

    # Create support ticket
    - kind: SendActivity
      activity:
        text: "Creating support ticket..."

    - kind: SetVariable
      variable: Local.TicketId
      value: =Concat("TKT-", System.ConversationId)

    # Route to appropriate team
    - kind: ConditionGroup
      id: route_ticket
      conditions:
        - condition: =Local.ServiceResult.Category = "technical"
          id: technical_route
          actions:
            - kind: InvokeAzureAgent
              id: technical_support
              agent:
                name: TechnicalSupportAgent
              conversationId: =System.ConversationId
              output:
                responseObject: Local.TechResult
        - condition: =Local.ServiceResult.Category = "billing"
          id: billing_route
          actions:
            - kind: InvokeAzureAgent
              id: billing_support
              agent:
                name: BillingSupportAgent
              conversationId: =System.ConversationId
              output:
                responseObject: Local.BillingResult
      elseActions:
        # Escalate to human
        - kind: SendActivity
          activity:
            text: "Escalating to human support..."
        - kind: SetVariable
          variable: Workflow.Outputs.resolution
          value: escalated

    - kind: SendActivity
      activity:
        text: =Concat("Ticket ", Local.TicketId, " has been processed.")

أفضل الممارسات

اصطلاحات التسمية

استخدم أسماء واضحة ووصفية للإجراءات والمتغيرات:

# Good
- kind: SetVariable
  id: calculate_total_price
  variable: Local.orderTotal

# Avoid
- kind: SetVariable
  id: sv1
  variable: Local.x

تنظيم مهام سير العمل الكبيرة

تقسيم مهام سير العمل المعقدة إلى أقسام منطقية مع تعليقات:

actions:
  # === INITIALIZATION ===
  - kind: SetVariable
    id: init_status
    variable: Local.status
    value: started

  # === DATA COLLECTION ===
  - kind: Question
    id: collect_name
    # ...

  # === PROCESSING ===
  - kind: InvokeAzureAgent
    id: process_request
    # ...

  # === OUTPUT ===
  - kind: SendActivity
    id: send_result
    # ...

معالجة الأخطاء

استخدم الفحوصات الشرطية لمعالجة المشكلات المحتملة:

actions:
  - kind: SetVariable
    variable: Local.hasError
    value: false

  - kind: InvokeAzureAgent
    id: call_agent
    agent:
      name: ProcessingAgent
    output:
      responseObject: Local.AgentResult

  - kind: If
    condition: =IsBlank(Local.AgentResult)
    then:
      - kind: SetVariable
        variable: Local.hasError
        value: true
      - kind: SendActivity
        activity:
          text: "An error occurred during processing."
    else:
      - kind: SendActivity
        activity:
          text: =Local.AgentResult.message

استراتيجيات الاختبار

  1. البدء البسيط: اختبار التدفقات الأساسية قبل إضافة التعقيد
  2. استخدام القيم الافتراضية: توفير افتراضيات معقولة للمدخلات
  3. إضافة تسجيل: استخدام SendActivity لتصحيح الأخطاء أثناء التطوير
  4. حالات حافة الاختبار: التحقق من السلوك مع المدخلات المفقودة أو غير الصالحة
# Debug logging example
- kind: SendActivity
  id: debug_log
  activity:
    text: '=Concat("[DEBUG] Current state: counter=", Local.counter, ", status=", Local.status)'

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

  • C# Declarative Workflow Samples - استكشاف أمثلة العمل الكاملة بما في ذلك:
    • StudentTeacher - محادثة متعددة العوامل مع التعلم التكراري
    • InvokeMcpTool - تكامل أداة خادم MCP
    • InvokeFunctionTool - استدعاء الدالة المباشرة من مهام سير العمل
    • FunctionTools - عامل مع أدوات الدالة
    • ToolApproval - الموافقة البشرية لتنفيذ الأداة
    • CustomerSupport - سير عمل تذكرة الدعم المعقد
    • DeepResearch - سير عمل الأبحاث مع عوامل متعددة

Note

سيتوفر الدعم لهذه الميزة قريبا. راجع مستودع Agent Framework Go للحصول على أحدث حالة.