All Posts
Voice AI

Simplify AI Voice Agent Bookings with Cloudflare Workers

Jan 17, 20267 min read
Featured image for Simplify AI Voice Agent Bookings with Cloudflare Workers

Use a Cloudflare Worker as lightweight middleware between Retell and Cal.com to handle reschedules and cancellations without n8n.

Introduction

I was in a workshop recently where somebody asked if there was an alternative to using n8n when rescheduling or cancelling bookings. The general consensus was no - but it got me thinking about Cloudflare Workers. I'd used one before to solve a security issue so why not a booking problem? In the first part of this blog post, I'll explain how we can use them to cancel and reschedule bookings. In the second part, I'll show you how to create an advanced create_booking function that improves on Retell's integrated create booking function, reducing bloat in your voice agent (and potentially saving you money in Cal too).

The Problem: Retell's Cal.com Limitation

Retell gives you two Cal.com functions out of the box: check_availability and create_booking. That covers the basic flow. In reality, we need more - cancelling and rescheduling are essential to any decent booking system. These are not built into Retell's Cal.com functions.

Typically you might use an automation platform like n8n, Make, Zapier. They all work. But there's friction: another account to manage, they cost money and there's a learning curve.

Why you can't just use Retell custom functions

The core issue is the booking UID. When you create a booking on Cal.com, you get back a unique booking UID. To reschedule or cancel, you need that UID to pass it to the Cal.com API.

Retell's custom functions let you call URLs, but you can't inject dynamic data into them (which is where the booking UID is added to cancel and reschedule). In other words, you can't take the booking UID you get from the get_all_bookings API call to Cal and slip it into the cancel or reschedule API call. So you need to go through a middle man to handle that logic.

That's where a Cloudflare Worker comes in.

What Is a Cloudflare Worker?

A Cloudflare Worker is a small piece of code that runs on Cloudflare's servers. It sits between your Retell agent and Cal.com. When your agent needs to reschedule or cancel, it sends a request to the Worker. The Worker takes that request, talks to Cal.com, and sends the response back.

The flow looks like this:

  1. Caller needs to cancel a booking
  2. Agent takes caller details and uses the get_all_bookings function.
  3. Worker sends details to Cal.com and get's back bookingUid and passes it to the agent.
  4. Agent calls the Cloudflare Worker with the bookingUid in the cancel_booking function.
  5. Worker sends the cancel request to Cal.com
  6. Cal.com responds confirming cancelation with acancel id
  7. Worker sends the response back to the agent
  8. Agent confirms cancelation with caller

Voice Agent to Cloudflare Worker to Cal.com flow

It happens in milliseconds. It's lightweight. It's fast. Speed is key when you're working with voice agents so every time we can shave a few milliseconds off a tool call the better. That being said, if Cal.com is having a bad day, there's not much we can do about it.

Why a Cloudflare Worker might be a good alternative to n8n

One of the main reasons to use a Cloudflare Worker is because it's just code. The irony is that vibe coding with advanced models like Claude's Opus 4.5 makes it easier to write the code for a Cloudflaire Worker to manage advanced booking options than doing it in a visual no-code platform like n8n. You can manage it all from your terminal using Cloudflare's Wrangler CLI. On top of that it's free!

  • Customizable code ✅
  • Speed ✅
  • Pricing ✅
  • Convenience ✅
  • Security ✅
  • Version control ✅
  • Maintenance ✅

The Cancel Booking Function

The agent calls get_all_bookings first to get the customer's booking UID. Then it passes that UID to the cancel function. The Worker handles the rest.

code
Name: cancel_booking Description: Cancel an existing booking by its unique identifier. Use this after confirming with the customer which booking they want to cancel. The booking UID can be obtained from the get_all_bookings function. Endpoint: POST https://barber-of-seville.workers.dev/ Headers: X-Cal-Api-Key: {{CAL_API_KEY}} Body Parameters: { "type": "object", "properties": { "action": { "type": "string", "const": "cancel_booking", "description": "Fixed action identifier for routing" }, "cancellationReason": { "type": "string", "description": "Optional reason for the cancellation" }, "bookingUid": { "type": "string", "description": "The unique identifier of the booking to cancel" } }, "required": ["action", "bookingUid"] }

Once the Worker receives it, it injects the booking UID into the Cal.com cancel booking API call and Bob's your uncle. Job done.

Don't Forget the Prompt

The tools only work if the agent knows when to use them. Your prompt needs to explain the flow for cancelling and rescheduling and the necessity to call get_all_bookings first to get the booking UID. Tools often fail, not because they are not well designed, but because the agent doesn't know how or when to use them.

Advanced Example: The Barber of Seville

Here's where this approach shines. Imagine a hairdresser in Seville offering ten different services: men's haircuts, women's haircuts, kids' haircuts, hair straightening, hair coloring, and so on. Each service has a different duration.

The obvious approach is to create one Cal.com event type for each service. That means your Retell agent needs ten different booking functions—one for each event type.

This creates problems. The more functions (or "tools") your agent can call, the higher the risk it calls the wrong one or doesn't invoke it at all! Some LLMs handle tool calling better than others, but even the best models struggle when there are too many options. You also bloat your prompt with descriptions and examples for each function, which increases token count and cost.

10 functions vs 1 function comparison

The solution: one booking function. You add metadata to the Cal.com create booking API endpoint. In that metadata, you define a service type field. You list all the services the barber offers.

When your agent gathers the customer's choice (men's haircut, hair coloring, etc.), it stores that in its memory (or function). Then it sends that service type along with the booking request to the Cloudflare Worker in the body of the custom function:

code
{ "properties": { "serviceType": { "type": "string", "description": "The type of service requested", "enum": [ "mens_haircut", "womens_haircut", "kids_haircut", "hair_color", "highlights", "hair_extensions", "roots_touchup" ] }, "startTime": { ... }, "attendeeName": { ... }, "attendeePhone": { ... } }, "required": ["action", "serviceType", "startTime", "attendeeName", "attendeePhone"] }

Inside the Worker, you have a simple mapping function. It maps each service name to the corresponding Cal.com event type. When the API call goes to Cal.com, it uses the right event type ID and duration. The response comes back and the agent confirms the booking with the customer.

code
const SEVILLE_BARBER_SERVICES = { 'mens_haircut': { eventTypeId: 4128616, duration: 20, displayName: "Men's Haircut" }, 'womens_haircut': { eventTypeId: 4128694, duration: 30, displayName: "Women's Haircut" }, 'hair_color': { eventTypeId: 4129162, duration: 30, displayName: 'Hair Color' }, 'highlights': { eventTypeId: 4129207, duration: 90, displayName: 'Highlights' }, 'hair_extensions': { eventTypeId: 4129259, duration: 60, displayName: 'Hair Extensions' }, // ... more services };

Miguel and his Lean Mean Booking Machine

You've gone from ten functions to one. Your agent is now a lean, mean booking machine.

Why This Approach Works

Cloudflare Workers offer an alternative, surprisingly simple yet highly effective solution to appointment booking on Cal.com.

It's fast, secure and cheap. It's easy to vibe code and test. You can set up a Cloudflare Worker on a client's behalf in minutes without the hassle of setting up an automation platform such as n8n or Make.

When someone mentions needing a voice agent for booking, my first instinct now is to consider a Cloudflare Worker.

Share this post