Knowing when not to answer

Clara answers every message she receives — including "thank you", goodbyes and thumbs-ups — and sometimes repeats what she just said. This page explains why, how often it happens in production, and asks you to pick a fix.

2026-08-28, revised 2026-08-29 · Status: Proposed — pending review · Evidence: full production sweep (read-only), code trace of the incident thread, and a live reproduction during the investigation

Conversations read: 174 real ones Goodbyes answered anyway: 25 of 29 (86%) Thumbs-ups answered: 2 of 2 Conversations with over-replying: 14.4% Picks on this page: 4, plus 6 already decided

Goal

Clara should know when a conversation is over — and say nothing. Today, staying silent is not something she is capable of choosing when she is talking to a prospect. That is a missing ability, not a tuning problem, and it is the single thing this page is about.

The bar we should hold her to is the one a good leasing agent holds: when someone says "thank you" and everything is handled, a person puts the phone down. They do not send "you're welcome — anything else?" That reply costs nothing to send and quite a lot to receive; it is what made the prospect in this week's incident write "you will always sound like a bot."

Strategy

Three commitments, in order. They matter more than the individual fixes, because they decide which of the options below actually fit together.

  1. Give her the ability before you tune the judgment. Every prompt we write telling Clara "don't reply to a closer" is currently unenforceable for a prospect: there is no action she can take that means "send nothing." Ability first; taste second.
  2. Put the last word in one place that every message passes through. Today a message can leave the building through at least three different doors, and the checks on each door are different. A necessity decision that lives in only one of them will be right most of the time and quietly wrong on the rest.
  3. Nothing on a timer sends blind. Decided by Fede, 2026-08-28. Every automated follow-up must check what is happening in the conversation at the moment it sends — not just the database fields it was built to read. This one is settled; only how to build it is open (number 3 below).
  4. Prove it in the lab before a real person sees it, and prove the failure first. The risk of a silence rule is not that it is annoying — it is that Clara goes quiet on someone who asked a real question. So the rule ships behind a test that first reproduces the bad behavior on the real incident thread, then shows it fixed, and it ships on texting only until that test has run for a while.

What is actually going wrong

She cannot be silent — for prospects, literally

Every incoming message wakes Clara up and makes her write something. We did build her a way to end a conversation on purpose, and we wrote good instructions telling her when to use it. But that ability is only handed to people we have already matched to a lease. Someone shopping for an apartment — exactly who was in this week's incident — never gets it (capabilities/index.ts:167-168, verified). For that group, silence is not a hard choice, it is not a choice at all.

And if she somehow wrote nothing, the system does not stay quiet: it fills the gap with a canned apology — "I'm sorry, I wasn't able to generate a response…" — and sends that instead (conversation-manager.ts:8886-8892, verified). Producing nothing is treated as a malfunction, never as an answer.

The one brake we built cannot reach the pedal

There is a circuit-breaker meant to stop an endless goodbye loop. It only trips when Clara's own last two messages were pure pleasantries with nothing in them. Her house style is to always tack a next step onto a sign-off — "talk to you tomorrow", "see you Friday at 11:45" — and the breaker counts a weekday, a time, or the word "tomorrow" as content (guards/farewell-loop.ts:82, verified). So her goodbyes never qualify as empty, the counter never reaches two, and the brake never fires. It is also only wired to incoming messages; none of the automated follow-up sequences ever consults it.

Nothing tells her not to repeat herself on text

The rule "never repeat yourself" exists — in the phone-call instructions only (clara-delivery.ts:252, verified). Texting and email have no equivalent. A separate rule pushes the other way, telling her never to claim she already answered something. And nothing anywhere compares a message she is about to send against one she just sent: there is no such check on the texting path at all.

Her own automated follow-up texts are deliberately hidden from her (context-message-filter.ts:53-58, verified) — a fix for an older bug that has created its mirror image. A reminder goes out making a promise, and on her next turn she cannot see that it was sent, so she makes the same promise again.

How widespread it is

We read every real text and email conversation in production — 174 of them after excluding test properties and voice-only records, essentially all at one property, 7,619 messages. Read-only; nothing was written.

What we looked forFoundReading
Real people sending a plain conversation-ender ("thank you", "ok", "see you then") 29 across 17 conversations Clara replied to 25 of them — 86%. She correctly stayed quiet 4 times.
Of those replies, how many added nothing 16 pure pleasantries in 9 conversations These are the unambiguous over-replies. A human agent would not have sent them.
Phone thumbs-up reactions received 2 She answered both. One reply was literally "👍". No rule for this exists.
Sending the same thing twice with nothing in between 2 conversations The same "rate your maintenance ticket" text twice — once 1 second apart, once 13 minutes apart.
Word-for-word identical follow-up, 48h later 9 prospects The "did you get a chance to apply?" chase re-sends the exact same sentence rather than varying it.
Any of the above 25 of 174 = 14.4% Of conversations that are a real back-and-forth (four messages or more): 24 of 101 = 23.8%.

The damage concentrates. It is not a light drizzle across every thread — one conversation, the Section 8 prospect at Camellia (conv a05c3c99…), holds 7 of the 16 pointless replies on its own. That is the shape of the problem: mostly invisible, then catastrophic in the one thread where somebody is already unhappy.

Is this new? No — with one exception

The obvious suspicion was that we broke something recently: we moved Clara's texting and email drafting onto a newer, reason-first model on 21 August, and raised how hard it thinks on 28 August, about seven hours before the incident. We tested that directly against the corpus, bucketing every message by its own timestamp.

MonthConversations activeGoodbyes sent to herAnswered anywayRate
June 2026495480%
July 2026877571%
August 202671171694%

August looks worse only because of concentration: 7 of its 10 pointless replies are the one incident thread. Remove that thread and August is 89% — in line with June and July.

So the causal story is: the compulsion is structural and old; the new escalation-and-promise machinery gave her fresh material to repeat; the model change is not the cause. Fix the structure, and be careful about what the new machinery puts in her mouth.

The yellow dot — the straight answer

The yellow dot means a safety check changed what Clara said. It does not mean a bad message went out. The words you are reading in the app are the corrected version; the wording the check objected to never left the building.

On the two dotted messages in the incident thread (4:34 PM and 4:43 PM Mountain), it was the promise-backing check: Clara drafted a version of "I've checked with the team, I'll get back to you", the check found nothing tracking behind that promise on that turn, and it swapped the clause for "I don't have that answer on file right now." Both delivered messages carry that substitute sentence word for word. So: the check caught something, a message did go out, but what went out was the rewrite.

Two things are genuinely wrong here, though, and they are not what the dot suggests. First, the dot is the same colour whether a message was withheld or merely rewritten — the underlying field is called "blocked" in both cases, which is why the app reads as more alarming than the event was. Second, and worse: the rewrite made the message sound like a robot. "I don't have that answer on file right now" is a phrase no person would say, and it is a fair candidate for the line that triggered the "you sound like a bot" reaction. Our safety checks are allowed to change what Clara says; they should not be allowed to make her sound like a form letter. That is Decision 6.

It happened again while we were investigating it

The sequence, all from production, the night of 28–29 August (times in UTC; local was late evening in Denver):

Read that last line as the finding it is. Not "the answer was wrong" and not "the reply was unsafe" — every message in that exchange was accurate, friendly and compliant. The volume alone, after the substance was already settled, was enough to make a real prospect ask to be taken off the AI. That is the entire case for this page in one exchange.

And then the one lane that does have a working state check did its job. Clara escalated the thread to a person herself, the conversation went human-owned, and when he followed up — "Is your team comprised of humans or ai?" — the system correctly sent nothing and left it for a human. That is silence, chosen and held, on the only path where the machinery is actually wired to conversation state.

Which is the argument of this whole document, demonstrated twice in five minutes: where a check reads what is happening in the conversation, Clara behaves like a colleague. Where no such check exists, she cannot stop talking.

What the rest of the industry does

Before proposing anything, we checked how mature conversational products and the research literature handle "should I answer this at all". Four things came back consistently.

Closing a conversation is a recognised, labelled speech act — not a vibe. Deciding what job an utterance is doing (a question, a statement, an acknowledgment, a goodbye) is a standard, decades-old classification task with public benchmarks; conversational-recommender work routinely uses an explicit "goodbye" class alongside greeting and follow-up. The classic conversation-analysis result behind it is that people do not just stop talking — they run a short, recognisable closing ritual, and a "terminal exchange" ("bye" / "bye") is its final move. In other words: "thank you" then "you're welcome" then silence is the correct human script, and Clara is inserting an extra turn after the script has ended.

Commercial support tools treat "no follow-up" as a first-class setting. Intercom's Fin lets you choose, explicitly, what happens after it answers — check in again, offer a human, or send no follow-up at all — and it can close a conversation on a positive closer like "that helped, thanks" rather than replying to it. Bot-building platforms document "respond only to valuable messages", where greetings and acknowledgments such as "thanks" or "okay" are classified as low-priority and skipped by design. Nobody mature ships an always-reply loop.

