webagents 0.1.13__py3-none-any.whl → 0.2.2__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.
- webagents/__init__.py +1 -1
- webagents/__main__.py +55 -0
- webagents/agents/__init__.py +1 -1
- webagents/agents/core/__init__.py +1 -1
- webagents/agents/core/base_agent.py +15 -15
- webagents/agents/core/handoffs.py +1 -1
- webagents/agents/skills/__init__.py +11 -11
- webagents/agents/skills/base.py +1 -1
- webagents/agents/skills/core/llm/litellm/__init__.py +1 -1
- webagents/agents/skills/core/llm/litellm/skill.py +1 -1
- webagents/agents/skills/core/mcp/README.md +2 -2
- webagents/agents/skills/core/mcp/skill.py +2 -2
- webagents/agents/skills/core/memory/long_term_memory/memory_skill.py +14 -14
- webagents/agents/skills/core/memory/short_term_memory/__init__.py +1 -1
- webagents/agents/skills/core/memory/short_term_memory/skill.py +1 -1
- webagents/agents/skills/core/memory/vector_memory/skill.py +6 -6
- webagents/agents/skills/core/planning/__init__.py +1 -1
- webagents/agents/skills/ecosystem/crewai/__init__.py +3 -1
- webagents/agents/skills/ecosystem/crewai/skill.py +158 -0
- webagents/agents/skills/ecosystem/database/__init__.py +3 -1
- webagents/agents/skills/ecosystem/database/skill.py +522 -0
- webagents/agents/skills/ecosystem/google/calendar/skill.py +1 -1
- webagents/agents/skills/ecosystem/mongodb/__init__.py +3 -0
- webagents/agents/skills/ecosystem/mongodb/skill.py +428 -0
- webagents/agents/skills/ecosystem/n8n/README.md +287 -0
- webagents/agents/skills/ecosystem/n8n/__init__.py +3 -0
- webagents/agents/skills/ecosystem/n8n/skill.py +341 -0
- webagents/agents/skills/ecosystem/x_com/README.md +401 -0
- webagents/agents/skills/ecosystem/x_com/__init__.py +3 -0
- webagents/agents/skills/ecosystem/x_com/skill.py +1048 -0
- webagents/agents/skills/ecosystem/zapier/README.md +363 -0
- webagents/agents/skills/ecosystem/zapier/__init__.py +3 -0
- webagents/agents/skills/ecosystem/zapier/skill.py +337 -0
- webagents/agents/skills/robutler/__init__.py +2 -2
- webagents/agents/skills/robutler/auth/__init__.py +3 -3
- webagents/agents/skills/robutler/auth/skill.py +16 -16
- webagents/agents/skills/robutler/crm/__init__.py +2 -2
- webagents/agents/skills/robutler/crm/skill.py +5 -5
- webagents/agents/skills/robutler/discovery/README.md +5 -5
- webagents/agents/skills/robutler/discovery/__init__.py +2 -2
- webagents/agents/skills/robutler/discovery/skill.py +21 -21
- webagents/agents/skills/robutler/message_history/__init__.py +2 -2
- webagents/agents/skills/robutler/message_history/skill.py +5 -5
- webagents/agents/skills/robutler/nli/__init__.py +1 -1
- webagents/agents/skills/robutler/nli/skill.py +9 -9
- webagents/agents/skills/robutler/payments/__init__.py +3 -3
- webagents/agents/skills/robutler/payments/exceptions.py +1 -1
- webagents/agents/skills/robutler/payments/skill.py +23 -23
- webagents/agents/skills/robutler/storage/__init__.py +2 -2
- webagents/agents/skills/robutler/storage/files/__init__.py +2 -2
- webagents/agents/skills/robutler/storage/files/skill.py +4 -4
- webagents/agents/skills/robutler/storage/json/__init__.py +1 -1
- webagents/agents/skills/robutler/storage/json/skill.py +3 -3
- webagents/agents/skills/robutler/storage/kv/skill.py +3 -3
- webagents/agents/skills/robutler/storage.py +6 -6
- webagents/agents/tools/decorators.py +12 -12
- webagents/server/__init__.py +3 -3
- webagents/server/context/context_vars.py +2 -2
- webagents/server/core/app.py +13 -13
- webagents/server/core/middleware.py +3 -3
- webagents/server/core/models.py +1 -1
- webagents/server/core/monitoring.py +2 -2
- webagents/server/middleware.py +1 -1
- webagents/server/models.py +2 -2
- webagents/server/monitoring.py +15 -15
- webagents/utils/logging.py +20 -20
- webagents-0.2.2.dist-info/METADATA +266 -0
- webagents-0.2.2.dist-info/RECORD +105 -0
- webagents-0.2.2.dist-info/licenses/LICENSE +20 -0
- webagents/api/__init__.py +0 -17
- webagents/api/client.py +0 -1207
- webagents/api/types.py +0 -253
- webagents-0.1.13.dist-info/METADATA +0 -32
- webagents-0.1.13.dist-info/RECORD +0 -96
- webagents-0.1.13.dist-info/licenses/LICENSE +0 -1
- {webagents-0.1.13.dist-info → webagents-0.2.2.dist-info}/WHEEL +0 -0
- {webagents-0.1.13.dist-info → webagents-0.2.2.dist-info}/entry_points.txt +0 -0
webagents/__init__.py
CHANGED
webagents/__main__.py
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
"""
|
3
|
+
WebAgents CLI Entry Point
|
4
|
+
|
5
|
+
Command-line interface for the WebAgents framework.
|
6
|
+
"""
|
7
|
+
|
8
|
+
import sys
|
9
|
+
import argparse
|
10
|
+
from webagents.server.core.app import WebAgentsServer
|
11
|
+
from webagents.utils.logging import setup_logging
|
12
|
+
|
13
|
+
|
14
|
+
def main():
|
15
|
+
"""Main entry point for the webagents CLI."""
|
16
|
+
parser = argparse.ArgumentParser(description="WebAgents - AI Agent Framework")
|
17
|
+
parser.add_argument(
|
18
|
+
"--server",
|
19
|
+
action="store_true",
|
20
|
+
help="Start the WebAgents server"
|
21
|
+
)
|
22
|
+
parser.add_argument(
|
23
|
+
"--port",
|
24
|
+
type=int,
|
25
|
+
default=8000,
|
26
|
+
help="Port to run the server on (default: 8000)"
|
27
|
+
)
|
28
|
+
parser.add_argument(
|
29
|
+
"--host",
|
30
|
+
default="0.0.0.0",
|
31
|
+
help="Host to bind the server to (default: 0.0.0.0)"
|
32
|
+
)
|
33
|
+
parser.add_argument(
|
34
|
+
"--debug",
|
35
|
+
action="store_true",
|
36
|
+
help="Enable debug logging"
|
37
|
+
)
|
38
|
+
|
39
|
+
args = parser.parse_args()
|
40
|
+
|
41
|
+
# Setup logging
|
42
|
+
setup_logging(debug=args.debug)
|
43
|
+
|
44
|
+
if args.server:
|
45
|
+
# Start the server
|
46
|
+
server = WebAgentsServer()
|
47
|
+
server.run(host=args.host, port=args.port)
|
48
|
+
else:
|
49
|
+
print("WebAgents - AI Agent Framework")
|
50
|
+
print("Use --server to start the server")
|
51
|
+
print("Use --help for more options")
|
52
|
+
|
53
|
+
|
54
|
+
if __name__ == "__main__":
|
55
|
+
main()
|
webagents/agents/__init__.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
"""
|
2
|
-
BaseAgent -
|
2
|
+
BaseAgent - WebAgents V2.0 Core Agent Implementation
|
3
3
|
|
4
4
|
Central agent implementation with automatic decorator registration,
|
5
5
|
unified context management, and comprehensive tool/hook/handoff execution.
|
@@ -158,7 +158,7 @@ class BaseAgent:
|
|
158
158
|
level = getattr(logging, log_level, logging.INFO)
|
159
159
|
# If using a LoggerAdapter (e.g., AgentContextAdapter), operate on the underlying logger
|
160
160
|
base_logger = self.logger.logger if isinstance(self.logger, logging.LoggerAdapter) else self.logger
|
161
|
-
# Set desired level and let it propagate to '
|
161
|
+
# Set desired level and let it propagate to 'webagents' logger configured by setup_logging
|
162
162
|
base_logger.setLevel(level)
|
163
163
|
base_logger.propagate = True
|
164
164
|
|
@@ -218,7 +218,7 @@ class BaseAgent:
|
|
218
218
|
# For agent-level tools, inheritance logic:
|
219
219
|
# - Decorated tools (@tool) keep their own scope (even default "all")
|
220
220
|
# - Undecorated tools inherit agent scopes
|
221
|
-
if hasattr(tool_func, '
|
221
|
+
if hasattr(tool_func, '_webagents_is_tool') and tool_func._webagents_is_tool:
|
222
222
|
# Tool is decorated - keep its own scope
|
223
223
|
scope = tool_func._tool_scope
|
224
224
|
else:
|
@@ -253,7 +253,7 @@ class BaseAgent:
|
|
253
253
|
# Direct Handoff object
|
254
254
|
self.register_handoff(handoff_item, source="agent")
|
255
255
|
self.logger.debug(f"📨 Registered handoff target='{handoff_item.target}' type='{handoff_item.handoff_type}'")
|
256
|
-
elif callable(handoff_item) and hasattr(handoff_item, '
|
256
|
+
elif callable(handoff_item) and hasattr(handoff_item, '_webagents_is_handoff'):
|
257
257
|
# Function with @handoff decorator
|
258
258
|
handoff_config = Handoff(
|
259
259
|
target=getattr(handoff_item, '_handoff_name', handoff_item.__name__),
|
@@ -277,13 +277,13 @@ class BaseAgent:
|
|
277
277
|
for capability_func in capabilities:
|
278
278
|
if callable(capability_func):
|
279
279
|
# Attempt to determine decorator type
|
280
|
-
if hasattr(capability_func, '
|
280
|
+
if hasattr(capability_func, '_webagents_is_tool') and capability_func._webagents_is_tool:
|
281
281
|
self.register_tool(capability_func, source="agent")
|
282
|
-
elif hasattr(capability_func, '
|
282
|
+
elif hasattr(capability_func, '_webagents_is_hook') and capability_func._webagents_is_hook:
|
283
283
|
priority = getattr(capability_func, '_hook_priority', 50)
|
284
284
|
scope = getattr(capability_func, '_hook_scope', self.scopes)
|
285
285
|
self.register_hook(getattr(capability_func, '_hook_event_type', 'on_request'), capability_func, priority, source="agent", scope=scope)
|
286
|
-
elif hasattr(capability_func, '
|
286
|
+
elif hasattr(capability_func, '_webagents_is_handoff') and capability_func._webagents_is_handoff:
|
287
287
|
handoff_config = Handoff(
|
288
288
|
target=getattr(capability_func, '_handoff_name', capability_func.__name__),
|
289
289
|
handoff_type=getattr(capability_func, '_handoff_type', 'agent'),
|
@@ -292,7 +292,7 @@ class BaseAgent:
|
|
292
292
|
)
|
293
293
|
handoff_config.metadata = {'function': capability_func}
|
294
294
|
self.register_handoff(handoff_config, source="agent")
|
295
|
-
elif hasattr(capability_func, '
|
295
|
+
elif hasattr(capability_func, '_webagents_is_http') and capability_func._webagents_is_http:
|
296
296
|
self.register_http_handler(capability_func)
|
297
297
|
self.logger.debug(f"🌐 Registered HTTP capability subpath='{getattr(capability_func, '_http_subpath', '<unknown>')}' method='{getattr(capability_func, '_http_method', 'get')}'")
|
298
298
|
|
@@ -360,25 +360,25 @@ class BaseAgent:
|
|
360
360
|
continue
|
361
361
|
|
362
362
|
# Check for @hook decorator
|
363
|
-
if hasattr(attr, '
|
363
|
+
if hasattr(attr, '_webagents_is_hook') and attr._webagents_is_hook:
|
364
364
|
event_type = attr._hook_event_type
|
365
365
|
priority = getattr(attr, '_hook_priority', 50)
|
366
366
|
scope = getattr(attr, '_hook_scope', None)
|
367
367
|
self.register_hook(event_type, attr, priority, source=skill_name, scope=scope)
|
368
368
|
|
369
369
|
# Check for @tool decorator
|
370
|
-
elif hasattr(attr, '
|
370
|
+
elif hasattr(attr, '_webagents_is_tool') and attr._webagents_is_tool:
|
371
371
|
scope = getattr(attr, '_tool_scope', None)
|
372
372
|
self.register_tool(attr, source=skill_name, scope=scope)
|
373
373
|
|
374
374
|
# Check for @prompt decorator
|
375
|
-
elif hasattr(attr, '
|
375
|
+
elif hasattr(attr, '_webagents_is_prompt') and attr._webagents_is_prompt:
|
376
376
|
priority = getattr(attr, '_prompt_priority', 50)
|
377
377
|
scope = getattr(attr, '_prompt_scope', None)
|
378
378
|
self.register_prompt(attr, priority, source=skill_name, scope=scope)
|
379
379
|
|
380
380
|
# Check for @handoff decorator
|
381
|
-
elif hasattr(attr, '
|
381
|
+
elif hasattr(attr, '_webagents_is_handoff') and attr._webagents_is_handoff:
|
382
382
|
handoff_config = Handoff(
|
383
383
|
target=getattr(attr, '_handoff_name', attr_name),
|
384
384
|
handoff_type=getattr(attr, '_handoff_type', 'agent'),
|
@@ -389,7 +389,7 @@ class BaseAgent:
|
|
389
389
|
self.register_handoff(handoff_config, source=skill_name)
|
390
390
|
|
391
391
|
# Check for @http decorator
|
392
|
-
elif hasattr(attr, '
|
392
|
+
elif hasattr(attr, '_webagents_is_http') and attr._webagents_is_http:
|
393
393
|
self.register_http_handler(attr, source=skill_name)
|
394
394
|
|
395
395
|
# Central registration methods (thread-safe)
|
@@ -402,7 +402,7 @@ class BaseAgent:
|
|
402
402
|
'scope': scope,
|
403
403
|
'name': getattr(tool_func, '_tool_name', tool_func.__name__),
|
404
404
|
'description': getattr(tool_func, '_tool_description', tool_func.__doc__ or ''),
|
405
|
-
'definition': getattr(tool_func, '
|
405
|
+
'definition': getattr(tool_func, '_webagents_tool_definition', {})
|
406
406
|
}
|
407
407
|
self._registered_tools.append(tool_config)
|
408
408
|
self.logger.debug(f"🛠️ Tool registered name='{tool_config['name']}' source='{source}' scope={scope}")
|
@@ -451,7 +451,7 @@ class BaseAgent:
|
|
451
451
|
|
452
452
|
def register_http_handler(self, handler_func: Callable, source: str = "manual"):
|
453
453
|
"""Register an HTTP handler function with conflict detection"""
|
454
|
-
if not hasattr(handler_func, '
|
454
|
+
if not hasattr(handler_func, '_webagents_is_http'):
|
455
455
|
raise ValueError(f"Function {handler_func.__name__} is not decorated with @http")
|
456
456
|
|
457
457
|
subpath = getattr(handler_func, '_http_subpath')
|
@@ -1,7 +1,7 @@
|
|
1
1
|
"""
|
2
|
-
|
2
|
+
WebAgents Agents Skills
|
3
3
|
|
4
|
-
This module provides the skill system for
|
4
|
+
This module provides the skill system for WebAgents agents, including core skills,
|
5
5
|
platform skills, and ecosystem skills. Skills are modular components that provide
|
6
6
|
specific functionality to agents.
|
7
7
|
"""
|
@@ -16,10 +16,10 @@ CORE_SKILLS = {
|
|
16
16
|
"litellm": LiteLLMSkill,
|
17
17
|
}
|
18
18
|
|
19
|
-
# Import
|
19
|
+
# Import WebAgents platform skills
|
20
20
|
from .robutler.crm import CRMAnalyticsSkill
|
21
21
|
|
22
|
-
#
|
22
|
+
# WebAgents platform skills - these integrate with WebAgents services
|
23
23
|
ROBUTLER_SKILLS = {
|
24
24
|
"crm": CRMAnalyticsSkill,
|
25
25
|
"analytics": CRMAnalyticsSkill, # Alias for convenience
|
@@ -74,13 +74,13 @@ def get_skill(skill_name: str):
|
|
74
74
|
|
75
75
|
# Lazy load ecosystem skills
|
76
76
|
ecosystem_imports = {
|
77
|
-
"google": ("
|
78
|
-
"database": ("
|
79
|
-
"filesystem": ("
|
80
|
-
"web": ("
|
81
|
-
"crewai": ("
|
82
|
-
"n8n": ("
|
83
|
-
"zapier": ("
|
77
|
+
"google": ("webagents.agents.skills.ecosystem.google", "GoogleSkill"),
|
78
|
+
"database": ("webagents.agents.skills.ecosystem.database", "DatabaseSkill"),
|
79
|
+
"filesystem": ("webagents.agents.skills.ecosystem.filesystem", "FilesystemSkill"),
|
80
|
+
"web": ("webagents.agents.skills.ecosystem.web", "WebSkill"),
|
81
|
+
"crewai": ("webagents.agents.skills.ecosystem.crewai", "CrewAISkill"),
|
82
|
+
"n8n": ("webagents.agents.skills.ecosystem.n8n", "N8nSkill"),
|
83
|
+
"zapier": ("webagents.agents.skills.ecosystem.zapier", "ZapierSkill"),
|
84
84
|
}
|
85
85
|
|
86
86
|
if skill_name in ecosystem_imports:
|
webagents/agents/skills/base.py
CHANGED
@@ -63,8 +63,8 @@ The `MCPSkill` provides comprehensive **Model Context Protocol (MCP) integration
|
|
63
63
|
### Basic Configuration
|
64
64
|
|
65
65
|
```python
|
66
|
-
from
|
67
|
-
from
|
66
|
+
from webagents.agents import BaseAgent
|
67
|
+
from webagents.agents.skills.core.mcp import MCPSkill
|
68
68
|
|
69
69
|
# Configure MCP skill with servers
|
70
70
|
mcp_config = {
|
@@ -346,7 +346,7 @@ class MCPSkill(Skill):
|
|
346
346
|
|
347
347
|
# Set tool attributes for registration
|
348
348
|
dynamic_tool_func.__name__ = dynamic_tool_name
|
349
|
-
dynamic_tool_func.
|
349
|
+
dynamic_tool_func._webagents_is_tool = True
|
350
350
|
dynamic_tool_func._tool_scope = "all"
|
351
351
|
|
352
352
|
# Convert MCP tool schema to OpenAI format
|
@@ -362,7 +362,7 @@ class MCPSkill(Skill):
|
|
362
362
|
}
|
363
363
|
}
|
364
364
|
|
365
|
-
dynamic_tool_func.
|
365
|
+
dynamic_tool_func._webagents_tool_definition = openai_schema
|
366
366
|
|
367
367
|
# Store and register the dynamic tool
|
368
368
|
self.dynamic_tools[dynamic_tool_name] = dynamic_tool_func
|
@@ -2,7 +2,7 @@
|
|
2
2
|
LongTermMemorySkill - Persistent Memory Management
|
3
3
|
|
4
4
|
Automatically extracts and stores key facts, preferences, and context
|
5
|
-
from conversations for future reference using
|
5
|
+
from conversations for future reference using WebAgents portal storage
|
6
6
|
via dependencies.
|
7
7
|
"""
|
8
8
|
|
@@ -37,7 +37,7 @@ class MemoryItem:
|
|
37
37
|
|
38
38
|
class LongTermMemorySkill(Skill):
|
39
39
|
"""
|
40
|
-
Long-term memory management skill with
|
40
|
+
Long-term memory management skill with webagents portal integration via dependencies.
|
41
41
|
|
42
42
|
Features:
|
43
43
|
- Automatic memory extraction from conversations
|
@@ -45,14 +45,14 @@ class LongTermMemorySkill(Skill):
|
|
45
45
|
- Importance scoring and prioritization
|
46
46
|
- Searchable memory retrieval
|
47
47
|
- Memory cleanup and maintenance
|
48
|
-
- Integration with
|
48
|
+
- Integration with webagents portal storage via dependencies
|
49
49
|
"""
|
50
50
|
|
51
51
|
def __init__(self, config: Optional[Dict[str, Any]] = None):
|
52
52
|
super().__init__(config)
|
53
53
|
self.max_memories = config.get('max_memories', 100) if config else 100
|
54
54
|
self.auto_extract = config.get('auto_extract', True) if config else True
|
55
|
-
self.
|
55
|
+
self.use_webagents_storage = config.get('use_webagents_storage', True) if config else True
|
56
56
|
self.fallback_file = config.get('fallback_file', '/tmp/agent_memory.json') if config else '/tmp/agent_memory.json'
|
57
57
|
self.memories: Dict[str, MemoryItem] = {}
|
58
58
|
self.agent_name = config.get('agent_name', 'default_agent') if config else 'default_agent'
|
@@ -71,8 +71,8 @@ class LongTermMemorySkill(Skill):
|
|
71
71
|
self.agent_name = agent_reference.name
|
72
72
|
|
73
73
|
# Get JSON storage from dependencies
|
74
|
-
if '
|
75
|
-
self.storage = self.dependencies['
|
74
|
+
if 'webagents.json_storage' in self.dependencies:
|
75
|
+
self.storage = self.dependencies['webagents.json_storage']
|
76
76
|
elif hasattr(agent_reference, 'skills') and 'json_storage' in agent_reference.skills:
|
77
77
|
# Fallback to agent skills
|
78
78
|
self.storage = agent_reference.skills['json_storage']
|
@@ -267,7 +267,7 @@ EXAMPLE TRIGGERS:
|
|
267
267
|
# Sort by importance and access count
|
268
268
|
filtered_memories.sort(key=lambda x: (x['importance'], x['access_count']), reverse=True)
|
269
269
|
|
270
|
-
storage_location = "
|
270
|
+
storage_location = "webagents_json_storage" if self.storage else "local_file"
|
271
271
|
|
272
272
|
return json.dumps({
|
273
273
|
"total_memories": len(self.memories),
|
@@ -392,7 +392,7 @@ EXAMPLE TRIGGERS:
|
|
392
392
|
JSON string with memory statistics
|
393
393
|
"""
|
394
394
|
try:
|
395
|
-
storage_location = "
|
395
|
+
storage_location = "webagents_json_storage" if self.storage else "local_file"
|
396
396
|
|
397
397
|
if not self.memories:
|
398
398
|
return json.dumps({
|
@@ -548,7 +548,7 @@ EXAMPLE TRIGGERS:
|
|
548
548
|
async def _load_memories(self):
|
549
549
|
"""Load memories from storage"""
|
550
550
|
try:
|
551
|
-
if self.
|
551
|
+
if self.use_webagents_storage and self.storage:
|
552
552
|
# Try to load from webagents JSON storage
|
553
553
|
result = await self.storage.retrieve_json_data(f"{self.agent_name}_memory.json")
|
554
554
|
result_data = json.loads(result)
|
@@ -584,8 +584,8 @@ EXAMPLE TRIGGERS:
|
|
584
584
|
}
|
585
585
|
}
|
586
586
|
|
587
|
-
if self.
|
588
|
-
# Try to save to
|
587
|
+
if self.use_webagents_storage and self.storage:
|
588
|
+
# Try to save to webagents JSON storage
|
589
589
|
result = await self.storage.store_json_data(
|
590
590
|
f"{self.agent_name}_memory.json",
|
591
591
|
data,
|
@@ -608,7 +608,7 @@ EXAMPLE TRIGGERS:
|
|
608
608
|
"""Get comprehensive skill information"""
|
609
609
|
return {
|
610
610
|
"name": "LongTermMemorySkill",
|
611
|
-
"description": "Persistent long-term memory with
|
611
|
+
"description": "Persistent long-term memory with webagents JSON storage via dependencies",
|
612
612
|
"version": "3.0.0",
|
613
613
|
"capabilities": [
|
614
614
|
"Automatic memory extraction from conversations",
|
@@ -616,7 +616,7 @@ EXAMPLE TRIGGERS:
|
|
616
616
|
"Searchable memory retrieval",
|
617
617
|
"Importance-based prioritization",
|
618
618
|
"Memory cleanup and maintenance",
|
619
|
-
"
|
619
|
+
"WebAgents JSON storage integration via dependencies"
|
620
620
|
],
|
621
621
|
"tools": [
|
622
622
|
"extract_key_memories",
|
@@ -629,7 +629,7 @@ EXAMPLE TRIGGERS:
|
|
629
629
|
"total_memories": len(self.memories),
|
630
630
|
"categories": list(set(m.category for m in self.memories.values())) if self.memories else [],
|
631
631
|
"config": {
|
632
|
-
"
|
632
|
+
"use_webagents_storage": self.use_webagents_storage,
|
633
633
|
"agent_name": self.agent_name,
|
634
634
|
"max_memories": self.max_memories,
|
635
635
|
"auto_extract": self.auto_extract,
|
@@ -10,11 +10,11 @@ Env configuration:
|
|
10
10
|
- MILVUS_HOST (e.g., https://in03)
|
11
11
|
- MILVUS_PORT (e.g., 443)
|
12
12
|
- MILVUS_TOKEN (if required by Milvus/Cosmos)
|
13
|
-
- MILVUS_COLLECTION (default:
|
13
|
+
- MILVUS_COLLECTION (default: webagents_memory)
|
14
14
|
- MILVUS_FORCE_RECREATE (truthy to recreate collection on init)
|
15
15
|
- EMBEDDING_MODEL (default: text-embedding-3-small)
|
16
16
|
- LITELLM_BASE_URL (default: http://localhost:2225)
|
17
|
-
- LITELLM_API_KEY or
|
17
|
+
- LITELLM_API_KEY or WEBAGENTS_API_KEY (bearer for embeddings)
|
18
18
|
"""
|
19
19
|
|
20
20
|
from __future__ import annotations
|
@@ -58,16 +58,16 @@ class VectorMemorySkill(Skill):
|
|
58
58
|
self.milvus_host = _get_env_str("MILVUS_HOST", "http://localhost")
|
59
59
|
self.milvus_port = int(os.getenv("MILVUS_PORT", "19530"))
|
60
60
|
self.milvus_token = _get_env_str("MILVUS_TOKEN")
|
61
|
-
self.milvus_collection = _get_env_str("MILVUS_COLLECTION", "
|
61
|
+
self.milvus_collection = _get_env_str("MILVUS_COLLECTION", "webagents_memory")
|
62
62
|
self.milvus_force_recreate = _is_truthy(os.getenv("MILVUS_FORCE_RECREATE", "false"))
|
63
63
|
# Embeddings config
|
64
64
|
self.embed_model = _get_env_str("EMBEDDING_MODEL", "text-embedding-3-small")
|
65
65
|
self.litellm_base = _get_env_str("LITELLM_BASE_URL", "http://localhost:2225")
|
66
|
-
self.litellm_key = _get_env_str("LITELLM_API_KEY") or _get_env_str("
|
66
|
+
self.litellm_key = _get_env_str("LITELLM_API_KEY") or _get_env_str("WEBAGENTS_API_KEY")
|
67
67
|
|
68
68
|
async def initialize(self, agent) -> None:
|
69
69
|
self.agent = agent
|
70
|
-
self.logger = get_logger('skill.
|
70
|
+
self.logger = get_logger('skill.webagents.vector_memory', agent.name)
|
71
71
|
if not _MILVUS_AVAILABLE:
|
72
72
|
self.logger.warning("pymilvus not available; VectorMemorySkill disabled")
|
73
73
|
return
|
@@ -96,7 +96,7 @@ class VectorMemorySkill(Skill):
|
|
96
96
|
FieldSchema(name="content", dtype=DataType.VARCHAR, max_length=8192),
|
97
97
|
FieldSchema(name="vector", dtype=DataType.FLOAT_VECTOR, dim=self.dim),
|
98
98
|
]
|
99
|
-
schema = CollectionSchema(fields=fields, description="
|
99
|
+
schema = CollectionSchema(fields=fields, description="WebAgents Vector Memory")
|
100
100
|
self.collection = Collection(name=self.milvus_collection, schema=schema)
|
101
101
|
try:
|
102
102
|
self.collection.create_index(
|
@@ -0,0 +1,158 @@
|
|
1
|
+
"""
|
2
|
+
Simplified CrewAI Skill for WebAgents
|
3
|
+
|
4
|
+
This skill runs a pre-configured CrewAI crew with agents and tasks.
|
5
|
+
The crew configuration is provided during skill initialization.
|
6
|
+
|
7
|
+
Main use case: Execute a specific crew workflow on demand.
|
8
|
+
"""
|
9
|
+
|
10
|
+
import os
|
11
|
+
import json
|
12
|
+
from typing import Dict, Any, Optional, List, Union
|
13
|
+
from datetime import datetime
|
14
|
+
|
15
|
+
from webagents.agents.skills.base import Skill
|
16
|
+
from webagents.agents.tools.decorators import tool, prompt
|
17
|
+
|
18
|
+
try:
|
19
|
+
from crewai import Agent, Task, Crew, Process
|
20
|
+
CREWAI_AVAILABLE = True
|
21
|
+
except ImportError:
|
22
|
+
CREWAI_AVAILABLE = False
|
23
|
+
Agent, Task, Crew, Process = None, None, None, None # type: ignore
|
24
|
+
|
25
|
+
|
26
|
+
class CrewAISkill(Skill):
|
27
|
+
"""Simplified CrewAI skill for running pre-configured crews"""
|
28
|
+
|
29
|
+
def __init__(self, crew_or_config: Optional[Union[Dict[str, Any], Any]] = None):
|
30
|
+
super().__init__({}, scope="all")
|
31
|
+
if not CREWAI_AVAILABLE:
|
32
|
+
raise ImportError("CrewAI is not installed. Install with: pip install crewai")
|
33
|
+
|
34
|
+
# Handle both Crew object and configuration dictionary
|
35
|
+
if crew_or_config is None:
|
36
|
+
self.crew_config = {}
|
37
|
+
self.crew = None
|
38
|
+
elif hasattr(crew_or_config, 'agents') and hasattr(crew_or_config, 'tasks'):
|
39
|
+
# It's a Crew object
|
40
|
+
self.crew_config = {}
|
41
|
+
self.crew = crew_or_config
|
42
|
+
else:
|
43
|
+
# It's a configuration dictionary
|
44
|
+
self.crew_config = crew_or_config or {}
|
45
|
+
self.crew = None
|
46
|
+
self._setup_crew()
|
47
|
+
|
48
|
+
def get_dependencies(self) -> List[str]:
|
49
|
+
"""Skill dependencies"""
|
50
|
+
return [] # No dependencies needed for simple crew execution
|
51
|
+
|
52
|
+
def _setup_crew(self):
|
53
|
+
"""Set up the CrewAI crew from configuration"""
|
54
|
+
if not self.crew_config:
|
55
|
+
return
|
56
|
+
|
57
|
+
try:
|
58
|
+
# Get agents configuration
|
59
|
+
agents_config = self.crew_config.get('agents', [])
|
60
|
+
tasks_config = self.crew_config.get('tasks', [])
|
61
|
+
process_type = self.crew_config.get('process', 'sequential')
|
62
|
+
|
63
|
+
if not agents_config or not tasks_config:
|
64
|
+
return
|
65
|
+
|
66
|
+
# Create agents
|
67
|
+
agents = []
|
68
|
+
for agent_config in agents_config:
|
69
|
+
agent = Agent(
|
70
|
+
role=agent_config.get('role', 'Agent'),
|
71
|
+
goal=agent_config.get('goal', 'Complete assigned tasks'),
|
72
|
+
backstory=agent_config.get('backstory', 'An AI agent ready to help'),
|
73
|
+
verbose=agent_config.get('verbose', True),
|
74
|
+
allow_delegation=agent_config.get('allow_delegation', False)
|
75
|
+
)
|
76
|
+
agents.append(agent)
|
77
|
+
|
78
|
+
# Create tasks
|
79
|
+
tasks = []
|
80
|
+
for i, task_config in enumerate(tasks_config):
|
81
|
+
# Assign agent to task (default to first agent if not specified)
|
82
|
+
agent_index = task_config.get('agent_index', 0)
|
83
|
+
if agent_index >= len(agents):
|
84
|
+
agent_index = 0 # Fallback to first agent
|
85
|
+
|
86
|
+
task = Task(
|
87
|
+
description=task_config.get('description', f'Task {i+1}'),
|
88
|
+
agent=agents[agent_index],
|
89
|
+
expected_output=task_config.get('expected_output', 'Task completion')
|
90
|
+
)
|
91
|
+
tasks.append(task)
|
92
|
+
|
93
|
+
# Create crew
|
94
|
+
process = Process.sequential
|
95
|
+
if process_type.lower() == 'hierarchical':
|
96
|
+
process = Process.hierarchical
|
97
|
+
|
98
|
+
self.crew = Crew(
|
99
|
+
agents=agents,
|
100
|
+
tasks=tasks,
|
101
|
+
process=process,
|
102
|
+
verbose=self.crew_config.get('verbose', True)
|
103
|
+
)
|
104
|
+
|
105
|
+
# CrewAI crew initialized successfully
|
106
|
+
|
107
|
+
except Exception as e:
|
108
|
+
self.crew = None
|
109
|
+
|
110
|
+
@prompt(priority=40, scope=["owner", "all"])
|
111
|
+
def crewai_prompt(self) -> str:
|
112
|
+
"""Prompt describing CrewAI capabilities"""
|
113
|
+
if not self.crew:
|
114
|
+
return """
|
115
|
+
CrewAI skill is available but no crew is configured.
|
116
|
+
|
117
|
+
To use CrewAI, initialize the skill with either:
|
118
|
+
1. A CrewAI Crew object: CrewAISkill(crew)
|
119
|
+
2. A crew configuration dictionary with agents, tasks, and process settings
|
120
|
+
"""
|
121
|
+
|
122
|
+
agents_count = len(self.crew.agents) if self.crew else 0
|
123
|
+
tasks_count = len(self.crew.tasks) if self.crew else 0
|
124
|
+
|
125
|
+
return f"""
|
126
|
+
CrewAI multi-agent orchestration is ready. Available tool:
|
127
|
+
|
128
|
+
• crewai_run(inputs) - Execute the configured crew with the given inputs
|
129
|
+
|
130
|
+
Configured crew:
|
131
|
+
- {agents_count} agents with specialized roles
|
132
|
+
- {tasks_count} tasks in the workflow
|
133
|
+
- Ready to process your requests through collaborative AI agents
|
134
|
+
|
135
|
+
Provide inputs as a dictionary to run the crew workflow.
|
136
|
+
"""
|
137
|
+
|
138
|
+
# Public tool
|
139
|
+
@tool(description="Execute the configured CrewAI crew with the given inputs")
|
140
|
+
async def crewai_run(self, inputs: Dict[str, Any]) -> str:
|
141
|
+
"""Execute the configured CrewAI crew with the provided inputs"""
|
142
|
+
if not self.crew:
|
143
|
+
return "❌ No CrewAI crew configured. Please initialize the skill with a crew configuration."
|
144
|
+
|
145
|
+
if not inputs:
|
146
|
+
return "❌ Inputs are required to run the crew"
|
147
|
+
|
148
|
+
try:
|
149
|
+
# Execute the crew with inputs
|
150
|
+
result = self.crew.kickoff(inputs=inputs)
|
151
|
+
|
152
|
+
agents_count = len(self.crew.agents)
|
153
|
+
tasks_count = len(self.crew.tasks)
|
154
|
+
|
155
|
+
return f"✅ CrewAI execution completed successfully!\n👥 Agents: {agents_count}\n📝 Tasks: {tasks_count}\n\n📊 Result:\n{result}"
|
156
|
+
|
157
|
+
except Exception as e:
|
158
|
+
return f"❌ CrewAI execution failed: {str(e)}"
|