GuardRAG
A published RAG engine with guardrails that run in code
Stack
- TypeScript
- Typed public API
- Browser client without credentials
- ESM + CJS builds
- Zero runtime dependencies
- Node 18+, Deno, Bun and edge runtimes
- OpenAI, Gemini and OpenAI-compatible providers
- Pluggable vector stores behind one interface, in-memory by default
- Dense, keyword and hybrid retrieval
- Reciprocal-rank fusion
How it works
Try it here
Live — runs in your browser
This runs the published package in your browser. Retrieval, every guardrail, the grounding gate and citation numbering are the real thing. Generation is not: with no API key on the page, the answer is the best-matching sentence from the retrieved passage, quoted rather than written. Point the same pipeline at a provider on your server and you get prose.
Knowledge base 6 passages
Six short passages about a product that does not exist. Anything outside it should be refused.
- Atlas 2 — OverviewThe Atlas 2 is a learning thermostat for apartments and small offices. It watches occupancy for the first fortnight and then builds a heating schedule on its own. It is sold as a single wall unit, with an optional remote sensor for a second room.
- InstallationThe Atlas 2 mounts on a standard 60 mm back box and requires a neutral wire. A typical installation takes about twenty minutes. If your wiring has no neutral, the Atlas 2 Bridge is required and is sold separately. Wiring the unit yourself does not void the warranty, but incorrect installation is not covered.
- Scheduling & LearningLearning takes fourteen days, during which the Atlas 2 holds whatever schedule you set manually. After that it proposes a schedule and asks you to confirm it. You can pin any period so the learning never moves it, which is what most people do with early mornings.
- Remote SensorThe remote sensor pairs over Bluetooth Low Energy and reports temperature every two minutes. Its coin cell lasts about eighteen months. When a sensor is paired, the Atlas 2 averages the two readings by default, or you can nominate one room as the one that decides.
- WarrantyEvery Atlas 2 carries a 3-year warranty on the wall unit and a 1-year warranty on the remote sensor. The warranty covers manufacturing defects. It excludes damage from incorrect installation, and it excludes the coin cell in the sensor, which is treated as a consumable.
- Data & PrivacyOccupancy patterns are held on the wall unit itself and are not uploaded. The mobile app reads them over the local network. Firmware updates are signed, and the unit will refuse an update whose signature does not verify. Factory reset erases the learned schedule and unpairs every sensor.
Try these Half of these are meant to be turned down.
Starting the engine…
Problem
Most RAG code is welded to one provider, one vector store and one framework, with safety living in a prompt string anyone can talk past. I wanted a retrieval engine you could drop into any runtime, point at any provider, and trust to refuse a bad question before it reached the model.
What I built
- A framework-agnostic RAG pipeline published as a package — zero runtime dependencies, ESM and CJS, typed, running on Node 18+, Deno, Bun, edge runtimes and browsers.
- A provider layer covering OpenAI, Gemini and any OpenAI-compatible endpoint, so a local model and a hosted one are the same call.
- A store layer built on a single VectorStore interface, so a backing store is an adapter rather than a rewrite.
- Three retrieval modes: dense, keyword scoring that needs no API key at all, and hybrid with reciprocal-rank fusion.
- A guardrail set: content safety, prompt-injection defence, PII redaction, rate limiting, and a grounding gate that refuses off-topic questions before a model call is spent.
Technical decisions & trade-offs
- Guardrails execute as code, not prompt text. A grounding gate that returns a blocked result is a control-flow decision, not a request the model can be argued out of.
- Constructing a provider or store with an API key inside a browser throws, with no override flag. A convenience escape hatch eventually becomes someone else’s production leak.
- Zero runtime dependencies and nothing but fetch, so the SDK runs anywhere JavaScript does and the supply-chain surface stays at the standard library.
- Retrieval, providers and stores each sit behind an interface, so swapping strategy is a new file rather than a fork.
- Citations are structural: passages are numbered and the answer has to reference them, so an uncited claim is visible rather than plausible.
Challenges solved
- Making one pipeline behave identically across four provider shapes and four store backends without leaking provider-specific concepts into the public API.
- Getting keyword retrieval to work with no API key, so the package is usable — and testable — before anyone signs up for anything.
Outcome
Published under MIT. The guardrail and key-custody patterns are the same ones I hold production systems to; packaging them made the practice reusable instead of retold.