diff --git a/backend/agent/config_helper.py b/backend/agent/config_helper.py index 5945bbdf..b7dc7713 100644 --- a/backend/agent/config_helper.py +++ b/backend/agent/config_helper.py @@ -119,7 +119,28 @@ def extract_agent_config(agent_data: Dict[str, Any], version_data: Optional[Dict 'model': None, # No model specified for default config 'configured_mcps': [], 'custom_mcps': [], - 'agentpress_tools': {}, + 'agentpress_tools': { + # Default all tools to enabled for new agents + "sb_shell_tool": True, + "sb_files_tool": True, + "sb_deploy_tool": True, + "sb_expose_tool": True, + "web_search_tool": True, + "sb_vision_tool": True, + "sb_image_edit_tool": True, + "sb_presentation_outline_tool": True, + "sb_presentation_tool": True, + "sb_presentation_tool_v2": True, + "sb_sheets_tool": True, + "sb_web_dev_tool": True, + "browser_tool": True, + "data_providers_tool": True, + "agent_config_tool": True, + "mcp_search_tool": True, + "credential_profile_tool": True, + "workflow_tool": True, + "trigger_tool": True + }, 'workflows': [], 'triggers': [], 'avatar': agent_data.get('avatar'), diff --git a/backend/agent/run.py b/backend/agent/run.py index e5f11a7b..036f0b2c 100644 --- a/backend/agent/run.py +++ b/backend/agent/run.py @@ -62,30 +62,70 @@ class ToolManager: self.project_id = project_id self.thread_id = thread_id - def register_all_tools(self): + def register_all_tools(self, agent_id: Optional[str] = None, disabled_tools: Optional[List[str]] = None): + """Register all available tools by default, with optional exclusions. + + Args: + agent_id: Optional agent ID for agent builder tools + disabled_tools: List of tool names to exclude from registration + """ + disabled_tools = disabled_tools or [] + + logger.info(f"Registering tools with disabled list: {disabled_tools}") + + # Core tools - always enabled + self._register_core_tools() + + # Sandbox tools + self._register_sandbox_tools(disabled_tools) + + # Data and utility tools + self._register_utility_tools(disabled_tools) + + # Agent builder tools - register if agent_id provided + if agent_id: + self._register_agent_builder_tools(agent_id, disabled_tools) + + # Browser tool + self._register_browser_tool(disabled_tools) + + logger.info(f"Tool registration complete. Registered tools: {list(self.thread_manager.tool_registry.tools.keys())}") + + def _register_core_tools(self): + """Register core tools that are always available.""" self.thread_manager.add_tool(ExpandMessageTool, thread_id=self.thread_id, thread_manager=self.thread_manager) self.thread_manager.add_tool(MessageTool) - - self.thread_manager.add_tool(SandboxShellTool, project_id=self.project_id, thread_manager=self.thread_manager) - self.thread_manager.add_tool(SandboxFilesTool, project_id=self.project_id, thread_manager=self.thread_manager) - self.thread_manager.add_tool(SandboxDeployTool, project_id=self.project_id, thread_manager=self.thread_manager) - self.thread_manager.add_tool(SandboxExposeTool, project_id=self.project_id, thread_manager=self.thread_manager) - self.thread_manager.add_tool(SandboxWebSearchTool, project_id=self.project_id, thread_manager=self.thread_manager) - self.thread_manager.add_tool(SandboxVisionTool, project_id=self.project_id, thread_id=self.thread_id, thread_manager=self.thread_manager) - self.thread_manager.add_tool(SandboxImageEditTool, project_id=self.project_id, thread_id=self.thread_id, thread_manager=self.thread_manager) - self.thread_manager.add_tool(SandboxPresentationOutlineTool, project_id=self.project_id, thread_manager=self.thread_manager) - self.thread_manager.add_tool(SandboxPresentationToolV2, project_id=self.project_id, thread_manager=self.thread_manager) self.thread_manager.add_tool(TaskListTool, project_id=self.project_id, thread_manager=self.thread_manager, thread_id=self.thread_id) - self.thread_manager.add_tool(SandboxSheetsTool, project_id=self.project_id, thread_manager=self.thread_manager) - # self.thread_manager.add_tool(SandboxWebDevTool, project_id=self.project_id, thread_id=self.thread_id, thread_manager=self.thread_manager) - if config.RAPID_API_KEY: - self.thread_manager.add_tool(DataProvidersTool) - - # Add Browser Tool - from agent.tools.browser_tool import BrowserTool - self.thread_manager.add_tool(BrowserTool, project_id=self.project_id, thread_id=self.thread_id, thread_manager=self.thread_manager) - def register_agent_builder_tools(self, agent_id: str): + def _register_sandbox_tools(self, disabled_tools: List[str]): + """Register sandbox-related tools.""" + sandbox_tools = [ + ('sb_shell_tool', SandboxShellTool, {'project_id': self.project_id, 'thread_manager': self.thread_manager}), + ('sb_files_tool', SandboxFilesTool, {'project_id': self.project_id, 'thread_manager': self.thread_manager}), + ('sb_deploy_tool', SandboxDeployTool, {'project_id': self.project_id, 'thread_manager': self.thread_manager}), + ('sb_expose_tool', SandboxExposeTool, {'project_id': self.project_id, 'thread_manager': self.thread_manager}), + ('web_search_tool', SandboxWebSearchTool, {'project_id': self.project_id, 'thread_manager': self.thread_manager}), + ('sb_vision_tool', SandboxVisionTool, {'project_id': self.project_id, 'thread_id': self.thread_id, 'thread_manager': self.thread_manager}), + ('sb_image_edit_tool', SandboxImageEditTool, {'project_id': self.project_id, 'thread_id': self.thread_id, 'thread_manager': self.thread_manager}), + ('sb_presentation_outline_tool', SandboxPresentationOutlineTool, {'project_id': self.project_id, 'thread_manager': self.thread_manager}), + ('sb_presentation_tool_v2', SandboxPresentationToolV2, {'project_id': self.project_id, 'thread_manager': self.thread_manager}), + ('sb_sheets_tool', SandboxSheetsTool, {'project_id': self.project_id, 'thread_manager': self.thread_manager}), + ('sb_web_dev_tool', SandboxWebDevTool, {'project_id': self.project_id, 'thread_id': self.thread_id, 'thread_manager': self.thread_manager}), + ] + + for tool_name, tool_class, kwargs in sandbox_tools: + if tool_name not in disabled_tools: + self.thread_manager.add_tool(tool_class, **kwargs) + logger.debug(f"Registered {tool_name}") + + def _register_utility_tools(self, disabled_tools: List[str]): + """Register utility and data provider tools.""" + if config.RAPID_API_KEY and 'data_providers_tool' not in disabled_tools: + self.thread_manager.add_tool(DataProvidersTool) + logger.debug("Registered data_providers_tool") + + def _register_agent_builder_tools(self, agent_id: str, disabled_tools: List[str]): + """Register agent builder tools.""" from agent.tools.agent_builder_tools.agent_config_tool import AgentConfigTool from agent.tools.agent_builder_tools.mcp_search_tool import MCPSearchTool from agent.tools.agent_builder_tools.credential_profile_tool import CredentialProfileTool @@ -94,57 +134,27 @@ class ToolManager: from services.supabase import DBConnection db = DBConnection() - self.thread_manager.add_tool(AgentConfigTool, thread_manager=self.thread_manager, db_connection=db, agent_id=agent_id) - self.thread_manager.add_tool(MCPSearchTool, thread_manager=self.thread_manager, db_connection=db, agent_id=agent_id) - self.thread_manager.add_tool(CredentialProfileTool, thread_manager=self.thread_manager, db_connection=db, agent_id=agent_id) - self.thread_manager.add_tool(WorkflowTool, thread_manager=self.thread_manager, db_connection=db, agent_id=agent_id) - self.thread_manager.add_tool(TriggerTool, thread_manager=self.thread_manager, db_connection=db, agent_id=agent_id) + + agent_builder_tools = [ + ('agent_config_tool', AgentConfigTool), + ('mcp_search_tool', MCPSearchTool), + ('credential_profile_tool', CredentialProfileTool), + ('workflow_tool', WorkflowTool), + ('trigger_tool', TriggerTool), + ] + + for tool_name, tool_class in agent_builder_tools: + if tool_name not in disabled_tools: + self.thread_manager.add_tool(tool_class, thread_manager=self.thread_manager, db_connection=db, agent_id=agent_id) + logger.debug(f"Registered {tool_name}") - def register_custom_tools(self, enabled_tools: Dict[str, Any]): - self.thread_manager.add_tool(ExpandMessageTool, thread_id=self.thread_id, thread_manager=self.thread_manager) - self.thread_manager.add_tool(MessageTool) - self.thread_manager.add_tool(TaskListTool, project_id=self.project_id, thread_manager=self.thread_manager, thread_id=self.thread_id) - - def safe_tool_check(tool_name: str) -> bool: - try: - if not isinstance(enabled_tools, dict): - return False - tool_config = enabled_tools.get(tool_name, {}) - if not isinstance(tool_config, dict): - return bool(tool_config) if isinstance(tool_config, bool) else False - return tool_config.get('enabled', False) - except Exception: - return False - - if safe_tool_check('sb_shell_tool'): - self.thread_manager.add_tool(SandboxShellTool, project_id=self.project_id, thread_manager=self.thread_manager) - if safe_tool_check('sb_files_tool'): - self.thread_manager.add_tool(SandboxFilesTool, project_id=self.project_id, thread_manager=self.thread_manager) - if safe_tool_check('sb_deploy_tool'): - self.thread_manager.add_tool(SandboxDeployTool, project_id=self.project_id, thread_manager=self.thread_manager) - if safe_tool_check('sb_expose_tool'): - self.thread_manager.add_tool(SandboxExposeTool, project_id=self.project_id, thread_manager=self.thread_manager) - if safe_tool_check('web_search_tool'): - self.thread_manager.add_tool(SandboxWebSearchTool, project_id=self.project_id, thread_manager=self.thread_manager) - if safe_tool_check('sb_vision_tool'): - self.thread_manager.add_tool(SandboxVisionTool, project_id=self.project_id, thread_id=self.thread_id, thread_manager=self.thread_manager) - if safe_tool_check('sb_presentation_tool'): - self.thread_manager.add_tool(SandboxPresentationOutlineTool, project_id=self.project_id, thread_manager=self.thread_manager) - self.thread_manager.add_tool(SandboxPresentationToolV2, project_id=self.project_id, thread_manager=self.thread_manager) - if safe_tool_check('sb_image_edit_tool'): - self.thread_manager.add_tool(SandboxImageEditTool, project_id=self.project_id, thread_id=self.thread_id, thread_manager=self.thread_manager) - if safe_tool_check('sb_sheets_tool'): - self.thread_manager.add_tool(SandboxSheetsTool, project_id=self.project_id, thread_manager=self.thread_manager) - if safe_tool_check('sb_web_dev_tool'): - self.thread_manager.add_tool(SandboxWebDevTool, project_id=self.project_id, thread_id=self.thread_id, thread_manager=self.thread_manager) - if config.RAPID_API_KEY and safe_tool_check('data_providers_tool'): - self.thread_manager.add_tool(DataProvidersTool) - - - if safe_tool_check('browser_tool'): + def _register_browser_tool(self, disabled_tools: List[str]): + """Register browser tool.""" + if 'browser_tool' not in disabled_tools: from agent.tools.browser_tool import BrowserTool self.thread_manager.add_tool(BrowserTool, project_id=self.project_id, thread_id=self.thread_id, thread_manager=self.thread_manager) - + logger.debug("Registered browser_tool") + class MCPManager: def __init__(self, thread_manager: ThreadManager, account_id: str): @@ -427,31 +437,70 @@ class AgentRunner: async def setup_tools(self): tool_manager = ToolManager(self.thread_manager, self.config.project_id, self.config.thread_id) + # Determine agent ID for agent builder tools + agent_id = None if self.config.agent_config and self.config.agent_config.get('is_suna_default', False): - suna_agent_id = self.config.agent_config['agent_id'] - tool_manager.register_agent_builder_tools(suna_agent_id) + agent_id = self.config.agent_config['agent_id'] + elif self.config.is_agent_builder and self.config.target_agent_id: + agent_id = self.config.target_agent_id - if self.config.is_agent_builder: - tool_manager.register_agent_builder_tools(self.config.target_agent_id) - - enabled_tools = None - if self.config.agent_config and 'agentpress_tools' in self.config.agent_config: - raw_tools = self.config.agent_config['agentpress_tools'] - - if isinstance(raw_tools, dict): - if self.config.agent_config.get('is_suna_default', False) and not raw_tools: - enabled_tools = None + # Convert agent config to disabled tools list + disabled_tools = self._get_disabled_tools_from_config() + + # Register all tools with exclusions + tool_manager.register_all_tools(agent_id=agent_id, disabled_tools=disabled_tools) + + def _get_disabled_tools_from_config(self) -> List[str]: + """Convert agent config to list of disabled tools.""" + disabled_tools = [] + + if not self.config.agent_config or 'agentpress_tools' not in self.config.agent_config: + # No tool configuration - enable all tools by default + return disabled_tools + + raw_tools = self.config.agent_config['agentpress_tools'] + + # Handle different formats of tool configuration + if not isinstance(raw_tools, dict): + # If not a dict, assume all tools are enabled + return disabled_tools + + # Special case: Suna default agents with empty tool config enable all tools + if self.config.agent_config.get('is_suna_default', False) and not raw_tools: + return disabled_tools + + def is_tool_enabled(tool_name: str) -> bool: + try: + tool_config = raw_tools.get(tool_name, True) # Default to True (enabled) if not specified + if isinstance(tool_config, bool): + return tool_config + elif isinstance(tool_config, dict): + return tool_config.get('enabled', True) # Default to True (enabled) if not specified else: - enabled_tools = raw_tools - else: - enabled_tools = None - - if enabled_tools is None: - tool_manager.register_all_tools() - else: - if not isinstance(enabled_tools, dict): - enabled_tools = {} - tool_manager.register_custom_tools(enabled_tools) + return True # Default to enabled + except Exception: + return True # Default to enabled + + # List of all available tools + all_tools = [ + 'sb_shell_tool', 'sb_files_tool', 'sb_deploy_tool', 'sb_expose_tool', + 'web_search_tool', 'sb_vision_tool', 'sb_presentation_tool', 'sb_image_edit_tool', + 'sb_sheets_tool', 'sb_web_dev_tool', 'data_providers_tool', 'browser_tool', + 'agent_config_tool', 'mcp_search_tool', 'credential_profile_tool', + 'workflow_tool', 'trigger_tool' + ] + + # Add tools that are explicitly disabled + for tool_name in all_tools: + if not is_tool_enabled(tool_name): + disabled_tools.append(tool_name) + + # Special handling for presentation tools + if 'sb_presentation_tool' in disabled_tools: + disabled_tools.extend(['sb_presentation_outline_tool', 'sb_presentation_tool_v2']) + + logger.info(f"Disabled tools from config: {disabled_tools}") + return disabled_tools async def setup_mcp_tools(self) -> Optional[MCPToolWrapper]: if not self.config.agent_config: diff --git a/backend/agent/suna/config.py b/backend/agent/suna/config.py index daf2c405..36a342d6 100644 --- a/backend/agent/suna/config.py +++ b/backend/agent/suna/config.py @@ -11,20 +11,32 @@ class SunaConfig: SYSTEM_PROMPT = SYSTEM_PROMPT DEFAULT_TOOLS = { + # Core sandbox tools "sb_shell_tool": True, "sb_files_tool": True, - "sb_web_dev_tool": True, - "browser_tool": True, "sb_deploy_tool": True, "sb_expose_tool": True, "web_search_tool": True, "sb_vision_tool": True, "sb_image_edit_tool": True, - "data_providers_tool": True, "sb_presentation_outline_tool": True, "sb_presentation_tool": True, + "sb_presentation_tool_v2": True, "sb_sheets_tool": True, - "sb_slides_tool": True + "sb_web_dev_tool": True, + + # Browser and interaction tools + "browser_tool": True, + + # Data provider tools + "data_providers_tool": True, + + # Agent builder tools (for configuration and management) + "agent_config_tool": True, + "mcp_search_tool": True, + "credential_profile_tool": True, + "workflow_tool": True, + "trigger_tool": True } DEFAULT_MCPS = [] diff --git a/docs/SELF-HOSTING.md b/docs/SELF-HOSTING.md index d8d59a13..904a8bcd 100644 --- a/docs/SELF-HOSTING.md +++ b/docs/SELF-HOSTING.md @@ -127,8 +127,8 @@ As part of the setup, you'll need to: 1. Create a Daytona account 2. Generate an API key 3. Create a Snapshot: - - Name: `kortix/suna:0.1.3` - - Image name: `kortix/suna:0.1.3` + - Name: `kortix/suna:0.1.3.4` + - Image name: `kortix/suna:0.1.3.4` - Entrypoint: `/usr/bin/supervisord -n -c /etc/supervisor/conf.d/supervisord.conf` ## Manual Configuration diff --git a/frontend/src/components/agents/tools.ts b/frontend/src/components/agents/tools.ts index 4f6ad494..b24976a0 100644 --- a/frontend/src/components/agents/tools.ts +++ b/frontend/src/components/agents/tools.ts @@ -1,17 +1,30 @@ export const AGENTPRESS_TOOL_DEFINITIONS: Record = { + // Core sandbox tools 'sb_shell_tool': { enabled: true, description: 'Execute shell commands in tmux sessions for terminal operations, CLI tools, and system management', icon: '💻', color: 'bg-slate-100 dark:bg-slate-800' }, 'sb_files_tool': { enabled: true, description: 'Create, read, update, and delete files in the workspace with comprehensive file management', icon: '📁', color: 'bg-blue-100 dark:bg-blue-800/50' }, - 'sb_web_dev_tool': { enabled: true, description: 'Create Next.js projects with shadcn/ui pre-installed, manage dependencies, build and deploy modern web applications', icon: '⚛️', color: 'bg-cyan-100 dark:bg-cyan-800/50' }, - 'browser_tool': { enabled: true, description: 'Browser automation for web navigation, clicking, form filling, and page interaction', icon: '🌐', color: 'bg-indigo-100 dark:bg-indigo-800/50' }, 'sb_deploy_tool': { enabled: true, description: 'Deploy applications and services with automated deployment capabilities', icon: '🚀', color: 'bg-green-100 dark:bg-green-800/50' }, 'sb_expose_tool': { enabled: true, description: 'Expose services and manage ports for application accessibility', icon: '🔌', color: 'bg-orange-100 dark:bg-orange-800/20' }, 'web_search_tool': { enabled: true, description: 'Search the web using Tavily API and scrape webpages with Firecrawl for research', icon: '🔍', color: 'bg-yellow-100 dark:bg-yellow-800/50' }, 'sb_vision_tool': { enabled: true, description: 'Vision and image processing capabilities for visual content analysis', icon: '👁️', color: 'bg-pink-100 dark:bg-pink-800/50' }, 'sb_image_edit_tool': { enabled: true, description: 'Generate new images or edit existing images using OpenAI GPT Image 1', icon: '🎨', color: 'bg-purple-100 dark:bg-purple-800/50' }, - 'data_providers_tool': { enabled: true, description: 'Access to data providers and external APIs (requires RapidAPI key)', icon: '🔗', color: 'bg-cyan-100 dark:bg-cyan-800/50' }, 'sb_presentation_outline_tool': { enabled: true, description: 'Create structured presentation outlines with slide descriptions and speaker notes', icon: '📋', color: 'bg-purple-100 dark:bg-purple-800/50' }, 'sb_presentation_tool': { enabled: true, description: 'Create professional presentations with HTML slides, preview, and export capabilities', icon: '📊', color: 'bg-violet-100 dark:bg-violet-800/50' }, + 'sb_presentation_tool_v2': { enabled: true, description: 'Enhanced presentation tool with advanced formatting and export options', icon: '📊', color: 'bg-violet-100 dark:bg-violet-800/50' }, 'sb_sheets_tool': { enabled: true, description: 'Create, view, update, analyze, visualize, and format spreadsheets (XLSX/CSV) with Luckysheet viewer', icon: '📊', color: 'bg-purple-100 dark:bg-purple-800/50' }, + 'sb_web_dev_tool': { enabled: true, description: 'Create Next.js projects with shadcn/ui pre-installed, manage dependencies, build and deploy modern web applications', icon: '⚛️', color: 'bg-cyan-100 dark:bg-cyan-800/50' }, + + // Browser and interaction tools + 'browser_tool': { enabled: true, description: 'Browser automation for web navigation, clicking, form filling, and page interaction', icon: '🌐', color: 'bg-indigo-100 dark:bg-indigo-800/50' }, + + // Data provider tools + 'data_providers_tool': { enabled: true, description: 'Access to data providers and external APIs', icon: '🔗', color: 'bg-cyan-100 dark:bg-cyan-800/50' }, + + // Agent builder tools + 'agent_config_tool': { enabled: true, description: 'Configure agent settings, tools, and integrations', icon: '⚙️', color: 'bg-gray-100 dark:bg-gray-800/50' }, + 'mcp_search_tool': { enabled: true, description: 'Search and discover MCP servers and integrations for external services', icon: '🔍', color: 'bg-teal-100 dark:bg-teal-800/50' }, + 'credential_profile_tool': { enabled: true, description: 'Manage credential profiles for secure integration authentication', icon: '🔐', color: 'bg-red-100 dark:bg-red-800/50' }, + 'workflow_tool': { enabled: true, description: 'Create and manage automated workflows and task sequences', icon: '🔄', color: 'bg-emerald-100 dark:bg-emerald-800/50' }, + 'trigger_tool': { enabled: true, description: 'Set up event triggers and scheduled automation', icon: '⏰', color: 'bg-amber-100 dark:bg-amber-800/50' }, }; export const DEFAULT_AGENTPRESS_TOOLS: Record = Object.entries(AGENTPRESS_TOOL_DEFINITIONS).reduce((acc, [key, value]) => { @@ -21,18 +34,32 @@ export const DEFAULT_AGENTPRESS_TOOLS: Record = Object.entries( export const getToolDisplayName = (toolName: string): string => { const displayNames: Record = { + // Core sandbox tools 'sb_shell_tool': 'Terminal', 'sb_files_tool': 'File Manager', - 'sb_web_dev_tool': 'Web Development', - 'browser_tool': 'Browser Automation', 'sb_deploy_tool': 'Deploy Tool', 'sb_expose_tool': 'Port Exposure', 'web_search_tool': 'Web Search', 'sb_vision_tool': 'Image Processing', - 'data_providers_tool': 'Data Providers', + 'sb_image_edit_tool': 'Image Editor', 'sb_presentation_outline_tool': 'Presentation Outline', 'sb_presentation_tool': 'Presentation Creator', - 'sb_sheets_tool': 'Sheets Tool', + 'sb_presentation_tool_v2': 'Presentation Creator V2', + 'sb_sheets_tool': 'Spreadsheets', + 'sb_web_dev_tool': 'Web Development', + + // Browser and interaction tools + 'browser_tool': 'Browser Automation', + + // Data provider tools + 'data_providers_tool': 'Data Providers', + + // Agent builder tools + 'agent_config_tool': 'Agent Builder Configuration', + 'mcp_search_tool': 'Agent Builder MCP Search', + 'credential_profile_tool': 'Agent Builder Credential Profiles', + 'workflow_tool': 'Agent Builder Workflows', + 'trigger_tool': 'Agent Builder Triggers', }; return displayNames[toolName] || toolName.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase());