| """ |
| Executor Agent for SPARKNET |
| Handles task execution and tool usage |
| """ |
|
|
| from typing import Optional, Dict, Any |
| from loguru import logger |
| import json |
| import re |
|
|
| from .base_agent import BaseAgent, Task, Message |
| from ..llm.ollama_client import OllamaClient |
|
|
|
|
| class ExecutorAgent(BaseAgent): |
| """Agent specialized in executing tasks using available tools.""" |
|
|
| def __init__( |
| self, |
| llm_client: OllamaClient, |
| model: str = "llama3.1:8b", |
| temperature: float = 0.5, |
| ): |
| system_prompt = """You are an execution agent specialized in completing tasks using available tools. |
| |
| Your role is to: |
| 1. Analyze the task requirements |
| 2. Select and use appropriate tools |
| 3. Execute actions to complete the task |
| 4. Report results clearly |
| |
| When you need to use a tool, format your response as: |
| TOOL: tool_name |
| PARAMETERS: { |
| "param1": "value1", |
| "param2": "value2" |
| } |
| |
| After receiving tool results, provide a final answer starting with: |
| RESULT: [your analysis and conclusion] |
| |
| Be precise, focused, and efficient in task completion.""" |
|
|
| super().__init__( |
| name="ExecutorAgent", |
| description="Task execution and tool usage agent", |
| llm_client=llm_client, |
| model=model, |
| system_prompt=system_prompt, |
| temperature=temperature, |
| max_tokens=1024, |
| ) |
|
|
| async def process_task(self, task: Task) -> Task: |
| """ |
| Process and execute a task. |
| |
| Args: |
| task: Task to process |
| |
| Returns: |
| Updated task with results |
| """ |
| logger.info(f"ExecutorAgent processing task: {task.id}") |
| task.status = "in_progress" |
|
|
| try: |
| |
| task_message = Message( |
| role="user", |
| content=f"Task: {task.description}\n\nAvailable tools: {', '.join(self.get_available_tools())}", |
| sender="system", |
| ) |
|
|
| |
| self.clear_history() |
| self.add_message(task_message) |
|
|
| |
| max_iterations = 5 |
| iteration = 0 |
| final_result = None |
|
|
| while iteration < max_iterations: |
| iteration += 1 |
| logger.debug(f"Iteration {iteration}/{max_iterations}") |
|
|
| |
| response = await self.call_llm(messages=self.messages) |
|
|
| |
| self.add_message( |
| Message( |
| role="assistant", |
| content=response, |
| sender=self.name, |
| ) |
| ) |
|
|
| |
| if "TOOL:" in response: |
| tool_result = await self._execute_tool_from_response(response) |
|
|
| |
| tool_message = Message( |
| role="user", |
| content=f"Tool execution result:\nSuccess: {tool_result.success}\nOutput: {tool_result.output}\nError: {tool_result.error}", |
| sender="system", |
| ) |
| self.add_message(tool_message) |
|
|
| |
| if "RESULT:" in response: |
| |
| result_match = re.search(r"RESULT:\s*(.+)", response, re.DOTALL) |
| if result_match: |
| final_result = result_match.group(1).strip() |
| break |
|
|
| if final_result: |
| task.result = final_result |
| task.status = "completed" |
| logger.info(f"Task {task.id} completed successfully") |
| else: |
| task.result = "Task processing reached maximum iterations without completion" |
| task.status = "completed" |
| logger.warning(f"Task {task.id} reached max iterations") |
|
|
| except Exception as e: |
| logger.error(f"Error processing task {task.id}: {e}") |
| task.status = "failed" |
| task.error = str(e) |
|
|
| return task |
|
|
| async def _execute_tool_from_response(self, response: str) -> Any: |
| """ |
| Parse and execute tool call from agent response. |
| |
| Args: |
| response: Agent response containing tool call |
| |
| Returns: |
| Tool result |
| """ |
| try: |
| |
| tool_match = re.search(r"TOOL:\s*(\w+)", response) |
| if not tool_match: |
| return {"success": False, "error": "Could not parse tool name"} |
|
|
| tool_name = tool_match.group(1) |
|
|
| |
| params_match = re.search(r"PARAMETERS:\s*(\{[^}]+\})", response, re.DOTALL) |
| if params_match: |
| params_str = params_match.group(1) |
| |
| params_str = params_str.replace("'", '"') |
| params = json.loads(params_str) |
| else: |
| params = {} |
|
|
| logger.info(f"Executing tool {tool_name} with params: {params}") |
|
|
| |
| result = await self.execute_tool(tool_name, **params) |
|
|
| return result |
|
|
| except Exception as e: |
| logger.error(f"Error executing tool from response: {e}") |
| return { |
| "success": False, |
| "error": f"Tool execution error: {str(e)}", |
| } |
|
|