autobyteus 1.1.4__py3-none-any.whl → 1.1.5__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.
Files changed (167) hide show
  1. autobyteus/agent/context/__init__.py +4 -2
  2. autobyteus/agent/context/agent_config.py +0 -4
  3. autobyteus/agent/context/agent_context_registry.py +73 -0
  4. autobyteus/agent/events/notifiers.py +4 -0
  5. autobyteus/agent/handlers/inter_agent_message_event_handler.py +7 -2
  6. autobyteus/agent/handlers/llm_complete_response_received_event_handler.py +19 -19
  7. autobyteus/agent/handlers/user_input_message_event_handler.py +15 -0
  8. autobyteus/agent/message/send_message_to.py +29 -23
  9. autobyteus/agent/runtime/agent_runtime.py +10 -2
  10. autobyteus/agent/sender_type.py +15 -0
  11. autobyteus/agent/streaming/agent_event_stream.py +6 -0
  12. autobyteus/agent/streaming/stream_event_payloads.py +12 -0
  13. autobyteus/agent/streaming/stream_events.py +3 -0
  14. autobyteus/agent/system_prompt_processor/tool_manifest_injector_processor.py +7 -4
  15. autobyteus/agent_team/__init__.py +1 -0
  16. autobyteus/agent_team/agent_team.py +93 -0
  17. autobyteus/agent_team/agent_team_builder.py +184 -0
  18. autobyteus/agent_team/base_agent_team.py +86 -0
  19. autobyteus/agent_team/bootstrap_steps/__init__.py +24 -0
  20. autobyteus/agent_team/bootstrap_steps/agent_configuration_preparation_step.py +73 -0
  21. autobyteus/agent_team/bootstrap_steps/agent_team_bootstrapper.py +54 -0
  22. autobyteus/agent_team/bootstrap_steps/agent_team_runtime_queue_initialization_step.py +25 -0
  23. autobyteus/agent_team/bootstrap_steps/base_agent_team_bootstrap_step.py +23 -0
  24. autobyteus/agent_team/bootstrap_steps/coordinator_initialization_step.py +41 -0
  25. autobyteus/agent_team/bootstrap_steps/coordinator_prompt_preparation_step.py +85 -0
  26. autobyteus/agent_team/bootstrap_steps/task_notifier_initialization_step.py +51 -0
  27. autobyteus/agent_team/bootstrap_steps/team_context_initialization_step.py +45 -0
  28. autobyteus/agent_team/context/__init__.py +17 -0
  29. autobyteus/agent_team/context/agent_team_config.py +33 -0
  30. autobyteus/agent_team/context/agent_team_context.py +61 -0
  31. autobyteus/agent_team/context/agent_team_runtime_state.py +56 -0
  32. autobyteus/agent_team/context/team_manager.py +147 -0
  33. autobyteus/agent_team/context/team_node_config.py +76 -0
  34. autobyteus/agent_team/events/__init__.py +29 -0
  35. autobyteus/agent_team/events/agent_team_event_dispatcher.py +39 -0
  36. autobyteus/agent_team/events/agent_team_events.py +53 -0
  37. autobyteus/agent_team/events/agent_team_input_event_queue_manager.py +21 -0
  38. autobyteus/agent_team/exceptions.py +8 -0
  39. autobyteus/agent_team/factory/__init__.py +9 -0
  40. autobyteus/agent_team/factory/agent_team_factory.py +99 -0
  41. autobyteus/agent_team/handlers/__init__.py +19 -0
  42. autobyteus/agent_team/handlers/agent_team_event_handler_registry.py +23 -0
  43. autobyteus/agent_team/handlers/base_agent_team_event_handler.py +16 -0
  44. autobyteus/agent_team/handlers/inter_agent_message_request_event_handler.py +61 -0
  45. autobyteus/agent_team/handlers/lifecycle_agent_team_event_handler.py +27 -0
  46. autobyteus/agent_team/handlers/process_user_message_event_handler.py +46 -0
  47. autobyteus/agent_team/handlers/tool_approval_team_event_handler.py +48 -0
  48. autobyteus/agent_team/phases/__init__.py +11 -0
  49. autobyteus/agent_team/phases/agent_team_operational_phase.py +19 -0
  50. autobyteus/agent_team/phases/agent_team_phase_manager.py +48 -0
  51. autobyteus/agent_team/runtime/__init__.py +13 -0
  52. autobyteus/agent_team/runtime/agent_team_runtime.py +82 -0
  53. autobyteus/agent_team/runtime/agent_team_worker.py +117 -0
  54. autobyteus/agent_team/shutdown_steps/__init__.py +17 -0
  55. autobyteus/agent_team/shutdown_steps/agent_team_shutdown_orchestrator.py +35 -0
  56. autobyteus/agent_team/shutdown_steps/agent_team_shutdown_step.py +42 -0
  57. autobyteus/agent_team/shutdown_steps/base_agent_team_shutdown_step.py +16 -0
  58. autobyteus/agent_team/shutdown_steps/bridge_cleanup_step.py +28 -0
  59. autobyteus/agent_team/shutdown_steps/sub_team_shutdown_step.py +41 -0
  60. autobyteus/agent_team/streaming/__init__.py +26 -0
  61. autobyteus/agent_team/streaming/agent_event_bridge.py +48 -0
  62. autobyteus/agent_team/streaming/agent_event_multiplexer.py +70 -0
  63. autobyteus/agent_team/streaming/agent_team_event_notifier.py +64 -0
  64. autobyteus/agent_team/streaming/agent_team_event_stream.py +33 -0
  65. autobyteus/agent_team/streaming/agent_team_stream_event_payloads.py +32 -0
  66. autobyteus/agent_team/streaming/agent_team_stream_events.py +56 -0
  67. autobyteus/agent_team/streaming/team_event_bridge.py +50 -0
  68. autobyteus/agent_team/task_notification/__init__.py +11 -0
  69. autobyteus/agent_team/task_notification/system_event_driven_agent_task_notifier.py +164 -0
  70. autobyteus/agent_team/task_notification/task_notification_mode.py +24 -0
  71. autobyteus/agent_team/utils/__init__.py +9 -0
  72. autobyteus/agent_team/utils/wait_for_idle.py +46 -0
  73. autobyteus/cli/agent_team_tui/__init__.py +4 -0
  74. autobyteus/cli/agent_team_tui/app.py +210 -0
  75. autobyteus/cli/agent_team_tui/state.py +180 -0
  76. autobyteus/cli/agent_team_tui/widgets/__init__.py +6 -0
  77. autobyteus/cli/agent_team_tui/widgets/agent_list_sidebar.py +149 -0
  78. autobyteus/cli/agent_team_tui/widgets/focus_pane.py +320 -0
  79. autobyteus/cli/agent_team_tui/widgets/logo.py +20 -0
  80. autobyteus/cli/agent_team_tui/widgets/renderables.py +77 -0
  81. autobyteus/cli/agent_team_tui/widgets/shared.py +60 -0
  82. autobyteus/cli/agent_team_tui/widgets/status_bar.py +14 -0
  83. autobyteus/cli/agent_team_tui/widgets/task_board_panel.py +82 -0
  84. autobyteus/events/event_types.py +7 -2
  85. autobyteus/llm/api/autobyteus_llm.py +11 -12
  86. autobyteus/llm/api/lmstudio_llm.py +10 -13
  87. autobyteus/llm/api/ollama_llm.py +8 -13
  88. autobyteus/llm/autobyteus_provider.py +73 -46
  89. autobyteus/llm/llm_factory.py +102 -140
  90. autobyteus/llm/lmstudio_provider.py +63 -48
  91. autobyteus/llm/models.py +83 -53
  92. autobyteus/llm/ollama_provider.py +69 -61
  93. autobyteus/llm/ollama_provider_resolver.py +1 -0
  94. autobyteus/llm/providers.py +13 -13
  95. autobyteus/llm/runtimes.py +11 -0
  96. autobyteus/task_management/__init__.py +43 -0
  97. autobyteus/task_management/base_task_board.py +68 -0
  98. autobyteus/task_management/converters/__init__.py +11 -0
  99. autobyteus/task_management/converters/task_board_converter.py +64 -0
  100. autobyteus/task_management/converters/task_plan_converter.py +48 -0
  101. autobyteus/task_management/deliverable.py +16 -0
  102. autobyteus/task_management/deliverables/__init__.py +8 -0
  103. autobyteus/task_management/deliverables/file_deliverable.py +15 -0
  104. autobyteus/task_management/events.py +27 -0
  105. autobyteus/task_management/in_memory_task_board.py +126 -0
  106. autobyteus/task_management/schemas/__init__.py +15 -0
  107. autobyteus/task_management/schemas/deliverable_schema.py +13 -0
  108. autobyteus/task_management/schemas/plan_definition.py +35 -0
  109. autobyteus/task_management/schemas/task_status_report.py +27 -0
  110. autobyteus/task_management/task_plan.py +110 -0
  111. autobyteus/task_management/tools/__init__.py +14 -0
  112. autobyteus/task_management/tools/get_task_board_status.py +68 -0
  113. autobyteus/task_management/tools/publish_task_plan.py +113 -0
  114. autobyteus/task_management/tools/update_task_status.py +135 -0
  115. autobyteus/tools/bash/bash_executor.py +59 -14
  116. autobyteus/tools/mcp/config_service.py +63 -58
  117. autobyteus/tools/mcp/server/http_managed_mcp_server.py +14 -2
  118. autobyteus/tools/mcp/server/stdio_managed_mcp_server.py +14 -2
  119. autobyteus/tools/mcp/server_instance_manager.py +30 -4
  120. autobyteus/tools/mcp/tool_registrar.py +103 -50
  121. autobyteus/tools/parameter_schema.py +17 -11
  122. autobyteus/tools/registry/tool_definition.py +24 -29
  123. autobyteus/tools/tool_category.py +1 -0
  124. autobyteus/tools/usage/formatters/default_json_example_formatter.py +78 -3
  125. autobyteus/tools/usage/formatters/default_xml_example_formatter.py +23 -3
  126. autobyteus/tools/usage/formatters/gemini_json_example_formatter.py +6 -0
  127. autobyteus/tools/usage/formatters/google_json_example_formatter.py +7 -0
  128. autobyteus/tools/usage/formatters/openai_json_example_formatter.py +6 -4
  129. autobyteus/tools/usage/parsers/gemini_json_tool_usage_parser.py +23 -7
  130. autobyteus/tools/usage/parsers/provider_aware_tool_usage_parser.py +14 -25
  131. autobyteus/tools/usage/providers/__init__.py +2 -12
  132. autobyteus/tools/usage/providers/tool_manifest_provider.py +36 -29
  133. autobyteus/tools/usage/registries/__init__.py +7 -12
  134. autobyteus/tools/usage/registries/tool_formatter_pair.py +15 -0
  135. autobyteus/tools/usage/registries/tool_formatting_registry.py +58 -0
  136. autobyteus/tools/usage/registries/tool_usage_parser_registry.py +55 -0
  137. {autobyteus-1.1.4.dist-info → autobyteus-1.1.5.dist-info}/METADATA +3 -3
  138. {autobyteus-1.1.4.dist-info → autobyteus-1.1.5.dist-info}/RECORD +146 -72
  139. examples/agent_team/__init__.py +1 -0
  140. examples/run_browser_agent.py +17 -15
  141. examples/run_google_slides_agent.py +17 -16
  142. examples/run_poem_writer.py +22 -12
  143. examples/run_sqlite_agent.py +17 -15
  144. autobyteus/tools/mcp/call_handlers/__init__.py +0 -16
  145. autobyteus/tools/mcp/call_handlers/base_handler.py +0 -40
  146. autobyteus/tools/mcp/call_handlers/stdio_handler.py +0 -76
  147. autobyteus/tools/mcp/call_handlers/streamable_http_handler.py +0 -55
  148. autobyteus/tools/usage/providers/json_example_provider.py +0 -32
  149. autobyteus/tools/usage/providers/json_schema_provider.py +0 -35
  150. autobyteus/tools/usage/providers/json_tool_usage_parser_provider.py +0 -28
  151. autobyteus/tools/usage/providers/xml_example_provider.py +0 -28
  152. autobyteus/tools/usage/providers/xml_schema_provider.py +0 -29
  153. autobyteus/tools/usage/providers/xml_tool_usage_parser_provider.py +0 -26
  154. autobyteus/tools/usage/registries/json_example_formatter_registry.py +0 -51
  155. autobyteus/tools/usage/registries/json_schema_formatter_registry.py +0 -51
  156. autobyteus/tools/usage/registries/json_tool_usage_parser_registry.py +0 -42
  157. autobyteus/tools/usage/registries/xml_example_formatter_registry.py +0 -30
  158. autobyteus/tools/usage/registries/xml_schema_formatter_registry.py +0 -33
  159. autobyteus/tools/usage/registries/xml_tool_usage_parser_registry.py +0 -30
  160. examples/workflow/__init__.py +0 -1
  161. examples/workflow/run_basic_research_workflow.py +0 -189
  162. examples/workflow/run_code_review_workflow.py +0 -269
  163. examples/workflow/run_debate_workflow.py +0 -212
  164. examples/workflow/run_workflow_with_tui.py +0 -153
  165. {autobyteus-1.1.4.dist-info → autobyteus-1.1.5.dist-info}/WHEEL +0 -0
  166. {autobyteus-1.1.4.dist-info → autobyteus-1.1.5.dist-info}/licenses/LICENSE +0 -0
  167. {autobyteus-1.1.4.dist-info → autobyteus-1.1.5.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,184 @@
1
+ # file: autobyteus/autobyteus/agent_team/agent_team_builder.py
2
+ import logging
3
+ from typing import List, Optional, Dict, Union, Set
4
+
5
+ from autobyteus.agent_team.agent_team import AgentTeam
6
+ from autobyteus.agent_team.context.agent_team_config import AgentTeamConfig
7
+ from autobyteus.agent_team.context.team_node_config import TeamNodeConfig
8
+ from autobyteus.agent.context.agent_config import AgentConfig
9
+ from autobyteus.agent_team.factory.agent_team_factory import AgentTeamFactory
10
+ from autobyteus.agent_team.task_notification.task_notification_mode import TaskNotificationMode
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+ # Define a type hint for the possible definition types for clarity
15
+ NodeDefinition = Union[AgentConfig, AgentTeamConfig]
16
+
17
+ class AgentTeamBuilder:
18
+ """
19
+ A fluent API for constructing and configuring an AgentTeam.
20
+
21
+ This builder simplifies creating an agent team by abstracting away the manual
22
+ creation of config objects and providing an intuitive way to define the
23
+ agent and sub-team graph. It enforces that all nodes within the team have
24
+ a unique name.
25
+ """
26
+ def __init__(self, name: str, description: str, role: Optional[str] = None):
27
+ """
28
+ Initializes the AgentTeamBuilder.
29
+
30
+ Args:
31
+ name: A unique name for the agent team.
32
+ description: A high-level description of the team's goal.
33
+ role: An optional role description for when this team is used
34
+ as a sub-team within a parent.
35
+ """
36
+ if not name or not isinstance(name, str):
37
+ raise ValueError("Agent team name must be a non-empty string.")
38
+ if not description or not isinstance(description, str):
39
+ raise ValueError("Agent team description must be a non-empty string.")
40
+
41
+ self._name = name
42
+ self._description = description
43
+ self._role = role
44
+ self._nodes: Dict[NodeDefinition, List[NodeDefinition]] = {}
45
+ self._coordinator_config: Optional[AgentConfig] = None
46
+ self._added_node_names: Set[str] = set()
47
+ self._task_notification_mode: TaskNotificationMode = TaskNotificationMode.AGENT_MANUAL_NOTIFICATION
48
+ logger.info(f"AgentTeamBuilder initialized for team: '{self._name}'.")
49
+
50
+ def add_agent_node(self, agent_config: AgentConfig, dependencies: Optional[List[NodeDefinition]] = None) -> 'AgentTeamBuilder':
51
+ """
52
+ Adds a regular agent node to the agent team.
53
+
54
+ Args:
55
+ agent_config: The configuration for the agent at this node.
56
+ dependencies: A list of AgentConfig or AgentTeamConfig objects for nodes
57
+ that this node depends on. These must have been added previously.
58
+
59
+ Returns:
60
+ The builder instance for fluent chaining.
61
+ """
62
+ self._add_node_internal(agent_config, dependencies)
63
+ return self
64
+
65
+ def add_sub_team_node(self, team_config: AgentTeamConfig, dependencies: Optional[List[NodeDefinition]] = None) -> 'AgentTeamBuilder':
66
+ """
67
+ Adds a sub-team node to the agent team.
68
+
69
+ Args:
70
+ team_config: The configuration for the sub-team.
71
+ dependencies: A list of AgentConfig or AgentTeamConfig objects for nodes
72
+ that this node depends on. These must have been added previously.
73
+
74
+ Returns:
75
+ The builder instance for fluent chaining.
76
+ """
77
+ self._add_node_internal(team_config, dependencies)
78
+ return self
79
+
80
+ def _add_node_internal(self, node_definition: NodeDefinition, dependencies: Optional[List[NodeDefinition]]):
81
+ """Internal helper to add a node of any type."""
82
+ if not isinstance(node_definition, (AgentConfig, AgentTeamConfig)):
83
+ raise TypeError("node_definition must be an instance of AgentConfig or AgentTeamConfig.")
84
+
85
+ node_name = node_definition.name
86
+ if node_name in self._added_node_names:
87
+ # Enforce unique names. This is the new, simpler validation.
88
+ raise ValueError(f"Duplicate node name '{node_name}' detected. All nodes in a team must have a unique name.")
89
+
90
+ if node_definition in self._nodes or node_definition == self._coordinator_config:
91
+ raise ValueError(f"The exact same node definition object for '{node_name}' has already been added to the team.")
92
+
93
+ if dependencies:
94
+ for dep_config in dependencies:
95
+ if dep_config not in self._nodes and dep_config != self._coordinator_config:
96
+ raise ValueError(f"Dependency node '{dep_config.name}' must be added to the builder before being used as a dependency.")
97
+
98
+ self._nodes[node_definition] = dependencies or []
99
+ self._added_node_names.add(node_name)
100
+
101
+ node_type = "Sub-Team" if isinstance(node_definition, AgentTeamConfig) else "Agent"
102
+ logger.debug(f"Added {node_type} node '{node_name}' to builder with {len(dependencies or [])} dependencies.")
103
+
104
+ def set_coordinator(self, agent_config: AgentConfig) -> 'AgentTeamBuilder':
105
+ """
106
+ Sets the coordinator agent for the team. A coordinator must be an agent.
107
+
108
+ Args:
109
+ agent_config: The configuration for the coordinator agent.
110
+
111
+ Returns:
112
+ The builder instance for fluent chaining.
113
+ """
114
+ if self._coordinator_config is not None:
115
+ raise ValueError("A coordinator has already been set for this team.")
116
+
117
+ if not isinstance(agent_config, AgentConfig):
118
+ raise TypeError("Coordinator must be an instance of AgentConfig.")
119
+
120
+ node_name = agent_config.name
121
+ if node_name in self._added_node_names:
122
+ raise ValueError(f"Duplicate node name '{node_name}' detected. The coordinator's name must also be unique within the team.")
123
+
124
+ self._coordinator_config = agent_config
125
+ self._added_node_names.add(node_name)
126
+ logger.debug(f"Set coordinator for team to '{agent_config.name}'.")
127
+ return self
128
+
129
+ def set_task_notification_mode(self, mode: TaskNotificationMode) -> 'AgentTeamBuilder':
130
+ """
131
+ Sets the task notification mode for the team.
132
+
133
+ Args:
134
+ mode: The desired TaskNotificationMode (AGENT_MANUAL_NOTIFICATION or SYSTEM_EVENT_DRIVEN).
135
+
136
+ Returns:
137
+ The builder instance for fluent chaining.
138
+ """
139
+ if not isinstance(mode, TaskNotificationMode):
140
+ raise TypeError("mode must be an instance of TaskNotificationMode.")
141
+ self._task_notification_mode = mode
142
+ logger.debug(f"Task notification mode set to '{mode.value}'.")
143
+ return self
144
+
145
+ def build(self) -> AgentTeam:
146
+ """
147
+ Constructs and returns the final AgentTeam instance using the
148
+ singleton AgentTeamFactory.
149
+ """
150
+ logger.info("Building AgentTeam from builder...")
151
+ if self._coordinator_config is None:
152
+ raise ValueError("Cannot build team: A coordinator must be set.")
153
+
154
+ node_map: Dict[NodeDefinition, TeamNodeConfig] = {}
155
+ # Ensure the coordinator config is also in the set of definitions to process
156
+ all_definitions = list(self._nodes.keys())
157
+ if self._coordinator_config not in all_definitions:
158
+ all_definitions.append(self._coordinator_config)
159
+
160
+ for definition in all_definitions:
161
+ node_map[definition] = TeamNodeConfig(node_definition=definition)
162
+
163
+ for node_def, dep_defs in self._nodes.items():
164
+ if node_def in node_map and dep_defs:
165
+ current_node = node_map[node_def]
166
+ dependency_nodes = [node_map[dep_def] for dep_def in dep_defs]
167
+ current_node.dependencies = tuple(dependency_nodes)
168
+
169
+ final_nodes = list(node_map.values())
170
+ coordinator_node_instance = node_map[self._coordinator_config]
171
+
172
+ team_config = AgentTeamConfig(
173
+ name=self._name,
174
+ description=self._description,
175
+ role=self._role,
176
+ nodes=tuple(final_nodes),
177
+ coordinator_node=coordinator_node_instance,
178
+ task_notification_mode=self._task_notification_mode
179
+ )
180
+
181
+ logger.info(f"AgentTeamConfig created successfully. Name: '{team_config.name}'. Total nodes: {len(final_nodes)}. Coordinator: '{coordinator_node_instance.name}'.")
182
+
183
+ factory = AgentTeamFactory()
184
+ return factory.create_team(config=team_config)
@@ -0,0 +1,86 @@
1
+ # file: autobyteus/autobyteus/agent_team/base_agent_team.py
2
+ import logging
3
+ from abc import ABC, abstractmethod
4
+ from typing import Optional, Any, TYPE_CHECKING
5
+
6
+ # These are forward declarations that might be used by subclasses.
7
+ if TYPE_CHECKING:
8
+ from autobyteus.agent_team.agent_team import AgentTeam
9
+
10
+ logger = logging.getLogger(__name__)
11
+
12
+ class BaseAgentTeam(ABC):
13
+ """
14
+ Optional abstract base class for creating domain-specific, type-safe
15
+ APIs for agent teams.
16
+
17
+ Users can subclass BaseAgentTeam to create a more structured and
18
+ specific interface for their multi-agent tasks, rather than using the
19
+ generic `AgentTeam.process(**kwargs)` method directly.
20
+
21
+ Subclasses would typically encapsulate an `AgentTeam` instance and define
22
+ methods that map domain-specific inputs to the underlying team's execution.
23
+ """
24
+
25
+ def __init__(self,
26
+ name: str,
27
+ wrapped_team_instance: Optional['AgentTeam'] = None):
28
+ """
29
+ Initializes the BaseAgentTeam.
30
+
31
+ Args:
32
+ name: A descriptive name for this specific team implementation.
33
+ wrapped_team_instance: Optional. An instance of AgentTeam that this class
34
+ will wrap and delegate to. If not provided, the subclass
35
+ is responsible for initializing its own team instance.
36
+ """
37
+ self.name: str = name
38
+ self._wrapped_team: Optional[Any] = wrapped_team_instance
39
+
40
+ if self._wrapped_team:
41
+ logger.info(f"BaseAgentTeam '{self.name}' initialized, wrapping an instance of "
42
+ f"'{self._wrapped_team.__class__.__name__}'.")
43
+ else:
44
+ logger.info(f"BaseAgentTeam '{self.name}' initialized without a pre-wrapped instance. "
45
+ "Subclass should handle team setup.")
46
+
47
+ @property
48
+ def wrapped_team(self) -> Optional[Any]:
49
+ """Provides access to the wrapped AgentTeam instance."""
50
+ return self._wrapped_team
51
+
52
+ @abstractmethod
53
+ async def start(self) -> None:
54
+ """
55
+ Starts the team. Subclasses should implement this to delegate
56
+ to the start method of their wrapped AgentTeam.
57
+ """
58
+ pass
59
+
60
+ @abstractmethod
61
+ async def stop(self, timeout: float = 10.0) -> None:
62
+ """
63
+ Stops the team. Subclasses should implement this to delegate
64
+ to the stop method of their wrapped AgentTeam.
65
+ """
66
+ pass
67
+
68
+ @property
69
+ @abstractmethod
70
+ def is_running(self) -> bool:
71
+ """
72
+ Checks if the team is currently running. Subclasses should implement
73
+ this to delegate to the is_running property of their wrapped instance.
74
+ """
75
+ pass
76
+
77
+ def __repr__(self) -> str:
78
+ running_status = "N/A (not implemented by subclass)"
79
+ try:
80
+ running_status = str(self.is_running)
81
+ except NotImplementedError:
82
+ pass
83
+
84
+ return (f"<{self.__class__.__name__} name='{self.name}', "
85
+ f"wraps='{self._wrapped_team.__class__.__name__ if self._wrapped_team else 'NoneInternal'}', "
86
+ f"is_running={running_status}>")
@@ -0,0 +1,24 @@
1
+ # file: autobyteus/autobyteus/agent_team/bootstrap_steps/__init__.py
2
+ """
3
+ Defines individual, self-contained steps for the agent team bootstrapping process.
4
+ """
5
+
6
+ from autobyteus.agent_team.bootstrap_steps.base_agent_team_bootstrap_step import BaseAgentTeamBootstrapStep
7
+ from autobyteus.agent_team.bootstrap_steps.agent_team_runtime_queue_initialization_step import AgentTeamRuntimeQueueInitializationStep
8
+ from autobyteus.agent_team.bootstrap_steps.team_context_initialization_step import TeamContextInitializationStep
9
+ from autobyteus.agent_team.bootstrap_steps.task_notifier_initialization_step import TaskNotifierInitializationStep
10
+ from autobyteus.agent_team.bootstrap_steps.coordinator_prompt_preparation_step import CoordinatorPromptPreparationStep
11
+ from autobyteus.agent_team.bootstrap_steps.agent_configuration_preparation_step import AgentConfigurationPreparationStep
12
+ from autobyteus.agent_team.bootstrap_steps.coordinator_initialization_step import CoordinatorInitializationStep
13
+ from autobyteus.agent_team.bootstrap_steps.agent_team_bootstrapper import AgentTeamBootstrapper
14
+
15
+ __all__ = [
16
+ "BaseAgentTeamBootstrapStep",
17
+ "AgentTeamRuntimeQueueInitializationStep",
18
+ "TeamContextInitializationStep",
19
+ "TaskNotifierInitializationStep",
20
+ "CoordinatorPromptPreparationStep",
21
+ "AgentConfigurationPreparationStep",
22
+ "CoordinatorInitializationStep",
23
+ "AgentTeamBootstrapper",
24
+ ]
@@ -0,0 +1,73 @@
1
+ # file: autobyteus/autobyteus/agent_team/bootstrap_steps/agent_configuration_preparation_step.py
2
+ import logging
3
+ from typing import TYPE_CHECKING
4
+
5
+ from autobyteus.agent_team.bootstrap_steps.base_agent_team_bootstrap_step import BaseAgentTeamBootstrapStep
6
+ from autobyteus.agent.context import AgentConfig
7
+ from autobyteus.agent.message.send_message_to import SendMessageTo
8
+
9
+ if TYPE_CHECKING:
10
+ from autobyteus.agent_team.context.agent_team_context import AgentTeamContext
11
+ from autobyteus.agent_team.phases.agent_team_phase_manager import AgentTeamPhaseManager
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+ class AgentConfigurationPreparationStep(BaseAgentTeamBootstrapStep):
16
+ """
17
+ Bootstrap step to prepare the final, immutable configuration for every
18
+ agent in the team. It injects team-specific context and applies the final
19
+ coordinator prompt. It no longer injects tools.
20
+ """
21
+ async def execute(self, context: 'AgentTeamContext', phase_manager: 'AgentTeamPhaseManager') -> bool:
22
+ team_id = context.team_id
23
+ logger.info(f"Team '{team_id}': Executing AgentConfigurationPreparationStep to prepare all agent configurations.")
24
+
25
+ team_manager = context.team_manager
26
+ if not team_manager:
27
+ logger.error(f"Team '{team_id}': TeamManager not found in context during agent config preparation.")
28
+ return False
29
+
30
+ try:
31
+ coordinator_node_config = context.config.coordinator_node
32
+
33
+ for node_config_wrapper in context.config.nodes:
34
+ # This step only configures direct agent members, not sub-teams.
35
+ if node_config_wrapper.is_sub_team:
36
+ continue
37
+
38
+ unique_name = node_config_wrapper.name
39
+ node_definition = node_config_wrapper.node_definition
40
+
41
+ if not isinstance(node_definition, AgentConfig):
42
+ logger.warning(f"Team '{team_id}': Node '{unique_name}' has an unexpected definition type and will be skipped: {type(node_definition)}")
43
+ continue
44
+
45
+ final_config = node_definition.copy()
46
+
47
+ # --- Shared Context Injection ---
48
+ # The shared context is injected into the initial_custom_data dictionary,
49
+ # which is then used by the AgentFactory to create the AgentRuntimeState.
50
+ if final_config.initial_custom_data is None:
51
+ final_config.initial_custom_data = {}
52
+ final_config.initial_custom_data["team_context"] = context
53
+ logger.debug(f"Team '{team_id}': Injected shared team_context into initial_custom_data for agent '{unique_name}'.")
54
+
55
+ # --- Tool Injection Logic Removed ---
56
+ # The user is now fully responsible for defining all tools an agent needs
57
+ # in its AgentConfig. The framework no longer implicitly injects SendMessageTo.
58
+
59
+ # If this is the coordinator, apply the prompt that was prepared in the previous step.
60
+ if node_config_wrapper == coordinator_node_config:
61
+ coordinator_prompt = context.state.prepared_coordinator_prompt
62
+ if coordinator_prompt:
63
+ final_config.system_prompt = coordinator_prompt
64
+ logger.info(f"Team '{team_id}': Applied dynamic prompt to coordinator '{unique_name}'.")
65
+
66
+ # Store the final, ready-to-use config in the team's state
67
+ context.state.final_agent_configs[unique_name] = final_config
68
+ logger.info(f"Team '{team_id}': Prepared final config for agent '{unique_name}' with user-defined tools: {[t.get_name() for t in final_config.tools]}")
69
+
70
+ return True
71
+ except Exception as e:
72
+ logger.error(f"Team '{team_id}': Failed during agent configuration preparation: {e}", exc_info=True)
73
+ return False
@@ -0,0 +1,54 @@
1
+ # file: autobyteus/autobyteus/agent_team/bootstrap_steps/agent_team_bootstrapper.py
2
+ import logging
3
+ from typing import TYPE_CHECKING, List, Optional
4
+
5
+ from autobyteus.agent_team.bootstrap_steps.base_agent_team_bootstrap_step import BaseAgentTeamBootstrapStep
6
+ from autobyteus.agent_team.bootstrap_steps.agent_team_runtime_queue_initialization_step import AgentTeamRuntimeQueueInitializationStep
7
+ from autobyteus.agent_team.bootstrap_steps.team_context_initialization_step import TeamContextInitializationStep
8
+ from autobyteus.agent_team.bootstrap_steps.task_notifier_initialization_step import TaskNotifierInitializationStep
9
+ from autobyteus.agent_team.bootstrap_steps.coordinator_prompt_preparation_step import CoordinatorPromptPreparationStep
10
+ from autobyteus.agent_team.bootstrap_steps.agent_configuration_preparation_step import AgentConfigurationPreparationStep
11
+ from autobyteus.agent_team.bootstrap_steps.coordinator_initialization_step import CoordinatorInitializationStep
12
+ from autobyteus.agent_team.events.agent_team_events import AgentTeamReadyEvent
13
+
14
+ if TYPE_CHECKING:
15
+ from autobyteus.agent_team.context.agent_team_context import AgentTeamContext
16
+ from autobyteus.agent_team.phases.agent_team_phase_manager import AgentTeamPhaseManager
17
+
18
+ logger = logging.getLogger(__name__)
19
+
20
+ class AgentTeamBootstrapper:
21
+ """Orchestrates the agent team's bootstrapping process."""
22
+ def __init__(self, steps: Optional[List[BaseAgentTeamBootstrapStep]] = None):
23
+ self.bootstrap_steps = steps or [
24
+ AgentTeamRuntimeQueueInitializationStep(),
25
+ TeamContextInitializationStep(),
26
+ TaskNotifierInitializationStep(),
27
+ CoordinatorPromptPreparationStep(),
28
+ AgentConfigurationPreparationStep(),
29
+ CoordinatorInitializationStep(),
30
+ ]
31
+
32
+ async def run(self, context: 'AgentTeamContext', phase_manager: 'AgentTeamPhaseManager') -> bool:
33
+ team_id = context.team_id
34
+ await phase_manager.notify_bootstrapping_started()
35
+ logger.info(f"Team '{team_id}': Bootstrapper starting.")
36
+
37
+ for step in self.bootstrap_steps:
38
+ step_name = step.__class__.__name__
39
+ logger.debug(f"Team '{team_id}': Executing bootstrap step: {step_name}")
40
+ if not await step.execute(context, phase_manager):
41
+ error_message = f"Bootstrap step {step_name} failed."
42
+ logger.error(f"Team '{team_id}': {error_message}")
43
+ await phase_manager.notify_error_occurred(error_message, f"Failed during bootstrap step '{step_name}'.")
44
+ return False
45
+
46
+ logger.info(f"Team '{team_id}': All bootstrap steps completed successfully.")
47
+ if context.state.input_event_queues:
48
+ await context.state.input_event_queues.enqueue_internal_system_event(AgentTeamReadyEvent())
49
+ else:
50
+ logger.critical(f"Team '{team_id}': Bootstrap succeeded but queues not available.")
51
+ await phase_manager.notify_error_occurred("Queues unavailable after bootstrap.", "")
52
+ return False
53
+
54
+ return True
@@ -0,0 +1,25 @@
1
+ # file: autobyteus/autobyteus/agent_team/bootstrap_steps/agent_team_runtime_queue_initialization_step.py
2
+ import logging
3
+ from typing import TYPE_CHECKING
4
+
5
+ from autobyteus.agent_team.bootstrap_steps.base_agent_team_bootstrap_step import BaseAgentTeamBootstrapStep
6
+ from autobyteus.agent_team.events.agent_team_input_event_queue_manager import AgentTeamInputEventQueueManager
7
+
8
+ if TYPE_CHECKING:
9
+ from autobyteus.agent_team.context.agent_team_context import AgentTeamContext
10
+ from autobyteus.agent_team.phases.agent_team_phase_manager import AgentTeamPhaseManager
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+ class AgentTeamRuntimeQueueInitializationStep(BaseAgentTeamBootstrapStep):
15
+ """Bootstrap step for initializing the agent team's runtime event queues."""
16
+ async def execute(self, context: 'AgentTeamContext', phase_manager: 'AgentTeamPhaseManager') -> bool:
17
+ team_id = context.team_id
18
+ logger.info(f"Team '{team_id}': Executing AgentTeamRuntimeQueueInitializationStep.")
19
+ try:
20
+ context.state.input_event_queues = AgentTeamInputEventQueueManager()
21
+ logger.info(f"Team '{team_id}': AgentTeamInputEventQueueManager initialized.")
22
+ return True
23
+ except Exception as e:
24
+ logger.error(f"Team '{team_id}': Critical failure during queue initialization: {e}", exc_info=True)
25
+ return False
@@ -0,0 +1,23 @@
1
+ # file: autobyteus/autobyteus/agent_team/bootstrap_steps/base_agent_team_bootstrap_step.py
2
+ import logging
3
+ from abc import ABC, abstractmethod
4
+ from typing import TYPE_CHECKING
5
+
6
+ if TYPE_CHECKING:
7
+ from autobyteus.agent_team.context.agent_team_context import AgentTeamContext
8
+ from autobyteus.agent_team.phases.agent_team_phase_manager import AgentTeamPhaseManager
9
+
10
+ logger = logging.getLogger(__name__)
11
+
12
+ class BaseAgentTeamBootstrapStep(ABC):
13
+ """Abstract base class for individual steps in the agent team bootstrapping process."""
14
+
15
+ @abstractmethod
16
+ async def execute(self, context: 'AgentTeamContext', phase_manager: 'AgentTeamPhaseManager') -> bool:
17
+ """
18
+ Executes the bootstrap step.
19
+
20
+ Returns:
21
+ True if the step completed successfully, False otherwise.
22
+ """
23
+ raise NotImplementedError("Subclasses must implement the 'execute' method.")
@@ -0,0 +1,41 @@
1
+ # file: autobyteus/autobyteus/agent_team/bootstrap_steps/coordinator_initialization_step.py
2
+ import logging
3
+ from typing import TYPE_CHECKING
4
+
5
+ from autobyteus.agent_team.bootstrap_steps.base_agent_team_bootstrap_step import BaseAgentTeamBootstrapStep
6
+
7
+ if TYPE_CHECKING:
8
+ from autobyteus.agent_team.context.agent_team_context import AgentTeamContext
9
+ from autobyteus.agent_team.phases.agent_team_phase_manager import AgentTeamPhaseManager
10
+
11
+ logger = logging.getLogger(__name__)
12
+
13
+ class CoordinatorInitializationStep(BaseAgentTeamBootstrapStep):
14
+ """
15
+ Bootstrap step that eagerly instantiates and starts the coordinator agent
16
+ using the TeamManager. This ensures the coordinator is ready before the
17
+ agent team becomes idle.
18
+ """
19
+ async def execute(self, context: 'AgentTeamContext', phase_manager: 'AgentTeamPhaseManager') -> bool:
20
+ team_id = context.team_id
21
+ logger.info(f"Team '{team_id}': Executing CoordinatorInitializationStep.")
22
+
23
+ try:
24
+ team_manager = context.team_manager
25
+ if not team_manager:
26
+ raise RuntimeError("TeamManager not found in team context. It should be created by the factory.")
27
+
28
+ coordinator_name = context.config.coordinator_node.name
29
+
30
+ # This call now ensures the coordinator agent is fully created and ready.
31
+ coordinator = await team_manager.ensure_coordinator_is_ready(coordinator_name)
32
+
33
+ if not coordinator:
34
+ raise RuntimeError(f"TeamManager failed to return a ready coordinator agent for '{coordinator_name}'.")
35
+
36
+ logger.info(f"Team '{team_id}': Coordinator '{coordinator_name}' initialized and started via TeamManager.")
37
+ return True
38
+
39
+ except Exception as e:
40
+ logger.error(f"Team '{team_id}': Failed to initialize coordinator agent: {e}", exc_info=True)
41
+ return False
@@ -0,0 +1,85 @@
1
+ # file: autobyteus/autobyteus/agent_team/bootstrap_steps/coordinator_prompt_preparation_step.py
2
+ import logging
3
+ from typing import TYPE_CHECKING, List
4
+
5
+ from autobyteus.agent_team.bootstrap_steps.base_agent_team_bootstrap_step import BaseAgentTeamBootstrapStep
6
+ from autobyteus.agent.context import AgentConfig
7
+ from autobyteus.agent_team.context import AgentTeamConfig
8
+
9
+ if TYPE_CHECKING:
10
+ from autobyteus.agent_team.context.agent_team_context import AgentTeamContext
11
+ from autobyteus.agent_team.phases.agent_team_phase_manager import AgentTeamPhaseManager
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+ class CoordinatorPromptPreparationStep(BaseAgentTeamBootstrapStep):
16
+ """
17
+ Bootstrap step to finalize the coordinator's system prompt by injecting a
18
+ dynamically generated team manifest into a user-defined prompt template.
19
+ The user is expected to provide a `system_prompt` in the coordinator's
20
+ AgentConfig with a `{{team}}` placeholder.
21
+ """
22
+ async def execute(self, context: 'AgentTeamContext', phase_manager: 'AgentTeamPhaseManager') -> bool:
23
+ team_id = context.team_id
24
+ logger.info(f"Team '{team_id}': Executing CoordinatorPromptPreparationStep.")
25
+ try:
26
+ coordinator_node_config_wrapper = context.config.coordinator_node
27
+
28
+ # The coordinator must be an agent with a defined config.
29
+ if not isinstance(coordinator_node_config_wrapper.node_definition, AgentConfig):
30
+ logger.error(f"Team '{team_id}': Coordinator node '{coordinator_node_config_wrapper.name}' is not defined by an AgentConfig. Cannot prepare prompt.")
31
+ return False
32
+
33
+ coordinator_agent_config: AgentConfig = coordinator_node_config_wrapper.node_definition
34
+
35
+ # Start with the user's provided prompt template.
36
+ prompt_template = coordinator_agent_config.system_prompt
37
+ if not prompt_template:
38
+ logger.warning(f"Team '{team_id}': Coordinator '{coordinator_agent_config.name}' has no system_prompt defined. No prompt will be applied.")
39
+ context.state.prepared_coordinator_prompt = ""
40
+ return True
41
+
42
+ team_manifest = self._generate_team_manifest(context)
43
+
44
+ # Inject the manifest into the template.
45
+ if "{{team}}" in prompt_template:
46
+ final_prompt = prompt_template.replace("{{team}}", team_manifest)
47
+ logger.debug(f"Team '{team_id}': Injected team manifest into coordinator's system prompt.")
48
+ else:
49
+ final_prompt = prompt_template
50
+ logger.warning(f"Team '{team_id}': The coordinator's system prompt does not contain a '{{team}}' placeholder. The team manifest will not be injected.")
51
+
52
+ # Store the finalized prompt in the state for the AgentToolInjectionStep to use.
53
+ context.state.prepared_coordinator_prompt = final_prompt
54
+
55
+ logger.info(f"Team '{team_id}': Coordinator prompt prepared successfully and stored in state.")
56
+ return True
57
+ except Exception as e:
58
+ logger.error(f"Team '{team_id}': Failed to prepare coordinator prompt: {e}", exc_info=True)
59
+ return False
60
+
61
+ def _generate_team_manifest(self, context: 'AgentTeamContext') -> str:
62
+ """Generates a string manifest of all non-coordinator team members."""
63
+ prompt_parts: List[str] = []
64
+ coordinator_node = context.config.coordinator_node
65
+ member_nodes = {node for node in context.config.nodes if node != coordinator_node}
66
+
67
+ if not member_nodes:
68
+ return "You are working alone. You have no team members to delegate to."
69
+
70
+ # Sort for deterministic prompt generation
71
+ for node in sorted(list(member_nodes), key=lambda n: n.name):
72
+ node_def = node.node_definition
73
+ description = "No description available."
74
+
75
+ # --- THE FIX ---
76
+ # Use the 'description' for an AgentConfig and the 'role' for an AgentTeamConfig (sub-team).
77
+ if isinstance(node_def, AgentConfig):
78
+ description = node_def.description
79
+ elif isinstance(node_def, AgentTeamConfig):
80
+ # A sub-team's role is its most concise and relevant description for a parent coordinator.
81
+ description = node_def.role or node_def.description
82
+
83
+ prompt_parts.append(f"- name: {node.name}\n description: {description}")
84
+
85
+ return "\n".join(prompt_parts)
@@ -0,0 +1,51 @@
1
+ # file: autobyteus/autobyteus/agent_team/bootstrap_steps/task_notifier_initialization_step.py
2
+ import logging
3
+ from typing import TYPE_CHECKING
4
+
5
+ from autobyteus.agent_team.bootstrap_steps.base_agent_team_bootstrap_step import BaseAgentTeamBootstrapStep
6
+ from autobyteus.agent_team.task_notification.task_notification_mode import TaskNotificationMode
7
+ from autobyteus.agent_team.task_notification.system_event_driven_agent_task_notifier import SystemEventDrivenAgentTaskNotifier
8
+
9
+ if TYPE_CHECKING:
10
+ from autobyteus.agent_team.context.agent_team_context import AgentTeamContext
11
+ from autobyteus.agent_team.phases.agent_team_phase_manager import AgentTeamPhaseManager
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+ class TaskNotifierInitializationStep(BaseAgentTeamBootstrapStep):
16
+ """
17
+ Bootstrap step to initialize the SystemEventDrivenAgentTaskNotifier if the
18
+ team is configured for event-driven notifications.
19
+ """
20
+ async def execute(self, context: 'AgentTeamContext', phase_manager: 'AgentTeamPhaseManager') -> bool:
21
+ team_id = context.team_id
22
+ logger.info(f"Team '{team_id}': Executing TaskNotifierInitializationStep.")
23
+
24
+ if context.config.task_notification_mode != TaskNotificationMode.SYSTEM_EVENT_DRIVEN:
25
+ logger.info(f"Team '{team_id}': Task notification mode is '{context.config.task_notification_mode.value}'. Skipping event-driven notifier setup.")
26
+ return True
27
+
28
+ logger.info(f"Team '{team_id}': Mode is SYSTEM_EVENT_DRIVEN. Initializing and activating task notifier.")
29
+ try:
30
+ task_board = context.state.task_board
31
+ if not task_board:
32
+ logger.error(f"Team '{team_id}': TaskBoard not found. Cannot initialize task notifier. This step should run after TeamContextInitializationStep.")
33
+ return False
34
+
35
+ team_manager = context.team_manager
36
+ if not team_manager:
37
+ logger.error(f"Team '{team_id}': TeamManager not found. Cannot initialize task notifier.")
38
+ return False
39
+
40
+ notifier = SystemEventDrivenAgentTaskNotifier(
41
+ task_board=task_board,
42
+ team_manager=team_manager
43
+ )
44
+ notifier.start_monitoring()
45
+
46
+ context.state.task_notifier = notifier
47
+ logger.info(f"Team '{team_id}': SystemEventDrivenAgentTaskNotifier initialized and monitoring started.")
48
+ return True
49
+ except Exception as e:
50
+ logger.error(f"Team '{team_id}': Critical failure during task notifier initialization: {e}", exc_info=True)
51
+ return False