Skip to content

Commit 3649bd2

Browse files
committed
Add support for the Agents-as-Tools pattern
1 parent b4e472c commit 3649bd2

File tree

3 files changed

+46
-10
lines changed

3 files changed

+46
-10
lines changed

coagent/agents/react_agent/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@
88
ToolCallOutputItem,
99
ToolCallProgressItem,
1010
)
11+
from .subagent import Subagent

coagent/agents/react_agent/agent.py

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
from .messages import InputHistory, OutputMessage
4242
from ..model import default_model, Model
4343
from .converter import Converter
44+
from .subagent import Subagent, SubagentTool
4445

4546
FAKE_ID = "__fake_id__"
4647

@@ -98,15 +99,36 @@ def model_settings(self) -> ModelSettings:
9899
return self._model_settings
99100

100101
async def started(self) -> None:
101-
# Extract MCP clients from tools list
102-
mcp_clients = [tool for tool in self._tools if isinstance(tool, mcputil.Client)]
102+
final_tools: list[Callable] = []
103103

104-
# Filter out MCP clients from tools list
105-
self._tools = [
106-
tool for tool in self._tools if not isinstance(tool, mcputil.Client)
104+
mcp_clients: list[mcputil.Client] = []
105+
subagents: list[Subagent] = []
106+
107+
for tool in self._tools:
108+
if isinstance(tool, mcputil.Client):
109+
mcp_clients.append(tool)
110+
elif isinstance(tool, Subagent):
111+
subagents.append(tool)
112+
else:
113+
final_tools.append(tool)
114+
115+
# Load tools from MCP clients
116+
mcp_tools = await self._load_mcp_tools(mcp_clients)
117+
final_tools.extend(mcp_tools)
118+
119+
# Create tools from subagents
120+
subagent_tools = [
121+
SubagentTool(self, subagent).as_tool() for subagent in subagents
107122
]
123+
final_tools.extend(subagent_tools)
124+
125+
self._tools = final_tools
126+
127+
async def _load_mcp_tools(
128+
self, mcp_clients: list[mcputil.Client]
129+
) -> list[Callable]:
130+
"""Load tools from all MCP clients concurrently."""
108131

109-
# Load tools from all MCP clients concurrently
110132
async def get_client_tools(client):
111133
try:
112134
return await client.get_tools()
@@ -120,9 +142,7 @@ async def get_client_tools(client):
120142
*[get_client_tools(client) for client in mcp_clients]
121143
)
122144

123-
# Add all tools to the tools list
124-
for mcp_tools in all_mcp_tools:
125-
self._tools.extend(mcp_tools)
145+
return [tool for sublist in all_mcp_tools for tool in sublist]
126146

127147
@handler
128148
async def handle_history(

coagent/agents/react_agent/context.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
from typing_extensions import TypeVar
88

9-
from .types import FunctionToolCallProgressItem, ToolCallProgressItem
9+
from .types import FunctionToolCallProgressItem, ToolCallProgressItem, StreamEvent
1010

1111
TData = TypeVar("TData", default=Any)
1212

@@ -41,6 +41,17 @@ def with_tool(
4141
tool=ToolData(name=name, call_id=call_id, arguments=arguments),
4242
)
4343

44+
@property
45+
def full_tool_name(self) -> str:
46+
if not self.tool:
47+
return ""
48+
49+
name = self.tool.name
50+
if self.parent and self.parent.full_tool_name:
51+
name = f"{self.parent.full_tool_name}/{name}"
52+
53+
return name
54+
4455
@property
4556
def data(self) -> TData | None:
4657
"""Get the underlying data object."""
@@ -73,6 +84,10 @@ def report_progress(
7384
),
7485
type="tool_call_progress_item",
7586
)
87+
self.put_event(event)
88+
89+
def put_event(self, event: StreamEvent) -> None:
90+
"""Put an event into the event queue."""
7691
if self.queue:
7792
self.queue.put_nowait(event)
7893

0 commit comments

Comments
 (0)