# Adding Tools

> Tools extend what your agent can do. There are seven types of tools.

**URL:** https://inference.sh/docs/agents/adding-tools
**Last updated:** 2026-10-15

---

Tools extend what your agent can do. There are seven types of tools.

---

## Tool Types

| Type | What it is | Use case |
|------|------------|----------|
| **App** | Any app from the grid | Image generation, search, transcription |
| **Agent** | Another agent | Delegate specialized tasks |
| **Connector** | MCP server tool | Linear, Slack, GitHub, Google |
| **Call** | HTTP API call | REST APIs, external services |
| **Hook** | External webhook | Connect to your own services |
| **Client** | Code-executed tools | Browser automation, custom logic |
| **Internal** | Built-in agent capabilities | Memory, planning, widgets |

All tools are managed in one place: the **Tools** tab.

---

## Adding an App Tool

1. Open your agent's settings
2. Go to the **Tools** tab
3. Click **Add Tool** → **App Tool**
4. Search and select an app

The agent can now call this app.

**What happens automatically:**
- Name is extracted from the app
- Input schema becomes tool parameters
- You can customize the description shown to the agent

### Configuring Setup & Default Inputs

App tools support two types of pre-configuration:

| Setting | Purpose | When it's used |
|---------|---------|----------------|
| **Setup** | One-time configuration values | Passed to the app on every call (e.g., API keys, model selection) |
| **Default Inputs** | Default parameter values | Merged with agent's call — agent can override these |

**To configure:**

1. After adding an app tool, click **Configure Setup** or **Configure Default Inputs**
2. Fill in the form fields
3. Save the agent

**Example:** An image generation tool might have:
- **Setup:** API key, default model, safety settings
- **Default Inputs:** Default resolution, style preset

The agent only sees input parameters — setup values are hidden from the LLM.

---

## Adding an Agent Tool

Agents can delegate to other agents:

1. Go to **Tools** tab
2. Click **Add Tool** → **Agent Tool**
3. Select another agent

The main agent can now delegate tasks to it.

```
Main Agent
├── Research Agent (gathers information)
├── Writing Agent (creates content)
└── Editor Agent (reviews and polishes)
```

See [Sub-Agents](/docs/agents/sub-agents) for more details.

---

## Adding a Webhook Tool

Connect your agent to external services:

1. Go to **Tools** tab
2. Click **Add Tool** → **Webhook Tool**
3. Enter a name and webhook URL
4. Optionally add a secret and input schema

When called, the hook receives:
- Tool arguments
- A callback URL to return results

See [Webhooks](/docs/agents/webhooks) for implementation details.

---

## Adding a Connector Tool

Connector tools call tools on MCP servers you've connected to — Linear, Slack, GitHub, and more.

1. Go to **Tools** tab
2. Click **Add Tool** → **Connector Tool**
3. Select a connected MCP server
4. Choose which tools to expose

The agent sees each tool with its name and description. Authentication is handled automatically at runtime.

```yaml
tools:
  - name: list_issues
    type: mcp
    description: List Linear issues
    mcp:
      server: "linear"
      tool_name: "list_issues"
```

See [Connectors](/docs/connectors/agent-tools) for full documentation.

---

## Adding a Call Tool

Call tools make HTTP requests to external APIs. Unlike webhooks, call tools execute directly — the agent sends a request and gets the response back immediately.

1. Go to **Tools** tab
2. Click **Add Tool** → **Call Tool**
3. Configure the tool:

| Field | Description |
|-------|-------------|
| **Name** | Tool name the agent sees (e.g. `get_weather`) |
| **Description** | What the tool does — helps the agent decide when to use it |
| **URL** | The endpoint to call (supports `{{context.X}}` templates) |
| **Method** | HTTP method (`GET`, `POST`, `PUT`, `DELETE`) |
| **Input Schema** | JSON Schema for the tool's parameters — becomes the request body |

### Authentication

Call tools support multiple auth methods. Credentials are injected at runtime — never exposed to the agent.

| Auth Type | How it works |
|-----------|-------------|
| **Bearer** | Sends `Authorization: Bearer <value>` using a workspace secret |
| **API Key** | Sends a header with a workspace secret value |
| **Credential** | Uses a connected OAuth credential |
| **None** | No authentication |

**Bearer auth** is the most common. Set it up:

1. Store your API key as a workspace secret: `belt secrets set my_api_key` (prompts for the value; or pipe it on stdin)
2. In the tool config, set auth type to **Bearer** and reference the secret name

```yaml
auth:
  type: bearer
  secret: my_api_key
```

### Context Templates

URLs can include `{{context.X}}` placeholders that resolve from per-chat context values. This lets one agent definition work across different resources.

```
https://api.example.com/projects/{{context.project_id}}/tasks
```

When starting a chat, pass context values:

```json
{
  "agent_id": "agent_abc123",
  "context": {
    "project_id": "proj_456"
  }
}
```

