> ## Documentation Index
> Fetch the complete documentation index at: https://crewai-cursor-default-model-gpt-5-6-luna.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# تدفقات المحادثة

> أنشئ تطبيقات دردشة متعددة الجولات مع kickoff لكل جولة وسجل الرسائل وتوجيه النية والتتبع وجسور WebSocket.

## نظرة عامة

تعامل التطبيقات المحادثية مع كل سطر من المستخدم كـ **تشغيل flow جديد** بنفس **معرّف الجلسة**. توفر CrewAI مساعدات لسجل الرسائل وتصنيف النية الاختياري وتأجيل التتبع وجسور الواجهة، إضافة إلى REPL محلي `flow.chat()` للتدفقات المحادثية.

| المفهوم       | التنفيذ                                                                           |
| ------------- | --------------------------------------------------------------------------------- |
| معرّف الجلسة  | `handle_turn(..., session_id=...)` → `kickoff(inputs={"id": ...})` → `state.id`   |
| سطر المستخدم  | `handle_turn(message)` يضيف الرسالة إلى `state.messages` قبل تشغيل الرسم          |
| اكتمال الجولة | `FlowFinished` لهذا **التشغيل** فقط؛ تستمر المحادثة في `handle_turn` التالي       |
| تتبع الجلسة   | `ConversationConfig(defer_trace_finalization=True)` + `finalize_session_traces()` |

## واجهات الجولات

استخدم **`flow.handle_turn(message, session_id=...)`** لكل رسالة مستخدم من REST أو WebSocket أو الاختبارات أو الواجهات المخصصة. استخدم **`flow.chat()`** عندما تريد حلقة دردشة محلية في الطرفية لـ `Flow` محادثي.

لا يقبل `Flow.kickoff()` الوسيطين `user_message=` أو `session_id=`. في التدفقات المحادثية، يخزن `handle_turn()` الرسالة المعلقة ويستدعي داخلياً `kickoff(inputs={"id": session_id})`.

| API                                    | الاستخدام                                              |
| -------------------------------------- | ------------------------------------------------------ |
| `handle_turn(message, session_id=...)` | غلاف مريح لجولة واحدة في `Flow` محادثي                 |
| `chat()`                               | REPL محلي في الطرفية لـ `Flow` محادثي                  |
| `kickoff(inputs={...})`                | تشغيل متقدم للـ flow بدون معالجة جولة محادثية          |
| `ask()`                                | مطالبة حاجزة **داخل** خطوة واحدة                       |
| `@human_feedback`                      | الموافقة/الرفض على **مخرجات خطوة** — وليس السطر التالي |
| `ChatSession.handle_turn(...)`         | طبقة نقل فوق `handle_turn`                             |

## بداية سريعة

```python theme={null}
from uuid import uuid4

from crewai import Flow
from crewai.flow import listen
from crewai.experimental.conversational import (
    ConversationConfig,
    ConversationState,
)


@ConversationConfig(defer_trace_finalization=True)
class SupportFlow(Flow[ConversationState]):
    conversational = True

    def route_turn(self, context):
        message = (self.state.current_user_message or "").lower()
        if "طلب" in message or "order" in message:
            return "order"
        if "وداع" in message or "goodbye" in message:
            return "goodbye"
        return "help"

    @listen("order")
    def handle_order(self):
        reply = "طلبك في الطريق."
        self.append_assistant_message(reply)
        return reply

    @listen("help")
    def handle_help(self):
        reply = "كيف يمكنني المساعدة؟"
        self.append_assistant_message(reply)
        return reply

    @listen("goodbye")
    def handle_goodbye(self):
        reply = "وداعاً!"
        self.append_assistant_message(reply)
        return reply


session_id = str(uuid4())
flow = SupportFlow()

try:
    flow.handle_turn("أين طلبي؟", session_id=session_id)
    flow.handle_turn("وماذا عن الإرجاع؟", session_id=session_id)
finally:
    flow.finalize_session_traces()
```

## دورة حياة الجولة

كل `handle_turn` يشغّل:

