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

# Tools

> Configure built-in, MCP, and custom tools on agent versions.

Tools are configured through the versioned `tools` field on
[`POST /v1/agents`](/api-reference/agents#create-an-agent) and
[`POST /v1/agents/{agentId}`](/api-reference/agents#update-an-agent).

## Tool config types

The `tools` array accepts three config types:

| Type            | Executes in               | Purpose                                                               |
| --------------- | ------------------------- | --------------------------------------------------------------------- |
| `agent_toolset` | Managed agent environment | Enable and permission built-in toolsets.                              |
| `mcp_toolset`   | Configured MCP server     | Enable and permission tools from an MCP server.                       |
| `custom_tool`   | Your application          | Expose application-owned actions to the model through session events. |

## Built-in agent toolsets

Managed agents expose these built-in toolsets. Configure them by toolset
name in `configs`; a toolset with `enabled: false` is invisible to the model.

| Toolset          | Tools                                              | Description                                                                     |
| ---------------- | -------------------------------------------------- | ------------------------------------------------------------------------------- |
| `clarify`        | `clarify`                                          | Ask the user a question when the agent needs clarification or approval context. |
| `vision`         | `vision_analyze`                                   | Analyze an image from a URL, local path, or data URL.                           |
| `skills`         | `skills_list`, `skill_view`, `skill_manage`        | List, inspect, create, update, or delete agent skills.                          |
| `todo`           | `todo`                                             | Read or update the session task list.                                           |
| `memory`         | `memory`                                           | Save, replace, or remove persistent memory and user-profile facts.              |
| `session_search` | `session_search`                                   | Search previous conversations for relevant context.                             |
| `code_execution` | `execute_code`                                     | Run Python code that can call agent tools programmatically.                     |
| `web`            | `web_search`, `web_extract`                        | Search the web and extract page contents.                                       |
| `terminal`       | `terminal`, `process`                              | Run shell commands and manage background processes in an isolated environment.  |
| `file`           | `read_file`, `write_file`, `patch`, `search_files` | Read, write, patch, and search files in the agent workspace.                    |

## Built-in toolset config

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "type": "agent_toolset",
  "defaultConfig": {
    "enabled": true,
    "permissionPolicy": { "type": "always_allow" }
  },
  "configs": [
    {
      "name": "terminal",
      "enabled": true,
      "permissionPolicy": { "type": "always_ask" }
    }
  ]
}
```

| Field           | Type      | Required | Description                                     |
| --------------- | --------- | -------- | ----------------------------------------------- |
| `type`          | string    | Yes      | Must be `agent_toolset`.                        |
| `defaultConfig` | object    | No       | Default enablement and permission policy.       |
| `configs`       | object\[] | No       | Per-toolset overrides by built-in toolset name. |

## MCP toolset config

MCP tools are attached by pairing an `mcpServers` entry with an `mcp_toolset`
entry in `tools`.

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "mcpServers": [
    {
      "type": "url",
      "name": "github",
      "url": "https://mcp.example.com/github"
    }
  ],
  "tools": [
    {
      "type": "mcp_toolset",
      "mcpServerName": "github",
      "defaultConfig": {
        "permissionPolicy": { "type": "always_ask" }
      },
      "configs": [
        {
          "name": "create_issue",
          "permissionPolicy": { "type": "always_allow" }
        }
      ],
      "resources": false,
      "prompts": false
    }
  ]
}
```

| Field           | Type      | Required | Description                                                          |
| --------------- | --------- | -------- | -------------------------------------------------------------------- |
| `type`          | string    | Yes      | Must be `mcp_toolset`.                                               |
| `mcpServerName` | string    | Yes      | Name of an entry in `mcpServers`.                                    |
| `defaultConfig` | object    | No       | Default enablement and permission policy for tools from this server. |
| `configs`       | object\[] | No       | Per-tool overrides by MCP tool name.                                 |
| `resources`     | boolean   | No       | Whether MCP resources are enabled.                                   |
| `prompts`       | boolean   | No       | Whether MCP prompts are enabled.                                     |

## Custom tool config

Custom tools are functions your application executes outside the managed agent
environment.
Declare them with `type: "custom_tool"`, a model-facing `name`, a clear
`description`, and an `input_schema`.

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "type": "custom_tool",
  "name": "check_order_status",
  "description": "Look up an order by ID.",
  "input_schema": {
    "type": "object",
    "properties": {
      "order_id": {
        "type": "string",
        "description": "Customer order ID"
      }
    },
    "required": ["order_id"],
    "additionalProperties": false
  },
  "enabled": true,
  "permissionPolicy": { "type": "always_ask" }
}
```

| Field              | Type    | Required | Description                                                                  |
| ------------------ | ------- | -------- | ---------------------------------------------------------------------------- |
| `type`             | string  | Yes      | Must be `custom_tool`.                                                       |
| `name`             | string  | Yes      | Tool name exposed to the model.                                              |
| `description`      | string  | Yes      | Tool description exposed to the model.                                       |
| `input_schema`     | object  | Yes      | Object-shaped input schema.                                                  |
| `enabled`          | boolean | No       | Defaults to `true`.                                                          |
| `permissionPolicy` | object  | No       | Approval policy for this custom tool. Defaults to `always_ask` when omitted. |

Custom tools use the permission policy above. With the default `always_ask`, the
stream emits an approval request first. After approval, the stream emits
`agent.custom_tool_use` and then `session.status_idle` with
`stop_reason.type: "requires_action"`. Execute the tool in your application and
return `user.custom_tool_result` to
[`POST /v1/sessions/{sessionId}/events`](/api-reference/send-message#return-a-custom-tool-result).

See the [Events Reference](/api-reference/events-reference#custom-tool-handling)
for the full request/response flow.

If the application-owned work cannot finish promptly, use the dedicated
[long-running custom tools](/api-reference/long-running-tools) flow. The initial
response must reach the pending tool call within approximately five minutes.

## Permission policies

Permission policies control whether built-in, MCP, and custom tools run
automatically or wait for approval.

| Policy         | Behavior                                                     |
| -------------- | ------------------------------------------------------------ |
| `always_allow` | The tool executes automatically.                             |
| `always_ask`   | The session pauses and waits for an approval response event. |
| `always_deny`  | Herm denies the tool automatically before it executes.       |

When a tool with `always_ask` is invoked, the session emits
`agent.approval_request`, then pauses with `session.status_idle` and
`stop_reason.type: "requires_action"`. Continue by sending
`user.approval_response` to [`POST /v1/sessions/{sessionId}/events`](/api-reference/send-message#confirm-a-tool-request).

For trusted autonomous sessions, set [`yoloMode: true`](/api-reference/sessions#yolo-mode) on the session to automatically accept `always_ask` approval prompts. YOLO mode does not bypass `always_deny` or disabled tools.

When a tool is disabled with `enabled: false`, Herm treats it as
`always_deny`: the request is denied before execution and no approval request is
emitted.

## Role-specific tool policies

Agent versions can also define named roles. A role contains its own `tools`
array using the same config shapes shown above. When a session is created with a
`role`, that role's tool policy is used for approval decisions instead of the
agent version's top-level `tools`.

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "name": "readonly",
  "tools": [
    {
      "type": "agent_toolset",
      "defaultConfig": { "enabled": false },
      "configs": [
        { "name": "terminal", "enabled": false },
        { "name": "file", "enabled": false },
        { "name": "clarify", "enabled": true }
      ]
    }
  ]
}
```

Create a session with that boundary by passing `role` to
[`POST /v1/sessions`](/api-reference/sessions#create-a-session).

## Update semantics

Agent updates create a new immutable version. With
`PATCH /v1/agents/{agentId}`, supplied tools are upserted by their stable key and
omitted tools are preserved; an empty array removes nothing. Use the
full-replacement `POST /v1/agents/{agentId}` to replace the complete `tools`
array or clear it with `tools: []`.
