> For the complete documentation index, see [llms.txt](https://docs.salescaling.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.salescaling.com/en/practical-guides/agentes-de-voz-ia/tools-agentes-voz.md).

# Tools for Voice Agents

> ⚠️ **Beta Feature**
>
> Voice Agent Tools are currently in beta. If you're interested in trying this feature, contact our support team.

## Introduction

The **Tools** (tools) are extensions that allow your voice agents to perform actions during conversations, such as querying databases, scheduling meetings, updating CRM, checking product availability, and much more.

### Main Benefits

* 🔧 **Extensibility**: Connect your agent with any external system
* 🤖 **Smart automation**: The agent decides when to use each tool
* 🔄 **Real-time integration**: Get up-to-date data during the conversation
* 🎯 **Customization**: Create tools specific to your business
* 📊 **Traceability**: Record all tool calls for auditing

## What is a Tool?

A **Tool** is a function that your voice agent can call during a conversation to:

1. **Get information** from external systems (databases, APIs, CRM)
2. **Perform actions** (create records, send emails, update data)
3. **Make decisions** based on real-time data

### How It Works

```
┌─────────────┐      ┌──────────────┐      ┌─────────────┐
│   Client   │ ───> │ Voice Agent  │ ───> │  Your Webhook │
│   (Call)   │      │   (Decides)   │      │  (Tool)     │
└─────────────┘      └──────────────┘      └─────────────┘
                            │                      │
                            │  <─── Response ─────┘
                            │
                            ▼
                     Continue conversation
                     with the information
```

**Detailed flow:**

1. **The client speaks**: "Do you have availability for Tuesday at 3pm?"
2. **The agent analyzes**: Detects that it needs to check availability
3. **Calls your tool**: Sends an HTTP request to your webhook with the parameters
4. **Your system responds**: Returns the requested information
5. **The agent continues**: "Yes, we have availability on Tuesday at 3pm. Would you like to book it?"

## Types of Tools

### System Tools (SYSTEM)

These are predefined tools by Salescaling that are available to all agents:

* 🗓️ **Calendar Scheduler**: Schedules meetings in integrated calendars
* 📧 **Email Sender**: Sends automated emails
* 📝 **Note Creator**: Creates notes in the CRM

> ℹ️ **Note**: System tools **cannot be edited or deleted**. You can only view their configuration.

### User Tools (USER)

These are custom tools that you create for your specific use case:

* 🔍 **Check product availability**
* 💰 **Check prices in real time**
* 👤 **Search customer information in CRM**
* 📦 **Check order status**
* ✅ **Validate promotional codes**
* 🎫 **Book tickets or services**

## Create a Tool

### Step 1: Navigate to Tools

1. Go to **Voice Agents** in the main menu
2. Click on the tab **Tools**
3. Click on **"Create tool"**

### Step 2: Basic Configuration

#### Name

The name should be descriptive and in English (snake\_case):

```
✅ Correct:
- check_product_availability
- get_customer_info
- schedule_meeting

❌ Incorrect:
- tool1
- my tool
- Check Product
```

> 💡 **Tip**: The name is used internally. Use clear names that describe the action.

#### Description

The description is **crucial** because the agent uses it to decide when to call the tool.

```
✅ Good description:
"Checks the availability of a specific product in inventory.
Returns whether there is stock, the available quantity, and the estimated delivery time."

❌ Bad description:
"Query products"
```

**Best practices for descriptions:**

* Be specific about what the tool does
* Mention what information it needs (parameters)
* Indicate what information it returns
* Use clear and direct language
* Write in Spanish (the agent understands both languages)

### Step 3: Configure the Webhook

#### Webhook URL

The URL of your endpoint that will receive the calls:

```
https://api.yourcompany.com/tools/check-availability
```

**Requirements:**

* ✅ Must be HTTPS (secure)
* ✅ Must be publicly accessible
* ✅ Must respond in less than 10 seconds
* ✅ Must return valid JSON

#### HTTP Method

Select the appropriate method:

* **GET**: For querying information without modifying data
* **POST**: For creating or modifying data (recommended)
* **PUT**: For updating existing resources
* **PATCH**: For partial updates
* **DELETE**: For deleting resources

> 💡 **Recommendation**: Use POST for most tools, as it allows complex parameters to be sent in the body.

#### Webhook Secret (Optional)

A secret that will be sent in the header `X-Webhook-Secret` to authenticate requests:

```
X-Webhook-Secret: your_super_secure_secret_123
```

**Recommended use:**

```javascript
// In your webhook
app.post('/tools/check-availability', (req, res) => {
  const secret = req.headers['x-webhook-secret'];
  
  if (secret !== process.env.WEBHOOK_SECRET) {
    return res.status(401).json({ error: 'Unauthorized' });
  }
  
  // Process the request...
});
```

### Step 4: Define Input Schema

The **Input Schema** defines which parameters the agent will send to your webhook.

#### Example: Product Availability Tool

**Input Schema properties:**

| Name         | Type   | Description                  |
| ------------ | ------ | ---------------------------- |
| `product_id` | string | Product ID to query          |
| `quantity`   | number | Desired quantity             |
| `location`   | string | Customer location (optional) |

**Request you will receive:**

```json
{
  "product_id": "PROD-12345",
  "quantity": 2,
  "location": "Madrid"
}
```

#### Supported Data Types

* **string**: Text (names, IDs, descriptions)
* **number**: Numbers (quantities, prices, numeric IDs)

> ℹ️ **Note**: More types will be added soon (boolean, array, object).

#### Best Practices

* ✅ Use descriptive names in English (snake\_case)
* ✅ Add clear descriptions to each property
* ✅ Only include necessary parameters
* ✅ Consider what information the agent can extract from the conversation

### Step 5: Define Output Schema (Optional)

The **Output Schema** defines what information your webhook will return to the agent.

#### Is It Mandatory?

**No**, but it is **highly recommended** because:

* 📊 Documents what your tool returns
* 🤖 Helps the agent understand the response
* 🔍 Makes debugging easier
* ✅ Validates that the response is correct

#### Example: Availability Response

**Output Schema properties:**

| Name            | Type   | Description            |
| --------------- | ------ | ---------------------- |
| `available`     | string | "yes" or "no"          |
| `quantity`      | number | Available quantity     |
| `delivery_days` | number | Days until delivery    |
| `message`       | string | Message for the client |

**Response you should return:**

```json
{
  "available": "yes",
  "quantity": 15,
  "delivery_days": 2,
  "message": "We have 15 units available with delivery in 2 days"
}
```

## Implement the Webhook

### Request Structure

When the agent calls your tool, it sends a request with this structure:

**Headers:**

```
Content-Type: application/json
X-Webhook-Secret: your_secret (if you configured it)
User-Agent: Salescaling-VoiceAgent/1.0
```

**Body:**

```json
{
  "tool_name": "check_product_availability",
  "call_id": "call_abc123",
  "agent_id": "agent_xyz789",
  "parameters": {
    "product_id": "PROD-12345",
    "quantity": 2,
    "location": "Madrid"
  },
  "context": {
    "customer_phone": "+34612345678",
    "conversation_id": "conv_456"
  }
}
```

### Implementation Example

#### Node.js (Express)

```javascript
const express = require('express');
const app = express();

app.use(express.json());

app.post('/tools/check-availability', async (req, res) => {
  try {
    // 1. Validate the secret
    const secret = req.headers['x-webhook-secret'];
    if (secret !== process.env.WEBHOOK_SECRET) {
      return res.status(401).json({ error: 'Unauthorized' });
    }

    // 2. Extract parameters
    const { product_id, quantity, location } = req.body.parameters;

    // 3. Query your database
    const product = await db.products.findOne({ id: product_id });
    
    if (!product) {
      return res.json({
        available: 'no',
        quantity: 0,
        delivery_days: 0,
        message: 'Product not found'
      });
    }

    // 4. Check availability
    const available = product.stock >= quantity;
    const deliveryDays = calculateDeliveryDays(location);

    // 5. Return response
    return res.json({
      available: available ? 'yes' : 'no',
      quantity: product.stock,
      delivery_days: deliveryDays,
      message: available 
        ? `We have ${product.stock} units available`
        : `We only have ${product.stock} units available`
    });

  } catch (error) {
    console.error('Error:', error);
    return res.status(500).json({ 
      error: 'Internal server error',
      message: 'We could not verify availability'
    });
  }
});

app.listen(3000, () => {
  console.log('Webhook listening on port 3000');
});
```

#### Python (Flask)

```python
from flask import Flask, request, jsonify
import os

app = Flask(__name__)

@app.route('/tools/check-availability', methods=['POST'])
def check_availability():
    try:
        # 1. Validate the secret
        secret = request.headers.get('X-Webhook-Secret')
        if secret != os.getenv('WEBHOOK_SECRET'):
            return jsonify({'error': 'Unauthorized'}), 401

        # 2. Extract parameters
        data = request.get_json()
        product_id = data['parameters']['product_id']
        quantity = data['parameters']['quantity']
        location = data['parameters'].get('location', 'Spain')

        # 3. Query database
        product = db.get_product(product_id)
        
        if not product:
            return jsonify({
                'available': 'no',
                'quantity': 0,
                'delivery_days': 0,
                'message': 'Product not found'
            })

        # 4. Check availability
        available = product['stock'] >= quantity
        delivery_days = calculate_delivery_days(location)

        # 5. Return response
        return jsonify({
            'available': 'yes' if available else 'no',
            'quantity': product['stock'],
            'delivery_days': delivery_days,
            'message': f"We have {product['stock']} units available"
        })

    except Exception as e:
        print(f'Error: {e}')
        return jsonify({
            'error': 'Internal server error',
            'message': 'We could not verify availability'
        }), 500

if __name__ == '__main__':
    app.run(port=3000)
```

### Error Handling

Your webhook should handle errors gracefully:

```javascript
// ✅ Good practice
return res.status(200).json({
  available: 'no',
  quantity: 0,
  delivery_days: 0,
  message: 'We could not verify availability at this time. Can I help you with something else?'
});

// ❌ Bad practice
return res.status(500).json({ error: 'Database error' });
// This will make the agent not know what to say to the client
```

**Golden rule**: Always return a 200 status with a useful message for the client, even when there are internal errors.

## Assign Tools to Agents

Once the tool is created, you must assign it to the agents that will use it:

### Step 1: Edit the Agent

1. Go to **Voice Agents** > **Agents**
2. Click on the agent you want to edit
3. Look for the section **"Tools"**

### Step 2: Select Tools

1. Click on **"Add tool"**
2. Select the tools you want to enable
3. Save changes

### Step 3: Update the Prompt (Important)

You must **update the agent prompt** so it knows when to use each tool:

```
You are a sales assistant for an electronics store.

AVAILABLE TOOLS:
- check_product_availability: Use this tool when the client asks 
  if a product is available or how many units are in stock.
  
- get_customer_info: Use this tool when you need information about the 
  client (purchase history, address, etc.)

INSTRUCTIONS:
- When the client mentions a product, use check_product_availability 
  to verify stock before confirming.
- If the client is a returning customer, use get_customer_info to personalize 
  the conversation.
- Always confirm the information before finalizing the sale.
```

> 💡 **Tip**: Be explicit about when and how to use each tool. The agent will follow your instructions.

## Usage Examples

### Example 1: Check Product Availability

**Conversation:**

```
Client: "Hi, do you have the iPhone 15 Pro in stock?"
Agent: [Calls check_product_availability]
Agent: "Yes, we have 8 units of the iPhone 15 Pro available. 
         Which color do you prefer?"
```

**Tool Call:**

```json
{
  "tool_name": "check_product_availability",
  "parameters": {
    "product_id": "IPHONE-15-PRO",
    "quantity": 1
  }
}
```

**Response:**

```json
{
  "available": "yes",
  "quantity": 8,
  "delivery_days": 1,
  "message": "We have 8 units available with delivery tomorrow"
}
```

***

### Example 2: Schedule Meeting

**Conversation:**

```
Client: "I would like to schedule a demo for Tuesday at 3pm"
Agent: [Calls schedule_meeting]
Agent: "Perfect, I have scheduled your demo for Tuesday, January 15 
         at 3pm. I will send you a confirmation email."
```

**Tool Call:**

```json
{
  "tool_name": "schedule_meeting",
  "parameters": {
    "date": "2024-01-15",
    "time": "15:00",
    "type": "demo",
    "customer_email": "client@example.com"
  }
}
```

**Response:**

```json
{
  "success": "yes",
  "meeting_id": "MTG-789",
  "calendar_link": "https://calendar.google.com/...",
  "message": "Meeting successfully scheduled"
}
```

***

### Example 3: Validate Promo Code

**Conversation:**

```
Client: "I have a discount code: SUMMER2024"
Agent: [Calls validate_promo_code]
Agent: "Great! Your code SUMMER2024 gives you a 20% discount 
         on the entire store. What would you like to buy?"
```

**Tool Call:**

```json
{
  "tool_name": "validate_promo_code",
  "parameters": {
    "code": "SUMMER2024",
    "customer_id": "CUST-456"
  }
}
```

**Response:**

```json
{
  "valid": "yes",
  "discount_percent": 20,
  "expires_at": "2024-08-31",
  "message": "Valid code: 20% discount until August 31"
}
```

## Testing and Debugging

### Test your Tool

1. **Create a test call**:
   * Go to your agent
   * Click on "New call"
   * Use your own number to test
2. **Mention the use case**:
   * Say something that triggers the tool
   * Example: "Do you have product XYZ available?"
3. **Check the logs**:
   * Go to the completed conversation
   * Look for the "Tool Calls" section
   * Verify the request and response

### Tool Calls Logs

Each tool call is logged with:

* ⏰ **Timestamp**: When it was called
* 📤 **Request**: What parameters were sent
* 📥 **Response**: What your webhook returned
* ⏱️ **Duration**: How long it took
* ✅/❌ **Status**: Whether it was successful or failed

### Common Debugging

#### Error: "Tool call timeout"

**Cause**: Your webhook took more than 10 seconds to respond.

**Solution**:

* Optimize database queries
* Use caching for frequent data
* Consider asynchronous responses

#### Error: "Invalid JSON response"

**Cause**: Your webhook did not return valid JSON.

**Solution**:

```javascript
// ✅ Correct
return res.json({ available: 'yes' });

// ❌ Incorrect
return res.send('yes');
```

#### Error: "Webhook unreachable"

**Cause**: Your webhook is not publicly accessible.

**Solution**:

* Verify that the URL is correct
* Make sure your server is running
* Check the firewall and security rules
* Use HTTPS, not HTTP

#### The agent does not call the tool

**Cause**: The prompt is not clear about when to use the tool.

**Solution**:

* Update the prompt with explicit instructions
* Mention the tool by name in the prompt
* Give examples of when to use it

## Best Practices

### ✅ Do

* **Fast responses**: Optimize to respond in < 2 seconds
* **Clear messages**: Return messages that the agent can use directly
* **Error handling**: Always return a helpful response, even in errors
* **Validation**: Validate parameters before processing them
* **Logging**: Log all calls for debugging
* **Idempotency**: The same inputs should produce the same outputs
* **Documentation**: Document what each tool does and how to use it

### ❌ Avoid

* **Long timeouts**: Do not make queries that take > 10 seconds
* **Technical responses**: Do not return technical error messages
* **Sensitive data**: Do not include confidential information in responses
* **Undocumented side effects**: Do not perform actions not described in the tool
* **External dependencies**: Minimize calls to slow external APIs
* **Ambiguous responses**: Be specific in your responses

## Security

### Authentication

Always validate the webhook secret:

```javascript
const secret = req.headers['x-webhook-secret'];
if (secret !== process.env.WEBHOOK_SECRET) {
  return res.status(401).json({ error: 'Unauthorized' });
}
```

### Data Validation

Validate all received parameters:

```javascript
const { product_id, quantity } = req.body.parameters;

if (!product_id || typeof product_id !== 'string') {
  return res.json({
    available: 'no',
    message: 'Invalid product ID'
  });
}

if (!quantity || quantity < 1) {
  return res.json({
    available: 'no',
    message: 'Invalid quantity'
  });
}
```

### Rate Limiting

Implement rate limiting to prevent abuse:

```javascript
const rateLimit = require('express-rate-limit');

const limiter = rateLimit({
  windowMs: 1 * 60 * 1000, // 1 minute
  max: 100 // maximum 100 requests per minute
});

app.use('/tools/', limiter);
```

### HTTPS Required

Always use HTTPS for your webhooks:

```
✅ https://api.yourcompany.com/tools/...
❌ http://api.yourcompany.com/tools/...
```

## Current Limitations

Since this functionality is in **beta phase**, keep in mind:

* ⚠️ **Timeout**: Tools must respond in < 10 seconds
* 🔢 **Data types**: Only string and number (more types coming soon)
* 📊 **Calls per conversation**: Maximum 10 tool calls per conversation
* 🌍 **Languages**: Optimized for Spanish and English
* 📝 **Complex schemas**: Arrays and nested objects coming soon

## Frequently Asked Questions

<details>

<summary>How many tools can I create?</summary>

There is no limit to the number of tools you can create. However, we recommend keeping a manageable number (5-10) to make maintenance easier.

</details>

<details>

<summary>Can I edit a tool after creating it?</summary>

Yes, you can edit any USER-type tool. SYSTEM-type tools cannot be edited.

</details>

<details>

<summary>What happens if my webhook is down?</summary>

If your webhook does not respond, the agent will continue the conversation without the tool information and will tell the customer that it could not verify the information at that time.

</details>

<details>

<summary>Can I use the same tool in multiple agents?</summary>

Yes, you can assign the same tool to multiple agents. This is useful for generic tools such as availability checks.

</details>

<details>

<summary>How do I know how many times my tool has been called?</summary>

You can see the usage statistics for each tool on the Tools page. You can also review the logs for each individual conversation.

</details>

<details>

<summary>Can I pass additional context to my webhook?</summary>

Yes, each call includes a `context` object with call information (call\_id, agent\_id, customer\_phone, etc.) that you can use for logging or personalization.

</details>

<details>

<summary>What happens if I return the wrong format?</summary>

If your response does not match the defined output schema, the agent will try to interpret the response as best as possible. However, it is recommended to always follow the defined schema.

</details>

<details>

<summary>Can I make one tool call another tool?</summary>

Not directly. Each tool is independent. If you need to chain actions, you must do it in your webhook before returning the response.

</details>

<details>

<summary>How can I test my webhook locally?</summary>

You can use tools like [ngrok](https://ngrok.com/) to expose your local server with a temporary public URL:

```bash
ngrok http 3000
# Use the https://xxxx.ngrok.io URL in your tool
```

</details>

<details>

<summary>Do tools work in all languages?</summary>

Yes, tools work regardless of the agent's language. The parameters are extracted from the conversation in any supported language.

</details>

## Support

If you need help with Tools:

* 📧 **Email**: <support@salescaling.com>
* 💬 **Live chat**: Available on the platform
* 📚 **Documentation**: [docs.salescaling.com](https://docs.salescaling.com)
* 🔗 **API Reference**: [Webhook API](/en/api/webhooks.md)

### Related Resources

* [AI Voice Agents](/en/practical-guides/agentes-de-voz-ia.md)
* [Webhook API](/en/api/webhooks.md)
* [Blacklist Management](/en/practical-guides/gestion-de-blacklist.md)

***


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.salescaling.com/en/practical-guides/agentes-de-voz-ia/tools-agentes-voz.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
