AI Automation

Teaching a support bot the house rules

How explicit rules for tone, facts, and return eligibility keep a support bot on-brand, and why shared rules require broader regression testing.

Octacer July 13, 2026
A single upright rulebook-like panel standing above a row of six clean chat-bubble shapes in the dark, one small green marker on the panel, no embedded text.

Teaching a support bot the house rules

When a bot answers as a brand, its small mistakes read as the brand's mistakes. A perfume retailer runs a customer-support bot on WhatsApp, and most of its answers were fine. The wrong ones were quiet: an emoji that didn't match the brand's voice, a branch reply that implied a store had never existed, a return offered on an item the customer had clearly used. None of those are crashes. All of them are the brand saying something it wouldn't say.

We fixed them by writing house rules — small, explicit rules about tone, facts, and eligibility — and by putting one of those rules above the individual conversation flows. That last decision is the interesting one, and it carried a cost we'll be honest about.

TL;DR: A support bot that speaks as a brand needs house rules for tone and facts, plus a shared eligibility rule that outranks every flow. Because the shared rule touches all six flows, changing it forced a full regression across every one.

The problem

A bot that speaks as the brand can be subtly wrong in ways a test suite doesn't catch.

The bot passed its happy paths. Customers asked about returns, exchanges, and deliveries, and it answered. But three patterns kept producing answers that were technically responsive and still wrong for this brand.

Tone drift

First, tone. The bot mirrored whatever emoji the customer sent. If a customer used a playful emoji, the bot echoed it back. That made the brand's voice drift chat by chat, controlled by strangers instead of by the brand.

Fact slip

Second, facts. A customer asked about a specific branch. The bot's wording implied the brand had never had a branch there — when in fact a former branch had closed. Denying it ever existed is a different, worse claim than saying it closed.

Eligibility gap

Third, eligibility. Customers described items they had tried on, used, or simply didn't like, then asked to return or exchange them. The bot walked them into the return flow anyway. For this retailer, a used item is not returnable, so the bot was setting up a promise the brand would have to break.

Why the obvious fix didn't work

The obvious fix is to patch each flow. Add an emoji instruction to the return flow. Add a branch-fact note to the store-info flow. Add a "was it opened?" check to the exchange flow. Repeat for every path.

That approach fails for the eligibility rule specifically. "Did the customer use the item?" is not a return question or an exchange question — it's the same question in both, and in wrong/missing, damaged, and complaint conversations too. If the check lives inside each flow, you copy it six times, and the six copies drift. One flow learns that "I wore it once" means opened; another doesn't. The bot then contradicts itself depending on which door the customer walked through.

Tone and facts have the same shape at smaller scale. If every flow carries its own emoji instruction, one flow will miss the update and the voice cracks there. Rules that are meant to be true everywhere shouldn't be stored per-flow.

What we did

We wrote house rules and gave one of them priority over the flows.

Brand-owned emojis

Brand-only emojis. The bot now uses only the brand's own emojis instead of mirroring the customer. The customer's emoji no longer sets the tone; the brand's does. The voice stays constant no matter who's typing.

Precise facts

Accurate facts. The branch reply now states that a former branch has closed, rather than implying the brand never had one. It's a one-line wording change with a real difference in meaning — "we closed that location" versus "we were never there."

Shared eligibility

A shared eligibility rule that outranks flow steps. This is the load-bearing rule. Any phrasing that means the customer tried, used, or didn't like the item is treated as "opened." Opened items are ineligible for return or exchange. The rule is evaluated before the flow's own steps run, so a flow can't offer a return that the eligibility rule has already ruled out. The rule wins.

Human handoff

Human-handoff labeling. Chats that need a person are labeled in WhatsApp so the team can pick them up and handle them directly. We documented the labeling so handoff is a known step, not a guess.

Underneath all of it, the bot still has to emit valid JSON, stay gender-neutral, and avoid banned words on every turn. Those constraints don't move; the house rules sit on top of them.

