ToolkitBuilder + ToolkitConfig, so agents only enable the tools they need when they need them.
Mental Model (how tool concepts fit together)
Tool= one discrete action an agent (or human participant) can take (e.g., WriteDocument, PresentForm).ToolContext= everything a tool needs when it runs (the active room, who called, optional “on behalf of”, extra caller context).Toolkit= a named bundle of tools plus optional rules (e.g., DocumentWritingToolkit with tools toread_documentandsummarize_documentalong with instructions for how to use these tools).RemoteToolkit= a runtime wrapper that registers your toolkit with the room, listens for tool calls, validates inputs, runs the tool, and returns a structured Response.ToolkitConfig= the options for constructing a toolkit (from simplenameto rich per-toolkit settings).ToolkitBuilder= factory that turns aToolkitConfiginto a concreteToolkit(used for dynamic, per-message toolkits).
Tools
Tool
A Tool defines an action that an agent or person can perform. The tool declares what it expects in the input_schema and what actions to perform in its execute() method.
Constructor Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
name | str | — | Unique tool name within a toolkit. |
input_schema | dict | — | JSON Schema for the tool’s arguments. Enforced at call time. |
title | Optional[str] | name | Human-readable display name. |
description | Optional[str] | "" | Short description of the tool. |
rules | Optional[list[str]] | None | Behavioral guidance/prompts for LLMs. |
thumbnail_url | Optional[str] | None | Icon/thumbnail shown in UIs. |
defs | Optional[dict[str, dict]] | None | Reusable JSON Schema definitions. Merged into the schema via $defs. Use to avoid repeating complex shapes. |
supports_context | Optional[bool] | False | Indicates the tool can use caller_context when provided. |
execute() method where its logic is implemented.
Python
Tool Return Types
Tools return subclasses ofResponse declared in meshagent.api.messaging. Use these helpers so the room can transport the result (and any usage metrics) in the proper format.
| Response type | When to use it |
|---|---|
JsonResponse | Structured JSON output (e.g., API payloads, summarized data). |
TextResponse | Plain-text answers or status messages. |
FileResponse | Binary content such as generated documents, images, or archives. |
LinkResponse | Share a URL pointing to an external resource (e.g., dashboard link). |
ToolContext
MeshAgent tools are passed a ToolContext when the tool is executed. This object carries a variety of information that helps the tool operate:
Constructor Parameters
| Property | Description |
|---|---|
| room | A room client that can be used to interact with the room or other participants in the room. |
| caller | The participant who called the tool. |
| on_behalf_of | If the tool was called by an agent that was acting on behalf of a user, the participant who invoked the agent. |
| caller_context | An optional dictionary of caller specific context data, this can be used to provide custom context data to the tool. For instance, this can be used for allowing agent based tools to receive the current chat context for implementing patterns such as handoffs. |
Toolkits
Toolkits vs Remote Toolkits
AToolkit is best for in-process scenarios, typically used when only one agent needs access to the tools in the toolkit.
A RemoteToolkit is hosted and registered with the room so any participant (human or agent) can discover and call its tools. Typically used when the toolkit needs to live outside the agent’s process or must be available to multiple participants.
Toolkit
A Toolkit bundles related tools under a single name so callers can discover, invoke, and permission them together. When a call arrives the toolkit looks up the tool, validates inputs, executes the tool, and ensures a valid return type.
Constructor Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
name | str | — | Toolkit identifier used for discovery/invocation. |
tools | list[BaseTool] | — | The tools this toolkit exposes. |
rules | list[str] | list[str] | Optional global guidance/prompts that apply to all tools in the toolkit. |
title | Optional[str] | name | Human-readable toolkit name. |
description | Optional[str] | "" | Description of the toolkit which can aid discovery and appears in MeshAgent Studio. |
thumbnail_url | Optional[str] | None | Icon/thumbnail for the toolkit. |
get_tool(name): returns the named tool or raises aRoomExceptionif it is not present.execute(context, name, arguments, optional attachment):- For a
Tool, validates the arguments withinput_schema/$defs, invokes the tool, and returns a response.
- For a
Note: Toolkits emit OpenTelemetry spans out of the box. This will automatically track information like who called a tool, how long the tool took to return a result, and what room the tool was used in. You can set additional span attributes or usage meters in your tool implementation to enrich observability.
RemoteToolkit
A RemoteToolkit adds lifecycle management around a Toolkit so it can be discoverable and callable by others.
Methods
start():- Starts any child
RemoteToolinstances - Subscribes to messages on the toolkits channel. This is how the room notifies the toolkit that a participant wants to run one of its tools. This is what allows your tools to be invoked remotely by any participants in the room
- Registers the toolkit with the room as public by default (this makes the tools and toolkit discoverable to other room participants)
- Starts any child
stop():- Stops child
RemoteToolsafely - Unregisters the toolkit
- Stops child
ToolkitBuilder and ToolkitConfig (dynamic toolkits)
Static toolkits are great when you always need the same tools. But many capabilities are situational (e.g., only enable MCP when the user asks for a connector, only enable storage when a file is attached, allow a user to add and remove tools through a UI).ToolkitBuilder + ToolkitConfig let you construct a toolkit on demand, even per message, so you don’t have to declare every tool up front.
ToolkitConfig: Captures the definition/options for a toolkit. Simple toolkits can just use aname. Complex ones add fields (e.g., which MCP servers to expose, whether storage writes are allowed, what model and image size to use for an image generation tool).ToolkitBuilder: A tiny factory that says “I can build toolkits named X from config type Y” and implementsmake(model, config) → Toolkit.
Note :You can still instantiate Toolkit(...) directly for always-on tools. Builders are for the dynamic cases.
How it works
- The caller provides any applicable
ToolkitConfigs for this turn / thread. For example, adding tools to a ChatBot through the MeshAgent Studio UI, or passing tools to themeshagent chatbot joinCLI command. - Call
make_tools(model, providers, tools=configs)(in standardChatBotflows this is called for you; if you’re integrating directly, call it yourself). It:- Matches each config’s
nameto aToolkitBuilder.nameinproviders - Validates the config
- Calls
builder.make(model, config)to create theToolkitwhich exposes applicableTools for the agent
- Matches each config’s
- The agent receives both the dynamically constructed toolkits and statically declared ones.
Tool Access and Availability
RequiredToolkit
Agents can declare a dependency on a toolkit by declaring:
Python
Tool Access and Permissions
Tool access is controlled by the participant token’sApiScope.agents grant:
register_public_toolkit/register_private_toolkit: allow registering toolkits that are visible to everyone or only the user who registers it and the agents they are interacting with.use_tools: required to list or inspect toolkits.call: required to invoke tools.
use_tools. Private toolkits are only listed for the participant that registered them. Adjust these flags via API scope grants to decide which services or users can call tools in each room.
Next Steps
- Tools Quickstart: Try creating and running your first tool.
- Dynamic UI Tools: Understand what dynamic UI tools are, why they matter, and how to build them.
- Tool Usage Patterns: Compare static toolkits with dynamic builder-driven toolkits and see how message-level selection works.