diff --git a/ra_aid/agent_backends/ciayn_agent.py b/ra_aid/agent_backends/ciayn_agent.py index eadfe11..2b9138d 100644 --- a/ra_aid/agent_backends/ciayn_agent.py +++ b/ra_aid/agent_backends/ciayn_agent.py @@ -1,5 +1,7 @@ import re import ast +import string +import random from dataclasses import dataclass from typing import Any, Dict, Generator, List, Optional, Union, Tuple @@ -246,6 +248,8 @@ class CiaynAgent: # If we have multiple valid bundleable calls, execute them in sequence if len(tool_calls) > 1: results = [] + result_strings = [] + for call in tool_calls: # Validate and fix each call if needed if validate_function_call_pattern(call): @@ -255,9 +259,13 @@ class CiaynAgent: # Execute the call and collect the result result = eval(call.strip(), globals_dict) results.append(result) + + # Generate a random ID for this result + result_id = self._generate_random_id() + result_strings.append(f"\n{result}\n") - # Return the result of the last tool call - return results[-1] + # Return all results as one big string with tagged sections + return "\n\n".join(result_strings) # Regular single tool call case if validate_function_call_pattern(code): @@ -284,6 +292,18 @@ class CiaynAgent: error_msg, base_message=msg, tool_name=tool_name ) from e + def _generate_random_id(self, length: int = 6) -> str: + """Generate a random ID string for result tagging. + + Args: + length: Length of the random ID to generate + + Returns: + String of random alphanumeric characters + """ + chars = string.ascii_lowercase + string.digits + return ''.join(random.choice(chars) for _ in range(length)) + def extract_tool_name(self, code: str) -> str: """Extract the tool name from the code.""" match = re.match(r"\s*([\w_\-]+)\s*\(", code) diff --git a/ra_aid/prompts/ciayn_prompts.py b/ra_aid/prompts/ciayn_prompts.py index d5ebb58..25f0028 100644 --- a/ra_aid/prompts/ciayn_prompts.py +++ b/ra_aid/prompts/ciayn_prompts.py @@ -93,6 +93,22 @@ PERFORMING WELL AS AN EFFICIENT YET COMPLETE AGENT WILL HELP MY CAREER. 4. WHEN USING put_complete_file_contents, ALWAYS PUT THE ENTIRE FILE CONTENT INSIDE ONE TRIPLE-QUOTED STRING + +When you bundle multiple tool calls in one response, you'll receive results in the following format: + +``` + +First tool result content + + + +Second tool result content + +``` + +Each result will have a unique random ID tag, and the order of results will match the order of your tool calls. + + DO NOT CLAIM YOU ARE FINISHED UNTIL YOU ACTUALLY ARE! Output **ONLY THE CODE** and **NO MARKDOWN BACKTICKS** """ @@ -115,19 +131,6 @@ def main(): \"\"\") - -You can bundle multiple calls to these tools in one response: -- emit_expert_context -- ask_expert -- emit_key_facts -- emit_key_snippet - -Example of bundled tools: -emit_key_facts(["Important fact 1", "Important fact 2"]) -emit_expert_context("Additional context") -ask_expert("Question about this context") - - --- EXAMPLE GOOD OUTPUTS --- @@ -169,5 +172,13 @@ CORRECT: put_complete_file_contents("/path/to/file.py", \"\"\"def main(): print("Hello") \"\"\") -NOTE: You can also bundle multiple calls to certain tools (emit_expert_context, ask_expert, emit_key_facts, emit_key_snippet) in one response. +NOTE: You can also bundle multiple calls to certain tools (emit_expert_context, ask_expert, emit_key_facts, emit_key_snippet, and others) in one response. When bundling tools, each result will be returned with a unique random ID tag in this format: + + +First tool result content + + + +Second tool result content + """ \ No newline at end of file diff --git a/tests/agent_backends/test_bundled_tools.py b/tests/agent_backends/test_bundled_tools.py index 801a80f..8d14907 100644 --- a/tests/agent_backends/test_bundled_tools.py +++ b/tests/agent_backends/test_bundled_tools.py @@ -120,8 +120,12 @@ ask_expert("What does this mean?")''' # Execute result = agent._execute_tool(mock_message) - # Assert - assert result == "Expert answer" # Should return the result of the last tool call + # Assert: We now verify that the result contains both tool call results with tagging + assert "