Purrx

System instructions vs the user prompt

Separate the rules that always apply from the request that changes each turn. How Gemini's systemInstruction works and why mixing the two causes bugs.

8 min+25 XPHands-on

A request can carry two kinds of text:

  • The system instruction is the standing brief that applies to every message: who the model is, what format to use, what never to do.
  • The user content is this particular message, and it changes every time.

It's tempting to put both in one string. That works at first, then breaks in confusing ways as the conversation grows.

the separation
await gemini.generateContent({
  contents: "How do I reverse a list?",          // changes every turn
  config: {
    systemInstruction:
      "You are a terse Python tutor. Answer in at most two sentences. " +
      "Always show code before explaining it.",   // stays constant
  },
});

Request 1

System: terse Python tutor, max two sentences
  • User: How do I reverse a list?

Request 2

System: terse Python tutor, max two sentences
  • User: How do I reverse a list?
  • Model: …answer…
  • User: And a string?

Request 3

System: terse Python tutor, max two sentences
  • User: How do I reverse a list?
  • Model: …answer…
  • User: And a string?
  • Model: …answer…
  • User: Can you make it shorter?
Every request carries the same system instruction on top. Only the conversation below it grows.

Why keep them separate

  • It stays in force. In a long chat, the system instruction is sent with every request. Rules buried in the first message lose influence as the history grows.
  • The model gives it more weight. Models are trained to rank system instructions above what the user types. That matters the moment a user tries to talk the model out of your rules.
  • It keeps your code clean. You define your rules once as a constant, instead of gluing them onto every prompt.
Under the hood — Why does the model treat system text as higher priority?

Nothing in the model's design enforces it. A model fresh from has no idea what an instruction is. It only continues text.

The behavior is trained in afterwards. During the model is shown enormous numbers of conversations formatted with these roles, where the correct response consistently follows the system content, including when the user turn argues against it. It learns the pattern statistically, the same way it learns everything else.

Which is exactly why the priority is strong but not absolute. It is a learned tendency, not a permission check. That gap is exactly what exploits, two lessons from now.

Writing one that works

Be specific, and say what to do rather than what not to do. Models follow "answer in one short paragraph" far more reliably than "don't be verbose". The first gives a clear target; the second only rules one thing out.

vague vs specific
"Be helpful and concise and don't make things up.""You are a support agent for an API company.
   Answer in at most 3 sentences.
   If the answer isn't in the provided documentation, reply exactly:
   'I don't have that in the docs.'
   Never invent endpoint names."

What it is not

A system instruction is strong guidance, not a security lock. A determined user can still talk the model out of it, which is the subject of the prompt injection lesson coming up. Anything that must be enforced belongs in your code, not in your prompt.

Key takeaways

  • Put standing rules in systemInstruction and the changing request in contents.
  • Be specific about what to do, and tell the model exactly what to say when it doesn't know.
  • A system instruction is guidance, not security. Enforce rules that really matter in your code.

Sign in to run the exercise

Reading is free. Writing code here needs an account so we have somewhere to keep your Gemini key and the +25 XP you are about to earn.