AboutExpertiseWorkR&DBlogToolsStartContact

Agents decide. Code executes. Knowing the line is the job.

The promise is that agents replace applications. In the systems we build, they do not. An agent is very good at understanding a request, weighing options and choosing a tool. It is the wrong place for a payment, a tax rule or a permission check. This is where the line falls, and why putting it in the wrong place is expensive.

pH7x Systems® · · 8 min read

There is a sentence going around boardrooms that sounds like the future and behaves like a bill: agents will replace applications. It is worth taking seriously, because the part that is true is genuinely new, and the part that is not will be paid for by whoever builds on it.

The useful question is not whether to use agents. It is where the line falls between what an agent decides and what code executes. Put it in the wrong place and you get a system that is slow, expensive, impossible to audit, and occasionally confident about something that never happened.

What actually changed

Models became good at three things that software was historically bad at: reading an instruction written by a human, breaking it into steps, and picking the right tool for each step. That is not a small change. It removes the need to anticipate every phrasing a user might choose, which is most of what makes traditional interfaces rigid.

What did not change is everything underneath. A tax rule is still a tax rule. A payment either settles or it does not. A permission check has one correct answer and no room for interpretation. Those things were never hard because they were tedious to express. They were hard because they must be exactly right, every time, and provably so afterwards.

The brain and the skeleton

The comparison that survives contact with a real project is anatomical. The model is the brain: it understands, weighs and decides. The tools are the arms: they reach out and act. The code is the skeleton, and without it the brain has nothing to move.

Skeletons are unglamorous. Nobody demonstrates one at a conference. But the reason the analogy is worth keeping is that it predicts the failure mode: a system built as brain and arms, with no skeleton, does not fall over dramatically. It works in the demo, works for a week, and then starts producing answers that are plausible and wrong, at a cost per request nobody budgeted for.

Book me a flight

The canonical example is worth walking through, because the line falls somewhere very specific.

The agent should understand that a trip to Berlin next Tuesday means departure after the morning meeting. It should compare options, notice that a two-hour saving costs three hundred euros, and ask whether that trade is worth making. All of that is judgement about an ambiguous request, and it is exactly what a model is for.

The agent should not charge the card. Not because the model is untrustworthy, but because charging a card is a transaction: it either happens once or the accounting is wrong. It needs idempotency, a retry policy, a rollback path and a record that survives an audit. None of those are decisions. They are guarantees, and guarantees live in code.

Where the line falls

Code Agent
Authentication and permissions Understanding the request
Payments and transactions Comparing options
Tax and regulatory rules Planning the steps
Validation and consistency Choosing which tool to use
Business workflows Summarising a result
Audit trail Asking the clarifying question

The pattern is not arbitrary. The left column is everything that must be identical on every run, provable after the fact, and correct even when the input is strange. The right column is everything that benefits from reading context and exercising judgement.

Anything you would want to unit test belongs on the left.

The mistake we keep seeing

The most common architecture error is putting the business logic in the prompt. It works immediately, which is what makes it dangerous.

The rules go into the system prompt, then the exceptions, then the exceptions to the exceptions. Six months later the prompt is four thousand tokens, every request pays for all of it, and nobody can say with confidence what the system will do with an unusual input, because the answer is not written anywhere that can be read as logic. Changing one rule risks changing three others, and there is no test that catches it.

The same rules expressed as code are cheaper on every request, reviewable in a pull request, and testable. The prompt then does what it is good at: deciding which of those rules applies to this situation.

The agent never touches the database

If there is one rule worth keeping from this article, it is this one.

A question like "which customers have no backup?" should not become SQL written by a model. It should become a call to something that already exists:

python
# The API is the contract. The agent chooses to call it;
# the code decides what that means and who is allowed to ask.
@router.get("/customers/without-backup")
def customers_without_backup(user: User = Depends(current_user)):
    if not user.can("read:customers"):
        raise Forbidden()
    return repository.customers_without_backup(tenant=user.tenant)

The agent picks the tool. The code enforces who may ask, which tenant they may ask about, and what the question means. If the permission model changes, one function changes and every caller inherits it, including the agent.

Written the other way, with the model generating queries against the database, the permission model lives in a prompt, and the prompt is a suggestion.

This is the same boundary we wrote about in the AI assistant that only reads what the user can read: the assistant is only ever as safe as the layer beneath it.

What MCP is for

The Model Context Protocol is the part of this that has moved fastest, and it is worth being precise about what problem it solves.

Before it, every assistant spoke to every tool in its own way. Connecting a model to an internal system meant writing an adapter for that model, and writing it again for the next one. MCP standardises that conversation: the tool describes what it can do, and any client that speaks the protocol can use it.

The specification repository went public in September 2024 and the server collection followed that November. The server collection now carries more than eighty thousand stars on GitHub, which says less about quality than about how badly the standard was wanted.

What matters architecturally is that MCP is a description layer, not an execution layer. It tells a model what a tool does and how to call it. It does not make the tool safe, correct or auditable. Those remain properties of what sits behind the endpoint, which is to say properties of your code.

Where this genuinely helps

The honest version of the value is narrower than the pitch and more useful.

An agent earns its place where the input is ambiguous and the action is bounded. Reading a supplier email and proposing which purchase order it matches. Turning a description of a problem into the right query across systems that do not share a schema. Reading a contract and flagging the clauses that differ from the template. In each case the hard part is interpretation, and the action taken afterwards runs through code that would run identically if a human had clicked the button.

It earns nothing where the input is already structured and the rules are already known. If a form has eight fields and the validation is a list of conditions, an agent adds latency, cost and uncertainty in exchange for nothing.

What this means for the architecture

Agents are a new layer, not a replacement for the ones underneath. The stack we build looks the same as it did, with one addition at the top:

PersonAgent: understands and plansAPI: decides what is allowedSystems of record

The API layer is where this is won or lost. It existed before agents, and if it was built properly it needs almost nothing to serve them: it already knows who is asking, what they may see, and what each operation means.

Which is the uncomfortable finding for anyone hoping agents make the old work unnecessary. They make it more valuable. An organisation with clean APIs and a real permission model can put an agent in front of them in weeks. An organisation without them is not slow because it lacks agents. It is slow because the foundation was never built, and adding a model on top makes that more visible, not less.

The part that ages well

Tools will change. The model in production today will be replaced twice before this is old, and the protocol may be replaced too.

What will not change is the division of labour. Judgement in one place, guarantees in the other. Systems that keep those separate can swap the model without touching the rules, and change the rules without retraining anything. Systems that mix them have to rebuild both every time either moves.

We wrote recently that AI solved syntax but not judgement. This is the architectural version of the same finding. The best systems being built with agents are not the ones that replaced their software. They are the ones that knew which half was worth keeping.

Keep reading