agent-mcp 0.1.4__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.
- agent_mcp/__init__.py +66 -12
- agent_mcp/a2a_protocol.py +316 -0
- agent_mcp/agent_lightning_library.py +214 -0
- agent_mcp/claude_mcp_adapter.py +195 -0
- agent_mcp/google_ai_mcp_adapter.py +183 -0
- agent_mcp/llamaindex_mcp_adapter.py +410 -0
- agent_mcp/microsoft_agent_framework.py +591 -0
- agent_mcp/missing_frameworks.py +435 -0
- agent_mcp/openapi_protocol.py +616 -0
- agent_mcp/payments.py +804 -0
- agent_mcp/pydantic_ai_mcp_adapter.py +628 -0
- agent_mcp/registry.py +768 -0
- agent_mcp/security.py +864 -0
- {agent_mcp-0.1.4.dist-info → agent_mcp-0.1.5.dist-info}/METADATA +174 -52
- {agent_mcp-0.1.4.dist-info → agent_mcp-0.1.5.dist-info}/RECORD +19 -6
- {agent_mcp-0.1.4.dist-info → agent_mcp-0.1.5.dist-info}/WHEEL +1 -1
- agent_mcp-0.1.5.dist-info/entry_points.txt +4 -0
- demos/comprehensive_framework_demo.py +202 -0
- agent_mcp-0.1.4.dist-info/entry_points.txt +0 -2
- {agent_mcp-0.1.4.dist-info → agent_mcp-0.1.5.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,591 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Microsoft Agent Framework Integration
|
|
3
|
+
Combines Semantic Kernel + AutoGen with MCP support
|
|
4
|
+
|
|
5
|
+
This module provides integration with Microsoft's unified agent framework
|
|
6
|
+
that brings together Semantic Kernel and AutoGen capabilities.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import asyncio
|
|
10
|
+
import json
|
|
11
|
+
import uuid
|
|
12
|
+
from typing import Dict, Any, List, Optional, Callable, Union
|
|
13
|
+
from dataclasses import dataclass, asdict
|
|
14
|
+
from datetime import datetime, timezone
|
|
15
|
+
import logging
|
|
16
|
+
|
|
17
|
+
logger = logging.getLogger(__name__)
|
|
18
|
+
|
|
19
|
+
# Try to import Microsoft frameworks
|
|
20
|
+
try:
|
|
21
|
+
import semantic_kernel as sk
|
|
22
|
+
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion, OpenAIChatCompletion
|
|
23
|
+
from semantic_kernel.kernel import Kernel
|
|
24
|
+
from semantic_kernel.planning import SequentialPlanner
|
|
25
|
+
from semantic_kernel.skills.core import TimeSkill
|
|
26
|
+
from semantic_kernel.orchestration import SkillContext
|
|
27
|
+
SEMANTIC_KERNEL_AVAILABLE = True
|
|
28
|
+
except ImportError:
|
|
29
|
+
SEMANTIC_KERNEL_AVAILABLE = False
|
|
30
|
+
sk = None
|
|
31
|
+
Kernel = None
|
|
32
|
+
logger.warning("Semantic Kernel not available. Install with: pip install semantic-kernel")
|
|
33
|
+
|
|
34
|
+
try:
|
|
35
|
+
from autogen import ConversableAgent, Agent, GroupChat, GroupChatManager
|
|
36
|
+
AUTOGEN_AVAILABLE = True
|
|
37
|
+
except ImportError:
|
|
38
|
+
AUTOGEN_AVAILABLE = False
|
|
39
|
+
ConversableAgent = None
|
|
40
|
+
Agent = None
|
|
41
|
+
logger.warning("AutoGen not available. Install with: pip install pyautogen")
|
|
42
|
+
|
|
43
|
+
from .mcp_transport import HTTPTransport
|
|
44
|
+
|
|
45
|
+
@dataclass
|
|
46
|
+
class MicrosoftAgentConfig:
|
|
47
|
+
"""Configuration for Microsoft Agent Framework integration"""
|
|
48
|
+
agent_id: str
|
|
49
|
+
name: str
|
|
50
|
+
description: str
|
|
51
|
+
framework: str = "unified" # "semantic_kernel", "autogen", "unified"
|
|
52
|
+
llm_config: Dict[str, Any] = None
|
|
53
|
+
skills: List[str] = None
|
|
54
|
+
mcp_server_url: str = "https://mcp-server-ixlfhxquwq-ew.a.run.app"
|
|
55
|
+
enable_monitoring: bool = True
|
|
56
|
+
enable_compliance: bool = True
|
|
57
|
+
|
|
58
|
+
def __post_init__(self):
|
|
59
|
+
if self.skills is None:
|
|
60
|
+
self.skills = []
|
|
61
|
+
if self.llm_config is None:
|
|
62
|
+
self.llm_config = {}
|
|
63
|
+
|
|
64
|
+
class MicrosoftMCPAgent:
|
|
65
|
+
"""Microsoft Agent with MCP capabilities"""
|
|
66
|
+
|
|
67
|
+
def __init__(
|
|
68
|
+
self,
|
|
69
|
+
config: MicrosoftAgentConfig,
|
|
70
|
+
transport: HTTPTransport = None
|
|
71
|
+
):
|
|
72
|
+
self.config = config
|
|
73
|
+
self.transport = transport or HTTPTransport.from_url(config.mcp_server_url)
|
|
74
|
+
self.mcp_id = config.agent_id
|
|
75
|
+
self.mcp_version = "0.1.0"
|
|
76
|
+
self.mcp_tools = {}
|
|
77
|
+
|
|
78
|
+
# Initialize Microsoft frameworks
|
|
79
|
+
self.kernel = None
|
|
80
|
+
self.autogen_agent = None
|
|
81
|
+
self.group_chat = None
|
|
82
|
+
|
|
83
|
+
# Setup based on framework choice
|
|
84
|
+
if config.framework in ["semantic_kernel", "unified"] and SEMANTIC_KERNEL_AVAILABLE:
|
|
85
|
+
self._setup_semantic_kernel()
|
|
86
|
+
|
|
87
|
+
if config.framework in ["autogen", "unified"] and AUTOGEN_AVAILABLE:
|
|
88
|
+
self._setup_autogen()
|
|
89
|
+
|
|
90
|
+
# Register MCP tools
|
|
91
|
+
self._register_default_mcp_tools()
|
|
92
|
+
|
|
93
|
+
def _setup_semantic_kernel(self):
|
|
94
|
+
"""Setup Semantic Kernel"""
|
|
95
|
+
try:
|
|
96
|
+
self.kernel = Kernel()
|
|
97
|
+
|
|
98
|
+
# Add LLM based on config
|
|
99
|
+
llm_config = self.config.llm_config
|
|
100
|
+
if llm_config.get("api_type") == "azure":
|
|
101
|
+
self.kernel.add_chat_service(
|
|
102
|
+
"azure_openai",
|
|
103
|
+
AzureChatCompletion(
|
|
104
|
+
deployment_name=llm_config.get("deployment_name", "gpt-35-turbo"),
|
|
105
|
+
endpoint=llm_config.get("endpoint"),
|
|
106
|
+
api_key=llm_config.get("api_key")
|
|
107
|
+
)
|
|
108
|
+
)
|
|
109
|
+
else:
|
|
110
|
+
self.kernel.add_chat_service(
|
|
111
|
+
"openai",
|
|
112
|
+
OpenAIChatCompletion(
|
|
113
|
+
ai_model_id=llm_config.get("model", "gpt-3.5-turbo"),
|
|
114
|
+
api_key=llm_config.get("api_key")
|
|
115
|
+
)
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
# Add default skills
|
|
119
|
+
self.kernel.import_skill(TimeSkill(), "TimeSkill")
|
|
120
|
+
|
|
121
|
+
# Add custom skills from config
|
|
122
|
+
for skill_name in self.config.skills:
|
|
123
|
+
try:
|
|
124
|
+
# Try to import and add skill
|
|
125
|
+
skill = self._load_skill(skill_name)
|
|
126
|
+
if skill:
|
|
127
|
+
self.kernel.import_skill(skill, skill_name)
|
|
128
|
+
logger.info(f"Added Semantic Kernel skill: {skill_name}")
|
|
129
|
+
except Exception as e:
|
|
130
|
+
logger.error(f"Failed to load skill {skill_name}: {e}")
|
|
131
|
+
|
|
132
|
+
except Exception as e:
|
|
133
|
+
logger.error(f"Error setting up Semantic Kernel: {e}")
|
|
134
|
+
|
|
135
|
+
def _setup_autogen(self):
|
|
136
|
+
"""Setup AutoGen agent"""
|
|
137
|
+
try:
|
|
138
|
+
llm_config = self.config.llm_config
|
|
139
|
+
|
|
140
|
+
# AutoGen LLM config format
|
|
141
|
+
autogen_config = {
|
|
142
|
+
"model": llm_config.get("model", "gpt-3.5-turbo"),
|
|
143
|
+
"api_key": llm_config.get("api_key"),
|
|
144
|
+
"temperature": llm_config.get("temperature", 0.7)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if llm_config.get("api_type") == "azure":
|
|
148
|
+
autogen_config.update({
|
|
149
|
+
"base_url": llm_config.get("endpoint"),
|
|
150
|
+
"api_version": "2023-12-01-preview",
|
|
151
|
+
"deployment_name": llm_config.get("deployment_name")
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
self.autogen_agent = ConversableAgent(
|
|
155
|
+
name=self.config.name,
|
|
156
|
+
llm_config=autogen_config,
|
|
157
|
+
system_message=self.config.description,
|
|
158
|
+
human_input_mode="NEVER",
|
|
159
|
+
code_execution_config=False,
|
|
160
|
+
max_consecutive_auto_reply=3
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
logger.info(f"Created AutoGen agent: {self.config.name}")
|
|
164
|
+
|
|
165
|
+
except Exception as e:
|
|
166
|
+
logger.error(f"Error setting up AutoGen: {e}")
|
|
167
|
+
|
|
168
|
+
def _load_skill(self, skill_name: str):
|
|
169
|
+
"""Load a Semantic Kernel skill by name"""
|
|
170
|
+
# This is a placeholder for skill loading logic
|
|
171
|
+
# In practice, this would load from various sources
|
|
172
|
+
|
|
173
|
+
if skill_name == "WebSearch":
|
|
174
|
+
return self._create_web_search_skill()
|
|
175
|
+
elif skill_name == "FileIO":
|
|
176
|
+
return self._create_file_io_skill()
|
|
177
|
+
else:
|
|
178
|
+
return None
|
|
179
|
+
|
|
180
|
+
def _create_web_search_skill(self):
|
|
181
|
+
"""Create a web search skill for Semantic Kernel"""
|
|
182
|
+
@sk.sk_function(description="Search the web for information")
|
|
183
|
+
async def search_web(query: str) -> str:
|
|
184
|
+
try:
|
|
185
|
+
import aiohttp
|
|
186
|
+
async with aiohttp.ClientSession() as session:
|
|
187
|
+
# Use a search API (placeholder)
|
|
188
|
+
url = f"https://api.duckduckgo.com/?q={query}&format=json"
|
|
189
|
+
async with session.get(url) as response:
|
|
190
|
+
data = await response.json()
|
|
191
|
+
results = data.get("AbstractText", "No results found")
|
|
192
|
+
return str(results)
|
|
193
|
+
except Exception as e:
|
|
194
|
+
return f"Search error: {e}"
|
|
195
|
+
|
|
196
|
+
return search_web
|
|
197
|
+
|
|
198
|
+
def _create_file_io_skill(self):
|
|
199
|
+
"""Create a file I/O skill for Semantic Kernel"""
|
|
200
|
+
@sk.sk_function(description="Read a file")
|
|
201
|
+
def read_file(file_path: str) -> str:
|
|
202
|
+
try:
|
|
203
|
+
with open(file_path, 'r') as f:
|
|
204
|
+
return f.read()
|
|
205
|
+
except Exception as e:
|
|
206
|
+
return f"Error reading file: {e}"
|
|
207
|
+
|
|
208
|
+
return read_file
|
|
209
|
+
|
|
210
|
+
def _register_default_mcp_tools(self):
|
|
211
|
+
"""Register default MCP tools for Microsoft Agent"""
|
|
212
|
+
|
|
213
|
+
# Semantic Kernel tools
|
|
214
|
+
if self.kernel:
|
|
215
|
+
self._register_kernel_tools_as_mcp()
|
|
216
|
+
|
|
217
|
+
# AutoGen tools
|
|
218
|
+
if self.autogen_agent:
|
|
219
|
+
self._register_autogen_tools_as_mcp()
|
|
220
|
+
|
|
221
|
+
# Unified Microsoft tools
|
|
222
|
+
self._register_microsoft_tools_as_mcp()
|
|
223
|
+
|
|
224
|
+
def _register_kernel_tools_as_mcp(self):
|
|
225
|
+
"""Register Semantic Kernel skills as MCP tools"""
|
|
226
|
+
if not self.kernel:
|
|
227
|
+
return
|
|
228
|
+
|
|
229
|
+
# Register each available skill
|
|
230
|
+
for skill_name, skill in self.kernel.skills.items():
|
|
231
|
+
for function_name, function in skill.items():
|
|
232
|
+
mcp_tool_name = f"sk_{skill_name}_{function_name}"
|
|
233
|
+
|
|
234
|
+
async def kernel_tool_wrapper(**kwargs):
|
|
235
|
+
"""Wrapper to call Semantic Kernel function"""
|
|
236
|
+
try:
|
|
237
|
+
context = SkillContext()
|
|
238
|
+
result = await function.invoke_async(context=context, **kwargs)
|
|
239
|
+
return {
|
|
240
|
+
"status": "success",
|
|
241
|
+
"result": str(result),
|
|
242
|
+
"tool_name": mcp_tool_name,
|
|
243
|
+
"framework": "semantic_kernel"
|
|
244
|
+
}
|
|
245
|
+
except Exception as e:
|
|
246
|
+
logger.error(f"Error in Semantic Kernel tool {mcp_tool_name}: {e}")
|
|
247
|
+
return {
|
|
248
|
+
"status": "error",
|
|
249
|
+
"message": str(e),
|
|
250
|
+
"tool_name": mcp_tool_name
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
self.mcp_tools[mcp_tool_name] = {
|
|
254
|
+
"name": mcp_tool_name,
|
|
255
|
+
"description": function.description or f"Semantic Kernel {function_name}",
|
|
256
|
+
"parameters": self._extract_kernel_function_parameters(function),
|
|
257
|
+
"function": kernel_tool_wrapper
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
def _register_autogen_tools_as_mcp(self):
|
|
261
|
+
"""Register AutoGen agent capabilities as MCP tools"""
|
|
262
|
+
if not self.autogen_agent:
|
|
263
|
+
return
|
|
264
|
+
|
|
265
|
+
async def autogen_send_message(message: str, target_agent: str = None) -> Dict[str, Any]:
|
|
266
|
+
"""Send a message through AutoGen"""
|
|
267
|
+
try:
|
|
268
|
+
if target_agent:
|
|
269
|
+
# Send to specific agent
|
|
270
|
+
response = await self.autogen_agent.a_generate_reply(
|
|
271
|
+
[{"content": message, "role": "user"}]
|
|
272
|
+
)
|
|
273
|
+
else:
|
|
274
|
+
# Internal message processing
|
|
275
|
+
response = await self.autogen_agent.a_generate_reply(
|
|
276
|
+
[{"content": message, "role": "user"}]
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
return {
|
|
280
|
+
"status": "success",
|
|
281
|
+
"result": response,
|
|
282
|
+
"tool_name": "autogen_send_message",
|
|
283
|
+
"framework": "autogen"
|
|
284
|
+
}
|
|
285
|
+
except Exception as e:
|
|
286
|
+
logger.error(f"Error in AutoGen tool: {e}")
|
|
287
|
+
return {
|
|
288
|
+
"status": "error",
|
|
289
|
+
"message": str(e),
|
|
290
|
+
"tool_name": "autogen_send_message"
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
self.mcp_tools["autogen_send_message"] = {
|
|
294
|
+
"name": "autogen_send_message",
|
|
295
|
+
"description": "Send a message using AutoGen framework",
|
|
296
|
+
"parameters": [
|
|
297
|
+
{
|
|
298
|
+
"name": "message",
|
|
299
|
+
"description": "The message to send",
|
|
300
|
+
"type": "string",
|
|
301
|
+
"required": True
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
"name": "target_agent",
|
|
305
|
+
"description": "Optional target agent name",
|
|
306
|
+
"type": "string",
|
|
307
|
+
"required": False
|
|
308
|
+
}
|
|
309
|
+
],
|
|
310
|
+
"function": autogen_send_message
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
def _register_microsoft_tools_as_mcp(self):
|
|
314
|
+
"""Register Microsoft-specific MCP tools"""
|
|
315
|
+
|
|
316
|
+
async def get_agent_capabilities() -> Dict[str, Any]:
|
|
317
|
+
"""Get capabilities of this Microsoft Agent"""
|
|
318
|
+
capabilities = {
|
|
319
|
+
"framework": self.config.framework,
|
|
320
|
+
"semantic_kernel_available": self.kernel is not None,
|
|
321
|
+
"autogen_available": self.autogen_agent is not None,
|
|
322
|
+
"skills": self.config.skills,
|
|
323
|
+
"tools": list(self.mcp_tools.keys())
|
|
324
|
+
}
|
|
325
|
+
return {
|
|
326
|
+
"status": "success",
|
|
327
|
+
"result": capabilities,
|
|
328
|
+
"agent_id": self.mcp_id
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
self.mcp_tools["get_agent_capabilities"] = {
|
|
332
|
+
"name": "get_agent_capabilities",
|
|
333
|
+
"description": "Get capabilities and configuration of this Microsoft Agent",
|
|
334
|
+
"parameters": [],
|
|
335
|
+
"function": get_agent_capabilities
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
async def execute_skill(skill_name: str, parameters: Dict[str, Any] = None) -> Dict[str, Any]:
|
|
339
|
+
"""Execute a Semantic Kernel skill"""
|
|
340
|
+
if not self.kernel:
|
|
341
|
+
return {"status": "error", "message": "Semantic Kernel not available"}
|
|
342
|
+
|
|
343
|
+
try:
|
|
344
|
+
context = SkillContext()
|
|
345
|
+
skill_function = self.kernel.skills.get_function(skill_name)
|
|
346
|
+
if not skill_function:
|
|
347
|
+
return {"status": "error", "message": f"Skill {skill_name} not found"}
|
|
348
|
+
|
|
349
|
+
result = await skill_function.invoke_async(
|
|
350
|
+
context=context,
|
|
351
|
+
**(parameters or {})
|
|
352
|
+
)
|
|
353
|
+
|
|
354
|
+
return {
|
|
355
|
+
"status": "success",
|
|
356
|
+
"result": str(result),
|
|
357
|
+
"skill_name": skill_name
|
|
358
|
+
}
|
|
359
|
+
except Exception as e:
|
|
360
|
+
logger.error(f"Error executing skill {skill_name}: {e}")
|
|
361
|
+
return {
|
|
362
|
+
"status": "error",
|
|
363
|
+
"message": str(e),
|
|
364
|
+
"skill_name": skill_name
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
self.mcp_tools["execute_skill"] = {
|
|
368
|
+
"name": "execute_skill",
|
|
369
|
+
"description": "Execute a Semantic Kernel skill",
|
|
370
|
+
"parameters": [
|
|
371
|
+
{
|
|
372
|
+
"name": "skill_name",
|
|
373
|
+
"description": "Name of the skill to execute",
|
|
374
|
+
"type": "string",
|
|
375
|
+
"required": True
|
|
376
|
+
},
|
|
377
|
+
{
|
|
378
|
+
"name": "parameters",
|
|
379
|
+
"description": "Parameters for the skill",
|
|
380
|
+
"type": "object",
|
|
381
|
+
"required": False
|
|
382
|
+
}
|
|
383
|
+
],
|
|
384
|
+
"function": execute_skill
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
def _extract_kernel_function_parameters(self, function) -> List[Dict[str, Any]]:
|
|
388
|
+
"""Extract parameters from Semantic Kernel function"""
|
|
389
|
+
parameters = []
|
|
390
|
+
|
|
391
|
+
if hasattr(function, 'parameters') and function.parameters:
|
|
392
|
+
for param_name, param_info in function.parameters.items():
|
|
393
|
+
parameter = {
|
|
394
|
+
"name": param_name,
|
|
395
|
+
"description": param_info.description or f"Parameter {param_name}",
|
|
396
|
+
"type": "string", # Default to string
|
|
397
|
+
"required": param_info.default_value is None
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
# Try to determine type
|
|
401
|
+
if hasattr(param_info, 'type_info'):
|
|
402
|
+
type_str = str(param_info.type_info)
|
|
403
|
+
if "int" in type_str.lower():
|
|
404
|
+
parameter["type"] = "number"
|
|
405
|
+
elif "bool" in type_str.lower():
|
|
406
|
+
parameter["type"] = "boolean"
|
|
407
|
+
|
|
408
|
+
parameters.append(parameter)
|
|
409
|
+
|
|
410
|
+
return parameters
|
|
411
|
+
|
|
412
|
+
async def register_with_mcp_server(self) -> Dict[str, Any]:
|
|
413
|
+
"""Register this Microsoft Agent with MCP server"""
|
|
414
|
+
registration_data = {
|
|
415
|
+
"agent_id": self.mcp_id,
|
|
416
|
+
"info": {
|
|
417
|
+
"name": self.config.name,
|
|
418
|
+
"description": self.config.description,
|
|
419
|
+
"framework": "Microsoft Agent Framework",
|
|
420
|
+
"framework_type": self.config.framework,
|
|
421
|
+
"capabilities": {
|
|
422
|
+
"semantic_kernel": self.kernel is not None,
|
|
423
|
+
"autogen": self.autogen_agent is not None,
|
|
424
|
+
"skills": self.config.skills,
|
|
425
|
+
"tools": list(self.mcp_tools.keys())
|
|
426
|
+
},
|
|
427
|
+
"version": self.mcp_version,
|
|
428
|
+
"microsoft_features": {
|
|
429
|
+
"monitoring": self.config.enable_monitoring,
|
|
430
|
+
"compliance": self.config.enable_compliance
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
return await self.transport.register_agent(self)
|
|
436
|
+
|
|
437
|
+
async def execute_mcp_tool(self, tool_name: str, **kwargs) -> Dict[str, Any]:
|
|
438
|
+
"""Execute an MCP tool"""
|
|
439
|
+
if tool_name in self.mcp_tools:
|
|
440
|
+
tool_func = self.mcp_tools[tool_name]["function"]
|
|
441
|
+
return await tool_func(**kwargs)
|
|
442
|
+
else:
|
|
443
|
+
return {
|
|
444
|
+
"status": "error",
|
|
445
|
+
"message": f"Tool {tool_name} not found",
|
|
446
|
+
"available_tools": list(self.mcp_tools.keys())
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
async def create_agent_collaboration(
|
|
450
|
+
self,
|
|
451
|
+
other_agents: List['MicrosoftMCPAgent'],
|
|
452
|
+
collaboration_type: str = "group_chat"
|
|
453
|
+
) -> 'AgentGroup':
|
|
454
|
+
"""Create collaboration between Microsoft Agents"""
|
|
455
|
+
|
|
456
|
+
if collaboration_type == "group_chat" and AUTOGEN_AVAILABLE:
|
|
457
|
+
# Create AutoGen group chat
|
|
458
|
+
agents = [self.autogen_agent] + [agent.autogen_agent for agent in other_agents if agent.autogen_agent]
|
|
459
|
+
|
|
460
|
+
if len(agents) > 1:
|
|
461
|
+
self.group_chat = GroupChat(
|
|
462
|
+
agents=agents,
|
|
463
|
+
messages=[],
|
|
464
|
+
max_round=10
|
|
465
|
+
)
|
|
466
|
+
|
|
467
|
+
group_manager = GroupChatManager(
|
|
468
|
+
groupchat=self.group_chat,
|
|
469
|
+
llm_config=self.config.llm_config
|
|
470
|
+
)
|
|
471
|
+
|
|
472
|
+
return AgentGroup(
|
|
473
|
+
type="autogen_group_chat",
|
|
474
|
+
manager=group_manager,
|
|
475
|
+
agents=agents
|
|
476
|
+
)
|
|
477
|
+
|
|
478
|
+
elif collaboration_type == "semantic_kernel_orchestration":
|
|
479
|
+
# Use Semantic Kernel for orchestration
|
|
480
|
+
if self.kernel:
|
|
481
|
+
planner = SequentialPlanner(self.kernel)
|
|
482
|
+
|
|
483
|
+
async def orchestrate_task(task: str) -> Dict[str, Any]:
|
|
484
|
+
try:
|
|
485
|
+
plan = await planner.create_plan_async(task)
|
|
486
|
+
result = await plan.invoke_async()
|
|
487
|
+
return {
|
|
488
|
+
"status": "success",
|
|
489
|
+
"result": str(result),
|
|
490
|
+
"plan_steps": len(plan._steps)
|
|
491
|
+
}
|
|
492
|
+
except Exception as e:
|
|
493
|
+
return {
|
|
494
|
+
"status": "error",
|
|
495
|
+
"message": str(e)
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
return AgentGroup(
|
|
499
|
+
type="semantic_kernel_orchestration",
|
|
500
|
+
planner=planner,
|
|
501
|
+
execute_function=orchestrate_task
|
|
502
|
+
)
|
|
503
|
+
|
|
504
|
+
return None
|
|
505
|
+
|
|
506
|
+
@dataclass
|
|
507
|
+
class AgentGroup:
|
|
508
|
+
"""Represents a group of collaborating agents"""
|
|
509
|
+
type: str
|
|
510
|
+
agents: List[Any] = None
|
|
511
|
+
manager: Any = None
|
|
512
|
+
planner: Any = None
|
|
513
|
+
execute_function: Callable = None
|
|
514
|
+
|
|
515
|
+
class MicrosoftAgentBridge:
|
|
516
|
+
"""Bridge for Microsoft Agent Framework integration with MCP"""
|
|
517
|
+
|
|
518
|
+
def __init__(self, mcp_server_url: str = "https://mcp-server-ixlfhxquwq-ew.a.run.app"):
|
|
519
|
+
self.mcp_server_url = mcp_server_url
|
|
520
|
+
self.agents = {}
|
|
521
|
+
self.groups = {}
|
|
522
|
+
|
|
523
|
+
async def create_agent(
|
|
524
|
+
self,
|
|
525
|
+
agent_id: str,
|
|
526
|
+
name: str,
|
|
527
|
+
description: str,
|
|
528
|
+
framework: str = "unified",
|
|
529
|
+
llm_config: Dict[str, Any] = None,
|
|
530
|
+
skills: List[str] = None
|
|
531
|
+
) -> MicrosoftMCPAgent:
|
|
532
|
+
"""Create and register a Microsoft Agent"""
|
|
533
|
+
|
|
534
|
+
config = MicrosoftAgentConfig(
|
|
535
|
+
agent_id=agent_id,
|
|
536
|
+
name=name,
|
|
537
|
+
description=description,
|
|
538
|
+
framework=framework,
|
|
539
|
+
llm_config=llm_config or {},
|
|
540
|
+
skills=skills or [],
|
|
541
|
+
mcp_server_url=self.mcp_server_url
|
|
542
|
+
)
|
|
543
|
+
|
|
544
|
+
agent = MicrosoftMCPAgent(config)
|
|
545
|
+
|
|
546
|
+
# Register with MCP server
|
|
547
|
+
registration_result = await agent.register_with_mcp_server()
|
|
548
|
+
|
|
549
|
+
if registration_result.get("status") == "registered":
|
|
550
|
+
logger.info(f"Microsoft Agent {agent_id} registered with MCP server")
|
|
551
|
+
self.agents[agent_id] = agent
|
|
552
|
+
else:
|
|
553
|
+
logger.error(f"Failed to register Microsoft Agent {agent_id}: {registration_result}")
|
|
554
|
+
|
|
555
|
+
return agent
|
|
556
|
+
|
|
557
|
+
async def create_collaboration(
|
|
558
|
+
self,
|
|
559
|
+
agent_ids: List[str],
|
|
560
|
+
collaboration_type: str = "group_chat"
|
|
561
|
+
) -> Optional[AgentGroup]:
|
|
562
|
+
"""Create collaboration between agents"""
|
|
563
|
+
|
|
564
|
+
agents = [self.agents[aid] for aid in agent_ids if aid in self.agents]
|
|
565
|
+
|
|
566
|
+
if len(agents) < 2:
|
|
567
|
+
logger.error("Need at least 2 agents for collaboration")
|
|
568
|
+
return None
|
|
569
|
+
|
|
570
|
+
# Use the first agent to create the group
|
|
571
|
+
lead_agent = agents[0]
|
|
572
|
+
other_agents = agents[1:]
|
|
573
|
+
|
|
574
|
+
group = await lead_agent.create_agent_collaboration(
|
|
575
|
+
other_agents, collaboration_type
|
|
576
|
+
)
|
|
577
|
+
|
|
578
|
+
if group:
|
|
579
|
+
group_id = str(uuid.uuid4())
|
|
580
|
+
self.groups[group_id] = group
|
|
581
|
+
logger.info(f"Created {collaboration_type} group with {len(agents)} agents")
|
|
582
|
+
|
|
583
|
+
return group
|
|
584
|
+
|
|
585
|
+
# Export classes for easy importing
|
|
586
|
+
__all__ = [
|
|
587
|
+
'MicrosoftAgentConfig',
|
|
588
|
+
'MicrosoftMCPAgent',
|
|
589
|
+
'AgentGroup',
|
|
590
|
+
'MicrosoftAgentBridge'
|
|
591
|
+
]
|