Dynamic User Interfaces

Dynamic User Interfaces enable agents to interact directly with users by presenting responsive, on-demand interfaces. With the ability to execute tools remotely, MeshAgent empowers agents to invoke and leverage user interface tools as needed.

Private Tool Registrations

Consider a collaborative environment where multiple users work alongside a group of agents. In such scenarios, agents may occasionally need to engage individual users—for example, to display notifications, request files, or gather specific information. To facilitate these interactions, the application can register specialized tools that agents can call upon.

How does an agent target a specific user with a dialog?
MeshAgent addresses this by supporting private tool registrations. When a user interface registers a private tool, that tool is accessible only to the registering user. An agent can then invoke this private tool by including the unique identifier of the user (the participant ID) in its call. This ensures that the interface is displayed solely to the intended recipient.

For instance, let’s update our Adder agent sample: instead of the studio collecting parameters externally, the agent now directly prompts the user for input by invoking the relevant private tool.


import asyncio

# We'll use pydantic to automate the creation of our input and output schemas.
from meshagent.agents.pydantic import PydanticAgent, BaseModel
from meshagent.agents import AgentCallContext, connect_development_agent

# define the structure of the input of our agent
class Input(BaseModel):
    model_config = dict(extra="forbid")

# define the structure of the output of our agent
class Output(BaseModel):
    model_config = dict(extra="forbid")
    result: float

class Adder(PydanticAgent):
    def __init__(self):
        super().__init__(
            name="samples.tool-adder",
            title="sample adder",
            description="an agent that adds two numbers",
            input_model=Input,
            output_model=Output,
        )

    # Our agent will receive content matching the input format, and must return content matching the output format
    async def ask_model(self, context: AgentCallContext, arguments: Input) -> Output:        

        # The studio has a few built in tools for interacting with users. we'll use the ask_user tool which presents a form
        # and waits for the user to fill it out, and then returns the results.
        response = await context.room.agents.invoke_tool(
            participant_id=context.caller.id,
            toolkit="ui",
            tool="ask_user",
            arguments={
                "subject" : "I need some information",
                "description" : "please give me some information",
                "form" : [
                    {
                        "input" : {
                            "multiline" : False,
                            "name" : "a",
                            "description" : "input a number",
                            "default_value" : "5"
                        },
                    },{
                        "input" : {
                            "multiline" : False,
                            "name" : "b",
                            "description" : "input a number",
                            "default_value" : "5"
                        }
                    }
                ]
            })

        a = float(response["a"])
        b = float(response["b"])

        return Output(result=a + b)

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_development_agent(room_name=room_name, agent=Adder())
            
            

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

Run the agent, connect to the “examples” room, and then invoke the agent from the Tasks menu in the studio. The agent will gather the inputs from the user and then return the result.

Intergrating with Your Own Applications

The studio registers a set of user interface tools which you can use right away. To enable your agents to work either inside the Meshagent Studio or inside your own applications, your user interface can register a toolkit with the same name, and tools with the same name and schema as the ones available inside the studio. Then, when a participant from your own application invokes the tool, it will display your application’s custom interface but it will continue to be usable directly from the studio. The key thing to remember is that the application needs to use a private tool registration so that it does not conflict with the studio.