From 1e281af39f49b16ec2bdbcd7f7c22bd4e73d26e2 Mon Sep 17 00:00:00 2001 From: Greyson LaLonde Date: Tue, 20 Jan 2026 12:51:36 -0500 Subject: [PATCH] chore: tweak tests to account for vcr race condiiton - noted race condition within the vcr package --- ...ntOrdering.test_crew_parent_is_method.yaml | 118 +++++++++ ...entOrdering.test_flow_events_have_ids.yaml | 118 +++++++++ ...ntOrdering.test_method_parent_is_flow.yaml | 118 +++++++++ ...Ordering.test_second_crew_after_first.yaml | 234 ++++++++++++++++++ ....test_tasks_have_correct_crew_parents.yaml | 234 ++++++++++++++++++ ...ing.test_two_crews_have_different_ids.yaml | 234 ++++++++++++++++++ .../tests/events/test_event_ordering.py | 70 +++--- 7 files changed, 1096 insertions(+), 30 deletions(-) create mode 100644 lib/crewai/tests/cassettes/events/TestFlowWithCrewEventOrdering.test_crew_parent_is_method.yaml create mode 100644 lib/crewai/tests/cassettes/events/TestFlowWithCrewEventOrdering.test_flow_events_have_ids.yaml create mode 100644 lib/crewai/tests/cassettes/events/TestFlowWithCrewEventOrdering.test_method_parent_is_flow.yaml create mode 100644 lib/crewai/tests/cassettes/events/TestFlowWithMultipleCrewsEventOrdering.test_second_crew_after_first.yaml create mode 100644 lib/crewai/tests/cassettes/events/TestFlowWithMultipleCrewsEventOrdering.test_tasks_have_correct_crew_parents.yaml create mode 100644 lib/crewai/tests/cassettes/events/TestFlowWithMultipleCrewsEventOrdering.test_two_crews_have_different_ids.yaml diff --git a/lib/crewai/tests/cassettes/events/TestFlowWithCrewEventOrdering.test_crew_parent_is_method.yaml b/lib/crewai/tests/cassettes/events/TestFlowWithCrewEventOrdering.test_crew_parent_is_method.yaml new file mode 100644 index 000000000..f8b04a451 --- /dev/null +++ b/lib/crewai/tests/cassettes/events/TestFlowWithCrewEventOrdering.test_crew_parent_is_method.yaml @@ -0,0 +1,118 @@ +interactions: +- request: + body: '{"messages":[{"role":"system","content":"You are Worker. You work.\nYour + personal goal is: Do work\nTo give my best complete final answer to the task + respond using the exact following format:\n\nThought: I now can give a great + answer\nFinal Answer: Your final answer must be the great and the most complete + as possible, it must be outcome described.\n\nI MUST use these formats, my job + depends on it!"},{"role":"user","content":"\nCurrent Task: Say ''go'' and nothing + else.\n\nThis is the expected criteria for your final answer: The word go.\nyou + MUST return the actual complete content as the final answer, not a summary.\n\nBegin! + This is VERY important to you, use the tools available and give your best Final + Answer, your job depends on it!\n\nThought:"}],"model":"gpt-4.1-mini"}' + headers: + User-Agent: + - X-USER-AGENT-XXX + accept: + - application/json + accept-encoding: + - ACCEPT-ENCODING-XXX + authorization: + - AUTHORIZATION-XXX + connection: + - keep-alive + content-length: + - '782' + content-type: + - application/json + host: + - api.openai.com + x-stainless-arch: + - X-STAINLESS-ARCH-XXX + x-stainless-async: + - async:asyncio + x-stainless-lang: + - python + x-stainless-os: + - X-STAINLESS-OS-XXX + x-stainless-package-version: + - 1.83.0 + x-stainless-read-timeout: + - X-STAINLESS-READ-TIMEOUT-XXX + x-stainless-retry-count: + - '0' + x-stainless-runtime: + - CPython + x-stainless-runtime-version: + - 3.12.10 + method: POST + uri: https://api.openai.com/v1/chat/completions + response: + body: + string: "{\n \"id\": \"chatcmpl-D09c91Qh5LJ73NLwFrcRhThK7zNKS\",\n \"object\": + \"chat.completion\",\n \"created\": 1768929329,\n \"model\": \"gpt-4.1-mini-2025-04-14\",\n + \ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\": + \"assistant\",\n \"content\": \"Thought: I now can give a great answer\\nFinal + Answer: go\",\n \"refusal\": null,\n \"annotations\": []\n },\n + \ \"logprobs\": null,\n \"finish_reason\": \"stop\"\n }\n ],\n + \ \"usage\": {\n \"prompt_tokens\": 158,\n \"completion_tokens\": 14,\n + \ \"total_tokens\": 172,\n \"prompt_tokens_details\": {\n \"cached_tokens\": + 0,\n \"audio_tokens\": 0\n },\n \"completion_tokens_details\": + {\n \"reasoning_tokens\": 0,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\": + 0,\n \"rejected_prediction_tokens\": 0\n }\n },\n \"service_tier\": + \"default\",\n \"system_fingerprint\": \"fp_376a7ccef1\"\n}\n" + headers: + CF-RAY: + - CF-RAY-XXX + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Tue, 20 Jan 2026 17:15:30 GMT + Server: + - cloudflare + Set-Cookie: + - SET-COOKIE-XXX + Strict-Transport-Security: + - STS-XXX + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - X-CONTENT-TYPE-XXX + access-control-expose-headers: + - ACCESS-CONTROL-XXX + alt-svc: + - h3=":443"; ma=86400 + cf-cache-status: + - DYNAMIC + openai-organization: + - OPENAI-ORG-XXX + openai-processing-ms: + - '521' + openai-project: + - OPENAI-PROJECT-XXX + openai-version: + - '2020-10-01' + x-envoy-upstream-service-time: + - '781' + x-openai-proxy-wasm: + - v0.1 + x-ratelimit-limit-requests: + - X-RATELIMIT-LIMIT-REQUESTS-XXX + x-ratelimit-limit-tokens: + - X-RATELIMIT-LIMIT-TOKENS-XXX + x-ratelimit-remaining-requests: + - X-RATELIMIT-REMAINING-REQUESTS-XXX + x-ratelimit-remaining-tokens: + - X-RATELIMIT-REMAINING-TOKENS-XXX + x-ratelimit-reset-requests: + - X-RATELIMIT-RESET-REQUESTS-XXX + x-ratelimit-reset-tokens: + - X-RATELIMIT-RESET-TOKENS-XXX + x-request-id: + - X-REQUEST-ID-XXX + status: + code: 200 + message: OK +version: 1 diff --git a/lib/crewai/tests/cassettes/events/TestFlowWithCrewEventOrdering.test_flow_events_have_ids.yaml b/lib/crewai/tests/cassettes/events/TestFlowWithCrewEventOrdering.test_flow_events_have_ids.yaml new file mode 100644 index 000000000..c9ce085fa --- /dev/null +++ b/lib/crewai/tests/cassettes/events/TestFlowWithCrewEventOrdering.test_flow_events_have_ids.yaml @@ -0,0 +1,118 @@ +interactions: +- request: + body: '{"messages":[{"role":"system","content":"You are Worker. You work.\nYour + personal goal is: Do work\nTo give my best complete final answer to the task + respond using the exact following format:\n\nThought: I now can give a great + answer\nFinal Answer: Your final answer must be the great and the most complete + as possible, it must be outcome described.\n\nI MUST use these formats, my job + depends on it!"},{"role":"user","content":"\nCurrent Task: Say ''complete'' + and nothing else.\n\nThis is the expected criteria for your final answer: The + word complete.\nyou MUST return the actual complete content as the final answer, + not a summary.\n\nBegin! This is VERY important to you, use the tools available + and give your best Final Answer, your job depends on it!\n\nThought:"}],"model":"gpt-4.1-mini"}' + headers: + User-Agent: + - X-USER-AGENT-XXX + accept: + - application/json + accept-encoding: + - ACCEPT-ENCODING-XXX + authorization: + - AUTHORIZATION-XXX + connection: + - keep-alive + content-length: + - '794' + content-type: + - application/json + host: + - api.openai.com + x-stainless-arch: + - X-STAINLESS-ARCH-XXX + x-stainless-async: + - async:asyncio + x-stainless-lang: + - python + x-stainless-os: + - X-STAINLESS-OS-XXX + x-stainless-package-version: + - 1.83.0 + x-stainless-read-timeout: + - X-STAINLESS-READ-TIMEOUT-XXX + x-stainless-retry-count: + - '0' + x-stainless-runtime: + - CPython + x-stainless-runtime-version: + - 3.12.10 + method: POST + uri: https://api.openai.com/v1/chat/completions + response: + body: + string: "{\n \"id\": \"chatcmpl-D09bYGfIe5pA04mBGuMO94KLyKhry\",\n \"object\": + \"chat.completion\",\n \"created\": 1768929292,\n \"model\": \"gpt-4.1-mini-2025-04-14\",\n + \ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\": + \"assistant\",\n \"content\": \"Thought: I now can give a great answer\\nFinal + Answer: complete\",\n \"refusal\": null,\n \"annotations\": + []\n },\n \"logprobs\": null,\n \"finish_reason\": \"stop\"\n + \ }\n ],\n \"usage\": {\n \"prompt_tokens\": 158,\n \"completion_tokens\": + 14,\n \"total_tokens\": 172,\n \"prompt_tokens_details\": {\n \"cached_tokens\": + 0,\n \"audio_tokens\": 0\n },\n \"completion_tokens_details\": + {\n \"reasoning_tokens\": 0,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\": + 0,\n \"rejected_prediction_tokens\": 0\n }\n },\n \"service_tier\": + \"default\",\n \"system_fingerprint\": \"fp_376a7ccef1\"\n}\n" + headers: + CF-RAY: + - CF-RAY-XXX + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Tue, 20 Jan 2026 17:14:53 GMT + Server: + - cloudflare + Set-Cookie: + - SET-COOKIE-XXX + Strict-Transport-Security: + - STS-XXX + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - X-CONTENT-TYPE-XXX + access-control-expose-headers: + - ACCESS-CONTROL-XXX + alt-svc: + - h3=":443"; ma=86400 + cf-cache-status: + - DYNAMIC + openai-organization: + - OPENAI-ORG-XXX + openai-processing-ms: + - '436' + openai-project: + - OPENAI-PROJECT-XXX + openai-version: + - '2020-10-01' + x-envoy-upstream-service-time: + - '660' + x-openai-proxy-wasm: + - v0.1 + x-ratelimit-limit-requests: + - X-RATELIMIT-LIMIT-REQUESTS-XXX + x-ratelimit-limit-tokens: + - X-RATELIMIT-LIMIT-TOKENS-XXX + x-ratelimit-remaining-requests: + - X-RATELIMIT-REMAINING-REQUESTS-XXX + x-ratelimit-remaining-tokens: + - X-RATELIMIT-REMAINING-TOKENS-XXX + x-ratelimit-reset-requests: + - X-RATELIMIT-RESET-REQUESTS-XXX + x-ratelimit-reset-tokens: + - X-RATELIMIT-RESET-TOKENS-XXX + x-request-id: + - X-REQUEST-ID-XXX + status: + code: 200 + message: OK +version: 1 diff --git a/lib/crewai/tests/cassettes/events/TestFlowWithCrewEventOrdering.test_method_parent_is_flow.yaml b/lib/crewai/tests/cassettes/events/TestFlowWithCrewEventOrdering.test_method_parent_is_flow.yaml new file mode 100644 index 000000000..fa566df82 --- /dev/null +++ b/lib/crewai/tests/cassettes/events/TestFlowWithCrewEventOrdering.test_method_parent_is_flow.yaml @@ -0,0 +1,118 @@ +interactions: +- request: + body: '{"messages":[{"role":"system","content":"You are Worker. You work.\nYour + personal goal is: Do work\nTo give my best complete final answer to the task + respond using the exact following format:\n\nThought: I now can give a great + answer\nFinal Answer: Your final answer must be the great and the most complete + as possible, it must be outcome described.\n\nI MUST use these formats, my job + depends on it!"},{"role":"user","content":"\nCurrent Task: Say ''ready'' and + nothing else.\n\nThis is the expected criteria for your final answer: The word + ready.\nyou MUST return the actual complete content as the final answer, not + a summary.\n\nBegin! This is VERY important to you, use the tools available + and give your best Final Answer, your job depends on it!\n\nThought:"}],"model":"gpt-4.1-mini"}' + headers: + User-Agent: + - X-USER-AGENT-XXX + accept: + - application/json + accept-encoding: + - ACCEPT-ENCODING-XXX + authorization: + - AUTHORIZATION-XXX + connection: + - keep-alive + content-length: + - '788' + content-type: + - application/json + host: + - api.openai.com + x-stainless-arch: + - X-STAINLESS-ARCH-XXX + x-stainless-async: + - async:asyncio + x-stainless-lang: + - python + x-stainless-os: + - X-STAINLESS-OS-XXX + x-stainless-package-version: + - 1.83.0 + x-stainless-read-timeout: + - X-STAINLESS-READ-TIMEOUT-XXX + x-stainless-retry-count: + - '0' + x-stainless-runtime: + - CPython + x-stainless-runtime-version: + - 3.12.10 + method: POST + uri: https://api.openai.com/v1/chat/completions + response: + body: + string: "{\n \"id\": \"chatcmpl-D09cBIfuX53tF9rWbEKXXIr20uzSv\",\n \"object\": + \"chat.completion\",\n \"created\": 1768929331,\n \"model\": \"gpt-4.1-mini-2025-04-14\",\n + \ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\": + \"assistant\",\n \"content\": \"Thought: I now can give a great answer\\nFinal + Answer: ready\",\n \"refusal\": null,\n \"annotations\": []\n + \ },\n \"logprobs\": null,\n \"finish_reason\": \"stop\"\n }\n + \ ],\n \"usage\": {\n \"prompt_tokens\": 158,\n \"completion_tokens\": + 14,\n \"total_tokens\": 172,\n \"prompt_tokens_details\": {\n \"cached_tokens\": + 0,\n \"audio_tokens\": 0\n },\n \"completion_tokens_details\": + {\n \"reasoning_tokens\": 0,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\": + 0,\n \"rejected_prediction_tokens\": 0\n }\n },\n \"service_tier\": + \"default\",\n \"system_fingerprint\": \"fp_376a7ccef1\"\n}\n" + headers: + CF-RAY: + - CF-RAY-XXX + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Tue, 20 Jan 2026 17:15:32 GMT + Server: + - cloudflare + Set-Cookie: + - SET-COOKIE-XXX + Strict-Transport-Security: + - STS-XXX + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - X-CONTENT-TYPE-XXX + access-control-expose-headers: + - ACCESS-CONTROL-XXX + alt-svc: + - h3=":443"; ma=86400 + cf-cache-status: + - DYNAMIC + openai-organization: + - OPENAI-ORG-XXX + openai-processing-ms: + - '517' + openai-project: + - OPENAI-PROJECT-XXX + openai-version: + - '2020-10-01' + x-envoy-upstream-service-time: + - '1841' + x-openai-proxy-wasm: + - v0.1 + x-ratelimit-limit-requests: + - X-RATELIMIT-LIMIT-REQUESTS-XXX + x-ratelimit-limit-tokens: + - X-RATELIMIT-LIMIT-TOKENS-XXX + x-ratelimit-remaining-requests: + - X-RATELIMIT-REMAINING-REQUESTS-XXX + x-ratelimit-remaining-tokens: + - X-RATELIMIT-REMAINING-TOKENS-XXX + x-ratelimit-reset-requests: + - X-RATELIMIT-RESET-REQUESTS-XXX + x-ratelimit-reset-tokens: + - X-RATELIMIT-RESET-TOKENS-XXX + x-request-id: + - X-REQUEST-ID-XXX + status: + code: 200 + message: OK +version: 1 diff --git a/lib/crewai/tests/cassettes/events/TestFlowWithMultipleCrewsEventOrdering.test_second_crew_after_first.yaml b/lib/crewai/tests/cassettes/events/TestFlowWithMultipleCrewsEventOrdering.test_second_crew_after_first.yaml new file mode 100644 index 000000000..629626893 --- /dev/null +++ b/lib/crewai/tests/cassettes/events/TestFlowWithMultipleCrewsEventOrdering.test_second_crew_after_first.yaml @@ -0,0 +1,234 @@ +interactions: +- request: + body: '{"messages":[{"role":"system","content":"You are First. You go first.\nYour + personal goal is: Be first\nTo give my best complete final answer to the task + respond using the exact following format:\n\nThought: I now can give a great + answer\nFinal Answer: Your final answer must be the great and the most complete + as possible, it must be outcome described.\n\nI MUST use these formats, my job + depends on it!"},{"role":"user","content":"\nCurrent Task: Say ''a'' and nothing + else.\n\nThis is the expected criteria for your final answer: The letter a.\nyou + MUST return the actual complete content as the final answer, not a summary.\n\nBegin! + This is VERY important to you, use the tools available and give your best Final + Answer, your job depends on it!\n\nThought:"}],"model":"gpt-4.1-mini"}' + headers: + User-Agent: + - X-USER-AGENT-XXX + accept: + - application/json + accept-encoding: + - ACCEPT-ENCODING-XXX + authorization: + - AUTHORIZATION-XXX + connection: + - keep-alive + content-length: + - '786' + content-type: + - application/json + host: + - api.openai.com + x-stainless-arch: + - X-STAINLESS-ARCH-XXX + x-stainless-async: + - async:asyncio + x-stainless-lang: + - python + x-stainless-os: + - X-STAINLESS-OS-XXX + x-stainless-package-version: + - 1.83.0 + x-stainless-read-timeout: + - X-STAINLESS-READ-TIMEOUT-XXX + x-stainless-retry-count: + - '0' + x-stainless-runtime: + - CPython + x-stainless-runtime-version: + - 3.12.10 + method: POST + uri: https://api.openai.com/v1/chat/completions + response: + body: + string: "{\n \"id\": \"chatcmpl-D09rkgXjWfa1XwICCnLAVV3LXFlUZ\",\n \"object\": + \"chat.completion\",\n \"created\": 1768930296,\n \"model\": \"gpt-4.1-mini-2025-04-14\",\n + \ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\": + \"assistant\",\n \"content\": \"Thought: I now can give a great answer\\nFinal + Answer: a\",\n \"refusal\": null,\n \"annotations\": []\n },\n + \ \"logprobs\": null,\n \"finish_reason\": \"stop\"\n }\n ],\n + \ \"usage\": {\n \"prompt_tokens\": 159,\n \"completion_tokens\": 14,\n + \ \"total_tokens\": 173,\n \"prompt_tokens_details\": {\n \"cached_tokens\": + 0,\n \"audio_tokens\": 0\n },\n \"completion_tokens_details\": + {\n \"reasoning_tokens\": 0,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\": + 0,\n \"rejected_prediction_tokens\": 0\n }\n },\n \"service_tier\": + \"default\",\n \"system_fingerprint\": \"fp_376a7ccef1\"\n}\n" + headers: + CF-RAY: + - CF-RAY-XXX + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Tue, 20 Jan 2026 17:31:37 GMT + Server: + - cloudflare + Set-Cookie: + - SET-COOKIE-XXX + Strict-Transport-Security: + - STS-XXX + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - X-CONTENT-TYPE-XXX + access-control-expose-headers: + - ACCESS-CONTROL-XXX + alt-svc: + - h3=":443"; ma=86400 + cf-cache-status: + - DYNAMIC + openai-organization: + - OPENAI-ORG-XXX + openai-processing-ms: + - '418' + openai-project: + - OPENAI-PROJECT-XXX + openai-version: + - '2020-10-01' + x-envoy-upstream-service-time: + - '443' + x-openai-proxy-wasm: + - v0.1 + x-ratelimit-limit-requests: + - X-RATELIMIT-LIMIT-REQUESTS-XXX + x-ratelimit-limit-tokens: + - X-RATELIMIT-LIMIT-TOKENS-XXX + x-ratelimit-remaining-requests: + - X-RATELIMIT-REMAINING-REQUESTS-XXX + x-ratelimit-remaining-tokens: + - X-RATELIMIT-REMAINING-TOKENS-XXX + x-ratelimit-reset-requests: + - X-RATELIMIT-RESET-REQUESTS-XXX + x-ratelimit-reset-tokens: + - X-RATELIMIT-RESET-TOKENS-XXX + x-request-id: + - X-REQUEST-ID-XXX + status: + code: 200 + message: OK +- request: + body: '{"messages":[{"role":"system","content":"You are Second. You go second.\nYour + personal goal is: Be second\nTo give my best complete final answer to the task + respond using the exact following format:\n\nThought: I now can give a great + answer\nFinal Answer: Your final answer must be the great and the most complete + as possible, it must be outcome described.\n\nI MUST use these formats, my job + depends on it!"},{"role":"user","content":"\nCurrent Task: Say ''b'' and nothing + else.\n\nThis is the expected criteria for your final answer: The letter b.\nyou + MUST return the actual complete content as the final answer, not a summary.\n\nBegin! + This is VERY important to you, use the tools available and give your best Final + Answer, your job depends on it!\n\nThought:"}],"model":"gpt-4.1-mini"}' + headers: + User-Agent: + - X-USER-AGENT-XXX + accept: + - application/json + accept-encoding: + - ACCEPT-ENCODING-XXX + authorization: + - AUTHORIZATION-XXX + connection: + - keep-alive + content-length: + - '789' + content-type: + - application/json + host: + - api.openai.com + x-stainless-arch: + - X-STAINLESS-ARCH-XXX + x-stainless-async: + - async:asyncio + x-stainless-lang: + - python + x-stainless-os: + - X-STAINLESS-OS-XXX + x-stainless-package-version: + - 1.83.0 + x-stainless-read-timeout: + - X-STAINLESS-READ-TIMEOUT-XXX + x-stainless-retry-count: + - '0' + x-stainless-runtime: + - CPython + x-stainless-runtime-version: + - 3.12.10 + method: POST + uri: https://api.openai.com/v1/chat/completions + response: + body: + string: "{\n \"id\": \"chatcmpl-D09rlVUPgS5haPGYgA4RmW9EfPArd\",\n \"object\": + \"chat.completion\",\n \"created\": 1768930297,\n \"model\": \"gpt-4.1-mini-2025-04-14\",\n + \ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\": + \"assistant\",\n \"content\": \"Thought: I now can give a great answer\\nFinal + Answer: b\",\n \"refusal\": null,\n \"annotations\": []\n },\n + \ \"logprobs\": null,\n \"finish_reason\": \"stop\"\n }\n ],\n + \ \"usage\": {\n \"prompt_tokens\": 159,\n \"completion_tokens\": 14,\n + \ \"total_tokens\": 173,\n \"prompt_tokens_details\": {\n \"cached_tokens\": + 0,\n \"audio_tokens\": 0\n },\n \"completion_tokens_details\": + {\n \"reasoning_tokens\": 0,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\": + 0,\n \"rejected_prediction_tokens\": 0\n }\n },\n \"service_tier\": + \"default\",\n \"system_fingerprint\": \"fp_376a7ccef1\"\n}\n" + headers: + CF-RAY: + - CF-RAY-XXX + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Tue, 20 Jan 2026 17:31:38 GMT + Server: + - cloudflare + Set-Cookie: + - SET-COOKIE-XXX + Strict-Transport-Security: + - STS-XXX + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - X-CONTENT-TYPE-XXX + access-control-expose-headers: + - ACCESS-CONTROL-XXX + alt-svc: + - h3=":443"; ma=86400 + cf-cache-status: + - DYNAMIC + openai-organization: + - OPENAI-ORG-XXX + openai-processing-ms: + - '345' + openai-project: + - OPENAI-PROJECT-XXX + openai-version: + - '2020-10-01' + x-envoy-upstream-service-time: + - '658' + x-openai-proxy-wasm: + - v0.1 + x-ratelimit-limit-requests: + - X-RATELIMIT-LIMIT-REQUESTS-XXX + x-ratelimit-limit-tokens: + - X-RATELIMIT-LIMIT-TOKENS-XXX + x-ratelimit-remaining-requests: + - X-RATELIMIT-REMAINING-REQUESTS-XXX + x-ratelimit-remaining-tokens: + - X-RATELIMIT-REMAINING-TOKENS-XXX + x-ratelimit-reset-requests: + - X-RATELIMIT-RESET-REQUESTS-XXX + x-ratelimit-reset-tokens: + - X-RATELIMIT-RESET-TOKENS-XXX + x-request-id: + - X-REQUEST-ID-XXX + status: + code: 200 + message: OK +version: 1 diff --git a/lib/crewai/tests/cassettes/events/TestFlowWithMultipleCrewsEventOrdering.test_tasks_have_correct_crew_parents.yaml b/lib/crewai/tests/cassettes/events/TestFlowWithMultipleCrewsEventOrdering.test_tasks_have_correct_crew_parents.yaml new file mode 100644 index 000000000..5a6dcfe50 --- /dev/null +++ b/lib/crewai/tests/cassettes/events/TestFlowWithMultipleCrewsEventOrdering.test_tasks_have_correct_crew_parents.yaml @@ -0,0 +1,234 @@ +interactions: +- request: + body: '{"messages":[{"role":"system","content":"You are Alpha. You are alpha.\nYour + personal goal is: Do alpha work\nTo give my best complete final answer to the + task respond using the exact following format:\n\nThought: I now can give a + great answer\nFinal Answer: Your final answer must be the great and the most + complete as possible, it must be outcome described.\n\nI MUST use these formats, + my job depends on it!"},{"role":"user","content":"\nCurrent Task: Say ''alpha'' + and nothing else.\n\nThis is the expected criteria for your final answer: The + word alpha.\nyou MUST return the actual complete content as the final answer, + not a summary.\n\nBegin! This is VERY important to you, use the tools available + and give your best Final Answer, your job depends on it!\n\nThought:"}],"model":"gpt-4.1-mini"}' + headers: + User-Agent: + - X-USER-AGENT-XXX + accept: + - application/json + accept-encoding: + - ACCEPT-ENCODING-XXX + authorization: + - AUTHORIZATION-XXX + connection: + - keep-alive + content-length: + - '798' + content-type: + - application/json + host: + - api.openai.com + x-stainless-arch: + - X-STAINLESS-ARCH-XXX + x-stainless-async: + - async:asyncio + x-stainless-lang: + - python + x-stainless-os: + - X-STAINLESS-OS-XXX + x-stainless-package-version: + - 1.83.0 + x-stainless-read-timeout: + - X-STAINLESS-READ-TIMEOUT-XXX + x-stainless-retry-count: + - '0' + x-stainless-runtime: + - CPython + x-stainless-runtime-version: + - 3.12.10 + method: POST + uri: https://api.openai.com/v1/chat/completions + response: + body: + string: "{\n \"id\": \"chatcmpl-D09ri7edf1TcYqD0vAkS3IjNkai3V\",\n \"object\": + \"chat.completion\",\n \"created\": 1768930294,\n \"model\": \"gpt-4.1-mini-2025-04-14\",\n + \ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\": + \"assistant\",\n \"content\": \"Thought: I now can give a great answer\\nFinal + Answer: alpha\",\n \"refusal\": null,\n \"annotations\": []\n + \ },\n \"logprobs\": null,\n \"finish_reason\": \"stop\"\n }\n + \ ],\n \"usage\": {\n \"prompt_tokens\": 160,\n \"completion_tokens\": + 14,\n \"total_tokens\": 174,\n \"prompt_tokens_details\": {\n \"cached_tokens\": + 0,\n \"audio_tokens\": 0\n },\n \"completion_tokens_details\": + {\n \"reasoning_tokens\": 0,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\": + 0,\n \"rejected_prediction_tokens\": 0\n }\n },\n \"service_tier\": + \"default\",\n \"system_fingerprint\": \"fp_376a7ccef1\"\n}\n" + headers: + CF-RAY: + - CF-RAY-XXX + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Tue, 20 Jan 2026 17:31:34 GMT + Server: + - cloudflare + Set-Cookie: + - SET-COOKIE-XXX + Strict-Transport-Security: + - STS-XXX + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - X-CONTENT-TYPE-XXX + access-control-expose-headers: + - ACCESS-CONTROL-XXX + alt-svc: + - h3=":443"; ma=86400 + cf-cache-status: + - DYNAMIC + openai-organization: + - OPENAI-ORG-XXX + openai-processing-ms: + - '491' + openai-project: + - OPENAI-PROJECT-XXX + openai-version: + - '2020-10-01' + x-envoy-upstream-service-time: + - '513' + x-openai-proxy-wasm: + - v0.1 + x-ratelimit-limit-requests: + - X-RATELIMIT-LIMIT-REQUESTS-XXX + x-ratelimit-limit-tokens: + - X-RATELIMIT-LIMIT-TOKENS-XXX + x-ratelimit-remaining-requests: + - X-RATELIMIT-REMAINING-REQUESTS-XXX + x-ratelimit-remaining-tokens: + - X-RATELIMIT-REMAINING-TOKENS-XXX + x-ratelimit-reset-requests: + - X-RATELIMIT-RESET-REQUESTS-XXX + x-ratelimit-reset-tokens: + - X-RATELIMIT-RESET-TOKENS-XXX + x-request-id: + - X-REQUEST-ID-XXX + status: + code: 200 + message: OK +- request: + body: '{"messages":[{"role":"system","content":"You are Beta. You are beta.\nYour + personal goal is: Do beta work\nTo give my best complete final answer to the + task respond using the exact following format:\n\nThought: I now can give a + great answer\nFinal Answer: Your final answer must be the great and the most + complete as possible, it must be outcome described.\n\nI MUST use these formats, + my job depends on it!"},{"role":"user","content":"\nCurrent Task: Say ''beta'' + and nothing else.\n\nThis is the expected criteria for your final answer: The + word beta.\nyou MUST return the actual complete content as the final answer, + not a summary.\n\nBegin! This is VERY important to you, use the tools available + and give your best Final Answer, your job depends on it!\n\nThought:"}],"model":"gpt-4.1-mini"}' + headers: + User-Agent: + - X-USER-AGENT-XXX + accept: + - application/json + accept-encoding: + - ACCEPT-ENCODING-XXX + authorization: + - AUTHORIZATION-XXX + connection: + - keep-alive + content-length: + - '793' + content-type: + - application/json + host: + - api.openai.com + x-stainless-arch: + - X-STAINLESS-ARCH-XXX + x-stainless-async: + - async:asyncio + x-stainless-lang: + - python + x-stainless-os: + - X-STAINLESS-OS-XXX + x-stainless-package-version: + - 1.83.0 + x-stainless-read-timeout: + - X-STAINLESS-READ-TIMEOUT-XXX + x-stainless-retry-count: + - '0' + x-stainless-runtime: + - CPython + x-stainless-runtime-version: + - 3.12.10 + method: POST + uri: https://api.openai.com/v1/chat/completions + response: + body: + string: "{\n \"id\": \"chatcmpl-D09rj5wiKmsX5P72qH0GEKL5pQEq6\",\n \"object\": + \"chat.completion\",\n \"created\": 1768930295,\n \"model\": \"gpt-4.1-mini-2025-04-14\",\n + \ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\": + \"assistant\",\n \"content\": \"Thought: I now can give a great answer\\nFinal + Answer: beta\",\n \"refusal\": null,\n \"annotations\": []\n + \ },\n \"logprobs\": null,\n \"finish_reason\": \"stop\"\n }\n + \ ],\n \"usage\": {\n \"prompt_tokens\": 160,\n \"completion_tokens\": + 14,\n \"total_tokens\": 174,\n \"prompt_tokens_details\": {\n \"cached_tokens\": + 0,\n \"audio_tokens\": 0\n },\n \"completion_tokens_details\": + {\n \"reasoning_tokens\": 0,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\": + 0,\n \"rejected_prediction_tokens\": 0\n }\n },\n \"service_tier\": + \"default\",\n \"system_fingerprint\": \"fp_376a7ccef1\"\n}\n" + headers: + CF-RAY: + - CF-RAY-XXX + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Tue, 20 Jan 2026 17:31:35 GMT + Server: + - cloudflare + Set-Cookie: + - SET-COOKIE-XXX + Strict-Transport-Security: + - STS-XXX + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - X-CONTENT-TYPE-XXX + access-control-expose-headers: + - ACCESS-CONTROL-XXX + alt-svc: + - h3=":443"; ma=86400 + cf-cache-status: + - DYNAMIC + openai-organization: + - OPENAI-ORG-XXX + openai-processing-ms: + - '506' + openai-project: + - OPENAI-PROJECT-XXX + openai-version: + - '2020-10-01' + x-envoy-upstream-service-time: + - '741' + x-openai-proxy-wasm: + - v0.1 + x-ratelimit-limit-requests: + - X-RATELIMIT-LIMIT-REQUESTS-XXX + x-ratelimit-limit-tokens: + - X-RATELIMIT-LIMIT-TOKENS-XXX + x-ratelimit-remaining-requests: + - X-RATELIMIT-REMAINING-REQUESTS-XXX + x-ratelimit-remaining-tokens: + - X-RATELIMIT-REMAINING-TOKENS-XXX + x-ratelimit-reset-requests: + - X-RATELIMIT-RESET-REQUESTS-XXX + x-ratelimit-reset-tokens: + - X-RATELIMIT-RESET-TOKENS-XXX + x-request-id: + - X-REQUEST-ID-XXX + status: + code: 200 + message: OK +version: 1 diff --git a/lib/crewai/tests/cassettes/events/TestFlowWithMultipleCrewsEventOrdering.test_two_crews_have_different_ids.yaml b/lib/crewai/tests/cassettes/events/TestFlowWithMultipleCrewsEventOrdering.test_two_crews_have_different_ids.yaml new file mode 100644 index 000000000..41129121a --- /dev/null +++ b/lib/crewai/tests/cassettes/events/TestFlowWithMultipleCrewsEventOrdering.test_two_crews_have_different_ids.yaml @@ -0,0 +1,234 @@ +interactions: +- request: + body: '{"messages":[{"role":"system","content":"You are First. You go first.\nYour + personal goal is: Be first\nTo give my best complete final answer to the task + respond using the exact following format:\n\nThought: I now can give a great + answer\nFinal Answer: Your final answer must be the great and the most complete + as possible, it must be outcome described.\n\nI MUST use these formats, my job + depends on it!"},{"role":"user","content":"\nCurrent Task: Say ''1'' and nothing + else.\n\nThis is the expected criteria for your final answer: The number 1.\nyou + MUST return the actual complete content as the final answer, not a summary.\n\nBegin! + This is VERY important to you, use the tools available and give your best Final + Answer, your job depends on it!\n\nThought:"}],"model":"gpt-4.1-mini"}' + headers: + User-Agent: + - X-USER-AGENT-XXX + accept: + - application/json + accept-encoding: + - ACCEPT-ENCODING-XXX + authorization: + - AUTHORIZATION-XXX + connection: + - keep-alive + content-length: + - '786' + content-type: + - application/json + host: + - api.openai.com + x-stainless-arch: + - X-STAINLESS-ARCH-XXX + x-stainless-async: + - async:asyncio + x-stainless-lang: + - python + x-stainless-os: + - X-STAINLESS-OS-XXX + x-stainless-package-version: + - 1.83.0 + x-stainless-read-timeout: + - X-STAINLESS-READ-TIMEOUT-XXX + x-stainless-retry-count: + - '0' + x-stainless-runtime: + - CPython + x-stainless-runtime-version: + - 3.12.10 + method: POST + uri: https://api.openai.com/v1/chat/completions + response: + body: + string: "{\n \"id\": \"chatcmpl-D09rmoYXlYGqmDh0Ca3r9xunjmE7k\",\n \"object\": + \"chat.completion\",\n \"created\": 1768930298,\n \"model\": \"gpt-4.1-mini-2025-04-14\",\n + \ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\": + \"assistant\",\n \"content\": \"Thought: I now can give a great answer\\nFinal + Answer: 1\",\n \"refusal\": null,\n \"annotations\": []\n },\n + \ \"logprobs\": null,\n \"finish_reason\": \"stop\"\n }\n ],\n + \ \"usage\": {\n \"prompt_tokens\": 160,\n \"completion_tokens\": 15,\n + \ \"total_tokens\": 175,\n \"prompt_tokens_details\": {\n \"cached_tokens\": + 0,\n \"audio_tokens\": 0\n },\n \"completion_tokens_details\": + {\n \"reasoning_tokens\": 0,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\": + 0,\n \"rejected_prediction_tokens\": 0\n }\n },\n \"service_tier\": + \"default\",\n \"system_fingerprint\": \"fp_376a7ccef1\"\n}\n" + headers: + CF-RAY: + - CF-RAY-XXX + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Tue, 20 Jan 2026 17:31:38 GMT + Server: + - cloudflare + Set-Cookie: + - SET-COOKIE-XXX + Strict-Transport-Security: + - STS-XXX + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - X-CONTENT-TYPE-XXX + access-control-expose-headers: + - ACCESS-CONTROL-XXX + alt-svc: + - h3=":443"; ma=86400 + cf-cache-status: + - DYNAMIC + openai-organization: + - OPENAI-ORG-XXX + openai-processing-ms: + - '387' + openai-project: + - OPENAI-PROJECT-XXX + openai-version: + - '2020-10-01' + x-envoy-upstream-service-time: + - '403' + x-openai-proxy-wasm: + - v0.1 + x-ratelimit-limit-requests: + - X-RATELIMIT-LIMIT-REQUESTS-XXX + x-ratelimit-limit-tokens: + - X-RATELIMIT-LIMIT-TOKENS-XXX + x-ratelimit-remaining-requests: + - X-RATELIMIT-REMAINING-REQUESTS-XXX + x-ratelimit-remaining-tokens: + - X-RATELIMIT-REMAINING-TOKENS-XXX + x-ratelimit-reset-requests: + - X-RATELIMIT-RESET-REQUESTS-XXX + x-ratelimit-reset-tokens: + - X-RATELIMIT-RESET-TOKENS-XXX + x-request-id: + - X-REQUEST-ID-XXX + status: + code: 200 + message: OK +- request: + body: '{"messages":[{"role":"system","content":"You are Second. You go second.\nYour + personal goal is: Be second\nTo give my best complete final answer to the task + respond using the exact following format:\n\nThought: I now can give a great + answer\nFinal Answer: Your final answer must be the great and the most complete + as possible, it must be outcome described.\n\nI MUST use these formats, my job + depends on it!"},{"role":"user","content":"\nCurrent Task: Say ''2'' and nothing + else.\n\nThis is the expected criteria for your final answer: The number 2.\nyou + MUST return the actual complete content as the final answer, not a summary.\n\nBegin! + This is VERY important to you, use the tools available and give your best Final + Answer, your job depends on it!\n\nThought:"}],"model":"gpt-4.1-mini"}' + headers: + User-Agent: + - X-USER-AGENT-XXX + accept: + - application/json + accept-encoding: + - ACCEPT-ENCODING-XXX + authorization: + - AUTHORIZATION-XXX + connection: + - keep-alive + content-length: + - '789' + content-type: + - application/json + host: + - api.openai.com + x-stainless-arch: + - X-STAINLESS-ARCH-XXX + x-stainless-async: + - async:asyncio + x-stainless-lang: + - python + x-stainless-os: + - X-STAINLESS-OS-XXX + x-stainless-package-version: + - 1.83.0 + x-stainless-read-timeout: + - X-STAINLESS-READ-TIMEOUT-XXX + x-stainless-retry-count: + - '0' + x-stainless-runtime: + - CPython + x-stainless-runtime-version: + - 3.12.10 + method: POST + uri: https://api.openai.com/v1/chat/completions + response: + body: + string: "{\n \"id\": \"chatcmpl-D09rnDNZsxICQvSZrx5rlgMdc2Tbp\",\n \"object\": + \"chat.completion\",\n \"created\": 1768930299,\n \"model\": \"gpt-4.1-mini-2025-04-14\",\n + \ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\": + \"assistant\",\n \"content\": \"Thought: I now can give a great answer\\nFinal + Answer: 2\",\n \"refusal\": null,\n \"annotations\": []\n },\n + \ \"logprobs\": null,\n \"finish_reason\": \"stop\"\n }\n ],\n + \ \"usage\": {\n \"prompt_tokens\": 160,\n \"completion_tokens\": 15,\n + \ \"total_tokens\": 175,\n \"prompt_tokens_details\": {\n \"cached_tokens\": + 0,\n \"audio_tokens\": 0\n },\n \"completion_tokens_details\": + {\n \"reasoning_tokens\": 0,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\": + 0,\n \"rejected_prediction_tokens\": 0\n }\n },\n \"service_tier\": + \"default\",\n \"system_fingerprint\": \"fp_376a7ccef1\"\n}\n" + headers: + CF-RAY: + - CF-RAY-XXX + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Tue, 20 Jan 2026 17:31:39 GMT + Server: + - cloudflare + Set-Cookie: + - SET-COOKIE-XXX + Strict-Transport-Security: + - STS-XXX + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - X-CONTENT-TYPE-XXX + access-control-expose-headers: + - ACCESS-CONTROL-XXX + alt-svc: + - h3=":443"; ma=86400 + cf-cache-status: + - DYNAMIC + openai-organization: + - OPENAI-ORG-XXX + openai-processing-ms: + - '560' + openai-project: + - OPENAI-PROJECT-XXX + openai-version: + - '2020-10-01' + x-envoy-upstream-service-time: + - '581' + x-openai-proxy-wasm: + - v0.1 + x-ratelimit-limit-requests: + - X-RATELIMIT-LIMIT-REQUESTS-XXX + x-ratelimit-limit-tokens: + - X-RATELIMIT-LIMIT-TOKENS-XXX + x-ratelimit-remaining-requests: + - X-RATELIMIT-REMAINING-REQUESTS-XXX + x-ratelimit-remaining-tokens: + - X-RATELIMIT-REMAINING-TOKENS-XXX + x-ratelimit-reset-requests: + - X-RATELIMIT-RESET-REQUESTS-XXX + x-ratelimit-reset-tokens: + - X-RATELIMIT-RESET-TOKENS-XXX + x-request-id: + - X-REQUEST-ID-XXX + status: + code: 200 + message: OK +version: 1 diff --git a/lib/crewai/tests/events/test_event_ordering.py b/lib/crewai/tests/events/test_event_ordering.py index a1a9b9662..82f585f91 100644 --- a/lib/crewai/tests/events/test_event_ordering.py +++ b/lib/crewai/tests/events/test_event_ordering.py @@ -252,8 +252,9 @@ class TestAgentEventOrdering: class TestFlowWithCrewEventOrdering: """Tests for event ordering in flows containing crews.""" + @pytest.mark.asyncio @pytest.mark.vcr() - def test_flow_events_have_ids(self, collector: EventCollector) -> None: + async def test_flow_events_have_ids(self, collector: EventCollector) -> None: """Flow events should have event_ids.""" agent = Agent( role="Worker", @@ -269,12 +270,12 @@ class TestFlowWithCrewEventOrdering: class SimpleFlow(Flow): @start() - def run_crew(self): + async def run_crew(self): c = Crew(agents=[agent], tasks=[task], verbose=False) - return c.kickoff() + return await c.akickoff() flow = SimpleFlow() - flow.kickoff() + await flow.akickoff() crewai_event_bus.flush() flow_started = collector.first(FlowStartedEvent) @@ -286,8 +287,9 @@ class TestFlowWithCrewEventOrdering: assert flow_finished is not None assert flow_finished.event_id is not None + @pytest.mark.asyncio @pytest.mark.vcr() - def test_method_parent_is_flow(self, collector: EventCollector) -> None: + async def test_method_parent_is_flow(self, collector: EventCollector) -> None: """Method execution events should have flow as parent.""" agent = Agent( role="Worker", @@ -303,12 +305,12 @@ class TestFlowWithCrewEventOrdering: class FlowWithMethod(Flow): @start() - def my_method(self): + async def my_method(self): c = Crew(agents=[agent], tasks=[task], verbose=False) - return c.kickoff() + return await c.akickoff() flow = FlowWithMethod() - flow.kickoff() + await flow.akickoff() crewai_event_bus.flush() flow_started = collector.first(FlowStartedEvent) @@ -318,8 +320,9 @@ class TestFlowWithCrewEventOrdering: assert method_started is not None assert method_started.parent_event_id == flow_started.event_id + @pytest.mark.asyncio @pytest.mark.vcr() - def test_crew_parent_is_method(self, collector: EventCollector) -> None: + async def test_crew_parent_is_method(self, collector: EventCollector) -> None: """Crew inside flow method should have method as parent.""" agent = Agent( role="Worker", @@ -335,12 +338,12 @@ class TestFlowWithCrewEventOrdering: class FlowWithCrew(Flow): @start() - def run_it(self): + async def run_it(self): c = Crew(agents=[agent], tasks=[task], verbose=False) - return c.kickoff() + return await c.akickoff() flow = FlowWithCrew() - flow.kickoff() + await flow.akickoff() crewai_event_bus.flush() method_started = collector.first(MethodExecutionStartedEvent) @@ -354,8 +357,11 @@ class TestFlowWithCrewEventOrdering: class TestFlowWithMultipleCrewsEventOrdering: """Tests for event ordering in flows with multiple crews.""" + @pytest.mark.asyncio @pytest.mark.vcr() - def test_two_crews_have_different_ids(self, collector: EventCollector) -> None: + async def test_two_crews_have_different_ids( + self, collector: EventCollector + ) -> None: """Two crews in a flow should have different event_ids.""" agent1 = Agent( role="First", @@ -382,17 +388,17 @@ class TestFlowWithMultipleCrewsEventOrdering: class TwoCrewFlow(Flow): @start() - def first(self): + async def first(self): c = Crew(agents=[agent1], tasks=[task1], verbose=False) - return c.kickoff() + return await c.akickoff() @listen(first) - def second(self, _): + async def second(self, _): c = Crew(agents=[agent2], tasks=[task2], verbose=False) - return c.kickoff() + return await c.akickoff() flow = TwoCrewFlow() - flow.kickoff() + await flow.akickoff() crewai_event_bus.flush() crew_started_events = collector.all_of(CrewKickoffStartedEvent) @@ -400,8 +406,9 @@ class TestFlowWithMultipleCrewsEventOrdering: assert len(crew_started_events) >= 2 assert crew_started_events[0].event_id != crew_started_events[1].event_id + @pytest.mark.asyncio @pytest.mark.vcr() - def test_second_crew_after_first(self, collector: EventCollector) -> None: + async def test_second_crew_after_first(self, collector: EventCollector) -> None: """Second crew should have higher sequence than first.""" agent1 = Agent( role="First", @@ -428,17 +435,17 @@ class TestFlowWithMultipleCrewsEventOrdering: class SequentialCrewFlow(Flow): @start() - def crew_a(self): + async def crew_a(self): c = Crew(agents=[agent1], tasks=[task1], verbose=False) - return c.kickoff() + return await c.akickoff() @listen(crew_a) - def crew_b(self, _): + async def crew_b(self, _): c = Crew(agents=[agent2], tasks=[task2], verbose=False) - return c.kickoff() + return await c.akickoff() flow = SequentialCrewFlow() - flow.kickoff() + await flow.akickoff() crewai_event_bus.flush() crew_started_events = collector.all_of(CrewKickoffStartedEvent) @@ -451,8 +458,11 @@ class TestFlowWithMultipleCrewsEventOrdering: assert second.emission_sequence is not None assert second.emission_sequence > first.emission_sequence + @pytest.mark.asyncio @pytest.mark.vcr() - def test_tasks_have_correct_crew_parents(self, collector: EventCollector) -> None: + async def test_tasks_have_correct_crew_parents( + self, collector: EventCollector + ) -> None: """Tasks in different crews should have their own crew as parent.""" agent1 = Agent( role="Alpha", @@ -479,17 +489,17 @@ class TestFlowWithMultipleCrewsEventOrdering: class ParentTestFlow(Flow): @start() - def alpha_crew(self): + async def alpha_crew(self): c = Crew(agents=[agent1], tasks=[task1], verbose=False) - return c.kickoff() + return await c.akickoff() @listen(alpha_crew) - def beta_crew(self, _): + async def beta_crew(self, _): c = Crew(agents=[agent2], tasks=[task2], verbose=False) - return c.kickoff() + return await c.akickoff() flow = ParentTestFlow() - flow.kickoff() + await flow.akickoff() crewai_event_bus.flush() crew_started_events = collector.all_of(CrewKickoffStartedEvent)