Our First Tool

Let’s create a simple tool that can add two numbers and connect it to our room:

import asyncio

# We'll use pydantic to automate the creation of our input schemas.
from meshagent.tools.pydantic import BaseModel, PydanticTool
from meshagent.tools import ToolContext, Toolkit, connect_remote_toolkit

# define the structure of the input of our agent
class Input(BaseModel):
    # We are using "strict" mode in our LLM, so we need to forbid extra properties
    model_config = dict(extra="forbid")
    a: int
    b: int

class Adder(PydanticTool):
    def __init__(self):
        super().__init__(
            name="adder",
            title="sample adder",
            description="an agent that adds two numbers",
            input_model=Input,
        )

    # Our agent will receive content matching the input format, and must return content matching the output format
    async def execute_model(self, context: ToolContext, arguments: Input):        
        result = {
            "result": arguments.a + arguments.b
        }
        print(result)
        return result

async def main():
    room_name = "examples"

    # start our agent in developer mode, it will connect to the room and be available immediately from the admin console UI    
    await connect_remote_toolkit(room_name=room_name, toolkit=Toolkit(name="samples.adder-tool", title="adder", description="a tool that can add two numbers", tools=[ Adder() ]))
                        

if __name__ == '__main__':
    
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    asyncio.get_event_loop().run_until_complete(main())
    

From the studio, if we select “Run” and then “Add Tools” this tool will show up under the “adder” menu. Under the tool description, you will see a play icon and an info icon. Pressing the info icon will show you a JSON schema that you can use to connect this tool to LLMs like OpenAI. Pressing the play icon will allow you to invoke the tool. Press the play icon and an agent will be launched that will generate a user interface to test the agent. If you watch your agent in the console, you will see it print the result when it is invoked.

Calling Tools

By default, a tool that connects to a room is available to everyone in the room. Keep our agent from the previous sample connected to the room, or restart it if you have already stopped it. In another tab, let’s try invoking the tool from another client.

import asyncio

from meshagent.api import RoomClient, websocket_protocol

async def main():
    room_name = "examples"

    async with RoomClient(protocol=websocket_protocol(
        participant_name="sample_user",
        room_name=room_name
    )) as room:
        
        result = await room.agents.invoke_tool(toolkit="samples.adder-tool", tool="adder", arguments={"a":1, "b":2})
        print(f"The result was {result}")       

if __name__ == '__main__':
    
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    asyncio.get_event_loop().run_until_complete(main())
    

Discovering Tools

At any time, a client can discover what tools have been connected to the room. This can be useful if you want to allow your users to be able to grant additional capabilities to your agents at runtime, or even if you just want to give users the ability to use the tools themselves:

import asyncio

from meshagent.api import RoomClient, websocket_protocol

async def main():
    room_name = "examples"

    async with RoomClient(protocol=websocket_protocol(
        participant_name="sample_user",
        room_name=room_name
    )) as room:
        
        toolkits = await room.agents.list_toolkits()

        print(f"The tools connected to our room are:")
        for toolkit in toolkits:
            print(f"\n{toolkit.name}: {toolkit.title} - {toolkit.description}")
            for tool in toolkit.tools:
                print(f"  {tool.name}: {tool.title} - {tool.description}")

if __name__ == '__main__':
    
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    asyncio.get_event_loop().run_until_complete(main())