Skip to content

[FEATURE] Allow passing invocation states to sub-agents as tools #579

@daixba

Description

@daixba

Problem Statement

When using Agents as Tools, there is no an easy way to pass the invocation states to sub agents, especially for non JSON serializable objects that we can't stored in agent states. One example is that we need to share a message queue (asyncio.Queue) that we can store all messages from both coordinator and sub-agents.

Also, there are some inconsistence in the tools design: For module based tools, we can pass the invocation states but not for the tools via decorator.

Proposed Solution

In module based tools, we can add a keyword parameter such as

def weather(tool: ToolUse, **kwargs: Any) -> ToolResult:
    ...

In this case, the agent invocation states will be passed to the tool

if inspect.iscoroutinefunction(self._tool_func):
    result = await self._tool_func(tool_use, **invocation_state)
else:
    result = await asyncio.to_thread(self._tool_func, tool_use, **invocation_state)

Hence, we can have similar design in tools decoractor.

Below is an expected example

@tool
def teacher(query: str, **kwargs):
    agent = kwargs.get("agent")

In this case, we can also use keyword parameter to get the agent information. So we don't need to maintain a unique logic to accept agent as a special parameter in the tool function. But for backwards compatibility, we can still keep it.

So here is a full example.

from strands import Agent
from strands.tools import tool

@tool
def teacher(query: str, **kwargs):
    hidden_number = kwargs.get("hidden_number")
    agent = kwargs.get("agent")
    print(f"Getting query from {agent.name}")

    teacher_agent = Agent(name="teacher", system_prompt=f"You're a math teacher help with math problems. You have got an hidden number {hidden_number} and you must use it in the calculation")
    
    return teacher_agent(query)


coordinator = Agent(name="coordinator", system_prompt="You're a coordinator, always pass your query to teacher agent", tools=[teacher])
invocation_state = {"hidden_number": 3}
response = coordinator("times 2", **invocation_state)

Use Case

This is to allow passing invocation states to sub-agents as tools, especially for non JSON serializable objects that we can't stored in agent states. One example is that we need to share a message queue (asyncio.Queue) that we can store all messages from both coordinator and sub-agents.

Alternatives Solutions

No response

Additional Context

No response

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions