> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.runtype.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.runtype.com/_mcp/server.

# Using tool-call steps

Use a `tool-call` step to run one tool at a fixed point in a Flow, with parameters that you set. No model chooses the tool or writes its arguments. The Flow editor labels this step **Tool Call**.

Use a tool-call step when the Flow always needs the same tool with predictable input, such as storing a file, looking up an order, or posting a message. When a model decides whether and how to call a tool, add the tool to a prompt step or an Agent instead. For more information, see [Using prompt steps](/user-guide/flows/using-prompt-steps).

> **Warning**
>
> A tool-call step has no approval gate. It runs every time the Flow reaches it, with the
> parameters that you wrote. A step that calls `builtin:send_email` sends the email unattended.
> Approval applies only to tool calls that a model chooses in an Agent or a prompt step.

## Before you begin

The step picker in the Flow editor doesn't list **Tool Call**. Add the step through the API, the Runtype MCP server, or the TypeScript SDK. After you save the Flow, you can edit the step's settings in the Flow editor.

To call a saved tool, create it first. For more information, see [Creating custom tools](/user-guide/tools/creating-custom-tools).

## Add a tool-call step

The following step stores a file from a URL that an earlier step wrote to the `report_url` variable:

```json
{
  "type": "tool-call",
  "name": "Store report",
  "config": {
    "toolId": "builtin:store_asset",
    "parameters": {
      "url": "{{report_url}}",
      "filename": "weekly-report.pdf",
      "visibility": "private"
    },
    "outputVariable": "stored_report"
  }
}
```

MCP flow tools and the Flows API accept the same step object in a Flow's steps.

To build the same step with the TypeScript SDK, call the `toolCall` method on `FlowBuilder`:

**`TypeScript SDK`**

```typescript title="TypeScript SDK"
import { FlowBuilder } from '@runtypelabs/sdk'

const flow = new FlowBuilder()
  .createFlow({ name: 'Archive weekly report' })
  .toolCall({
    name: 'Store report',
    toolId: 'builtin:store_asset',
    parameters: {
      url: '{{report_url}}',
      filename: 'weekly-report.pdf',
      visibility: 'private',
    },
    outputVariable: 'stored_report',
  })
  .build()
```

After the step runs, `stored_report` holds the tool's result. Later steps read it with `{{stored_report}}`, or read a field with a path such as `{{stored_report.url}}`.

## Configure the step

A tool-call step takes these fields in its `config`:

* `toolId` (required): the tool to call. For the accepted forms, see [Choose the tool](#choose-the-tool).
* `parameters` (required): a JSON object of arguments for the tool. Use `{}` for a tool that takes no arguments.
* `outputVariable` (required): the variable that receives the tool's result.
* `toolConfig` (optional): settings for a built-in or platform tool that aren't call arguments, such as a Slack `integrationId`.
* `onError` (optional): `fail`, `continue`, or `retry`. The default is `fail`. For more information, see [Handle failures](#handle-failures).
* `maxRetries` (optional): the total number of attempts, including the first call. The default is 3.
* `timeout` (optional): the time limit for each attempt, in milliseconds. When you don't set it, the call has no time limit.

In the Flow editor, the step card shows **Tool ID**, **Parameters**, and **Output variable**. The other fields are under **Execution settings** as **On error**, **Maximum attempts**, **Timeout (ms)**, and **Tool settings**. The **Parameters** and **Tool settings** fields accept only a valid JSON object. The editor doesn't save a change to either field until the JSON is valid.

### Choose the tool

The `toolId` field accepts three forms:

* A built-in or platform tool ID, such as `builtin:store_asset` or `builtin:slack:send_message`. For the available IDs, see [Built-in tools](/user-guide/tools/built-in-tools).
* A saved tool's ID, which starts with `tool_`.
* A saved tool's name in the form `tool:TOOL_NAME`, such as `tool:lookup_order`. Replace `TOOL_NAME` with the exact name of the saved tool.

Use the `tool:TOOL_NAME` form in a Flow definition that you deploy to more than one environment, because each environment gives a saved tool a different ID. If several saved tools share the name, the step calls the oldest one. For more information, see [Manage flows as code](/user-guide/flows/manage-flows-as-code).

A tool-call step can't call a local tool, because a local tool runs in a connected client and a Flow step has no client. The step fails with an error that names the tool. Call a local tool from an Agent or a prompt step instead.

### Pass variables in parameters

A string value in `parameters` can contain Flow variables, such as `"{{customer.email}}"`. The step substitutes each variable before it calls the tool. The result is always a string, even when the variable holds a number or an object.

The step substitutes variables only in top-level string values. It passes numbers, booleans, arrays, and nested objects to the tool unchanged, so a `{{variable}}` inside a nested object reaches the tool as literal text. To pass a computed object, build it in a transform-data step and pass each top-level field as its own parameter. For more information, see [Using transform-data steps](/user-guide/flows/using-transform-data-steps).

For the variable syntax, see [Flow variables and templates](/user-guide/flows/flow-variables-and-templates).

## Handle failures

A tool-call step uses its own `onError` field. It ignores the `errorHandling` setting that other steps use, and validation warns when a tool-call step sets `errorHandling.onError`. For more information, see [Tool-call step ignores errorHandling](/user-guide/flows/flow-validation-warnings#tool-call-step-ignores-errorhandling).

The following table describes each `onError` value:

| Value      | Editor label                   | Behavior when the tool call fails                                                                       |
| ---------- | ------------------------------ | ------------------------------------------------------------------------------------------------------- |
| `fail`     | **Fail**                       | The step fails and the Flow run stops. This is the default.                                             |
| `continue` | **Continue with error output** | The Flow continues. The output variable holds `{ "error": "MESSAGE", "result": null }`.                 |
| `retry`    | **Retry, then fail**           | The step calls the tool again, up to `maxRetries` attempts. If every attempt fails, the Flow run stops. |

By default, the step doesn't call a failed tool again, because a second call repeats the tool's side effects. It retries only when you set `onError` to `retry` or set `maxRetries`. Between attempts, the step waits 1 second, then doubles the wait for each later attempt, up to 5 seconds.

Some failures are never retried:

* The call takes longer than `timeout`.
* No tool matches `toolId`, or the tool is inactive.
* The tool is a local tool.

With `onError` set to `continue`, add a conditional step after the tool-call step to route the failure case. For example, test `stored_report.error`. For more information, see [Using conditional steps](/user-guide/flows/using-conditional-steps).

## Check your step

Validate the Flow before you run it. Call the validate endpoint (`POST /v1/public/flows/validate`) or the `validate_flow` MCP tool. A `toolId` that starts with `builtin:` or `platform:` but matches no catalog tool blocks the save. For more information, see [Tool-call step points at an unknown catalog tool](/user-guide/flows/flow-validation-warnings#tool-call-step-points-at-an-unknown-catalog-tool).

After a run, open the step's result to see the tool's output and any error. For more information, see [Debugging flows](/user-guide/flows/debugging-flows).

## Next steps

* [Flow step types overview](/user-guide/flows/flow-step-types-overview): compare the tool-call step with other step types
* [Built-in tools](/user-guide/tools/built-in-tools): find catalog tool IDs and their parameters
* [What are Tools?](/user-guide/tools/what-are-tools): learn which kinds of tools you can save
* [Manage flows as code](/user-guide/flows/manage-flows-as-code): keep tool references portable across environments