During my internship at MorpheLabs, I worked on a real estate platform whose viewing bookings all went through a contact form. Someone interested would fill it out, and a staff member would follow up manually to confirm a time, check it against everyone else’s schedule, and get it onto the calendar.
That’s fine at a handful of bookings a week, but it breaks down once viewings overlap or staff can’t keep up. The bottleneck was never interest in the properties. It was everything between someone expressing interest and a viewing landing on a calendar without conflicting with another one.
My job was to remove that: let people book, reschedule, or cancel a viewing by talking to an AI voice agent, with the scheduling workflow behind it running automatically and correctly, no double-booking.
Why a form was the wrong interface for this
A form works when the person filling it out already knows exactly what they want. That’s often not true here. Someone browsing listings is usually still deciding, closer to “what’s available this weekend for the unit on the corner” than a fixed date they can type into a field. That’s a conversation, not a form submission, and a voice agent can hold it: take a loose request, ask for whatever’s missing, land on a concrete booking.
But the conversational front end is only half the problem. What happens after the agent hangs up matters more: the booking has to be checked against every other booking for that property, written down correctly, reflected on a calendar, and confirmed. Get any of that wrong and you’ve just replaced a slow manual process with a fast way to double-book someone.
What I built
The voice agent doesn’t touch booking data directly. It only handles the conversation: figuring out whether someone wants to schedule, reschedule, or cancel, and pulling out the property, date, and time from however they phrase it. It then hands off a structured request to an automation layer built in n8n, where the scheduling logic actually lives.
Turning a request into a confirmed booking
This workflow receives the agent’s request, validates it, and routes it by intent. For a new booking, it checks the date against existing bookings before writing anything. If the slot’s taken, it computes the nearest open slots and sends those back instead of just failing, so the agent can offer alternatives in the same conversation. If it’s free, it creates the booking, a matching calendar event, and a confirmation.
Rescheduling and cancellation follow the same shape: look up the booking, re-check availability if the time changed, update or remove the calendar event, confirm. Cancelling marks a booking as cancelled rather than deleting it, so there’s still a record of what happened.
Reminding people before they forget
This one runs every 15 minutes, checking for bookings coming up in roughly three hours that haven’t been reminded yet, and flags each one after sending so it never goes out twice. The voice agent doesn’t need to stay involved after the initial request; once a booking exists, this picks it up entirely on its own.
What this changed
Booking a viewing no longer depends on a staff member reading a form and manually checking a calendar. The conflict check that used to happen in someone’s head now happens before a slot is even offered back, so a confirmed booking is actually free. It also cut no-shows, since reminders now go out automatically instead of depending on someone remembering.
What I learned
The hard part was never getting the voice agent to sound natural, conversational AI is good at that out of the box. It was treating the agent as an input to a workflow rather than the workflow itself. Once the agent decides what someone wants, that decision has to survive a conflict check, a calendar sync, and a notification without silently going wrong. I spent most of my time on the boring parts: validation, availability checks, making sure every branch confirmed the same way it wrote.
That part doesn’t show up in a demo, but it’s what decides whether the automation is actually trustworthy enough to replace a human doing the job.