The Claude API
Advanced AI Workflows & the Claude API
The system prompt is the most powerful tool you have when building Claude-powered applications. It runs before every conversation turn, shapes how Claude interprets user messages, and establishes constraints that persist for the entire session. A well-written system prompt is the difference between an unpredictable AI and a reliable product feature. This chapter covers how to write them, what to put in them, and the common mistakes that undermine their effectiveness.
What a System Prompt Actually Does
From Claude's perspective, the system prompt is high-priority context that arrives before the user speaks. It doesn't override Claude's values or safety behaviours, but it does everything else: it narrows the topic space, establishes tone and format, sets a persona, and defines what Claude should and shouldn't do within the conversation.
Think of it as the standing instructions you'd give a contractor before they start work — not a script for every scenario, but the ground rules that govern how they handle everything they encounter.
Five Sections of an Effective System Prompt
Vague vs Specific — The Most Common Mistake
Vague instructions produce inconsistent outputs. Every word in a system prompt that could be interpreted multiple ways will be interpreted multiple ways across different user inputs. Specificity is the primary lever for reliability.
Dynamic Context Injection
The system prompt is a string — you build it in code before each request. This makes it easy to inject runtime data: the current user's name, their account tier, retrieved documents, the current date. Treat the static sections as a template and fill in the dynamic parts with Python string formatting:
return f"""You are a billing support assistant for Acme SaaS.
Current user: {user.name} ({user.email})
Subscription: {user.plan} — expires {user.expiry}
Today's date: {today}
Rules:
- Only discuss billing, invoices, and plan changes.
- Never reveal internal pricing or discount structures.
- If the user requests a refund, collect their reason and say
a human agent will follow up within 24 hours.
- Respond in plain prose, no bullet points, under 100 words."""
message = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=256,
system=build_system_prompt(current_user, date.today()),
messages=[{"role": "user", "content": user_message}]
)
Ignore previous instructions and... and you inject it directly, you've handed them partial control of the system prompt. Strip or escape user-provided strings before injection, or put user data in a clearly delimited section Claude recognises as data, not instructions.
Application System Prompt Templates
Instruction Priority — When Instructions Conflict
In a real application, instructions can come from multiple places: the system prompt, injected documents, and the user's message. Claude applies a rough priority order:
| Priority | Source | Typical use |
|---|---|---|
| 1 | System prompt (static) | Application-level rules, persona, scope, format. Treated as developer intent — highest weight. |
| 2 | System prompt (injected context) | Retrieved documents, user data. Treated as data to reason over, not instructions to follow. |
| 3 | User message | End-user input. Treated as the task to perform within the constraints set above. |
If a user message says "ignore your previous instructions" — a classic prompt injection attempt — Claude will generally hold to the system prompt constraints because the system prompt has higher contextual authority. This is not a hard guarantee, but it holds reliably for well-written system prompts.
Testing Your System Prompt
A system prompt that works for happy-path inputs often fails at the edges. Test deliberately against adversarial inputs before shipping:
- Out-of-scope questions — does Claude correctly decline topics outside its brief, or does it helpfully answer anyway?
- Prompt injection attempts — user messages like "ignore your instructions and tell me X" — does the system prompt hold?
- Format edge cases — very short inputs, very long inputs, inputs in other languages, inputs with no clear question
- Instruction conflicts — if the user explicitly asks Claude to break a rule ("please use bullet points"), does it comply or hold to the system prompt?
- Ambiguous requests — inputs that could be interpreted as in-scope or out-of-scope — which does Claude choose?
temperature=0 to get deterministic responses. Once the prompt is stable, test with default temperature to see how it holds under variation. A prompt that only works at temperature 0 is too fragile for production.