From Zero to AI

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

  1. Good prompts have structure: Context, Instruction, Input, Output Format, and Constraints
  2. Be specific: Vague prompts get vague results
  3. Provide context: The model does not know your situation unless you explain it
  4. Use formatting: Delimiters, sections, and numbered steps improve clarity
  5. Specify output format: Especially important for programmatic processing
  6. 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.

Continue to Lesson 3.2: System Prompts