Skip to content
MR
Back to all workCase Study 01 / 03
Conversational AI PlatformTimeline · Aug 2026 — Present

— Voice & DM agents for salons and service businesses

AI Receptionist.

Answers every call. Books the real diary.

Role
Technical Operations Manager · AI Systems Engineer
Timeline
Aug 2026 — Present
Sectors
Salons & Beauty · Residential Heating & Energy Supply
Status
Live · 12–15 clients · Ireland & UK
01Overview

CallHandlers.io gives small businesses an AI receptionist that answers the phone, checks the real diary and books, moves or cancels appointments. I own production: the ElevenLabs agents, the n8n orchestration layer on Railway, the multi-tenant Supabase Postgres, five booking-system integrations, and the DM agent that brings the same receptionist to Facebook Messenger, WhatsApp and Instagram.

02Evidence

Claims are cheap. Here is what a stranger can check: a real recorded call, one client’s month in numbers, and a sample of the register every production fix is proven against.

— Recorded call0:50

A real booking call

0:000:50

A caller rings a Cork salon and asks for an appointment. The agent checks the live diary, offers the nearest slots by stylist and confirms the booking. This is the clip CallHandlers publishes on its own site; it is an edited segment of a real call.

Source: callhandlers.io

In numbers
315
calls handled
98
appointments booked directly
74
calls answered outside salon hours
80
callbacks captured for the team
€10,950
in bookings captured

One partnered salon, August 2026 — the figures CallHandlers publishes in its own product deck.

Findings register

Every production defect gets an ID, a layer, a status and a named proof — a transcript line, a tool response, a database row. The register runs to 129 entries and is what turns one client’s bug into a rule for every client. Four entries, anonymised:

  • Proven — names the artefact
  • Applied, not yet demonstrated on an organic call
  • Open
  • Disproved on evidence — kept, never deleted
  1. IT-111 → IT-122

    Workflow

    🟠 Fixed · 8/8 unit cases + live vendor read-back

    Landline and UK callers could never be booked on one booking system. After the first fix, UK callers looped forever, asked for a mobile number they had already given.

    — Root cause

    The phone normaliser prefixed every number with the Irish country code and tested for Irish mobiles only. The vendor accepted UK mobiles all along; our normaliser was the constraint. A fix that is right for the numbers you tested can be worse than the bug for the numbers you did not.

    — Proof

    Eight unit cases across Irish, UK and landline forms, then a live booking from a UK number read back from the vendor with the real number stored. Ghost booking cancelled, diary clean.

  2. IT-144

    Data · fleet standard

    🟠 Applied + ghost-proven · 6/6 probes · 25 rows swept

    Salons were told to ring the same customer twice: 37 duplicate callback clusters across 10 clients in 30 days.

    — Root cause

    A database trigger compared phone numbers as raw strings (0866… against +353866…) and demanded an exact service match, so the post-call safety net never collapsed onto the real callback beside it.

    — Proof

    The obvious fix was tested against all 37 clusters and 60 days of history first, and rejected: it would have hidden the informative row and eaten genuinely distinct requests. The shipped rule was probed six times against the live trigger, rolled back, then applied with a full rollback in the repo.

  3. IT-092

    Workflow + config · fleet standard

    🟠 Applied · live-call proof owed at the time

    Two capable therapists, one facial room: the engine sold the same room twice because availability was computed per stylist, not per resource.

    — Root cause

    Availability was rota ∩ stylist-free ∩ caller-free, with no term for the salon’s equipment. Any service bound to a scarce resource could be double-sold whenever two staff were free.

    — Proof

    The booking system already modelled rooms and machines. Three workflow nodes were patched to veto any slot with no free instance, verified against the live diary.

  4. IT-097

    Workflow + factory

    🟠 Fixed · ghost-proven

    Every reschedule on one cloned agent silently rewrote the appointment to 30 minutes.

    — Root cause

    The clone shipped with its donor’s service-duration map. None of the ids matched, so the duration fell back to the default and the update overwrote real durations.

    — Proof

    A 45-minute ghost booking moved from Thursday to Friday read back as 10:00–10:45; the pre-fix arithmetic gives 10:00–10:30. Factory lesson: anything keyed on catalogue ids must be regenerated per client.

