Skip to content

Commit 4e3c44b

Browse files
committed
introduce multiagent events and persistence hooks
1 parent a5b8d92 commit 4e3c44b

File tree

6 files changed

+76
-393
lines changed

6 files changed

+76
-393
lines changed

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

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,19 @@
55
"""
66

77
from .multiagent_events import (
8-
AfterGraphInvocationEvent,
8+
AfterMultiAgentInvocationEvent,
99
AfterNodeInvocationEvent,
10-
BeforeGraphInvocationEvent,
10+
BeforeMultiAgentInvocationEvent,
1111
BeforeNodeInvocationEvent,
1212
MultiAgentInitializationEvent,
1313
)
14-
from .multiagent_state import MultiAgentState, MultiAgentType
15-
from .multiagent_state_adapter import MultiAgentAdapter
14+
from .persistence_hooks import PersistentHook
1615

1716
__all__ = [
18-
"BeforeGraphInvocationEvent",
19-
"AfterGraphInvocationEvent",
17+
"BeforeMultiAgentInvocationEvent",
18+
"AfterMultiAgentInvocationEvent",
2019
"MultiAgentInitializationEvent",
2120
"BeforeNodeInvocationEvent",
2221
"AfterNodeInvocationEvent",
23-
"MultiAgentState",
24-
"MultiAgentAdapter",
25-
"MultiAgentType",
22+
"PersistentHook"
2623
]
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: 17 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -11,33 +11,20 @@
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
2825

2926

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)
38-
39-
40-
class MultiAgentHook(HookProvider):
27+
class PersistentHook(HookProvider):
4128
"""Hook provider for automatic multi-agent session persistence.
4229
4330
This hook automatically persists multi-agent orchestrator state at key
@@ -48,15 +35,14 @@ class MultiAgentHook(HookProvider):
4835
session_id: Unique identifier for the session
4936
"""
5037

51-
def __init__(self, session_manager: SessionManager, session_id: str):
38+
def __init__(self, session_manager: SessionManager):
5239
"""Initialize the multi-agent persistence hook.
5340
5441
Args:
5542
session_manager: SessionManager instance for state persistence
5643
session_id: Unique identifier for the session
5744
"""
5845
self._session_manager = session_manager
59-
self._session_id = session_id
6046
self._lock = threading.RLock()
6147

6248
def register_hooks(self, registry: HookRegistry, **kwargs: object) -> None:
@@ -67,17 +53,18 @@ def register_hooks(self, registry: HookRegistry, **kwargs: object) -> None:
6753
**kwargs: Additional keyword arguments (unused)
6854
"""
6955
registry.add_callback(MultiAgentInitializationEvent, self._on_initialization)
70-
registry.add_callback(BeforeGraphInvocationEvent, self._on_before_graph)
56+
registry.add_callback(BeforeMultiAgentInvocationEvent, self._on_initialization)
7157
registry.add_callback(BeforeNodeInvocationEvent, self._on_before_node)
7258
registry.add_callback(AfterNodeInvocationEvent, self._on_after_node)
73-
registry.add_callback(AfterGraphInvocationEvent, self._on_after_graph)
59+
registry.add_callback(AfterMultiAgentInvocationEvent, self._on_after_Execution)
7460

7561
def _on_initialization(self, event: MultiAgentInitializationEvent):
7662
"""Persist state when multi-agent orchestrator initializes."""
77-
self._persist(_get_multiagent_state(event.state, event.orchestrator))
63+
self._persist(event.orchestrator)
64+
pass
7865

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

8370
def _on_before_node(self, event: BeforeNodeInvocationEvent):
@@ -86,21 +73,20 @@ def _on_before_node(self, event: BeforeNodeInvocationEvent):
8673

8774
def _on_after_node(self, event: AfterNodeInvocationEvent):
8875
"""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)
76+
self._persist(event.orchestrator)
9177

92-
def _on_after_graph(self, event: AfterGraphInvocationEvent):
78+
def _on_after_Execution(self, event: AfterMultiAgentInvocationEvent):
9379
"""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)
80+
self._persist(event.orchestrator)
9681

97-
def _persist(self, multiagent_state: MultiAgentState) -> None:
82+
def _persist(self, orchestrator: MultiAgentBase) -> None:
9883
"""Persist the provided MultiAgentState using the configured SessionManager.
9984
10085
This method is synchronized across threads/tasks to avoid write races.
10186
10287
Args:
103-
multiagent_state: State to persist
88+
orchestrator: State to persist
10489
"""
90+
current_state = orchestrator.get_state_from_orchestrator()
10591
with self._lock:
106-
self._session_manager.write_multi_agent_state(multiagent_state)
92+
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)