Skip to content

Commit 41d2f44

Browse files
committed
feat: multiagent session interface
1 parent 54bc162 commit 41d2f44

File tree

5 files changed

+518
-0
lines changed

5 files changed

+518
-0
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from .multiagent_events import (
2+
AfterGraphInvocationEvent,
3+
AfterNodeInvocationEvent,
4+
BeforeGraphInvocationEvent,
5+
BeforeNodeInvocationEvent,
6+
MultiAgentInitializationEvent,
7+
)
8+
from .multiagent_state import MultiAgentState, MultiAgentType
9+
from .multiagent_state_adapter import MultiAgentAdapter
10+
11+
__all__ = [
12+
"BeforeGraphInvocationEvent",
13+
"AfterGraphInvocationEvent",
14+
"MultiAgentInitializationEvent",
15+
"BeforeNodeInvocationEvent",
16+
"AfterNodeInvocationEvent",
17+
"MultiAgentState",
18+
"MultiAgentAdapter",
19+
"MultiAgentType",
20+
]
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
"""Multi-agent execution lifecycle events for hook system integration.
2+
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
11+
"""
12+
13+
from dataclasses import dataclass
14+
from typing import TYPE_CHECKING
15+
16+
from ...hooks.registry import HookEvent
17+
from .multiagent_state import MultiAgentState
18+
19+
if TYPE_CHECKING:
20+
from ...multiagent.base import MultiAgentBase
21+
22+
23+
@dataclass
24+
class MultiAgentInitializationEvent(HookEvent):
25+
"""Event triggered when multi-agent orchestrator initializes.
26+
27+
Attributes:
28+
orchestrator: The multi-agent orchestrator instance
29+
state: Current state of the orchestrator
30+
"""
31+
orchestrator: "MultiAgentBase"
32+
state: MultiAgentState
33+
34+
35+
@dataclass
36+
class BeforeGraphInvocationEvent(HookEvent):
37+
"""Event triggered before orchestrator execution begins.
38+
39+
Attributes:
40+
orchestrator: The multi-agent orchestrator instance
41+
state: Current state before execution starts
42+
"""
43+
orchestrator: "MultiAgentBase"
44+
state: MultiAgentState
45+
46+
47+
@dataclass
48+
class BeforeNodeInvocationEvent(HookEvent):
49+
"""Event triggered before individual node execution.
50+
51+
Attributes:
52+
orchestrator: The multi-agent orchestrator instance
53+
next_node_to_execute: ID of the node about to be executed
54+
"""
55+
orchestrator: "MultiAgentBase"
56+
next_node_to_execute: str
57+
58+
59+
@dataclass
60+
class AfterNodeInvocationEvent(HookEvent):
61+
"""Event triggered after individual node execution completes.
62+
63+
Attributes:
64+
orchestrator: The multi-agent orchestrator instance
65+
executed_node: ID of the node that just completed execution
66+
state: Updated state after node execution
67+
"""
68+
orchestrator: "MultiAgentBase"
69+
executed_node: str
70+
state: MultiAgentState
71+
72+
73+
@dataclass
74+
class AfterGraphInvocationEvent(HookEvent):
75+
"""Event triggered after orchestrator execution completes.
76+
77+
Attributes:
78+
orchestrator: The multi-agent orchestrator instance
79+
state: Final state after execution completes
80+
"""
81+
orchestrator: "MultiAgentBase"
82+
state: MultiAgentState
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
"""Multi-agent state data structures for session persistence.
2+
3+
This module defines the core data structures used to represent the state
4+
of multi-agent orchestrators in a serializable format for session persistence.
5+
6+
Key Components:
7+
- MultiAgentType: Enum for orchestrator types (Graph/Swarm)
8+
- MultiAgentState: Serializable state container with conversion methods
9+
"""
10+
11+
from dataclasses import dataclass, field
12+
from enum import Enum
13+
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Set
14+
15+
from ...types.content import ContentBlock
16+
17+
if TYPE_CHECKING:
18+
from ...multiagent.base import Status
19+
20+
21+
# TODO: Move to Base after experimental
22+
class MultiAgentType(Enum):
23+
"""Enumeration of supported multi-agent orchestrator types.
24+
25+
Attributes:
26+
SWARM: Collaborative agent swarm orchestrator
27+
GRAPH: Directed graph-based agent orchestrator
28+
"""
29+
SWARM = "swarm"
30+
GRAPH = "graph"
31+
32+
33+
@dataclass
34+
class MultiAgentState:
35+
"""Serializable state container for multi-agent orchestrators.
36+
37+
This class represents the complete execution state of a multi-agent
38+
orchestrator (Graph or Swarm) in a format suitable for persistence
39+
and restoration across sessions.
40+
41+
Attributes:
42+
completed_nodes: Set of node IDs that have completed execution
43+
node_results: Dictionary mapping node IDs to their execution results
44+
status: Current execution status of the orchestrator
45+
next_node_to_execute: List of node IDs ready for execution
46+
current_task: The original task being executed
47+
execution_order: Ordered list of executed node IDs
48+
error_message: Optional error message if execution failed
49+
type: Type of orchestrator (Graph or Swarm)
50+
context: Additional context data (primarily for Swarm)
51+
"""
52+
# Mutual
53+
completed_nodes: Set[str] = field(default_factory=set)
54+
node_results: Dict[str, Any] = field(default_factory=dict)
55+
status: "Status" = "pending"
56+
next_node_to_execute: Optional[List[str]] = None
57+
current_task: Optional[str | List[ContentBlock]] = None
58+
execution_order: list[str] = field(default_factory=list)
59+
error_message: Optional[str] = None
60+
type: Optional[MultiAgentType] = field(default=MultiAgentType.GRAPH)
61+
# Swarm
62+
context: Optional[dict] = field(default_factory=dict)
63+
64+
def to_dict(self) -> dict[str, Any]:
65+
"""Convert MultiAgentState to JSON-serializable dictionary.
66+
67+
Returns:
68+
Dictionary representation suitable for JSON serialization
69+
"""
70+
def _serialize(v: Any) -> Any:
71+
if isinstance(v, (str, int, float, bool)) or v is None:
72+
return v
73+
if isinstance(v, set):
74+
return list(v)
75+
if isinstance(v, dict):
76+
return {str(k): _serialize(val) for k, val in v.items()}
77+
if isinstance(v, (list, tuple)):
78+
return [_serialize(x) for x in v]
79+
if hasattr(v, "to_dict"):
80+
return v.to_dict()
81+
# last resort: stringize anything non-serializable (locks, objects, etc.)
82+
return str(v)
83+
84+
return {
85+
"status": self.status,
86+
"completed_nodes": list(self.completed_nodes),
87+
"next_node_to_execute": list(self.next_node_to_execute) if self.next_node_to_execute else [],
88+
"node_results": _serialize(self.node_results),
89+
"current_task": self.current_task,
90+
"error_message": self.error_message,
91+
"execution_order": self.execution_order,
92+
"type": self.type,
93+
"context": _serialize(self.context),
94+
}
95+
96+
@classmethod
97+
def from_dict(cls, data: dict):
98+
"""Create MultiAgentState from dictionary data.
99+
100+
Args:
101+
data: Dictionary containing state data
102+
103+
Returns:
104+
MultiAgentState instance
105+
"""
106+
data["completed_nodes"] = set(data.get("completed_nodes", []))
107+
return cls(**data)

0 commit comments

Comments
 (0)