Reaction texts are a known category of noise, and the platforms fixed them by filtering. When an iPhone user taps a thumbs-up on a message to a non-Apple number, it arrives as a separate text reading 👍 to "…". Both Apple (from iOS 16) and Google Messages solved this by recognising the pattern and rendering it as a reaction instead of a message. The industry answer to a tapback is to convert it to metadata — never to reply to it. We reply to 2 out of 2.

Self-repetition is a known failure mode of generated text with known countermeasures. The research literature treats repetition as a degeneration problem and applies explicit blocking of previously-produced phrases, repetition penalties, and training-side fixes; surveys of neural conversation models list self-repetition as one of the standard failures needing a deliberate fix. The recurring warning is that blanket penalties damage text that legitimately repeats (names, addresses, links) — so the useful version compares a new message against her own recent sends, not against everything.

One boundary worth stating: the messaging-compliance world (quiet hours, contact frequency) already gives us ceilings on volume and timing, and we implement them. None of them help here. A reply to "thank you" at 4pm is perfectly legal and perfectly unwanted. Necessity is a separate axis from compliance.

The decisions

Four picks left, each with a recommendation. Six things are already settled — the global silence ability (1), conversation-aware follow-ups (3), the takeover rule (3d, now its own page), what an empty reply means (4), one shared closing behaviour for texting and email (5), and promised deadlines (9, now its own effort) — and one turned out to be plain defect work rather than a choice (2). Take the recommendation on the remaining five and the result is a coherent package; they were chosen to fit together.

1. Where does the "should I answer at all?" decision live?

In plain terms

Right now there is no such decision anywhere. The safety checks all run after Clara has written a reply, and every one of them assumes a reply is going out — they only edit it. The question is whether the choice to stay quiet should be Clara's own judgment, a mechanical rule that runs before she is even woken up, or a last check just before the message is sent.

2. Repeating herself — not a pick, a defect

In plain terms

One incoming event should produce exactly one reply, guaranteed by a mechanical key on that event — not by inspecting what the message says afterwards. The investigation proving the precise mechanism is running now, and the fix follows it, failing-test-first, under the standing grant. No decision needed from you.

Separately, and also being fixed: Clara cannot see her own automated reminders — they are stripped from what she reads, so she re-promises what a reminder already promised. Fede: "this seems like a separate context issue." It is, and it is decoupled from the reply-necessity work. The fix: her context will show every person-facing message exactly as the person's own phone shows them — reminders and cadence touches included — while purely internal notices stay hidden. In flight under the grant.

Between these two, the already-shipped fix to the escalation prompt block that scripted the repeated "I'll follow up tomorrow" line, and the silence work in decision 1, every class of repetition we actually observed is addressed at its root — none of them by comparing one message against another.

3. Automated follow-ups must read the room before they send

In plain terms

Today the automated sequences do not look at the conversation at all. They read a few database fields — has this person applied, is a tour booked — and send. Three of the four never check whether the person already said goodbye, and none of them ever consults the goodbye brake, which is wired only to incoming messages. That is how someone who says "we went with another place" keeps getting chased, and how a reminder can land minutes after Clara said the same thing live.

The check has to ask, every time, right before sending: is a question about this person already escalated and open? Has the thread been active in the last little while with something that contradicts this message? Has a human taken this thread over? Did the person say they are waiting on us, or that they are done? Are they on do-not-contact? Any yes, and the message does not go.

3a — Where the check lives

3b — What it does when it cannot read the conversation

3c — How it sits with the timing rules we already have

3d — When a human answers instead

The other half of this — a person stepping in and answering as Clara, and that answer becoming ground truth in one indivisible act — is its own design, on its own page: When a human answers. Decided there, in short: a takeover absorbs the answer and hands the thread back, rather than parking it with us. One half shipped tonight; the page names what has not.

The check described in this section is the durable fix. It is not what makes tomorrow's message correct — that is the rehearsal-and-correct work above, which is being handled directly and per message.

4. When Clara writes nothing

In plain terms

Two facts make this easy. First: we already have retries, a dead-letter queue and error reporting for turns that fail — but a turn that succeeds and returns nothing is not an error today, so none of that machinery fires; the apology path catches it instead. Second, and it settles the risk: that apology has never once been sent to a real person — zero matches across 3,913 of Clara's messages and 324 turn traces, checking both wordings (the test bench was not scanned). So this is a zero-blast-radius cleanup of an error path nobody has ever hit.

