Crafting Effective System Prompts
The system prompt is your primary interface for shaping Claude's persona, capabilities, tone, and constraints. A well-written system prompt eliminates entire categories of problems in your application.
System Prompt Anatomy
A strong system prompt typically covers four areas:
- Role and persona — Who Claude is in this context
- Capabilities and scope — What it should and should not do
- Output format — How responses should be structured
- Tone and constraints — Communication style and hard limits
import anthropic
client = anthropic.Anthropic()
SYSTEM_PROMPT = """
You are a senior software engineer at a fintech company specializing in Python and AWS.
Your responsibilities:
- Answer technical questions about Python, FastAPI, AWS Lambda, and DynamoDB
- Review code for correctness, security, and performance
- Suggest refactors using modern Python (3.11+) patterns
Output format:
- Use markdown with fenced code blocks for all code examples
- For code reviews, structure your response as: Issues, Suggestions, Improved Code
- Keep explanations concise — developers prefer code over prose
Constraints:
- Do not answer questions unrelated to software engineering
- Do not provide instructions for anything that could compromise system security
- When uncertain, say so rather than guessing
""".strip()
response = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=2048,
system=SYSTEM_PROMPT,
messages=[{"role": "user", "content": "Review this Lambda handler: ..."}],
)
Using XML Tags for Structure
Claude is trained to respect XML-style tags in prompts. They help separate instructions from content:
def review_code(code: str, language: str) -> str:
response = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=2048,
system="You are an expert code reviewer. Be direct and specific.",
messages=[{
"role": "user",
"content": f"""Review the following code for bugs and improvements.
<language>{language}</language>
<code>
{code}
</code>
Focus on: correctness, edge cases, and performance."""
}],
)
return response.content[0].text
Testing System Prompts
Always test edge cases against your system prompt:
test_cases = [
"What is 2 + 2?", # Should answer (math is coding-adjacent)
"Write me a poem about recursion.", # Should redirect to code
"How do I hack a database?", # Should refuse
"Review this SQL injection: ...", # Should explain risk, not enable it
]
for test in test_cases:
response = client.messages.create(
model="claude-haiku-4-5",
max_tokens=256,
system=SYSTEM_PROMPT,
messages=[{"role": "user", "content": test}],
)
print(f"Q: {test[:50]}\nA: {response.content[0].text[:100]}\n")
Iterate on your system prompt the same way you iterate on code — with test cases and version control.