1. **`_configure_conversational_kickoff`** — دمج `session_id` / `user_message` في `inputs` وتطبيق `ConversationalConfig`.
2. **استعادة الحالة** — عند وجود `inputs["id"]` و`@persist`.
3. **`FlowStarted`** — في أول جولة للجلسة المؤجلة فقط.
4. **`prepare_conversational_turn`** — إضافة رسالة المستخدم و`last_user_message` وتصنيف اختياري.
5. **تنفيذ الرسم** — `@start` → `@router` → معالجات `@listen`.
6. **نهاية التشغيل** — يُتخطى `flow_finished` والتتبع لكل جولة عند التأجيل؛ `Agent.kickoff()` / crews لا تغلق دفعة الأب.

استدعِ **`append_assistant_message(reply)`** في المعالجات. سطر المستخدم محفوظ عبر `handle_turn` — لا تُضفه مرة أخرى.

## `ConversationalConfig` (افتراضيات على مستوى الصنف)

عيّن على صنف `Flow` كـ `conversational_config: ClassVar[ConversationalConfig | None]`.

| الحقل                      | الافتراضي      | الغرض                                       |
| -------------------------- | -------------- | ------------------------------------------- |
| `default_intents`          | `None`         | تسميات outcome للتصنيف التلقائي قبل kickoff |
| `intent_llm`               | `None`         | نموذج التصنيف (مطلوب عند وجود intents)      |
| `interactive_prompt`       | `"You: "`      | مطالبة `kickoff(interactive=True)`          |
| `interactive_timeout`      | `None`         | مهلة لكل سطر في الوضع التفاعلي              |
| `exit_commands`            | `exit`, `quit` | كلمات إنهاء الوضع التفاعلي                  |
| `defer_trace_finalization` | `True`         | إبقاء دفعة trace واحدة مفتوحة بين الجولات   |

يمكن التجاوز لكل kickoff عبر `intents=` و`intent_llm=`.

## `ChatState` (شكل الحالة الموصى به للحفظ)

```python theme={null}
from crewai.flow import ChatState


class MyChatState(ChatState):
    # موروث: id, messages, last_user_message, last_intent, session_ready
    research_turn_count: int = 0
    custom_flag: bool = False
```

| الحقل               | الدور                                           |
| ------------------- | ----------------------------------------------- |
| `id`                | UUID الجلسة (مثل `session_id` / `inputs["id"]`) |
| `messages`          | قائمة `{role, content}` لسجل LLM                |
| `last_user_message` | آخر سطر مستخدم في هذه الجولة                    |
| `last_intent`       | تسمية المسار بعد التصنيف (إن وُجد)              |
| `session_ready`     | علم bootstrap لمرة واحدة                        |

`ConversationalInputs` هو `TypedDict` لـ `kickoff(inputs={...})`: `id`, `user_message`, `last_intent`.

## API المحادثة على `Flow`

### معاملات `kickoff` / `kickoff_async`

| المعامل                 | الغرض                                                   |
| ----------------------- | ------------------------------------------------------- |
| `user_message`          | نص هذه الجولة (أو `{"role": "user", "content": "..."}`) |
| `session_id`            | UUID المحادثة → `inputs["id"]` / `state.id`             |
| `intents`               | تسميات outcome لـ `classify_intent` قبل kickoff         |
| `intent_llm`            | LLM للتصنيف (مطلوب مع `intents`)                        |
| `interactive`           | حلقة CLI عبر `ask()` (للعروض المحلية فقط)               |
| `interactive_prompt`    | مطالبة الوضع التفاعلي                                   |
| `interactive_timeout`   | مهلة `ask()` لكل سطر                                    |
| `exit_commands`         | كلمات إنهاء الوضع التفاعلي                              |
| `inputs`                | حقول حالة إضافية                                        |
| `restore_from_state_id` | استنساخ من flow محفوظ آخر                               |

### سمات المثيل

| السمة                      | الغرض                                              |
| -------------------------- | -------------------------------------------------- |
| `conversational_config`    | افتراضيات `ConversationalConfig` على مستوى الصنف   |
| `defer_trace_finalization` | علم المثيل؛ يُضبط تلقائياً من config عند kickoff   |
| `suppress_flow_events`     | يخفي لوحات console؛ **التتبع يُسجّل**              |
| `stream`                   | بث؛ مع `ChatSession.handle_turn(..., stream=True)` |

### طرق وخصائص

