Skip to content

Commit c9a0034

Browse files
committed
introduce multiagent events and persistence hooks
1 parent 64a2ecb commit c9a0034

File tree

15 files changed

+848
-541
lines changed

15 files changed

+848
-541
lines changed

src/strands/experimental/multiagent_session/__init__.py renamed to src/strands/experimental/multiagent_hooks/__init__.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,20 @@
44
enabling resumable execution after interruptions or failures.
55
"""
66

7+
from personal.saved.multiagent_state import MultiAgentState, MultiAgentType
8+
from personal.saved.multiagent_state_adapter import MultiAgentAdapter
9+
710
from .multiagent_events import (
8-
AfterGraphInvocationEvent,
11+
AfterMultiAgentInvocationEvent,
912
AfterNodeInvocationEvent,
10-
BeforeGraphInvocationEvent,
13+
BeforeMultiAgentInvocationEvent,
1114
BeforeNodeInvocationEvent,
1215
MultiAgentInitializationEvent,
1316
)
14-
from .multiagent_state import MultiAgentState, MultiAgentType
15-
from .multiagent_state_adapter import MultiAgentAdapter
1617

1718
__all__ = [
18-
"BeforeGraphInvocationEvent",
19-
"AfterGraphInvocationEvent",
19+
"BeforeMultiAgentInvocationEvent",
20+
"AfterMultiAgentInvocationEvent",
2021
"MultiAgentInitializationEvent",
2122
"BeforeNodeInvocationEvent",
2223
"AfterNodeInvocationEvent",
Original file line numberDiff line numberDiff line change
@@ -1,87 +1,82 @@
11
"""Multi-agent execution lifecycle events for hook system integration.
22
3-
This module defines event classes that are triggered at key points during
4-
multi-agent orchestrator execution, enabling hooks to respond to lifecycle
5-
events for purposes like persistence, monitoring, and debugging.
6-
7-
Event Types:
8-
- Initialization: When orchestrator starts up
9-
- Before/After Graph: Start/end of overall execution
10-
- Before/After Node: Start/end of individual node execution
3+
These events are fired by orchestrators (Graph/Swarm) at key points so
4+
hooks can persist, monitor, or debug execution. No intermediate state model
5+
is used—hooks read from the orchestrator directly.
116
"""
127

138
from dataclasses import dataclass
14-
from typing import TYPE_CHECKING
9+
from typing import TYPE_CHECKING, Any
1510

16-
from ...hooks.registry import HookEvent
17-
from .multiagent_state import MultiAgentState
11+
from ...hooks.registry import HookEventBase
1812

1913
if TYPE_CHECKING:
2014
from ...multiagent.base import MultiAgentBase
2115

2216

2317
@dataclass
24-
class MultiAgentInitializationEvent(HookEvent):
18+
class MultiAgentInitializationEvent(HookEventBase):
2519
"""Event triggered when multi-agent orchestrator initializes.
2620
2721
Attributes:
2822
orchestrator: The multi-agent orchestrator instance
29-
state: Current state of the orchestrator
23+
invocation_state: Configuration that user pass in
3024
"""
3125

3226
orchestrator: "MultiAgentBase"
33-
state: MultiAgentState
27+
invocation_state: dict[str, Any]
3428

3529

3630
@dataclass
37-
class BeforeGraphInvocationEvent(HookEvent):
31+
class BeforeMultiAgentInvocationEvent(HookEventBase):
3832
"""Event triggered before orchestrator execution begins.
3933
4034
Attributes:
4135
orchestrator: The multi-agent orchestrator instance
42-
state: Current state before execution starts
36+
invocation_state: Configuration that user pass in
4337
"""
4438

4539
orchestrator: "MultiAgentBase"
46-
state: MultiAgentState
40+
invocation_state: dict[str, Any]
4741

4842

4943
@dataclass
50-
class BeforeNodeInvocationEvent(HookEvent):
44+
class BeforeNodeInvocationEvent(HookEventBase):
5145
"""Event triggered before individual node execution.
5246
5347
Attributes:
5448
orchestrator: The multi-agent orchestrator instance
55-
next_node_to_execute: ID of the node about to be executed
49+
invocation_state: Configuration that user pass in
5650
"""
5751

5852
orchestrator: "MultiAgentBase"
5953
next_node_to_execute: str
54+
invocation_state: dict[str, Any]
6055

6156

6257
@dataclass
63-
class AfterNodeInvocationEvent(HookEvent):
58+
class AfterNodeInvocationEvent(HookEventBase):
6459
"""Event triggered after individual node execution completes.
6560
6661
Attributes:
6762
orchestrator: The multi-agent orchestrator instance
6863
executed_node: ID of the node that just completed execution
69-
state: Updated state after node execution
64+
invocation_state: Configuration that user pass in
7065
"""
7166

7267
orchestrator: "MultiAgentBase"
7368
executed_node: str
74-
state: MultiAgentState
69+
invocation_state: dict[str, Any]
7570

7671

7772
@dataclass
78-
class AfterGraphInvocationEvent(HookEvent):
73+
class AfterMultiAgentInvocationEvent(HookEventBase):
7974
"""Event triggered after orchestrator execution completes.
8075
8176
Attributes:
8277
orchestrator: The multi-agent orchestrator instance
83-
state: Final state after execution completes
78+
invocation_state: Configuration that user pass in
8479
"""
8580

8681
orchestrator: "MultiAgentBase"
87-
state: MultiAgentState
82+
invocation_state: dict[str, Any]

src/strands/experimental/multiagent_session/persistence_hooks.py renamed to src/strands/experimental/multiagent_hooks/persistence_hooks.py

Lines changed: 15 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -11,30 +11,17 @@
1111
"""
1212

