waldiez 0.4.7__py3-none-any.whl → 0.4.8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of waldiez might be problematic. Click here for more details.
- waldiez/__init__.py +5 -5
- waldiez/_version.py +1 -1
- waldiez/cli.py +112 -73
- waldiez/exporter.py +61 -19
- waldiez/exporting/__init__.py +25 -6
- waldiez/exporting/agent/__init__.py +7 -3
- waldiez/exporting/agent/code_execution.py +114 -0
- waldiez/exporting/agent/exporter.py +354 -0
- waldiez/exporting/agent/extras/__init__.py +15 -0
- waldiez/exporting/agent/extras/captain_agent_extras.py +315 -0
- waldiez/exporting/agent/extras/group/target.py +178 -0
- waldiez/exporting/agent/extras/group_manager_agent_extas.py +500 -0
- waldiez/exporting/agent/extras/group_member_extras.py +181 -0
- waldiez/exporting/agent/extras/handoffs/__init__.py +19 -0
- waldiez/exporting/agent/extras/handoffs/after_work.py +78 -0
- waldiez/exporting/agent/extras/handoffs/available.py +74 -0
- waldiez/exporting/agent/extras/handoffs/condition.py +158 -0
- waldiez/exporting/agent/extras/handoffs/handoff.py +171 -0
- waldiez/exporting/agent/extras/handoffs/target.py +189 -0
- waldiez/exporting/agent/extras/rag/__init__.py +10 -0
- waldiez/exporting/agent/{utils/rag_user/chroma_utils.py → extras/rag/chroma_extras.py} +16 -15
- waldiez/exporting/agent/{utils/rag_user/mongo_utils.py → extras/rag/mongo_extras.py} +10 -10
- waldiez/exporting/agent/{utils/rag_user/pgvector_utils.py → extras/rag/pgvector_extras.py} +13 -13
- waldiez/exporting/agent/{utils/rag_user/qdrant_utils.py → extras/rag/qdrant_extras.py} +13 -13
- waldiez/exporting/agent/{utils/rag_user/vector_db.py → extras/rag/vector_db_extras.py} +59 -46
- waldiez/exporting/agent/extras/rag_user_proxy_agent_extras.py +245 -0
- waldiez/exporting/agent/extras/reasoning_agent_extras.py +88 -0
- waldiez/exporting/agent/factory.py +95 -0
- waldiez/exporting/agent/processor.py +150 -0
- waldiez/exporting/agent/system_message.py +36 -0
- waldiez/exporting/agent/termination.py +50 -0
- waldiez/exporting/chats/__init__.py +7 -3
- waldiez/exporting/chats/exporter.py +97 -0
- waldiez/exporting/chats/factory.py +65 -0
- waldiez/exporting/chats/processor.py +226 -0
- waldiez/exporting/chats/utils/__init__.py +6 -5
- waldiez/exporting/chats/utils/common.py +11 -45
- waldiez/exporting/chats/utils/group.py +55 -0
- waldiez/exporting/chats/utils/nested.py +37 -52
- waldiez/exporting/chats/utils/sequential.py +72 -61
- waldiez/exporting/chats/utils/{single_chat.py → single.py} +48 -50
- waldiez/exporting/core/__init__.py +196 -0
- waldiez/exporting/core/constants.py +17 -0
- waldiez/exporting/core/content.py +69 -0
- waldiez/exporting/core/context.py +244 -0
- waldiez/exporting/core/enums.py +89 -0
- waldiez/exporting/core/errors.py +19 -0
- waldiez/exporting/core/exporter.py +390 -0
- waldiez/exporting/core/exporters.py +67 -0
- waldiez/exporting/core/extras/__init__.py +39 -0
- waldiez/exporting/core/extras/agent_extras/__init__.py +27 -0
- waldiez/exporting/core/extras/agent_extras/captain_extras.py +57 -0
- waldiez/exporting/core/extras/agent_extras/group_manager_extras.py +102 -0
- waldiez/exporting/core/extras/agent_extras/rag_user_extras.py +53 -0
- waldiez/exporting/core/extras/agent_extras/reasoning_extras.py +68 -0
- waldiez/exporting/core/extras/agent_extras/standard_extras.py +263 -0
- waldiez/exporting/core/extras/base.py +241 -0
- waldiez/exporting/core/extras/chat_extras.py +118 -0
- waldiez/exporting/core/extras/flow_extras.py +70 -0
- waldiez/exporting/core/extras/model_extras.py +73 -0
- waldiez/exporting/core/extras/path_resolver.py +93 -0
- waldiez/exporting/core/extras/serializer.py +138 -0
- waldiez/exporting/core/extras/tool_extras.py +82 -0
- waldiez/exporting/core/protocols.py +259 -0
- waldiez/exporting/core/result.py +705 -0
- waldiez/exporting/core/types.py +329 -0
- waldiez/exporting/core/utils/__init__.py +11 -0
- waldiez/exporting/core/utils/comment.py +33 -0
- waldiez/exporting/core/utils/llm_config.py +117 -0
- waldiez/exporting/core/validation.py +96 -0
- waldiez/exporting/flow/__init__.py +6 -2
- waldiez/exporting/flow/execution_generator.py +193 -0
- waldiez/exporting/flow/exporter.py +107 -0
- waldiez/exporting/flow/factory.py +94 -0
- waldiez/exporting/flow/file_generator.py +214 -0
- waldiez/exporting/flow/merger.py +387 -0
- waldiez/exporting/flow/orchestrator.py +411 -0
- waldiez/exporting/flow/utils/__init__.py +9 -36
- waldiez/exporting/flow/utils/common.py +206 -0
- waldiez/exporting/flow/utils/importing.py +373 -0
- waldiez/exporting/flow/utils/linting.py +200 -0
- waldiez/exporting/flow/utils/{logging_utils.py → logging.py} +23 -9
- waldiez/exporting/models/__init__.py +3 -1
- waldiez/exporting/models/exporter.py +233 -0
- waldiez/exporting/models/factory.py +66 -0
- waldiez/exporting/models/processor.py +139 -0
- waldiez/exporting/tools/__init__.py +11 -0
- waldiez/exporting/tools/exporter.py +207 -0
- waldiez/exporting/tools/factory.py +57 -0
- waldiez/exporting/tools/processor.py +248 -0
- waldiez/exporting/tools/registration.py +133 -0
- waldiez/io/__init__.py +128 -0
- waldiez/io/_ws.py +199 -0
- waldiez/io/models/__init__.py +60 -0
- waldiez/io/models/base.py +66 -0
- waldiez/io/models/constants.py +78 -0
- waldiez/io/models/content/__init__.py +23 -0
- waldiez/io/models/content/audio.py +43 -0
- waldiez/io/models/content/base.py +45 -0
- waldiez/io/models/content/file.py +43 -0
- waldiez/io/models/content/image.py +96 -0
- waldiez/io/models/content/text.py +37 -0
- waldiez/io/models/content/video.py +43 -0
- waldiez/io/models/user_input.py +269 -0
- waldiez/io/models/user_response.py +215 -0
- waldiez/io/mqtt.py +681 -0
- waldiez/io/redis.py +782 -0
- waldiez/io/structured.py +419 -0
- waldiez/io/utils.py +184 -0
- waldiez/io/ws.py +298 -0
- waldiez/logger.py +481 -0
- waldiez/models/__init__.py +108 -51
- waldiez/models/agents/__init__.py +34 -70
- waldiez/models/agents/agent/__init__.py +10 -4
- waldiez/models/agents/agent/agent.py +466 -65
- waldiez/models/agents/agent/agent_data.py +119 -47
- waldiez/models/agents/agent/agent_type.py +13 -2
- waldiez/models/agents/agent/code_execution.py +12 -12
- waldiez/models/agents/agent/human_input_mode.py +8 -0
- waldiez/models/agents/agent/{linked_skill.py → linked_tool.py} +7 -7
- waldiez/models/agents/agent/nested_chat.py +35 -7
- waldiez/models/agents/agent/termination_message.py +30 -22
- waldiez/models/agents/{swarm_agent → agent}/update_system_message.py +22 -22
- waldiez/models/agents/agents.py +58 -63
- waldiez/models/agents/assistant/assistant.py +4 -4
- waldiez/models/agents/assistant/assistant_data.py +13 -1
- waldiez/models/agents/{captain_agent → captain}/captain_agent.py +5 -5
- waldiez/models/agents/{captain_agent → captain}/captain_agent_data.py +5 -5
- waldiez/models/agents/extra_requirements.py +11 -16
- waldiez/models/agents/group_manager/group_manager.py +103 -13
- waldiez/models/agents/group_manager/group_manager_data.py +36 -14
- waldiez/models/agents/group_manager/speakers.py +77 -24
- waldiez/models/agents/{rag_user → rag_user_proxy}/__init__.py +16 -16
- waldiez/models/agents/rag_user_proxy/rag_user_proxy.py +64 -0
- waldiez/models/agents/{rag_user/rag_user_data.py → rag_user_proxy/rag_user_proxy_data.py} +6 -5
- waldiez/models/agents/{rag_user → rag_user_proxy}/retrieve_config.py +182 -114
- waldiez/models/agents/{rag_user → rag_user_proxy}/vector_db_config.py +13 -13
- waldiez/models/agents/reasoning/reasoning_agent.py +6 -6
- waldiez/models/agents/reasoning/reasoning_agent_data.py +110 -63
- waldiez/models/agents/reasoning/reasoning_agent_reason_config.py +38 -10
- waldiez/models/agents/user_proxy/user_proxy.py +11 -7
- waldiez/models/agents/user_proxy/user_proxy_data.py +2 -2
- waldiez/models/chat/__init__.py +2 -1
- waldiez/models/chat/chat.py +166 -87
- waldiez/models/chat/chat_data.py +99 -136
- waldiez/models/chat/chat_message.py +33 -23
- waldiez/models/chat/chat_nested.py +31 -30
- waldiez/models/chat/chat_summary.py +10 -8
- waldiez/models/common/__init__.py +52 -2
- waldiez/models/common/ag2_version.py +1 -1
- waldiez/models/common/base.py +38 -7
- waldiez/models/common/dict_utils.py +42 -17
- waldiez/models/common/handoff.py +459 -0
- waldiez/models/common/id_generator.py +19 -0
- waldiez/models/common/method_utils.py +130 -68
- waldiez/{exporting/base/utils → models/common}/naming.py +38 -61
- waldiez/models/common/waldiez_version.py +37 -0
- waldiez/models/flow/__init__.py +9 -2
- waldiez/models/flow/connection.py +18 -0
- waldiez/models/flow/flow.py +311 -215
- waldiez/models/flow/flow_data.py +207 -40
- waldiez/models/flow/info.py +85 -0
- waldiez/models/flow/naming.py +131 -0
- waldiez/models/model/__init__.py +7 -1
- waldiez/models/model/extra_requirements.py +3 -12
- waldiez/models/model/model.py +76 -21
- waldiez/models/model/model_data.py +108 -20
- waldiez/models/tool/__init__.py +16 -0
- waldiez/models/tool/extra_requirements.py +36 -0
- waldiez/models/{skill/skill.py → tool/tool.py} +88 -88
- waldiez/models/tool/tool_data.py +51 -0
- waldiez/models/tool/tool_type.py +8 -0
- waldiez/models/waldiez.py +97 -80
- waldiez/runner.py +114 -49
- waldiez/running/__init__.py +1 -1
- waldiez/running/environment.py +49 -68
- waldiez/running/gen_seq_diagram.py +16 -14
- waldiez/running/running.py +53 -34
- waldiez/utils/__init__.py +0 -4
- waldiez/utils/cli_extras/jupyter.py +5 -3
- waldiez/utils/cli_extras/runner.py +6 -4
- waldiez/utils/cli_extras/studio.py +6 -4
- waldiez/utils/conflict_checker.py +15 -9
- waldiez/utils/flaml_warnings.py +5 -5
- {waldiez-0.4.7.dist-info → waldiez-0.4.8.dist-info}/METADATA +235 -91
- waldiez-0.4.8.dist-info/RECORD +200 -0
- waldiez/exporting/agent/agent_exporter.py +0 -297
- waldiez/exporting/agent/utils/__init__.py +0 -23
- waldiez/exporting/agent/utils/captain_agent.py +0 -263
- waldiez/exporting/agent/utils/code_execution.py +0 -65
- waldiez/exporting/agent/utils/group_manager.py +0 -220
- waldiez/exporting/agent/utils/rag_user/__init__.py +0 -7
- waldiez/exporting/agent/utils/rag_user/rag_user.py +0 -209
- waldiez/exporting/agent/utils/reasoning.py +0 -36
- waldiez/exporting/agent/utils/swarm_agent.py +0 -469
- waldiez/exporting/agent/utils/teachability.py +0 -41
- waldiez/exporting/agent/utils/termination_message.py +0 -44
- waldiez/exporting/base/__init__.py +0 -25
- waldiez/exporting/base/agent_position.py +0 -75
- waldiez/exporting/base/base_exporter.py +0 -118
- waldiez/exporting/base/export_position.py +0 -48
- waldiez/exporting/base/import_position.py +0 -23
- waldiez/exporting/base/mixin.py +0 -137
- waldiez/exporting/base/utils/__init__.py +0 -18
- waldiez/exporting/base/utils/comments.py +0 -96
- waldiez/exporting/base/utils/path_check.py +0 -68
- waldiez/exporting/base/utils/to_string.py +0 -84
- waldiez/exporting/chats/chats_exporter.py +0 -240
- waldiez/exporting/chats/utils/swarm.py +0 -210
- waldiez/exporting/flow/flow_exporter.py +0 -528
- waldiez/exporting/flow/utils/agent_utils.py +0 -204
- waldiez/exporting/flow/utils/chat_utils.py +0 -71
- waldiez/exporting/flow/utils/def_main.py +0 -77
- waldiez/exporting/flow/utils/flow_content.py +0 -202
- waldiez/exporting/flow/utils/flow_names.py +0 -116
- waldiez/exporting/flow/utils/importing_utils.py +0 -227
- waldiez/exporting/models/models_exporter.py +0 -199
- waldiez/exporting/models/utils.py +0 -174
- waldiez/exporting/skills/__init__.py +0 -9
- waldiez/exporting/skills/skills_exporter.py +0 -176
- waldiez/exporting/skills/utils.py +0 -369
- waldiez/models/agents/agent/teachability.py +0 -70
- waldiez/models/agents/rag_user/rag_user.py +0 -60
- waldiez/models/agents/swarm_agent/__init__.py +0 -50
- waldiez/models/agents/swarm_agent/after_work.py +0 -179
- waldiez/models/agents/swarm_agent/on_condition.py +0 -105
- waldiez/models/agents/swarm_agent/on_condition_available.py +0 -142
- waldiez/models/agents/swarm_agent/on_condition_target.py +0 -40
- waldiez/models/agents/swarm_agent/swarm_agent.py +0 -107
- waldiez/models/agents/swarm_agent/swarm_agent_data.py +0 -124
- waldiez/models/flow/utils.py +0 -232
- waldiez/models/skill/__init__.py +0 -16
- waldiez/models/skill/extra_requirements.py +0 -36
- waldiez/models/skill/skill_data.py +0 -53
- waldiez/models/skill/skill_type.py +0 -8
- waldiez/utils/pysqlite3_checker.py +0 -308
- waldiez/utils/rdps_checker.py +0 -122
- waldiez-0.4.7.dist-info/RECORD +0 -149
- /waldiez/models/agents/{captain_agent → captain}/__init__.py +0 -0
- /waldiez/models/agents/{captain_agent → captain}/captain_agent_lib_entry.py +0 -0
- {waldiez-0.4.7.dist-info → waldiez-0.4.8.dist-info}/WHEEL +0 -0
- {waldiez-0.4.7.dist-info → waldiez-0.4.8.dist-info}/entry_points.txt +0 -0
- {waldiez-0.4.7.dist-info → waldiez-0.4.8.dist-info}/licenses/LICENSE +0 -0
- {waldiez-0.4.7.dist-info → waldiez-0.4.8.dist-info}/licenses/NOTICE.md +0 -0
waldiez/models/flow/flow.py
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
# SPDX-License-Identifier: Apache-2.0.
|
|
2
2
|
# Copyright (c) 2024 - 2025 Waldiez and contributors.
|
|
3
|
+
# pyright: reportCallIssue=false
|
|
3
4
|
"""Waldiez flow model."""
|
|
4
5
|
|
|
5
|
-
import
|
|
6
|
-
from typing import
|
|
6
|
+
from functools import cached_property
|
|
7
|
+
from typing import Optional
|
|
7
8
|
|
|
8
9
|
from pydantic import Field, model_validator
|
|
9
10
|
from typing_extensions import Annotated, Literal, Self
|
|
10
11
|
|
|
11
|
-
from ..agents import WaldiezAgent,
|
|
12
|
+
from ..agents import WaldiezAgent, WaldiezGroupManager
|
|
12
13
|
from ..chat import WaldiezChat
|
|
13
|
-
from ..common import WaldiezBase, now
|
|
14
|
+
from ..common import WaldiezBase, get_id, get_waldiez_version, now
|
|
15
|
+
from .connection import WaldiezAgentConnection
|
|
14
16
|
from .flow_data import WaldiezFlowData
|
|
15
|
-
from .
|
|
17
|
+
from .naming import WaldiezUniqueNames, ensure_unique_names
|
|
16
18
|
|
|
17
19
|
|
|
18
20
|
class WaldiezFlow(WaldiezBase):
|
|
@@ -28,9 +30,9 @@ class WaldiezFlow(WaldiezBase):
|
|
|
28
30
|
The name of the flow.
|
|
29
31
|
description : str
|
|
30
32
|
The description of the flow.
|
|
31
|
-
tags :
|
|
33
|
+
tags : list[str]
|
|
32
34
|
The tags of the flow.
|
|
33
|
-
requirements :
|
|
35
|
+
requirements : list[str]
|
|
34
36
|
The requirements of the flow.
|
|
35
37
|
storage_id : str
|
|
36
38
|
The storage ID of the flow (ignored, UI related).
|
|
@@ -47,9 +49,17 @@ class WaldiezFlow(WaldiezBase):
|
|
|
47
49
|
Field(
|
|
48
50
|
description="The ID of the flow",
|
|
49
51
|
title="ID",
|
|
50
|
-
default_factory=
|
|
52
|
+
default_factory=get_id,
|
|
51
53
|
),
|
|
52
54
|
]
|
|
55
|
+
version: Annotated[
|
|
56
|
+
str,
|
|
57
|
+
Field(
|
|
58
|
+
default_factory=get_waldiez_version,
|
|
59
|
+
description="The version waldiez that was used to create the flow",
|
|
60
|
+
title="Version",
|
|
61
|
+
),
|
|
62
|
+
] = "0.0.0" # default to 0.0.0 if not found
|
|
53
63
|
type: Annotated[
|
|
54
64
|
Literal["flow"],
|
|
55
65
|
Field(
|
|
@@ -75,7 +85,7 @@ class WaldiezFlow(WaldiezBase):
|
|
|
75
85
|
),
|
|
76
86
|
]
|
|
77
87
|
tags: Annotated[
|
|
78
|
-
|
|
88
|
+
list[str],
|
|
79
89
|
Field(
|
|
80
90
|
description="The tags of the flow",
|
|
81
91
|
title="Tags",
|
|
@@ -83,7 +93,7 @@ class WaldiezFlow(WaldiezBase):
|
|
|
83
93
|
),
|
|
84
94
|
]
|
|
85
95
|
requirements: Annotated[
|
|
86
|
-
|
|
96
|
+
list[str],
|
|
87
97
|
Field(
|
|
88
98
|
description="The requirements of the flow",
|
|
89
99
|
title="Requirements",
|
|
@@ -101,7 +111,7 @@ class WaldiezFlow(WaldiezBase):
|
|
|
101
111
|
storage_id: Annotated[
|
|
102
112
|
str,
|
|
103
113
|
Field(
|
|
104
|
-
|
|
114
|
+
default_factory=get_id,
|
|
105
115
|
description="The storage ID of the flow (ignored, UI related)",
|
|
106
116
|
title="Storage ID",
|
|
107
117
|
alias="storageId",
|
|
@@ -123,10 +133,9 @@ class WaldiezFlow(WaldiezBase):
|
|
|
123
133
|
description="The date and time when the flow was last updated.",
|
|
124
134
|
),
|
|
125
135
|
]
|
|
126
|
-
_ordered_flow: Optional[
|
|
127
|
-
List[Tuple[WaldiezChat, WaldiezAgent, WaldiezAgent]]
|
|
128
|
-
] = None
|
|
136
|
+
_ordered_flow: Optional[list[WaldiezAgentConnection]] = None
|
|
129
137
|
_single_agent_mode: bool = False
|
|
138
|
+
_is_group_chat: bool = False
|
|
130
139
|
|
|
131
140
|
@property
|
|
132
141
|
def is_async(self) -> bool:
|
|
@@ -150,19 +159,6 @@ class WaldiezFlow(WaldiezBase):
|
|
|
150
159
|
"""
|
|
151
160
|
return self.data.cache_seed
|
|
152
161
|
|
|
153
|
-
@property
|
|
154
|
-
def is_swarm_flow(self) -> bool:
|
|
155
|
-
"""Check if the flow is a swarm flow.
|
|
156
|
-
|
|
157
|
-
Returns
|
|
158
|
-
-------
|
|
159
|
-
bool
|
|
160
|
-
True if the flow is a swarm flow, False otherwise.
|
|
161
|
-
"""
|
|
162
|
-
return any(
|
|
163
|
-
agent.agent_type == "swarm" for agent in self.data.agents.members
|
|
164
|
-
)
|
|
165
|
-
|
|
166
162
|
@property
|
|
167
163
|
def is_single_agent_mode(self) -> bool:
|
|
168
164
|
"""Check if the flow is in single agent mode.
|
|
@@ -177,12 +173,30 @@ class WaldiezFlow(WaldiezBase):
|
|
|
177
173
|
@property
|
|
178
174
|
def ordered_flow(
|
|
179
175
|
self,
|
|
180
|
-
) ->
|
|
176
|
+
) -> list[WaldiezAgentConnection]:
|
|
181
177
|
"""Get the ordered flow."""
|
|
182
|
-
if
|
|
178
|
+
if self._ordered_flow is None:
|
|
183
179
|
self._ordered_flow = self._get_flow_order()
|
|
184
180
|
return self._ordered_flow
|
|
185
181
|
|
|
182
|
+
@cached_property
|
|
183
|
+
def unique_names(self) -> WaldiezUniqueNames:
|
|
184
|
+
"""Get the unique names for the flow.
|
|
185
|
+
|
|
186
|
+
Returns
|
|
187
|
+
-------
|
|
188
|
+
WaldiezUniqueNames
|
|
189
|
+
The unique names for the flow.
|
|
190
|
+
"""
|
|
191
|
+
return ensure_unique_names(
|
|
192
|
+
flow_id=self.id,
|
|
193
|
+
flow_name=self.name,
|
|
194
|
+
flow_agents=self.data.agents.members,
|
|
195
|
+
flow_chats=self.data.chats,
|
|
196
|
+
flow_tools=self.data.tools,
|
|
197
|
+
flow_models=self.data.models,
|
|
198
|
+
)
|
|
199
|
+
|
|
186
200
|
def get_agent_by_id(self, agent_id: str) -> WaldiezAgent:
|
|
187
201
|
"""Get the agent by ID.
|
|
188
202
|
|
|
@@ -206,89 +220,51 @@ class WaldiezFlow(WaldiezBase):
|
|
|
206
220
|
return agent
|
|
207
221
|
raise ValueError(f"Agent with ID {agent_id} not found.")
|
|
208
222
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
"""Get the ordered flow."""
|
|
213
|
-
# in the chats, there is the 'order' field, we use this,
|
|
214
|
-
# we only keep the ones with order >=0
|
|
215
|
-
# and sort them by this property
|
|
216
|
-
ordered_flow: List[Tuple[WaldiezChat, WaldiezAgent, WaldiezAgent]] = []
|
|
217
|
-
# if swarm, we only keep the first chat
|
|
218
|
-
if self.is_swarm_flow:
|
|
219
|
-
ordered_flow = self._get_swarm_flow()
|
|
220
|
-
if ordered_flow:
|
|
221
|
-
return ordered_flow
|
|
222
|
-
for chat in self.data.chats:
|
|
223
|
-
if chat.data.order < 0:
|
|
224
|
-
continue
|
|
225
|
-
source = self.get_agent_by_id(chat.source)
|
|
226
|
-
target = self.get_agent_by_id(chat.target)
|
|
227
|
-
ordered_flow.append((chat, source, target))
|
|
228
|
-
if not ordered_flow:
|
|
229
|
-
if len(self.data.chats) == 1:
|
|
230
|
-
chat = self.data.chats[0]
|
|
231
|
-
source = self.get_agent_by_id(chat.source)
|
|
232
|
-
target = self.get_agent_by_id(chat.target)
|
|
233
|
-
ordered_flow.append((chat, source, target))
|
|
234
|
-
return ordered_flow
|
|
223
|
+
@classmethod
|
|
224
|
+
def default(cls) -> "WaldiezFlow":
|
|
225
|
+
"""Get the default flow.
|
|
235
226
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
if not valid_chats:
|
|
254
|
-
return []
|
|
255
|
-
for valid_chat in valid_chats:
|
|
256
|
-
source = self.get_agent_by_id(valid_chat.source)
|
|
257
|
-
if isinstance(source, WaldiezSwarmAgent) and source.is_initial:
|
|
258
|
-
return [
|
|
259
|
-
(
|
|
260
|
-
valid_chat,
|
|
261
|
-
source,
|
|
262
|
-
self.get_agent_by_id(valid_chat.target),
|
|
263
|
-
)
|
|
264
|
-
]
|
|
265
|
-
first_chat: Optional[WaldiezChat] = None
|
|
266
|
-
# first check the order
|
|
267
|
-
by_order = sorted(
|
|
268
|
-
filter(lambda edge: edge.data.order >= 0, valid_chats),
|
|
269
|
-
key=lambda edge: edge.data.order,
|
|
227
|
+
Returns
|
|
228
|
+
-------
|
|
229
|
+
WaldiezFlow
|
|
230
|
+
The default flow.
|
|
231
|
+
"""
|
|
232
|
+
an_id = get_id()
|
|
233
|
+
return cls(
|
|
234
|
+
id=an_id,
|
|
235
|
+
storage_id=an_id,
|
|
236
|
+
created_at=now(),
|
|
237
|
+
updated_at=now(),
|
|
238
|
+
type="flow",
|
|
239
|
+
name="Default Flow",
|
|
240
|
+
description="Default Flow",
|
|
241
|
+
tags=[],
|
|
242
|
+
requirements=[],
|
|
243
|
+
data=WaldiezFlowData.default(),
|
|
270
244
|
)
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
245
|
+
|
|
246
|
+
def get_group_members(self, group_id: str) -> list[WaldiezAgent]:
|
|
247
|
+
"""Get the group members.
|
|
248
|
+
|
|
249
|
+
Parameters
|
|
250
|
+
----------
|
|
251
|
+
group_id : str
|
|
252
|
+
The ID of the group.
|
|
253
|
+
|
|
254
|
+
Returns
|
|
255
|
+
-------
|
|
256
|
+
list[WaldiezAgent]
|
|
257
|
+
The list of group members.
|
|
258
|
+
"""
|
|
259
|
+
return [
|
|
260
|
+
agent
|
|
261
|
+
for agent in self.data.agents.members
|
|
262
|
+
if agent.data.parent_id == group_id
|
|
263
|
+
]
|
|
288
264
|
|
|
289
265
|
def get_agent_connections(
|
|
290
266
|
self, agent_id: str, all_chats: bool = True
|
|
291
|
-
) ->
|
|
267
|
+
) -> list[str]:
|
|
292
268
|
"""Get the agent connections.
|
|
293
269
|
|
|
294
270
|
Parameters
|
|
@@ -301,10 +277,10 @@ class WaldiezFlow(WaldiezBase):
|
|
|
301
277
|
|
|
302
278
|
Returns
|
|
303
279
|
-------
|
|
304
|
-
|
|
280
|
+
list[str]
|
|
305
281
|
The list of agent ids that the agent with the given ID connects to.
|
|
306
282
|
"""
|
|
307
|
-
connections:
|
|
283
|
+
connections: list[str] = []
|
|
308
284
|
if all_chats:
|
|
309
285
|
for chat in self.data.chats:
|
|
310
286
|
if chat.source == agent_id:
|
|
@@ -312,7 +288,9 @@ class WaldiezFlow(WaldiezBase):
|
|
|
312
288
|
if chat.target == agent_id:
|
|
313
289
|
connections.append(chat.source)
|
|
314
290
|
else:
|
|
315
|
-
for
|
|
291
|
+
for entry in self.ordered_flow:
|
|
292
|
+
source = entry["source"]
|
|
293
|
+
target = entry["target"]
|
|
316
294
|
if source.id == agent_id:
|
|
317
295
|
connections.append(target.id)
|
|
318
296
|
if target.id == agent_id:
|
|
@@ -321,7 +299,7 @@ class WaldiezFlow(WaldiezBase):
|
|
|
321
299
|
|
|
322
300
|
def get_group_chat_members(
|
|
323
301
|
self, group_manager_id: str
|
|
324
|
-
) ->
|
|
302
|
+
) -> list[WaldiezAgent]:
|
|
325
303
|
"""Get the group chat members.
|
|
326
304
|
|
|
327
305
|
Parameters
|
|
@@ -331,89 +309,142 @@ class WaldiezFlow(WaldiezBase):
|
|
|
331
309
|
|
|
332
310
|
Returns
|
|
333
311
|
-------
|
|
334
|
-
|
|
335
|
-
The list of group chat
|
|
312
|
+
list[WaldiezAgent]
|
|
313
|
+
The list of group chat members.
|
|
336
314
|
"""
|
|
337
315
|
agent = self.get_agent_by_id(group_manager_id)
|
|
338
|
-
if agent.
|
|
316
|
+
if not agent.is_group_manager or not isinstance(
|
|
317
|
+
agent, WaldiezGroupManager
|
|
318
|
+
):
|
|
339
319
|
return []
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
320
|
+
members = [
|
|
321
|
+
agent
|
|
322
|
+
for agent in self.data.agents.members
|
|
323
|
+
if agent.data.parent_id == group_manager_id
|
|
324
|
+
]
|
|
325
|
+
if agent.data.speakers.selection_method != "round_robin":
|
|
326
|
+
return members
|
|
327
|
+
ordered_ids = agent.get_speakers_order()
|
|
328
|
+
if not ordered_ids:
|
|
329
|
+
return members
|
|
330
|
+
members_dict = {member.id: member for member in members}
|
|
331
|
+
ordered_members = [
|
|
332
|
+
members_dict[member_id]
|
|
333
|
+
for member_id in ordered_ids
|
|
334
|
+
if member_id in members_dict
|
|
335
|
+
]
|
|
336
|
+
return ordered_members
|
|
345
337
|
|
|
346
|
-
def
|
|
347
|
-
|
|
338
|
+
def _get_flow_order(
|
|
339
|
+
self,
|
|
340
|
+
) -> list[WaldiezAgentConnection]:
|
|
341
|
+
"""Get the ordered flow."""
|
|
342
|
+
if self._is_group_chat:
|
|
343
|
+
return self._get_group_chat_flow()
|
|
344
|
+
# in the chats, there is the 'order' field, we use this,
|
|
345
|
+
# we only keep the ones with order >=0
|
|
346
|
+
# and sort them by this property
|
|
347
|
+
ordered_flow: list[WaldiezAgentConnection] = []
|
|
348
|
+
for chat in self.data.chats:
|
|
349
|
+
if chat.data.order < 0:
|
|
350
|
+
continue
|
|
351
|
+
source = self.get_agent_by_id(chat.source)
|
|
352
|
+
target = self.get_agent_by_id(chat.target)
|
|
353
|
+
ordered_flow.append(
|
|
354
|
+
{
|
|
355
|
+
"source": source,
|
|
356
|
+
"target": target,
|
|
357
|
+
"chat": chat,
|
|
358
|
+
}
|
|
359
|
+
)
|
|
360
|
+
# ordered_flow.append((chat, source, target))
|
|
361
|
+
if not ordered_flow:
|
|
362
|
+
if len(self.data.chats) == 1:
|
|
363
|
+
chat = self.data.chats[0]
|
|
364
|
+
source = self.get_agent_by_id(chat.source)
|
|
365
|
+
target = self.get_agent_by_id(chat.target)
|
|
366
|
+
ordered_flow.append(
|
|
367
|
+
{
|
|
368
|
+
"source": source,
|
|
369
|
+
"target": target,
|
|
370
|
+
"chat": chat,
|
|
371
|
+
}
|
|
372
|
+
)
|
|
373
|
+
return ordered_flow
|
|
374
|
+
|
|
375
|
+
def get_root_group_manager(self) -> WaldiezGroupManager:
|
|
376
|
+
"""Get the root group manager.
|
|
348
377
|
|
|
349
378
|
Returns
|
|
350
379
|
-------
|
|
351
|
-
|
|
352
|
-
The
|
|
380
|
+
WaldiezGroupManager
|
|
381
|
+
The root group manager.
|
|
382
|
+
|
|
383
|
+
Raises
|
|
384
|
+
------
|
|
385
|
+
ValueError
|
|
386
|
+
If no group manager is found.
|
|
353
387
|
"""
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
if (
|
|
359
|
-
target_agent.agent_type == "swarm"
|
|
360
|
-
and source_agent.agent_type != "swarm"
|
|
361
|
-
):
|
|
362
|
-
return target_agent
|
|
363
|
-
if (
|
|
364
|
-
source_agent.agent_type == "swarm"
|
|
365
|
-
and target_agent.agent_type == "swarm"
|
|
366
|
-
):
|
|
367
|
-
fallback_agent = source_agent
|
|
368
|
-
break
|
|
369
|
-
for swarm_agent in self.data.agents.swarm_agents:
|
|
370
|
-
if swarm_agent.is_initial:
|
|
371
|
-
return swarm_agent
|
|
372
|
-
return fallback_agent
|
|
373
|
-
|
|
374
|
-
def get_swarm_chat_members(
|
|
375
|
-
self,
|
|
376
|
-
initial_agent: WaldiezAgent,
|
|
377
|
-
) -> Tuple[List[WaldiezAgent], Optional[WaldiezAgent]]:
|
|
378
|
-
"""Get the swarm chat members.
|
|
388
|
+
for agent in self.data.agents.groupManagerAgents:
|
|
389
|
+
if agent.data.parent_id is None:
|
|
390
|
+
return agent
|
|
391
|
+
raise ValueError("No group manager found.")
|
|
379
392
|
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
393
|
+
def _get_group_chat_flow(
|
|
394
|
+
self,
|
|
395
|
+
) -> list[WaldiezAgentConnection]:
|
|
396
|
+
"""Get the ordered flow for group chat.
|
|
384
397
|
|
|
385
398
|
Returns
|
|
386
399
|
-------
|
|
387
|
-
|
|
388
|
-
The
|
|
400
|
+
list[tuple[WaldiezChat, WaldiezAgent, WaldiezAgent]]
|
|
401
|
+
The ordered flow for group chat.
|
|
389
402
|
"""
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
403
|
+
# in a group chat there is no "order", the group manager
|
|
404
|
+
# handles the conversation (using the group "pattern")
|
|
405
|
+
# the only thin to check is if there is a user agent that connects
|
|
406
|
+
# to the group manager agent (so that would be the first chat)
|
|
407
|
+
# if found, we must then check if the message from the user
|
|
408
|
+
# to the group manager is:
|
|
409
|
+
# - "text" or "none" => no need to create a group manager on ag2
|
|
410
|
+
# - "function/method" => create a group manager and a group chat on ag2
|
|
411
|
+
# in the first case, the chat would be:
|
|
412
|
+
# result, context, last_agent = initiate_group_chat(
|
|
413
|
+
# pattern=pattern,
|
|
414
|
+
# messages=...,
|
|
415
|
+
# max_rounds=10
|
|
416
|
+
# )
|
|
417
|
+
# in the second case, the chat would be:
|
|
418
|
+
# user.initiate_chat(manager, ...)
|
|
393
419
|
user_agent: Optional[WaldiezAgent] = None
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
return members, user_agent
|
|
420
|
+
to_root_manager: Optional[WaldiezChat] = None
|
|
421
|
+
root_manager: WaldiezGroupManager = self.get_root_group_manager()
|
|
422
|
+
for chat in self.data.chats:
|
|
423
|
+
if chat.target == root_manager.id:
|
|
424
|
+
# check if the source is a user agent
|
|
425
|
+
source = self.get_agent_by_id(chat.source)
|
|
426
|
+
if source.is_user:
|
|
427
|
+
user_agent = source
|
|
428
|
+
to_root_manager = chat
|
|
429
|
+
break
|
|
430
|
+
if not to_root_manager or not user_agent:
|
|
431
|
+
return []
|
|
432
|
+
return [
|
|
433
|
+
{
|
|
434
|
+
"source": user_agent,
|
|
435
|
+
"target": root_manager,
|
|
436
|
+
"chat": to_root_manager,
|
|
437
|
+
}
|
|
438
|
+
]
|
|
414
439
|
|
|
415
440
|
def _validate_agent_connections(self) -> None:
|
|
416
441
|
for agent in self.data.agents.members:
|
|
442
|
+
if agent.is_group_member:
|
|
443
|
+
# group members are allowed
|
|
444
|
+
# to not connect to any other node
|
|
445
|
+
# the group manager will take care of
|
|
446
|
+
# the agent/speaker connections
|
|
447
|
+
continue
|
|
417
448
|
if not any(
|
|
418
449
|
agent.id in (chat.source, chat.target)
|
|
419
450
|
for chat in self.data.chats
|
|
@@ -429,15 +460,15 @@ class WaldiezFlow(WaldiezBase):
|
|
|
429
460
|
|
|
430
461
|
- unique node ids
|
|
431
462
|
- there are at least two agents
|
|
432
|
-
- (or a single agent but not a group manager
|
|
463
|
+
- (or a single agent but not a group manager)
|
|
433
464
|
- all the agents connect to at least one other agent
|
|
434
|
-
- all the linked agent
|
|
465
|
+
- all the linked agent tools are found in the flow
|
|
435
466
|
- all the linked agent models are found in the flow
|
|
436
467
|
- all the managers have at least one member in the chat group
|
|
437
468
|
- the ordered flow (chats with position >=0) is not empty
|
|
438
|
-
- all agents' code execution config functions exist in the flow
|
|
439
|
-
- if
|
|
440
|
-
- if
|
|
469
|
+
- all agents' code execution config functions exist in the flow tools
|
|
470
|
+
- if group chat flow, there is at least one group manager agent
|
|
471
|
+
- if group chat flow, there is an initial group member agent
|
|
441
472
|
|
|
442
473
|
Returns
|
|
443
474
|
-------
|
|
@@ -449,34 +480,35 @@ class WaldiezFlow(WaldiezBase):
|
|
|
449
480
|
ValueError
|
|
450
481
|
If the ordered flow is empty.
|
|
451
482
|
If the model IDs are not unique.
|
|
452
|
-
If the
|
|
483
|
+
If the tool IDs are not unique.
|
|
453
484
|
If the agents do not connect to any other node.
|
|
454
485
|
If the manager's group chat has no members.
|
|
455
486
|
"""
|
|
456
487
|
all_members = list(self.data.agents.members)
|
|
488
|
+
all_chats = list(self.data.chats)
|
|
489
|
+
for agent in all_members:
|
|
490
|
+
agent.gather_nested_chats(
|
|
491
|
+
all_agents=all_members, all_chats=all_chats
|
|
492
|
+
)
|
|
493
|
+
agent.gather_handoffs(all_agents=all_members, all_chats=all_chats)
|
|
494
|
+
self._validate_group_chat(all_members)
|
|
457
495
|
if len(all_members) == 1:
|
|
458
|
-
return self.
|
|
459
|
-
|
|
496
|
+
return self._validate_single_agent_mode(all_members[0])
|
|
497
|
+
ordered_flow = self.ordered_flow # could be empty (if group chat)
|
|
498
|
+
if not ordered_flow and self._ordered_flow is None:
|
|
460
499
|
raise ValueError("The ordered flow is empty.")
|
|
461
|
-
model_ids = self.
|
|
462
|
-
|
|
463
|
-
self.data.agents.validate_flow(model_ids,
|
|
500
|
+
model_ids = self._validate_flow_models()
|
|
501
|
+
tools_ids = self._validate_flow_tools()
|
|
502
|
+
self.data.agents.validate_flow(model_ids, tools_ids)
|
|
464
503
|
self._validate_agent_connections()
|
|
465
|
-
if self.is_swarm_flow:
|
|
466
|
-
for swarm_agent in self.data.agents.swarm_agents:
|
|
467
|
-
check_handoff_to_nested_chat(
|
|
468
|
-
swarm_agent,
|
|
469
|
-
all_agents=list(self.data.agents.members),
|
|
470
|
-
all_chats=self.data.chats,
|
|
471
|
-
)
|
|
472
504
|
return self
|
|
473
505
|
|
|
474
|
-
def
|
|
506
|
+
def _validate_flow_models(self) -> list[str]:
|
|
475
507
|
"""Validate the flow models.
|
|
476
508
|
|
|
477
509
|
Returns
|
|
478
510
|
-------
|
|
479
|
-
|
|
511
|
+
list[str]
|
|
480
512
|
The list of model IDs.
|
|
481
513
|
|
|
482
514
|
Raises
|
|
@@ -489,25 +521,25 @@ class WaldiezFlow(WaldiezBase):
|
|
|
489
521
|
raise ValueError("Model IDs must be unique.")
|
|
490
522
|
return model_ids
|
|
491
523
|
|
|
492
|
-
def
|
|
493
|
-
"""Validate the flow
|
|
524
|
+
def _validate_flow_tools(self) -> list[str]:
|
|
525
|
+
"""Validate the flow tools.
|
|
494
526
|
|
|
495
527
|
Returns
|
|
496
528
|
-------
|
|
497
|
-
|
|
498
|
-
The list of
|
|
529
|
+
list[str]
|
|
530
|
+
The list of tool IDs.
|
|
499
531
|
|
|
500
532
|
Raises
|
|
501
533
|
------
|
|
502
534
|
ValueError
|
|
503
|
-
If the
|
|
535
|
+
If the tool IDs are not unique.
|
|
504
536
|
"""
|
|
505
|
-
|
|
506
|
-
if len(
|
|
507
|
-
raise ValueError("
|
|
508
|
-
return
|
|
537
|
+
tool_ids = [tool.id for tool in self.data.tools]
|
|
538
|
+
if len(tool_ids) != len(set(tool_ids)):
|
|
539
|
+
raise ValueError("Tool IDs must be unique.")
|
|
540
|
+
return tool_ids
|
|
509
541
|
|
|
510
|
-
def
|
|
542
|
+
def _validate_single_agent_mode(self, member: WaldiezAgent) -> Self:
|
|
511
543
|
"""Flow validation for single agent mode.
|
|
512
544
|
|
|
513
545
|
Parameters
|
|
@@ -523,17 +555,81 @@ class WaldiezFlow(WaldiezBase):
|
|
|
523
555
|
Raises
|
|
524
556
|
------
|
|
525
557
|
ValueError
|
|
526
|
-
- If the only agent is a group manager
|
|
558
|
+
- If the only agent is a group manager.
|
|
527
559
|
- If the model IDs are not unique.
|
|
528
|
-
- If the
|
|
560
|
+
- If the tool IDs are not unique.
|
|
529
561
|
"""
|
|
530
|
-
if member.
|
|
562
|
+
if member.is_group_manager:
|
|
531
563
|
raise ValueError(
|
|
532
|
-
"In single agent mode, "
|
|
533
|
-
"the agent must not be a group manager or a swarm agent."
|
|
564
|
+
"In single agent mode, the agent must not be a group manager."
|
|
534
565
|
)
|
|
535
|
-
model_ids = self.
|
|
536
|
-
|
|
537
|
-
self.data.agents.validate_flow(model_ids,
|
|
566
|
+
model_ids = self._validate_flow_models()
|
|
567
|
+
tools_ids = self._validate_flow_tools()
|
|
568
|
+
self.data.agents.validate_flow(model_ids, tools_ids)
|
|
538
569
|
self._single_agent_mode = True
|
|
539
570
|
return self
|
|
571
|
+
|
|
572
|
+
def _validate_group_manager(
|
|
573
|
+
self, group_manager: WaldiezGroupManager, all_member_ids: list[str]
|
|
574
|
+
) -> None:
|
|
575
|
+
"""Validate the group manager agents.
|
|
576
|
+
|
|
577
|
+
Raises
|
|
578
|
+
------
|
|
579
|
+
ValueError
|
|
580
|
+
If there are no group manager agents.
|
|
581
|
+
"""
|
|
582
|
+
if not group_manager.data.initial_agent_id:
|
|
583
|
+
raise ValueError(
|
|
584
|
+
"The flow is a group chat but the group manager agent "
|
|
585
|
+
f"{group_manager.id} has no initial agent ID."
|
|
586
|
+
)
|
|
587
|
+
if group_manager.data.initial_agent_id not in all_member_ids:
|
|
588
|
+
raise ValueError(
|
|
589
|
+
"The flow is a group chat but the initial agent ID "
|
|
590
|
+
f"{group_manager.data.initial_agent_id} is not in the flow."
|
|
591
|
+
)
|
|
592
|
+
group_members = self.get_group_members(group_manager.id)
|
|
593
|
+
if not group_members:
|
|
594
|
+
raise ValueError(
|
|
595
|
+
"The flow is a group chat but the group manager agent "
|
|
596
|
+
f"{group_manager.id} has no members in the group."
|
|
597
|
+
)
|
|
598
|
+
group_manager.set_speakers_order(
|
|
599
|
+
[member.id for member in group_members]
|
|
600
|
+
)
|
|
601
|
+
|
|
602
|
+
def _validate_group_chat(self, all_members: list[WaldiezAgent]) -> None:
|
|
603
|
+
"""Check if the flow is a group chat and validate it.
|
|
604
|
+
|
|
605
|
+
Raises
|
|
606
|
+
------
|
|
607
|
+
ValueError
|
|
608
|
+
If the flow is a group chat and there is no group manager agent,
|
|
609
|
+
if the group has no members,
|
|
610
|
+
or if the group has no initial member agent.
|
|
611
|
+
"""
|
|
612
|
+
if not self.data.agents.groupManagerAgents:
|
|
613
|
+
# no group manager agents, not a group chat
|
|
614
|
+
return
|
|
615
|
+
self._is_group_chat = True
|
|
616
|
+
if not any(agent.is_group_member for agent in self.data.agents.members):
|
|
617
|
+
raise ValueError(
|
|
618
|
+
"The flow is a group chat but has no members in the group."
|
|
619
|
+
)
|
|
620
|
+
# check if the group manager agents are the flow
|
|
621
|
+
group_manager_ids = [
|
|
622
|
+
agent.id for agent in self.data.agents.groupManagerAgents
|
|
623
|
+
]
|
|
624
|
+
all_member_ids = [agent.id for agent in all_members]
|
|
625
|
+
if not all(
|
|
626
|
+
group_manager_id in all_member_ids
|
|
627
|
+
for group_manager_id in group_manager_ids
|
|
628
|
+
):
|
|
629
|
+
raise ValueError(
|
|
630
|
+
"The flow is a group chat but not all group manager agents are "
|
|
631
|
+
"in the flow."
|
|
632
|
+
)
|
|
633
|
+
# check the initial_agent_id for each group
|
|
634
|
+
for group_manager in self.data.agents.groupManagerAgents:
|
|
635
|
+
self._validate_group_manager(group_manager, all_member_ids)
|