Context is set once per chat and cannot change. See [Context](#context) below.

### Require Approval

For destructive or expensive operations, enable **Require Approval**. The agent pauses and waits for user confirmation before calling the tool.

---

## Context

Context provides per-chat variables for the agent's tools. Declare the fields your agent expects, then pass values when creating a chat. The server puts the values into tool calls, call tool URLs and headers.

### Declaring Context Fields

In the agent config, declare what context the agent needs:

```yaml
context:
  - name: project_id
    description: The project to operate on
    required: true
  - name: environment
    description: Target environment (staging or production)
    default: staging
    in_prompt: true
```

| Field | Description |
|-------|-------------|
| `name` | Variable name, used as `{{context.NAME}}` |
| `description` | Shown to the model next to the name |
| `required` | Marks the field as expected. The server does not enforce it: a chat without the value still runs |
| `default` | Value used when the caller does not send this key |
| `in_prompt` | When `true`, the value is shown to the model too, labeled as data from the caller |

### Passing Context

Context values are passed when creating a chat or running an agent:

**REST API:**
```json
{
  "agent_id": "agent_abc123",
  "context": {
    "project_id": "proj_456",
    "environment": "staging"
  }
}
```

**Belt CLI:**
```bash
belt agent run myteam/my-agent "do the thing" \
  --context project_id=proj_456 \
  --context environment=staging
```

Context is **immutable** — once set on a chat, it cannot change. This ensures all tool calls within a conversation operate on the same resource.

### How the agent uses context

Context values are not written into the system prompt. The prompt lists the variables the chat has (names and declared descriptions) and tells the agent to write `{{context.NAME}}` in a tool call's arguments. The server substitutes the value when the tool runs:

```json
{ "project": "{{context.project_id}}", "status": "open" }
```

- Substitution applies to app, http, call, MCP, hook and client tools.
- Sub-agents, `spawn`, internal tools and `remote_exec` get the placeholder as written.
- A sub-agent starts with no context variables. The delegating agent passes the ones it chooses in the call's `variables` argument, for example `{"customer_id": "{{context.customer_id}}"}`. The server fills the value in from the parent chat and stores it as the sub-chat's context, so neither model sees it. A placeholder the parent can't fill is dropped.
- The model's own history keeps the placeholder, so the value does not reach the model through its tool calls.
- A placeholder that names no variable is left as written.
- Keys the caller sends that the agent does not declare are variables too, listed by name.
- `{{context.X}}` in http and call tool URL and header templates is resolved too.

Fields with `in_prompt: true` are the exception: their values appear in the system prompt under a section that labels them as the caller's data and tells the model not to follow them. Use it only for values the model needs to read, such as a customer's display name.

---

## Client Tools

Client tools execute in your application code. They're defined with a handler function that runs when the agent calls the tool.

```typescript
import { tool, string } from '@inferencesh/sdk'

const myTool = tool('search_ui')
  .describe('Scans the UI for interactive elements')
  .param('query', string('Search query'))
  .handler(async (args) => {
    // Your code runs here
    return JSON.stringify({ results: [...] })
  })
```

A client tool's result can also carry files, such as a screenshot: upload them first and return them as attachments. Images reach models that accept images. See [Returning files](/docs/api/agent/client-tools#returning-files).

Client tools are useful for:
- Browser automation (DOM interaction)
- Accessing local resources
- Custom business logic
- Integrating with frontend frameworks

The inference.sh browser extension follows this pattern. Its agent, `infsh/browser-agent`, declares client tools (`read_page`, `get_source`, `fill`, `click`, `press_key`, `scroll`, `edit_dom`, `navigate`, `screenshot`, `list_tabs`, `switch_tab`) that run in the extension against the user's active tab. `screenshot` uploads the visible tab and returns it as a tool-result attachment.

---

## Internal Tools

Internal tools are built-in capabilities provided by the runtime. They're automatically available based on agent configuration.

### Plan Tools

Task planning for complex multi-step operations:

| Tool | Description |
|------|-------------|
| `plan_create` | Create a plan with steps |
| `plan_update` | Update step status |
| `plan_load` | View current plan |

### Memory Tools

Per-chat scratch key-value notes: only this chat sees them. Use [knowledge tools](/docs/api/agent/internal-tools#knowledge-tools) for facts that should reach later chats.

| Tool | Description |
|------|-------------|
| `memory_set` | Save a scratch note under a key |
| `memory_get` | Read a scratch note by key |
| `memory_getall` | List all scratch notes in this chat |

### Widget Tool

UI rendering for interactive forms (top-level agents only):

| Tool | Description |
|------|-------------|
| `widget` | Create forms, buttons, cards |

### Finish Tool

For agents to report structured output:

| Tool | Description |
|------|-------------|
| `finish` | Report status and results |

When `output_schema` is set on the agent config, the finish tool validates results against the schema. See [Structured Output](/docs/api/agent/structured-output) for details.

### Skills Tool

Load skill content on-demand (when agent has skills defined):

| Tool | Description |
|------|-------------|
| `skill_get` | Retrieve a skill's full content |

See [Skills](/docs/agents/skills) for more details on defining and using skills.

---

## Example App Tools

| Tool | What it does |
|------|--------------|
| `stable-diffusion` | Generate images |
| `whisper` | Transcribe audio |
| `summarize` | Condense text |
| `web-search` | Search the internet |

---

## How Agents Use Tools

When you chat:

```
You: Generate a sunset image

Agent: I'll create that for you.
       [Calling stable-diffusion with prompt "sunset"]

       Here's your sunset image!
```

The agent decides when to use which tool based on your request.

---

## Tool Descriptions

Each tool has a description that tells the agent what it does. Good descriptions help the agent choose the right tool:

**Generic:**
```
Search the web
```

**Better:**
```
Search the web for current information. Use when you need up-to-date
facts, news, or information not in your training data.
```

---

## Next

→ [Sub-Agents](/docs/agents/sub-agents)
