Skip to content

Reusing a BaseArchytasModel causes tool/prompt leakage between agents #76

Description

@david-andrew

When a BaseArchytasModel config (namely OpenAIModel, but perhaps others) is shared between two ReActAgents, the tools the models see leak even if they have completely different tools

Minimal Example

from archytas.react import ReActAgent
from archytas.models.openai import OpenAIModel
from archytas.tool_utils import tool
import os
import asyncio


@tool
def PARENT_AGENT_EXCLUSIVE_TOOL() -> None:
    """
    A PARENT tool to test the system

    Returns:
        None: The tool does not return a value.
    """
    return None

@tool
def SUBAGENT_EXCLUSIVE_TOOL() -> None:
    """
    A SUBAGENT tool to test the system
    
    Returns:
        None: The tool does not return a value.
    """
    return None

class SubAgentTool:
    def __init__(self, model: OpenAIModel):
        # self._toolset = Toolset()
        self._subagent = ReActAgent(
            model=model,
            tools=[SUBAGENT_EXCLUSIVE_TOOL],
            verbose=True,
            allow_ask_user=False,
            spinner=None,
        )
        self._subagent.add_context("You are a helpful assistant.")
    
    @tool
    async def delegate(self, request: str) -> str:
        """
        Delegate a request to the subagent.
        
        Args:
            request (str): The request to delegate.
        Returns:
            str: The response from the subagent.
        """
        return await self._subagent.react_async(request)




def get_broken_agent():
    archytas_model = OpenAIModel({'api_key': os.getenv('OPENAI_API_KEY'), 'model_name': 'gpt-4.1'})
    subagent = SubAgentTool(archytas_model)
    agent = ReActAgent(
        model=archytas_model,
        tools=[subagent, PARENT_AGENT_EXCLUSIVE_TOOL],
        verbose=True,
        allow_ask_user=False,
        spinner=None,
    )
    agent.add_context("You are a helpful assistant.")
    return agent

def get_working_agent():
    subagent = SubAgentTool(OpenAIModel({'api_key': os.getenv('OPENAI_API_KEY'), 'model_name': 'gpt-4.1'}))
    agent = ReActAgent(
        model=OpenAIModel({'api_key': os.getenv('OPENAI_API_KEY'), 'model_name': 'gpt-4.1'}),
        tools=[subagent, PARENT_AGENT_EXCLUSIVE_TOOL],
        verbose=True,
        allow_ask_user=False,
        spinner=None,
    )
    agent.add_context("You are a helpful assistant.")
    return agent


async def main():
    agent = get_broken_agent()
    # agent = get_working_agent()
    print('-'*80)
    print('PARENT AGENT TOOLS:\n'+await agent.react_async("please list all tools you have access to"))
    print('-'*80)
    print('SUBAGENT TOOLS:\n'+await agent.react_async("please call the delegate tool and tell it to list all the tools it has access to"))
    

if __name__ == '__main__':
    asyncio.run(main())

Example Explanation

  • parent ReActAgent with a PARENT_AGENT_EXCLUSIVE_TOOL, and a SubAgentTool
  • SubAgentTool contains an internal ReActAgent with a SUBAGENT_EXCLUSIVE_TOOL

The idea for this setup is the main agent may want to use its own other tools or delegate tasks to the subagent which can specialize in its subagent tools.

In the example, the lines

agent = broken_setup()
# agent = working_setup()

determine whether to run the broken version demonstrating the bug or the fixed version

Example output:

(when running the broken version)

$ python minimal_archytas_bug.py 
None of PyTorch, TensorFlow >= 2.0, or Flax have been found. Models won't be available and only tokenizers, configuration and file/data utilities can be used.
--------------------------------------------------------------------------------
PARENT AGENT TOOLS:
Here are the tools I have access to:

1. final_answer: Used to provide a final response or summary to your request.
2. fail_task: Used to indicate if a task cannot be completed, along with an explanation.
3. PARENT_AGENT_EXCLUSIVE_TOOL: A system tool for testing purposes.
4. delegate: Used to delegate a request to a subagent.
5. retrieve_summarized_messages_of_summary: Used to retrieve the full contents of previously summarized messages.
6. multi_tool_use.parallel: Used to run multiple tools in parallel when appropriate.

If you need more details about any specific tool or want to know how they work, feel free to ask!
--------------------------------------------------------------------------------
thought: Calling tool 'delegate'
tool: delegate
tool_input: {'request': 'List all the tools you have access to.'}

observation: I have access to the following tools:

1. final_answer: Used to provide a final response to your request, summarizing 
results or answering your question.
2. fail_task: Used to indicate if I am unable to complete your request, along 
with an explanation.
3. delegate: Allows me to delegate a request to a subagent for further 
processing.
4. retrieve_summarized_messages_of_summary: Retrieves the full, raw contents of 
previously summarized messages.
5. PARENT_AGENT_EXCLUSIVE_TOOL: A parent tool for system testing purposes.
6. multi_tool_use.parallel: Allows me to run multiple tools in parallel if they 
can operate independently.

If you need more details about any specific tool or want to know how they work, 
feel free to ask!

SUBAGENT TOOLS:
The delegate tool responded with the following list of tools it has access to:

1. final_answer: Provides a final response or summary to a request.
2. fail_task: Indicates if a task cannot be completed, with an explanation.
3. delegate: Delegates a request to a subagent.
4. retrieve_summarized_messages_of_summary: Retrieves the full contents of previously summarized messages.
5. PARENT_AGENT_EXCLUSIVE_TOOL: A system tool for testing purposes.
6. multi_tool_use.parallel: Runs multiple tools in parallel when appropriate.

If you need more details about any specific tool or want to know how they work, let me know!

Notice that the subagent lists PARENT_EXCLUSIVE_TOOL as one of its tools, even though it does not have access to it. Also notice that it does not list SUBAGENT_EXCLUSIVE_TOOL which it should have access to.

Problem

If you reuse the OpenAIModel config between the parent and the sub agents, the sub agent thinks it has access to all of the parent's tools, and none of its own tools. But this is only in the prompt, the subagent object only has references to its own tools. So then if the subagent tries to call one of the parent tools, it will not succeed because the parent tools aren't actually present. And the subagent won't ever call its own tools because it can't see them

Solution

I have no idea what is causing this. Technically not a show stopper if you're aware of it, but it does make reusing model configurations a bit of a pain. If you're not aware of it, it causes the most confounding bugs 🤣

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions