Skip to content

Build1 publisher3 min readPublished

A reply bot's confidence score was always 0.85, because it was typed in, not computed

Five adversarial queries against a RAG email assistant, including a GDPR deletion demand, all came back with the same self-reported confidence. A constant cannot gate auto-send.

The Engineer · Build desk

Drafted by a language model from the sources cited here and checked against its claim ledger before publication. How we use AISend a correction

Illustration accompanying A reply bot's confidence score was always 0.85, because it was typed in, not computed
Generated illustration

What happened

  • InboxSync is a personal project: a multi-account email aggregation API that indexes emails via IMAP, categorises them with GPT-4o-mini, and for actionable emails retrieves semantically similar training examples from a pgvector database to generate reply suggestions.
  • The stack is Node.js / TypeScript backend, PostgreSQL with the pgvector extension for vector similarity search, OpenAI's text-embedding-3-small for embeddings, and gpt-4o-mini for generation.
  • The training corpus contains three examples, covering job interview scheduling, product demos, and partnership proposals.
  • The system is built for B2B outreach, helping salespeople respond to inbound leads faster.
  • The author says he built the confidence field months earlier with a vague plan to use it to decide which replies were safe to auto-send versus flag for review, and never wired that logic in.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

A developer went back to finally wire up the auto-send gate he had sketched months earlier in InboxSync, his RAG email assistant, and pulled a handful of live responses to sanity-check the values first: every one read 0.85 [5][6]. The number turned out not to be computed at all, but a literal sitting in two lines of `src/services/rag.service.ts`, one that writes the row and one that returns the reply [13].

InboxSync is a personal multi-account email aggregation API that indexes mail over IMAP, categorises it with gpt-4o-mini, and for actionable messages retrieves similar training examples from pgvector to ground a suggested reply [1]. The stack is Node.js and TypeScript over PostgreSQL with pgvector, using text-embedding-3-small and gpt-4o-mini [2]. The training corpus is three examples: job interview scheduling, product demos, and partnership proposals [3]. It is aimed at salespeople answering inbound leads [4].

The author ran five adversarial queries and got 0.85 and a fluent reply every time [7]. Spam ("URGENT! Get 50% OFF") drew a thank-you for the exciting offer, where the correct behaviour is no reply [8]. An out-of-office notice drew a cheerful acknowledgement, which in production is an auto-reply answering an auto-reply [9]. A "we are using a competitor and are happy" message drew exactly the pushy follow-up that gets senders blocked, because the system has no concept that "not interested" is terminal [10]. A GDPR Article 17 deletion request drew an authoritative promise to confirm deletion within 30 days, complete with unfilled `[Your Name]` placeholders, from a system with zero training data on legal compliance; sent, that is a written acknowledgment of a deletion obligation [11]. A two-topic query about an interview and pricing for 50 seats retrieved the nearest single example, ignored the second topic, and promised pricing it never supplied [12].

The gate lesson is arithmetic, not philosophy. Across five trials the field took exactly one value, so its variance is zero and it cannot correlate with retrieval relevance, output quality, or anything else [1]. Any threshold set at or below 0.85, which is where a hand-picked number like that invites you to set it, would have passed all five, including the legal reply [2].

The uncomfortable part is that the retrieval signal was there the whole time. Cosine distance via pgvector's `<=>` operator runs correctly and returns accurate distances; the system computes real similarity and then discards it in favour of the constant [14][3]. The author ran a diagnostic script to surface those per-case scores, though the published text available here stops before listing them [15].

Even wired up, similarity alone is a thin gate. It measures distance to the closest of three examples [3], and three of the five failures - spam, out-of-office, and the GDPR request - have no counterpart in that corpus at all [4]. What those cases need is suppression, not a better match.

Two things worth checking in your own pipeline this week. First, grep the confidence field for a literal, then measure its variance across a batch of real traffic; a field that never moves is decoration. Second, keep "should we reply at all" as a separate classifier from "how close was the retrieval", with explicit terminal states for auto-replies and refusals [9][10]. Whether InboxSync's real similarity scores would have separated the five failures from legitimate leads is the number to look for when the full diagnostic is published [15].

Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories