C3 · lesson 1 · 9 min read
System prompts and roles
Use the system parameter for the role and standing rules, keep task data in the user turn, and replace old prefill tricks with clear instructions.
Հայերեն
Official video by Anthropic on YouTube. Pressing play loads it from youtube-nocookie.com. ·open on YouTube
Every Messages API request can carry a system prompt: the instructions that frame the whole conversation before the first user turn. It is where you tell Claude who it is in this application, what rules always apply, and what the output should look like. Getting this layer right removes most of the “why did it answer like that?” surprises.
Where it goes
The system prompt is the top-level system parameter, not a message in the
messages array. It accepts a plain string or an array of text blocks. The array form
lets you attach cache_control to a long, stable prefix so repeated calls reuse it.
import os
import sys
import anthropic
client = anthropic.Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])
SYSTEM = (
"You are the on-call assistant for a platform team that runs Kubernetes on AWS. "
"Your summaries are pasted into the incident channel and read on phones, "
"so keep them under 120 words. "
"State only what the log shows; if the cause is unclear, say so."
)
log_text = sys.stdin.read()
response = client.messages.create(
model="claude-haiku-5-5",
max_tokens=2048,
system=SYSTEM,
messages=[
{
"role": "user",
"content": f"<log>\n{log_text}\n</log>\n\nSummarise this incident: impact, likely cause, next check.",
}
],
)
# Current models can return thinking blocks first, so select by type, not position.
print("".join(b.text for b in response.content if b.type == "text"))
What belongs in the system prompt
Put it in system |
Put it in the user turn |
|---|---|
| The role (“on-call assistant for a platform team”) | The log, plan output or ticket to work on |
| Standing rules (scope, tone, what to do when unsure) | The specific question for this request |
| Output conventions (length, format, language) | Per-request details such as the cluster |
| Context that explains why a rule exists | Content from users or third-party systems |
Two habits from the official guidance do most of the work:
- Give a role. Even one sentence focuses vocabulary, tone and assumptions. “You are the on-call assistant for a platform team” gets you shorter, more operational answers than no role at all.
- Explain the reason behind a rule. “Keep it under 120 words because it is read on phones” generalises better than a bare “be brief”. Claude uses the reason to decide edge cases you didn’t list.
Be explicit about what you want rather than hoping Claude infers it. A useful test: if a new colleague with no context would be confused by your prompt, Claude will be too. Say what to do instead of what not to do (“write flowing prose paragraphs” beats “no markdown”), and use calm language. Shouting “CRITICAL: you MUST” tends to make current models over-apply the rule.
Changing instructions mid-conversation
Editing the top-level system field between turns changes the start of the prompt,
which invalidates the prompt cache for the whole conversation. On supported models
(including Claude Opus 5.5, Sonnet 5.5 and Haiku 5.5, but not Sonnet 5) you can instead
append a message with "role": "system" to messages, right after a user turn. It
applies from that point on and overrides the top-level system for later turns. When
two system messages conflict, the later one wins.
Prefill and sampling parameters: what changed
Older prompts often prefilled the assistant turn (for example starting it with
{) to force JSON or skip a preamble. Starting with the Claude 4.6 models, a prefilled
final assistant turn returns a 400 error. The replacements are:
- Format: structured outputs or a tool with a schema (lessons 5 and 6).
- No preamble: an instruction such as “Respond directly, without an introduction”.
- Continuations: put the cut-off text in the next user message and ask Claude to continue from it.
Current models also reject non-default temperature, top_p and top_k. Steer
behaviour with the prompt and with effort, not with sampling knobs.
Recap
- The system prompt lives in the top-level
systemparameter, as a string or as text blocks that can be cached. - Put the role, standing rules and output conventions there, and give reasons for rules.
- Task data and anything untrusted goes in the user turn, never in
system. - Mid-conversation
role: "system"messages change instructions without breaking the cache. - Prefill is rejected on current models; use instructions, structured outputs or tools.
$ ./try-it.sh
Try it: an incident-summary bot with a real system prompt
- Install the SDK (
pip install anthropic) and exportANTHROPIC_API_KEYin your shell. Never paste the key into the script. - Save the script from this lesson as
summarise.pyand run it with any log excerpt:python summarise.py < incident.log. - Delete the role sentence and the reason behind the length limit from
SYSTEM, run it again, and compare tone and length. - Add
temperature=0.2to the call and note the 400 error that current models return for sampling parameters.
Check yourself
4 questions. Original practice questions, not taken from the real exam.