diff --git a/README.md b/README.md index d22ad3ce..f28bb92c 100644 --- a/README.md +++ b/README.md @@ -139,7 +139,7 @@ You'll need the following components: 6. **RapidAPI API Key** (Optional): - To enable API services like LinkedIn, and others, you'll need a RapidAPI key - Each service requires individual activation in your RapidAPI account: - 1. Locate the service's `base_url` in its corresponding file (e.g., `"https://linkedin-data-scraper.p.rapidapi.com"` in [`backend/agent/tools/api_services/LinkedInService.py`](backend/agent/tools/api_services/LinkedInService.py)) + 1. Locate the service's `base_url` in its corresponding file (e.g., `"https://linkedin-data-scraper.p.rapidapi.com"` in [`backend/agent/tools/data_providers/LinkedinProvider.py`](backend/agent/tools/data_providers/LinkedinProvider.py)) 2. Visit that specific API on the RapidAPI marketplace 3. Subscribe to the service (many offer free tiers with limited requests) 4. Once subscribed, the service will be available to your agent through the API Services tool diff --git a/backend/agent/run.py b/backend/agent/run.py index 88abb144..ef504345 100644 --- a/backend/agent/run.py +++ b/backend/agent/run.py @@ -1,8 +1,7 @@ import os import json from uuid import uuid4 -from typing import Optional, List, Any -from datetime import datetime, timezone +from typing import Optional from agent.tools.message_tool import MessageTool from agent.tools.sb_deploy_tool import SandboxDeployTool @@ -14,7 +13,7 @@ from agentpress.response_processor import ProcessorConfig from agent.tools.sb_shell_tool import SandboxShellTool from agent.tools.sb_files_tool import SandboxFilesTool from agent.tools.sb_browser_tool import SandboxBrowserTool -from agent.tools.api_services_tool import APIServicesTool +from agent.tools.data_providers_tool import DataProvidersTool from agent.prompt import get_system_prompt from sandbox.sandbox import create_sandbox, get_or_start_sandbox from utils.billing import check_billing_status, get_account_id_from_thread @@ -74,7 +73,7 @@ async def run_agent(thread_id: str, project_id: str, stream: bool = True, thread thread_manager.add_tool(WebSearchTool) if os.getenv("RAPID_API_KEY"): - thread_manager.add_tool(APIServicesTool) + thread_manager.add_tool(DataProvidersTool) xml_examples = "" for tag_name, example in thread_manager.tool_registry.get_xml_examples().items(): diff --git a/backend/agent/tools/api_services/AmazonService.py b/backend/agent/tools/data_providers/AmazonProvider.py similarity index 97% rename from backend/agent/tools/api_services/AmazonService.py rename to backend/agent/tools/data_providers/AmazonProvider.py index 662ace3c..5ecea89e 100644 --- a/backend/agent/tools/api_services/AmazonService.py +++ b/backend/agent/tools/data_providers/AmazonProvider.py @@ -1,9 +1,9 @@ from typing import Dict, Optional -from agent.tools.api_services.APIServicesBase import APIServicesBase, EndpointSchema +from agent.tools.data_providers.RapidDataProviderBase import RapidDataProviderBase, EndpointSchema -class AmazonService(APIServicesBase): +class AmazonProvider(RapidDataProviderBase): def __init__(self): endpoints: Dict[str, EndpointSchema] = { "search": { @@ -107,9 +107,9 @@ class AmazonService(APIServicesBase): if __name__ == "__main__": - import os - os.environ["RAPID_API_KEY"] = "b5258e1150msh2e4f098fdeeda7fp1ac998jsncbc24fc76b95" - tool = AmazonService() + from dotenv import load_dotenv + load_dotenv() + tool = AmazonProvider() # Example for product search search_result = tool.call_endpoint( diff --git a/backend/agent/tools/api_services/LinkedInService.py b/backend/agent/tools/data_providers/LinkedinProvider.py similarity index 98% rename from backend/agent/tools/api_services/LinkedInService.py rename to backend/agent/tools/data_providers/LinkedinProvider.py index adb483db..6a70e21a 100644 --- a/backend/agent/tools/api_services/LinkedInService.py +++ b/backend/agent/tools/data_providers/LinkedinProvider.py @@ -1,9 +1,9 @@ from typing import Dict -from agent.tools.api_services.APIServicesBase import APIServicesBase, EndpointSchema +from agent.tools.data_providers.RapidDataProviderBase import RapidDataProviderBase, EndpointSchema -class LinkedInService(APIServicesBase): +class LinkedinProvider(RapidDataProviderBase): def __init__(self): endpoints: Dict[str, EndpointSchema] = { "person": { @@ -238,9 +238,9 @@ class LinkedInService(APIServicesBase): if __name__ == "__main__": - import os - os.environ["RAPID_API_KEY"] = "" - tool = LinkedInService() + from dotenv import load_dotenv + load_dotenv() + tool = LinkedinProvider() result = tool.call_endpoint( route="comments_from_recent_activity", diff --git a/backend/agent/tools/api_services/APIServicesBase.py b/backend/agent/tools/data_providers/RapidDataProviderBase.py similarity index 98% rename from backend/agent/tools/api_services/APIServicesBase.py rename to backend/agent/tools/data_providers/RapidDataProviderBase.py index 7ea9c9b1..5b7ccd66 100644 --- a/backend/agent/tools/api_services/APIServicesBase.py +++ b/backend/agent/tools/data_providers/RapidDataProviderBase.py @@ -11,7 +11,7 @@ class EndpointSchema(TypedDict): payload: Dict[str, Any] -class APIServicesBase: +class RapidDataProviderBase: def __init__(self, base_url: str, endpoints: Dict[str, EndpointSchema]): self.base_url = base_url self.endpoints = endpoints diff --git a/backend/agent/tools/api_services/YahooFinanceService.py b/backend/agent/tools/data_providers/YahooFinanceProvider.py similarity index 95% rename from backend/agent/tools/api_services/YahooFinanceService.py rename to backend/agent/tools/data_providers/YahooFinanceProvider.py index dbba83ac..d18674e7 100644 --- a/backend/agent/tools/api_services/YahooFinanceService.py +++ b/backend/agent/tools/data_providers/YahooFinanceProvider.py @@ -1,9 +1,9 @@ -from typing import Dict, Optional +from typing import Dict -from agent.tools.api_services.APIServicesBase import APIServicesBase, EndpointSchema +from agent.tools.data_providers.RapidDataProviderBase import RapidDataProviderBase, EndpointSchema -class YahooFinanceService(APIServicesBase): +class YahooFinanceProvider(RapidDataProviderBase): def __init__(self): endpoints: Dict[str, EndpointSchema] = { "get_tickers": { @@ -93,9 +93,9 @@ class YahooFinanceService(APIServicesBase): if __name__ == "__main__": - import os - os.environ["RAPID_API_KEY"] = "b5258e1150msh2e4f098fdeeda7fp1ac998jsncbc24fc76b95" - tool = YahooFinanceService() + from dotenv import load_dotenv + load_dotenv() + tool = YahooFinanceProvider() # Example for getting stock tickers tickers_result = tool.call_endpoint( diff --git a/backend/agent/tools/api_services_tool.py b/backend/agent/tools/data_providers_tool.py similarity index 58% rename from backend/agent/tools/api_services_tool.py rename to backend/agent/tools/data_providers_tool.py index e05ecdf2..4ca8d026 100644 --- a/backend/agent/tools/api_services_tool.py +++ b/backend/agent/tools/data_providers_tool.py @@ -1,29 +1,33 @@ import json from agentpress.tool import Tool, ToolResult, openapi_schema, xml_schema -from agent.tools.api_services.LinkedInService import LinkedInService +from agent.tools.data_providers.LinkedinProvider import LinkedinProvider +from agent.tools.data_providers.YahooFinanceProvider import YahooFinanceProvider +from agent.tools.data_providers.AmazonProvider import AmazonProvider -class APIServicesTool(Tool): - """Tool for making requests to various API services.""" +class DataProvidersTool(Tool): + """Tool for making requests to various data providers.""" def __init__(self): super().__init__() - self.register_apis = { - "linkedin": LinkedInService() + self.register_data_providers = { + "linkedin": LinkedinProvider(), + "yahoo_finance": YahooFinanceProvider(), + "amazon": AmazonProvider() } @openapi_schema({ "type": "function", "function": { - "name": "get_api_service_endpoints", - "description": "Get available endpoints for a specific API service", + "name": "get_data_provider_endpoints", + "description": "Get available endpoints for a specific data provider", "parameters": { "type": "object", "properties": { "service_name": { "type": "string", - "description": "The name of the API service (e.g., 'linkedin')" + "description": "The name of the data provider (e.g., 'linkedin')" } }, "required": ["service_name"] @@ -31,44 +35,44 @@ class APIServicesTool(Tool): } }) @xml_schema( - tag_name="get-api-service-endpoints", + tag_name="get-data-provider-endpoints", mappings=[ {"param_name": "service_name", "node_type": "attribute", "path": "."} ], example=''' - - + + ''' ) - async def get_api_service_endpoints( + async def get_data_provider_endpoints( self, service_name: str ) -> ToolResult: """ - Get available endpoints for a specific API service. + Get available endpoints for a specific data provider. Parameters: - - service_name: The name of the API service (e.g., 'linkedin') + - service_name: The name of the data provider (e.g., 'linkedin') """ try: if not service_name: - return self.fail_response("API name is required.") + return self.fail_response("Data provider name is required.") - if service_name not in self.register_apis: - return self.fail_response(f"API '{service_name}' not found. Available APIs: {list(self.register_apis.keys())}") + if service_name not in self.register_data_providers: + return self.fail_response(f"Data provider '{service_name}' not found. Available data providers: {list(self.register_data_providers.keys())}") - endpoints = self.register_apis[service_name].get_endpoints() + endpoints = self.register_data_providers[service_name].get_endpoints() return self.success_response(endpoints) except Exception as e: error_message = str(e) - simplified_message = f"Error getting API endpoints: {error_message[:200]}" + simplified_message = f"Error getting data provider endpoints: {error_message[:200]}" if len(error_message) > 200: simplified_message += "..." return self.fail_response(simplified_message) @@ -76,8 +80,8 @@ Use this tool when you need to discover what endpoints are available. @openapi_schema({ "type": "function", "function": { - "name": "execute_api_call", - "description": "Execute a call to a specific API endpoint", + "name": "execute_data_provider_call", + "description": "Execute a call to a specific data provider endpoint", "parameters": { "type": "object", "properties": { @@ -99,7 +103,7 @@ Use this tool when you need to discover what endpoints are available. } }) @xml_schema( - tag_name="execute-api-call", + tag_name="execute-data-provider-call", mappings=[ {"param_name": "service_name", "node_type": "attribute", "path": "service_name"}, {"param_name": "route", "node_type": "attribute", "path": "route"}, @@ -107,30 +111,30 @@ Use this tool when you need to discover what endpoints are available. ], example=''' - + {"link": "https://www.linkedin.com/in/johndoe/"} - + ''' ) - async def execute_api_call( + async def execute_data_provider_call( self, service_name: str, route: str, payload: str # this actually a json string ) -> ToolResult: """ - Execute a call to a specific API endpoint. + Execute a call to a specific data provider endpoint. Parameters: - - service_name: The name of the API service (e.g., 'linkedin') + - service_name: The name of the data provider (e.g., 'linkedin') - route: The key of the endpoint to call - - payload: The payload to send with the API call + - payload: The payload to send with the data provider call """ try: payload = json.loads(payload) @@ -141,24 +145,24 @@ Use this tool when you need to discover what endpoints are available. if not route: return self.fail_response("route is required.") - if service_name not in self.register_apis: - return self.fail_response(f"API '{service_name}' not found. Available APIs: {list(self.register_apis.keys())}") + if service_name not in self.register_data_providers: + return self.fail_response(f"API '{service_name}' not found. Available APIs: {list(self.register_data_providers.keys())}") - api_service = self.register_apis[service_name] + data_provider = self.register_data_providers[service_name] if route == service_name: return self.fail_response(f"route '{route}' is the same as service_name '{service_name}'. YOU FUCKING IDIOT!") - if route not in api_service.get_endpoints().keys(): - return self.fail_response(f"Endpoint '{route}' not found in {service_name} API.") + if route not in data_provider.get_endpoints().keys(): + return self.fail_response(f"Endpoint '{route}' not found in {service_name} data provider.") - result = api_service.call_endpoint(route, payload) + result = data_provider.call_endpoint(route, payload) return self.success_response(result) except Exception as e: error_message = str(e) print(error_message) - simplified_message = f"Error executing API call: {error_message[:200]}" + simplified_message = f"Error executing data provider call: {error_message[:200]}" if len(error_message) > 200: simplified_message += "..." return self.fail_response(simplified_message)