Lesson 3.1: Anatomy of a Good Prompt
Duration: 50 minutes
Learning Objectives
By the end of this lesson, you will be able to:
- Identify the key components of an effective prompt
- Write clear and specific instructions for LLMs
- Structure prompts for consistent results
- Avoid common prompting mistakes
- Apply prompting principles to real-world tasks
Introduction
You have learned how LLMs work - they predict text based on patterns from training data. But how do you communicate with them effectively? The answer is prompt engineering: the skill of writing inputs that get the outputs you need.
A prompt is more than just a question. It is a set of instructions, context, and constraints that guide the model toward your desired output. In this lesson, you will learn what makes a prompt effective and how to structure your prompts for success.
The Core Components of a Prompt
Every effective prompt contains some combination of these elements:
┌─────────────────────────────────────────────────────────┐
│ Anatomy of a Prompt │
├─────────────────────────────────────────────────────────┤
│ 1. CONTEXT │ Background information the model │
│ │ needs to understand your request │
├──────────────────┼──────────────────────────────────────┤
│ 2. INSTRUCTION │ The specific task you want the │
│ │ model to perform │
├──────────────────┼──────────────────────────────────────┤
│ 3. INPUT DATA │ The content the model should │
│ │ process or work with │
├──────────────────┼──────────────────────────────────────┤
│ 4. OUTPUT │ How you want the response │
│ FORMAT │ structured and formatted │
├──────────────────┼──────────────────────────────────────┤
│ 5. CONSTRAINTS │ Rules, limitations, or things │
│ │ to avoid │
└─────────────────────────────────────────────────────────┘
Not every prompt needs all five components, but knowing them helps you craft better prompts.
Example: Breaking Down a Prompt
Let us see these components in action:
const prompt = `
You are a senior software engineer reviewing code.
Analyze the following TypeScript function for potential issues:
\`\`\`typescript
function calculateTotal(items: any[]) {
let total = 0;
for (let i = 0; i <= items.length; i++) {
total += items[i].price;
}
return total;
}
\`\`\`
List each issue you find with:
1. The problem
2. Why it is a problem
3. How to fix it
Focus on bugs, type safety, and best practices.
Do not suggest style changes unless they affect functionality.
`;
Breaking it down:
| Component | Text |
|---|---|
| Context | "You are a senior software engineer reviewing code." |
| Instruction | "Analyze the following TypeScript function for potential issues" |
| Input Data | The code block with the function |
| Output Format | "List each issue... 1. The problem, 2. Why..., 3. How to fix" |
| Constraints | "Focus on bugs... Do not suggest style changes..." |
Principle 1: Be Specific, Not Vague
The most common mistake is being too vague. LLMs have no way to read your mind - they need explicit instructions.
Bad vs Good Examples
Bad: Vague prompt
Write about TypeScript.
What about TypeScript? An introduction? Advanced features? A comparison with JavaScript? The model has to guess.
Good: Specific prompt
Write a 200-word introduction to TypeScript for JavaScript developers.
Explain what TypeScript adds to JavaScript and list 3 key benefits.
Use a practical, conversational tone.
Bad: Ambiguous request
Improve this code.
Good: Clear request
Refactor this code to:
1. Use TypeScript strict types instead of 'any'
2. Handle potential null values
3. Add JSDoc comments for each function
The Specificity Checklist
Before sending a prompt, ask yourself:
- Is the task clearly defined?
- Have I specified the format I want?
- Did I provide enough context?
- Are there constraints the model should follow?
- Would someone else understand exactly what I want?
Principle 2: Provide Context
LLMs do not know your specific situation. Give them the context they need to provide relevant answers.
Context Types
Domain context: What field or area are you working in?
// Without context
const prompt1 = 'What is a model?';
// With domain context
const prompt2 =
'In machine learning, what is a model? Explain for someone learning AI development.';
Situation context: What is the specific scenario?
// Without situation
const prompt1 = 'How should I handle errors?';
// With situation
const prompt2 = `
I'm building a REST API with Express and TypeScript.
When a user requests a resource that doesn't exist,
how should I handle and return the error?
Include the HTTP status code and response format.
`;
Audience context: Who is this for?
// Without audience
const prompt1 = 'Explain closures in JavaScript.';
// With audience
const prompt2 = `
Explain closures in JavaScript to a developer who knows Python
but is new to JavaScript. Use Python analogies where helpful.
`;
Principle 3: Structure Your Prompts
Well-structured prompts are easier for models to parse and follow. Use formatting to your advantage.
Use Clear Sections
const structuredPrompt = `
## Task
Summarize the following customer feedback.
## Input
"I've been using your app for 3 months. The interface is clean
and intuitive, but the sync feature is unreliable. Sometimes my
data doesn't appear on other devices for hours. Customer support
was helpful when I reported it though."
## Requirements
- Extract the main sentiment (positive, negative, mixed)
- List specific praise points
- List specific complaint points
- Suggest one actionable improvement
## Output Format
Return a JSON object with keys: sentiment, praise, complaints, suggestion
`;
Use Delimiters for Input Data
When your prompt includes data to process, clearly separate it:
// Using triple quotes
const prompt1 = `
Translate the following text to Spanish:
"""
Hello, how are you today? I hope you're having a great day.
"""
`;
// Using XML-style tags
const prompt2 = `
Analyze the sentiment of this review:
<review>
The product arrived on time and works exactly as described.
Very happy with my purchase!
</review>
`;
// Using markdown code blocks
const prompt3 = `
Find bugs in this code:
\`\`\`typescript
const data = fetchData();
console.log(data.name);
\`\`\`
`;
Use Numbered Steps for Complex Tasks
const multiStepPrompt = `
Process the user's message in the following steps:
1. Identify the language of the message
2. Detect the sentiment (positive, negative, neutral)
3. Extract any mentioned product names
4. Summarize the main point in one sentence
User message: "${userMessage}"
Respond with each step labeled clearly.
`;
Principle 4: Specify the Output Format
Tell the model exactly how you want the response formatted. This is crucial for programmatic processing.
Requesting JSON Output
import Anthropic from '@anthropic-ai/sdk';
const anthropic = new Anthropic();
const prompt = `
Extract the following information from this text and return as JSON:
Text: "John Smith, age 32, works at TechCorp as a Senior Developer.
His email is john.smith@techcorp.com and he's been there for 5 years."
Return a JSON object with these exact keys:
- name (string)
- age (number)
- company (string)
- position (string)
- email (string)
- yearsAtCompany (number)
Return ONLY the JSON, no additional text.
`;
const response = await anthropic.messages.create({
model: 'claude-sonnet-4-20250514',
max_tokens: 200,
messages: [{ role: 'user', content: prompt }],
});
const data = JSON.parse(response.content[0].text);
console.log(data);
// { name: "John Smith", age: 32, company: "TechCorp", ... }
Requesting Specific Formats
Bullet points:
List 5 benefits of TypeScript. Use bullet points, one benefit per line.
Numbered list:
Explain the steps to set up a Node.js project. Number each step.
Table format:
Compare React, Vue, and Angular. Format as a markdown table with columns:
Framework | Learning Curve | Performance | Ecosystem
Code only:
Write a TypeScript function that validates email addresses.
Return ONLY the code, no explanations.
Principle 5: Use Constraints Wisely
Constraints tell the model what NOT to do. They are essential for consistent, safe outputs.
Length Constraints
// Word limit
const prompt1 = 'Summarize this article in exactly 50 words.';
// Sentence limit
const prompt2 = 'Explain recursion in 2-3 sentences.';
// Character limit (useful for UI constraints)
const prompt3 = 'Write a product description under 150 characters.';
Content Constraints
// What to avoid
const prompt1 = `
Explain this code.
Do NOT include information about unrelated topics.
Do NOT provide code examples unless asked.
`;
// What to include/exclude
const prompt2 = `
Review this essay for grammar only.
Do NOT comment on the content or arguments.
Do NOT rewrite sentences, just point out errors.
`;
Style Constraints
// Tone and style
const prompt = `
Write a welcome email for new users.
Constraints:
- Use a friendly, professional tone
- Avoid jargon and technical terms
- Do not use exclamation marks excessively
- Keep paragraphs to 2-3 sentences maximum
`;
Common Prompting Mistakes
Mistake 1: Too Many Instructions at Once
Bad:
Analyze this code, find bugs, suggest improvements, add comments,
refactor for readability, optimize for performance, and write tests.
Better: Break into separate prompts or prioritize:
Analyze this code for bugs. List each bug with its line number
and how to fix it. Focus only on bugs that would cause runtime errors.
Mistake 2: Contradictory Instructions
Bad:
Write a detailed explanation in one sentence.
Better:
Write a comprehensive explanation in 3-4 sentences.
or
Write a one-sentence summary capturing the key point.
Mistake 3: Assuming Knowledge
Bad:
Use the standard format for the API response.
Better:
Format the API response as JSON with these fields:
- success: boolean
- data: object or null
- error: string or null
Mistake 4: No Examples When Needed
For subjective or ambiguous tasks, examples clarify expectations:
Without example:
Write a catchy headline for this article.
With example:
Write a catchy headline for this article.
Style example: "10 TypeScript Features You Didn't Know Existed"
The headline should be specific, use numbers if relevant,
and promise value to the reader.
Practical Example: Building a Prompt Step by Step
Let us build a prompt for a code documentation generator:
Step 1: Define the Task
let prompt = `
Generate documentation for the following TypeScript function.
`;
Step 2: Add Input Format
prompt = `
Generate documentation for the following TypeScript function.
\`\`\`typescript
${functionCode}
\`\`\`
`;
Step 3: Specify Output Format
prompt = `
Generate documentation for the following TypeScript function.
\`\`\`typescript
${functionCode}
\`\`\`
Generate JSDoc-style documentation that includes:
- @description: A clear explanation of what the function does
- @param: For each parameter, include name, type, and description
- @returns: What the function returns and when
- @throws: Any errors the function might throw
- @example: A usage example
`;
Step 4: Add Constraints
prompt = `
Generate documentation for the following TypeScript function.
\`\`\`typescript
${functionCode}
\`\`\`
Generate JSDoc-style documentation that includes:
- @description: A clear explanation of what the function does
- @param: For each parameter, include name, type, and description
- @returns: What the function returns and when
- @throws: Any errors the function might throw
- @example: A usage example
Constraints:
- Keep descriptions concise but complete
- Use technical terms appropriate for developers
- The example should be runnable code
- Do not include obvious information (e.g., "name is the name parameter")
Return ONLY the JSDoc comment block, nothing else.
`;
Full Implementation
import OpenAI from 'openai';
const openai = new OpenAI();
async function generateDocs(functionCode: string): Promise<string> {
const prompt = `
Generate documentation for the following TypeScript function.
\`\`\`typescript
${functionCode}
\`\`\`
Generate JSDoc-style documentation that includes:
- @description: A clear explanation of what the function does
- @param: For each parameter, include name, type, and description
- @returns: What the function returns and when
- @throws: Any errors the function might throw
- @example: A usage example
Constraints:
- Keep descriptions concise but complete
- Use technical terms appropriate for developers
- The example should be runnable code
- Do not include obvious information
Return ONLY the JSDoc comment block, nothing else.
`;
const response = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [{ role: 'user', content: prompt }],
temperature: 0.3, // Lower temperature for consistent output
});
return response.choices[0].message.content || '';
}
// Usage
const code = `
async function fetchUserById(id: string, includeProfile: boolean = false): Promise<User | null> {
const response = await fetch(\`/api/users/\${id}\`);
if (!response.ok) {
if (response.status === 404) return null;
throw new Error(\`Failed to fetch user: \${response.statusText}\`);
}
const user = await response.json();
if (includeProfile) {
user.profile = await fetchUserProfile(id);
}
return user;
}
`;
const docs = await generateDocs(code);
console.log(docs);
Exercises
Exercise 1: Improve the Prompt
This prompt gets inconsistent results. Improve it using the principles from this lesson.
Original:
Tell me about this error.
Solution
I encountered the following error in my TypeScript application:
\`\`\`
TypeError: Cannot read property 'map' of undefined
at processItems (app.ts:42:15)
at main (app.ts:10:3)
\`\`\`
Please help me understand:
1. What this error means
2. Common causes for this error
3. How to fix it
Context: I'm calling an API and trying to process the response data.
Why it's better:
- Includes the actual error message
- Provides context about where it occurs
- Specifies what information you need
- Gives relevant background
Exercise 2: Write a Structured Prompt
Create a prompt that asks an LLM to generate test cases for a function. The function signature is:
function validatePassword(password: string): { valid: boolean; errors: string[] };
Solution
Generate test cases for the following TypeScript function:
\`\`\`typescript
function validatePassword(password: string): { valid: boolean; errors: string[] }
\`\`\`
The function validates passwords with these rules:
- Minimum 8 characters
- At least one uppercase letter
- At least one lowercase letter
- At least one number
- At least one special character (!@#$%^&*)
Generate test cases covering:
1. Valid passwords (should return { valid: true, errors: [] })
2. Passwords that fail each individual rule
3. Passwords that fail multiple rules
4. Edge cases (empty string, very long passwords, special characters)
Output format: For each test case, provide:
- Test name (descriptive)
- Input password
- Expected output
Return as a TypeScript array of test objects.
Exercise 3: Identify Components
Identify the Context, Instruction, Input, Output Format, and Constraints in this prompt:
You are a helpful assistant that translates marketing copy.
Translate the following product description from English to Spanish:
"Introducing our revolutionary smart water bottle. Track your hydration,
set reminders, and sync with your fitness apps. Stay healthy, stay hydrated."
Requirements:
- Maintain the marketing tone and enthusiasm
- Keep the translation under 60 words
- Do not translate brand names or technical terms
- Return only the Spanish translation
Solution
| Component | Text |
|---|---|
| Context | "You are a helpful assistant that translates marketing copy." |
| Instruction | "Translate the following product description from English to Spanish" |
| Input Data | The quoted product description |
| Output Format | "Return only the Spanish translation" |
| Constraints | "Maintain the marketing tone...", "Keep under 60 words...", "Do not translate brand names..." |
Key Takeaways
- Good prompts have structure: Context, Instruction, Input, Output Format, and Constraints
- Be specific: Vague prompts get vague results
- Provide context: The model does not know your situation unless you explain it
- Use formatting: Delimiters, sections, and numbered steps improve clarity
- Specify output format: Especially important for programmatic processing
- Add constraints: Tell the model what to avoid, not just what to do
Resources
| Resource | Type | Description |
|---|---|---|
| OpenAI Prompt Engineering Guide | Documentation | Official best practices from OpenAI |
| Anthropic Prompt Design | Documentation | Claude-specific prompting techniques |
| Learn Prompting | Tutorial | Free comprehensive course on prompting |
| Prompt Engineering Guide | Reference | Extensive collection of techniques |
Next Lesson
You have learned the fundamentals of writing good prompts. In the next lesson, you will learn about system prompts - powerful instructions that define how the AI behaves across an entire conversation.