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

# Function Call Agent Actions

> Configure the capabilities of your agent with function calls

During the conversation with a caller, you can configure your agent to perform certain actions at the request of the caller. This is done by configuring the various function calls available.

This guide covers how to define and customize function calls for your AI agent.

This Function Call feature is displayed on the Platform dashboard alongside the [Custom Prompt](conversation-prompts#custom-prompts) feature.

### Quick Overview

<CardGroup>
  <Card title="End Call" icon="phone-slash" href="function-calls#end-call">
    **Cost:** Free\
    **Customisable Aspects:**

    * Transition message
  </Card>

  <Card title="Transfer Call" icon="phone-arrow-right" href="function-calls#transfer-call">
    **Cost:** 10 credits, 40 credits per minute of the transferred call\
    **Customisable Aspects:**

    * Transition message.
    * Display Agent's or caller's number to transferee.
    * Warm transfer or Cold.
    * List of transferrable contacts.
  </Card>

  <Card title="Custom Function Call" icon="satellite-dish" href="function-calls#custom-function-call">
    **Cost:** Free\
    **Customisable Aspects:**

    * Transition message
    * Function prompt description
    * External API Integration
    * Authentication Methods
    * Request/Response Processing
    * Error Handling & Retries
  </Card>

  <Card title="GCal — Check Availability" icon="calendar-check" href="function-calls#gcal-check-availability">
    **Cost:** Free\
    **Requires:** [Google Calendar integration](../integrations/google-calendar/overview) connected at the workspace level\
    **Customisable Aspects:**

    * Transition message
    * Calendars to check (multi-select picker)
    * Slot duration, look-ahead window, minimum notice
    * Max number of slots to offer
    * Default timezone
  </Card>
</CardGroup>

## End Call

End Call is a simple function call in which the Agent intelligently determines when to end the call based on the conversation with the caller.

It's free of cost and available for all agents.

#### Transition Message

Users can customize the goodbye message that the Agent delivers to the caller before ending the call.

<Frame>
  <img src="https://mintcdn.com/heffronai/KV6HO4h8tpBJL03E/images/function-call/end-call-config.webp?fit=max&auto=format&n=KV6HO4h8tpBJL03E&q=85&s=e10f82815515d267b4fd32cd3ccc0a56" style={{ borderRadius: '0.5rem' }} width="800" height="384" data-path="images/function-call/end-call-config.webp" />
</Frame>

## Transfer Call

The Transfer Call function allows the agent to transfer the call to another number, at the request of the caller. It is available for all agents.

Each Transfer Call request is charged at a cost of 10 credits. Once the transferred call is in progress, it will be charged at a rate of 40 credits per minute, independently from the initial AI call.

#### Transition Message

Custom message the Agent delivers to the caller before attempting to transfer the call to the desired transferee.

#### Display Agent Caller ID

Whether the transferree should see the Agent's phone number or the caller's phone number in the dialled call.

#### Warm vs Cold Transfer

Select between either Warm or Cold transfer.
Warm transfer allows the transferree to hear a summary of the previous AI call whilst the call is still connecting. This way the transferree can be provided some context of the previous call.
Cold transfer has no summary of the previous call.

#### Transferrable Contacts

A list of contacts the agents can transfer the call to. The contacts are mapped between name and number

The agent can use the name in the conversation to help caller identify whom they wish to transfer the call to.

<Warning>
  The numbers must entered in E.164 format, and we only support Australian numbers at the moment. I.e. +614XXXXXXXX for mobile, or +61XYYYYYYYY for landline where X is not 4.
</Warning>

<Frame>
  <img src="https://mintcdn.com/heffronai/KV6HO4h8tpBJL03E/images/function-call/transfer-call-config.webp?fit=max&auto=format&n=KV6HO4h8tpBJL03E&q=85&s=57fc5d1720d76a68eb48021c2eb6c0b3" style={{ borderRadius: '0.5rem' }} width="800" height="383" data-path="images/function-call/transfer-call-config.webp" />
</Frame>

## Custom Function Call

The Custom Function Call feature enables your AI agent to dynamically call external APIs during conversations, allowing it to fetch real-time data, perform actions, or integrate with third-party services. This powerful capability transforms your agent from a static conversational AI into a dynamic, action-oriented assistant.

### Key Features

* **Dynamic API Integration**: Connect to any REST API endpoint
* **Multiple Authentication Methods**: Support for API keys, Bearer tokens, Basic auth, and webhook secrets
* **Intelligent Parameter Mapping**: Automatic URL templating and parameter substitution
* **Response Processing**: Extract and structure data from API responses
* **Error Handling**: Configurable retry logic and error mapping
* **Secure Credential Storage**: Encrypted storage of sensitive API keys and passwords

### Configuration Overview

<Frame>
  <img src="https://mintcdn.com/heffronai/KV6HO4h8tpBJL03E/images/function-call/custom-fnc-call-config.webp?fit=max&auto=format&n=KV6HO4h8tpBJL03E&q=85&s=920e43e4827ebace32cd200dfce243cd" style={{ borderRadius: '0.5rem' }} width="1488" height="668" data-path="images/function-call/custom-fnc-call-config.webp" />
</Frame>

### Function Configuration

#### Function Name

A unique identifier for your custom function (e.g., `get_weather_forecast`, `fetch_github_profile`). This name is used by the AI agent to identify and call the appropriate function during conversations.

#### Function Description

A clear, detailed description of what the function does. Include relevant keywords to help the AI agent understand when to use this function:

```
"Retrieve weather forecast and climate data for specific locations and dates. Use this function when the caller asks about weather conditions, temperature, or climate information."
```

#### Parameter Specification

Define the input parameters your function accepts using JSON Schema format, abiding by [OpenAPI Specification](https://swagger.io/specification/):

<Tip>
  Additionally refer to OpenAI's [cookbook](https://cookbook.openai.com/examples/function_calling_with_an_openapi_spec) for an easy-to-follow example.
</Tip>

```json theme={null}
{
  "location": {
    "type": "string",
    "description": "The city, state, or location for weather forecast (e.g., 'Sydney, NSW')",
    "required": true,
    "minLength": 2,
    "maxLength": 100
  },
  "start_date": {
    "type": "string",
    "description": "Start date for weather forecast in YYYY-MM-DD format. For single day requests, use the same date as end_date. For multiple days, use the earliest requested date to create an optimal date range.",
    "format": "date",
    "required": true,
  },
  "end_date": {
    "type": "string",
    "description": "End date for weather forecast in YYYY-MM-DD format. For single day requests, use the same date as start_date. For multiple days, use the latest requested date to create an optimal date range that covers all requested days.",
    "format": "date",
    "required": true,
  },
  "unitGroup": {
    "type": "string",
    "required": false,
    "default": "metric",
    "enum": ["metric", "us", "uk"],
    "description": "Temperature unit system"
  },
  "include": {
    "type": "string",
    "required": false,
    "default": "days",
    "enum": ["days", "hours", "current"],
    "description": "Data granularity level"
  }
}
```

### API Configuration

#### API Endpoint

The URL endpoint for your external API. Supports parameter templating using `{parameter_name}` syntax:

```
https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/timeline/{location}/{start_date}/{end_date}
```

#### HTTP Method

Select the appropriate HTTP method for your API (GET, POST, PUT, PATCH, DELETE).

#### Timeout

Maximum time (in seconds) to wait for the API response before timing out (default: 30 seconds).

### Authentication Methods

Custom Function Call supports four authentication methods to accommodate different API security requirements:

#### 1. API Key Authentication

Use for APIs that require an API key in headers or query parameters.

**Configuration:**

* **API Key**: Your authentication key (include prefix if required, e.g., `Bearer your_key` or `token your_key`)
* **Header Name**: Custom header name (e.g., `Authorization`, `X-API-Key`)
* **Query Parameter Name**: Query parameter name (e.g., `key`, `api_key`)

**Examples:**

```bash theme={null}
# GitHub API (Header)
Authorization: Bearer ghp_your_token_here

# Weather API (Query Parameter)  
https://api.weather.com/forecast?location=sydney&key=your_api_key

# Custom Header
X-API-Key: your_api_key_here
```

#### 2. Bearer Token Authentication

Standard OAuth2 Bearer token authentication.

**Configuration:**

* **Bearer Token**: Your OAuth2 access token

**Example:**

```bash theme={null}
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```

#### 3. Basic Authentication

HTTP Basic authentication using username and password.

**Configuration:**

* **Username**: Your API username
* **Password**: Your API password

<Note>
  Credentials are automatically base64 encoded and prefixed with "Basic " in the Authorization header. Additionally password is also hashed when stored, for security reasons.
</Note>

#### 4. Webhook Secret Authentication

For APIs that require webhook signature verification.

**Configuration:**

* **Webhook Secret**: Your webhook signing secret
* **Event Type**: Custom event type (default: `voqo.custom_function_call`)

<Note>
  We only support POST requests for webhook authentication.
</Note>

### Response Processing

#### Response Extraction

Map API response fields to variables, via simple path dot notation, that can be used in the conversation:

```json theme={null}
{
  "location": "resolvedAddress",
  "first_day_temp": "days[0].temperature",
  "all_days_max_temp": "days[*].tempmax"
}
```

**Path Syntax:**

* Simple paths: `current.temperature`
* Array access: `forecast[0].date`
* Wildcard arrays: `forecast[*].tempMax`

#### Error Mapping

Map API error responses to user-friendly messages:

```json theme={null}
{
  "401": "Request failed due to system error, I will notify my boss about this. Sorry for the inconvenience.",
  "429": "You've made too many of these requests in a short period of time. Please try again later."
}
```

### Retry Configuration

Configure automatic retry behavior for failed API calls:

* **Max Attempts**: Maximum number of retry attempts (default: 3)
* **Initial Delay**: Starting delay between retries in seconds (default: 1.0)
* **Max Delay**: Maximum delay between retries in seconds (default: 10.0)
* **Backoff Factor**: Multiplier to increase delay between retries (default: 2.0)

### Security & Best Practices

#### Credential Security

* All secrets (API keys, passwords, webhook secrets) are encrypted at rest.
* Secrets are never stored in plain text.
* Secrets are automatically masked in the UI for security.

#### API Key Prefixes

When using API Key authentication, include any required prefixes in the API key field:

* GitHub: `Bearer ghp_your_token_here`
* Some APIs: `token your_token_here`
* Simple APIs: `your_key_here` (no prefix)

#### Rate Limiting

* Implement appropriate timeout values to avoid API rate limits
* Use retry configuration with exponential backoff for transient failures
* Consider API usage limits when designing function calls

### Example Configurations

#### Weather API GET Request

```json theme={null}
{
  "transition_message": "grabbing climate info, please wait",
  "function_name": "get_weather_forecast",
  "function_description": "Retrieve weather forecast and climate data for specific locations and dates. Keywords: weather, forecast, temperature, climate, precipitation, rain, sunny, cold, hot, atmospheric, humidity, wind. Use this function ONLY when the caller asks about weather conditions, temperature, precipitation, climate, or atmospheric conditions for a specific location and date range. Requires location, start_date, and end_date parameters.",
  "parameter_specification": {
    "location": {
      "type": "string",
      "required": true,
      "description": "The city, state, or location for weather forecast (e.g., 'San Francisco, CA')",
      "minLength": 2,
      "maxLength": 100
    },
    "start_date": {
      "type": "string",
      "format": "date",
      "required": true,
      "description": "Start date for weather forecast in YYYY-MM-DD format. For single day requests, use the same date as end_date. For multiple days, use the earliest requested date to create an optimal date range."
    },
    "end_date": {
      "type": "string",
      "format": "date",
      "required": true,
      "description": "End date for weather forecast in YYYY-MM-DD format. For single day requests, use the same date as start_date. For multiple days, use the latest requested date to create an optimal date range that covers all requested days."
    },
    "unitGroup": {
      "type": "string",
      "required": false,
      "default": "metric",
      "enum": ["metric", "us", "uk"],
      "description": "Temperature unit system"
    },
    "include": {
      "type": "string",
      "required": false,
      "default": "days",
      "enum": ["days", "hours", "current"],
      "description": "Data granularity level"
    }
  },
  "api_endpoint": "https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/timeline/{location}/{start_date}/{end_date}",
  "api_method": "GET",
  "auth": {
    "type": "api_key",
    "api_key": "your_api_key",
    "query_param_name": "key",
  },
  "headers": {},
  "timeout": "30",
  "retry_config": {
    "max_attempts": 3,
    "initial_delay": 1.0,
    "max_delay": 10.0,
    "backoff_factor": 2.0
  },
  "response_status_processing": {
    "success_criteria": {},
    "error_mapping": {}
  },
  "response_extraction": {
    "location": "resolvedAddress",
    "all_daily_tempmax_data": "days[*].tempmax",
    "all_daily_tempmin_data": "days[*].tempmin"
  }
},
```

#### GitHub API GET user info Request

```json theme={null}
{
  "function_name": "fetch_github_profile", 
  "function_description": "Retrieve GitHub user profile public information",
  "api_endpoint": "https://api.github.com/users/{username}",
  "api_method": "GET",
  "auth": {
    "type": "bearer",
    "api_key": "ghp_your_github_token_here"
  },
  "headers": {},
  "timeout": "30",
  "retry_config": {
    "max_attempts": 3,
    "initial_delay": 1.0,
    "max_delay": 10.0,
    "backoff_factor": 2.0
  },
  "parameter_specification": {
    "username": {
      "type": "string",
      "required": true,
      "description": "The username of the GitHub user to fetch profile information for"
    }
  },
  "response_status_processing": {
    "success_criteria": {},
    "error_mapping": {}
  },
  "response_extraction": {}
}
```

### Usage in Conversations

Once configured, your AI agent will automatically identify when to use custom functions based on the caller's requests:

**Caller:** *"What's the weather like in Sydney next weekend?"*

**Agent:** *"Let me check the forecast for you..."*

*\[Agent calls get\_weather\_forecast function with next Saturday and Sunday as the date range, and other parameters if applicable (inclu. humidity in this example), then processes and returns the following response]*

**Agent:** *"The temperature in Sydney next Saturday is 22°C with partly cloudy skies and 65% humidity, and the temperature on Sunday is 25°C with sunny skies and 50% humidity."*

<Tip>
  The quality of the Agent's ability to use the custom function call is dependent on the custom function call's configuration, especially the prompting in the `description` fields (function description and parameter specification).
</Tip>

### Troubleshooting

#### Common Issues

1. **Authentication Errors (401)**
   * Verify API key/token is correct and not expired
   * Check if prefix is required (e.g., `Bearer ` for GitHub)
   * Ensure credentials are properly encrypted and stored

2. **Parameter Mapping Errors**
   * Verify JSON Schema syntax is valid
   * Check that required parameters are properly defined
   * Ensure parameter names match URL template placeholders

3. **Response Processing Issues**
   * Validate response extraction paths match actual API response structure
   * Test API endpoint directly to understand response format
   * Check for nested objects and array structures

4. **Timeout Errors**
   * Increase timeout value for slow APIs
   * Implement retry configuration for transient failures
   * Consider API rate limits and usage patterns

#### Debug Information

Enable debug logging to troubleshoot function call issues:

* Check terminal logs for API request/response details
* Verify authentication headers are correctly formatted
* Monitor retry attempts and error responses

### Cost & Limitations

* **Cost**: Free for all agents
* **Rate Limits**: Subject to your API provider's rate limits
* **Timeout**: Maximum 60 seconds per API call
* **Response Size**: No hard limit, but recommended to define specific Response Variables for key info extraction to avoid bloating Agent memory.
* **Concurrent Calls**: Not applicable, we only allow sequential function calls (one at a time) for now.

## GCal — Check Availability

The GCal Check Availability function lets your agent read your Google Calendar(s) mid-call and offer the caller concrete open slots. The agent confirms the slot verbally — your team books it manually afterwards.

It's currently the **only Google Calendar function-call action** — booking (writing events directly from a call) is on the roadmap. It's free and available for every agent in a workspace that has Google Calendar connected.

<Note>
  This function call is **integration-backed** — it only appears in the function-call picker when [Google Calendar is connected](../integrations/google-calendar/setup) at the workspace level. Disconnect Google Calendar and the action silently drops out of every agent that uses it on the next call. For the full integration story, see the [Google Calendar integration docs](../integrations/google-calendar/overview).
</Note>

<Note>
  **Two calendar selections, two scopes.** The **Calendars** you pick here apply to *this agent's* availability checks. Your workspace's **AI assistant** ("what's on my plate") has its own, separate calendar selection, set on the Google Calendar card under **⋮ → Choose calendars** — see [choosing calendars for your AI assistant](../integrations/google-calendar/setup#choose-which-calendars-your-ai-assistant-uses). Both selections accept multiple calendars.
</Note>

### Prerequisites

* Google Calendar integration connected for the workspace (see [setup](../integrations/google-calendar/setup))
* Workspace's connected Google account has access to the calendars you want the agent to read

### Configuration

| Field                        | What it does                                                                                                                     | Recommended starting point                         |
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- |
| **Calendars**                | Which calendars to check. A multi-select dropdown shows every calendar your connected Google account can see — pick one or more. | **Primary** (your main calendar)                   |
| **Slot duration (minutes)**  | How long each proposed slot should be.                                                                                           | 30 (or 15 for quick callbacks, 60 for inspections) |
| **Look-ahead (minutes)**     | How far into the future to search for free slots.                                                                                | 7200 (5 days)                                      |
| **Minimum notice (minutes)** | Don't propose slots starting within this many minutes from now.                                                                  | 60 (don't propose slots within the next hour)      |
| **Max slots**                | The maximum number of options the agent will read out.                                                                           | 5 (more than this is overwhelming on a call)       |
| **Default timezone**         | IANA timezone, e.g. `Australia/Sydney`. The agent uses this when the caller doesn't specify a timezone.                          | Your office's timezone                             |
| **Transition message**       | A short phrase the agent says before checking the calendar — fills the silence during the lookup.                                | "Let me check the calendar for you…"               |

### What the caller hears

> **Caller:** *"When can I come and see the property?"*
>
> **Agent:** *"Let me check the calendar for you…"*
>
> *\[Agent calls Google Calendar's freeBusy endpoint for the selected calendars and time window, finds open slots that match the configured duration and notice constraints, then reads them back.]*
>
> **Agent:** *"I've got three options that work: Thursday at 10 AM, Thursday at 2 PM, or Friday at 9 AM. Which suits you?"*
>
> **Caller:** *"Thursday at 2 PM works."*
>
> **Agent:** *"Great — I'll note that down and someone from our team will confirm with you shortly."*

### Common configurations

#### Inspection requests

* Slot duration **60 minutes**, look-ahead **48 hours**, max slots **3**
* Default timezone matches the property's location

#### Vendor catch-up calls

* Slot duration **15 minutes**, look-ahead **5 days**, max slots **5**
* Useful for callers who want a short check-in this week

#### Sales colleague handovers

* Add the colleague's shared calendar to the **Calendars** dropdown (the colleague needs to share their calendar with your connected Google account first)
* Slot duration matches the colleague's typical call length

### Failure handling

| Failure                                      | What the caller hears                                                         | What you do                                                                                                                             |
| -------------------------------------------- | ----------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| Google Calendar is disconnected at call time | Agent doesn't offer the availability check at all (action silently drops out) | Reconnect from the [Integrations page](../integrations/google-calendar/setup)                                                           |
| `freeBusy` API timeout or transient error    | *"I can't check the calendar right now"*                                      | Usually transient — try again. If persistent, contact <a href="mailto:support@voqo.ai?subject=GCal%20availability%20errors">support</a> |
| No slots found in the look-ahead window      | Agent says it can't find any open times that match                            | Increase look-ahead, reduce minimum notice, or check that the selected calendar(s) actually have free windows                           |
| Selected calendar no longer exists in Google | Skipped silently for that calendar; others still checked                      | Re-open the action config — the picker refreshes from Google and you can remove the dead calendar                                       |

### Cost & limitations

* **Cost**: Free for all agents (no Google Calendar API charges either — we operate within Google's free tier for the volumes in scope)
* **Read-only**: v1.0 ships availability lookups only. Writing events (locking the booking in directly from the call) is on the roadmap
* **Read-only at the OAuth scope level too**: Voqo only requests `calendar.readonly` — we cannot create, modify, or delete anything on your calendar in v1.0
* **No background syncing**: Voqo reads your calendar live each call. Nothing is cached on our side

For the full integration story (OAuth flow, what other Voqo AI surfaces will use this connection, troubleshooting), see the [Google Calendar overview](../integrations/google-calendar/overview).
