Pitchbar's self-improvement loop watches every conversation and
flags questions your agent could not answer confidently. Those
questions cluster into content gaps at
/app/analytics/content-gaps. Treat the page as a
prioritised backlog of what to teach your bot next.
After every visitor turn — once the stream has already emitted
done, so the visitor's latency is unaffected —
DetectGapJob runs inline
(dispatchSync) with the user message and the agent id.
It is deliberately NOT left on the analytics queue:
gap-recording is the only visible surface of the self-improvement
loop, and a production worker started without that queue in its list
would silently strand every gap unwritten. Running it inline — the
same guarantee PersistTurnJob has — means a misconfigured
worker can never drop a gap. The follow-up email is the only queued
part (see below). The job:
occurrences and refreshes
last_seen_at.content_gaps
with status=open.
The job is single-attempt — duplicating a gap row is harmless,
but retrying after a transient DB hiccup would over-inflate
occurrences.
Each row carries the question text, the count of times it has been asked, the last time it was asked, and the agent it belongs to.
answered (the source / curated answer that
addresses it is live).ignored (out of
scope for this bot, e.g. visitor asked about a product the
workspace doesn't sell).| Role | View gaps | Resolve / Ignore |
|---|---|---|
| Owner / Admin | Yes | Yes |
| Editor | Yes | Yes |
| Viewer | Yes | No |
Most chatbots silently degrade — a question never gets answered, the visitor bounces, no one notices. Pitchbar turns those silent failures into a triage queue. Working the gap queue weekly is the fastest path to a high-quality agent.