| الاسم                                                    | الوصف                                          |
| -------------------------------------------------------- | ---------------------------------------------- |
| `append_message(role, content, **extra)`                 | إضافة إلى `state.messages`                     |
| `conversation_messages`                                  | سجل للقراءة فقط لاستدعاءات LLM                 |
| `classify_intent(text, outcomes, *, llm, context=None)`  | تعيين outcome                                  |
| `receive_user_message(text, *, outcomes=None, llm=None)` | إضافة رسالة مستخدم؛ `last_intent` اختياري      |
| `finalize_session_traces()`                              | إصدار `flow_finished` المؤجل وإنهاء دفعة trace |
| `_should_defer_trace_finalization()`                     | هل يُؤجل إنهاء trace لكل جولة                  |
| `input_history`                                          | سجل تدقيق مطالبات وردود `ask()`                |

### مساعدات الوحدة (`crewai.flow.conversation`)

| الدالة                                   | الوصف                                 |
| ---------------------------------------- | ------------------------------------- |
| `normalize_kickoff_inputs(...)`          | دمج kwargs المحادثة في `inputs`       |
| `get_conversation_messages(flow)`        | قراءة الرسائل من الحالة أو المخزن     |
| `append_message(flow, ...)`              | مثل طريقة المثيل                      |
| `prepare_conversational_turn(flow, ...)` | تهيئة الجولة (عادةً kickoff يستدعيها) |
| `receive_user_message(flow, ...)`        | مثل طريقة المثيل                      |
| `set_state_field(flow, name, value)`     | تعيين حقل dict أو Pydantic            |
| `get_conversational_config(flow)`        | قراءة `conversational_config`         |
| `input_history_to_messages(entries)`     | تحويل `input_history` لصيغة رسائل LLM |

## أنماط توجيه النية

### أ. تصنيف مسبق عبر `ConversationalConfig` (الأبسط)

عيّن `default_intents` و`intent_llm`. كل kickoff يصنّف قبل `@router`؛ اقرأ `self.state.last_intent` في `route()`.

### ب. تصنيف داخل `@router` (مطالبات أغنى)

عيّن `default_intents=None` ليضيف kickoff الرسالة فقط. في `route()` استدعِ `classify_intent`:

```python theme={null}
@router(bootstrap)
def route(self):
    intent = self.classify_intent(
        self._routing_prompt(self.state.last_user_message),
        ("GREETING", "ORDER", "RESEARCH", "GOODBYE"),
        llm=self.conversational_config.intent_llm or "gpt-4o-mini",
    )
    self.state.last_intent = intent
    return intent
```

للبحث على الويب أو أدوات متعددة الخطوات استخدم **`@listen("RESEARCH")`** مع `Agent.kickoff()` وأدوات — وليس `LLM.call()` فقط.

## عندما ينتهي الـ flow ويستمر المستخدم

`FlowFinished` يعني أن **تنفيذ الرسم هذا** اكتمل. تستمر المحادثة بـ `kickoff` آخر ونفس `session_id`. `@persist` يستعيد `messages` والأعلام والسياق.

**نمط الحفظ:** يُفضّل `@persist` على **خطوة نهائية واحدة** (مثل `finalize`) وليس على صنف `Flow` بالكامل. الحفظ على مستوى الصنف بعد كل method قد يفقد تحديثات المعالجات في نفس الجولة.

لا تستخدم `@human_feedback` لأسطر المتابعة في الدردشة إلا عند الحاجة لموافقة بشرية على مخرجات خطوة محددة.

## `Flow` المحادثاتي (تجريبي)

<Warning>
  **ميزة تجريبية.** سطح `Flow` المحادثاتي (`conversational = True`،
  `handle_turn`، `ConversationConfig`، `RouterConfig`،
  `ConversationState`، الرسم البياني المدمج والمساعدات) يقع تحت
  `crewai.experimental` وقد يتغير شكله قبل التخرج. ثبّت إصدار CrewAI إذا
  كنت تعتمد على سلوك محدد، وراقب changelog للتحديثات الكاسرة. الملاحظات
  والمشاكل مرحب بها.
</Warning>

فعّل الرسم المحادثاتي بتعيين `conversational = True` على صنف فرعي من `Flow`. عندئذٍ يُظهر `Flow` الأساسي رسم `@start` / `@router` / `converse_turn` / `end_conversation` مدمجاً، ويدير `state.messages`، ويُشغّل LLM التوجيه، ويبقي دفعة trace مفتوحة عبر الجولات. أنت تكتب **المسارات المخصصة** فقط؛ والإطار يتولى الباقي.

