Part 8 of an ongoing series on vibe coding in EdTech.

When I started building AI-powered tools for education, my instinct was the same one most people have: send the user’s question to Claude, get a response, display it. The AI was the tool and everything ran through it, which worked until it didn’t. An API key expired over a long break and nobody noticed for a good while. Claude went down occasionally and the tool went with it. And the monthly bill for what amounted to answering the same twelve questions over and over started to feel like a problem I’d created rather than one I’d solved.

Over the course of building about half a dozen tools this past year, I gradually arrived at an approach I wish I’d started with. The short version is that the AI should be the finishing layer, not the foundation. The longer version is what this article is about, because the reasoning behind that shift has changed how I think about every tool I build now.

It’s also a commitment I’ve already made in writing. The working ethos I keep for this work says that if a chatbot can do keyword matching against a small index before sending a query to a model, that’s the craftier and lower-energy approach, and the one to reach for. This piece is what that sentence looks like when it’s actually built.

The principle: do the work before you call the API

Every API call has a cost, and the costs stack in ways that are easy to miss when you’re testing a tool by yourself.

The financial cost is the obvious one. It’s also the one that scales in the direction you least want: a tool that’s cheap to run for one person becomes expensive when a district puts it in front of three hundred. The latency cost is quieter but more visible to users, since an API round trip adds seconds to an interaction that a local lookup answers instantly. There’s a reliability cost, because every call is a dependency on a service you don’t control, a key that can expire, and an internet connection that rural buildings don’t always have. And there’s an environmental cost that’s real but genuinely hard to size. The published per-query figures vary by roughly an order of magnitude depending on who’s doing the estimating, and most of the credible ones come from the companies themselves. I’ve written elsewhere about why the environmental question deserves more than a hand-wave, and I’d rather say plainly that I don’t know the footprint of a single query than attach a number I can’t defend. What I do know is that the number isn’t zero, and that a tool making a thousand unnecessary calls a week is making a thousand unnecessary calls a week.

The principle I’ve landed on follows from all four: do as much as possible with structured data and deterministic logic before the AI is involved at all. If a question can be answered by matching against a curated database, match against the database. If a set of strategies can be narrowed by the dropdown selections a user already made, narrow them first. Save the call for the part of the task that actually requires generation, meaning the part where the user needs something personalized or synthesized in a way a pre-written answer can’t be.

What this looks like in practice

The clearest public example from my own work is the FAQ Chatbot, which I built for a help desk and published with its full code and setup guide. The version most people would build first sends every user question to Claude along with the entire FAQ database and lets the model figure out which answer applies. That works. It also means that “what are your office hours” costs tokens, takes seconds, and requires a live key.

The version I actually built runs keyword matching against a sheet of FAQ entries first. Each entry carries its own keywords and synonyms, and the matching logic scores how much the user’s question overlaps with them. A confident match returns the human-written answer immediately, with no call at all. Only an unconfident one escalates, and even then the tool doesn’t ship the whole knowledge base. It sends the handful of entries that scored highest but fell short of the threshold, along with the original question. The model gets a focused context instead of everything, which costs less and, in my experience, answers better, because it’s working with relevant material rather than sorting through noise.

If no key is configured, the tool still runs on keyword matching alone. It’s less capable that way, but it isn’t broken. That distinction matters more than it sounds when you’re deploying into settings where budgets are tight and a subscription isn’t guaranteed to survive the next fiscal year.

The architecture behind it

Across the tools I’ve built this year, a consistent pattern emerged that I now use as the starting point for anything involving AI. The tool runs in one of three modes and picks between them on its own based on what’s available.

In the first mode, a valid key is present and the call succeeds, so the user gets the full experience. The tool has already filtered and structured the relevant data, so the model receives a focused prompt and returns something personalized.

In the second mode, the key is missing or the call fails, and the tool falls back to returning its curated content directly. The user still gets what the underlying database holds, matched to their inputs. They lose the personalization layer, not the substance.

In the third mode, the tool returns an error. I use this only where showing raw unprocessed data would mislead someone, which in practice is rare. For most educational tools, the curated content is the real value and the AI is adding polish.

One configuration decision has mattered more than any of the code. When I build for an external organization, fallback mode is on by default. If a key expires because nobody renewed it, or billing lapses over the summer, or a new administrator doesn’t realize the tool depends on an outside service, the thing keeps working. That setting lives in the tool’s config sheet where any administrator can see and change it, and it has kept several tools alive through exactly those circumstances.

Sending less context, getting better answers

Sending less to the model often produces better results and not just cheaper ones, which sounds backward until you look at what the model is actually being asked to do.

