إشعار
يتطلب الوصول إلى هذه الصفحة تخويلاً. يمكنك محاولة تسجيل الدخول أو تغيير الدلائل.
يتطلب الوصول إلى هذه الصفحة تخويلاً. يمكنك محاولة تغيير الدلائل.
تسمح لك مهام سير العمل التعريفية بتحديد منطق سير العمل باستخدام ملفات تكوين 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
- الإلمام الأساسي ببناء جملة YAML
- فهم مفاهيم سير العمل
أول سير عمل تعريفي
دعونا ننشئ سير عمل بسيطا يحيي المستخدم بناء على إدخاله.
الخطوة 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 تلقائيا.
- الإلمام الأساسي ببناء جملة YAML
- فهم مفاهيم سير العمل
أول سير عمل تعريفي
دعونا ننشئ سير عمل بسيطا يحيي المستخدم بالاسم.
الخطوة 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
استراتيجيات الاختبار
- البدء البسيط: اختبار التدفقات الأساسية قبل إضافة التعقيد
- استخدام القيم الافتراضية: توفير افتراضيات معقولة للمدخلات
- إضافة تسجيل: استخدام SendActivity لتصحيح الأخطاء أثناء التطوير
- حالات حافة الاختبار: التحقق من السلوك مع المدخلات المفقودة أو غير الصالحة
# 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 - سير عمل الأبحاث مع عوامل متعددة
- Python نماذج سير العمل التعريفية - استكشاف أمثلة العمل الكاملة
Note
سيتوفر الدعم لهذه الميزة قريبا. راجع مستودع Agent Framework Go للحصول على أحدث حالة.