> ## Documentation Index
> Fetch the complete documentation index at: https://rasa.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Tools

> Typed functions that let a skill take action.

Tools are how a skill *does* things. Look up an account, lock a card, place an
order. A tool is a decorated Python function. Drop it in the skill's `tools/`
folder and it's automatically available; the LLM reads its name, description, and
inputs and decides when to call it.

## Defining a tool

```python skills/check_balance/tools.py theme={null}
from rasa.mantle.tools.decorator import ToolContext, tool
from rasa.mantle.tools.result import ToolResult


@tool(description="Look up account balance by account number")
async def check_balance(
    account_number: str,
    context: ToolContext = None,
) -> ToolResult:
    balance = await call_api(account_number)
    return ToolResult(
        llm_response={"balance": balance, "currency": "USD"}
    )
```

The function signature *is* the schema:

* **Name**: the function name (`check_balance`)
* **Description**: the `@tool` decorator argument
* **Inputs**: extracted from the type hints
* **`context`**: injected by the runtime, never visible to the LLM

Tools are **auto-discovered** from the skill's `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](https://rasa.com/docs/mantle/concepts/instructions.md) body with
its plain name:

```markdown theme={null}
Ask for their account number, then call check_balance and report
the balance clearly.
```

The tool is already in the model's schema whenever the skill is active: naming
it in prose is guidance about *when* to use it, not a reference the compiler
resolves.

## Sharing state with the skill

Tools read and write [memory](https://rasa.com/docs/mantle/concepts/memory.md) through `context`, so their
results are available to the rest of the skill:

```python theme={null}
context.memory.set("current_plan_id", plan.id)
```

Every key you write must be declared in the skill's `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:

```python theme={null}
await context.send(f"Your balance is ${balance}")
```

## When a turn is cancelled

On voice, a user can start talking while your tool is still running. The runtime
ends the turn and raises `asyncio.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](https://rasa.com/docs/mantle/reference/tools.md#cancellation).

## Shared tools

Local tools need no declaration. To use a tool defined outside the skill
folder — one in the agent-root `tools/` folder — add `import_tools` to the
frontmatter:

```yaml theme={null}
import_tools:
  - get_customer_info              # shared, from tools/ at the agent root
```

A shared tool that isn't declared is not available to the skill at all.

## Import MCP tools

To call a tool on a remote MCP server, declare the server in
[`integrations.yml`](https://rasa.com/docs/mantle/reference/integrations-yml#mcp_servers), then allowlist
the tool in the skill:

```yaml integrations.yml theme={null}
mcp_servers:
  - name: banking
    url: http://localhost:8000/mcp/
    token: ${MCP_BANKING_TOKEN}
```

```yaml skills/check_balance/skill.md theme={null}
---
name: Check Balance
description: Look up the customer's account balance.
import_tools:
  - mcp/banking:get_balance
---

Ask for the account number if needed, then call @tool.get_balance and report the
result clearly.
```

`import_tools` is an explicit allowlist: only the tools you list are attached.
The model sees the bare name (`get_balance`); name it in prose like any other
tool. `tool_constraints` use that same bare name.

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](https://rasa.com/docs/mantle/reference/skill-md#import_tools).

## 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](https://rasa.com/docs/mantle/build-guide/tool-constraints.md):

```yaml theme={null}
tool_constraints:
  - check_balance:
      requires: "session.check_balance.account_number"
```

Now `check_balance` is invisible to the LLM until `account_number` is set.

`requires:` is a string expression using the namespaced memory form: see
[Conditions](https://rasa.com/docs/mantle/reference/conditions.md).

When a tool actually runs, Mantle records `tool_executed` with `source` `local`
or `mcp` **and** a matching `mcp_tool_executed` so existing consumers still
match. 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. Older
conversations that stored only `mcp_tool_executed` still load. See
[Tracker events](https://rasa.com/docs/mantle/reference/execution-loop.md#tracker-events).

## Reference

For `ToolContext`, `ToolResult`, invocation modes, tool resolution order, and the
built-in default tools, see the [Tools reference](https://rasa.com/docs/mantle/reference/tools.md).


## Related topics

- [Tools reference](https://rasa.com/docs/mantle/reference/tools.md)
- [Tool Constraints](https://rasa.com/docs/mantle/build-guide/tool-constraints.md)
- [Rasa MCP Tools](https://rasa.com/docs/pro/installation/rasa-mcp-tools.md)
- [Rasa MCP Tools API Reference](https://rasa.com/docs/reference/api/rasa-mcp-tools.md)
- [skill.md](https://rasa.com/docs/mantle/reference/skill-md.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.