What Belongs in the System Prompt vs the App Layer
The useful split is not “prompting versus code.” It is steering versus enforcement.
Anthropic’s prompt-engineering docs explicitly frame prompt engineering as the place for success criteria you can control through prompting, and they call out role prompting, examples, XML structuring, thinking, and prompt chaining as the prompt-level techniques.1 Anthropic’s own system prompt notes also make the boundary visible: Claude’s web and mobile apps use a system prompt to inject product behavior like the current date and Markdown code snippets, and those updates do not apply to the API.2
That is the key lesson: a system prompt shapes product behavior, while enforcement belongs in the app and server layers.
What belongs in the prompt
Keep the prompt focused on behavior that is meant to be soft and model-facing:
- role or task framing
- tone and style
- output shape
- when to ask clarifying questions
- how cautious the assistant should be
- how to use tools at a high level
Those are the things the model is good at reading as guidance.
What belongs in the app
Anything that must hold even when the model is wrong belongs in code or server policy:
- authorization and tenant scoping
- read versus write permissions
- idempotency and retries
- rate limits and spend ceilings
- validation and invariant checks
- which tools are available in the current session
If breaking the rule would create an incident, the prompt is the wrong place to enforce it.
The MCP spec makes this same point from another angle. MCP servers expose resources and tools, but hosts must obtain explicit user consent before exposing data or invoking tools, and implementors are told to build real consent and authorization flows because the protocol itself cannot enforce them.3 That is the shape of the boundary we want in LLM apps too.
The failure modes are well-known
When teams overuse the system prompt, the breakage usually looks like this:
| Failure mode | What it looks like | Why it happens |
|---|---|---|
| Prompt injection | A retrieved document or user message changes the assistant’s behavior | The model was trusted to interpret untrusted text |
| Insecure output handling | The app executes model-generated SQL, shell, or JSON without validation | Output was treated as authority instead of input |
| Excessive agency | The model can take side effects with broad credentials | The action boundary lived in prose, not policy |
| Prompt drift | A tiny wording change changes a business-critical workflow | Enforcement was mixed into style instructions |
OWASP’s LLM Top 10 covers these failures directly. Prompt injection is the classic instruction-confusion problem. Insecure output handling is what happens when generated output is used downstream without validation. Excessive agency is the moment a model gets more power than the workflow can safely tolerate.456
Why prompt-only systems rot
The reason prompt-only systems feel attractive is also why they rot.
Prompt changes are fast, but they are also opaque. Once you start encoding policy in prose, you get:
- no unit tests for the rule
- no clear owner for the rule
- no obvious rollback story
- no durable audit trail
- no way to prove the rule was enforced before the action
That is how an LLM product becomes hard to debug. The prompt is carrying obligations it cannot actually satisfy.
A practical split that holds up
The split I trust looks like this:
Prompt layer
- what the assistant is for
- how it should sound
- how it should structure answers
- when it should ask for more information
Application layer
- auth, scope, and permissions
- state transitions
- validation and invariants
- retries, quotas, and timeouts
- tool availability and confirmation checks
Server layer
- data access filters
- provenance and freshness
- audit logging
- safe defaults for reads versus writes
This split is less magical than prompt-only design, but it is much easier to reason about after the first incident.
What to migrate first
If your current prompt is overloaded, move the things with operational consequences first:
- permissions
- tool gating
- state transitions
- validation and required fields
- retries and duplicate prevention
Then leave the conversational parts in the prompt. Style is a good prompt use case. Safety and business invariants are not.
The standard
I want a prompt to tell the model how to behave. I want the app to tell the system what is allowed.
That distinction is small in wording and large in consequence. It is the difference between a nice assistant and a system that can be trusted when the model makes a mistake.