> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.vapi.ai/llms.txt.
> For full documentation content, see https://docs.vapi.ai/llms-full.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.vapi.ai/_mcp/server.

# Custom tools troubleshooting

> Resolve common issues with custom tool integrations

## Overview

Troubleshoot and fix common issues with custom tool integrations in your Vapi assistants.

**In this guide, you'll learn to:**

* Diagnose why tools aren't triggering
* Fix response format errors
* Resolve parameter and token issues
* Handle multiple tool scenarios

## Quick diagnosis

Start with the most common issue for your symptoms:

**Symptoms:** Assistant doesn't call your tool Check prompting and schema
setup

**Symptoms:** Logs show "no result returned" Fix response format issues

**Symptoms:** Tool returns data but assistant ignores it Resolve parsing and
format problems

**Symptoms:** Tool parameters or responses truncated Increase token limits

## Tool won't trigger

Your assistant doesn't call the tool even when it should.

### Check your assistant prompting

`txt title="❌ Too vague" Handle weather requests ` `txt title="✅
  Specific and clear" When user asks for weather, use weather_tool with city
  parameter `

Use the exact tool name in your assistant instructions. If your tool is named
`get_weather`, reference `get_weather` in prompts, not `weather_tool`.

### Verify required parameters

Check that your tool schema includes all required parameters:

```json title="Tool schema"
{
  "name": "get_weather",
  "parameters": {
    "type": "object",
    "properties": {
      "city": {
        "type": "string",
        "description": "City name for weather lookup"
      }
    },
    "required": ["city"] // Must be array of required parameter names
  }
}
```

### Enable schema validation

Add `strict: true` to catch validation errors early:

```json title="Tool configuration" {7}
{
  "name": "get_weather",
  "description": "Get current weather for a city",
  "parameters": {
    // ... your parameters
  },
  "strict": true,
  "maxTokens": 500
}
```

Check your call logs for "Schema validation errors" to identify parameter
issues.

## No result returned error

Logs show "ok, no result returned" or similar messages.

### Use the correct response format

Your webhook **must** return this exact JSON structure:

```json title="✅ Success response"
{
  "results": [
    {
      "toolCallId": "call_123",
      "result": "Your response as single-line string"
    }
  ]
}
```

```json title="✅ Error response"
{
  "results": [
    {
      "toolCallId": "call_123", 
      "error": "Error message as single-line string"
    }
  ]
}
```

### Common format mistakes

**Always return HTTP 200**, even for errors. Any other status code is ignored completely.

```json
// Return this with HTTP 200
{
  "results": [
    {
      "toolCallId": "call_123",
      "error": "Something went wrong"
    }
  ]
}
```

Use single-line strings only. Line breaks cause parsing errors.

```json title="❌ Has line breaks"
{
  "result": "Line 1\nLine 2\nLine 3"
}
```

```json title="✅ Single line"
{
  "result": "Line 1, Line 2, Line 3"
}
```

The response must have the `results` array structure. Individual result objects won't work.

The `toolCallId` in your response must exactly match the ID from the request.

Both `result` and `error` fields must be strings, not objects or arrays.

## Response ignored

Tool returns data but the assistant doesn't use it in conversation.

### Fix line breaks and formatting

```json title="❌ Line breaks cause parsing errors"
{
  "results": [
    {
      "toolCallId": "call_123",
      "result": "Temperature: 72°F\nCondition: Sunny\nHumidity: 45%"
    }
  ]
}
```

```json title="✅ Single-line string works"
{
  "results": [
    {
      "toolCallId": "call_123", 
      "result": "Temperature: 72°F, Condition: Sunny, Humidity: 45%"
    }
  ]
}
```

### Verify HTTP status and JSON structure

Ensure your webhook returns HTTP 200. Any other status code causes the
response to be ignored.

{" "}

Use a JSON validator to ensure your response structure is valid.

For multiple tools, return results in the same order as calls were
triggered, with matching `toolCallId` values.

## Token truncation

Tool parameters or responses are getting cut off.

### Increase token limits

The default token limit is only 100. Increase it for complex tools:

```json title="Tool configuration" {7}
{
  "name": "complex_tool",
  "description": "Tool that needs more tokens",
  "parameters": {
    // ... your parameters
  },
  "maxTokens": 500 // Increase from default 100
}
```

Look for "Token truncation warnings" in your call logs to identify when this
occurs.

## Multiple tools scenarios

Some tools in parallel calls fail or return wrong results.

### Handle multiple tool responses

Return all results in the same order as the calls were triggered:

```json title="Multiple tool response"
{
  "results": [
    {
      "toolCallId": "call_1",
      "result": "First tool success"
    },
    {
      "toolCallId": "call_2",
      "error": "Second tool failed"
    },
    {
      "toolCallId": "call_3",
      "result": "Third tool success"
    }
  ]
}
```

Use HTTP 200 for the entire response, even if some individual tools error.
Handle errors within the `results` array using the `error` field.

## Async vs sync behavior

Tool behavior doesn't match your expectations.

**Configuration:** `"async": false` (default)

**Behavior:**

* Wait for webhook response before resolving
* Tool call resolution depends on your response
* Use for immediate operations

```json
{
  "name": "sync_tool",
  "async": false,  // or omit (default)
  // ... other config
}
```

**Configuration:** `"async": true`

**Behavior:**

* Tool call marked as resolved immediately
* Don't wait for actual processing
* Use for long-running operations

```json
{
  "name": "async_tool", 
  "async": true,
  // ... other config
}
```

Most tools should use sync behavior unless you specifically need async
processing for long-running operations.

## Reference: Required formats

### Response format template

```json title="Success response"
{
  "results": [
    {
      "toolCallId": "call_123",
      "result": "Single-line string response"
    }
  ]
}
```

```json title="Error response"
{
  "results": [
    {
      "toolCallId": "call_123",
      "error": "Single-line error message"  
    }
  ]
}
```

### Tool schema template

```json title="Complete tool configuration"
{
  "name": "tool_name",
  "description": "Clear description of what the tool does",
  "parameters": {
    "type": "object",
    "properties": {
      "param1": {
        "type": "string",
        "description": "Parameter description"
      }
    },
    "required": ["param1"]
  },
  "strict": true,
  "maxTokens": 500,
  "async": false
}
```

### Critical response rules

**Always return HTTP 200** - Even for errors

**Use single-line strings** - No `\n` line breaks

**Match tool call IDs exactly** - From request to response

**Include results array** - Required structure

**String types only** - For result/error values

## Debugging with call logs

Look for these key error messages in your call logs:

| Error Message               | What It Means               | How to Fix                 |
| --------------------------- | --------------------------- | -------------------------- |
| "ok, no result returned"    | Wrong response format       | Use correct JSON structure |
| "Tool call ID mismatches"   | toolCallId doesn't match    | Ensure exact ID match      |
| "HTTP errors"               | Webhook not returning 200   | Return HTTP 200 always     |
| "Schema validation errors"  | Missing required parameters | Check required array       |
| "Token truncation warnings" | Need more tokens            | Increase maxTokens         |
| "Response parsing errors"   | Malformed JSON/line breaks  | Fix JSON format            |