massgen 0.1.4__py3-none-any.whl → 0.1.6__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 massgen might be problematic. Click here for more details.
- massgen/__init__.py +1 -1
- massgen/backend/base_with_custom_tool_and_mcp.py +453 -23
- massgen/backend/capabilities.py +39 -0
- massgen/backend/chat_completions.py +111 -197
- massgen/backend/claude.py +210 -181
- massgen/backend/gemini.py +1015 -1559
- massgen/backend/grok.py +3 -2
- massgen/backend/response.py +160 -220
- massgen/chat_agent.py +340 -20
- massgen/cli.py +399 -25
- massgen/config_builder.py +20 -54
- massgen/config_validator.py +931 -0
- massgen/configs/README.md +95 -10
- massgen/configs/memory/gpt5mini_gemini_baseline_research_to_implementation.yaml +94 -0
- massgen/configs/memory/gpt5mini_gemini_context_window_management.yaml +187 -0
- massgen/configs/memory/gpt5mini_gemini_research_to_implementation.yaml +127 -0
- massgen/configs/memory/gpt5mini_high_reasoning_gemini.yaml +107 -0
- massgen/configs/memory/single_agent_compression_test.yaml +64 -0
- massgen/configs/tools/custom_tools/claude_code_custom_tool_with_mcp_example.yaml +1 -0
- massgen/configs/tools/custom_tools/claude_custom_tool_example_no_path.yaml +1 -1
- massgen/configs/tools/custom_tools/claude_custom_tool_with_mcp_example.yaml +1 -0
- massgen/configs/tools/custom_tools/computer_use_browser_example.yaml +1 -1
- massgen/configs/tools/custom_tools/computer_use_docker_example.yaml +1 -1
- massgen/configs/tools/custom_tools/gemini_custom_tool_with_mcp_example.yaml +1 -0
- massgen/configs/tools/custom_tools/gpt5_nano_custom_tool_with_mcp_example.yaml +1 -0
- massgen/configs/tools/custom_tools/gpt_oss_custom_tool_with_mcp_example.yaml +1 -0
- massgen/configs/tools/custom_tools/grok3_mini_custom_tool_with_mcp_example.yaml +1 -0
- massgen/configs/tools/custom_tools/interop/ag2_and_langgraph_lesson_planner.yaml +65 -0
- massgen/configs/tools/custom_tools/interop/ag2_and_openai_assistant_lesson_planner.yaml +65 -0
- massgen/configs/tools/custom_tools/interop/ag2_lesson_planner_example.yaml +48 -0
- massgen/configs/tools/custom_tools/interop/agentscope_lesson_planner_example.yaml +48 -0
- massgen/configs/tools/custom_tools/interop/langgraph_lesson_planner_example.yaml +49 -0
- massgen/configs/tools/custom_tools/interop/openai_assistant_lesson_planner_example.yaml +50 -0
- massgen/configs/tools/custom_tools/interop/smolagent_lesson_planner_example.yaml +49 -0
- massgen/configs/tools/custom_tools/qwen_api_custom_tool_with_mcp_example.yaml +1 -0
- massgen/configs/tools/custom_tools/two_models_with_tools_example.yaml +44 -0
- massgen/formatter/_gemini_formatter.py +61 -15
- massgen/memory/README.md +277 -0
- massgen/memory/__init__.py +26 -0
- massgen/memory/_base.py +193 -0
- massgen/memory/_compression.py +237 -0
- massgen/memory/_context_monitor.py +211 -0
- massgen/memory/_conversation.py +255 -0
- massgen/memory/_fact_extraction_prompts.py +333 -0
- massgen/memory/_mem0_adapters.py +257 -0
- massgen/memory/_persistent.py +687 -0
- massgen/memory/docker-compose.qdrant.yml +36 -0
- massgen/memory/docs/DESIGN.md +388 -0
- massgen/memory/docs/QUICKSTART.md +409 -0
- massgen/memory/docs/SUMMARY.md +319 -0
- massgen/memory/docs/agent_use_memory.md +408 -0
- massgen/memory/docs/orchestrator_use_memory.md +586 -0
- massgen/memory/examples.py +237 -0
- massgen/orchestrator.py +207 -7
- massgen/tests/memory/test_agent_compression.py +174 -0
- massgen/tests/memory/test_context_window_management.py +286 -0
- massgen/tests/memory/test_force_compression.py +154 -0
- massgen/tests/memory/test_simple_compression.py +147 -0
- massgen/tests/test_ag2_lesson_planner.py +223 -0
- massgen/tests/test_agent_memory.py +534 -0
- massgen/tests/test_config_validator.py +1156 -0
- massgen/tests/test_conversation_memory.py +382 -0
- massgen/tests/test_langgraph_lesson_planner.py +223 -0
- massgen/tests/test_orchestrator_memory.py +620 -0
- massgen/tests/test_persistent_memory.py +435 -0
- massgen/token_manager/token_manager.py +6 -0
- massgen/tool/__init__.py +2 -9
- massgen/tool/_decorators.py +52 -0
- massgen/tool/_extraframework_agents/ag2_lesson_planner_tool.py +251 -0
- massgen/tool/_extraframework_agents/agentscope_lesson_planner_tool.py +303 -0
- massgen/tool/_extraframework_agents/langgraph_lesson_planner_tool.py +275 -0
- massgen/tool/_extraframework_agents/openai_assistant_lesson_planner_tool.py +247 -0
- massgen/tool/_extraframework_agents/smolagent_lesson_planner_tool.py +180 -0
- massgen/tool/_manager.py +102 -16
- massgen/tool/_registered_tool.py +3 -0
- massgen/tool/_result.py +3 -0
- {massgen-0.1.4.dist-info → massgen-0.1.6.dist-info}/METADATA +138 -77
- {massgen-0.1.4.dist-info → massgen-0.1.6.dist-info}/RECORD +82 -37
- massgen/backend/gemini_mcp_manager.py +0 -545
- massgen/backend/gemini_trackers.py +0 -344
- {massgen-0.1.4.dist-info → massgen-0.1.6.dist-info}/WHEEL +0 -0
- {massgen-0.1.4.dist-info → massgen-0.1.6.dist-info}/entry_points.txt +0 -0
- {massgen-0.1.4.dist-info → massgen-0.1.6.dist-info}/licenses/LICENSE +0 -0
- {massgen-0.1.4.dist-info → massgen-0.1.6.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,586 @@
|
|
|
1
|
+
# Orchestrator Shared Memory Integration
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
This document describes how the MassGen `Orchestrator` uses shared memory to enable collaboration between multiple agents. Unlike individual agents that maintain their own private memory, the Orchestrator provides shared memory that all coordinated agents can access and contribute to.
|
|
6
|
+
|
|
7
|
+
## Motivation
|
|
8
|
+
|
|
9
|
+
In multi-agent coordination scenarios, agents need to:
|
|
10
|
+
- Share findings and discoveries with each other
|
|
11
|
+
- Build on each other's work
|
|
12
|
+
- Avoid duplicating efforts
|
|
13
|
+
- Maintain a unified knowledge base
|
|
14
|
+
|
|
15
|
+
The shared memory system enables these capabilities by providing a common memory space that all agents can read from and write to.
|
|
16
|
+
|
|
17
|
+
## Architecture
|
|
18
|
+
|
|
19
|
+
The Orchestrator supports two types of shared memory:
|
|
20
|
+
|
|
21
|
+
1. **Shared ConversationMemory**: All agents see the same conversation history
|
|
22
|
+
2. **Shared PersistentMemory**: All agents contribute to and retrieve from shared long-term knowledge
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
26
|
+
│ Orchestrator │
|
|
27
|
+
├─────────────────────────────────────────────────────────────────┤
|
|
28
|
+
│ │
|
|
29
|
+
│ ┌────────────────────────┐ ┌─────────────────────────────┐ │
|
|
30
|
+
│ │ Shared Conversation │ │ Shared Persistent │ │
|
|
31
|
+
│ │ Memory (Optional) │ │ Memory (Optional) │ │
|
|
32
|
+
│ ├────────────────────────┤ ├─────────────────────────────┤ │
|
|
33
|
+
│ │ • Agent contributions │ │ • Cross-session knowledge │ │
|
|
34
|
+
│ │ • Shared insights │ │ • Semantic search │ │
|
|
35
|
+
│ │ • Agent attribution │ │ • Long-term collaboration │ │
|
|
36
|
+
│ └────────────────────────┘ └─────────────────────────────┘ │
|
|
37
|
+
│ ▲ ▲ │
|
|
38
|
+
│ │ │ │
|
|
39
|
+
│ │ Inject & Record │ │
|
|
40
|
+
│ │ │ │
|
|
41
|
+
│ ┌────────┴──────┐ ┌──────────┐ ┌────┴──────┐ │
|
|
42
|
+
│ │ Agent 1 │ │ Agent 2 │ │ Agent 3 │ │
|
|
43
|
+
│ │ │ │ │ │ │ │
|
|
44
|
+
│ │ Reads shared │ │ Reads │ │ Reads │ │
|
|
45
|
+
│ │ memory before │ │ shared │ │ shared │ │
|
|
46
|
+
│ │ responding │ │ memory │ │ memory │ │
|
|
47
|
+
│ │ │ │ │ │ │ │
|
|
48
|
+
│ │ Writes to │ │ Writes │ │ Writes │ │
|
|
49
|
+
│ │ shared memory │ │ to shared│ │ to shared │ │
|
|
50
|
+
│ └───────────────┘ └──────────┘ └───────────┘ │
|
|
51
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Implementation Details
|
|
55
|
+
|
|
56
|
+
### Initialization
|
|
57
|
+
|
|
58
|
+
The Orchestrator accepts shared memory instances during initialization:
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
from massgen.orchestrator import Orchestrator
|
|
62
|
+
from massgen.memory import ConversationMemory, PersistentMemory
|
|
63
|
+
|
|
64
|
+
# Create shared memories
|
|
65
|
+
shared_conv_memory = ConversationMemory()
|
|
66
|
+
shared_persist_memory = PersistentMemory(
|
|
67
|
+
user_id="team_workspace",
|
|
68
|
+
agent_id="orchestrator"
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
# Create orchestrator with shared memories
|
|
72
|
+
orchestrator = Orchestrator(
|
|
73
|
+
agents=agents_dict,
|
|
74
|
+
shared_conversation_memory=shared_conv_memory, # Optional
|
|
75
|
+
shared_persistent_memory=shared_persist_memory # Optional
|
|
76
|
+
)
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Both parameters are optional - orchestrators can use:
|
|
80
|
+
- Only shared conversation memory
|
|
81
|
+
- Only shared persistent memory
|
|
82
|
+
- Both shared memories
|
|
83
|
+
- No shared memory (agents work independently)
|
|
84
|
+
|
|
85
|
+
### Memory Injection Workflow
|
|
86
|
+
|
|
87
|
+
When an agent is about to process a task, the Orchestrator injects shared memory context into the agent's messages through the `_inject_shared_memory_context()` method.
|
|
88
|
+
|
|
89
|
+
#### Method Signature
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
async def _inject_shared_memory_context(
|
|
93
|
+
self,
|
|
94
|
+
messages: List[Dict[str, Any]],
|
|
95
|
+
agent_id: str
|
|
96
|
+
) -> List[Dict[str, Any]]:
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**Code location**: `massgen/orchestrator.py:330-399`
|
|
100
|
+
|
|
101
|
+
#### Injection Process
|
|
102
|
+
|
|
103
|
+
1. **Check if shared memory exists**
|
|
104
|
+
- If no shared memory is configured, return original messages unchanged
|
|
105
|
+
- This ensures orchestrators work fine without shared memory
|
|
106
|
+
|
|
107
|
+
2. **Retrieve Shared ConversationMemory** (if configured)
|
|
108
|
+
- Fetches recent messages from shared conversation memory (last 10 messages)
|
|
109
|
+
- Formats each message with agent attribution: `[agent_id]: content`
|
|
110
|
+
- Creates a "SHARED CONVERSATION MEMORY" section
|
|
111
|
+
|
|
112
|
+
3. **Retrieve Shared PersistentMemory** (if configured)
|
|
113
|
+
- Calls `retrieve()` to get semantically relevant long-term knowledge
|
|
114
|
+
- Creates a "SHARED PERSISTENT MEMORY" section
|
|
115
|
+
|
|
116
|
+
4. **Inject into messages**
|
|
117
|
+
- Adds a system message with the memory context
|
|
118
|
+
- Inserts after the first system message (if exists) or at the beginning
|
|
119
|
+
- Memory context is clearly labeled for the agent
|
|
120
|
+
|
|
121
|
+
#### Example Memory Injection
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
# Original messages
|
|
125
|
+
messages = [
|
|
126
|
+
{"role": "system", "content": "You are a helpful agent"},
|
|
127
|
+
{"role": "user", "content": "Solve the problem"}
|
|
128
|
+
]
|
|
129
|
+
|
|
130
|
+
# After injection (example)
|
|
131
|
+
injected_messages = [
|
|
132
|
+
{"role": "system", "content": "You are a helpful agent"},
|
|
133
|
+
{
|
|
134
|
+
"role": "system",
|
|
135
|
+
"content": """
|
|
136
|
+
=== SHARED CONVERSATION MEMORY ===
|
|
137
|
+
[agent1]: I found that the issue is in module X
|
|
138
|
+
[agent2]: I've verified agent1's finding and tested a fix
|
|
139
|
+
|
|
140
|
+
=== SHARED PERSISTENT MEMORY ===
|
|
141
|
+
Historical context: Previous sessions show this is a recurring issue
|
|
142
|
+
"""
|
|
143
|
+
},
|
|
144
|
+
{"role": "user", "content": "Solve the problem"}
|
|
145
|
+
]
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Memory Recording Workflow
|
|
149
|
+
|
|
150
|
+
When an agent produces output, the Orchestrator records it to shared memory through the `_record_to_shared_memory()` method.
|
|
151
|
+
|
|
152
|
+
#### Method Signature
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
async def _record_to_shared_memory(
|
|
156
|
+
self,
|
|
157
|
+
agent_id: str,
|
|
158
|
+
content: str,
|
|
159
|
+
role: str = "assistant"
|
|
160
|
+
) -> None:
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
**Code location**: `massgen/orchestrator.py:400-433`
|
|
164
|
+
|
|
165
|
+
#### Recording Process
|
|
166
|
+
|
|
167
|
+
1. **Create message with metadata**
|
|
168
|
+
```python
|
|
169
|
+
message = {
|
|
170
|
+
"role": role,
|
|
171
|
+
"content": content,
|
|
172
|
+
"agent_id": agent_id,
|
|
173
|
+
"timestamp": time.time()
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
2. **Add to Shared ConversationMemory** (if configured)
|
|
178
|
+
- Stores the message in chronological order
|
|
179
|
+
- Includes agent attribution
|
|
180
|
+
- Errors are logged but don't interrupt workflow
|
|
181
|
+
|
|
182
|
+
3. **Record to Shared PersistentMemory** (if configured)
|
|
183
|
+
- Records the message for long-term storage
|
|
184
|
+
- Handles `NotImplementedError` gracefully
|
|
185
|
+
- Errors are logged but don't interrupt workflow
|
|
186
|
+
|
|
187
|
+
### Integration with Agent Workflow
|
|
188
|
+
|
|
189
|
+
The Orchestrator integrates shared memory at key points in the agent coordination workflow:
|
|
190
|
+
|
|
191
|
+
#### 1. Before Agent Processes Task
|
|
192
|
+
|
|
193
|
+
**Code location**: `massgen/orchestrator.py:1474-1476`
|
|
194
|
+
|
|
195
|
+
```python
|
|
196
|
+
# Inject shared memory context before agent responds
|
|
197
|
+
conversation_messages = await self._inject_shared_memory_context(
|
|
198
|
+
conversation_messages, agent_id
|
|
199
|
+
)
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
This happens right before the agent starts working on its task, ensuring it sees all shared knowledge.
|
|
203
|
+
|
|
204
|
+
#### 2. After Agent Votes
|
|
205
|
+
|
|
206
|
+
**Code location**: `massgen/orchestrator.py:1771-1775`
|
|
207
|
+
|
|
208
|
+
```python
|
|
209
|
+
# Record vote to shared memory
|
|
210
|
+
await self._record_to_shared_memory(
|
|
211
|
+
agent_id=agent_id,
|
|
212
|
+
content=vote_message,
|
|
213
|
+
role="assistant"
|
|
214
|
+
)
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
When an agent votes for another agent's answer, the vote is recorded to shared memory so all agents can see voting activity.
|
|
218
|
+
|
|
219
|
+
#### 3. After Agent Provides New Answer
|
|
220
|
+
|
|
221
|
+
**Code location**: `massgen/orchestrator.py:1823-1827`
|
|
222
|
+
|
|
223
|
+
```python
|
|
224
|
+
# Record new answer to shared memory
|
|
225
|
+
await self._record_to_shared_memory(
|
|
226
|
+
agent_id=agent_id,
|
|
227
|
+
content=content,
|
|
228
|
+
role="assistant"
|
|
229
|
+
)
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
When an agent produces a new answer, it's immediately shared with all other agents.
|
|
233
|
+
|
|
234
|
+
## Memory Visibility and Attribution
|
|
235
|
+
|
|
236
|
+
### Agent Attribution
|
|
237
|
+
|
|
238
|
+
Every message recorded to shared memory includes the `agent_id` field, which allows:
|
|
239
|
+
- Tracking which agent contributed what
|
|
240
|
+
- Proper attribution in memory injection
|
|
241
|
+
- Understanding collaboration patterns
|
|
242
|
+
|
|
243
|
+
### Cross-Agent Visibility
|
|
244
|
+
|
|
245
|
+
Key principle: **All agents see all shared memory**
|
|
246
|
+
|
|
247
|
+
- Agent A can see Agent B's contributions
|
|
248
|
+
- Agent B can see Agent C's findings
|
|
249
|
+
- Agent C can see both A and B's work
|
|
250
|
+
|
|
251
|
+
This creates a collaborative environment where agents build on each other's work.
|
|
252
|
+
|
|
253
|
+
### Example Collaboration Flow
|
|
254
|
+
|
|
255
|
+
```
|
|
256
|
+
Step 1: Agent1 analyzes the problem
|
|
257
|
+
→ Records to shared memory: "The issue is in the database connection"
|
|
258
|
+
|
|
259
|
+
Step 2: Agent2 receives task
|
|
260
|
+
→ Sees Agent1's finding in shared memory
|
|
261
|
+
→ Builds on it: "Confirmed. The connection pool is exhausted"
|
|
262
|
+
→ Records to shared memory
|
|
263
|
+
|
|
264
|
+
Step 3: Agent3 receives task
|
|
265
|
+
→ Sees both Agent1 and Agent2's findings
|
|
266
|
+
→ Provides solution: "Increased pool size to 50. Issue resolved"
|
|
267
|
+
→ Records to shared memory
|
|
268
|
+
|
|
269
|
+
Result: Efficient collaboration with no duplicate work
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## Error Handling
|
|
273
|
+
|
|
274
|
+
The Orchestrator implements robust error handling for shared memory operations:
|
|
275
|
+
|
|
276
|
+
### Memory Retrieval Errors
|
|
277
|
+
|
|
278
|
+
```python
|
|
279
|
+
# Code location: massgen/orchestrator.py:353-356
|
|
280
|
+
try:
|
|
281
|
+
conv_messages = await self.shared_conversation_memory.get_messages()
|
|
282
|
+
except Exception as e:
|
|
283
|
+
logger.warning(f"Failed to retrieve shared conversation memory: {e}")
|
|
284
|
+
conv_messages = []
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
- Errors during retrieval are logged
|
|
288
|
+
- Orchestrator continues with empty memory context
|
|
289
|
+
- Agents still receive their tasks
|
|
290
|
+
|
|
291
|
+
### Memory Recording Errors
|
|
292
|
+
|
|
293
|
+
```python
|
|
294
|
+
# Code location: massgen/orchestrator.py:420-423
|
|
295
|
+
try:
|
|
296
|
+
await self.shared_conversation_memory.add(message)
|
|
297
|
+
except Exception as e:
|
|
298
|
+
logger.warning(f"Failed to add to shared conversation memory: {e}")
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
- Recording failures are logged
|
|
302
|
+
- Workflow continues normally
|
|
303
|
+
- Other agents may miss this contribution but system remains stable
|
|
304
|
+
|
|
305
|
+
### NotImplementedError Handling
|
|
306
|
+
|
|
307
|
+
```python
|
|
308
|
+
# Code location: massgen/orchestrator.py:427-430
|
|
309
|
+
try:
|
|
310
|
+
await self.shared_persistent_memory.record([message])
|
|
311
|
+
except NotImplementedError:
|
|
312
|
+
pass # Memory backend doesn't support record
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
- Gracefully handles unimplemented memory operations
|
|
316
|
+
- Allows using memory backends with partial functionality
|
|
317
|
+
|
|
318
|
+
## Usage Examples
|
|
319
|
+
|
|
320
|
+
### Example 1: Orchestrator with Shared ConversationMemory
|
|
321
|
+
|
|
322
|
+
```python
|
|
323
|
+
from massgen.orchestrator import Orchestrator
|
|
324
|
+
from massgen.memory import ConversationMemory
|
|
325
|
+
from massgen.chat_agent import SingleAgent
|
|
326
|
+
|
|
327
|
+
# Create agents
|
|
328
|
+
agents = {
|
|
329
|
+
"analyzer": SingleAgent(backend=backend1, agent_id="analyzer"),
|
|
330
|
+
"implementer": SingleAgent(backend=backend2, agent_id="implementer"),
|
|
331
|
+
"reviewer": SingleAgent(backend=backend3, agent_id="reviewer")
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
# Create shared conversation memory
|
|
335
|
+
shared_memory = ConversationMemory()
|
|
336
|
+
|
|
337
|
+
# Create orchestrator
|
|
338
|
+
orchestrator = Orchestrator(
|
|
339
|
+
agents=agents,
|
|
340
|
+
shared_conversation_memory=shared_memory
|
|
341
|
+
)
|
|
342
|
+
|
|
343
|
+
# Use orchestrator - agents automatically share findings
|
|
344
|
+
async for chunk in orchestrator.chat(messages):
|
|
345
|
+
print(chunk)
|
|
346
|
+
|
|
347
|
+
# Check what was shared
|
|
348
|
+
shared_messages = await shared_memory.get_messages()
|
|
349
|
+
for msg in shared_messages:
|
|
350
|
+
print(f"[{msg['agent_id']}]: {msg['content']}")
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
### Example 2: Orchestrator with Shared PersistentMemory
|
|
354
|
+
|
|
355
|
+
```python
|
|
356
|
+
from massgen.orchestrator import Orchestrator
|
|
357
|
+
from massgen.memory import PersistentMemory
|
|
358
|
+
from massgen.chat_agent import SingleAgent
|
|
359
|
+
|
|
360
|
+
# Create agents
|
|
361
|
+
agents = {
|
|
362
|
+
"agent1": SingleAgent(backend=backend, agent_id="agent1"),
|
|
363
|
+
"agent2": SingleAgent(backend=backend, agent_id="agent2")
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
# Create shared persistent memory
|
|
367
|
+
shared_persist_memory = PersistentMemory(
|
|
368
|
+
user_id="team_project_alpha",
|
|
369
|
+
agent_id="orchestrator"
|
|
370
|
+
)
|
|
371
|
+
|
|
372
|
+
# Create orchestrator
|
|
373
|
+
orchestrator = Orchestrator(
|
|
374
|
+
agents=agents,
|
|
375
|
+
shared_persistent_memory=shared_persist_memory
|
|
376
|
+
)
|
|
377
|
+
|
|
378
|
+
# Session 1
|
|
379
|
+
messages1 = [{"role": "user", "content": "Design the API"}]
|
|
380
|
+
async for chunk in orchestrator.chat(messages1):
|
|
381
|
+
print(chunk)
|
|
382
|
+
|
|
383
|
+
# Session 2 - agents remember previous session
|
|
384
|
+
messages2 = [{"role": "user", "content": "Implement the API we designed"}]
|
|
385
|
+
async for chunk in orchestrator.chat(messages2):
|
|
386
|
+
print(chunk)
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
### Example 3: Orchestrator with Both Shared Memories
|
|
390
|
+
|
|
391
|
+
```python
|
|
392
|
+
from massgen.orchestrator import Orchestrator
|
|
393
|
+
from massgen.memory import ConversationMemory, PersistentMemory
|
|
394
|
+
from massgen.chat_agent import SingleAgent
|
|
395
|
+
|
|
396
|
+
# Create agents
|
|
397
|
+
agents = {
|
|
398
|
+
"researcher": SingleAgent(backend=backend, agent_id="researcher"),
|
|
399
|
+
"developer": SingleAgent(backend=backend, agent_id="developer"),
|
|
400
|
+
"tester": SingleAgent(backend=backend, agent_id="tester")
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
# Create both shared memories
|
|
404
|
+
shared_conv_memory = ConversationMemory()
|
|
405
|
+
shared_persist_memory = PersistentMemory(
|
|
406
|
+
user_id="project_gamma",
|
|
407
|
+
agent_id="orchestrator"
|
|
408
|
+
)
|
|
409
|
+
|
|
410
|
+
# Create orchestrator with both
|
|
411
|
+
orchestrator = Orchestrator(
|
|
412
|
+
agents=agents,
|
|
413
|
+
shared_conversation_memory=shared_conv_memory,
|
|
414
|
+
shared_persistent_memory=shared_persist_memory
|
|
415
|
+
)
|
|
416
|
+
|
|
417
|
+
# Benefits:
|
|
418
|
+
# - Current session: All agents see each other's work
|
|
419
|
+
# - Cross-session: Knowledge persists and accumulates over time
|
|
420
|
+
messages = [{"role": "user", "content": "Build a new feature"}]
|
|
421
|
+
async for chunk in orchestrator.chat(messages):
|
|
422
|
+
print(chunk)
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
### Example 4: Orchestrator without Shared Memory
|
|
426
|
+
|
|
427
|
+
```python
|
|
428
|
+
from massgen.orchestrator import Orchestrator
|
|
429
|
+
from massgen.chat_agent import SingleAgent
|
|
430
|
+
|
|
431
|
+
# Create agents
|
|
432
|
+
agents = {
|
|
433
|
+
"agent1": SingleAgent(backend=backend, agent_id="agent1"),
|
|
434
|
+
"agent2": SingleAgent(backend=backend, agent_id="agent2")
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
# Create orchestrator without shared memory
|
|
438
|
+
orchestrator = Orchestrator(agents=agents)
|
|
439
|
+
|
|
440
|
+
# Agents work independently, no shared context
|
|
441
|
+
# Useful for independent parallel tasks
|
|
442
|
+
messages = [{"role": "user", "content": "Analyze this problem"}]
|
|
443
|
+
async for chunk in orchestrator.chat(messages):
|
|
444
|
+
print(chunk)
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
## Memory Flow Diagram
|
|
448
|
+
|
|
449
|
+
```
|
|
450
|
+
┌─────────────────────────────────────────────────────────┐
|
|
451
|
+
│ User sends task to Orchestrator │
|
|
452
|
+
└─────────────────────────────────────────────────────────┘
|
|
453
|
+
│
|
|
454
|
+
▼
|
|
455
|
+
┌─────────────────────────────────────────────────────────┐
|
|
456
|
+
│ Orchestrator assigns task to Agent 1 │
|
|
457
|
+
└─────────────────────────────────────────────────────────┘
|
|
458
|
+
│
|
|
459
|
+
▼
|
|
460
|
+
┌─────────────────────────────────────────────────────────┐
|
|
461
|
+
│ _inject_shared_memory_context(messages, "agent1") │
|
|
462
|
+
│ │
|
|
463
|
+
│ 1. Retrieve from Shared ConversationMemory │
|
|
464
|
+
│ └─ Get recent agent contributions │
|
|
465
|
+
│ │
|
|
466
|
+
│ 2. Retrieve from Shared PersistentMemory │
|
|
467
|
+
│ └─ Get relevant long-term knowledge │
|
|
468
|
+
│ │
|
|
469
|
+
│ 3. Inject into messages as system message │
|
|
470
|
+
│ └─ Agent sees what others have found │
|
|
471
|
+
└─────────────────────────────────────────────────────────┘
|
|
472
|
+
│
|
|
473
|
+
▼
|
|
474
|
+
┌─────────────────────────────────────────────────────────┐
|
|
475
|
+
│ Agent 1 processes task │
|
|
476
|
+
│ │
|
|
477
|
+
│ • Sees shared memory context │
|
|
478
|
+
│ • Understands what others have done │
|
|
479
|
+
│ • Builds on previous findings │
|
|
480
|
+
└─────────────────────────────────────────────────────────┘
|
|
481
|
+
│
|
|
482
|
+
▼
|
|
483
|
+
┌─────────────────────────────────────────────────────────┐
|
|
484
|
+
│ Agent 1 produces answer/vote │
|
|
485
|
+
└─────────────────────────────────────────────────────────┘
|
|
486
|
+
│
|
|
487
|
+
▼
|
|
488
|
+
┌─────────────────────────────────────────────────────────┐
|
|
489
|
+
│ _record_to_shared_memory("agent1", content) │
|
|
490
|
+
│ │
|
|
491
|
+
│ 1. Record to Shared ConversationMemory │
|
|
492
|
+
│ └─ Add with agent_id and timestamp │
|
|
493
|
+
│ │
|
|
494
|
+
│ 2. Record to Shared PersistentMemory │
|
|
495
|
+
│ └─ Store for future sessions │
|
|
496
|
+
└─────────────────────────────────────────────────────────┘
|
|
497
|
+
│
|
|
498
|
+
▼
|
|
499
|
+
┌─────────────────────────────────────────────────────────┐
|
|
500
|
+
│ Next agent sees Agent 1's contribution │
|
|
501
|
+
└─────────────────────────────────────────────────────────┘
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
## Key Differences from Agent Memory
|
|
505
|
+
|
|
506
|
+
| Feature | Agent Memory | Orchestrator Shared Memory |
|
|
507
|
+
|---------|-------------|---------------------------|
|
|
508
|
+
| **Scope** | Private to one agent | Shared across all agents |
|
|
509
|
+
| **Purpose** | Track agent's own conversation | Enable agent collaboration |
|
|
510
|
+
| **Visibility** | Only the agent sees it | All agents see all contributions |
|
|
511
|
+
| **Attribution** | Not needed | Agent ID tracked for each message |
|
|
512
|
+
| **Use Case** | Single-agent conversations | Multi-agent coordination |
|
|
513
|
+
| **Injection** | Automatic per agent | Orchestrator injects before tasks |
|
|
514
|
+
| **Recording** | Agent records own messages | Orchestrator records all agent outputs |
|
|
515
|
+
|
|
516
|
+
## Key Files
|
|
517
|
+
|
|
518
|
+
Implementation files:
|
|
519
|
+
- `massgen/orchestrator.py:73-100` - Orchestrator class definition
|
|
520
|
+
- `massgen/orchestrator.py:330-399` - Memory injection implementation
|
|
521
|
+
- `massgen/orchestrator.py:400-433` - Memory recording implementation
|
|
522
|
+
- `massgen/orchestrator.py:1474-1476` - Injection before agent task
|
|
523
|
+
- `massgen/orchestrator.py:1771-1827` - Recording after agent output
|
|
524
|
+
|
|
525
|
+
Test files:
|
|
526
|
+
- `massgen/tests/test_orchestrator_memory.py` - Comprehensive orchestrator memory tests
|
|
527
|
+
|
|
528
|
+
## Best Practices
|
|
529
|
+
|
|
530
|
+
1. **Choose Shared Memory Based on Task**:
|
|
531
|
+
- Use Shared ConversationMemory for short-term collaboration tasks
|
|
532
|
+
- Use Shared PersistentMemory for long-running projects across sessions
|
|
533
|
+
- Use both for comprehensive team collaboration
|
|
534
|
+
|
|
535
|
+
2. **Memory Size Management**:
|
|
536
|
+
- Shared ConversationMemory shows last 10 messages by default
|
|
537
|
+
- Prevents overwhelming agents with too much context
|
|
538
|
+
- For very large teams, consider more aggressive filtering
|
|
539
|
+
|
|
540
|
+
3. **Agent Attribution**:
|
|
541
|
+
- Always check which agent contributed what
|
|
542
|
+
- Use agent_id to track collaboration patterns
|
|
543
|
+
- Attribution helps debug coordination issues
|
|
544
|
+
|
|
545
|
+
4. **Error Resilience**:
|
|
546
|
+
- Shared memory failures don't crash the orchestrator
|
|
547
|
+
- Agents can still work if memory is unavailable
|
|
548
|
+
- Monitor logs for memory errors in production
|
|
549
|
+
|
|
550
|
+
5. **Privacy and Isolation**:
|
|
551
|
+
- If agents need private memory, give them individual memories (not shared)
|
|
552
|
+
- Shared memory is truly shared - all agents see everything
|
|
553
|
+
- Consider task requirements when deciding to use shared memory
|
|
554
|
+
|
|
555
|
+
## Limitations
|
|
556
|
+
|
|
557
|
+
1. **Shared ConversationMemory**:
|
|
558
|
+
- Shows last 10 messages only (hardcoded limit)
|
|
559
|
+
- May miss earlier contributions in very long collaborations
|
|
560
|
+
- No filtering by relevance, only recency
|
|
561
|
+
|
|
562
|
+
2. **Shared PersistentMemory**:
|
|
563
|
+
- Retrieval is semantic and may not be perfect
|
|
564
|
+
- All agents use the same user_id/agent_id for shared memory
|
|
565
|
+
- No per-agent persistent memory isolation when using shared mode
|
|
566
|
+
|
|
567
|
+
3. **Scalability**:
|
|
568
|
+
- Memory injection happens for every agent task
|
|
569
|
+
- May add latency with many agents or large memory
|
|
570
|
+
- No caching of memory context between agent calls
|
|
571
|
+
|
|
572
|
+
4. **Attribution Overhead**:
|
|
573
|
+
- Agent attribution increases message size
|
|
574
|
+
- More context tokens consumed by LLM
|
|
575
|
+
- Formatting overhead for memory display
|
|
576
|
+
|
|
577
|
+
## Future Enhancements
|
|
578
|
+
|
|
579
|
+
- [ ] Configurable memory window size (currently hardcoded to 10)
|
|
580
|
+
- [ ] Relevance-based filtering instead of only recency
|
|
581
|
+
- [ ] Memory context caching to reduce retrieval overhead
|
|
582
|
+
- [ ] Per-agent memory isolation within orchestrator
|
|
583
|
+
- [ ] Memory compression for large collaborations
|
|
584
|
+
- [ ] Analytics on agent collaboration patterns
|
|
585
|
+
- [ ] Selective memory sharing (agent groups/permissions)
|
|
586
|
+
- [ ] Memory summarization for very long collaborations
|