Status: decided in shape, pending your read of that count. The one thing to keep: silence here is a technical outcome, so it must always report to us — and escalate to a person if it happens twice on the same thread.

5. Texting and email behave the same

In plain terms

Today the two are barely related: texting has a closing protocol, email has none and instead requires every reply to end by proposing a tour. Under this decision email gets the same closing behaviour as texting, and the carve-out from the mandatory tour pitch lives inside the shared gate — not as a parallel email rule sitting beside it. Also in the package: "never repeat yourself" applies to both channels (it is voice-only today), and a bare "thanks" stops being routed as a question to answer.

6. When a safety check changes her words, may it make her sound worse?

In plain terms

In this week's incident a check replaced Clara's sentence with "I don't have that answer on file right now." That is honest and it is also robot-speak — and it went out twice to a person who then said she sounds like a bot. Right now a check can swap in any wording it likes, and nothing checks the result for tone.

7. Checking a draft against what a human already said in the same thread

In plain terms

When one of us sends a message manually as Clara, nothing stops her next automatic message from contradicting it. In the incident thread a manual message went out saying one thing, and shortly after Clara walked it back on her own — which was arguably the right call, but nothing in the system checked, and it could just as easily have gone the other way.

8. How far, and how fast

In plain terms

A rule that makes Clara go quiet is the one kind of change where the failure is invisible: nobody complains about the message they never got. So the rollout matters as much as the rule.

This question is about her replies only. The decided rule for automated follow-ups (number 3) is not scoped by channel — a follow-up that goes out blind by email is the same defect as one that goes out blind by text, so that check applies to every automated lane from the start.

9. Promised deadlines — decided, and now its own effort

In plain terms

Where "tomorrow" came from: when a question is escalated, the system stamps two clocks automatically — nag our staff in four hours, promise the customer an answer in twenty-four — and Clara repeats the second one as a commitment. Nobody on the team promised anything by tomorrow; a constant did. They are raw wall-clock arithmetic too, so a 7 PM escalation nags the on-site team at 11 PM and a Friday 5 PM escalation promises Saturday.

Scoping note for whoever picks this up: those clocks live in the newer escalation lane, not the older forward-to-a-manager one. Two escalation implementations currently coexist in production — the effort must scope against the new one, or it will change code that is not producing this behaviour.

Appendix A — where the safety checks reach, and where they do not

There is no single door every message leaves by. There are three, they overlap unevenly, and this table is why a necessity rule has to be placed deliberately rather than wherever is convenient.

LaneContent checks when Clara writes itThe shared send gateGap
Incoming text → her replyall of themyesNone — this is the fully covered lane
Incoming email → her replyall of themnever calledThe "a human owns this thread, stay out" rule does not apply to email replies
Automated prospect follow-upsn/a (templated)yesNo content check, but no generated text either
Turnover nudges, renewal notices, renewal letter picture-message, team recaps, follow-up texts on an open mattern/abypassedFive paths send texts directly, skipping the shared gate. The code documents this gap itself.
Tour confirmationsn/adeliberately exemptIntentional — but it means a human-owned thread still gets automated tour texts
Bulk sendschecked once, at approvalyesThe approved wording is re-sent to every recipient with no re-check
Phone callsnonen/aNo outbound content check exists on this channel at all. The app already says so on screen.

Appendix B — the promise check is inconsistent, and it is a punctuation bug

Worth reading even though it is not the over-reply problem, because it is what made the incident thread look arbitrary from the outside.

In the same conversation, the same promise — "I've checked with the team, I'll follow up with you tomorrow" — was rewritten twice and delivered untouched three times. Two separate causes, both verified:

Net: the two catches were correct by the rules as written; the three passes are the bug. Both defects deserve their own cards.

Appendix C — flagged bug: Clara has been texting herself since May

There is no customer in it. It matters because it is the same missing rule with nobody on the other end to stop it: two of our own lanes replying to each other, forever, because neither one can decide that a conversation is over. It is also the clearest possible argument for putting the necessity decision at a point that catches machine-to-machine loops, not only human closers.

Sources

Production numbers come from a read-only sweep of the live database on 2026-08-28 (1,619 conversation records enumerated, 7,619 messages read, test properties and voice-only records excluded). Code references were read directly in the repository and are quoted with file and line. Industry references:

PropFlow Docs