How the Parts of an AI Application Depend on Each Other
The boxes in an architecture diagram are the easy part. What matters is what each part establishes, and what the next part is assuming was already settled.
AI systems get drawn as boxes with arrows. Somebody adds a box for retrieval, one for the model, one for tools, one for logging, and the diagram looks complete.
The boxes are the easy part. Which ones a given application needs depends on the job it does, and plenty of useful systems have three of them. What the diagram never shows is the thing that actually decides how the system behaves: what each arrow is carrying, and what the box at the other end believes it received.
What this page is for
The detailed pages explain individual mechanisms. This one is about where responsibility transfers between them, and which part to inspect when something goes wrong.
That is a different question from what the parts are, and it is not answerable from inside any one of them. Each component can be designed well, tested on its own terms, and correct by its own definition, while the system built from them produces a wrong answer that nobody's component is responsible for.
What the model contributes
The model generates candidate outputs. The surrounding system supplies context, validates contracts, controls effects, preserves state, and records and evaluates behaviour.
Not every application does all of those. A system that summarises a document and shows the result to a person supplies context and does little else, and that is a complete architecture for that job.
What is worth being exact about is the model's specific contribution. It produces a candidate. Generation does not establish that the candidate is true, does not authorize anything, and does not establish that the task was accomplished. Those are three separate things that three other mechanisms may or may not be doing, and the habit of saying the model decides or knows quietly assigns them to it.
The rest of the system is not a wrapper around that capability. It is where those other questions get answered, when the job requires answering them.
- The model
What the model contributes
- A candidate output
What the surrounding system may do
- Supply context
- Validate contracts
- Control effects
- Preserve state; record and evaluate behaviour
- The model
The model generates candidate outputs. The surrounding system supplies context, validates contracts, controls effects, preserves state, and records and evaluates behaviour.
The assumption that crosses each boundary
Here is the principle the rest of this page is an application of.
A downstream component should not assume a stronger guarantee than the upstream component actually provides.
It sounds obvious stated baldly. It is easy to violate, because the violation is invisible: the upstream component returns something with a name, and the name suggests more than the thing establishes.
Retrieved suggests relevant and current. It establishes that a selection process returned something. Validated suggests correct. It usually establishes that a shape matched. Authorized suggests appropriate. It establishes that a rule permitted it. Stored suggests available and true. It establishes that a write succeeded.
Each of those is a real guarantee and worth having. None of them is the stronger guarantee its name implies.
What the name suggests
- Retrieved: relevant and current
- Validated: correct
- Authorized: appropriate
- Stored: available and true
What it establishes
- A selection process returned something
- A shape matched
- A rule permitted it
- A write succeeded
Each is a real guarantee. None is the stronger guarantee its name implies.
What each responsibility establishes
This table is not a stack and not an ordering, and nothing in it ranks anything. It is a list of the claims worth checking at each boundary, for whichever of these a given system actually has.
| Responsibility | Establishes | Does not by itself establish |
|---|---|---|
| Generation | A candidate output exists | That it is true, permitted, or sufficient |
| Retrieval | Material was selected and supplied | That it is current, authoritative, complete, or supports the claim made from it |
| Instruction | Behaviour was shaped toward something | That the output complied |
| Schema validation | The output has the expected form | That its meaning is correct |
| Authorization | A rule permitted this operation | That performing it achieves the goal |
| Tool execution | An operation ran and returned | That the intended change happened |
| State persistence | A value was written | That it is still current |
| Recorded signals | Something can be investigated later | That the behaviour was acceptable |
| Evaluation | Behaviour met a stated expectation | That the expectation was the right one, or that this justifies every exposure |
Read down the right-hand column and the architecture of a specific system starts to become a set of questions rather than a diagram. For each row that applies: who checks the thing in the right-hand column, and where?
A request, traced
Here is an illustrative walk through one request. It is a constructed example, not a description of a particular system, and a real application may skip several of these steps or repeat others.
A user asks for something. The application selects material it judges relevant and supplies it with the request. The model returns a candidate. If downstream software needs a particular shape, a check confirms the shape. If the candidate proposes an action with a real effect, a separate decision determines whether that action may proceed. If it proceeds, something needs to confirm the effect rather than the response. State is updated where the work continues later. Signals are preserved where the behaviour may need investigating. The result reaches a person or another system.
Now watch one assumption cross wrongly.
The selection step returns a document that is six months out of date. Nothing in the pipeline is broken by that. The model conditions on it and still produces a fluent, specific, well-formed answer. The schema check passes, because the shape is right. The policy check passes, because the operation is permitted. The tool call succeeds, because the API accepted it. The state update succeeds. The trace is complete and accurate.
And the effect is wrong, because the subsequent schema, policy and tool checks in this example were not designed to test whether the supplied context was current. A stale premise can survive several locally successful checks when those checks are testing different properties.
Retrieval returns a document six months out of date
The model answers fluently and specifically
The schema check passes: the shape is right
The policy check passes: the operation is permitted
The tool call and the state update succeed; the trace is complete
The effect is wrong
None of those checks tested whether the context was current.
Local success is not system success
That example is the general case, and it is the strongest reason this page exists.
Each part can satisfy its own narrow contract while the workflow as a whole produces the wrong result. Retrieval returned documents. The model returned parseable output. The schema matched. The API returned success. The state was written. The log entry exists. Every one of those is a true local fact, and none of them is the outcome anyone wanted.
Retrieval returned documents
Not that they are current, authoritative or complete
The model returned parseable output
Not that it is true, permitted or sufficient
The schema matched
Not that its meaning is correct
The API returned success
Not that the intended change happened
The state was written
Not that it is still current
The log entry exists
Not that the behaviour was acceptable
This is also why the end-to-end behaviour needs judging on its own terms rather than inferred from component health. A dashboard of green components is a claim about components.
There is a second cost, and it is organisational rather than technical. Where responsibility at a boundary is unclear, each component can be improved against its own measures without anything addressing the boundary itself. Local component metrics can improve while end-to-end behaviour stays the same, if no check covers the boundary assumption that is failing.
Which seam to inspect
The useful version of that observation is diagnostic rather than statistical. A seam is worth inspecting when one part is assuming something the previous part never established.
That converts a vague question into a short list. Was the material actually current, or only retrieved? Did anything check meaning, or only shape? Did anything confirm the effect, or only the response? Was the state still true when it was read, or only present? Where a person was involved, were they positioned to judge, or only asked to approve?
Each of those points at a specific mechanism with a page of its own. What this page adds is knowing which one to open.
Only established
- Retrieved
- The shape
- The response
- Present
- Asked to approve
Assumed downstream
- Current
- The meaning
- The effect
- Still true when it was read
- Positioned to judge
Each of those points at a specific mechanism with a page of its own.
Where these responsibilities actually live
A boundary in a diagram is not a boundary in the software.
Several of these responsibilities can live in one function. Selecting context, calling the model and checking the result can be forty lines in one file, and that file is a perfectly reasonable architecture for a small system. The responsibilities are still distinct, and the questions above still apply to it.
The reverse happens too. One responsibility can be spread across a library, a service and a manual step. When a conceptual responsibility spans several implementation surfaces like that, ownership of it may need to be assigned explicitly rather than inferred from where the code sits.
So the diagram describes what the system is responsible for, not how it is deployed. A conceptual box does not imply a separately deployed service, and a single code path may still contain several of these boundaries.
Several responsibilities, one function
- Select context, call the model, check the result: forty lines in one file
- Still distinct responsibilities
One responsibility, several places
- A library, a service and a manual step
- Ownership may need assigning explicitly
A conceptual box does not imply a separately deployed service.
What crosses each boundary varies as much as where it lives: a function argument, a structured object, a row in a database, a queue message, text in a prompt, a person deciding. Making the dependency explicit does not require making it a formal contract. An ordinary function call with a well-chosen name can carry a boundary perfectly well, provided what it carries is understood.
It is not a pipeline
The walk above reads as a sequence, which is a property of prose rather than of systems.
Real applications retrieve more than once and sometimes not at all, call no tools, branch on what came back, retry, stop and ask a person, do deterministic work between model calls, or finish at generation with nothing further. A fixed order is one possible shape rather than the definition of the architecture, and any ordering presented as the default is answering a question about someone else's system.
Replacing the model
Explicit boundaries make a component easier to change. It is worth being careful about how much easier.
Models differ in context size, in how they take tool definitions, in output tendencies, in latency, in modality support, in provider interface and in refusal behaviour. A clean boundary reduces coupling to any of these, and it does not make the model a drop-in part. The work after a swap is usually smaller and rarely zero, and calling it interchangeable sets an expectation the next migration will correct.
What this changes
When the next architecture diagram arrives, the components are the part everyone will discuss. Ask about the arrows instead.
For each one: what did the thing on the left actually establish, and what is the thing on the right treating as settled? Where those two differ, you have found either a gap worth closing or a check somebody already wrote. Both are worth knowing about, and neither is visible from the boxes.
Where this helps, and where it stops
- What it is
- An explainer of how the responsibilities in an AI application depend on each other, and what crosses each boundary between them.
- What it does not guarantee
- A stack, a reference architecture, a definition of any individual mechanism, or a guide to deployment topology.
- When the distinction matters
- Something went wrong and every component looks like it did its job.