Build A Function Call
Learn how to build a Function Call to use with your Agent.
This guide walks you through how to build a simple function call for a demo application. Please refer to this code repository for the complete application code.
Getting Started
We'll setup a module called functions.py
that defines a collection of functions and configurations which can be used in a Voice Agent API system for customer service automation. These functions will handle customer lookups, appointments, and order management through a set of async functions and standardized function definitions.
Please note: functions.py
will rely on the business_logic.py and the client.py files to work end to end.
Prerequisites
- Python 3.7+
- Familiarity with Python
- An understanding of how to use Python Virtual environments.
- Familiarity with the Deepgram Voice Agent API
Create the file
Create a file called functions.py
and at the top of the file:
Set Up the dependencies and Import the business logic
import json
from datetime import datetime, timedelta
import asyncio
from business_logic import (
get_customer,
get_customer_appointments,
get_customer_orders,
schedule_appointment,
get_available_appointment_slots,
prepare_agent_filler_message,
prepare_farewell_message
)
This guide doesn't cover the development of the business logic for this application. Please see this code for more details on the business logic used.
Implement the Functions
We'll start with the customer lookup function:
This function handles:
- Multiple lookup methods (phone, email, ID)
- Standardized ID formatting (CUSTXXXX)
- Phone number normalization (+1XXXXXXXXXX)
- Email address parsing
async def find_customer(params):
"""Look up a customer by phone, email, or ID."""
phone = params.get("phone")
email = params.get("email")
customer_id = params.get("customer_id")
result = await get_customer(phone=phone, email=email, customer_id=customer_id)
return result
Next we'll create a function to find customer appointments for a specific customer:
This function handles:
- retrieving all appointments for a specific customer using their customer ID.
async def get_appointments(params):
"""Get appointments for a customer."""
customer_id = params.get("customer_id")
if not customer_id:
return {"error": "customer_id is required"}
result = await get_customer_appointments(customer_id)
return result
Next we'll create a function to do appointment management:
This function handles:
- Scheduling new appointments
- Checking availability
- Retrieving existing appointments
async def get_orders(params):
"""Get orders for a customer."""
customer_id = params.get("customer_id")
if not customer_id:
return {"error": "customer_id is required"}
result = await get_customer_orders(customer_id)
return result
Next we'll create a function to do order management:
This function handles:
- Order history lookup
- Order status checking
async def create_appointment(params):
"""Schedule a new appointment."""
customer_id = params.get("customer_id")
date = params.get("date")
service = params.get("service")
if not all([customer_id, date, service]):
return {"error": "customer_id, date, and service are required"}
result = await schedule_appointment(customer_id, date, service)
return result
Next will create a function to find available appointment times:
This function handles:
- Finding available appointment slots
- Pre-scheduling availability checks
- Responding to "When can I come in?" queries
async def check_availability(params):
"""Check available appointment slots."""
start_date = params.get("start_date")
end_date = params.get("end_date", (datetime.fromisoformat(start_date) + timedelta(days=7)).isoformat())
if not start_date:
return {"error": "start_date is required"}
result = await get_available_appointment_slots(start_date, end_date)
return result
Next will setup a function to handle conversational flow:
This function handles:
- Agent filler messages for natural interaction
- Proper conversation closure handling
async def agent_filler(websocket, params):
"""
Handle agent filler messages while maintaining proper function call protocol.
"""
result = await prepare_agent_filler_message(websocket, **params)
return result
Finally we'll create a function to end the call gracefully.
This function handles:
- Conversation closure
- Adding appropriate farewell messages
async def end_call(websocket, params):
"""
End the conversation and close the connection.
"""
farewell_type = params.get("farewell_type", "general")
result = await prepare_farewell_message(websocket, farewell_type)
return result
Create Function Definitions
Next well need to setup FUNCTION_DEFINITIONS
Which is an array that defines the API contract for the Voice Agent system. It specifies all available operations, their parameters, and usage guidelines.
Each function definition follows a JSON Schema format with:
- Name
- Description
- Parameters specification
- Required fields
- Enumerated values where applicable
# Function definitions that will be sent to the Voice Agent API
FUNCTION_DEFINITIONS = [
{
"name": "agent_filler",
"description": """Use this function to provide natural conversational filler before looking up information.
ALWAYS call this function first with message_type='lookup' when you're about to look up customer information.
After calling this function, you MUST immediately follow up with the appropriate lookup function (e.g., find_customer).""",
"parameters": {
"type": "object",
"properties": {
"message_type": {
"type": "string",
"description": "Type of filler message to use. Use 'lookup' when about to search for information.",
"enum": ["lookup", "general"]
}
},
"required": ["message_type"]
}
},
{
"name": "find_customer",
"description": """Look up a customer's account information. Use context clues to determine what type of identifier the user is providing:
Customer ID formats:
- Numbers only (e.g., '169', '42') → Format as 'CUST0169', 'CUST0042'
- With prefix (e.g., 'CUST169', 'customer 42') → Format as 'CUST0169', 'CUST0042'
Phone number recognition:
- Standard format: '555-123-4567' → Format as '+15551234567'
- With area code: '(555) 123-4567' → Format as '+15551234567'
- Spoken naturally: 'five five five, one two three, four five six seven' → Format as '+15551234567'
- International: '+1 555-123-4567' → Use as is
- Always add +1 country code if not provided
Email address recognition:
- Spoken naturally: 'my email is john dot smith at example dot com' → Format as '[email protected]'
- With domain: '[email protected]' → Use as is
- Spelled out: 'j o h n at example dot com' → Format as '[email protected]'""",
"parameters": {
"type": "object",
"properties": {
"customer_id": {
"type": "string",
"description": "Customer's ID. Format as CUSTXXXX where XXXX is the number padded to 4 digits with leading zeros. Example: if user says '42', pass 'CUST0042'"
},
"phone": {
"type": "string",
"description": """Phone number with country code. Format as +1XXXXXXXXXX:
- Add +1 if not provided
- Remove any spaces, dashes, or parentheses
- Convert spoken numbers to digits
Example: 'five five five one two three four five six seven' → '+15551234567'"""
},
"email": {
"type": "string",
"description": """Email address in standard format:
- Convert 'dot' to '.'
- Convert 'at' to '@'
- Remove spaces between spelled out letters
Example: 'j dot smith at example dot com' → '[email protected]'"""
}
}
}
},
{
"name": "get_appointments",
"description": """Retrieve all appointments for a customer. Use this function when:
- A customer asks about their upcoming appointments
- A customer wants to know their appointment schedule
- A customer asks 'When is my next appointment?'
Always verify you have the customer's account first using find_customer before checking appointments.""",
"parameters": {
"type": "object",
"properties": {
"customer_id": {
"type": "string",
"description": "Customer's ID in CUSTXXXX format. Must be obtained from find_customer first."
}
},
"required": ["customer_id"]
}
},
{
"name": "get_orders",
"description": """Retrieve order history for a customer. Use this function when:
- A customer asks about their orders
- A customer wants to check order status
- A customer asks questions like 'Where is my order?' or 'What did I order?'
Always verify you have the customer's account first using find_customer before checking orders.""",
"parameters": {
"type": "object",
"properties": {
"customer_id": {
"type": "string",
"description": "Customer's ID in CUSTXXXX format. Must be obtained from find_customer first."
}
},
"required": ["customer_id"]
}
},
{
"name": "create_appointment",
"description": """Schedule a new appointment for a customer. Use this function when:
- A customer wants to book a new appointment
- A customer asks to schedule a service
Before scheduling:
1. Verify customer account exists using find_customer
2. Check availability using check_availability
3. Confirm date/time and service type with customer before booking""",
"parameters": {
"type": "object",
"properties": {
"customer_id": {
"type": "string",
"description": "Customer's ID in CUSTXXXX format. Must be obtained from find_customer first."
},
"date": {
"type": "string",
"description": "Appointment date and time in ISO format (YYYY-MM-DDTHH:MM:SS). Must be a time slot confirmed as available."
},
"service": {
"type": "string",
"description": "Type of service requested. Must be one of the following: Consultation, Follow-up, Review, or Planning",
"enum": ["Consultation", "Follow-up", "Review", "Planning"]
}
},
"required": ["customer_id", "date", "service"]
}
},
{
"name": "check_availability",
"description": """Check available appointment slots within a date range. Use this function when:
- A customer wants to know available appointment times
- Before scheduling a new appointment
- A customer asks 'When can I come in?' or 'What times are available?'
After checking availability, present options to the customer in a natural way, like:
'I have openings on [date] at [time] or [date] at [time]. Which works better for you?'""",
"parameters": {
"type": "object",
"properties": {
"start_date": {
"type": "string",
"description": "Start date in ISO format (YYYY-MM-DDTHH:MM:SS). Usually today's date for immediate availability checks."
},
"end_date": {
"type": "string",
"description": "End date in ISO format. Optional - defaults to 7 days after start_date. Use for specific date range requests."
}
},
"required": ["start_date"]
}
},
{
"name": "end_call",
"description": """End the conversation and close the connection. Call this function when:
- User says goodbye, thank you, etc.
- User indicates they're done ("that's all I need", "I'm all set", etc.)
- User wants to end the conversation
Examples of triggers:
- "Thank you, bye!"
- "That's all I needed, thanks"
- "Have a good day"
- "Goodbye"
- "I'm done"
Do not call this function if the user is just saying thanks but continuing the conversation.""",
"parameters": {
"type": "object",
"properties": {
"farewell_type": {
"type": "string",
"description": "Type of farewell to use in response",
"enum": ["thanks", "general", "help"]
}
},
"required": ["farewell_type"]
}
}
]
Create a Function Map
Finally we'll need to create aFUNCTION_MAP
which is a dictionary that maps function names to their corresponding implementation functions. It serves as a routing mechanism to connect the function definitions with their actual implementations.
# Map function names to their implementations
FUNCTION_MAP = {
"find_customer": find_customer,
"get_appointments": get_appointments,
"get_orders": get_orders,
"create_appointment": create_appointment,
"check_availability": check_availability,
"agent_filler": agent_filler,
"end_call": end_call
}
Call the functions from client.py
client.py
This guide doesn't cover the development of the client application but you can refer to the client code for how you can connect your Voice Agent to
functions.py
as well as the documentation Configuring the Voice Agent.
# Example of the Voice Agent Settings Configuration used the Demo app
SETTINGS = {
"type": "SettingsConfiguration",
"audio": {
"input": {
"encoding": "linear16",
"sample_rate": USER_AUDIO_SAMPLE_RATE,
},
"output": {
"encoding": "linear16",
"sample_rate": AGENT_AUDIO_SAMPLE_RATE,
"container": "none",
},
},
"agent": {
"listen": {"model": "nova-2"},
"think": {
"provider": {"type": "open_ai"},
"model": "gpt-4o-mini",
"instructions": PROMPT_TEMPLATE,
"functions": FUNCTION_DEFINITIONS,
},
"speak": {"model": VOICE},
},
"context": {
"messages": [
{"role": "assistant", "content": "Hello! I'm Sarah from TechStyle customer service. How can I help you today?"}
],
"replay": True
}
}
What's Next?
- For more ideas and function code samples for using Function Calling with your Agent check out this repository.
Updated about 12 hours ago