Lesson 02
Anatomy of a prompt that works
The five pieces that separate an amateur prompt from a professional one: role, context, instruction, examples, and format.
The (unofficial but useful) formula
After reading hundreds of prompts that work in production, most share this shape:
[ROLE] → who you are, model
[CONTEXT] → what this is about
[INSTRUCTION] → what I want you to do
[EXAMPLES] → what a good output looks like
[FORMAT] → how to return it
You don’t always need all five. But when something is failing, the missing piece is always on this list.
1. Role — the system
The system pins down who the model is. It is the piece with the most leverage.
const res = await client.messages.create({
model: "claude-opus-4-7",
max_tokens: 500,
system: "You are a sharp, concise British literary critic. You write in British English, not American.",
messages: [
{ role: "user", content: "Review *One Hundred Years of Solitude* in 80 words." },
],
});
One sentence in system changes tone, register, and format without repeating it in every user turn.
2. Context — the data
If the answer depends on information the model cannot know, hand it over explicitly. Don’t make it guess.
const products = [
{ id: 1, name: "Shirt", price: 29.9, stock: 0 },
{ id: 2, name: "Trousers", price: 49, stock: 12 },
];
const res = await client.messages.create({
model: "claude-haiku-4-5",
max_tokens: 300,
messages: [
{
role: "user",
content: `Catalog:\n${JSON.stringify(products, null, 2)}\n\nCustomer question: "Do you have shirts?"`,
},
],
});
3. Instruction — what to do
Most common mistake here: asking for several things at once. If you need three tasks, do them in three prompts or number them.
Return:
1. A one-sentence summary.
2. Three key bullet points.
3. A Twitter-style headline (max 240 chars).
4. Examples — few-shot
If the format is unusual, show it with examples, don’t describe it with words.
“Return it in
key: valueformat” → ambiguous. “Here are 3 examples:” + 3 examples → unambiguous.
You will see this in detail in lesson 3.
5. Format — what the output looks like
If you are going to parse the response in code, force the format:
- JSON → say only JSON, and use assistant prefill (lesson 4).
- Markdown with sections → list the exact sections you expect.
- Plain text → say “no markdown, no bullets”.
Guided exercise
Combine the five pieces to solve this real case:
I want to classify support emails into
bug | billing | feature | other, and have it return the reason in one sentence.
const SYSTEM = `You are a support ticket classifier. \
You always return JSON with two keys: category and reason. \
Allowed categories: bug | billing | feature | other.`;
const EXAMPLES = `
Email: "I'm not receiving the password reset email."
{ "category": "bug", "reason": "broken password recovery flow" }
Email: "How much does the enterprise plan cost?"
{ "category": "billing", "reason": "pricing inquiry" }
`;
async function classify(email: string) {
const res = await client.messages.create({
model: "claude-haiku-4-5",
max_tokens: 200,
system: SYSTEM,
messages: [
{ role: "user", content: `${EXAMPLES}\n\nEmail: "${email}"` },
{ role: "assistant", content: "{" },
],
});
return JSON.parse("{" + res.content[0].text);
}
Hit “Run” in the playground on the right and try your own examples.
Up next
When and how to use zero-shot (no examples) and few-shot (2-5 examples). The gap between them is worth more than any “bigger model”.
Pro challenge
Pro challenge for this lesson
Same idea, no hints, graded by automated tests.
Hard Mode
Hard Mode
Extreme variant of the challenge. Time-bound with extra constraints.