From Zero to AI

Lesson 3.2: System Prompts

Duration: 55 minutes

Learning Objectives

By the end of this lesson, you will be able to:

  • Understand the role of system prompts in AI applications
  • Write effective system prompts that define AI behavior
  • Create personas and roles for different use cases
  • Set constraints and safety guidelines
  • Structure system prompts for maintainability

Introduction

In the previous lesson, you learned how to write effective prompts. But there is a special type of prompt that is even more powerful: the system prompt.

A system prompt is a set of instructions that defines how the AI behaves throughout an entire conversation. It is like giving the AI a job description before it starts working. While user prompts ask specific questions, system prompts establish the rules of engagement.


What is a System Prompt?

System prompts are sent at the beginning of a conversation and set the context for all interactions that follow.

┌─────────────────────────────────────────────────────────┐
│                   Message Flow                           │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  ┌─────────────────┐                                    │
│  │ SYSTEM PROMPT   │  "You are a helpful coding         │
│  │ (sent once)     │   assistant specializing in        │
│  │                 │   TypeScript..."                   │
│  └────────┬────────┘                                    │
│           │                                             │
│           ▼                                             │
│  ┌─────────────────┐                                    │
│  │ USER MESSAGE 1  │  "How do I create an interface?"   │
│  └────────┬────────┘                                    │
│           │                                             │
│           ▼                                             │
│  ┌─────────────────┐                                    │
│  │ AI RESPONSE 1   │  (follows system prompt rules)     │
│  └────────┬────────┘                                    │
│           │                                             │
│           ▼                                             │
│  ┌─────────────────┐                                    │
│  │ USER MESSAGE 2  │  "Show me an example"              │
│  └────────┬────────┘                                    │
│           │                                             │
│           ▼                                             │
│  ┌─────────────────┐                                    │
│  │ AI RESPONSE 2   │  (still follows system prompt)     │
│  └─────────────────┘                                    │
│                                                         │
└─────────────────────────────────────────────────────────┘

System vs User Messages

import OpenAI from 'openai';

const openai = new OpenAI();

const response = await openai.chat.completions.create({
  model: 'gpt-4o',
  messages: [
    {
      role: 'system', // System prompt - defines behavior
      content:
        'You are a helpful TypeScript tutor. Explain concepts clearly with examples. Keep responses concise.',
    },
    {
      role: 'user', // User message - the actual question
      content: 'What is a generic type?',
    },
  ],
});

With Anthropic's API, the system prompt is a separate parameter:

import Anthropic from '@anthropic-ai/sdk';

const anthropic = new Anthropic();

const response = await anthropic.messages.create({
  model: 'claude-sonnet-4-20250514',
  max_tokens: 1024,
  system:
    'You are a helpful TypeScript tutor. Explain concepts clearly with examples. Keep responses concise.',
  messages: [
    {
      role: 'user',
      content: 'What is a generic type?',
    },
  ],
});

Components of an Effective System Prompt

A well-structured system prompt typically includes these elements:

1. Role Definition

Tell the AI who it is and what it does:

You are a senior TypeScript developer with 10 years of experience.
You specialize in building scalable backend systems with Node.js.

2. Behavioral Guidelines

Define how the AI should interact:

Communication style:
- Use clear, technical language appropriate for developers
- Be concise but thorough
- Ask clarifying questions when requirements are ambiguous

3. Capabilities and Limitations

Set expectations about what the AI can and cannot do:

You can help with:
- Writing and reviewing TypeScript code
- Explaining programming concepts
- Debugging errors
- Suggesting best practices

You cannot:
- Access external systems or databases
- Execute code
- Remember information from previous conversations

4. Output Format Instructions

Specify how responses should be structured:

Response format:
- Start with a brief summary
- Provide code examples when helpful
- Use markdown formatting for code blocks
- End with actionable next steps

5. Constraints and Safety Rules

Define boundaries and safety guidelines:

Important rules:
- Never generate harmful or malicious code
- Always validate user input in code examples
- If asked about topics outside your expertise, acknowledge limitations
- Do not make up information - say "I don't know" when uncertain

Writing Effective System Prompts

Start with the Role

The role gives the AI a mental model to work from. Be specific about expertise and perspective:

Generic:

You are a helpful assistant.

Specific:

You are an expert code reviewer specializing in TypeScript and Node.js applications.
You have extensive experience with:
- Clean code principles
- Security best practices
- Performance optimization
- Testing strategies

When reviewing code, you focus on maintainability, security, and scalability.

Define the Interaction Style

Different applications need different tones:

Professional and formal:

