System Prompts in Spring AI: Templates, Context, and Tests

Spring AI lets you define system prompts as typed templates, pass runtime context into them, and test them without a live model. Here is how to build a reusable setup your team can rely on.

Updated 6 min read

A system prompt in Spring AI is the instruction block sent before the conversation begins, telling the model what role to take, what constraints to respect, and what format to use. Spring AI handles it through a typed template system, so you can parameterize the text, swap values at runtime, and test it without calling a live API. Getting this right once means every assistant built on that template behaves predictably from the first request.

Teams that share AI tooling also need a place to record which version of a prompt is approved, why, and what changed. Tools like fenbs keep those decisions alongside the project so every developer works from the same agreed instructions.

What Spring AI gives you for system prompts

Spring AI uses a PromptTemplate class that accepts a template string and a map of variables. You write the text once with {placeholders}, then supply the actual values at call time. For system-level instructions, the SystemPromptTemplate class works the same way but marks the message with the system role, which OpenAI-compatible models treat differently from user turns.

The separation matters. The system message sets the frame: persona, rules, output format. The user message contains the request. Mixing them into one string makes the frame hard to update without touching the request logic.

How to write a reusable system prompt template

Start with the smallest set of instructions that makes the model useful for your use case. Three sections cover most needs:

  • Role: what the assistant is and who it serves ("You are a code reviewer for a Java team").
  • Rules: what it must always do and what it must never do, stated plainly.
  • Format: the expected structure of each response, especially for automated downstream use.

Avoid writing rules that contradict the user prompt your code will send. Say a downstream step parses JSON from every response; the format rule should be specific: "Respond only with valid JSON. No markdown fences."

Example SystemPromptTemplate in Spring AI
String template = """
    You are a {role} for {teamName}.
    Rules:
    - Respond in US English.
    - Keep answers under {maxWords} words.
    - Never include personally identifiable information.
    Format: plain text, one paragraph.
    """;

SystemPromptTemplate systemPrompt = new SystemPromptTemplate(template);
Message systemMessage = systemPrompt.createMessage(Map.of(
    "role", "pull request reviewer",
    "teamName", "Payments Platform",
    "maxWords", "150"
));

Passing runtime context cleanly

Templates become powerful when runtime facts flow in from the application rather than being hardcoded. Useful runtime variables include the current user's role, the name of the project being processed, environment-specific constraints, and any reference data retrieved from a database before the call.

Keep template variables coarse-grained. A variable called {currentUserRole} is useful. A variable that includes a 2,000-word document pasted inline will push other content out of the context window and make tests hard to read. For long reference material, add it to the user message as a separate UserMessage, not inside the system template.

For context that carries across sessions, such as project rules or standards that do not change between calls, consider loading them from a shared source at startup rather than hard-coding them in the template file. See the guide on system prompt examples for patterns that work across different frameworks.

How to test a system prompt without calling a live model

Spring AI supports a MockChatClient in its test module. Wire it in place of your real ChatClient, supply a canned response, and assert on what the prompt looked like when it left your code. This catches template variable mismatches, encoding problems, and missing placeholders before you pay for API calls.

For behavior tests that need a real model, use a separate test profile that calls a cheap endpoint with a small token limit. Keep a small set of fixed inputs with known expected outputs and compare against them on every significant change to the template. When a response shifts unexpectedly, the test surfaces it before the change reaches production.

Record the test cases alongside the template, not only in the test file. When a teammate adjusts the template later, they need to know what cases the previous version was tuned against. This is separate from understanding system prompt vs user prompt boundaries, which the linked post covers.

Common mistakes when writing Spring AI system prompts

Common mistakes and how to fix them
MistakeWhat goes wrongFix
Putting the role and the rules in the user messageSome models deprioritize system-level instructions in user turnsUse SystemPromptTemplate for the frame; UserMessage for the request
Too many variablesTemplates become hard to read and testKeep to 3-5 variables; move long text to a separate message
No output format ruleDownstream JSON parsers break on markdown-wrapped outputState the exact format once, specifically
Hardcoded team-specific valuesReuse across projects is impossibleParameterize anything project-specific
Single long template for all use casesEdge cases conflict with common casesOne template per assistant persona

Managing prompt versions across a team

A system prompt is a decision. When the team agrees on a rule ("always respond in plain text, never markdown"), that rule belongs in a shared place where anyone who changes it can see who made the call and why. Keeping it only in a template file means the next developer who edits it may not know what the original reasoning was.

Treat the approved template string as you would a configuration constant: version it, review changes, and record the reason for each update. For projects that share prompts across services, a prompt library stored outside any one service lets every team pick up the current approved version.

How fenbs helps

Keep your approved Spring AI prompts in a shared library

fenbs Skills and prompts holds the current approved instructions alongside the project context that shaped them. Add the template text, the rationale, and any test cases that define it. Every connected AI app on the team reads from the same record, so new services start from the agreed version rather than a copy someone forked last month.

Create a free account

Free for one person · No credit card · Works with Claude, ChatGPT, Cursor and more

How to do this with fenbs

  1. Create a free account and open a project for the service or team that owns the prompts.
  2. Add the current approved system prompt text to Skills and prompts with the model it targets, the variables it expects, and the test cases it was checked against.
  3. Record the decisions that shaped it in Decisions and rules: "always respond in plain text", "role must match the calling user's actual permission level". These appear first when any connected assistant reads the project context.
  4. When a teammate proposes a change, update the plan on the task and record the outcome as a decision. Link the old version as a note so the reasoning is never lost.
  5. Connect your AI assistant over MCP from Integrations so it can read the current instructions and lessons before generating a draft update.

Questions people ask.

What is the difference between SystemPromptTemplate and PromptTemplate in Spring AI?

Both accept a template string and a variable map. SystemPromptTemplate marks the resulting message with the system role, which is processed separately by OpenAI-compatible models. PromptTemplate creates a plain user-role message by default.

Can I load a system prompt from a file in Spring AI?

Yes. Pass a Spring Resource to the SystemPromptTemplate constructor instead of a raw string. This keeps long templates out of Java source files and makes them easier to diff in version control.

How many variables should a system prompt template have?

Aim for three to five. More than that usually means the template is doing too many jobs. Split complex setups into a persona template and a separate context-injection step.

How do I test a Spring AI system prompt without a live API key?

Use the MockChatClient from the Spring AI test module. Supply a canned response, then assert on the messages that were sent to the client. This catches template errors without any API cost.

Where should team-wide prompt decisions be stored?

Store them outside the codebase where non-developers can read them too, and where the reasoning is recorded alongside the text. A shared project tool that connects to your AI apps keeps the approved version accessible without a code review.

Start with one thing.

Free for one person · No credit card · Works with Claude, ChatGPT, Cursor and more

There is nothing to set up first. Write one line and you’ve started.