Findings accumulate into cross-cutting patterns, and the patterns are what upgrade the skeleton every new client is built from. A few of them:

  • Every “keep trying” instruction needs a counter and a terminus.
  • The tool schema is part of the prompt, and they must agree.
  • Silence is a caller-facing failure, not a technical detail.
  • A path that cannot fail cannot be proof.
  • “The tool fired” is never “the tool worked”.
  • A guard added to one flow does not exist in the flows that share the question.
  • A finding whose layer you cannot open is a hypothesis, however confident the prose sounds.
  • Fixes do not propagate on their own; only the register will catch it.
03The Problem

— Context

Where the workflow broke down.

Salon owners miss calls while their hands are busy, and every missed call is a booking that goes to the next salon. Off-the-shelf bots can talk, but they cannot see the real diary: five different booking systems, most without a public API, each with its own rules about deposits, colour services, stylist rosters and opening hours. When I joined, the platform had live clients but no monitoring, a database on the wrong continent, agents whose accents drifted mid-call, and no written record of what had already gone wrong.

04Challenges & Solutions

Each pain point above mapped directly to a system response. Below, the field-observed challenge on the left and the shipped solution on the right.

  1. 01

    — Challenge

    Agents’ accents flipped mid-call, apparently at random, and the defect predated my hire.

    — Solution

    The ElevenLabs expressive mode shipped eleven audio tags enabled while the system prompt banned those exact tags by name — two contradictory instructions in the same turn. I documented the collision and presented it to the founder as a decision rather than a unilateral fix.

  2. 02

    — Challenge

    Callers heard 20–30 seconds of dead air while the agent thought.

    — Solution

    Traced it to the underlying model’s default reasoning latency, which could not be disabled on that family. Re-architected model selection and parameters with reasoning latency disabled, eliminating dead air and verifying the fix against historical conversations before rollout.

  3. 03

    — Challenge

    The production database sat in US-West while every caller and every service was in Europe.

    — Solution

    Migrated Postgres to the EU with zero downtime, a rollback card with exact revert values and a 20-minute abort deadline. Internal queries fell from 2.82 s to 0.20 s and end-to-end response from ~6 s to under 1 s across 88/88 runs.

  4. 04

    — Challenge

    Reschedules on one booking system cancelled first and rebooked second — if the rebook failed, the caller was left with no appointment at all.

    — Solution

    Rebuilt it as an in-place move, then built a ghost-probe replay harness that proves every fix against the live booking system before and after. Replaying real appointments through it caught a bug in my own fix before it shipped.

  5. 05

    — Challenge

    Business rules written into prompts, knowledge bases and client configs still failed in production.

    — Solution

    Argued for and helped design the three-layer model — rules in workflow code, facts in retrieval, per-client values in config — using a live counter-example: a colour-booking restriction written in all three places that only held once it was enforced in node code.

  6. 06

    — Challenge

    No monitoring: the team learned an agent was down when a client said so.

    — Solution

    Built the first observability stack from nothing — Better Stack, a status channel, deploy-freshness watchdogs — and an automated morning digest per client. The first live digest surfaced six previously unreported production defects.