The example I keep coming back to is a behavior intervention tool I built for the University of South Dakota. It was shared inside select programs as a prototype and never publicly deployed, and unlike the rest of my tools it isn’t open source, so I can describe how it works but not hand you the code. That’s worth naming directly in a piece like this, since most of what I write argues for tools districts can own outright. This one is theirs, not mine to give away.

When a user fills out the form, selecting a grade band, a behavior category, a framework such as PBIS or restorative practices, and a setting, the tool uses those selections to filter a research base of strategies before the model sees anything. Rather than sending two hundred strategies and asking which ones apply, it sends the fifteen or twenty that already match the user’s context and asks for them to be synthesized into specific recommendations.

The model’s job becomes synthesis rather than search. The prompt is smaller, and over hundreds of uses the difference in tokens is substantial. The pattern generalizes past my particular tools: any time you’re about to hand a knowledge base to a model, ask what you could filter with dropdowns, keyword matches, categorical filters, or date ranges first. You’re reducing the footprint without reducing quality, and often improving quality by removing noise.

Pre-built responses are not a consolation prize

Not every response needs to be generated, and treating generation as the default creates overhead that buys nothing.

Several of my tools have response paths that are entirely pre-written. A high-confidence FAQ match returns the human-authored answer from the spreadsheet verbatim, with no model involvement whatsoever. That answer was written once by someone who understood the question, checked for accuracy, and stored somewhere any colleague with access can update it.

There’s a pedagogical argument here as well as a technical one. In educational settings, curated content from a known source often carries more weight than generated text, particularly with administrators and teachers who are reasonably cautious about accuracy. A tool that returns four research-based strategies from a named framework, with citations, is offering something concrete and checkable. The AI layer can make that more conversational and more specific to the situation someone described, but the foundation holds without it.

PII and local processing

There’s one more place where doing the work locally makes both practical and ethical sense, and it’s the one I feel most strongly about.

The USD tool accepts free-text descriptions of student behavior, which means a user could paste in a name, an ID number, or other identifying detail without thinking about it. Before anything goes to an API, the tool runs a local check using pattern matching and warns the user if it finds something that looks like identifying information, giving them a chance to edit. The free-text field is never stored regardless of what happens next.

Could I send the text to a model for more sophisticated detection? Technically, yes. That would mean transmitting potentially sensitive student information to an outside service in order to find out whether it contains sensitive student information. The local approach has false positives, since plenty of numbers look like student IDs, but warning rather than blocking means a false positive costs someone three seconds rather than locking them out of the tool. The data stays inside the user’s own Google Workspace, which is the part that matters.

The larger principle is that not everything AI can do is something AI should do in a given context. In education, where data privacy is a legal obligation and a trust relationship at the same time, whether a task requires sending data outside the building deserves a deliberate decision rather than an automatic one.

A practical checklist

These are the questions I now work through during planning, before any code gets written.

  • Can the core function of this tool work without AI at all? If the answer is no, consider whether you’re building an AI tool or a tool that uses AI. The distinction shapes reliability, cost, and who can run it.
  • What can be filtered or structured before the call? Every dropdown, keyword match, or categorical filter that narrows the context reduces token usage and usually improves the result.
  • Are there responses that can be pre-written rather than generated? For FAQ-style questions and standard informational content, human-authored answers in a spreadsheet are faster, cheaper, more reliable, and easier to trust.
  • What happens when the API is unavailable? Whether the key expired, the service is down, or the building lost internet, the tool needs a plan that isn’t an error message. For anything deployed into a real school, this is a design requirement rather than a nicety.
  • Does this data need to leave the user’s environment? For anything involving student information, local processing should be the default until there’s a clear reason to do otherwise, and that reason should be weighed against the privacy implications.

What is this really about?

The argument here isn’t primarily about API credits, although those matter for districts and cooperatives working on tight budgets.

A tool that requires a constant connection, a valid subscription, and an outside service to be operational is fragile in exactly the ways that hurt most in rural and under-resourced settings. A tool that treats AI as an enhancement on top of solid local functionality keeps working when circumstances change, and in education circumstances always change. That’s the same argument I made in Designing for Human Judgement about where the model belongs in a workflow, applied one layer down to where it belongs in the architecture.

What I have not resolved is where the line sits. Every deterministic path I build instead of calling a model is a path I have to maintain, and a keyword index is a small curation job that somebody has to keep current. There is a version of this approach that becomes so committed to using less AI that it spends more human effort than the thing was worth. I have not found that line yet in my own work, but I am fairly sure it is out there.

If you are building tools like this, I would be interested in where you have drawn it. What does your tool handle on its own, and what did you decide genuinely needed the model? You can reach me at licht.education@gmail.com, and there are more tools, articles, and resources at bradylicht.com.


Discover more from Brady Licht

Subscribe to get the latest posts sent to your email.