1313
import threading
14-
from typing import Optional
1514

1615
from ...hooks.registry import HookProvider, HookRegistry
1716
from ...multiagent.base import MultiAgentBase
1817
from ...session import SessionManager
1918
from .multiagent_events import (
20-
AfterGraphInvocationEvent,
19+
AfterMultiAgentInvocationEvent,
2120
AfterNodeInvocationEvent,
22-
BeforeGraphInvocationEvent,
21+
BeforeMultiAgentInvocationEvent,
2322
BeforeNodeInvocationEvent,
2423
MultiAgentInitializationEvent,
25-
MultiAgentState,
2624
)
27-
from .multiagent_state_adapter import MultiAgentAdapter
28-
29-
30-
def _get_multiagent_state(
31-
multiagent_state: Optional[MultiAgentState],
32-
orchestrator: MultiAgentBase,
33-
) -> MultiAgentState:
34-
if multiagent_state is not None:
35-
return multiagent_state
36-
37-
return MultiAgentAdapter.create_multi_agent_state(orchestrator=orchestrator)
3825

3926

4027
class MultiAgentHook(HookProvider):
@@ -67,17 +54,18 @@ def register_hooks(self, registry: HookRegistry, **kwargs: object) -> None:
6754
**kwargs: Additional keyword arguments (unused)
6855
"""
6956
registry.add_callback(MultiAgentInitializationEvent, self._on_initialization)
70-
registry.add_callback(BeforeGraphInvocationEvent, self._on_before_graph)
57+
registry.add_callback(BeforeMultiAgentInvocationEvent, self._on_initialization)
7158
registry.add_callback(BeforeNodeInvocationEvent, self._on_before_node)
7259
registry.add_callback(AfterNodeInvocationEvent, self._on_after_node)
73-
registry.add_callback(AfterGraphInvocationEvent, self._on_after_graph)
60+
registry.add_callback(AfterMultiAgentInvocationEvent, self._on_after_Execution)
7461

7562
def _on_initialization(self, event: MultiAgentInitializationEvent):
7663
"""Persist state when multi-agent orchestrator initializes."""
77-
self._persist(_get_multiagent_state(event.state, event.orchestrator))
64+
self._persist(event.orchestrator)
65+
pass
7866

79-
def _on_before_graph(self, event: BeforeGraphInvocationEvent):
80-
"""Hook called before graph execution starts."""
67+
def _on_before_Invocation(self, event: MultiAgentInitializationEvent):
68+
"""Persist state when multi-agent orchestrator initializes."""
8169
pass
8270

8371
def _on_before_node(self, event: BeforeNodeInvocationEvent):
@@ -86,21 +74,20 @@ def _on_before_node(self, event: BeforeNodeInvocationEvent):
8674

8775
def _on_after_node(self, event: AfterNodeInvocationEvent):
8876
"""Persist state after each node completes execution."""
89-
multi_agent_state = _get_multiagent_state(multiagent_state=event.state, orchestrator=event.orchestrator)
90-
self._persist(multi_agent_state)
77+
self._persist(event.orchestrator)
9178

92-
def _on_after_graph(self, event: AfterGraphInvocationEvent):
79+
def _on_after_Execution(self, event: AfterMultiAgentInvocationEvent):
9380
"""Persist final state after graph execution completes."""
94-
multiagent_state = _get_multiagent_state(multiagent_state=event.state, orchestrator=event.orchestrator)
95-
self._persist(multiagent_state)
81+
self._persist(event.orchestrator)
9682

97-
def _persist(self, multiagent_state: MultiAgentState) -> None:
83+
def _persist(self, orchestrator: MultiAgentBase) -> None:
9884
"""Persist the provided MultiAgentState using the configured SessionManager.
9985
10086
This method is synchronized across threads/tasks to avoid write races.
10187
10288
Args:
103-
multiagent_state: State to persist
89+
orchestrator: State to persist
10490
"""
91+
current_state = orchestrator.get_state_from_orchestrator()
10592
with self._lock:
106-
self._session_manager.write_multi_agent_state(multiagent_state)
93+
self._session_manager.write_multi_agent_state(current_state)

src/strands/experimental/multiagent_session/multiagent_state.py

Lines changed: 0 additions & 110 deletions
This file was deleted.

0 commit comments

Comments
 (0)