Maintain a professional, formal tone. Use precise technical terminology.
Address users respectfully and provide thorough explanations.

Friendly and casual:

Be friendly and approachable. Use casual language and occasional humor.
Make learning fun while still being helpful and accurate.

Concise and efficient:

Be direct and efficient. Avoid unnecessary explanations.
Get to the point quickly. Use bullet points for clarity.

Set Clear Boundaries

Boundaries prevent the AI from going off-track:

Scope:
- Only answer questions related to TypeScript and JavaScript
- If asked about other programming languages, politely redirect to TypeScript
- Do not engage in debates about "best" languages or frameworks
- Focus on practical solutions, not theoretical discussions

Practical System Prompt Examples

Example 1: Customer Support Bot

const customerSupportSystem = `
You are a customer support assistant for TechGadgets Inc., an electronics retailer.

ROLE:
- Help customers with order inquiries, product questions, and technical support
- Be friendly, patient, and empathetic
- Represent the company professionally

CAPABILITIES:
- Answer questions about products in our catalog
- Help with order status inquiries (ask for order number)
- Provide basic troubleshooting for electronics
- Explain return and warranty policies

LIMITATIONS:
- Cannot process refunds or modify orders (direct to human support)
- Cannot access real-time inventory (suggest checking website)
- Cannot make promises about delivery times

RESPONSE GUIDELINES:
- Keep responses concise (under 150 words unless explaining something complex)
- Use simple language, avoid technical jargon
- Always offer to help with anything else
- If you cannot help, provide the customer service phone number: 1-800-TECH-HELP

POLICIES TO KNOW:
- 30-day return policy for unused items
- 1-year warranty on all electronics
- Free shipping on orders over $50
`;

Example 2: Code Review Assistant

const codeReviewSystem = `
You are a thorough code reviewer for TypeScript applications.

REVIEW FOCUS AREAS (in priority order):
1. Security vulnerabilities (SQL injection, XSS, etc.)
2. Bugs and logic errors
3. Type safety issues
4. Performance problems
5. Code maintainability
6. Best practices

REVIEW FORMAT:
For each issue found, provide:
- Severity: Critical / High / Medium / Low
- Location: File and line reference
- Issue: Clear description of the problem
- Fix: Specific suggestion for resolution

BEHAVIOR:
- Be constructive, not critical - suggest improvements positively
- Acknowledge good patterns when you see them
- Prioritize actionable feedback over stylistic preferences
- If code looks good, say so - do not invent issues

DO NOT:
- Comment on formatting (assume linter handles this)
- Suggest rewrites unless there is a clear benefit
- Be pedantic about minor issues when there are major ones
`;

Example 3: SQL Query Helper

const sqlHelperSystem = `
You are a SQL expert helping developers write efficient, safe queries.

EXPERTISE:
- PostgreSQL, MySQL, SQLite syntax
- Query optimization
- Index strategies
- Security best practices

RESPONSE FORMAT:
1. The SQL query (formatted and commented)
2. Brief explanation of what it does
3. Performance considerations (if relevant)
4. Security notes (if relevant)

RULES:
- Always use parameterized queries, never string concatenation
- Include appropriate indexes in schema suggestions
- Warn about potential N+1 query problems
- Consider NULL handling in all queries

SAFETY:
- Never generate DELETE or DROP statements without WHERE clauses
- Always confirm destructive operations with the user
- Suggest LIMIT clauses for potentially large result sets
`;

System Prompt Patterns

The Persona Pattern

Create a specific character with expertise:

const personaPrompt = `
You are Dr. Debug, a friendly computer science professor with 30 years of experience.

Personality:
- Patient and encouraging with beginners
- Uses analogies to explain complex concepts
- Occasionally uses dad jokes about programming
- Gets excited about elegant solutions

Teaching style:
- Start with the "why" before the "how"
- Use real-world analogies
- Build concepts incrementally
- Celebrate when students understand something

Catchphrases:
- "Let's debug this together!"
- "Ah, a classic gotcha!"
- "Here's a neat trick..."
`;

The Format Enforcer Pattern

Ensure consistent output structure:

const formatEnforcerPrompt = `
You are an API response generator. ALWAYS respond in this exact JSON format:

{
  "intent": "string - the user's detected intent",
  "confidence": "number - 0 to 1",
  "response": "string - your response to the user",
  "suggestedActions": ["array", "of", "follow-up", "actions"]
}

RULES:
- ONLY output valid JSON, nothing else
- Never include markdown code blocks
- All fields are required
- confidence must be between 0 and 1
`;

The Guardian Pattern

Enforce safety and boundaries:

const guardianPrompt = `
You are a coding assistant with strict safety guidelines.

ALWAYS:
- Sanitize user inputs in code examples
- Use parameterized queries for database operations
- Include error handling in all code
- Follow the principle of least privilege

NEVER:
- Generate code that could be used for hacking
- Provide instructions for bypassing security
- Create scripts that access systems without authorization
- Help with any request that seems malicious

If you suspect a request is malicious:
1. Do not comply with the request
2. Explain why you cannot help
3. Suggest legitimate alternatives if applicable

When uncertain about intent, ask clarifying questions.
`;

Managing System Prompts in Code

Template Approach

interface SystemPromptConfig {
  role: string;
  expertise: string[];
  tone: string;
  constraints: string[];
  outputFormat?: string;
}

function buildSystemPrompt(config: SystemPromptConfig): string {
  const sections = [
    `You are ${config.role}.`,
    '',
    'EXPERTISE:',
    config.expertise.map((e) => `- ${e}`).join('\n'),
    '',
    `COMMUNICATION STYLE: ${config.tone}`,
    '',
    'CONSTRAINTS:',
    config.constraints.map((c) => `- ${c}`).join('\n'),
  ];

  if (config.outputFormat) {
    sections.push('', 'OUTPUT FORMAT:', config.outputFormat);
  }

  return sections.join('\n');
}

// Usage
const tutorPrompt = buildSystemPrompt({
  role: 'a TypeScript tutor for intermediate developers',
  expertise: [
    'TypeScript type system',
    'Generics and utility types',
    'Best practices and patterns',
    'Common pitfalls and how to avoid them',
  ],
  tone: 'Friendly and encouraging. Use analogies to explain complex concepts.',
  constraints: [
    'Keep code examples under 20 lines',
    'Always explain why, not just how',
    'Acknowledge when there are multiple valid approaches',
  ],
  outputFormat: 'Start with a brief answer, then provide a code example if helpful.',
});

Version Control for Prompts

Store prompts in separate files for easier management:

// prompts/customer-support.ts
export const customerSupportPrompt = `
You are a customer support assistant...
`;

export const customerSupportVersion = "1.2.0";
export const customerSupportLastUpdated = "2024-01-15";

// prompts/index.ts
export * from "./customer-support";
export * from "./code-review";
export * from "./sql-helper";

// main.ts
import { customerSupportPrompt } from "./prompts";

const response = await openai.chat.completions.create({
  model: "gpt-4o",
  messages: [
    { role: "system", content: customerSupportPrompt },
    { role: "user", content: userMessage }
  ]
});

Testing System Prompts

Test for Consistent Behavior

async function testSystemPrompt(
  systemPrompt: string,
  testCases: { input: string; shouldContain?: string[]; shouldNotContain?: string[] }[]
): Promise<{ passed: number; failed: number; results: any[] }> {
  const results = [];
  let passed = 0;
  let failed = 0;

  for (const testCase of testCases) {
    const response = await openai.chat.completions.create({
      model: 'gpt-4o',
      messages: [
        { role: 'system', content: systemPrompt },
        { role: 'user', content: testCase.input },
      ],
      temperature: 0, // For consistent testing
    });

    const output = response.choices[0].message.content || '';
    let testPassed = true;

    // Check required content
    for (const phrase of testCase.shouldContain || []) {
      if (!output.toLowerCase().includes(phrase.toLowerCase())) {
        testPassed = false;
        break;
      }
    }

    // Check forbidden content
    for (const phrase of testCase.shouldNotContain || []) {
      if (output.toLowerCase().includes(phrase.toLowerCase())) {
        testPassed = false;
        break;
      }
    }

    if (testPassed) passed++;
    else failed++;

    results.push({
      input: testCase.input,
      output,
      passed: testPassed,
    });
  }

  return { passed, failed, results };
}

// Usage
const results = await testSystemPrompt(customerSupportPrompt, [
  {
    input: 'I want a refund',
    shouldContain: ['human support', '1-800'],
    shouldNotContain: ['I can process that'],
  },
  {
    input: "What's your return policy?",
    shouldContain: ['30-day', 'unused'],
  },
  {
    input: 'Tell me about politics',
    shouldNotContain: ['republican', 'democrat'],
    shouldContain: ['help you with', 'product', 'order'],
  },
]);

Common Mistakes to Avoid

Mistake 1: Too Long and Complex

Bad: A 2000-word system prompt covering every possible scenario

Better: Focus on the most important behaviors. Add specifics in user prompts as needed.

Mistake 2: Conflicting Instructions

Bad:

Be concise and brief.
...
Always provide comprehensive explanations with multiple examples.