05Key Features
  1. 01— Feature

    Per-client voice agents

    One ElevenLabs conversational agent per business, with a factory-compiled system prompt, a client knowledge base, a chosen voice and a fixed tool contract. The prompt carries tone and flow; the facts and rules live elsewhere, so a fix never has to be re-typed into twelve prompts.

  2. 02— Feature

    Shared orchestration chassis

    One self-hosted n8n workflow per booking system on Railway, serving every tenant on that system. The tenant is resolved at runtime from the agent id, every webhook is secret-authenticated, and opening hours, never-offer stylists and eligibility rules are enforced in node code — not in prose.

  3. 03— Feature

    Five booking-system integrations

    Phorest, Barespace, Floomly, Fresha and Salon IQ — several reverse-engineered from browser traffic into working adapters. Credentials and sessions that can silently expire get health checks, because a quiet failure is what actually loses a client’s trust.

  4. 04— Feature

    Omnichannel DM agent

    The same receptionist on Facebook Messenger, WhatsApp and Instagram, calling the same tools and obeying the same business rules as the phone line. The moment the owner starts typing in the thread, the AI stops — automatically. Built, live, and still being tuned from real conversations.

  5. 05— Feature

    Client & agency dashboards

    Calls, bookings and callbacks for each client, and an agency console for the founders: a fleet board, a live callback queue ordered oldest-waiting first, a phone-number asset pool and a credential registry that stores labels, never secrets.

  6. 06— Feature

    Observability & morning digests

    Better Stack uptime monitoring, a status channel, deploy-freshness watchdogs and volume alerts, plus an automated morning digest to every client channel with seven-day baselines. Before this, an outage was discovered when a client complained.

06Architecture & Tech Stack

— System map

Two front doors, one brain.

The voice line and the messaging channels are separate agents with separate constraints, but they share one orchestration layer, one set of booking rules and one database. That is what makes a fix land everywhere at once.

AI receptionist platform architecturePhone calls flow from the caller through Twilio to an ElevenLabs voice agent; messages flow from Messenger, WhatsApp and Instagram to a DM agent. Both reach one n8n orchestration layer on Railway, which talks to five booking systems and writes to Supabase Postgres. Dashboards and observability sit on the database.VoiceMessagingWhere behaviour livesOrchestration · Data · OpsCallerrings the salonSalon lineconditional forwardTwilioclient numberElevenLabs voice agentprompt · knowledge basevoice · asr · tool contractMessenger · WhatsApp · Instagramthe owner’s inboxesDM agentsame tools · same rulesstops when the owner typesn8n orchestrationself-hosted on Railwayone shared workflow perbooking systemtenant resolved by agent idsecret-authenticated webhooksbusiness rules in node codeBooking systemsPhorestBarespaceFloomlyFreshaSalon IQSupabase Postgrescalls · bookings · callbacksrow-level security · edge fnsDashboardsclient + agency consolescallback queue · fleet boardObservabilityBetter Stack · watchdogsstatus feed · morning digestsRulesworkflow code — prompts drift, node code doesn’tFactsretrieval — the client’s knowledge basePer-client valuesruntime config — hours, staff, services, policies
Every path — phone or DM — ends in the same orchestration layer, the same booking rules and the same database. Fix it once, and every client gets the fix.

— How it's built

A call reaches the salon’s own line, forwards to a Twilio number and lands on the client’s ElevenLabs agent. Every tool call goes to the n8n chassis on Railway — one shared workflow per booking system, tenant resolved by agent id, secret-authenticated webhooks — which talks to the booking-system adapter and writes the call record, booking or callback into Supabase Postgres. Messaging channels enter through the DM agent and reach the same tools. Behaviour lives in three layers: rules in workflow code, facts in retrieval, per-client values in runtime config. Edge functions front the operational database with row-level security; Better Stack and Slack carry the alerting.

07Outcomes
  1. 12×— Outcome

    Faster database

    Internal query time cut from 2.82 s to 0.20 s after the zero-downtime EU migration.

  2. <1s— Outcome

    Caller response

    End-to-end response down from ~6 s, verified across 88 of 88 test runs post-cutover.

  3. 129— Outcome

    Findings documented

    Production defects recorded with severity, root cause and proof — now the company’s primary institutional knowledge asset.

— End of case study

Want to see more work?