-
Notifications
You must be signed in to change notification settings - Fork 386
Description
Intro
Help needed on designing and implementing a truly flexible tool system for Cat v2 agents.
Background
In v2 tools will come from three different places:
1 - MCP servers
2 - global tools (defined in plugins) with the @tool decorator
3 - agent specific tools (defined in plugins, directly in the agent class)
1 and 2 already work, this issue is on 3.
Agent specific tools
Tools available to an agent come from the agent.list_tools() method. The method gives out a list of CatTool objects to be passed to agent.llm(...) alongside messages and other params. Example of the typical agentic loop is found in the default agent:
while True:
llm_mex: Message = await self.llm(
# delegate prompt construction to plugins
await self.get_system_prompt(),
# pass conversation messages
messages=self.chat_request.messages + self.chat_response.messages,
# pass tools (both internal and MCP)
tools=await self.list_tools(),
# whether to stream or not
stream=self.chat_request.stream,
)
# do stuff with the messageI'll probably wrap this loop in a method like agent.inner_loop() so it can be reused or overridden at your pleasure. The issue here regards list_tools.
How list_tools work
The method is included in BaseAgent:
async def list_tools(self) -> List[CatTool]:
"""Get both plugins' tools and MCP tools in CatTool format."""
mcp_tools = await self.mcp.list_tools()
mcp_tools = [
CatTool.from_fastmcp(t, self.mcp.call_tool)
for t in mcp_tools
]
tools = await self.execute_hook(
"agent_allowed_tools",
mcp_tools + self.mad_hatter.tools
)
return toolsWhat is missing here are tools defined in the agent itself, in the most simple way possible.
Something like (in a plugin):
from cat import tool, BaseAgent
class MyAgent(BaseAgent):
async def execute(self):
# ...
@tool
async def get_weather(self, city: str):
# possibility here to use `self.xxx`
return xNote cat is not needed here, as the BaseAgent has CatMixin allowing it to access user, execute hooks, and do everything that was previously possible to do with cat in the tool arguments.
So in your own agent, it will be possible to:
- ignore
list_toolsand passCatToolobjects manually, or none - call
list_toolsto give your agent all the tools available (eventually filtered byagent_allowed_toolshook that was already active in v1) - override
list_toolsin your agent to define a custom logic
What to do
Method list_tools should add to the list also class based tools.
I don't know if CatTool.from_decorated_function will work or requires adjustments or another constructor is necessary. The self argument there must be taken into account, also in the decorator function.
Comments are welcome if you get ideas on the design. Most agent libraries assume you give to the agent the list of tools at construction and you let it run. This is an amateurish approach, and we're gonna make school on this as we already made school on many other primitives.
If available to implement the feature, wait for direct assignation.
I'll open many issues on v2 in the next days :)
Thanks
P.S.: instructions on how to install v2 are available in V2_DEV_NOTES.md.
P.S.: tests are broken in branch v2 and many bugs around. Will be fixed and available later on.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status