Sometimes the Best AI Integration Is No AI Integration
A substantial body of engineering practice now exists for making model-based systems behave. How to constrain them, how to evaluate them, how to catch their failures before those failures reach anyone, where to place a person so that a wrong answer gets stopped while it is still cheap to stop. It is real craft and it is worth having. All of it begins one step too late. By the time any of it applies, a system has already decided that a language model belongs somewhere in the design, and that decision is rarely examined with the rigor spent on the ones that follow it. The most consequential choice in an AI-integrated system is not how to integrate the model well. It is whether a given part of the system should involve a model at all. Often it should not, and the best integration available is the one you decline to build.
This runs against the prevailing reflex, which is to look at a problem and ask where a model could go. The disciplined version of the question runs the other way. For this specific capability, is a language model the right instrument, or is it a probabilistic answer to a question that already had an exact one? A great deal of what ships as AI would be smaller, faster, cheaper, and more reliable as ordinary software, and some of it should not be built at all. Seeing those cases is not a rejection of the technology. It is the first thing a serious use of the technology asks of you.
A model is the right tool for one shape of problem
A language model is an instrument for a particular class of problem, and the class is narrower than the enthusiasm around it suggests. It is the right tool where the input is unstructured or genuinely ambiguous, where the task is understanding or generating natural language, where the correct response depends on fuzzy pattern rather than a rule anyone could write down, where judgment over messy human material is the whole point. Summarizing a document nobody templated, drafting prose to a brief, extracting meaning from text that arrives in a thousand shapes, deciding what an unstructured request is actually asking for. These are problems whose answers cannot be enumerated in advance and cannot be computed from a formula, and for them a model is not merely acceptable but close to the only viable instrument.
The trouble starts when the same instrument is pointed at problems of the opposite kind. A large share of what systems actually need to do has an exact, known, checkable answer. Arithmetic. Looking a value up by its key. Converting one well-defined format into another. Sorting, filtering, and routing on structured fields. Validating that a string matches a pattern. Applying a rule that a domain expert could state in a sentence. These are not fuzzy problems, and handing them to a model does not make them easier. It makes them worse, because it answers a question that had one correct output with a process that produces a spread of possible answers, most of them right and some of them not, with no way to tell which kind you got on any given call. Using a probabilistic engine on a deterministic problem manufactures a category of error the problem never contained. The failure here is not a tuning problem to be dialed out. It is a mismatch between the instrument and the task, and no amount of care applied to the model closes a gap that opened the moment the model was chosen for work that had an exact answer waiting.
The clarifying question is simple to state and uncomfortable to ask honestly. Could a competent engineer, given the specification, write down the logic that produces the correct output? If the answer is yes, the problem has a deterministic solution, and a model is at best a slower, costlier, less reliable way to reach an answer that plain code would reach exactly, every time, for free.
The options the reflex skips past
Once a model stops being the assumed answer, a set of alternatives comes back into view that the reflex tends to skip straight past. Each of them is boring in the specific way that reliable systems are boring, and each buys something a model cannot.
Deterministic code is the first and most often overlooked. A function that implements the rule gives an exact answer, the same answer on every run, testable against cases that mean the same thing each time they execute, at a marginal cost indistinguishable from zero. Where the logic is knowable, this is not a fallback. It is the correct engineering, and it closes the problem permanently in a way a model call never does.
A known algorithm covers a wider range of problems than the reflex remembers. Decades of computer science exist precisely to solve the recurring hard problems, matching, ranking, searching, deduplicating, scheduling, parsing, with methods that are correct by construction and understood down to their edge cases. Reaching for a model to do fuzzy matching that an established string-distance metric handles exactly, or to rank results that a well-understood scoring function orders correctly, discards a solved problem and reintroduces it as an unsolved one.
A rule or a lookup table handles the large space of problems that are neither fuzzy nor algorithmically deep, just specific. Much of what looks like judgment is a finite set of cases with known answers. A table that maps inputs to outputs, or a short list of rules a domain expert can read and confirm, is inspectable, auditable, and correct by inspection, and it does not drift when a model version changes underneath it.
A person doing the task directly is an option worth naming separately, because it is easy to conflate with putting a human at a review checkpoint. This is different. For low-volume, high-judgment, high-stakes work, the honest answer is sometimes that a qualified person should simply do the task, not supervise a model attempting it. Automating a task that runs ten times a month and carries real consequences on each run can cost more to build and defend than it will ever save, and it trades a reliable human judgment for a probabilistic imitation of one.
And the option that gets skipped most completely is building nothing. Not every capability that can be added should be. A feature that solves a problem few people have, or a problem they solve well enough already, is not improved by adding a model to it. The clearest-eyed decision available in many designs is to decline the capability, and it almost never gets made, because declining to build does not look like progress and adding AI does.
Every model call is a probabilistic dependency you now own
The case for these alternatives is usually argued on token cost, and token cost is real, but it is the least of it. The deeper price of a model call is what it does to the character of the operation. It takes a step that was deterministic, testable, and reproducible, and turns it into one you can no longer speak about in the singular, only in aggregate and by likelihood. That single change pulls an entire apparatus in behind it.
An operation a single assertion once settled now needs a scored test suite run over representative inputs, with a passing bar expressed as a rate instead of a yes, because no input can be promised its output anymore, only given good odds of it. An operation that used to fail loudly and locally now fails quietly, returning a confident, well-formed, plausible answer that happens to be wrong, which means you also need monitoring designed to catch a failure mode that leaves no exception behind. The behavior can shift when the model behind it is updated, so you inherit a versioning and regression surface that a pure function never had. Latency stops being a fixed property of your own code and becomes a dependency on a service you do not control. And you take on a failure class that deterministic systems do not have at all, the fabricated answer, the output that is coherent and authoritative and unsupported by anything.
None of this is an argument against paying that price where the problem justifies it. It is an argument for seeing the price clearly before you agree to it. A model call is not a function call with better vocabulary. It is a standing dependency on a probabilistic system, carried on every request for the life of the feature, along with the whole practice of guarding, measuring, and maintaining it. When the problem genuinely needs a model, that cost is the cost of doing something no deterministic system could do, and it is worth it. When the problem had an exact answer, you have stood up a reliability practice to solve what a single tested function would have closed once and never revisited.
A capability justified by its technology is built backward
There is a force working against this discipline, and it is not a technical one. AI is what leadership asked for, what the budget was approved to pursue, what the market rewards a team for shipping, what looks like forward motion on a roadmap and like relevant experience on a resume. Under that pressure the question quietly inverts. Instead of asking what a given problem needs and sometimes concluding it needs a model, teams start with the model as a fixed commitment and go looking for problems to attach it to. The engineering question, does this task need a model, gets replaced by an organizational one, where can we put the model we have already decided to use.
That inversion is how solutions in search of a problem get built, and it produces a recognizable artifact. The feature is described by the technology inside it rather than by the problem it solves. Its value proposition is that it uses AI, not that it does something a user needed done and could not do before. When the most compelling thing that can be said about a capability is the name of the technique it employs, that is the tell. A well-conceived capability is justified by the problem it closes, and the implementation, model or otherwise, is a detail chosen to serve that problem. A capability justified by its implementation has been built backward, and no quality of execution downstream corrects a direction of reasoning that was wrong from the start.
The corrective is to force the technology to compete for its place. State the problem without naming any solution. Then ask what the cheapest, most reliable, most boring thing is that would solve it. If a model wins that comparison honestly, on the merits of the problem rather than the appeal of the tool, it has earned its place and you should use it without hesitation. If it does not win, the fact that it is the more impressive option is not a reason to choose it. It is the reason to be suspicious of the impulse.
Where a model genuinely earns its place
None of this diminishes the cases where a model is exactly right, and those cases are transformative. Where a task requires understanding language in its full ambiguity, where the input cannot be structured because it arrives as whatever a human happened to write, where the goal is to generate fluent and appropriate text, where the correct response turns on nuance and context that no rule captures, a model does something that no volume of deterministic code could achieve. In those places, refusing to use one out of an excess of caution is its own failure of judgment, and just as costly as reaching for one where it does not belong. The discipline cuts in both directions. It is as much a mistake to hand a genuinely fuzzy problem to a brittle pile of rules as it is to hand an exact one to a probabilistic model.
The mature systems tend to look the same when you inspect them. The model is present, and it is doing the specific thing that only a model can do, and it is surrounded by deterministic code doing everything else. The unstructured input is understood by the model and then handed to ordinary logic that validates, routes, computes, and enforces with exactness. The surface on which the system depends on probabilistic behavior is kept as small as the problem truly requires, not because the model is distrusted, but because every part of the work that can be made exact is worth making exact. The best of these systems tend to grow more deterministic over time rather than less, as their builders discover which parts they had reflexively assigned to a model were deterministic all along, and quietly move that work into code where it becomes testable, cheaper, and permanently solved.
The smallest integration the problem allows
The instinct to build without a model reads, in the current moment, as caution or as skepticism about the technology. It is neither. It is what taking the technology seriously actually looks like. A tool used well is a tool used where it fits and left in the drawer where it does not, and a language model is a tool with a real and specific mandate, not a general substitute for engineering. The teams that get the most from it are not the ones that put it in the most places. They are the ones that make it earn each place it appears, so that where the model does act, it acts on exactly the problem that needed it, backed by deterministic systems everywhere a deterministic answer was available.
The whole practice of building reliable model-based systems, the constraining and the evaluating and the guarding and the recovering, is worth having, and its first act is knowing where not to spend it. Ask, before anything else, whether the problem in front of you is a model’s problem or whether it merely arrived during a season when everything is being framed as one. Make the model win the comparison against the boring, exact, testable alternatives, on the merits of the problem and not the appeal of the tool. Keep the model’s footprint as small as the problem allows, and let deterministic code hold everything it can hold, because everything it holds is something you can test, guarantee, and stop thinking about. The best integration is the smallest one the problem genuinely requires. Often that is a model doing one thing it alone can do. Sometimes it is no model at all, and recognizing that case is not the absence of good engineering. It is the whole of it.
