What are Custom Functions?
Custom functions let your Voice AI agent call your own APIs during live conversations. Check order status, update a CRM, book appointments, or integrate with any system - all while on a call.Bolna custom functions follow the OpenAI function calling specification. If you’ve used OpenAI function calling before, you’ll feel right at home.

How Custom Functions Work
LLM Reads Function Definition
The LLM sees your function’s
name and description to understand what the function doesDecides When to Call
Based on conversation context, the LLM decides if this function should be triggered
Extracts Parameters
The LLM collects required parameter values from the conversation with the caller
Bolna Executes API Call
Bolna makes the HTTP request to your API endpoint with the extracted parameters
Complete Schema Structure
Every custom function has two parts: Function Definition (tells LLM what it does) and API Configuration (tells Bolna how to call your API).Schema Reference
Parts 1-2 follow the OpenAI function calling specification - they define what the function does. Parts 3-5 are Bolna extensions that define how to execute the API call automatically.
1. Function Definition
These fields tell the LLM about your function:| Field | Required | Description |
|---|---|---|
name | Yes | Unique function identifier. Use snake_case (e.g., get_order_status) |
description | Yes | Tells the LLM when to trigger this function. Be specific and detailed. |
parameters | Yes | Defines what information to collect from the caller |
2. Parameters Object
Theparameters object defines what information the LLM should collect from the caller.
| Type | Use Case | Example Values |
|---|---|---|
string | Text, names, IDs, phone numbers | "John Doe", "ORD-12345" |
integer | Whole numbers | 5, 100, -10 |
number | Decimal numbers | 29.99, 3.14 |
boolean | True/false flags | true, false |
In required array? | Behavior |
|---|---|
| Yes | LLM will keep asking until this value is provided |
| No | Optional - included if mentioned, skipped otherwise |
3. Bolna Extensions
These fields are specific to Bolna:| Field | Required | Description |
|---|---|---|
pre_call_message | No | Message the agent speaks while API is executing (e.g., “One moment please…”) |
key | Yes | Must be "custom_task" - identifies this as a custom function |
value | Yes | API configuration object (see below) |
4. API Configuration (value object)
This tells Bolna how to make the HTTP request:
| Field | Required | Description |
|---|---|---|
method | Yes | HTTP method: GET, POST, PUT, PATCH, DELETE |
url | Yes | Your API endpoint URL |
param | Yes | Maps parameters to API request using format specifiers |
api_token | No | Authorization header value (e.g., Bearer your_token) |
headers | No | Additional HTTP headers as key-value pairs |
5. Format Specifiers
Theparam object maps your parameters to the API request. Use Python-style format specifiers:
| Data Type | Format Specifier | Example |
|---|---|---|
| String | %(param_name)s | "customer_id": "%(customer_id)s" |
| Integer | %(param_name)i | "quantity": "%(quantity)i" |
| Float | %(param_name)f | "price": "%(price)f" |
Parameter names must match exactly. The name in
properties must be identical to the name in param mapping (case-sensitive).Examples
GET Request - Fetch Product Details
GET Request - Fetch Product Details
GET custom function:POST Request - Save Customer Feedback
POST Request - Save Customer Feedback
POST custom function:Using Variables and Dynamic Context
Context variables defined in your agent prompt are automatically substituted into custom functions. The LLM won’t ask the caller for these values - they’re already available.Auto-Injected System Variables
| Variable | Description |
|---|---|
{agent_id} | The id of the agent |
{call_sid} | Unique id of the phone call (from Twilio, Plivo, etc.) |
{from_number} | Phone number that initiated the call |
{to_number} | Phone number that received the call |
How Variable Substitution Works
| Parameter | Defined in Prompt? | Result |
|---|---|---|
to_number | Yes (system) | Auto-substituted |
agent_id | Yes (system) | Auto-substituted |
customer_name | Yes (passed via call) | Auto-substituted |
customer_address | No | LLM will collect from caller |
Best Practices
Write Detailed Descriptions
Include synonyms and variations: “Use when customer asks about order status, shipping, delivery, or tracking”
Always Add Pre-call Message
Set a friendly message like “Let me check that for you” so callers know to wait
Use Required Fields Wisely
Only mark parameters as required if the function truly cannot work without them
Test APIs First
Verify your API works with tools like curl or Postman before adding to Bolna
Leverage Auto-Injection
Put known data in the agent prompt to avoid asking callers for information you already have
Match Names Exactly
Parameter names in
properties and param must be identical (case-sensitive)Troubleshooting
Function not being triggered
Function not being triggered
Cause: Description doesn’t match what the caller is saying.Fix: Make your description more comprehensive. Include synonyms and example phrases.
API returns error
API returns error
Cause: Incorrect URL, authentication, or headers.Fix: Test your API with curl or Postman first. Verify
api_token format and required headers.Parameters not being passed correctly
Parameters not being passed correctly
Cause: Typo or format specifier mismatch.Fix: Ensure parameter names match exactly between
properties and param. Use %(name)s format.Variables not being substituted
Variables not being substituted
Cause: Variable not defined in agent prompt.Fix: Add the variable to your agent prompt using
{variable_name} syntax.
