> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://developers.deepgram.com/docs/build-a-function-call/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developers.deepgram.com/_mcp/server. # Build A Function Call This guide walks you through building function calls for your Voice Agent. We start with a basic weather lookup example and then move to a more complex customer management system. ## Basic Example: Weather Lookup This example demonstrates a simple client-side function call. When a user asks about the weather, the agent extracts the location and requests that your client fetch the data. ### 1. Define the Function in Settings Include the function definition in your `Settings` message under the `agent.think` object. `get_weather` only reads data, so it is safe to dispatch as soon as the model asks for it. A function that changes something should set `defer_until_eot: true` instead, as [`end_call`](#end-call) does later in this guide. See [`defer_until_eot`](/docs/configure-voice-agent#agentthinkfunctionsdefer_until_eot). **`JSON`** ```json JSON { "type": "Settings", "agent": { "think": { "provider": { "type": "open_ai", "model": "gpt-4o-mini" }, "prompt": "You are a helpful AI assistant that can provide weather information.", "functions": [ { "name": "get_weather", "description": "Get the current weather for a specific location", "parameters": { "type": "object", "properties": { "location": { "type": "string", "description": "The city or location to get weather for" } }, "required": ["location"] } } ] } } } ``` ### 2. Implement the Function Logic Your client application must implement the logic to handle the `get_weather` request. **`JavaScript`** ```javascript JavaScript export const getWeather = async (location: string): Promise => { const apiKey = import.meta.env.VITE_OPENWEATHER_API_KEY; try { const response = await fetch( `https://api.openweathermap.org/data/2.5/weather?q=${location}&appid=${apiKey}` ); if (!response.ok) { throw new Error('Failed to fetch weather data'); } const data = await response.json(); return `The current weather in ${data.name} is ${data.weather[0].description} with a temperature of ${data.main.temp}°K.`; } catch (err) { console.error(err); return null; } }; ``` **`Python`** ```python Python import os import requests from typing import Optional def get_weather(location: str) -> Optional[str]: api_key = os.getenv("OPENWEATHER_API_KEY") try: response = requests.get( f"https://api.openweathermap.org/data/2.5/weather", params={"q": location, "appid": api_key} ) response.raise_for_status() data = response.json() return f"The current weather in {data['name']} is {data['weather'][0]['description']} with a temperature of {data['main']['temp']}°K." except Exception as err: print(f"Error: {err}") return None ``` **`C#`** ```CSharp C# using System; using System.Net.Http; using System.Text.Json; using System.Threading.Tasks; public class WeatherService { private readonly HttpClient _httpClient; public WeatherService(HttpClient httpClient) { _httpClient = httpClient; } public async Task GetWeather(string location) { var apiKey = Environment.GetEnvironmentVariable("OPENWEATHER_API_KEY"); try { var response = await _httpClient.GetAsync( $"https://api.openweathermap.org/data/2.5/weather?q={location}&appid={apiKey}" ); response.EnsureSuccessStatusCode(); var data = await JsonSerializer.DeserializeAsync( await response.Content.ReadAsStreamAsync() ); return $"The current weather in {data?.Name} is {data?.Weather[0].Description} with a temperature of {data?.Main.Temp}°K."; } catch (Exception ex) { Console.Error.WriteLine($"Error: {ex.Message}"); return null; } } } public class WeatherResponse { public string Name { get; set; } public Weather[] Weather { get; set; } public Main Main { get; set; } } public class Weather { public string Description { get; set; } } public class Main { public float Temp { get; set; } } ``` **`Go`** ```Go Go package main import ( "encoding/json" "fmt" "net/http" "os" ) type WeatherResponse struct { Name string `json:"name"` Weather []struct { Description string `json:"description"` } `json:"weather"` Main struct { Temp float64 `json:"temp"` } `json:"main"` } func getWeather(location string) (string, error) { apiKey := os.Getenv("OPENWEATHER_API_KEY") url := fmt.Sprintf("https://api.openweathermap.org/data/2.5/weather?q=%s&appid=%s", location, apiKey) resp, err := http.Get(url) if err != nil { return "", fmt.Errorf("failed to fetch weather data: %v", err) } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { return "", fmt.Errorf("failed to fetch weather data: status code %d", resp.StatusCode) } var data WeatherResponse if err := json.NewDecoder(resp.Body).Decode(&data); err != nil { return "", fmt.Errorf("failed to decode response: %v", err) } return fmt.Sprintf("The current weather in %s is %s with a temperature of %.2f°K.", data.Name, data.Weather[0].Description, data.Main.Temp), nil } ``` --- ## Advanced Example: Customer Management System This section walks you through building a more complex function call system for a demo Voice Agent application. For the complete code, see the [code repository](https://github.com/deepgram-devs/flask-agent-function-calling-demo). ### Getting Started You'll create two files: * **`agent_functions.py`**: Contains async functions and configuration for customer lookups, appointments, and order management. * **`agent_templates.py`**: Defines the agent prompt, settings, and the `AgentTemplates` factory class for industry-specific configuration. ### Prerequisites * Python 3.7+ * Familiarity with Python * An understanding of how to use Python Virtual environments. * Familiarity with the [Deepgram Voice Agent API](/reference/voice-agent/voice-agent) ## Create `agent_functions.py` > **Info** > > This guide doesn't cover the development of the **business logic** for this application. Please see [business\_logic.py](https://github.com/deepgram-devs/flask-agent-function-calling-demo/blob/main/common/business_logic.py) for more details. First, create a file called: `agent_functions.py`. Then in `agent_functions.py` set up the dependencies and import the business logic. **`Python`** ```python Python 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 ) ``` **`Java`** ```java Java import com.deepgram.DeepgramClient; import com.deepgram.resources.agent.v1.types.*; import com.deepgram.resources.agent.v1.websocket.V1WebSocketClient; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; // Business logic imports (your application-specific classes) import com.example.BusinessLogic; ``` ### Implement the Functions We'll implement the following functions in `agent_functions.py` to handle customer and appointment management: | Function Name | Purpose | | -------------------- | ---------------------------------------------------------- | | `find_customer` | Lookup by phone, email, or ID; normalizes input | | `get_appointments` | Retrieve all appointments for a customer | | `get_orders` | Retrieve order history for a customer | | `create_appointment` | Schedule a new appointment | | `check_availability` | Find available appointment slots | | `agent_filler` | Provide conversational filler (requires websocket param) | | `end_call` | End the conversation gracefully (requires websocket param) | ### Find Customer **`Python`** ```python Python 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 ``` **`Java`** ```java Java public Map findCustomer(Map params) { String phone = (String) params.get("phone"); String email = (String) params.get("email"); String customerId = (String) params.get("customer_id"); return BusinessLogic.getCustomer(phone, email, customerId); } ``` ### Get Appointments **`Python`** ```python Python 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 ``` **`Java`** ```java Java public Map getAppointments(Map params) { String customerId = (String) params.get("customer_id"); if (customerId == null) { return Map.of("error", "customer_id is required"); } return BusinessLogic.getCustomerAppointments(customerId); } ``` ### Get Orders **`Python`** ```python Python 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 ``` **`Java`** ```java Java public Map getOrders(Map params) { String customerId = (String) params.get("customer_id"); if (customerId == null) { return Map.of("error", "customer_id is required"); } return BusinessLogic.getCustomerOrders(customerId); } ``` ### Create Appointment **`Python`** ```python Python 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 ``` **`Java`** ```java Java public Map createAppointment(Map params) { String customerId = (String) params.get("customer_id"); String date = (String) params.get("date"); String service = (String) params.get("service"); if (customerId == null || date == null || service == null) { return Map.of("error", "customer_id, date, and service are required"); } return BusinessLogic.scheduleAppointment(customerId, date, service); } ``` ### Check Availability **`Python`** ```python Python 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 ``` **`Java`** ```java Java public Map checkAvailability(Map params) { String startDate = (String) params.get("start_date"); String endDate = (String) params.get("end_date"); if (startDate == null) { return Map.of("error", "start_date is required"); } if (endDate == null) { endDate = LocalDateTime.parse(startDate) .plusDays(7).format(DateTimeFormatter.ISO_LOCAL_DATE_TIME); } return BusinessLogic.getAvailableAppointmentSlots(startDate, endDate); } ``` ### Agent Filler **`Python`** ```python Python 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 ``` **`Java`** ```java Java public Map agentFiller( V1WebSocketClient wsClient, Map params) { return BusinessLogic.prepareAgentFillerMessage(wsClient, params); } ``` ### End Call Ending a call cannot be undone, so this function sets `defer_until_eot: true` in its definition below. The agent holds the call until the user's turn is confirmed, and discards it if the user keeps speaking. See [`defer_until_eot`](/docs/configure-voice-agent#agentthinkfunctionsdefer_until_eot). **`Python`** ```python Python 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 ``` **`Java`** ```java Java public Map endCall( V1WebSocketClient wsClient, Map params) { String farewellType = (String) params.getOrDefault("farewell_type", "general"); return BusinessLogic.prepareFarewellMessage(wsClient, farewellType); } ``` ### Create Function Definitions Next in `agent_functions.py` we'll 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 **`Python`** ```python Python # 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"] }, # Hanging up cannot be undone, so wait for a confirmed end of turn. "defer_until_eot": True } ] ``` **`Java`** ```java Java // Function definitions sent to the Voice Agent API. // In the Java SDK, define these as AgentV1Function objects. List functionDefinitions = List.of( AgentV1Function.builder() .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.") .parameters(Map.of( "type", "object", "properties", Map.of( "message_type", Map.of( "type", "string", "description", "Type of filler message to use.", "enum", List.of("lookup", "general") ) ), "required", List.of("message_type") )) .build(), AgentV1Function.builder() .name("find_customer") .description("Look up a customer's account information by phone, email, or ID.") .parameters(Map.of( "type", "object", "properties", Map.of( "customer_id", Map.of( "type", "string", "description", "Customer's ID in CUSTXXXX format." ), "phone", Map.of( "type", "string", "description", "Phone number with country code (+1XXXXXXXXXX)." ), "email", Map.of( "type", "string", "description", "Email address in standard format." ) ) )) .build(), AgentV1Function.builder() .name("get_appointments") .description("Retrieve all appointments for a customer.") .parameters(Map.of( "type", "object", "properties", Map.of( "customer_id", Map.of( "type", "string", "description", "Customer's ID in CUSTXXXX format." ) ), "required", List.of("customer_id") )) .build(), AgentV1Function.builder() .name("get_orders") .description("Retrieve order history for a customer.") .parameters(Map.of( "type", "object", "properties", Map.of( "customer_id", Map.of( "type", "string", "description", "Customer's ID in CUSTXXXX format." ) ), "required", List.of("customer_id") )) .build(), AgentV1Function.builder() .name("create_appointment") .description("Schedule a new appointment for a customer.") .parameters(Map.of( "type", "object", "properties", Map.of( "customer_id", Map.of("type", "string", "description", "Customer's ID in CUSTXXXX format."), "date", Map.of("type", "string", "description", "Appointment date/time in ISO format."), "service", Map.of("type", "string", "description", "Service type.", "enum", List.of("Consultation", "Follow-up", "Review", "Planning")) ), "required", List.of("customer_id", "date", "service") )) .build(), AgentV1Function.builder() .name("check_availability") .description("Check available appointment slots within a date range.") .parameters(Map.of( "type", "object", "properties", Map.of( "start_date", Map.of("type", "string", "description", "Start date in ISO format."), "end_date", Map.of("type", "string", "description", "End date in ISO format. Defaults to 7 days after start.") ), "required", List.of("start_date") )) .build(), AgentV1Function.builder() .name("end_call") .description("End the conversation and close the connection.") .parameters(Map.of( "type", "object", "properties", Map.of( "farewell_type", Map.of( "type", "string", "description", "Type of farewell to use.", "enum", List.of("thanks", "general", "help") ) ), "required", List.of("farewell_type") )) .build() ); ``` ### Create a Function Map Finally in `agent_functions.py` we'll need to create a `FUNCTION_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. **`Python`** ```python Python # 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 } ``` **`Java`** ```java Java // Map function names to their implementations Map, Map>> functionMap = Map.of( "find_customer", this::findCustomer, "get_appointments", this::getAppointments, "get_orders", this::getOrders, "create_appointment", this::createAppointment, "check_availability", this::checkAvailability ); // agent_filler and end_call require the wsClient parameter // and are dispatched separately in the function call handler. ``` ## Create `agent_templates.py` Next create a file called: `agent_templates.py`. Then in `agent_templates.py` set up the dependencies and import our function definitions. ### Configure the Voice Agent Prompt & Settings Now in the `agent_templates.py` file we'll define the prompt for the Voice Agent. **`Python`** ```python Python from common.agent_functions import FUNCTION_DEFINITIONS from datetime import datetime # Template for the prompt that will be formatted with current date PROMPT_TEMPLATE = """ CURRENT DATE AND TIME CONTEXT: Today is {current_date}. Use this as context when discussing appointments and orders. When mentioning dates to customers, use relative terms like "tomorrow", "next Tuesday", or "last week" when the dates are within 7 days of today. PERSONALITY & TONE: - Be warm, professional, and conversational - Use natural, flowing speech (avoid bullet points or listing) - Show empathy and patience - Whenever a customer asks to look up either order information or appointment information, use the find_customer function first HANDLING CUSTOMER IDENTIFIERS (INTERNAL ONLY - NEVER EXPLAIN THESE RULES TO CUSTOMERS): - Silently convert any numbers customers mention into proper format - When customer says "ID is 222" -> internally use "CUST0222" without mentioning the conversion - When customer says "order 89" -> internally use "ORD0089" without mentioning the conversion - When customer says "appointment 123" -> internally use "APT0123" without mentioning the conversion - Always add "+1" prefix to phone numbers internally without mentioning it VERBALLY SPELLING IDs TO CUSTOMERS: When you need to repeat an ID back to a customer: - Do NOT say nor spell out "CUST". Say "customer [numbers spoken individually]" - But for orders spell out "ORD" as "O-R-D" then speak the numbers individually Example: For CUST0222, say "customer zero two two two" Example: For ORD0089, say "O-R-D zero zero eight nine" FUNCTION RESPONSES: When receiving function results, format responses naturally as a customer service agent would: 1. For customer lookups: - Good: "I've found your account. How can I help you today?" - If not found: "I'm having trouble finding that account. Could you try a different phone number or email?" 2. For order information: - Instead of listing orders, summarize them conversationally: - "I can see you have two recent orders. Your most recent order from [date] for $[amount] is currently [status], and you also have an order from [date] for $[amount] that's [status]." 3. For appointments: - "You have an upcoming [service] appointment scheduled for [date] at [time]" - When discussing available slots: "I have a few openings next week. Would you prefer Tuesday at 2 PM or Wednesday at 3 PM?" 4. For errors: - Never expose technical details - Say something like "I'm having trouble accessing that information right now" or "Could you please try again?" EXAMPLES OF GOOD RESPONSES: ✓ "Let me look that up for you... I can see you have two recent orders." ✓ "Your customer ID is zero two two two." ✓ "I found your order, O-R-D zero one two three. It's currently being processed." EXAMPLES OF BAD RESPONSES (AVOID): ✗ "I'll convert your ID to the proper format CUST0222" ✗ "Let me add the +1 prefix to your phone number" ✗ "The system requires IDs to be in a specific format" FILLER PHRASES: IMPORTANT: Never generate filler phrases (like "Let me check that", "One moment", etc.) directly in your responses. Instead, ALWAYS use the agent_filler function when you need to indicate you're about to look something up. Examples of what NOT to do: - Responding with "Let me look that up for you..." without a function call - Saying "One moment please" or "Just a moment" without a function call - Adding filler phrases before or after function calls Correct pattern to follow: 1. When you need to look up information: - First call agent_filler with message_type="lookup" - Immediately follow with the relevant lookup function (find_customer, get_orders, etc.) 2. Only speak again after you have the actual information to share Remember: ANY phrase indicating you're about to look something up MUST be done through the agent_filler function, never through direct response text. """ ``` **`Java`** ```java Java // The prompt template is the same string across all languages. // In Java, define it as a constant and inject the current date: String promptTemplate = """ CURRENT DATE AND TIME CONTEXT: Today is %s. Use this as context when discussing appointments and orders. PERSONALITY & TONE: - Be warm, professional, and conversational - Use natural, flowing speech - Show empathy and patience - Use find_customer before looking up orders or appointments FILLER PHRASES: IMPORTANT: Always use the agent_filler function when indicating you're about to look something up. Never generate filler phrases directly. """; String prompt = String.format(promptTemplate, LocalDate.now().format(DateTimeFormatter.ofPattern("EEEE, MMMM dd, yyyy"))); ``` Next in the same file we'll define the settings for the Voice Agent. **`Python`** ```python Python VOICE = "aura-2-thalia-en" # this gets updated by the agent template FIRST_MESSAGE = "" # audio settings USER_AUDIO_SAMPLE_RATE = 48000 USER_AUDIO_SECS_PER_CHUNK = 0.05 USER_AUDIO_SAMPLES_PER_CHUNK = round(USER_AUDIO_SAMPLE_RATE * USER_AUDIO_SECS_PER_CHUNK) AGENT_AUDIO_SAMPLE_RATE = 16000 AGENT_AUDIO_BYTES_PER_SEC = 2 * AGENT_AUDIO_SAMPLE_RATE VOICE_AGENT_URL = "wss://agent.deepgram.com/v1/agent/converse" # For EU data processing, use: "wss://api.eu.deepgram.com/v1/agent/converse" # For AU data processing, use: "wss://api.au.deepgram.com/v1/agent/converse" # For India data processing, use: "wss://api.in.deepgram.com/v1/agent/converse" AUDIO_SETTINGS = { "input": { "encoding": "linear16", "sample_rate": USER_AUDIO_SAMPLE_RATE, }, "output": { "encoding": "linear16", "sample_rate": AGENT_AUDIO_SAMPLE_RATE, "container": "none", }, } LISTEN_SETTINGS = { "provider": { "type": "deepgram", "model": "nova-3", } } THINK_SETTINGS = { "provider": { "type": "open_ai", "model": "gpt-4o-mini", "temperature": 0.7, }, "prompt": PROMPT_TEMPLATE, "functions": FUNCTION_DEFINITIONS, } SPEAK_SETTINGS = { "provider": { "type": "deepgram", "model": VOICE, } } AGENT_SETTINGS = { "language": "en", "listen": LISTEN_SETTINGS, "think": THINK_SETTINGS, "speak": SPEAK_SETTINGS, "greeting": FIRST_MESSAGE, } SETTINGS = {"type": "Settings", "audio": AUDIO_SETTINGS, "agent": AGENT_SETTINGS} ``` **`Java`** ```java Java // Build the agent settings using the Java SDK builder pattern AgentV1Settings settings = AgentV1Settings.builder() .audio(AgentV1SettingsAudio.builder() .input(AgentV1SettingsAudioInput.builder() .encoding("linear16") .sampleRate(48000) .build()) .output(AgentV1SettingsAudioOutput.builder() .encoding("linear16") .sampleRate(16000) .container("none") .build()) .build()) .agent(AgentV1SettingsAgent.builder() .listen(AgentV1SettingsAgentListen.builder() .provider(AgentV1SettingsAgentListenProvider.builder() .type("deepgram") .model("nova-3") .build()) .build()) .think(AgentV1SettingsAgentThink.builder() .provider(AgentV1SettingsAgentThinkProvider.builder() .type("open_ai") .model("gpt-4o-mini") .build()) .prompt(prompt) .functions(functionDefinitions) .build()) .speak(AgentV1SettingsAgentSpeak.builder() .provider(AgentV1SettingsAgentSpeakProvider.builder() .type("deepgram") .model("aura-2-thalia-en") .build()) .build()) .greeting(firstMessage) .build()) .build(); ``` Finally in the same file we'll define the factory class `AgentTemplates` which will be used to configure the Voice Agent. This class will be used to configure the Voice Agent for different industries. **`Python`** ```python Python class AgentTemplates: PROMPT_TEMPLATE = PROMPT_TEMPLATE def __init__( self, industry="tech_support", voiceModel="aura-2-thalia-en", voiceName="", ): self.voiceName = voiceName self.voiceModel = voiceModel self.personality = "" self.company = "" self.first_message = "" self.capabilities = "" self.industry = industry self.prompt = self.PROMPT_TEMPLATE.format( current_date=datetime.now().strftime("%A, %B %d, %Y") ) self.voice_agent_url = VOICE_AGENT_URL self.settings = SETTINGS self.user_audio_sample_rate = USER_AUDIO_SAMPLE_RATE self.user_audio_secs_per_chunk = USER_AUDIO_SECS_PER_CHUNK self.user_audio_samples_per_chunk = USER_AUDIO_SAMPLES_PER_CHUNK self.agent_audio_sample_rate = AGENT_AUDIO_SAMPLE_RATE self.agent_audio_bytes_per_sec = AGENT_AUDIO_BYTES_PER_SEC match self.industry: case "tech_support": self.tech_support() case "healthcare": self.healthcare() case "banking": self.banking() case "pharmaceuticals": self.pharmaceuticals() case "retail": self.retail() self.first_message = f"Hello! I'm {self.voiceName} from {self.company} customer service. {self.capabilities} How can I help you today?" self.settings["agent"]["speak"]["provider"]["model"] = self.voiceModel self.settings["agent"]["think"]["prompt"] = self.prompt self.settings["agent"]["greeting"] = self.first_message self.prompt = self.personality + "\n\n" + self.prompt def tech_support( self, company="TechStyle", agent_voice="aura-2-thalia-en", voiceName="" ): if voiceName == "": voiceName = self.get_voice_name_from_model(agent_voice) self.voiceName = voiceName self.company = company self.voiceModel = agent_voice self.personality = f"You are {self.voiceName}, a friendly and professional customer service representative for {self.company}, an online electronics and accessories retailer. Your role is to assist customers with orders, appointments, and general inquiries." self.capabilities = "I'd love to help you with your order or appointment." def healthcare( self, company="HealthFirst", agent_voice="aura-2-andromeda-en", voiceName="" ): if voiceName == "": voiceName = self.get_voice_name_from_model(agent_voice) self.voiceName = voiceName self.company = company self.voiceModel = agent_voice self.personality = f"You are {self.voiceName}, a compassionate and knowledgeable healthcare assistant for {self.company}, a leading healthcare provider. Your role is to assist patients with appointments, medical inquiries, and general health information." self.capabilities = "I can help you schedule appointments or answer questions about our services." def banking( self, company="SecureBank", agent_voice="aura-2-apollo-en", voiceName="" ): if voiceName == "": voiceName = self.get_voice_name_from_model(agent_voice) self.voiceName = voiceName self.company = company self.voiceModel = agent_voice self.personality = f"You are {self.voiceName}, a professional and trustworthy banking representative for {self.company}, a secure financial institution. Your role is to assist customers with account inquiries, transactions, and financial services." self.capabilities = ( "I can assist you with your account or any banking services you need." ) def pharmaceuticals( self, company="MedLine", agent_voice="aura-2-helena-en", voiceName="" ): if voiceName == "": voiceName = self.get_voice_name_from_model(agent_voice) self.voiceName = voiceName self.company = company self.voiceModel = agent_voice self.personality = f"You are {self.voiceName}, a professional and trustworthy pharmaceutical representative for {self.company}, a secure pharmaceutical company. Your role is to assist customers with account inquiries, transactions, and appointments. You MAY NOT provide medical advice." self.capabilities = "I can assist you with your account or appointments." def retail(self, company="StyleMart", agent_voice="aura-2-aries-en", voiceName=""): if voiceName == "": voiceName = self.get_voice_name_from_model(agent_voice) self.voiceName = voiceName self.company = company self.voiceModel = agent_voice self.personality = f"You are {self.voiceName}, a friendly and attentive retail associate for {self.company}, a trendy clothing and accessories store. Your role is to assist customers with product inquiries, orders, and style recommendations." self.capabilities = ( "I can help you find the perfect item or check on your order status." ) def travel(self, company="TravelTech", agent_voice="aura-2-arcas-en", voiceName=""): if voiceName == "": voiceName = self.get_voice_name_from_model(agent_voice) self.voiceName = voiceName self.company = company self.voiceModel = agent_voice self.personality = f"You are {self.voiceName}, a friendly and professional customer service representative for {self.company}, a tech-forward travel agency. Your role is to assist customers with travel bookings, appointments, and general inquiries." self.capabilities = ( "I'd love to help you with your travel bookings or appointments." ) @staticmethod def get_available_industries(): """Return a dictionary of available industries with display names""" return { "tech_support": "Tech Support", "healthcare": "Healthcare", "banking": "Banking", "pharmaceuticals": "Pharmaceuticals", "retail": "Retail", "travel": "Travel", } def get_voice_name_from_model(self, model): return model.split("-")[2].split("-")[0].capitalize() ``` **`Java`** ```java Java /** * Factory class that configures the Voice Agent for different industries. * Each industry method sets the personality, company, voice model, and capabilities. */ public class AgentTemplates { private String voiceName; private String voiceModel; private String company; private String personality; private String capabilities; private String firstMessage; private AgentV1Settings settings; public AgentTemplates(String industry, String voiceModel) { this.voiceModel = voiceModel; switch (industry) { case "tech_support" -> techSupport(); case "healthcare" -> healthcare(); case "banking" -> banking(); default -> techSupport(); } this.firstMessage = String.format( "Hello! I'm %s from %s customer service. %s How can I help you today?", voiceName, company, capabilities); // Build settings using the configured values this.settings = AgentV1Settings.builder() .agent(AgentV1SettingsAgent.builder() .speak(AgentV1SettingsAgentSpeak.builder() .provider(AgentV1SettingsAgentSpeakProvider.builder() .type("deepgram").model(this.voiceModel).build()) .build()) .think(AgentV1SettingsAgentThink.builder() .prompt(this.personality + "\n\n" + prompt) .functions(functionDefinitions) .build()) .greeting(this.firstMessage) .build()) .build(); } private void techSupport() { this.company = "TechStyle"; this.voiceModel = "aura-2-thalia-en"; this.voiceName = getVoiceNameFromModel(this.voiceModel); this.personality = String.format( "You are %s, a friendly customer service representative for %s.", voiceName, company); this.capabilities = "I'd love to help you with your order or appointment."; } private void healthcare() { this.company = "HealthFirst"; this.voiceModel = "aura-2-andromeda-en"; this.voiceName = getVoiceNameFromModel(this.voiceModel); this.personality = String.format( "You are %s, a compassionate healthcare assistant for %s.", voiceName, company); this.capabilities = "I can help you schedule appointments or answer questions."; } private void banking() { this.company = "SecureBank"; this.voiceModel = "aura-2-apollo-en"; this.voiceName = getVoiceNameFromModel(this.voiceModel); this.personality = String.format( "You are %s, a professional banking representative for %s.", voiceName, company); this.capabilities = "I can assist you with your account or banking services."; } private static String getVoiceNameFromModel(String model) { String[] parts = model.split("-"); String name = parts[2]; return name.substring(0, 1).toUpperCase() + name.substring(1); } public AgentV1Settings getSettings() { return settings; } } ``` ## Call the functions from `client.py` > **Info** > > This guide doesn't cover the development of the **client** for this application. Please see [client.py](https://github.com/deepgram-devs/flask-agent-function-calling-demo/blob/main/client.py#L66) for more details. In the `client.py` file we'll need reference `agent_templates.py` which will define the settings for the Voice Agent. **`Python`** ```python Python settings = self.agent_templates.settings ``` **`Java`** ```java Java DeepgramClient client = DeepgramClient.builder().build(); V1WebSocketClient wsClient = client.agent().v1().v1WebSocket(); wsClient.connect().get(10, TimeUnit.SECONDS); AgentTemplates templates = new AgentTemplates("tech_support", "aura-2-thalia-en"); wsClient.sendSettings(templates.getSettings()); // Handle function call requests from the agent wsClient.onFunctionCallRequest(request -> { String functionName = request.getName(); Map params = request.getInput(); Map result = functionMap.get(functionName).apply(params); wsClient.sendFunctionCallResponse( AgentV1SendFunctionCallResponse.builder() .id(request.getId()) .output(new ObjectMapper().writeValueAsString(result)) .build()); }); ``` > Learn how to build a Function Call to use with your Agent.