
# عمليات التسليم غير المتزامنة

استخدم `start_workflows()` عندما يحتاج سير العمل إلى تسليم العمل المكتشف إلى عمليات سير عمل مستقلة في المستوى الأعلى، بدلًا من إبقاء كل شيء ضمن تشغيل واحد.

إذا كنت تصمم صراحةً تشغيلات للوكلاء، فإن `start_agents()` و`wait_for_agents()` اسمان بديلان مترادفان مع إعدادات افتراضية ملائمة للوكلاء.

للاطلاع على أمثلة أكبر وشاملة من البداية إلى النهاية، راجع [تنسيق الوكلاء](https://queuety.inline0.dev/ar/docs/workflows/agent-orchestration).

هذا مفيد لتنسيق سير العمل بأسلوب الوكلاء:

- يكتشف سير عمل المخطط المهام أثناء وقت التشغيل
- تصبح كل مهمة سير عمل دائمًا مستقلًا
- يخزّن الأصل معرّفات سير العمل هذه في الحالة
- يمكن للأصل لاحقًا انتظار `all` أو `any` أو `quorum` أو مجموعة بدأت بالاسم

## طريقة `->start_workflows()`

```php
use Queuety\Enums\WaitMode;
use Queuety\Queuety;

$agent_task = Queuety::workflow( 'agent_task' )
    ->then( ResearchTopicStep::class )
    ->then( SummarizeTopicStep::class );

Queuety::workflow( 'brief_research' )
    ->then( PlanTopicsStep::class )
    ->start_workflows(
        items_key: 'topics',
        workflow_builder: $agent_task,
        result_key: 'child_workflow_ids',
        group_key: 'researchers',
    )
    ->wait_for_workflow_group( 'researchers', WaitMode::All, result_key: 'child_results' )
    ->then( SynthesizeBriefStep::class )
    ->dispatch( [ 'brief_id' => 42 ] );
```

في هذا المثال:

1. يكتب `PlanTopicsStep` مصفوفة من حمولات الموضوعات إلى `$state['topics']`
2. يطلق `start_workflows()` سير عمل `agent_task` واحدًا لكل موضوع
3. تُكتب معرّفات عمليات سير العمل التي بدأت إلى `$state['child_workflow_ids']`
4. يتوقف `wait_for_workflow_group()` مؤقتًا حتى تستوفي المجموعة التي بدأت شرط الاكتمال المحدد
5. يتلقى `SynthesizeBriefStep` حالات سير العمل الفرعية المكتملة ضمن `$state['child_results']`

## حمولات سير العمل الفرعية

يصبح كل عنصر في `items_key` الحمولة الأولية لسير عمل واحد يتم تشغيله.

إذا كان العنصر مصفوفة، تُدمج مفاتيحه العامة في حمولة سير العمل الفرعي:

```php
[
    [ 'topic' => 'pricing', 'source' => 'competitors' ],
    [ 'topic' => 'reviews', 'source' => 'customers' ],
]
```

إذا كان العنصر قيمة مفردة، يخزّن Queuety قيمته ضمن `payload_key`:

```php
->start_workflows(
    items_key: 'topic_names',
    workflow_builder: $agent_task,
    payload_key: 'topic',
)
```

## وراثة حالة الأصل

افتراضيًا، يدمج `start_workflows()` الحالة العامة لسير عمل الأصل في حمولة كل سير عمل فرعي.

وهذا يعني أن السياق المشترك مثل `brief_id` أو `account_id` أو `campaign` يصبح متاحًا تلقائيًا في كل سير عمل يبدأ.

يُستثنى المصدر `items_key` و`result_key` من الوراثة، كيلا يتلقى كل سير عمل فرعي قائمة المهام كاملة أو مصفوفة معرّفات سير العمل النهائية.

عيّن `inherit_state: false` عندما ينبغي أن يتلقى كل سير عمل فرعي حمولة عنصره فقط.

## لماذا لا تستخدم `run_workflow()`؟

ينشئ `run_workflow()` علاقة أصل بفرع، يتوقف فيها الأصل عند تلك الخطوة حتى يكتمل سير العمل الفرعي.

`start_workflows()` أقل ارتباطًا:

- عمليات سير العمل التي بدأت مستقلة وعلى المستوى الأعلى
- يمكن فحص كل سير عمل بدأ، أو إعادة محاولته أو تصديره على حدة
- يقرر الأصل لاحقًا ما إذا كان سينتظرها وكيفية ذلك

لذلك يناسب `start_workflows()` تسليم مهام الوكلاء غير المتزامن أكثر، بينما يظل `run_workflow()` أنسب للتركيب المتداخل ضمن شجرة تنسيق واحدة.

## الانتظار لاحقًا

صُمم `start_workflows()` للعمل مع [تبعيات سير العمل](https://queuety.inline0.dev/ar/docs/workflows/dependencies):

```php
use Queuety\Enums\WaitMode;

Queuety::workflow( 'review_board' )
    ->start_workflows( 'review_tasks', $review_task_workflow, 'review_workflow_ids' )
    ->wait_for_workflows( 'review_workflow_ids', WaitMode::Any, 'winner' )
    ->then( FinalizeDecisionStep::class )
    ->dispatch( $payload );
```

- يجمع `WaitMode::All` كل حالات سير العمل الفرعية المكتملة
- يستأنف `WaitMode::Any` عند أول سير عمل فرعي يكتمل بنجاح

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

## أسماء بديلة ملائمة للوكلاء

`start_agents()` اسم بديل لـ`start_workflows()`، مع إعدادات افتراضية ملائمة لتدفقات عمل المخطط والمنفّذ:

- القيمة الافتراضية لـ`result_key` هي `agent_workflow_ids`
- القيمة الافتراضية لـ`payload_key` هي `agent_task`
- القيمة الافتراضية لـ`name` هي `start_agents`

`wait_for_agents()` اسم بديل لـ`wait_for_workflows()`، مع إعدادات افتراضية ملائمة لجمع نتائج الوكلاء:

- القيمة الافتراضية لـ`workflows` هي `agent_workflow_ids`
- القيمة الافتراضية لـ`result_key` هي `agent_results`
- القيمة الافتراضية لـ`name` هي `wait_for_agents`

`wait_for_agent_group()` اسم بديل لـ`wait_for_workflow_group()`، مع إعدادات افتراضية ملائمة لمجموعات الوكلاء.

```php
use Queuety\Enums\WaitMode;

$agent_run = Queuety::workflow( 'agent_run' )
    ->then( ResearchTopicStep::class )
    ->then( SummarizeTopicStep::class );

Queuety::workflow( 'brief_research' )
    ->then( PlanTopicsStep::class )
    ->start_agents( 'agent_tasks', $agent_run, group_key: 'researchers' )
    ->wait_for_agent_group( 'researchers', WaitMode::Quorum, 2 )
    ->then( SynthesizeBriefStep::class )
    ->dispatch( [ 'brief_id' => 42 ] );
```
