Building a Voice AI Agent That Books Appointments
Step-by-step guide to creating an AI agent that handles inbound calls, looks up patient records, checks availability, and schedules appointments — autonomously.
Building a Voice AI Agent That Books Appointments
A medical office gets dozens of scheduling calls a day. Most follow the same pattern: identify the patient, check the doctor's availability, pick a slot, confirm. That's a perfect fit for a voice AI agent — one that picks up the phone 24/7, never puts anyone on hold, and books the appointment before the caller hangs up.
This guide walks through building that agent with the Trunx API. By the end, you'll have a phone number that answers calls, looks up patient records, checks availability, books appointments, and sends an SMS confirmation — all without a human in the loop.
What You'll Need
- A Trunx account with an API key
- A phone number (DID) provisioned in your account
- Your backend endpoints for CRM lookup, availability, and booking (or mock them for testing)
Step 1: Define the Tools
Tools are HTTP endpoints your agent can call mid-conversation. When the AI decides it needs to look up a patient or check a schedule, it makes a real HTTP request to your backend.
You'll need four tools:
# Look up a patient by name or date of birth
curl -X POST https://your-trunx-url/v1/tools \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "lookup_patient",
"description": "Look up a patient record by name and date of birth",
"url": "https://your-backend.com/api/patients/lookup",
"method": "POST",
"headers": { "Authorization": "Bearer YOUR_CRM_TOKEN" },
"parameters": {
"type": "object",
"properties": {
"name": { "type": "string", "description": "Patient full name" },
"dob": { "type": "string", "description": "Date of birth (YYYY-MM-DD)" }
},
"required": ["name"]
}
}'Create the remaining three tools the same way — check_availability, book_appointment, and send_confirmation:
# Check doctor availability
curl -X POST https://your-trunx-url/v1/tools \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "check_availability",
"description": "Check available appointment slots for a given doctor and date range",
"url": "https://your-backend.com/api/availability",
"method": "POST",
"headers": { "Authorization": "Bearer YOUR_CRM_TOKEN" },
"parameters": {
"type": "object",
"properties": {
"doctor_id": { "type": "string" },
"date": { "type": "string", "description": "Date to check (YYYY-MM-DD)" }
},
"required": ["doctor_id", "date"]
}
}'
# Book the appointment
curl -X POST https://your-trunx-url/v1/tools \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "book_appointment",
"description": "Book an appointment for a patient at a specific slot",
"url": "https://your-backend.com/api/appointments",
"method": "POST",
"headers": { "Authorization": "Bearer YOUR_CRM_TOKEN" },
"parameters": {
"type": "object",
"properties": {
"patient_id": { "type": "string" },
"slot_id": { "type": "string" },
"reason": { "type": "string", "description": "Reason for visit" }
},
"required": ["patient_id", "slot_id"]
}
}'
# Send SMS confirmation
curl -X POST https://your-trunx-url/v1/tools \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "send_confirmation",
"description": "Send an SMS confirmation to the patient with appointment details",
"url": "https://your-trunx-url/v1/sms/send",
"method": "POST",
"headers": { "Authorization": "Bearer YOUR_API_KEY" },
"parameters": {
"type": "object",
"properties": {
"to": { "type": "string", "description": "Patient phone number in E.164 format" },
"body": { "type": "string", "description": "Confirmation message" }
},
"required": ["to", "body"]
}
}'Save the tool IDs from each response. You'll pass them when creating the agent.
Step 2: Create the Agent
Now create the agent with a system prompt that defines its behavior and the tools it can use:
curl -X POST https://your-trunx-url/v1/agents \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "scheduling-agent",
"systemPrompt": "You are a scheduling assistant for Lakewood Family Medicine. Your job is to help callers book, reschedule, or cancel appointments. Always greet the caller warmly. Ask for their name and date of birth to look them up. Once identified, ask what they need — new appointment, reschedule, or cancellation. For new appointments, ask for the preferred doctor and date, check availability, present options, and book once confirmed. After booking, send an SMS confirmation to the patient phone number on file. Be concise and professional. If you cannot find the patient, offer to transfer to the front desk.",
"voice": "terrence",
"toolIds": ["TOOL_ID_1", "TOOL_ID_2", "TOOL_ID_3", "TOOL_ID_4"]
}'The voice field selects the TTS voice for the agent. The toolIds array links the tools you just created. Under the hood, Trunx provisions an Ultravox agent with a SIP-connected voice pipeline.
Step 3: Assign a Phone Number
Point a DID at your new agent so inbound calls route to it:
curl -X PATCH https://your-trunx-url/v1/dids/DID_ID \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agentId": "AGENT_ID"
}'That's it. Calls to that number now hit your voice AI agent.
How It Works at Runtime
Here's the flow when a patient calls:
- Inbound call arrives — Trunx receives the call on the assigned DID
- Route to agent — Trunx looks up the DID configuration and initiates an Ultravox session with your agent's system prompt and tools
- Conversation begins — The agent greets the caller and asks for identifying information
- Tool calls fire — When the agent needs data, it makes real HTTP requests to your tool endpoints mid-conversation. The caller hears natural filler ("Let me check on that...") while the request completes
- Appointment booked — The agent confirms the details verbally and triggers the SMS confirmation tool
- Call completes — Trunx publishes a
call.completedevent with the full transcript, duration, and tool call log
You can subscribe to these events via webhooks or SSE to feed data into your analytics pipeline.
Keep Your Number Healthy
A phone number that gets flagged as spam is useless. Trunx runs DID health monitoring in the background — tracking answer rates, call duration patterns, and external reputation scores. If a number's health score drops, you'll see it in the dashboard and can rotate it before it impacts pickup rates.
What's Next
You've got a working voice AI agent that books appointments autonomously. From here you can:
- Add more tools (insurance verification, prescription refill requests)
- Set up webhooks to sync appointment data back to your EHR
- Build an IVR front-end that routes callers to the right agent based on department
- Launch outbound reminder campaigns using the same DID
Check out the Agent Guide for advanced configuration and the Agents API Reference for the full endpoint spec.
Wrap-up
Telecom infrastructure shouldn't slow you down. Trunx fits into your workflow — whether you're building voice AI agents, managing outbound campaigns, or scaling SMS at 2am.
If that sounds like the kind of tooling you want to use — try Trunx or join us on Discord.