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

# Tool execution and reliability

> The reliability you can count on for every tool call — what runs before a tool fires, protection against duplicate actions, time limits, retries, and the approval gates in front of destructive actions.

Tools are where your agent touches the world — sending an email, writing to a
connected system, running code. This page describes the reliability you get for
those calls: what runs before a tool fires, the protection against duplicate
actions, how failures are handled, and the approval gates in front of
destructive actions.

## What runs before a tool fires

Every tool — built-in, custom code, MCP, Composio, OpenAPI, GraphQL, and skills
— goes through the same checks, in the same order:

1. **Your hooks.** `pre_tool_call` [hooks](/sidebar-menu/hooks) run first and
   can block the call, rewrite its arguments, or supply the result directly.
2. **Parameter guards.** Your [tool parameter guards](/reference/tool_guards)
   validate and adjust the arguments. A rejected call comes back as a
   plain-English error the model can fix in the same turn, and values you've
   pinned can't be overridden by the model or a subscriber. See the
   [Tools page](/sidebar-menu/tools).
3. **Duplicate protection.** Actions that change something outside the platform
   are checked so a retry doesn't repeat them (below).
4. **Execution**, within a time limit.
5. **Your hooks again.** `post_tool_call` hooks run on success and failure and
   can adjust the result.

Every step is recorded, so a blocked, guarded, or timed-out call is visible in
[Monitoring](/runtime/observability) with its reason.

## Approved actions aren't repeated

An agent can legitimately re-run a turn — for example when quality
[regeneration](/runtime/evaluation) tries again, or when a client re-sends
after a network hiccup. Your agent won't repeat an action that already
happened: a send or an external write that already went through returns its
recorded result instead of firing again.

| Situation                        | What happens                                           |
| -------------------------------- | ------------------------------------------------------ |
| A new action                     | Runs normally                                          |
| An action that already completed | The earlier result is returned — it doesn't fire again |
| An action still in progress      | It isn't started a second time                         |
| An action that failed            | A retry runs it again                                  |

This protection covers external actions (MCP, Composio, OpenAPI, GraphQL) and
the built-in send, delegation, and schedule tools. Read-only tools are never
affected.

<Note>
  An agent that appears to "refuse" to send the exact same message twice in quick
  succession is this protection doing its job — change the content or wait a
  moment.
</Note>

## Time limits and failures

Every tool call is time-bounded, so no single hung call can hold up a reply.

* **A tool that fails** returns its error to the model, which can correct
  itself within the same turn.
* **A tool that times out** is reported to the model as an **unknown outcome** —
  the action may still have completed — so the agent verifies or tells the user
  rather than blindly retrying an action that might have side effects.
* **The agent doesn't blindly re-run actions.** The one retry the platform
  never makes on its own is re-firing an action that changes the world.

Where retries *are* safe, they happen automatically: connecting to a tool
server, and switching to a backup model when the primary can't be reached. A
model your plan doesn't allow is swapped for the closest one it does, so a
misconfigured model never fails a turn. See
[How a turn executes](/runtime/turn-execution) for model fallback, and
[Evaluation and quality](/runtime/evaluation) for judge-driven regeneration.

## No undo on completed actions

Once an external action completes — an email delivered, a connector write
committed — there's no automatic undo. The platform's effort goes into
preventing bad or duplicate actions *before* they happen: consent gates,
duplicate protection, and your hooks and guards. Design flows so irreversible
actions happen as late in a turn as possible.

## Approval gates and caps

### Consent for destructive actions

When your agent uses `confirm_action`, the user sees a confirmation card and
their Yes/No is recorded. The follow-up `commit_action` only succeeds if the
user actually confirmed — the model can't proceed by claiming the user said
yes.

### Prefilled parameter forms

Eligible tools can show the user a **prefilled form** to review and complete
before the tool runs. On web and widget the user fills in a form; on IM the
same flow runs as a short question-and-answer; on API, A2A, and email it's
skipped. The tool runs only after the user submits.

### Outbound send caps

Your agent has a shared daily limit across `email_send` and `im_send`. Set
**Max outbound sends per day** on the [Tools page](/sidebar-menu/tools) (`0` =
unlimited); until you set it, a default of 100/day applies, so a new agent
starts capped. The count resets daily. Connected-mailbox tools (`gmail_send` /
`outlook_send`) aren't counted — they send from the user's own mailbox.

### Sandboxed code limits

The built-in `execute_code` tool and your custom code tools run in an isolated
sandbox with these limits:

* **30-second** wall-clock timeout per execution
* **\~512 MB** memory
* Up to **50** built-in-tool calls back through the [`ctx` bridge](/custom-tools-ctx)
  per execution

Each execution is billed individually.
