From 9590121d52f8519a80ec5f70d43935267bfb6c81 Mon Sep 17 00:00:00 2001 From: Xiaotian Jin Date: Tue, 9 Sep 2025 17:47:31 +0300 Subject: [PATCH 1/3] add camel_terminal_agent based on camel terminal toolkits --- agents/camel_terminal_agent.py | 120 ++++++++++++++++++++++ pyproject.toml | 2 +- test.sh | 6 ++ util/agent_factory.py | 180 +++++++++++++++++++++++++++++++++ 4 files changed, 307 insertions(+), 1 deletion(-) create mode 100644 agents/camel_terminal_agent.py create mode 100644 util/agent_factory.py diff --git a/agents/camel_terminal_agent.py b/agents/camel_terminal_agent.py new file mode 100644 index 0000000..6e0f46c --- /dev/null +++ b/agents/camel_terminal_agent.py @@ -0,0 +1,120 @@ +# CAMEL agent using Terminal Toolkit +import os +import logging +from pathlib import Path +from typing import List, Tuple +from terminal_bench.agents.base_agent import BaseAgent, AgentResult +from terminal_bench.agents.failure_mode import FailureMode +from terminal_bench.terminal.tmux_session import TmuxSession + +from camel.models import ModelFactory +from camel.types import ModelPlatformType, ModelType + +logger = logging.getLogger(__name__) + + +class CamelTerminalAgent(BaseAgent): + @staticmethod + def name() -> str: + return "CamelTerminalAgent" + + def perform_task( + self, + instruction: str, + session: TmuxSession, + logging_dir: Path | None = None, + ) -> AgentResult: + """Execute a task using the Terminal Bench harness. + + Args: + instruction: The task instruction to execute + session: TmuxSession object for command execution + logging_dir: Optional directory for logging + + Returns: + AgentResult with token counts and failure mode + """ + + container_name = session.container.name + if not container_name: + raise ValueError("Container name is required for DockerExecutor") + + # Set up CAMEL working directory for logs and internal operations + camel_workdir = logging_dir / "CAMEL_WORKDIR" + if not camel_workdir.exists(): + camel_workdir.mkdir(parents=True) + + absolute_camel_workdir = str(camel_workdir.resolve()) + os.environ["CAMEL_WORKDIR"] = absolute_camel_workdir + print(f"Set CAMEL_WORKDIR to: {os.environ['CAMEL_WORKDIR']}") + + session_logs_dir = logging_dir / "session" / 'logs' + if not session_logs_dir.exists(): + session_logs_dir.mkdir(parents=True) + print(f"Session logs directory: {session_logs_dir}") + + from util.agent_factory import developer_agent_factory + + # Use Terminal-Bench's Docker container with TerminalToolkit's Docker backend + terminal_toolkit_kwargs = { + "working_directory": "/app", # Work in container's /app directory where tests expect files + "use_docker_backend": True, # Enable Docker backend + "docker_container_name": container_name, # Use Terminal-Bench's container + "session_logs_dir": str(session_logs_dir), + "safe_mode": False, # Allow more commands in Docker environment + } + + print(f"Using Docker container: {container_name}") + print(f"Docker working directory: /app") + model_backend_reason = ModelFactory.create( + model_platform=ModelPlatformType.OPENAI, + model_type=ModelType.GPT_4_1, + model_config_dict={ + "stream": False, + }, + ) + + task_id = 'workforce_task' + camel_agent = developer_agent_factory( + model_backend_reason, + task_id, + terminal_toolkit_kwargs + ) + camel_agent.reset() + + usr_msg = f"{instruction}\n" + + # Get response information + response = camel_agent.step(usr_msg) + + total_input_tokens = response.info['usage']['prompt_tokens'] + total_output_tokens = response.info['usage']['completion_tokens'] + + memory_list = camel_agent._memory._chat_history_block.storage.memory_list + + def create_timestamped_marker_from_memory(records: List[dict]) -> Tuple[float, str]: + """Create a timestamped marker from memory records.""" + results = [] + print(f"Total records: {len(records)}") + for record in records: + + if 'func_name' in record['message'].keys(): + timestamp = record['timestamp'] + func_name = record['message']['func_name'] + args = record['message'].get('args', {}) + if args: + command = args.get('command', '') + else: + command = '' + results.append((timestamp, f"Called tool: {func_name} with args: {command}")) + return results + + timestamped_markers = create_timestamped_marker_from_memory(memory_list) + + + return AgentResult( + total_input_tokens=total_input_tokens, + total_output_tokens=total_output_tokens, + failure_mode=FailureMode.NONE, + timestamped_markers=timestamped_markers, + ) diff --git a/pyproject.toml b/pyproject.toml index f0bc01c..2092670 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,5 +7,5 @@ requires-python = "==3.12.*" dependencies = [ "terminal-bench>=0.2.16", "openai>=1.0.0", - "camel-ai @ git+https://github.com/camel-ai/camel.git@agent-summarize", + "camel-ai @ git+https://github.com/camel-ai/camel.git@7bde8ec", ] diff --git a/test.sh b/test.sh index f569785..482bf5f 100755 --- a/test.sh +++ b/test.sh @@ -11,4 +11,10 @@ uv run tb run \ uv run tb run \ --dataset terminal-bench-core==head \ --agent-import-path agents.camel_agent:CamelTerminus \ + --task-id hello-world + + +uv run tb run \ + --dataset terminal-bench-core==head \ + --agent-import-path agents.camel_terminal_agent:CamelTerminalAgent \ --task-id hello-world \ No newline at end of file diff --git a/util/agent_factory.py b/util/agent_factory.py new file mode 100644 index 0000000..0533ef7 --- /dev/null +++ b/util/agent_factory.py @@ -0,0 +1,180 @@ +# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. ========= +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. ========= + +import asyncio +import datetime +import os +import platform +import uuid + +from camel.agents.chat_agent import ChatAgent +from camel.logger import get_logger +from camel.messages.base import BaseMessage +from camel.models import BaseModelBackend, ModelFactory +from camel.societies.workforce import Workforce +from camel.tasks.task import Task +from camel.toolkits import ( + AgentCommunicationToolkit, + NoteTakingToolkit, + TerminalToolkit, + ToolkitMessageIntegration, +) +from camel.types import ModelPlatformType, ModelType +from camel.utils.commons import api_keys_required + +logger = get_logger(__name__) + +WORKING_DIRECTORY = os.environ.get("CAMEL_WORKDIR") + +print(f"Using working directory: {WORKING_DIRECTORY}") + + +def send_message_to_user( + message_title: str, + message_description: str, + message_attachment: str = "", +) -> str: + r"""Use this tool to send a tidy message to the user, including a + short title, a one-sentence description, and an optional attachment. + + This one-way tool keeps the user informed about your progress, + decisions, or actions. It does not require a response. + You should use it to: + - Announce what you are about to do. + For example: + message_title="Starting Task" + message_description="Searching for papers on GUI Agents." + - Report the result of an action. + For example: + message_title="Search Complete" + message_description="Found 15 relevant papers." + - Report a created file. + For example: + message_title="File Ready" + message_description="The report is ready for your review." + message_attachment="report.pdf" + - State a decision. + For example: + message_title="Next Step" + message_description="Analyzing the top 10 papers." + - Give a status update during a long-running task. + + Args: + message_title (str): The title of the message. + message_description (str): The short description. + message_attachment (str): The attachment of the message, + which can be a file path or a URL. + + Returns: + str: Confirmation that the message was successfully sent. + """ + print(f"\nAgent Message:\n{message_title} " f"\n{message_description}\n") + if message_attachment: + print(message_attachment) + logger.info( + f"\nAgent Message:\n{message_title} " + f"{message_description} {message_attachment}" + ) + return ( + f"Message successfully sent to user: '{message_title} " + f"{message_description} {message_attachment}'" + ) + + +def developer_agent_factory( + model: BaseModelBackend, + task_id: str, + terminal_toolkit_kwargs: dict = None, +): + r"""Factory for creating a developer agent.""" + # Initialize message integration + message_integration = ToolkitMessageIntegration( + message_handler=send_message_to_user + ) + + # Initialize toolkits + # terminal_toolkit = TerminalToolkit(safe_mode=True, clone_current_env=False) + terminal_toolkit = TerminalToolkit(**terminal_toolkit_kwargs) + note_toolkit = NoteTakingToolkit(working_directory=WORKING_DIRECTORY) + + # Add messaging to toolkits + terminal_toolkit = message_integration.register_toolkits(terminal_toolkit) + note_toolkit = message_integration.register_toolkits(note_toolkit) + + # Get enhanced tools + tools = [ + *terminal_toolkit.get_tools(), + *note_toolkit.get_tools(), + ] + + # Determine environment info based on Docker usage + if terminal_toolkit_kwargs and terminal_toolkit_kwargs.get('use_docker_backend'): + # Use Docker container environment + system_info = "Linux (Docker Container)" + working_dir = terminal_toolkit_kwargs.get('working_directory', '/app') + env_note = "You are running inside a Docker container. All commands execute within the containerized environment." + else: + # Use host system environment + system_info = f"{platform.system()} ({platform.machine()})" + working_dir = WORKING_DIRECTORY + env_note = "You are running on the host system." + + system_message = f""" + +You are a Lead Software Engineer, a master-level coding assistant with a +powerful terminal. Your role is to solve technical tasks by writing and +executing code, installing necessary libraries, interacting with the operating +system, and deploying applications. + + + +- **System**: {system_info} +- **Working Directory**: `{working_dir}`. {env_note} +- **Current Date**: {datetime.date.today()}. +- **IMPORTANT**: When working with files, use paths relative to the working directory above. + Do NOT use host system paths like /Users/... when in a Docker container. + + + +- When you complete your task, provide a clear summary of what you accomplished. +- Focus on creating files in the correct location as specified by the task. + + + +- **Code Execution**: You can write and execute code in any language to solve tasks. +- **Terminal Control**: You have access to the terminal and can run command-line tools, + manage files, and interact with the OS. Install missing tools with package managers + like `pip3`, `uv`, or `apt-get`. +- **File Operations**: {"Create files directly in the working directory using simple paths like './filename' or 'filename'." if terminal_toolkit_kwargs and terminal_toolkit_kwargs.get('use_docker_backend') else "You can access files from any place in the file system."} +- **Verification**: Test and verify your solutions by executing them. + + + + +- Take action to solve problems. Don't just suggest solutions—implement them. +- Use the terminal effectively to execute commands and manage files. +- Verify your solutions by testing them. + + """ + + return ChatAgent( + system_message=BaseMessage.make_assistant_message( + role_name="Developer Agent", + content=system_message, + ), + model=model, + tools=tools, + # toolkits_to_register_agent=[screenshot_toolkit], + ) + From 0e93272405cb54a6c686548543c63cda7e056e99 Mon Sep 17 00:00:00 2001 From: Xiaotian Jin Date: Tue, 23 Sep 2025 11:15:36 +0300 Subject: [PATCH 2/3] add camel logging --- agents/camel_terminal_agent.py | 87 ++++++++++++++++------------------ pyproject.toml | 2 +- 2 files changed, 42 insertions(+), 47 deletions(-) diff --git a/agents/camel_terminal_agent.py b/agents/camel_terminal_agent.py index 6e0f46c..5f74afa 100644 --- a/agents/camel_terminal_agent.py +++ b/agents/camel_terminal_agent.py @@ -8,10 +8,9 @@ from terminal_bench.terminal.tmux_session import TmuxSession from camel.models import ModelFactory +from camel.logger import enable_logging, set_log_file, set_log_level from camel.types import ModelPlatformType, ModelType -logger = logging.getLogger(__name__) - class CamelTerminalAgent(BaseAgent): @staticmethod @@ -22,50 +21,54 @@ def perform_task( self, instruction: str, session: TmuxSession, - logging_dir: Path | None = None, + logging_dir: Path | None = "logs", ) -> AgentResult: """Execute a task using the Terminal Bench harness. - + Args: instruction: The task instruction to execute session: TmuxSession object for command execution logging_dir: Optional directory for logging - + Returns: AgentResult with token counts and failure mode """ + if logging_dir is None: + raise ValueError("logging_dir is required for CamelTerminalAgent") + + if not isinstance(logging_dir, Path): + logging_dir = Path(logging_dir) + + logging_dir.mkdir(parents=True, exist_ok=True) + + camel_logs_dir = logging_dir / "camel" + camel_logs_dir.mkdir(parents=True, exist_ok=True) + + enable_logging() + set_log_level(logging.DEBUG) + set_log_file(str(camel_logs_dir / "camel_chat_agent.log")) container_name = session.container.name if not container_name: raise ValueError("Container name is required for DockerExecutor") - - # Set up CAMEL working directory for logs and internal operations + camel_workdir = logging_dir / "CAMEL_WORKDIR" - if not camel_workdir.exists(): - camel_workdir.mkdir(parents=True) - - absolute_camel_workdir = str(camel_workdir.resolve()) - os.environ["CAMEL_WORKDIR"] = absolute_camel_workdir - print(f"Set CAMEL_WORKDIR to: {os.environ['CAMEL_WORKDIR']}") - - session_logs_dir = logging_dir / "session" / 'logs' - if not session_logs_dir.exists(): - session_logs_dir.mkdir(parents=True) - print(f"Session logs directory: {session_logs_dir}") + camel_workdir.mkdir(parents=True, exist_ok=True) + os.environ["CAMEL_WORKDIR"] = str(camel_workdir.resolve()) + + session_logs_dir = logging_dir / "session" / "logs" + session_logs_dir.mkdir(parents=True, exist_ok=True) from util.agent_factory import developer_agent_factory - - # Use Terminal-Bench's Docker container with TerminalToolkit's Docker backend + terminal_toolkit_kwargs = { - "working_directory": "/app", # Work in container's /app directory where tests expect files - "use_docker_backend": True, # Enable Docker backend - "docker_container_name": container_name, # Use Terminal-Bench's container + "working_directory": "/app", + "use_docker_backend": True, + "docker_container_name": container_name, "session_logs_dir": str(session_logs_dir), - "safe_mode": False, # Allow more commands in Docker environment + "safe_mode": False, } - - print(f"Using Docker container: {container_name}") - print(f"Docker working directory: /app") + model_backend_reason = ModelFactory.create( model_platform=ModelPlatformType.OPENAI, model_type=ModelType.GPT_4_1, @@ -74,47 +77,39 @@ def perform_task( }, ) - task_id = 'workforce_task' + task_id = "terminal_task" camel_agent = developer_agent_factory( model_backend_reason, task_id, - terminal_toolkit_kwargs + terminal_toolkit_kwargs, ) camel_agent.reset() usr_msg = f"{instruction}\n" - - # Get response information response = camel_agent.step(usr_msg) - total_input_tokens = response.info['usage']['prompt_tokens'] - total_output_tokens = response.info['usage']['completion_tokens'] - + total_input_tokens = response.info["usage"]["prompt_tokens"] + total_output_tokens = response.info["usage"]["completion_tokens"] + memory_list = camel_agent._memory._chat_history_block.storage.memory_list def create_timestamped_marker_from_memory(records: List[dict]) -> Tuple[float, str]: """Create a timestamped marker from memory records.""" results = [] - print(f"Total records: {len(records)}") for record in records: - - if 'func_name' in record['message'].keys(): - timestamp = record['timestamp'] - func_name = record['message']['func_name'] - args = record['message'].get('args', {}) - if args: - command = args.get('command', '') - else: - command = '' + if "func_name" in record["message"].keys(): + timestamp = record["timestamp"] + func_name = record["message"]["func_name"] + args = record["message"].get("args", {}) + command = args.get("command", "") if args else "" results.append((timestamp, f"Called tool: {func_name} with args: {command}")) return results timestamped_markers = create_timestamped_marker_from_memory(memory_list) - return AgentResult( total_input_tokens=total_input_tokens, total_output_tokens=total_output_tokens, failure_mode=FailureMode.NONE, timestamped_markers=timestamped_markers, - ) + ) \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 2092670..99fd5a9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,5 +7,5 @@ requires-python = "==3.12.*" dependencies = [ "terminal-bench>=0.2.16", "openai>=1.0.0", - "camel-ai @ git+https://github.com/camel-ai/camel.git@7bde8ec", + "camel-ai @ git+https://github.com/camel-ai/camel.git@master", ] From f15ec5b844e33cfb2daed16cd7c502804fae3f90 Mon Sep 17 00:00:00 2001 From: Xiaotian Jin Date: Tue, 23 Sep 2025 16:43:23 +0300 Subject: [PATCH 3/3] update agent implementation, add prompts folder --- agents/camel_terminal_agent.py | 150 +++++++++++++++++++++++++++--- prompts/summary_prompt.txt | 20 ++++ prompts/summary_prompt_simple.txt | 15 +++ util/agent_factory.py | 1 + 4 files changed, 172 insertions(+), 14 deletions(-) create mode 100644 prompts/summary_prompt.txt create mode 100644 prompts/summary_prompt_simple.txt diff --git a/agents/camel_terminal_agent.py b/agents/camel_terminal_agent.py index 5f74afa..297bdc9 100644 --- a/agents/camel_terminal_agent.py +++ b/agents/camel_terminal_agent.py @@ -11,28 +11,94 @@ from camel.logger import enable_logging, set_log_file, set_log_level from camel.types import ModelPlatformType, ModelType +MODEL_TYPE = ModelType.GPT_5 +DEFAULT_SUMMARY_DIR = Path("agent_summary") +DEFAULT_CONTEXT_FILENAME = "terminal_task.md" + + +def _find_latest_context_file( + base_dir: Path, filename: str +) -> Path | None: + """Return the newest matching context file within ``base_dir`` if any.""" + + try: + entries = list(base_dir.iterdir()) + except FileNotFoundError: + return None + + newest_path: Path | None = None + newest_mtime: float = float("-inf") + + for entry in entries: + if not entry.is_dir(): + continue + + candidate = entry / filename + if not candidate.exists(): + continue + + try: + mtime = candidate.stat().st_mtime + except OSError: + continue + + if mtime > newest_mtime: + newest_mtime = mtime + newest_path = candidate + + return newest_path + + +def _resolve_default_context_file() -> Path | None: + return _find_latest_context_file(DEFAULT_SUMMARY_DIR, DEFAULT_CONTEXT_FILENAME) + + +DEFAULT_CONTEXT_FILE = _resolve_default_context_file() +with open(Path("prompts/summary_prompt_simple.txt"), "r") as f: + DEFAULT_SUMMARY_PROMPT = f.read() + class CamelTerminalAgent(BaseAgent): @staticmethod def name() -> str: return "CamelTerminalAgent" + def __init__( + self, + *, + load_context: bool = False, + context_working_dir: str | Path | None = None, + context_filename: str | Path | None = None, + summary_working_dir: str | Path | None = DEFAULT_SUMMARY_DIR, + summary_filename: str | None = None, + task_id: str = "terminal_task", + **kwargs, + ) -> None: + super().__init__(**kwargs) + self.load_context = load_context + self.context_working_dir = ( + Path(context_working_dir) + if context_working_dir is not None + else None + ) + self.context_filename = ( + Path(context_filename) if context_filename is not None else None + ) + self.summary_working_dir = ( + Path(summary_working_dir) + if summary_working_dir is not None + else None + ) + self.summary_filename = summary_filename or f"{task_id}.md" + self.task_id = task_id + def perform_task( self, instruction: str, session: TmuxSession, logging_dir: Path | None = "logs", ) -> AgentResult: - """Execute a task using the Terminal Bench harness. - - Args: - instruction: The task instruction to execute - session: TmuxSession object for command execution - logging_dir: Optional directory for logging - - Returns: - AgentResult with token counts and failure mode - """ + """Execute a task using the Terminal Bench harness.""" if logging_dir is None: raise ValueError("logging_dir is required for CamelTerminalAgent") @@ -67,27 +133,60 @@ def perform_task( "docker_container_name": container_name, "session_logs_dir": str(session_logs_dir), "safe_mode": False, + "timeout": 120, } model_backend_reason = ModelFactory.create( model_platform=ModelPlatformType.OPENAI, - model_type=ModelType.GPT_4_1, + model_type=MODEL_TYPE, model_config_dict={ "stream": False, }, ) - task_id = "terminal_task" camel_agent = developer_agent_factory( model_backend_reason, - task_id, + self.task_id, terminal_toolkit_kwargs, ) camel_agent.reset() + if self.load_context: + if self.context_working_dir is None: + raise ValueError( + "context_working_dir must be provided when load_context is True" + ) + if self.context_filename is None: + raise ValueError( + "context_filename must be provided when load_context is True" + ) + + from camel.utils.context_utils import ContextUtility + + context_utility = ContextUtility( + working_directory=str(self.context_working_dir) + ) + context_path = self.context_filename + if not context_path.is_absolute(): + context_path = self.context_working_dir / context_path + context_utility.load_markdown_context_to_memory( + camel_agent, + filename=str(context_path), + ) + usr_msg = f"{instruction}\n" response = camel_agent.step(usr_msg) + summary_kwargs: dict[str, str] = {} + if self.summary_working_dir is not None: + summary_kwargs["working_directory"] = str(self.summary_working_dir) + if self.summary_filename is not None: + summary_kwargs["filename"] = self.summary_filename + summary_kwargs["summary_prompt"] = DEFAULT_SUMMARY_PROMPT + + if summary_kwargs: + camel_agent.summarize(**summary_kwargs) + total_input_tokens = response.info["usage"]["prompt_tokens"] total_output_tokens = response.info["usage"]["completion_tokens"] @@ -112,4 +211,27 @@ def create_timestamped_marker_from_memory(records: List[dict]) -> Tuple[float, s total_output_tokens=total_output_tokens, failure_mode=FailureMode.NONE, timestamped_markers=timestamped_markers, - ) \ No newline at end of file + ) + + +class CamelTerminalAgentWithContext(CamelTerminalAgent): + @staticmethod + def name() -> str: + return "CamelTerminalAgentWithContext" + + def __init__(self, **kwargs) -> None: + default_context = DEFAULT_CONTEXT_FILE + if default_context is None: + raise FileNotFoundError( + "No context file found under agent_summary with name " + f"{DEFAULT_CONTEXT_FILENAME}." + ) + super().__init__( + load_context=True, + context_working_dir=DEFAULT_SUMMARY_DIR, + context_filename=default_context, + summary_working_dir=DEFAULT_SUMMARY_DIR, + summary_filename="terminal_task.md", + task_id="terminal_task", + **kwargs, + ) diff --git a/prompts/summary_prompt.txt b/prompts/summary_prompt.txt new file mode 100644 index 0000000..62a385d --- /dev/null +++ b/prompts/summary_prompt.txt @@ -0,0 +1,20 @@ +Summarize the following conversation as a concise **Run Log** that focuses strictly on executed commands and tool calls and their outputs. + +Requirements: +- Be chronological; keep timestamps if present. +- For each step, capture: command or tool name, exact arguments, key stdout/stderr (trimmed), exit code/finish reason, and any retries. +- Record file system side effects: created/modified/renamed/deleted files, target paths, and brief diff/summary if stated. +- Note environment/context changes: working directory, Docker/container name, env vars toggled, compiler flags, model or tool versions. +- Highlight errors/warnings and how they were resolved. +- List final artifacts (paths) and next actions. + +Format (Markdown): +1) **Run Summary** – 3–5 bullets. +2) **Commands & Outputs** – table with columns: Time | Action | Command/Tool | Output (first lines) | Exit/Reason. +3) **File Changes** +4) **Environment Notes** +5) **Errors & Retries** +6) **Artifacts** +7) **Next Steps** + +Only include facts from the logs; omit general discussion or speculation. diff --git a/prompts/summary_prompt_simple.txt b/prompts/summary_prompt_simple.txt new file mode 100644 index 0000000..3915d09 --- /dev/null +++ b/prompts/summary_prompt_simple.txt @@ -0,0 +1,15 @@ +Summarize this conversation as a simple run log. Focus only on what actually happened. + +Include: +- Commands that were executed +- Files that were created/modified +- Any errors or warnings +- Final results + +Format as markdown with: +1. **What was done** (bullets) +2. **Commands run** (list with outputs) +3. **Files changed** (if any) +4. **Result** (success/failure) + +Be factual - only describe what actually occurred in the logs. \ No newline at end of file diff --git a/util/agent_factory.py b/util/agent_factory.py index 0533ef7..5496842 100644 --- a/util/agent_factory.py +++ b/util/agent_factory.py @@ -175,6 +175,7 @@ def developer_agent_factory( ), model=model, tools=tools, + max_iteration=10, # toolkits_to_register_agent=[screenshot_toolkit], )