# Custom tools (/agents/custom-tools)





A custom tool combines a parameter schema with a JavaScript function body. Save the definition in your workspace, then give it to an **Agent** block as an action the model can call.

Use custom tools for calculations, transformations, or API requests that several agents share. Use a [Function block](/workflows/blocks/function) for a fixed code step on a workflow path.

## Create a custom tool [#create-a-custom-tool]

You need **Write** or **Admin** access to the workspace.

1. Open **Settings → Custom tools** and select **Add tool**.
2. Enter the function-calling definition in **Schema**.
3. Write the JavaScript function body in **Code**.
4. Select **Save**.

Schema and Code are sections on the same page. Each has a generation control that can draft content from a description; review the generated schema and code before saving.

### Define the schema [#define-the-schema]

The schema tells the model what the tool does and which inputs it accepts. Use the function-calling format below, with `function.parameters.type` set to `object`:

```json
{
  "type": "function",
  "function": {
    "name": "get_weather",
    "description": "Get the current weather for a city",
    "parameters": {
      "type": "object",
      "properties": {
        "city": {
          "type": "string",
          "description": "The city name, optionally including a country code"
        },
        "units": {
          "type": "string",
          "enum": ["celsius", "fahrenheit"],
          "description": "Temperature units; defaults to celsius when omitted"
        }
      },
      "required": ["city"]
    }
  }
}
```

Function names must contain 1–64 letters, digits, underscores, or hyphens. Describe when to call the tool and mark required inputs in the schema.

### Write the code [#write-the-code]

The code runs as an async function body. Supplied parameters with valid JavaScript names are available by name, such as `city`. All inputs are also available through `params`. Read optional inputs through `params`, because an omitted parameter may have no named variable.

This example requires an OpenWeather API key saved as `OPENWEATHER_API_KEY` under **Settings → Secrets**. It handles the optional units input and returns the weather fields the agent needs:

```javascript
const apiKey = {{OPENWEATHER_API_KEY}};
const requestedUnits = params.units ?? 'celsius';
const apiUnits = requestedUnits === 'celsius' ? 'metric' : 'imperial';
const response = await fetch(
  `https://api.openweathermap.org/data/2.5/weather?q=${encodeURIComponent(city)}&units=${apiUnits}&appid=${apiKey}`
);

if (!response.ok) {
  throw new Error(`Weather request failed: ${response.status}`);
}

const data = await response.json();
return {
  temperature: data.main.temp,
  units: requestedUnits,
  description: data.weather[0].description,
  humidity: data.main.humidity
};
```

The return value becomes the tool result available to the agent. The [OpenWeather API reference](https://openweathermap.org/api/current) describes its inputs and responses.

## Attach the tool to an Agent [#attach-the-tool-to-an-agent]

1. Open an **Agent** block with a model that supports tools.
2. In **Tools**, select &#x2A;*Add tool...**.
3. Find the saved definition under **Custom Tools** and select it.
4. Run a task that needs the tool and inspect the Agent's tool calls.

The model chooses whether to call it based on its schema and the task, subject to the tool's **Permission Mode**. See [Agent tools](/workflows/blocks/agent) for Auto, Force, and None.

## JavaScript runtime [#javascript-runtime]

Custom tools run in an isolated JavaScript VM, including when a workflow has a remote sandbox configured.

| Capability | Behavior |
| - | - |
| Async code | Use `await` directly and `return` the result. |
| Inputs | Read supplied inputs by valid JavaScript name or through `params`; use `params` for optional or non-identifier keys. |
| HTTP requests | `fetch()` returns status, headers, and `.json()` or `.text()`. Requests must satisfy the deployment's network policy. |
| Secrets | Use `{{KEY}}` placeholders to bind saved secrets at execution time. |
| File content | Pass content as an input or use supported scoped `sim.files` helpers to read an authorized file. See the [Function file reference](/workflows/blocks/function#files). |

Node module loading, external packages, and a sandbox filesystem are unavailable. Do not use `require`, `process`, `Buffer`, Node crypto, or package imports such as axios or lodash. The custom-tool fetch response does not support `.blob()` or `.arrayBuffer()`.

The separate **Function** tool supports additional runtimes and configured file inputs/outputs. Its controls differ from a saved custom tool and from the standalone Function block; see [Function](/workflows/blocks/function).

## Use secrets [#use-secrets]

For a secret used as a complete JavaScript expression, use an unquoted placeholder:

```javascript
const apiKey = {{MY_API_KEY}};
```

Quoted and embedded forms are also supported, including `"Bearer {{KEY}}"`, template literals, and JavaScript regex literals. Sim binds the value separately from the source, preserving its string contents.

<Callout type="warn">
  Exact recognized secret values are masked in the trace copy and replaced before a tool result reaches the Agent model, unless the secret's visibility setting exempts it. Encoded or transformed values can escape that protection. Runtime operations still receive the real secret. Do not return or print secrets; see [Execution log protection](/platform/credentials#execution-log-protection) for the full scope and limits.
</Callout>

## Manage tools and access [#manage-tools-and-access]

Under **Settings → Custom tools**, search by tool name, function name, or description. Open a definition to edit its schema or code.

<Callout type="warn">
  Deleting a saved tool removes its definition and can break Agents that reference it. Review dependent workflows and remove or replace their bindings before deleting the tool.
</Callout>

| Action | Required workspace role |
| - | - |
| View tools | Read, Write, or Admin |
| Create, edit, or delete tools | Write or Admin |

Organization permission groups can restrict custom-tool use. See [Permission groups](/platform/enterprise/access-control) for how restrictions apply.

## Related docs [#related-docs]

* [Choosing what to use](/agents/choosing)
* [Agent block reference](/workflows/blocks/agent)
* [Function](/workflows/blocks/function)
* [Secrets](/platform/credentials)
