WrinkleHQ

Answering Layer

The AI Front Desk Engine

Claude answers your customers' texts, one conversation at a time, and knows who is writing before it picks its words. It hands off to a person, honors STOP, and never quotes a price your team did not approve.

6 years
  1. Year 1Website
  2. Year 2Map Listings
  3. Year 3Booking Tool
  4. Year 4Front Desk
  5. Year 5Payments
  6. Year 6Reports

Same six pieces.
Ten layers, already running.

The Short Version

  • Each conversation gets its own small worker, so two replies never cross.
  • A burst of texts gets one answer, not four.
  • The caller is looked up first, so a regular never gets a stranger's greeting.
  • Alarms watch whether customers got an answer, not whether a job ran.
At a Glance
ModelClaude
StateOne durable object per conversation
BurstsBatched into one reply
Opt outSTOP words honored at once
PricesDrafted for a person to approve
AlarmOn customer outcome
What happens when a customer texts
  1. Customer TextSMSWeb chat
  2. GateSTOP checkHuman in thread
  3. Conversation ObjectBatch the burstLook up the caller
  4. ClaudeDraft replyDraft quote
  5. OutcomeReply sentHand-offAlarm check

What the Front Desk Does for You

A customer texts at 9pm. You are home. Your team is home. Without help, that text waits until morning, and so does the job.

Our front desk answers it. It reads the text, knows who sent it, and replies the way your best advisor would. It asks what it needs to ask. It books when it can. When a person should take over, it says so and hands the thread to your team.

It is not a chat bot that reads a script. It is Claude, a language model, working inside rules we wrote from running a real shop. Those rules are the part that took the longest. They are also the part that keeps it from embarrassing you.

One Durable Object per Conversation

People do not text in full paragraphs. They send three short texts in ten seconds. If each one gets its own answer, the customer gets three replies that talk over each other.

So every conversation gets its own durable object on Cloudflare. That is a tiny program with its own storage that handles one thread and only one. Texts for that thread line up in order. Each new text resets a short timer. When the customer stops typing for a few seconds, the whole burst goes to Claude as one message.

export class Conversation {
  constructor(state, env) {
    this.state = state;
    this.env = env;
  }

  async fetch(request) {
    const msg = await request.json();
    const queue = (await this.state.storage.get("queue")) || [];
    queue.push(msg);
    await this.state.storage.put("queue", queue);
    // A new alarm replaces the old one, so each text restarts the wait.
    await this.state.storage.setAlarm(Date.now() + 8000);
    return new Response("queued");
  }

  async alarm() {
    const queue = (await this.state.storage.get("queue")) || [];
    await this.state.storage.delete("queue");
    if (queue.length) await this.reply(queue);
  }

  async reply(messages) {
    // Look up the caller, check for a human, then ask Claude.
  }
}

Because one object owns one thread, two replies can never race. That class of bug is gone by design.

The Rules That Run Before Claude Speaks

The first message does the most damage, because it goes out before anyone can see it. So a set of plain checks runs first.

  • STOP means stop. STOP and the other standard opt out words end the thread at once. No reply, no follow up.
  • Is a person already here? If someone on your team typed in the thread, the bot stands down.
  • Who is this? The number is looked up before any words are chosen. A customer with a car in the shop hears about their car. A stranger gets the plain greeting.
const OPT_OUT = new Set(["STOP", "STOPALL", "UNSUBSCRIBE", "CANCEL", "END", "QUIT"]);

export function isOptOut(text) {
  return OPT_OUT.has(text.trim().toUpperCase());
}

The lookup is built to fail open. If the match is not exact, it falls back to the stranger reply. A slightly generic message is fine. Silence is not.

Hand-Off Without Walking Away

Handing a thread to a person cannot mean the customer is left alone. If nobody on the team replies, the thread goes quiet, and the lead goes cold.

So hand-off is a grace period. Your team gets a window to jump in. The moment a real person replies, the thread is theirs for good. If nobody does and the customer is still waiting, the front desk picks it back up. It still follows the limit on how many questions it may ask.

Never a Price Nobody Approved

A text thread that ends in a number is a promise. The bot never makes one on its own. It uses the same quote builder your staff use, drafts the estimate, and leaves it for an advisor to approve. The customer sees a total only after a person says yes. Showing it sooner is a small code change and a large business decision, so it stays the owner's call.

Knowing Who Sent Each Message

Once your team can type into the same thread, the bot has to tell its own texts from theirs. It does that by matching each outbound text against the words it recorded sending. No match means a person typed it.

This sounds simple and it is easy to get wrong. Text providers often add opt out wording to the first message. So the words that went out are not quite the words that were saved. We match on the start of the message in either direction. We also ignore very short texts, since a bot's "Got it" could match a person's reply by accident.

We also record both sides of the thread before the bot decides to stay quiet. If that order is flipped, a thread where your team did all the talking looks empty, and your reports say nobody answered.

What It Saves the Owner

You stop losing the after hours text. You stop paying someone to answer the same questions all day. Your team walks in to threads that are already sorted: booked, waiting on a quote, or needing a person. It is live today for Shop Desk shops, and it is the core of our answering service.

What We Learned the Hard Way

Alarm on what the customer got, not on whether the job ran. We once had a sender that ran on schedule and failed every time. A monitor that asked "did it run" stayed green the whole way. Ours asks one thing: is anyone waiting on an answer with nothing coming back?

Watch out for a false all clear. On a quiet night, a real outage can age its own waiting threads out of the window, and the list goes empty. So the all clear needs proof the bot spoke recently, not just an empty list.

Read the words, not just the logs. Generated replies drift longer and ask more questions than a real person. We read a day of them next to what your team typed, and tune the voice from there.

For the full build, see the AI front desk build. Next in the stack is search and indexing.

Questions People Ask

Will the AI tell my customer a price I did not approve?

No. It drafts the quote with your own quote builder and leaves it for a person to approve. The customer only sees a total after your team says yes.

What if my customer wants to talk to a real person?

The front desk hands the thread to your team right away. If nobody replies and the customer is still waiting, it picks back up so they are not left hanging.

Does it know my regular customers?

Yes. It looks up the number before it writes anything. A customer with a car in the shop gets an update on that car, not a stranger's greeting.

What happens if someone texts STOP?

The thread ends at once. No reply and no follow up go out to that number.

Will it reply at night?

Yes. When someone texts you first, a reply is not marketing, so quiet hours do not apply. It answers at any hour.

We sell time

Get Years of Building Switched On in Hours

A thirty minute call. A written price. Nothing built until you say yes.

Get Your Time Back