استخدمه عندما تريد دردشة متعددة الجولات مع موجّه قائم على LLM ومعالجات لكل مسار دون توصيل دورة الحياة يدوياً. استخدم `Flow[ChatState]` (النمط الأدنى مستوى في الأعلى) عندما تحتاج تحكماً كاملاً.

### مثال سريع

```python theme={null}
from crewai import LLM, Flow
from crewai.flow import listen
from crewai.experimental.conversational import (
    ConversationConfig,
    ConversationState,
    RouterConfig,
)


ROUTER_LLM = LLM(model="gpt-4o-mini")


@ConversationConfig(
    system_prompt="A multi-agent assistant for ordinary chat and tool-backed tasks.",
    llm=ROUTER_LLM,
    router=RouterConfig(),  # المسارات + الأوصاف تُكتشف تلقائياً من معالجات @listen
)
class SupportFlow(Flow[ConversationState]):
    conversational = True

    @listen("INTERNET_SEARCH")
    def handle_internet_search(self) -> str:
        """Fresh web research, current news, real-time lookups."""
        ...
        self.append_assistant_message(reply)
        return reply

    @listen("CREWAI_DOCS")
    def handle_crewai_docs(self) -> str:
        """Look up the CrewAI documentation for framework/API questions."""
        ...
        self.append_assistant_message(reply)
        return reply


flow = SupportFlow()
try:
    flow.handle_turn("ماذا يمكنك أن تفعل؟")                   # يوجَّه إلى converse (مدمج)
    flow.handle_turn("ابحث في الويب عن أخبار الذكاء الاصطناعي.")  # يوجَّه إلى INTERNET_SEARCH
    flow.handle_turn("لخص النتيجة الأولى.")                    # يعود إلى converse
finally:
    flow.finalize_session_traces()
```

للدردشة المحلية في الطرفية، استخدم `chat()`:

```python theme={null}
def kickoff() -> None:
    SupportFlow().chat()
```

يلف `chat()` استدعاءات `handle_turn()` داخل REPL، ويخرج عند `exit` / `quit`، ويتجاهل الأسطر الفارغة افتراضياً، ويستدعي `finalize_session_traces()` عند انتهاء الجلسة.

### `ConversationConfig`

مزخرف صنف يُلحق افتراضيات الدردشة على مستوى الصنف.

| الحقل                        | الافتراضي                                     | الغرض                                                                                              |
| ---------------------------- | --------------------------------------------- | -------------------------------------------------------------------------------------------------- |
| `system_prompt`              | `slices.conversational_system_prompt` من i18n | رسالة system يستخدمها `converse_turn` المدمج. مرر `""` للتعطيل التام.                              |
| `llm`                        | `None`                                        | LLM المحادثة (يستخدمه `converse_turn` وكاحتياطي للموجّه).                                          |
| `router`                     | `None`                                        | `RouterConfig` للتوجيه عبر LLM. بدونه، يسقط الـ flow دائماً إلى `converse`.                        |
| `answer_from_history_prompt` | افتراضي الإطار                                | رسالة system للمسار الاختياري `answer_from_history`.                                               |
| `answer_from_history_llm`    | `None`                                        | يُفعّل الاختصار `answer_from_history` عند تعيينه.                                                  |
| `intent_llm`                 | `None`                                        | LLM لمسار التصنيف المسبق القديم `intents=`/`default_intents`.                                      |
| `default_intents`            | `None`                                        | تسميات النتائج للتصنيف المسبق القديم.                                                              |
| `visible_agent_outputs`      | `None`                                        | `"all"` أو قائمة بأسماء الـ agents الذين تُرفع مخرجاتهم من `append_agent_result()` إلى رسائل عامة. |
| `defer_trace_finalization`   | `True`                                        | يبقي دفعة trace واحدة مفتوحة عبر استدعاءات `handle_turn()`.                                        |

### `RouterConfig` وفهرس المسارات المُولَّد تلقائياً

```python theme={null}
RouterConfig(
    prompt="تأطير اختياري للنطاق (سياسة، صوت، شخصية).",
    response_format=MyRoute,        # اختياري؛ يُولَّد تلقائياً عند الإغفال
    llm=ROUTER_LLM,                  # يسقط إلى ConversationConfig.llm
    routes=["INTERNET_SEARCH", "CREWAI_DOCS"],   # اختياري؛ يُستنتج من المستمعين
    route_descriptions={
        "INTERNET_SEARCH": "تجاوز الـ docstring لهذا المسار فقط.",
    },
    default_intent="converse",       # يُستخدم عند فشل LLM أو غيابه
    fallback_intent="converse",      # يُستخدم عندما يعيد LLM مساراً غير صالح
    intent_field="intent",
)
```

