Skip to main content

BenBot: Ask Ben's Site and How It Works

·698 words·4 mins
FTC Disclosure: As an Amazon Associate, I earn from qualifying purchases. Some links on this site are affiliate links.
Ben Piper
Author
Ben Piper
Wiley bestselling author — 100k+ copies, AWS Solutions Architect Associate (SAA) & Cloud Practitioner (CLF) bestsellers, 7+ books. 45 Pluralsight courses (4.7-star, 3,003 ratings). 10+ yrs 100% remote, solo CCNP ENCOR.

Search is useful but limited. It matches words. It does not understand intent. It does not know whether you are trying to find an article, a profile link, a course, or the one page where I explained something in plain English instead of technical English.

So I built BenBot, which I call Ask Ben’s Site.

The idea is simple. You ask a question. The site answers from its own content. It cites the pages it used. And if it cannot support an answer from the corpus, it says so instead of making something up.

What It Is
#

BenBot is a site-specific assistant with guardrails. It is designed to answer questions like:

  • What have I written about?
  • Where is my RSS feed?
  • What is my background?
  • Which articles explain networking concepts in understandable way?

The Stack
#

The architecture is intentionally boring in the right places.

The site is built with Hugo. Hugo generates a JSON corpus of public, non-draft content at /benbot-index.json. That file is the public retrieval index. It is simple on purpose, because simple systems are easier to inspect and harder to break.

The widget itself is rendered by a Hugo partial in layouts/partials/benbot.html. That partial injects the launcher button, the modal panel, the form, and the endpoint configuration. The client-side behavior lives in static/js/benbot.js, which handles opening the panel, sending the question, rendering the answer, and displaying citations.

On the backend, a Cloudflare Worker receives the request at /api/benbot. That Worker is the brains of the operation. It checks the origin, enforces rate limits, validates the request, looks up relevant content, and then asks OpenAI to produce a grounded answer in a strict JSON schema.

Why I Wanted It This Way
#

When I build systems, I usually start with one question:

What are the inputs and what are the outputs?

For BenBot, the input is a question from the user. The output is an answer that is tied back to the site’s actual content.

That means the middle has to do a few things well:

  1. Find relevant material.
  2. Keep the result grounded.
  3. Make the source trail visible.
  4. Avoid pretending to know things it does not know.

If the assistant cannot explain where an answer came from, it is not very useful. If the assistant can answer, but cannot cite the supporting pages, it is not trustworthy enough for a technical audience.

Retrieval
#

The public corpus comes from the Hugo-generated site index. That means every non-draft page can participate in retrieval without hand-curating a second database.

For semantic retrieval, the Worker prefers Cloudflare Vectorize. The embeddings are generated with OpenAI’s text-embedding-3-small model at 512 dimensions, which gives me better matching than simple keyword search when a user asks something in natural language instead of site-specific vocabulary. If Vectorize is unavailable, the Worker falls back to keyword retrieval so the assistant still works.

Trust And Safety
#

I did not want the assistant to become an open relay for abuse, so I added a few practical controls.

The Worker checks the request origin. It uses Cloudflare Turnstile when configured. It also applies a daily rate limit.

How The Answer Is Generated
#

Once the Worker has relevant sources, it sends them to OpenAI through the Responses API.

The important part is not that the model answers the question. The important part is that it answers in a constrained schema. The Worker asks for:

  • a short summary answer, and
  • an array of atomic claims, each tied to source IDs.

That is a better pattern than letting the model freewheel through prose and then trying to guess which sentence came from where.

The result is a response that can be rendered with citations in the UI. If a claim is supported by sources, the interface shows that.

Why It Exists
#

BenBot exists because my site has a lot of information spread across years of posts, course pages, profile links, and technical essays. If you land here looking for one thing, you should not have to click around for ten minutes to find it.

The assistant gives the site a conversational front door.

Recommended Reading#