# Tools

> Select Raw's built-in tools for an agent, control them with rules, fork a shipped tool, and write a local tool manifest.

A tool is an action the model can call, such as reading a file or running a shell command. Each agent selects its tools in `tools.use`, in the order you list them. Raw loads only the tools an agent selects, and the model sees only those tools.

## Built-in tools

Raw ships eleven tools. Select them with the `builtin/` prefix.

| Tool ID               | What it does                                                                                             | Selection     |
| --------------------- | -------------------------------------------------------------------------------------------------------- | ------------- |
| `builtin/read_file`   | Reads up to 16 UTF-8 files in one call, with an optional line range for each file.                       | Starter agent |
| `builtin/write_file`  | Applies ordered writes: `overwrite`, `append`, `replace_text`, `replace_lines`, or a multi-file `patch`. | Starter agent |
| `builtin/bash`        | Runs up to 16 Bash commands in order. A nonzero exit does not stop later commands.                       | Starter agent |
| `builtin/list_skills` | Lists the skills the agent selected, with their descriptions.                                            | Starter agent |
| `builtin/load_skill`  | Loads the Markdown body of one selected skill.                                                           | Starter agent |
| `builtin/view_image`  | Reads a local PNG or JPEG for the model. Requires `vision: true` on the model.                           | Explicit      |
| `builtin/list_vars`   | Lists the runtime variables the agent selected, without reading their values.                            | Starter agent |
| `builtin/read_var`    | Reads one selected runtime variable.                                                                     | Starter agent |
| `builtin/todo`        | Keeps a task list in a live side panel.                                                                  | Explicit      |
| `builtin/ask_user`    | Asks the user one to three structured questions.                                                         | Explicit      |
| `builtin/process`     | Starts and manages background processes across turns.                                                    | Explicit      |

The starter agent created by `raw config init` selects the seven tools marked “Starter agent”. Tools marked “Explicit” are off until an agent lists them.

## Select tools for an agent

`tools.use` is required in every agent. It accepts these ID forms:

| Prefix                       | Where Raw loads it from                                                                          |
| ---------------------------- | ------------------------------------------------------------------------------------------------ |
| `builtin/<name>`             | The installed Raw package.                                                                       |
| `local/<folder>`             | `$XDG_CONFIG_HOME/raw/tools/<folder>/`, or `~/.config/raw/tools/<folder>/`.                      |
| `agent/<folder>`             | `tools/<folder>/` beside the selected config file.                                               |
| `mcp/<server>/<tool>`        | A tool from a server in `mcp.servers`. See [MCP](https://raw.tlelabs.com/docs/extend/mcp/).      |
| `pkg/<alias>/tools/<export>` | A tool from an installed package. See [Packages](https://raw.tlelabs.com/docs/extend/packages/). |

An empty array gives the agent no tools.

```json
{
  "agents": {
    "coder": {
      "model": "local",
      "tools": {
        "use": [
          "builtin/read_file",
          "builtin/write_file",
          "builtin/bash",
          "local/my_bash"
        ]
      }
    }
  }
}
```

Model-visible tool names must be unique among the selected tools. Two tools cannot share a name, and the same folder cannot be selected twice.

## Control tools with rules

`tools.rules` sets a policy for tools in `tools.use`. Each rule has a `match` glob and an `effect`.

| Field    | Values                                                                                                                                         |
| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `match`  | A glob over the full tool identity, such as `builtin/bash` or `mcp/search/*`. `*` matches any run of characters and `?` matches one character. |
| `effect` | `allow`, `ask`, or `deny`.                                                                                                                     |
| `when`   | Optional. Only valid with `ask`. Inspects selected string arguments.                                                                           |

Rules apply in order, and the last matching rule wins. A call with no matching rule runs automatically.

- `allow` runs the call without a prompt.
- `ask` asks for permission each time the call is made.
- `deny` removes the tool’s schema from the model and rejects direct calls.

The following rule asks before any Bash command that runs `rm`. Other Bash calls run without a prompt.

```json
{
  "match": "builtin/bash",
  "effect": "ask",
  "when": {
    "source": "arguments",
    "any": "commands[*].command",
    "regex": "(^|[;&|()\\n])\\s*(sudo\\s+)?(/usr/bin/|/bin/)?rm(\\s|$)"
  }
}
```

> **Caution:**
>
> Tool rules filter tool names and argument text. They are not a sandbox. Allowing `builtin/bash` gives the agent your full shell permissions, even if `builtin/write_file` is denied. The `-y` flag never overrides an explicit `ask` rule.

## Fork a shipped tool

Every built-in tool has an editable copy in the package at `examples/tools/<name>/`. To change one, copy it into your config directory and select it as a `local/` tool.

1. Copy the folder to a new ID under your Raw config directory.

   ```sh
   mkdir -p ~/.config/raw/tools
   cp -R examples/tools/bash ~/.config/raw/tools/my_bash
   ```

2. Edit `tool.json` in the copy. Set `id` to match the folder name, `my_bash`. Change `name` if the model-facing name should differ.

3. Edit `index.mjs` as needed. The `.mjs` file runs directly, so you do not need to rebuild Raw.

4. Select the fork in the agent’s `tools.use` list.

   ```json
   "tools": { "use": ["builtin/read_file", "local/my_bash"] }
   ```

> **Caution:**
>
> A local tool runs with your full OS account permissions. Read the handler before you select a fork. When you change a batch tool, keep its `validateArgs` checks so invalid calls are rejected before any side effect.

## Write a local tool

A local tool is a folder with two files: `tool.json` and an entry module named by `entry`.

```text
~/.config/raw/tools/
  project_note/
    tool.json
    index.mjs
```

This manifest is from the [project helper example](https://github.com/lploc94/raw-cli/tree/main/examples/agents/project-helper/tools/project_note).

```json
{
  "api_version": 2,
  "id": "project_note",
  "version": "1.0.0",
  "name": "project_note",
  "description": "Return a short note about the current project directory.",
  "input_schema": {
    "type": "object",
    "properties": {},
    "required": [],
    "additionalProperties": false
  },
  "entry": "./index.mjs",
  "condition_sources": ["arguments"]
}
```

```js
export async function handler(_args, context) {
  return { content: [{ type: "text", text: `Project directory: ${context.cwd}` }] };
}
```

### Manifest fields

| Field               | Required | Rules                                                                                                                                    |
| ------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `api_version`       | Yes      | Must be `2`.                                                                                                                             |
| `id`                | Yes      | Folder name. Lowercase letters, digits, `_` and `-`, starting with a letter.                                                             |
| `version`           | Yes      | `major.minor.patch`.                                                                                                                     |
| `name`              | Yes      | Model-facing name. Starts with a letter or `_`, up to 64 letters, digits, `_` or `-`.                                                    |
| `description`       | Yes      | Tells the model what the tool does and what its result means.                                                                            |
| `input_schema`      | Yes      | A JSON Schema object (draft-07 or 2020-12). Local `$ref` only.                                                                           |
| `entry`             | Yes      | Path to the module, such as `./index.mjs`.                                                                                               |
| `condition_sources` | No       | Argument sources that rules may inspect. Use `["arguments"]` for argument-based rules.                                                   |
| `effects_schema`    | No       | Schema for effects a tool declares before it runs. Advanced; see [Tool contract](https://raw.tlelabs.com/docs/reference/tool-contract/). |
| `panels`            | No       | Up to four live side panels the tool owns. See [Tool contract](https://raw.tlelabs.com/docs/reference/tool-contract/).                   |

Manifests reject unknown fields. Symlinked folders, manifests, or entries that point outside the tool’s root fail before any code is imported.

### Entry module

The entry module exports:

- `handler(args, context)`, an async function that returns the result. Results are text, JSON, or image blocks.
- `validateArgs(args)`, optional. Returns an error string for invalid arguments, or `undefined`.

Raw checks the JSON Schema and `validateArgs` before it asks for permission or runs anything. The `context` object provides:

- `cwd`, the session’s working directory.
- `signal`, an abort signal that fires on cancellation.
- The result size cap and the tool-call ID.
- `vars`, the variable service. See [Variables](https://raw.tlelabs.com/docs/extend/variables/).

## Batch-capable tools

The three core tools take an ordered batch. Each call contains an array, and the array may hold up to 16 entries.

```json
{
  "files": [
    { "path": "package.json" },
    { "path": "src/agent.ts", "start_line": 40, "max_lines": 20 }
  ]
}
```

Batch rules:

- A batch is validated as a whole. An invalid entry rejects the entire call before anything runs.
- Results are indexed. Each entry reports its own status, so one failure does not hide the others.
- `bash` runs commands one at a time. A nonzero exit is an ordinary result, and later commands still run. A timeout or abort stops the running command and skips the rest.
- All rows in one call share one result size cap. The cap is set by `--max-output-bytes` or `max_output_bytes` and defaults to 8192 bytes. The cap limits what the model receives, not what the terminal shows.
- The old single-object shapes, such as `{ "path": ... }` for `read_file` or `{ "command": ... }` for `bash`, are not supported.

See the [CLI reference](https://raw.tlelabs.com/docs/reference/cli/) for the flags, and the [Configuration reference](https://raw.tlelabs.com/docs/reference/configuration/) for the agent fields.

## Next steps

- Use [Skills](https://raw.tlelabs.com/docs/extend/skills/) to give an agent reusable instructions.
- Use [Hooks](https://raw.tlelabs.com/docs/extend/hooks/) to run a command before or after a tool call.
- Use [MCP](https://raw.tlelabs.com/docs/extend/mcp/) to add tools from an external server.
