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

# Pre-Tool Webhooks

> Dynamically configure tool behavior and inject real-time data before specific tools execute.

<Info>
  **Dynamic Tool Configuration**: Pre-tool webhooks allow you to fetch
  contextual data and customize tool parameters in real-time before specific
  tools are executed during calls.
</Info>

## Overview

<img src="https://mintcdn.com/openmic-ea75a20d/n3f_akOE86bDxuYq/images/pre-tool-webhook.png?fit=max&auto=format&n=n3f_akOE86bDxuYq&q=85&s=a69127b33270d510eeb334ce9f3b04e0" alt="Showing the configuration for pre-tool webhook" height="300" className="rounded-lg" data-path="images/pre-tool-webhook.png" />

Pre-tool webhooks enable targeted data injection for specific tools during active calls. When certain tools are about to execute, Openmic can optionally send tool details to your webhook endpoint, and your system responds with dynamic variables that customize the tool's behavior.

<CardGroup cols={2}>
  <Card title="Tool-Specific Data" icon="wrench" iconType="solid">
    Fetch relevant information and parameters specific to the tool being
    executed.
  </Card>

  <Card title="Runtime Customization" icon="gear" iconType="solid">
    Modify tool parameters dynamically based on call context and external
    data sources.
  </Card>
</CardGroup>

***

## Configuration Options

### Webhook URL Selection

Pre-tool webhooks support flexible URL configuration:

<CardGroup cols={2}>
  <Card title="Use Pre-Call URL" icon="link" iconType="solid">
    To reuse your existing pre-call webhook endpoint
  </Card>

  {" "}

  <Card title="Dedicated URL" icon="globe" iconType="solid">
    Specify a dedicated URL for a tool-specific webhook endpoint
  </Card>
</CardGroup>

<Note>
  Pre-tool webhooks are tool-specific and must be enabled individually for
  each tool through the configuration.
</Note>

***

## Request Specification

### HTTP Method and Timeout

Openmic sends a `POST` request to your configured webhook URL with:

* **Content-Type**: `application/json`
* **Timeout**: 3 seconds per attempt
* **User-Agent**: `Openmic-Webhook/1.0`

<Warning>
  Unlike pre-call webhooks, pre-tool webhook failures do not terminate the
  call. Tools will execute with original parameters if the webhook fails.
</Warning>

### Request Payload

```json theme={null}
{
	"event": "tool",
	"tool_name": "calendar_booking",
	"tool": {
		"direction": "inbound",
		"bot_id": "cmdx5w8oc0005q671s3cbg063",
		"from_number": "+16167948654",
		"to_number": "+916297653534",
	}
}
```

### Payload Fields

| Field              | Type   | Required | Description                                 |
| ------------------ | ------ | -------- | ------------------------------------------- |
| `event`            | string | Yes      | Always `"tool"` for pre-tool webhooks       |
| `tool_name`        | string | Yes      | Name of the tool being executed             |
| `tool.direction`   | string | Yes      | Call direction: `"inbound"` or `"outbound"` |
| `tool.bot_id`      | string | Yes      | Unique identifier for the bot/session       |
| `tool.from_number` | string | Yes      | Caller's phone number in E.164 format       |
| `tool.to_number`   | string | Yes      | Callee's phone number in E.164 format       |

### Tool Names

* `calendar_check`
* `calendar_booking`
* `transfer_call`

***

## Expected Response

### Success Response

Your webhook must return a `200` status code with a JSON response containing dynamic variables:

```json theme={null}
{
	"tool": {
		"dynamic_variables": {
			"transfer_number": "+15551234567",
			"booking_preference": "morning",
			"calendar_timezone": "America/New_York",
			"priority_level": "high"
		}
	}
}
```

### Response Structure

| Field                    | Type   | Required | Description                                          |
| ------------------------ | ------ | -------- | ---------------------------------------------------- |
| `tool`                   | object | Yes      | Container for tool-related data                      |
| `tool.dynamic_variables` | object | Yes      | Key-value pairs of variables to inject into the tool |

<Tip>
  **Variable Merging**: Pre-tool dynamic variables are merged with existing
  call variables, with pre-tool variables taking precedence for conflicts.
</Tip>

***

## Retry Logic and Error Handling

### Retry Configuration

<CardGroup cols={3}>
  <Card title="Max Attempts" icon="rotate-right" iconType="solid">
    **3 total attempts** 1 initial request + 2 retries
  </Card>

  <Card title="Timeout" icon="clock" iconType="solid">
    **3 seconds** Per individual request attempt
  </Card>

  <Card title="Backoff Strategy" icon="arrow-trend-up" iconType="solid">
    **Exponential delays** 1s, 2s, 3s between retries
  </Card>
</CardGroup>

### Retry Triggers

Openmic retries your webhook in these scenarios:

* **Timeout**: No response within 3 seconds
* **HTTP Errors**: 4xx or 5xx status codes
* **Network Errors**: Connection failures or DNS resolution issues
* **Invalid JSON**: Malformed response body

### Failure Handling

<Info>
  **Graceful Degradation**: If all webhook attempts fail, the tool will
  execute using its original parameters without dynamic variables.
</Info>

Pre-tool webhooks are designed for graceful degradation. When webhook calls fail:

1. The failure is logged for debugging purposes
2. The tool continues execution with its original static parameters
3. Any existing call-level dynamic variables remain available
4. The call continues normally without interruption

***

## Examples

```js theme={null}
// Example transfer number lookup function
async function getTransferNumber(fromNumber) {
    // Pretend we're fetching from a transfer number lookup API
    console.log(`Looking up transfer number for: ${fromNumber}`);
    return {
        transfer_number: '+1234567890' // match variable name from docs
    };
}

app.post('/webhook/pre-tool', async (req, res) => {
  const { tool_name, tool } = req.body;
  console.log(`🔧 Pre-tool webhook for: ${tool_name}`, tool);

  try {
    if (tool_name === 'transfer_call') {
      const transferNumber = await getTransferNumber(tool.from_number);

      return res.json({
        tool: {
          dynamic_variables: transferNumber
        }
      });
  	}

    // Default: no customization for other tools
    return res.json({
      tool: {
        dynamic_variables: {}
      }
    });
  } catch (err) {
    console.error('❌ Failed to fetch tool data', err);

    // Graceful degradation: return empty vars if lookup fails
    return res.json({
      tool: {
        dynamic_variables: {}
      }
    });
  }
});
```
