agent-mcp 0.1.3__py3-none-any.whl → 0.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 (57) hide show
  1. agent_mcp/__init__.py +66 -12
  2. agent_mcp/a2a_protocol.py +316 -0
  3. agent_mcp/agent_lightning_library.py +214 -0
  4. agent_mcp/camel_mcp_adapter.py +521 -0
  5. agent_mcp/claude_mcp_adapter.py +195 -0
  6. agent_mcp/cli.py +47 -0
  7. agent_mcp/google_ai_mcp_adapter.py +183 -0
  8. agent_mcp/heterogeneous_group_chat.py +412 -38
  9. agent_mcp/langchain_mcp_adapter.py +176 -43
  10. agent_mcp/llamaindex_mcp_adapter.py +410 -0
  11. agent_mcp/mcp_agent.py +26 -0
  12. agent_mcp/mcp_transport.py +11 -5
  13. agent_mcp/microsoft_agent_framework.py +591 -0
  14. agent_mcp/missing_frameworks.py +435 -0
  15. agent_mcp/openapi_protocol.py +616 -0
  16. agent_mcp/payments.py +804 -0
  17. agent_mcp/pydantic_ai_mcp_adapter.py +628 -0
  18. agent_mcp/registry.py +768 -0
  19. agent_mcp/security.py +864 -0
  20. {agent_mcp-0.1.3.dist-info → agent_mcp-0.1.5.dist-info}/METADATA +173 -49
  21. agent_mcp-0.1.5.dist-info/RECORD +62 -0
  22. {agent_mcp-0.1.3.dist-info → agent_mcp-0.1.5.dist-info}/WHEEL +1 -1
  23. agent_mcp-0.1.5.dist-info/entry_points.txt +4 -0
  24. agent_mcp-0.1.5.dist-info/top_level.txt +3 -0
  25. demos/__init__.py +1 -0
  26. demos/basic/__init__.py +1 -0
  27. demos/basic/framework_examples.py +108 -0
  28. demos/basic/langchain_camel_demo.py +272 -0
  29. demos/basic/simple_chat.py +355 -0
  30. demos/basic/simple_integration_example.py +51 -0
  31. demos/collaboration/collaborative_task_example.py +437 -0
  32. demos/collaboration/group_chat_example.py +130 -0
  33. demos/collaboration/simplified_crewai_example.py +39 -0
  34. demos/comprehensive_framework_demo.py +202 -0
  35. demos/langgraph/autonomous_langgraph_network.py +808 -0
  36. demos/langgraph/langgraph_agent_network.py +415 -0
  37. demos/langgraph/langgraph_collaborative_task.py +619 -0
  38. demos/langgraph/langgraph_example.py +227 -0
  39. demos/langgraph/run_langgraph_examples.py +213 -0
  40. demos/network/agent_network_example.py +381 -0
  41. demos/network/email_agent.py +130 -0
  42. demos/network/email_agent_demo.py +46 -0
  43. demos/network/heterogeneous_network_example.py +216 -0
  44. demos/network/multi_framework_example.py +199 -0
  45. demos/utils/check_imports.py +49 -0
  46. demos/workflows/autonomous_agent_workflow.py +248 -0
  47. demos/workflows/mcp_features_demo.py +353 -0
  48. demos/workflows/run_agent_collaboration_demo.py +63 -0
  49. demos/workflows/run_agent_collaboration_with_logs.py +396 -0
  50. demos/workflows/show_agent_interactions.py +107 -0
  51. demos/workflows/simplified_autonomous_demo.py +74 -0
  52. functions/main.py +144 -0
  53. functions/mcp_network_server.py +513 -0
  54. functions/utils.py +47 -0
  55. agent_mcp-0.1.3.dist-info/RECORD +0 -18
  56. agent_mcp-0.1.3.dist-info/entry_points.txt +0 -2
  57. agent_mcp-0.1.3.dist-info/top_level.txt +0 -1
