Skip to main content
Chapter 3 Prompt Engineering Mastery

Crafting Effective System Prompts

20 min read Lesson 9 / 28

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:

  1. Role and persona — Who Claude is in this context
  2. Capabilities and scope — What it should and should not do
  3. Output format — How responses should be structured
  4. 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.