Write Clear Prompts
What a Prompt Is
A prompt is everything you send to Claude to describe what you want: the system prompt, the user message, any documents or examples, and the conversation history. Earlier lessons focused on how to send prompts with the SDK. This section, Lessons 31–40, focuses on what to write, because the quality of the prompt is the biggest factor in the quality of the answer.
Clear prompting is a practical skill, not a trick. The same principle applies to people: a vague request to a capable new colleague produces a guess, and a clear request produces what you actually need.
The Golden Rule
Anthropic's prompting guidance offers a simple test: show your prompt to a colleague who has minimal context on the task, and ask them to follow it. If they would be confused, Claude will be too.
Claude is highly capable, but it does not know:
- your project, your users, or your company's conventions,
- why you need the output, or what you will do with it,
- what "good" looks like for this task, unless you say so, or
- anything you have not written down.
Every clarity technique in this lesson follows from closing those gaps.
Principle 1: Be Explicit About the Task
State exactly what you want done. Do not leave Claude to infer the task from a topic.
Vague: Python decorators.
Clear: Explain what a Python decorator is to a developer who knows functions but
has never used decorators. Include one example that times how long a
function takes to run.
The clear version specifies the action (explain), the audience (knows functions, new to decorators), and a concrete deliverable (one timing example).
Ask Explicitly for Extra Effort
If you want a thorough, ambitious, or comprehensive result, say so. Anthropic's guidance notes that "above and beyond" behavior should be requested explicitly rather than expected from a short prompt:
Build a contact form page. Include validation, helpful error messages, accessible labels,
and a confirmation state after submission. Go beyond a minimal version.
Principle 2: Specify the Output
Describe what the answer should look like: its format, length, structure, and level of detail.
| Aspect | Example instruction |
|---|---|
| Format | "Answer as a numbered list." / "Return a Markdown table with columns Name, Purpose, Example." |
| Length | "Use at most 3 sentences." / "About 200 words." |
| Structure | "Start with a one-sentence summary, then give the details." |
| Detail level | "Assume the reader is a beginner; define technical terms." |
| Exclusions | "Return only the code, with no explanation." |
Why length deserves explicit attention: current Claude models have a more concise, direct communication style than earlier models. If you need a long, detailed answer, ask for it. If you need a very short one, ask for that too. Do not rely on max_tokens to control length; it only cuts responses off (Lesson 13).
Principle 3: Explain Why
Giving the reason behind an instruction helps Claude apply it intelligently, including in situations your instruction did not anticipate.
Without reason: Do not use abbreviations.
With reason: Do not use abbreviations, because this text will be translated
automatically and the translation tool handles abbreviations poorly.
With the reason, Claude understands the real goal, which is translation-friendly text. It may also avoid other things that hurt translation, such as slang or idioms, without being told. The documentation describes this directly: Claude can generalize from the explanation.
Principle 4: Say What to Do, Not Only What to Avoid
Positive instructions are clearer than prohibitions. "Do not do X" leaves open what to do instead.
| Instead of | Try |
|---|---|
| "Don't use Markdown." | "Write your answer as plain paragraphs of prose." |
| "Don't be too technical." | "Explain in everyday language, as you would to a non-programmer." |
| "Don't write long answers." | "Answer in at most two sentences." |
Prohibitions are still useful for real boundaries, such as "Never include API keys in examples". When possible, pair them with what you want instead.
Principle 5: Use Steps When Order Matters
When a task has several parts that must happen in order, or all of which must be completed, list them as numbered steps:
Review the function below.
1. Identify any bugs and explain each in one sentence.
2. Suggest a fix for each bug.
3. Rewrite the complete function with all fixes applied.
4. Add a docstring to the rewritten function.
Why it helps: numbered steps make the sequence and the completeness requirement explicit. Claude is much less likely to skip a step, and you can easily check whether each one was done.
Principle 6: Remove Ambiguity
Ambiguous words force Claude to guess. Replace them with specifics:
| Ambiguous | Specific |
|---|---|
| "a short summary" | "a summary of at most 50 words" |
| "the latest version" | "Python 3.13" |
| "clean up this code" | "rename variables to be descriptive and split the function into smaller functions" |
| "make it better" | "make it more persuasive for small-business owners" |
| "recent changes" | "changes made after 1 October 2026" |
Before and After: A Complete Example
Before:
Review my code.
After:
You are reviewing a pull request for a Django project used by about 500 students.
Review the view function below for security and correctness. This project has had
problems with unauthorized access, so prioritize those.
<code>
{code}
</code>
1. List any security problems first, then correctness problems.
2. For each problem, give the line, a one-sentence explanation, and a fix.
3. If you find no problems in a category, say "None found" for that category.
Keep the review under 250 words. Use a Markdown list.
The improved prompt adds:
- context: a Django project with 500 students,
- the reason for the priority: past unauthorized-access problems,
- clearly separated data in
<code>tags (Lesson 37), - ordered steps,
- behavior for an edge case ("None found"), and
- output constraints: length and format.
Practical Example: A Prompt Builder
Writing clear prompts consistently is easier with structure. This small builder turns the principles into fields, so a prompt cannot be sent without a task, and the other parts are added in a consistent order.
"""prompt_builder.py: assemble clear prompts from explicit parts."""
from dataclasses import dataclass, field
from anthropic import Anthropic
from anthropic.types import Message
@dataclass
class PromptSpec:
task: str # What to do (required)
audience: str = "" # Who the output is for
reason: str = "" # Why it matters
steps: list[str] = field(default_factory=list)
output_format: str = "" # Format and length requirements
data: dict[str, str] = field(default_factory=dict) # Tag name -> content
def render(self) -> str:
if not self.task.strip():
raise ValueError("A prompt needs a task.")
parts = []
for tag, content in self.data.items(): # Data first (Lesson 18)
parts.append(f"<{tag}>\n{content}\n</{tag}>")
parts.append(self.task)
if self.audience:
parts.append(f"Audience: {self.audience}")
if self.reason:
parts.append(f"Why this matters: {self.reason}")
if self.steps:
parts.append("\n".join(f"{n}. {step}" for n, step in enumerate(self.steps, start=1)))
if self.output_format:
parts.append(f"Output format: {self.output_format}")
return "\n\n".join(parts)
def get_text(message: Message) -> str:
return "".join(block.text for block in message.content if block.type == "text").strip()
if __name__ == "__main__":
spec = PromptSpec(
task="Explain what the function below does and suggest one improvement.",
audience="Beginner Python students who know loops but not comprehensions.",
reason="Students will use this explanation to learn idiomatic Python.",
steps=[
"Explain the function's purpose in one sentence.",
"Walk through the loop line by line.",
"Rewrite it using a list comprehension and explain the change.",
],
output_format="Markdown, under 200 words, with the rewritten code in a code block.",
data={"code": "def squares(n):\n result = []\n for i in range(n):\n result.append(i * i)\n return result"},
)
prompt = spec.render()
print(prompt, "\n" + "=" * 60)
reply = Anthropic().messages.create(
model="claude-opus-5-5",
max_tokens=2048,
messages=[{"role": "user", "content": prompt}],
)
print(get_text(reply))
The rendered prompt:
<code>
def squares(n):
result = []
for i in range(n):
result.append(i * i)
return result
</code>
Explain what the function below does and suggest one improvement.
Audience: Beginner Python students who know loops but not comprehensions.
Why this matters: Students will use this explanation to learn idiomatic Python.
1. Explain the function's purpose in one sentence.
2. Walk through the loop line by line.
3. Rewrite it using a list comprehension and explain the change.
Output format: Markdown, under 200 words, with the rewritten code in a code block.
How It Works
PromptSpecmakes each principle a field: task, audience, reason, steps, output format, and data. Writing a prompt becomes filling in a checklist.render()refuses an empty task, so a prompt always has a clear action.- Data comes first, wrapped in tags, followed by the instructions. This follows the "long data before the question" guidance (Lessons 18 and 33).
- Steps are numbered automatically with
enumerate(..., start=1). - Optional parts are included only when provided, so short prompts stay short.
The task says "the function below", but the code appears above it. Exercise 3 asks you to fix this kind of inconsistency. Reading your rendered prompts with fresh eyes catches such mistakes.
Common Mistakes
Writing a Topic Instead of a Task
What happens: "Python decorators" produces a generic overview that may not match what you need.
Fix: state the action, the audience, and the deliverable.
Assuming Claude Knows Your Context
What happens: answers follow general conventions instead of yours.
Fix: include the relevant context: project, users, constraints, and purpose (Lesson 33).
Relying Only on Prohibitions
What happens: "don't do X" is followed, but the alternative Claude chooses is not what you wanted.
Fix: state the desired behavior positively.
Vague Quality Words
What happens: "better", "short", and "clean" mean different things to different readers.
Fix: replace them with measurable or concrete criteria.
Packing Many Unrelated Tasks into One Prompt
What happens: some tasks get detailed answers and others are skipped.
Fix: use numbered steps for related parts, or split unrelated tasks into separate requests or turns (Lesson 28).
Best Practices
- Apply the colleague test before sending important prompts.
- State the task, audience, and deliverable explicitly.
- Specify format and length, and request extra depth or brevity when you need it.
- Explain the reasons behind important instructions.
- Phrase instructions positively, and keep prohibitions for real boundaries.
- Number the steps when order or completeness matters.
- Replace vague words with concrete criteria.
- Iterate: compare outputs, adjust the prompt, and test again (Lesson 39).
Exercise
- Rewrite each vague prompt into a clear one: "Write about SQL joins.", "Make my email better.", "Give me some project ideas."
- Take one of your rewritten prompts and add a reason to one of its instructions. Compare Claude's output with and without the reason.
- In the
PromptSpecexample, the task says "the function below", butrender()places the data above the task. Fix the inconsistency in the task text, and explain why reading the rendered prompt helps catch this kind of mistake. - Add an optional
examplesfield toPromptSpecthat renders each example inside<example>tags (Lesson 35).
Step 3: change the task to "Explain what the function above does and suggest one improvement." Reading the final rendered prompt, rather than only the code that builds it, shows exactly what Claude receives. Problems such as wrong references, missing data, or contradictory instructions are easy to miss in code and obvious in the rendered text.
Step 4:
examples: list[str] = field(default_factory=list)
# In render(), before the task:
if self.examples:
rendered = "\n".join(f"<example>\n{example}\n</example>" for example in self.examples)
parts.append(f"<examples>\n{rendered}\n</examples>")
Wrapping each example in <example> tags, and the group in <examples>, helps Claude distinguish examples from instructions and data.