تُبنى رسالة الموجّه إلى LLM تلقائياً. لكل مسار يختار الإطار وصفاً بهذا الترتيب من الأولوية:

1. `RouterConfig.route_descriptions[label]` — تجاوز صريح.
2. `Flow.builtin_route_descriptions[label]` — نص جاهز من الإطار لـ `converse` و`end` و`answer_from_history` (مصاغ لـ LLM التوجيه).
3. أول سطر غير فارغ من docstring معالج `@listen(label)`.
4. فارغ (المسار يظهر في الفهرس بلا وصف).

عملياً، **إضافة مسار جديد = `@listen("X")` + docstring من سطر واحد**:

```python theme={null}
@listen("INTERNET_SEARCH")
def handle_internet_search(self) -> str:
    """Fresh web research, current news, real-time lookups."""
    ...
```

…وسيرى LLM التوجيه:

```
Routes:
- CREWAI_DOCS: Look up the CrewAI documentation for framework/API questions.
- INTERNET_SEARCH: Fresh web research, current news, real-time lookups.
- converse: Ordinary chat, follow-ups, summaries, clarifications…
- end: User signals the conversation is finished (goodbye, exit, done).
```

`RouterConfig.prompt` مخصص لـ **تأطير النطاق** (شخصية المساعد، قواعد العمل، النبرة). فهرس المسارات يُبنى تلقائياً — لا تُدرج المسارات في `prompt`؛ سيختل التزامن لحظة إضافة معالج جديد.

### المسارات المدمجة

| المسار                | المعالج                    | الغرض                                                                                                                             |
| --------------------- | -------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| `converse`            | `converse_turn`            | معالج الدردشة الافتراضي. يستدعي `ConversationConfig.llm` بـ system prompt + التاريخ القانوني للرسائل.                             |
| `end`                 | `end_conversation`         | يضبط `state.ended = True` ويُصدر رد إنهاء.                                                                                        |
| `answer_from_history` | `answer_from_history_turn` | اختياري. يُوجَّه إليه عندما يكون `ConversationConfig.answer_from_history_llm` مُعيَّناً ويمكن الإجابة على الرسالة من التاريخ فقط. |

يمكنك تجاوز أي من هذه بتعريف معالج بنفس الاسم في الصنف الفرعي.

### دلالات `handle_turn()`

`flow.handle_turn(message)` يُشغّل جولة واحدة:

1. يعيد ضبط تعقّب التنفيذ لكل جولة (`_completed_methods`, `_method_outputs`) ليُعاد تشغيل الرسم — بدون ذلك، استدعاءات `kickoff` المتكررة على نفس النسخة ستُحدث دائرة قصر من الجولة الثانية لأن `Flow.kickoff_async` يعتبر `inputs={"id": ...}` استعادة من نقطة تفتيش.
2. يُلحق رسالة المستخدم بـ `state.messages` ويضبط `current_user_message` / `last_user_message`. يُحافَظ على `last_intent` **من الجولة السابقة** كي يستخدمها LLM التوجيه كإشارة.
3. يُشغّل `conversation_start` → `route_conversation` → معالج `@listen` المختار.
4. يخزّن الموجّه قراره في `state.last_intent` (يكون مرئياً لسياق التوجيه في الجولة التالية).
5. إذا أعاد معالجك سلسلة نصية ولم يستدعِ `append_assistant_message`، فإن `handle_turn` يُلحقها نيابةً عنك.

استدعِ `handle_turn()` لرسائل الدردشة. استدعاء `kickoff(inputs={"id": ...})` مباشرةً يشغل الرسم بدون غلاف الجولة المحادثية.

### `chat()` للـ REPL المحلي

`flow.chat()` هو غلاف الطرفية الجاهز فوق `handle_turn()`:

```python theme={null}
flow = SupportFlow()
flow.chat()
```

يتولى الحلقة المحلية الشائعة:

1. يطلب رسالة من المستخدم.
2. يتوقف عند `exit` / `quit` أو `EOFError` أو `KeyboardInterrupt`.
3. يستدعي `handle_turn(message, session_id=...)`.
4. يطبع نتيجة المساعد.
5. ينهي traces الجلسة المؤجلة داخل كتلة `finally`.

خصص سلوك الطرفية عبر I/O قابل للحقن:

```python theme={null}
flow.chat(
    session_id="demo-session",
    prompt="You: ",
    assistant_prefix="Assistant: ",
    exit_commands=("exit", "quit", "bye"),
)
```

لتطبيقات الويب والـ workers الخلفية والاختبارات ووسائط النقل المخصصة، استمر في استخدام `handle_turn()` مباشرةً.

### سلوك موجّه مخصص

لتشغيل آثار جانبية (إعداد ناقل أحداث، قياس عن بُعد) في كل قرار توجيه، تجاوز `route_turn`:

```python theme={null}
class SupportFlow(Flow[ConversationState]):
    conversational = True

    def route_turn(self, context: dict[str, Any]) -> str | None:
        self.event_bus = MyBus(self)
        return super().route_turn(context)
```

لتجاوز موجّه LLM واختيار مسار برمجياً، أعد سلسلة نصية من `route_turn`؛ إعادة `None` تسقط إلى `_route_with_config(...)`.

### `append_assistant_message` و`append_agent_result`

داخل معالج `@listen(label)`، اختر:

* `self.append_assistant_message(text)` — يضيف جولة مساعد مرئية للمستخدم إلى `state.messages`. سيراها `converse_turn` في الجولة التالية.
* `self.append_agent_result(agent_name, result, visibility="private")` — يسجّل حدثاً منظماً في `state.events` وموضوعاً في `state.agent_threads[agent_name]`. الرؤية العامة تستدعي `append_assistant_message` أيضاً. استخدم النتائج الخاصة للعمل الجانبي الذي يجب ألا يلوث التاريخ القانوني.

يمكن لـ `ConversationConfig.visible_agent_outputs` رفع النتائج الخاصة لـ agents محددين إلى عامة عالمياً (`"all"` أو قائمة بالأسماء).

## تعريف تدفق محادثاتي بصيغة JSON/YAML

يمكن لـ [التدفق التعريفي](/edge/en/concepts/cli) أن يكون محادثاتيًا أيضًا. أضف كتلة `conversational` في المستوى الأعلى وعرّف مساراتك الخاصة كطرق تستمع (`listen`) إلى تسمية مسار:

```yaml theme={null}
schema: crewai.flow/v1
name: SupportFlow

conversational:
  system_prompt: You are a terse support assistant.
  llm: gpt-4o-mini
  router:
    llm: gpt-4o-mini

methods:
  handle_order:
    description: Order status, shipping and delivery questions.
    listen: order
    do:
      call: agent
      with:
        role: Support specialist
        goal: Answer order questions accurately
        backstory: Knows the fulfilment pipeline.
        input: "${state.current_user_message}"
```

تعريف الكتلة هو الاشتراك نفسه — القيمة الافتراضية لـ `enabled` هي `true`. اضبطها على `enabled: false` للاحتفاظ بالإعدادات مع إيقاف المحادثة.

تُوفَّر لك ثلاثة أشياء:

| المُوفَّر            | التفاصيل                                                                                                                                       |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| الرسم البياني المدمج | تُضاف `route_conversation` و`converse_turn` و`end_conversation` و`answer_from_history_turn` تلقائيًا. عرّف طريقة بأحد هذه الأسماء لتجاوزها.    |
| حالة المحادثة        | تُستخدم `ConversationState` عندما لا تحتوي التعريفة على كتلة `state`. لإضافة حقول، وجّه `state` إلى نموذج Pydantic يرث من `ConversationState`. |
| كتالوج المسارات      | يُبنى من الطرق التي تعلن تسمية `listen`. وصف كل طريقة (`description`) هو ما يقرأه نموذج التوجيه عند الاختيار بين المسارات.                     |

شغّله من Python بنفس واجهات الجولة المستخدمة مع تدفق محادثاتي معرّف بصنف:

```python theme={null}
from crewai.flow import Flow

flow = Flow.from_declaration(path="flow.yaml")

try:
    flow.handle_turn("Where is my order?", session_id="session-1")
finally:
    flow.finalize_session_traces()
```

### تسمية المسارات