Better: Choose one approach and be consistent.

Mistake 3: No Escape Hatch

Bad: Rigid rules with no flexibility

Better: Include guidance for edge cases:

If you encounter a situation not covered by these guidelines,
use your best judgment while prioritizing user helpfulness and safety.

Mistake 4: Forgetting About Failures

Bad: Only defining happy-path behavior

Better: Include error handling:

If you don't understand the request:
- Ask one clarifying question
- Provide your best interpretation and ask if it's correct

If you cannot help with a request:
- Explain why briefly
- Suggest an alternative if possible

Exercises

Exercise 1: Write a System Prompt

Create a system prompt for a fitness coaching chatbot that:

  • Provides workout advice
  • Answers nutrition questions
  • Cannot provide medical advice
  • Maintains an encouraging tone
Solution
You are FitBot, a friendly fitness and nutrition coach.

ROLE:
- Help users with workout routines and exercise form
- Provide general nutrition guidance
- Motivate and encourage users on their fitness journey

PERSONALITY:
- Enthusiastic and positive
- Supportive without being pushy
- Uses fitness-related encouragement ("You've got this!", "Keep pushing!")

CAPABILITIES:
- Suggest workout routines based on goals
- Explain proper exercise form
- Provide general nutrition tips
- Help set realistic fitness goals
- Offer alternatives for exercises

LIMITATIONS:
- Cannot provide medical advice - always recommend consulting a doctor for health concerns
- Cannot create meal plans for medical conditions
- Cannot diagnose injuries

SAFETY RULES:
- Always emphasize proper form to prevent injuries
- Recommend consulting healthcare providers for:
  - Existing medical conditions
  - Pain or injuries
  - Significant dietary changes
  - Supplements or medications
- Never shame users about their current fitness level

RESPONSE STYLE:
- Keep advice actionable and specific
- Include safety tips when describing exercises
- Celebrate progress and effort, not just results

Exercise 2: Fix the System Prompt

This system prompt has problems. Identify and fix them:

You are a helpful assistant. Be friendly. Be professional.
Answer all questions about everything. Never say you don't know.
Keep answers short but also make them very detailed.
Solution

Problems identified:

  1. "Be friendly" and "Be professional" can conflict - which takes priority?
  2. "Answer all questions about everything" - no scope defined
  3. "Never say you don't know" - encourages hallucination
  4. "Keep answers short but also make them very detailed" - contradiction

Fixed version:

You are a helpful technical assistant specializing in web development.

COMMUNICATION STYLE:
- Professional but approachable
- Clear and well-organized responses

SCOPE:
- Focus on web development topics (HTML, CSS, JavaScript, TypeScript)
- For questions outside this scope, acknowledge limitations and suggest resources

HONESTY:
- If uncertain about something, say so clearly
- Distinguish between facts and opinions/recommendations

RESPONSE LENGTH:
- Default to concise answers (2-3 paragraphs)
- Provide more detail only when the question requires it or user asks

Exercise 3: Create Test Cases

Write 3 test cases for the following system prompt:

You are a JSON formatting assistant.
Always respond with valid JSON only.
Never include explanations or markdown.
Solution
const testCases = [
  {
    input: 'Convert this to JSON: name is John, age is 30',
    shouldContain: ['"name"', '"John"', '"age"', '30'],
    shouldNotContain: ['```', 'Here is', 'The JSON'],
  },
  {
    input: 'Create a JSON array with three colors',
    shouldContain: ['[', ']'],
    shouldNotContain: ['```json', 'Here are'],
  },
  {
    input: 'What is JSON?',
    // Even explanatory questions should get JSON responses
    shouldNotContain: ['JSON stands for', 'JavaScript Object Notation'],
    // Could contain a JSON response about JSON
    shouldContain: ['{', '}'],
  },
];

Key Takeaways

  1. System prompts define AI behavior for the entire conversation
  2. Include key components: role, behavior, capabilities, limitations, and constraints
  3. Be specific about the role - it shapes all responses
  4. Set clear boundaries - what to do and what not to do
  5. Test your prompts - verify they produce consistent, expected behavior
  6. Keep prompts maintainable - use templates and version control

Resources

Resource Type Description
OpenAI System Prompts Guide Documentation Official guidance on personas
Anthropic System Prompts Documentation Claude-specific system prompt advice
Prompting Guide - Role Prompting Tutorial Techniques for effective role prompting

Next Lesson

You have learned how to define AI behavior with system prompts. In the next lesson, you will learn few-shot learning - teaching the AI by example within your prompts.

Continue to Lesson 3.3: Few-Shot Learning