tools/
folder and it’s automatically available; the LLM reads its name, description, and
inputs and decides when to call it.
Defining a tool
skills/check_balance/tools.py
- Name: the function name (
check_balance) - Description: the
@tooldecorator argument - Inputs: extracted from the type hints
context: injected by the runtime, never visible to the LLM
tools.py (or a tools/ folder,
if you’d rather split them across files). No imports, no registration. The LLM
sees the tool and calls it when the instructions call for it.
The tool must be async, and the injected parameter must be named exactly
context.
Using a tool in instructions
Reference a tool from the instructions body with its plain name:Sharing state with the skill
Tools read and write memory throughcontext, so their
results are available to the rest of the skill:
memory.yml or the
project-root one. rasa train rejects an undeclared write.
A tool can also send a message to the user directly, bypassing the LLM. It is a
coroutine, so it must be awaited:
When a turn is cancelled
On voice, a user can start talking while your tool is still running. The runtime ends the turn and raisesasyncio.CancelledError inside your tool at whatever
await it is suspended on. Read-only tools can ignore this. For a tool that
changes something, check context.is_cancelled before the irreversible step.
See Cancellation.
Shared tools
Local tools need no declaration. To use a tool defined outside the skill folder — one in the agent-roottools/ folder — add import_tools to the
frontmatter:
Import MCP tools
To call a tool on a remote MCP server, declare the server inintegrations.yml, then allowlist
the tool in the skill:
integrations.yml
skills/check_balance/skill.md
import_tools is an explicit allowlist: only the tools you list are attached.
The tool arrives under its bare name (get_balance), which is what
tool_constraints use. In the body, refer to it as @tool.get_balance, the same
form as any other tool.
If the same bare name would collide with a local or shared tool in that skill,
train fails. If the server cannot be reached when the agent starts, startup
fails. Full rules are in the skill.md reference.
Adding guarantees
By default the LLM decides when to call a tool, and it can get it wrong. Gate a tool behind a required value with tool constraints:check_balance is invisible to the LLM until account_number is set.
requires: is a string expression using the namespaced memory form: see
Conditions.
When a tool actually runs, Mantle records tool_executed with source local
or mcp. For MCP tools, mcp_server is the MCP server name (the mcp_servers:
key in integrations.yml, same id as in mcp/<server>:<tool>) so two servers
that expose the same tool name stay distinct. Local tools omit it. See
Tracker events.
Handing off to another skill from a tool
A tool can end by activating another skill. Return anActivateSkill in
ToolResult.next:
call
step: the current skill waits and continues when the new skill finishes. To
start one ordered block of the skill, pass ordered_block="<block_id>". See
ActivateSkill for when it runs and which
tools honour it.
To call another tool from a tool, call it as plain Python:
await other_tool(..., context=context).
Reference
ForToolContext, ToolResult, invocation modes, tool resolution order, and the
built-in default tools, see the Tools reference.