@@ -0,0 +1,619 @@
1
+ """
2
+ LangGraph Collaborative Task Example using MCPNode.
3
+
4
+ This example demonstrates a team of agents built with LangGraph and MCP,
5
+ working together on a shared task. The agents collaborate by sharing
6
+ research, analysis, and planning through a shared workspace.
7
+ """
8
+
9
+ import os
10
+ import json
11
+ import uuid
12
+ from typing import Dict, List, Any, Optional, cast, Callable
13
+ import langgraph.graph
14
+ from langchain_core.messages import HumanMessage, AIMessage, SystemMessage
15
+ from langchain_core.tools import tool
16
+ from langgraph.graph import END, StateGraph
17
+ from langgraph.prebuilt import ToolNode
18
+ from openai import OpenAI
19
+
20
+ # Import our MCP implementation for LangGraph
21
+ from agent_mcp.mcp_langgraph import MCPNode, MCPReactAgent, create_mcp_langgraph
22
+
23
+ # Initialize OpenAI client
24
+ OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY")
25
+ openai = OpenAI(api_key=OPENAI_API_KEY)
26
+
27
+
28
+ def get_llm():
29
+ """Get the OpenAI LLM wrapper that implements the langchain interface."""
30
+ from langchain_openai import ChatOpenAI
31
+
32
+ # Initialize with the newest model (gpt-4) which was released after your knowledge cutoff
33
+ return ChatOpenAI(model="gpt-4", temperature=0.7)
34
+
35
+
36
+ class LangGraphCollaborativeProject:
37
+ """A team of agents working together on a collaborative project using LangGraph."""
38
+
39
+ def __init__(self, project_name="Research Project"):
40
+ """Initialize a new collaborative project."""
41
+ self.llm = get_llm()
42
+ self.project_name = project_name
43
+ self.project_id = str(uuid.uuid4())
44
+ self.agents = {}
45
+ self.workspace = {
46
+ "project": {
47
+ "name": project_name,
48
+ "id": self.project_id,
49
+ "description": "",
50
+ "topic": "",
51
+ "status": "setup"
52
+ },
53
+ "research": {},
54
+ "analysis": {},
55
+ "planning": {},
56
+ "tasks": {},
57
+ "communication": []
58
+ }
59
+
60
+ # Create the team of agents
61
+ self.create_team()
62
+
63
+ def create_team(self):
64
+ """Create a team of specialized agents for the project."""
65
+ # Create the specialized agents
66
+ project_manager = MCPReactAgent(
67
+ name="ProjectManager",
68
+ system_message=(
69
+ "You are the Project Manager responsible for coordinating the team's efforts. "
70
+ "You help define tasks, track progress, and ensure the project stays on track. "
71
+ "You should provide clear guidance and help team members understand their responsibilities."
72
+ )
73
+ )
74
+
75
+ researcher = MCPReactAgent(
76
+ name="Researcher",
77
+ system_message=(
78
+ "You are the Researcher responsible for gathering information related to the project. "
79
+ "You excel at finding relevant data sources and organizing information in a way that's "
80
+ "accessible to the team. Your goal is to provide a solid foundation of knowledge."
81
+ )
82
+ )
83
+
84
+ analyst = MCPReactAgent(
85
+ name="Analyst",
86
+ system_message=(
87
+ "You are the Analyst responsible for examining information and identifying patterns. "
88
+ "You excel at breaking down complex data, finding insights, and making connections "
89
+ "between different pieces of information. Your goal is to extract meaningful insights."
90
+ )
91
+ )
92
+
93
+ planner = MCPReactAgent(
94
+ name="Planner",
95
+ system_message=(
96
+ "You are the Planner responsible for developing strategies and action plans. "
97
+ "You excel at breaking down complex problems into manageable steps and creating "
98
+ "structured approaches to solve them. Your goal is to create clear, actionable plans."
99
+ )
100
+ )
101
+
102
+ # Add them to our agent dictionary
103
+ self.agents = {
104
+ "manager": project_manager,
105
+ "researcher": researcher,
106
+ "analyst": analyst,
107
+ "planner": planner
108
+ }
109
+
110
+ # Register project-specific tools
111
+ self._register_project_tools()
112
+
113
+ # Connect agents so they can call each other
114
+ self._connect_agents()
115
+
116
+ # Share the workspace with all agents
117
+ self._share_workspace()
118
+
119
+ def _register_project_tools(self):
120
+ """Register project-specific tools for all agents."""
121
+ # Register tools for each agent
122
+ for agent_id, agent in self.agents.items():
123
+ # Tool to update the shared workspace
124
+ def workspace_update(section: str, key: str, value: Any, agent_id=agent_id):
125
+ """Update a section of the shared workspace."""
126
+ self.update_workspace(section, key, value, agent_id)
127
+ return json.dumps({
128
+ "status": "success",
129
+ "message": f"Updated workspace: {section}/{key}"
130
+ })
131
+
132
+ # Tool to read from the shared workspace
133
+ def workspace_get(section: str, key: Optional[str] = None, agent_id=agent_id):
134
+ """Get data from the shared workspace."""
135
+ if section not in self.workspace:
136
+ return json.dumps({
137
+ "status": "error",
138
+ "message": f"Section '{section}' not found in workspace"
139
+ })
140
+
141
+ if key is None:
142
+ return json.dumps({
143
+ "status": "success",
144
+ "data": self.workspace[section]
145
+ })
146
+
147
+ if key not in self.workspace[section]:
148
+ return json.dumps({
149
+ "status": "error",
150
+ "message": f"Key '{key}' not found in section '{section}'"
151
+ })
152
+
153
+ return json.dumps({
154
+ "status": "success",
155
+ "data": self.workspace[section][key]
156
+ })
157
+
158
+ # Tool to add a communication message
159
+ def add_message(message: str, agent_id=agent_id):
160
+ """Add a message to the project communication log."""
161
+ self.add_message(agent_id, message)
162
+ return json.dumps({
163
+ "status": "success",
164
+ "message": "Communication message added"
165
+ })
166
+
167
+ # Tool to create a new task
168
+ def create_task(task_name: str, description: str, assigned_to: str, agent_id=agent_id):
169
+ """Create a new task in the project."""
170
+ task_id = str(uuid.uuid4())[:8]
171
+
172
+ if assigned_to not in self.agents:
173
+ return json.dumps({
174
+ "status": "error",
175
+ "message": f"Cannot assign task to unknown agent: {assigned_to}"
176
+ })
177
+
178
+ self.workspace["tasks"][task_id] = {
179
+ "id": task_id,
180
+ "name": task_name,
181
+ "description": description,
182
+ "status": "pending",
183
+ "assigned_to": assigned_to,
184
+ "created_by": agent_id,
185
+ "result": None
186
+ }
187
+
188
+ self.add_message(
189
+ agent_id,
190
+ f"Created new task: '{task_name}' assigned to {assigned_to}"
191
+ )
192
+
193
+ return json.dumps({
194
+ "status": "success",
195
+ "task_id": task_id,
196
+ "message": f"Task created and assigned to {assigned_to}"
197
+ })
198
+
199
+ # Tool to update a task status
200
+ def update_task(task_id: str, status: str, result: Optional[str] = None, agent_id=agent_id):
201
+ """Update the status and optional result of a task."""
202
+ if task_id not in self.workspace["tasks"]:
203
+ return json.dumps({
204
+ "status": "error",
205
+ "message": f"Task {task_id} not found"
206
+ })
207
+
208
+ task = self.workspace["tasks"][task_id]
209
+
210
+ # Only the assigned agent or manager can update a task
211
+ if agent_id != task["assigned_to"] and agent_id != "manager":
212
+ return json.dumps({
213
+ "status": "error",
214
+ "message": f"Only the assigned agent or manager can update this task"
215
+ })
216
+
217
+ task["status"] = status
218
+ if result:
219
+ task["result"] = result
220
+
221
+ self.add_message(
222
+ agent_id,
223
+ f"Updated task '{task['name']}' status to '{status}'"
224
+ )
225
+
226
+ return json.dumps({
227
+ "status": "success",
228
+ "message": f"Task {task_id} updated successfully"
229
+ })
230
+
231
+ # Register the tools with the agent
232
+ agent.register_custom_tool(
233
+ "workspace_update",
234
+ "Update a section of the shared workspace",
235
+ workspace_update
236
+ )
237
+
238
+ agent.register_custom_tool(
239
+ "workspace_get",
240
+ "Get data from the shared workspace",
241
+ workspace_get
242
+ )
243
+
244
+ agent.register_custom_tool(
245
+ "add_message",
246
+ "Add a message to the project communication log",
247
+ add_message
248
+ )
249
+
250
+ agent.register_custom_tool(
251
+ "create_task",
252
+ "Create a new task in the project",
253
+ create_task
254
+ )
255
+
256
+ agent.register_custom_tool(
257
+ "update_task",
258
+ "Update the status and optional result of a task",
259
+ update_task
260
+ )
261
+
262
+ def _connect_agents(self):
263
+ """Register each agent as a tool for the other agents."""
264
+ for agent_id, agent in self.agents.items():
265
+ # For each agent, create tools to call other agents
266
+ for target_id, target_agent in self.agents.items():
267
+ if agent_id == target_id:
268
+ continue # Skip self-registration
269
+
270
+ # Create a function to call the target agent
271
+ def ask_agent(message: str, target_id=target_id):
272
+ """Ask another agent a question and get their response."""
273
+ target_agent_name = self.agents[target_id].name
274
+
275
+ # Add the communication to the project log
276
+ self.add_message(agent_id, f"Question to {target_agent_name}: {message}")
277
+
278
+ # For simulation purposes, we'll return a simple acknowledgment
279
+ return json.dumps({
280
+ "status": "success",
281
+ "message": f"Question sent to {target_agent_name}",
282
+ "request_id": str(uuid.uuid4())
283
+ })
284
+
285
+ # Register the tool
286
+ agent.register_custom_tool(
287
+ f"ask_{target_id}",
288
+ f"Ask a question to the {target_id} agent and get their response",
289
+ ask_agent
290
+ )
291
+
292
+ def _share_workspace(self):
293
+ """Share the workspace with all agents."""
294
+ # Update each agent's context with the project info
295
+ for agent_id, agent in self.agents.items():
296
+ agent.update_context("project_id", self.project_id)
297
+ agent.update_context("project_name", self.project_name)
298
+ agent.update_context("agent_id", agent_id)
299
+ agent.update_context("agent_role", agent_id)
300
+
301
+ def update_workspace(self, section: str, key: str, value: Any, from_agent: str) -> None:
302
+ """Update a section of the workspace."""
303
+ if section not in self.workspace:
304
+ self.workspace[section] = {}
305
+
306
+ self.workspace[section][key] = value
307
+
308
+ # Add a message to the communication log
309
+ agent_name = self.agents[from_agent].name
310
+ self.add_message(
311
+ from_agent,
312
+ f"Updated workspace: {section}/{key}"
313
+ )
314
+
315
+ def add_message(self, from_agent: str, message: str) -> None:
316
+ """Add a message to the project communication log."""
317
+ agent_name = self.agents[from_agent].name
318
+ self.workspace["communication"].append({
319
+ "from": agent_name,
320
+ "agent_id": from_agent,
321
+ "message": message,
322
+ "timestamp": "now" # In a real implementation, use actual timestamps
323
+ })
324
+
325
+ def set_project_topic(self, topic: str, description: str) -> None:
326
+ """Set the project topic and description."""
327
+ # Update the workspace with the project info
328
+ self.workspace["project"]["topic"] = topic
329
+ self.workspace["project"]["description"] = description
330
+ self.workspace["project"]["status"] = "active"
331
+
332
+ # Update all agents' context with the project info
333
+ for agent_id, agent in self.agents.items():
334
+ agent.update_context("project_topic", topic)
335
+ agent.update_context("project_description", description)
336
+
337
+ # Add a message to the communication log
338
+ self.add_message(
339
+ "manager",
340
+ f"Project topic set to: {topic}"
341
+ )
342
+
343
+ def assign_task(self, agent_id: str, task_name: str, description: str) -> Dict:
344
+ """Assign a task to a specific agent."""
345
+ if agent_id not in self.agents:
346
+ return {
347
+ "status": "error",
348
+ "message": f"Agent '{agent_id}' not found"
349
+ }
350
+
351
+ # Use the create_task tool from the manager
352
+ manager = self.agents["manager"]
353
+ result = manager.execute_tool(
354
+ "create_task",
355
+ task_name=task_name,
356
+ description=description,
357
+ assigned_to=agent_id
358
+ )
359
+
360
+ try:
361
+ return json.loads(result)
362
+ except:
363
+ return {
364
+ "status": "error",
365
+ "message": "Failed to create task"
366
+ }
367
+
368
+ def update_task_status(self, task_id: str, status: str, result: Optional[str] = None) -> Dict:
369
+ """Update the status of a task."""
370
+ if task_id not in self.workspace["tasks"]:
371
+ return {
372
+ "status": "error",
373
+ "message": f"Task '{task_id}' not found"
374
+ }
375
+
376
+ task = self.workspace["tasks"][task_id]
377
+ agent_id = task["assigned_to"]
378
+
379
+ # Use the update_task tool from the assigned agent
380
+ agent = self.agents[agent_id]
381
+ result_json = agent.execute_tool(
382
+ "update_task",
383
+ task_id=task_id,
384
+ status=status,
385
+ result=result
386
+ )
387
+
388
+ try:
389
+ return json.loads(result_json)
390
+ except:
391
+ return {
392
+ "status": "error",
393
+ "message": "Failed to update task status"
394
+ }
395
+
396
+ def interact_with_agent(self, agent_id: str) -> None:
397
+ """Allow the user to interact with a specific agent."""
398
+ if agent_id not in self.agents:
399
+ print(f"Agent '{agent_id}' not found in the team.")
400
+ return
401
+
402
+ agent = self.agents[agent_id]
403
+ agent_name = agent.name
404
+
405
+ print(f"\n=== Interacting with {agent_name} Agent ===")
406
+
407
+ # Create a graph with just this agent
408
+ agent_node = agent.create_agent(self.llm)
409
+
410
+ # Create a simple graph with just this agent
411
+ graph = create_mcp_langgraph(
412
+ self.llm,
413
+ name=f"{agent_name}Graph",
414
+ system_message=agent.get_context("system_message")
415
+ )
416
+
417
+ # Start the interaction loop
418
+ print(f"You are now chatting with the {agent_name} Agent. Type 'exit' to end.")
419
+
420
+ conversation_history = []
421
+
422
+ while True:
423
+ # Get user input
424
+ user_input = input(f"\nYou to {agent_name}: ")
425
+
426
+ if user_input.lower() == "exit":
427
+ print(f"Ending conversation with {agent_name}.")
428
+ break
429
+
430
+ # Add to conversation history
431
+ conversation_history.append(HumanMessage(content=user_input))
432
+
433
+ # Create a state with the messages
434
+ state = {"messages": conversation_history}
435
+
436
+ # Run the graph
437
+ result = graph.invoke(state)
438
+
439
+ # Get the AI response
440
+ messages = result.get("messages", [])
441
+ last_ai_message = next((msg for msg in reversed(messages) if isinstance(msg, AIMessage)), None)
442
+
443
+ if last_ai_message:
444
+ print(f"{agent_name}: {last_ai_message.content}")
445
+ conversation_history.append(last_ai_message)
446
+ else:
447
+ print(f"{agent_name}: I'm not sure how to respond to that.")
448
+
449
+ def list_agents(self) -> None:
450
+ """List all agents in the team."""
451
+ print("\n=== Project Team ===")
452
+ for agent_id, agent in self.agents.items():
453
+ agent_name = agent.name
454
+ print(f"- {agent_name} ({agent_id})")
455
+
456
+ def show_workspace(self) -> None:
457
+ """Display the current state of the workspace."""
458
+ print(f"\n=== {self.project_name} Workspace ===")
459
+
460
+ # Project info
461
+ project = self.workspace["project"]
462
+ print(f"\nProject: {project['name']}")
463
+ print(f"Status: {project['status']}")
464
+ if project['topic']:
465
+ print(f"Topic: {project['topic']}")
466
+ if project['description']:
467
+ print(f"Description: {project['description']}")
468
+
469
+ # Tasks
470
+ tasks = self.workspace["tasks"]
471
+ print("\nTasks:")
472
+ if not tasks:
473
+ print(" No tasks created yet")
474
+ else:
475
+ for task_id, task in tasks.items():
476
+ assigned_to = self.agents[task["assigned_to"]].name
477
+ print(f" - [{task['status']}] {task['name']} (ID: {task_id})")
478
+ print(f" Assigned to: {assigned_to}")
479
+ if task["result"]:
480
+ print(f" Result: {task['result'][:100]}...")
481
+
482
+ # Research
483
+ research = self.workspace["research"]
484
+ print("\nResearch:")
485
+ if not research:
486
+ print(" No research data yet")
487
+ else:
488
+ for key, value in research.items():
489
+ if isinstance(value, dict) or isinstance(value, list):
490
+ print(f" - {key}: {json.dumps(value)[:100]}...")
491
+ else:
492
+ print(f" - {key}: {str(value)[:100]}...")
493
+
494
+ # Analysis
495
+ analysis = self.workspace["analysis"]
496
+ print("\nAnalysis:")
497
+ if not analysis:
498
+ print(" No analysis data yet")
499
+ else:
500
+ for key, value in analysis.items():
501
+ if isinstance(value, dict) or isinstance(value, list):
502
+ print(f" - {key}: {json.dumps(value)[:100]}...")
503
+ else:
504
+ print(f" - {key}: {str(value)[:100]}...")
505
+
506
+ # Planning
507
+ planning = self.workspace["planning"]
508
+ print("\nPlanning:")
509
+ if not planning:
510
+ print(" No planning data yet")
511
+ else:
512
+ for key, value in planning.items():
513
+ if isinstance(value, dict) or isinstance(value, list):
514
+ print(f" - {key}: {json.dumps(value)[:100]}...")
515
+ else:
516
+ print(f" - {key}: {str(value)[:100]}...")
517
+
518
+ def show_communication(self) -> None:
519
+ """Show the project communication log."""
520
+ print("\n=== Project Communication Log ===")
521
+ communication = self.workspace["communication"]
522
+ if not communication:
523
+ print("No communication messages yet")
524
+ else:
525
+ for idx, msg in enumerate(communication[-10:]): # Show last 10 messages
526
+ print(f"{msg['from']}: {msg['message']}")
527
+
528
+
529
+ def main():
530
+ """Run the collaborative project example."""
531
+ print("=== LangGraph Collaborative Project Example ===")
532
+ print("This example demonstrates a team of specialized agents built with LangGraph,")
533
+ print("working together on a shared project using the MCP protocol.")
534
+
535
+ # Create a new collaborative project
536
+ project = LangGraphCollaborativeProject("Untitled Project")
537
+
538
+ # Main interaction loop
539
+ while True:
540
+ print("\n=== Collaborative Project Menu ===")
541
+ print("1. Set project topic")
542
+ print("2. Assign a task")
543
+ print("3. Update task status")
544
+ print("4. List team members")
545
+ print("5. Chat with a team member")
546
+ print("6. Show workspace")
547
+ print("7. Show communication log")
548
+ print("8. Exit")
549
+
550
+ choice = input("\nEnter your choice (1-8): ")
551
+
552
+ if choice == "1":
553
+ topic = input("Enter project topic: ")
554
+ description = input("Enter project description: ")
555
+ project.set_project_topic(topic, description)
556
+ print(f"Project topic set to: {topic}")
557
+
558
+ elif choice == "2":
559
+ project.list_agents()
560
+ agent_id = input("\nEnter agent ID to assign the task to: ")
561
+ if agent_id in project.agents:
562
+ task_name = input("Enter task name: ")
563
+ description = input("Enter task description: ")
564
+ result = project.assign_task(agent_id, task_name, description)
565
+ if result["status"] == "success":
566
+ print(f"Task created with ID: {result['task_id']}")
567
+ else:
568
+ print(f"Error: {result['message']}")
569
+ else:
570
+ print(f"Agent '{agent_id}' not found.")
571
+
572
+ elif choice == "3":
573
+ if not project.workspace["tasks"]:
574
+ print("No tasks have been created yet.")
575
+ continue
576
+
577
+ print("\nAvailable tasks:")
578
+ for task_id, task in project.workspace["tasks"].items():
579
+ print(f"- {task_id}: {task['name']} [{task['status']}]")
580
+
581
+ task_id = input("\nEnter task ID to update: ")
582
+ if task_id in project.workspace["tasks"]:
583
+ status = input("Enter new status (pending, in_progress, completed, blocked): ")
584
+ result = input("Enter task result (optional): ")
585
+ update_result = project.update_task_status(task_id, status, result if result else None)
586
+ if update_result["status"] == "success":
587
+ print("Task updated successfully.")
588
+ else:
589
+ print(f"Error: {update_result['message']}")
590
+ else:
591
+ print(f"Task '{task_id}' not found.")
592
+
593
+ elif choice == "4":
594
+ project.list_agents()
595
+
596
+ elif choice == "5":
597
+ project.list_agents()
598
+ agent_id = input("\nEnter agent ID to chat with: ")
599
+ if agent_id in project.agents:
600
+ project.interact_with_agent(agent_id)
601
+ else:
602
+ print(f"Agent '{agent_id}' not found.")
603
+
604
+ elif choice == "6":
605
+ project.show_workspace()
606
+
607
+ elif choice == "7":
608
+ project.show_communication()
609
+
610
+ elif choice == "8":
611
+ print("Exiting collaborative project example.")
612
+ break
613
+
614
+ else:
615
+ print("Invalid choice. Please enter a number from 1 to 8.")
616
+
617
+
618
+ if __name__ == "__main__":
619
+ main()