Enhanced Rentals
Blog
EngineeringJune 2026·7 min read

Your AI support bot gets dumber on long threads. Here's the fix.

Structured working memory, an escalation that knows when to stop, and an improvement loop a human keeps on a leash — the architecture behind ~3,300 AI-handled support cases.

Adrian Barwicki

Adrian Barwicki

CEO, Enhanced Rentals GmbH

A guest messages on arrival day. Over twenty messages we sort out a late check-in, a parking spot, and a broken coffee machine. Then they ask one more thing — and the bot answers a question from message three as if it were still live, re-confirms the parking they'd already cancelled, and ignores the coffee machine entirely.

To the guest, it looked like nobody was listening. In a way, nobody was.

I saw that failure over and over while running short-term rentals, and it taught me something that shaped everything we built afterward: most AI support bots get dumber the longer a conversation runs. Not because the model is weak — because of how the conversation is fed to it.

This is the architecture we built to fix that. It now runs roughly 3,300 support cases for one operator — about two-thirds messaging, one-third voice. No model rewriting its own weights, no autonomous agent loose in production. Just a few small systems that feed each other, with a human in the loop where it counts.

~3,300 support cases · one operator · ~90 days

Roughly 2 in 3 messaging, 1 in 3 voice

Messaging
2,228
Voice
1,072
Quick context, since two companies show up in this story. Enhanced Rentals is the software company I founded — it builds the platform. RENTUJEMY is a short-term rental business I also run; it's the operator behind those 3,300 cases, and it's where Enhanced Rentals proves its software first, before any other operator uses it.

Why the obvious approach breaks

The default way to build an AI support bot is to paste the entire conversation transcript into the prompt on every new message.

Five messages in, fine. Thirty messages in — my coffee-machine guest — it falls apart. The bot re-reads its own old replies and treats them as gospel. It repeats answers. It misses the newest, most important thing the guest just said.

The instinct is to reach for a bigger context window. It feels like “more memory.” It isn't — it just makes it cheaper to keep doing the wrong thing. The real gap is that there's nowhere to put working memory: a clean, current understanding of the conversation, separate from the raw log of everything ever said.

So we built one.

1Memory: a structured snapshot, refreshed every turn

After every bot reply, a cheap, fast model compresses the recent thread into a small structured snapshot. Four fields — not freeform text:

For the coffee-machine guest, that snapshot reads:

intent:  settle in for the stay
facts:   checked in late (ok); parking cancelled; coffee machine broken
open:    replacement or refund for the coffee machine?
summary: Guest arrived late and is settled. Parking no longer
         needed. Coffee machine is broken; they want it resolved.

Next turn, the bot reads that plus the last couple of raw messages — not forty. It can't re-confirm the cancelled parking, because the snapshot says it's cancelled. The newest open question sits at the top.

The per-turn memory loop

Guest sends a message

load snapshot

Bot reads snapshot + last ~6 messages

not the whole transcript

Reply sent to guest

fire-and-forget · after the reply ships

Refresh the 4-field snapshot

intent · facts · open questions · summary

↻ next turn reads the updated snapshot

Two decisions made it safe on real guests:

Fire-and-forget. The refresh runs after the reply is already in the guest's inbox. The guest never waits for the summarizer. Added latency: zero.

Graceful degradation. No snapshot yet? Use the full transcript. Summarizer fails or returns garbage? Keep the previous snapshot. The memory layer can improve a reply — it can never break one.


2Escalation: when unsure, it stops

The worst early moments weren't wrong facts. They were confident wrong answers to questions the bot had no business touching — a deposit dispute, a refund, an angry guest. A human would have paused. The bot just answered.

So now, when the routing bot can't safely handle a message, it doesn't guess. It opens a support case and goes silent while a human takes over. A guard on every incoming message keeps the bot out of the way while a human is handling it — no bot and operator talking over each other.

This is the workhorse. Those ~3,300 cases are this mechanism, routing work to the right place across messaging and voice.

And the memory pays off twice here: that same snapshot becomes the operator's brief. Whoever picks up the coffee-machine case reads three sentences instead of scrolling forty messages. We built the memory for the bot; it turned out to be just as useful for the human handoff.

Escalation & flagging

Routing bot evaluates a message

can't safely handle it

Open a support case

bot goes silent while a human handles it

+ the memory snapshot as the brief

Operator picks it up

reads 3 sentences, not 40 messages

spots a bad bot reply

One-click flag (+ optional note)

the training signal — a human says 'this was wrong'

3Flagging: humans mark the misses, one click

People expect this part to be clever. It isn't, on purpose.

The bot sends a guest the wrong wifi password — unit 4B's code to a guest in 4A. An operator spots it and flags that reply: one click, optional note (“wrong wifi — that's 4B's”). That's the whole mechanism. No sentiment classifier, no intent pipeline, no labelling team.

This is where most “self-improving” claims overreach, so I'll be exact: we don't score sentiment or intent per turn. The signal is a human saying “that one was wrong.” Cheaper and more trustworthy than a model grading itself. Operators already know a bad reply when they see one — we just gave them a button.

4The loop: built, and deliberately on a leash

Here's the part the title implies, and here's exactly how far it actually goes — because this is where I see the most hand-waving in the industry.

The mechanism is wired end-to-end: a scheduled job pulls recent conversations, surfaces the flagged ones, and hands them to an LLM with the bot's current instructions. It proposes a rewrite. The wifi mistake doesn't just get fixed in one chat — it becomes a proposed instruction change: match the wifi code to the exact unit before sending it.

But the proposal does not ship itself. It lands in an admin UI as a diff, flagged examples highlighted. A human approves it or bins it. Only on approval does it go live.

I'll be straight about maturity: the escalation backbone is mature — thousands of cases, every day. The memory layer and the flagging signal are newer, in early real use. The loop is built and deliberately gated — and I'm in no rush to take the leash off. I am not going to let a prompt rewrite itself unsupervised and then explain to a guest why it went sideways. The human gate isn't a temporary limitation. It's the design.

The improvement loop — built, and gated

Scheduled job pulls recent conversations

flagged ones surfaced first

+ the bot's current instructions

LLM proposes a rewrite

specific changes, with rationale

Lands as a diff in the admin UI

flagged examples highlighted

a human approves — or bins it

Approved version goes live

on the very next message


What I'd tell another builder

Skip the generic lessons. Three specific things earned their keep:

The takeaway

“Self-improving AI” sounds like a black box you have to trust.

What we built is the opposite: structured memory, an escalation that knows when to stop, and an improvement loop a human keeps on a leash. It came straight out of being the operator answering the messages — and being embarrassed enough, often enough, to fix it properly.

The unglamorous version is the one you can actually put in front of customers.

I'm building Enhanced Rentals — AI telephony that answers, handles, and escalates calls and messages for businesses that live or die by the phone. I also run RENTUJEMY, a separate short-term rental company, where Enhanced Rentals proves its software first before any other operator touches it.