# Tool approvals

URL: https://docs.assistantcore.com/en/tools-mcp/approvals

Choose which tool calls run on their own, wait for a person to approve them, or never run, in chat and in scheduled tasks.



Tools that change things outside the chat, such as sending an email or running a command on a server, wait for a person to approve the exact call before they run. Approval rules let people skip the question for calls they trust, and let the assistant's owner allow, require approval for, or block calls for everyone.

## Which calls ask first [#which-calls-ask-first]

Without a rule, the assistant decides from what each tool declares:

| Tool                                           | What it does                                                                                               | Without a rule             |
| ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | -------------------------- |
| [Built-in tools](/en/tools-mcp/built-in-tools) | Knowledge base, memory, web, images…                                                                       | Run. Rules can't name them |
| Reading tool                                   | MCP tool with `readOnlyHint`, or custom API tool with `GET`                                                | Runs                       |
| Writing tool                                   | Anything else, including MCP tools that declare nothing and custom API tools with `POST`, `PUT` or `PATCH` | Asks first                 |
| Destructive tool                               | MCP tool with `destructiveHint`, or custom API tool with `DELETE`                                          | Asks first, every time     |

An MCP tool is judged by the hints it declared when its tools were last approved with **Refresh tools**, not by what the server says later. See [MCP Server](/en/tools-mcp/mcp-server) and [MCP Endpoint](/en/tools-mcp/mcp-endpoint).

## Approve a call in chat [#approve-a-call-in-chat]

When the assistant needs a call that asks first, the Web App chat shows an **Approval needed** card with the tool, its app and its arguments (or the command line, for a tool that runs shell commands). The turn stops until you decide:

* **Approve and run** runs that exact call once. The assistant then continues with the result.
* **Deny** does not run it. The assistant continues knowing you declined.

To skip the question next time, tick the box on the card before you click **Approve and run**:

| Tool                          | Box on the card                                                    | What it allows from then on                                                      |
| ----------------------------- | ------------------------------------------------------------------ | -------------------------------------------------------------------------------- |
| Writing tool                  | **Don't ask again for … on this assistant**                        | Every call of that tool                                                          |
| Tool that runs shell commands | **Don't ask again on this assistant for commands starting with** … | Commands starting with the words shown, such as `git status`, not the whole tool |
| Destructive tool              | Not offered                                                        | Nothing. It asks every time                                                      |

The box is also not shown when the owner has set **Ask** or **Block** for every call of that tool.

A card that waits too long expires: after 24 hours, or as soon as you send a new message in that conversation. Ask again if you still want it.

## Your saved rules [#your-saved-rules]

Rules you save from a card are yours, on that assistant only. They apply to your chats and your [scheduled tasks](#scheduled-tasks).

To see or remove them, open **Settings → Approvals** in the Web App. **Allowed without asking** lists your rules; click **Remove** to be asked again. The rules the owner set for everyone are listed under **Set by the assistant's owner**; you can't change them.

## Rules for everyone [#rules-for-everyone]

The assistant's owner sets rules that apply to everyone who uses the assistant.

**Prerequisites:** the **Assistant Owner** role. An **Assistant Admin** can view the rules but not change them.

1. Open the [Admin Panel](https://admin.assistantcore.com) and select the assistant.
2. Go to **Approvals**.
3. Under **Rules for everyone**, click **Add rule**.
4. Choose the **Tool**. The list has custom API tools, MCP server tools and MCP Endpoint tools; built-in tools always run.
5. Under **Applies to**, choose **Every call**, or, for a tool that runs shell commands, **Commands starting with…** and enter a **Command prefix** such as `git status`.
6. Under **What happens**, choose one:
   * **Allow**: runs without asking.
   * **Ask**: waits until the person approves it.
   * **Block**: never runs; the assistant says it is blocked.
7. Click **Add rule**.

When several rules match a call, **Block** wins over **Ask**, and **Ask** over **Allow**. People can only save Allow rules, so they never override your Ask or Block.

The **Saved by people** card lists the rules people saved from approval cards, with who saved them. Click **Revoke** to make that person be asked again.

<Callout type="warn">
  Choosing **Allow** with **Every call** on a destructive tool lets the assistant delete or change data without asking anyone. Prefer a command prefix, or leave it on Ask.
</Callout>

## Shell command rules [#shell-command-rules]

A tool that runs shell commands can be matched by command, not just as a whole. This works for MCP Endpoint tools that name the argument holding the command line in `_meta.assistant_platform.shell_argument`, such as the `bash` tool in [mcp-bash](https://github.com/assistant-core/mcp-bash).

* A prefix matches whole words: `git` matches `git log`, not `gitk`.
* A line with several commands, such as `git status && rm -rf x`, runs without asking only when **every** command in it is allowed.
* A line with `$(…)`, backticks, redirections, variable assignments or several lines is never allowed by a prefix rule.
* Commands that run other commands (`sudo`, `bash -c`, `xargs`, `env`, `ssh`, `python`, `node`, `find`…) can only be set to **Ask** or **Block**, never allowed by prefix.

If you build such a tool, declare `shell_argument` (a string parameter, for example `"command"`), then click **Refresh Tools** on the **MCP** page so Assistant Core picks it up.

## Where nobody can approve [#where-nobody-can-approve]

On the [Web Widget](/en/web-widget), the [Developer API](/en/developers), voice and [messaging](/en/messaging) channels, there is no approval card:

| Call                                     | What happens there                                                      |
| ---------------------------------------- | ----------------------------------------------------------------------- |
| Destructive tool                         | Not offered to the assistant at all                                     |
| Writing tool with no rule                | Runs                                                                    |
| Call a rule sets to **Ask** or **Block** | Refused. The assistant tells the person to run it from the Web App chat |
| Reading tool or built-in tool            | Runs                                                                    |

To keep a writing tool off these channels, limit where it runs instead: see [Choose where a tool runs](/en/tools-mcp#choose-where-a-tool-runs).

## Scheduled tasks [#scheduled-tasks]

A scheduled task runs with nobody watching, so it does not stop for approval:

* Calls that would ask first in chat are saved for later and the run continues without them. The task shows **Needs you**, and the calls wait for you in the task's conversation, where you approve or deny each one.
* In a task, the built-in web tool also waits for approval before it opens a URL the assistant picked.
* Your saved rules and the owner's rules apply as in chat, so a call you allowed runs without waiting.
* A held call expires after 24 hours, or when the task runs again or you send a new message in its conversation.

## Troubleshooting [#troubleshooting]

<Accordions>
  <Accordion title="A tool asks every time even though I ticked Don't ask again">
    The tool is destructive, or the command line contains several commands, a redirection or a command that runs other commands. Check the line on the card. The owner may also have set **Ask** for it.
  </Accordion>

  <Accordion title="The assistant says a call is blocked">
    The owner set **Block** for it in **Approvals**. Ask the owner if you need it.
  </Accordion>

  <Accordion title="The widget or a messaging app says to use the web chat">
    A rule sets that call to **Ask**, and nobody can approve there. Run it from the Web App chat, or ask the owner to change the rule.
  </Accordion>

  <Accordion title="A tool I expected doesn't appear in the Tool list of Add rule">
    MCP tools appear only after you approve them with **Refresh tools**. Built-in tools are not listed because they always run.
  </Accordion>
</Accordions>

<Cards>
  <Card title="MCP Endpoint" description="Connect tools on your own machine, including shell tools." href="/en/tools-mcp/mcp-endpoint" />

  <Card title="Custom API tools" description="How the HTTP method sets whether a tool asks first." href="/en/tools-mcp/custom-api-tools" />
</Cards>