How it works

The shared eligibility rule sits above the six business flows and runs first.

A message comes in and gets routed toward one of six flows: Return, Exchange, Wrong or Missing item, Damaged item, Delay, or Complaint. Before that flow executes its own steps, the shared eligibility rule reads the customer's language. If the customer signals the item was tried, used, or disliked, the rule marks it opened and blocks return or exchange — regardless of which flow the customer is in. Only if the rule doesn't fire does the flow run its normal steps.

The picture is one gate over six branches, not six gates:

                incoming message
                       |
        +--------------+--------------+
        |   SHARED ELIGIBILITY RULE   |   <- evaluated first
        |  tried / used / disliked?   |
        |     => opened => ineligible |
        +--------------+--------------+
                       | (passes)
   +--------+--------+--------+--------+--------+--------+
   | Return |Exchange| Wrong/ |Damaged | Delay  |Complaint|
   |        |        |Missing |        |        |         |
   +--------+--------+--------+--------+--------+--------+

The eligibility rule is the box every flow passes through. It's stored once, in the shared return/exchange logic, and each flow inherits it. That's the whole point: one rule, one place, every flow bound by it.

What broke / what surprised us

Putting the rule in shared logic is what makes it correct. It's also what made the change expensive.

Because the eligibility rule lives in shared return/exchange logic, it touches every flow. So a change to that one rule isn't a one-flow change — it's a change to all of them. We couldn't test Return, ship it, and call it done. Editing the shared rule meant re-testing everything that depends on the shared rule, which is everything.

So we ran a full regression in fresh chats: all six business flows — Return, Exchange, Wrong/Missing, Damaged, Delay, Complaint — plus every edge case: bot identity, discount, talk-to-human without a circular loop, off-topic, out-of-hours, other languages, and gibberish. Fresh chats matter because a bot carries conversation state; testing inside an existing thread hides bugs that only appear on a clean start.

The surprise, stated plainly: shared logic trades local cost for global cost. Writing the rule once saved us from six drifting copies, but it also meant every edit paid a full-regression tax. That's the deal you sign when you centralize a rule — cheaper to keep consistent, more expensive to change.

Results

The bot now holds the brand's voice and facts where it used to slip.

It uses only the brand's emojis, so tone no longer drifts with each customer. Its branch reply states that a former branch has closed instead of denying it existed — the factual claim is now correct. Used, tried, or disliked items are turned away from return and exchange consistently, in whichever flow the customer enters, because the eligibility rule is checked before the flow's steps. Chats that need a person are labeled for direct handling, and that handoff is documented for the team.

We verified this the only way that's honest for a stateful bot: a full regression pass across all six flows and every edge case, each in a fresh chat, confirming valid JSON, gender-neutral wording, and no banned words throughout. The measurement wasn't a metric dashboard — it was a re-test of every path the shared rule can reach.

Takeaways

Five lessons from teaching an LLM support bot to speak as a brand:

  1. Voice is a rule, not a vibe. "Use only the brand's emojis" is a house rule you can enforce. Mirroring the customer hands your tone to strangers — write the rule down and make the bot follow it.
  1. Wrong facts and missing facts are different failures. "That branch closed" and "we were never there" both sound plausible; only one is true. For a brand-voice bot, precise wording on real-world facts is part of correctness.
  1. A rule that's true everywhere belongs in one place, above the flows. Eligibility isn't a return question or an exchange question — it's a shared question. Store it once and let it outrank the flows, or watch six copies drift apart.
  1. Centralizing a rule moves the cost, it doesn't remove it. One shared rule is cheaper to keep consistent and more expensive to change. Know which trade you're making before you make it.
  1. Change shared logic, regress everything — in fresh chats. If a rule touches every flow, editing it means re-testing every flow, and a stateful bot hides bugs inside old threads. Start clean, test all of it, every time.

Ready to Implement These Strategies?

Let's discuss how to apply these insights to your specific business challenges.

Schedule Consultation