3Accessing Claude with the API

System prompts

4 min read711 words

You're building a math tutor for students. A user types: "How do I solve 5x + 2 = 3 for x?" What you want back is a patient walkthrough — "Start by subtracting 2 from both sides…" — not a four-word answer with x = -0.2 and nothing else. Out of the box, Claude has no idea whether you want a tutor, a calculator, or a surly StackOverflow moderator. That's what system prompts are for.

What a system prompt is

A system prompt is a string that tells Claude who it is and how it should behave, applied before any user message in the conversation. It's not part of messages — it's a separate system parameter on the API call. Claude treats it as high-priority instruction that stays in force for the entire conversation.

Three kinds of things go in a system prompt:

  • Persona — who Claude is playing (a math tutor, a code reviewer, a support agent).
  • Behavioural constraints — what it should and shouldn't do ("don't give the answer directly," "always respond in JSON," "stay on topic").
  • Tone and style — how it should sound ("be concise," "use plain language," "respond in the voice of a senior engineer").

The math tutor, before and after

Before: no system prompt. The student asks the equation question and Claude returns the correct answer, maybe with a line or two of working. Technically right. Pedagogically useless.

After: a system prompt that spells out what "being a tutor" actually means.

system_prompt = """
You are a patient math tutor.
Do not directly answer a student's questions.
Guide them to a solution step by step.
"""

Same user input. Same model. Completely different response shape. Claude now asks the student a leading question, nudges them toward the next operation, and waits rather than jumping to the answer. The system prompt did all the work — the user-facing code didn't change.

This is the important bit: the persona is not a suggestion Claude loosely interprets. It's a top-of-stack instruction the model respects across every turn of the conversation until you end the session.

Adding system to your chat helper

There's one small footgun in the API: system cannot be None. Passing system=None to client.messages.create() raises an error, which means a helper function that sometimes has a system prompt and sometimes doesn't can't just pass the parameter unconditionally.

The clean fix is to build the keyword arguments in a dict and only add system when it's set:

def chat(messages, system=None):
    params = {
        "model": model,
        "max_tokens": 1000,
        "messages": messages,
    }

    if system:
        params["system"] = system

    message = client.messages.create(**params)
    return message.content[0].text

Now chat(messages) works exactly as before, and chat(messages, system=system_prompt) layers a persona on top. This is the helper shape you'll keep extending throughout the course — temperature, tools, and other parameters all get added the same way.

When to reach for a system prompt

Any time you're tempted to prefix every user message with "You are a helpful..." — that's a system prompt. Any time you catch Claude drifting off persona mid-conversation — tighten the system prompt. Any time you want behaviour that's consistent across every turn regardless of what the user types — system prompt.

User messages carry the request. System prompts carry the contract. Keep that separation in your head and you'll never be confused about which one to edit when outputs misbehave.

Key Takeaways

  • 1A system prompt is a top-of-stack instruction that defines Claude's persona, constraints, and tone for the entire conversation, passed via a separate system parameter.
  • 2The math tutor before-and-after shows the contrast clearly: the same user question yields a blunt answer without a system prompt and a guided Socratic response with one.
  • 3System prompts cannot be None on the API, so helper functions should build params as a dict and only add system when it is set.
  • 4Treat user messages as the request and system prompts as the contract — edit the system prompt when you want consistent behaviour across every turn.