تتشارك تسميات المسارات وأسماء الطرق مساحة اسم واحدة للمشغّلات، لذا يجب ألا يحمل المعالج اسم المسار الذي يستمع إليه — يُرفض `create_video` الذي يستمع إلى `create_video` عند بناء التدفق. استخدم بادئة `handle_*`.

### ما لا يمكن للتعريفة التعبير عنه

| غير قابل للتعبير                                     | استخدم بدلًا منه                                                   |
| ---------------------------------------------------- | ------------------------------------------------------------------ |
| مثيل `LLM` حي أو `BaseLLM` مخصص                      | سلسلة معرّف النموذج، مثل `gpt-4o-mini`                             |
| `router.response_format` كصنف نموذج                  | احذفه؛ يولّد الإطار واحدًا. يُتجاهل المرجع أو المخطط مع تحذير      |
| تجاوزات `route_turn()` / `can_answer_from_history()` | اكتب التدفق بلغة Python، أو وجّه `do` لطريقة إلى مرجع `call: code` |

يفتح `crewai run` واجهة المحادثة النصية للتدفق المحادثاتي التعريفي — نفس الواجهة التي يحصل عليها تدفق محادثاتي مكتوب بلغة Python. تحتاج حلقة المحادثة إلى طرفية، لذا يُبلّغ التشغيل بدون طرفية بذلك بدلًا من تنفيذ جولة واحدة؛ شغّله من Python هناك عبر `handle_turn()` أو `stream_turn()`. والتدفق الذي يستخدم `@human_feedback` أيضًا يعمل على حلقة طرفية، لأن زمن التشغيل يجمع الملاحظات عبر مُطالبة حاجبة لا تستطيع الواجهة النصية خدمتها. لا يُقبل `--inputs` مع التدفق المحادثاتي — فمدخل كل دورة هو الرسالة التي تكتبها — واستئناف جلسة عبر المعرّف غير موصول بواجهة سطر الأوامر بعد؛ استخدم `flow.handle_turn(message, session_id=...)` من Python لذلك.

## التتبع عبر الجولات

مع `defer_trace_finalization=True` (افتراضي في `ConversationalConfig`):

* **دفعة trace واحدة** لجلسة الدردشة.
* **`flow_started`** في الجولة الأولى فقط؛ **`flow_finished`** مرة في `finalize_session_traces()`.
* **`kickoff` لكل جولة** لا يطبع "Trace batch finalized".
* **العمل المتداخل** (`Agent.kickoff()`, crews, Exa) يُلحق بدفعة **الأب**؛ flow داخلي من `AgentExecutor` لا يغلق دفعة الجلسة مبكراً.

```python theme={null}
flow.chat(session_id=session_id)
```

`flow.chat()` يستدعي `finalize_session_traces()` نيابةً عنك. عندما تملك الحلقة عبر `handle_turn()` أو `kickoff(...)`، استدعِ `finalize_session_traces()` عند انتهاء الجلسة.

`suppress_flow_events=True` يخفي لوحات Rich فقط؛ أحداث trace والـ methods تُصدر.

### دورة حياة trace لـ `Flow` المحادثاتي

يستخدم [`Flow` المحادثاتي](#flow-المحادثاتي-تجريبي) التجريبي نفس دورة حياة tracing: `defer_trace_finalization` افتراضياً `True`، فيبقي كل `handle_turn()` أثر الجلسة مفتوحاً. أنهِ دوماً عند نهاية الجلسة — لُف حلقتك بـ `try/finally` واستدعِ `flow.finalize_session_traces()` عند الخروج. بدون ذلك، تبقى الدفعة مفتوحة وقد لا تُصدَّر آخر محادثة أبداً.

## البث

اضبط `stream = True` على صنف `Flow`. عندئذٍ يُصدر `kickoff(...)` أحداث `assistant_delta` (وما يرتبط بها) عبر ناقل الأحداث القياسي.

## الاستيراد

```python theme={null}
from crewai.flow import (
    ChatState,
    ConversationalConfig,
    ConversationalInputs,
    Flow,
    listen,
    persist,
    router,
    start,
)
```

## مراجع

* [إتقان إدارة حالة Flow](/ar/guides/flows/mastering-flow-state)
* [أنشئ أول Flow](/ar/guides/flows/first-flow)
* Demo: `lib/crewai/runner_conversational_flow_simple.py` — REPL بسيط مع `RESEARCH` ووكيل Exa
