Module 2 (Gemini) - Lesson 2b: System Prompt with Gemini

Shape model behavior using systemInstruction in Gemini.

Published: 1/15/2026

Lesson 2b: System Prompt with Google Gemini

System prompts define the AI's role, personality, and behavior. Learn how Gemini handles system prompts differently from OpenAI and Anthropic.

Key Differences from OpenAI and Anthropic

OpenAI: System prompt is part of the messages array

messages: [
  { role: "system", content: "You are a helpful assistant" },
  { role: "user", content: "Hello" }
]

Anthropic: System prompt is a separate top-level parameter

system: "You are a helpful assistant",
messages: [
  { role: "user", content: "Hello" }
]

Gemini: System prompt uses config.systemInstruction

contents: "Hello",
config: {
  systemInstruction: "You are a helpful assistant"
}

Code Example

Create src/gemini/basic-prompt-with-system.ts:

import { GoogleGenAI, ApiError } from "@google/genai";
import dotenv from "dotenv";

// Load environment variables
dotenv.config();

// Create Gemini client
const gemini = new GoogleGenAI({});

// Async function with proper return type
async function basicPromptWithSystem(): Promise<void> {
  try {
    console.log("Testing Gemini connection...");

    // Make API call with system instruction
    const response = await gemini.models.generateContent({
      model: "gemini-3-flash-preview",
      contents: "Suggest a travel destination",
      config: {
        systemInstruction: "You are a helpful travel assistant.",
      },
    });

    console.log("Basic Prompt with System Success!");
    console.log("Tokens used:");
    console.dir(response.usageMetadata, { depth: null });

    if (!response.text) {
      throw new Error("No content in response");
    }

    console.log("AI Response:", response.text);
  } catch (error) {
    if (error instanceof ApiError) {
      console.log("API Error:", error.status, error.message);
    } else if (error instanceof Error) {
      console.log("Error:", error.message);
    } else {
      console.log("Unknown error occurred");
    }
  }
}

// Run the test
basicPromptWithSystem().catch((error) => {
  console.error("Error:", error);
});

Run It

pnpm tsx src/gemini/basic-prompt-with-system.ts

System Prompt Best Practices

1. Be Clear and Specific

Bad:

config: {
  systemInstruction: "You help people"
}

Good:

config: {
  systemInstruction: "You are a helpful travel assistant with expertise in European destinations. Provide detailed, practical travel advice."
}

2. Define Personality and Tone

config: {
  systemInstruction: "You are a friendly, enthusiastic travel expert. Use a warm, conversational tone while providing accurate information."
}

3. Set Constraints

config: {
  systemInstruction: "You are a travel assistant. Always include: 1) Destination details 2) Best time to visit 3) Budget estimate. Keep responses under 200 words."
}

4. Specify Format

config: {
  systemInstruction: "You are a travel assistant. Format all responses with clear sections: Overview, Attractions, Practical Tips."
}

Comparison: With vs Without System Prompt

Without System Prompt

const response = await gemini.models.generateContent({
  model: "gemini-3-flash-preview",
  contents: "Suggest a travel destination"
});

Response: Generic travel suggestion

With System Prompt

const response = await gemini.models.generateContent({
  model: "gemini-3-flash-preview",
  contents: "Suggest a travel destination",
  config: {
    systemInstruction: "You are a budget travel expert specializing in off-the-beaten-path destinations."
  }
});

Response: Budget-friendly, unique destination with cost-saving tips


Advanced System Prompts

Multi-Part System Prompts

config: {
  systemInstruction: `You are a professional travel assistant with the following guidelines:

**Expertise:**
- European destinations
- Budget travel tips
- Cultural experiences

**Response Format:**
1. Destination name and location
2. Why visit (2-3 sentences)
3. Best time to visit
4. Estimated budget
5. Top 3 attractions

**Tone:** Friendly, informative, and encouraging`
}

Role-Based System Prompts

// Code reviewer
config: {
  systemInstruction: "You are an experienced TypeScript developer. Review code for best practices, potential bugs, and performance issues."
}

// Creative writer
config: {
  systemInstruction: "You are a creative writing coach. Provide constructive feedback on story structure, character development, and prose."
}

// Technical explainer
config: {
  systemInstruction: "You are a patient teacher explaining complex technical concepts to beginners. Use analogies and simple language."
}

System Prompt vs User Prompt

System Prompt (Persistent Role)

  • Sets the AI's personality
  • Defines expertise area
  • Establishes response format
  • Stays the same across conversation

User Prompt (Specific Request)

  • What you want the AI to do
  • Changes with each message
  • Specific questions or tasks

Example Conversation Flow

// Persistent system (in config)
config: {
  systemInstruction: "You are a travel assistant specializing in Europe"
}

// First user message
contents: "Suggest a destination in France"

// Second turn (multi-turn requires array of contents)
contents: [
  { role: "user", parts: [{ text: "Suggest a destination in France" }] },
  { role: "model", parts: [{ text: "..." }] },
  { role: "user", parts: [{ text: "What about Italy?" }] }
]

// System instruction affects ALL responses with European expertise

Side-by-Side Comparison

OpenAI Approach

const response = await openai.chat.completions.create({
  model: "gpt-5-nano",
  messages: [
    { role: "system", content: "You are a travel assistant." },
    { role: "user", content: "Suggest a destination" }
  ]
});

Anthropic Approach

const response = await anthropic.messages.create({
  model: "claude-haiku-4-5",
  max_tokens: 1000,
  system: "You are a travel assistant.",
  messages: [
    { role: "user", content: "Suggest a destination" }
  ]
});

Gemini Approach

const response = await gemini.models.generateContent({
  model: "gemini-3-flash-preview",
  contents: "Suggest a destination",
  config: {
    systemInstruction: "You are a travel assistant."
  }
});

Key Differences Table

FeatureOpenAIAnthropicGemini
LocationIn messages arrayTop-level systemconfig.systemInstruction
Role name"system"N/A (separate param)N/A (separate config)
FormatMessage objectStringString
Multiple system msgsYes (in array)Single stringSingle string

Common Patterns

Customer Support

config: {
  systemInstruction: `You are a customer support agent for TechCorp.

Guidelines:
- Be polite and professional
- If you don't know, say so
- Offer to escalate complex issues
- Always confirm the customer's problem before solving

Product knowledge:
- We sell software subscriptions
- Refunds available within 30 days
- Support hours: 9am-6pm EST`
}

Code Assistant

config: {
  systemInstruction: `You are an expert TypeScript developer.

When reviewing code:
1. Check for type safety
2. Look for potential bugs
3. Suggest performance improvements
4. Follow best practices

When writing code:
- Use TypeScript strict mode
- Include proper error handling
- Add JSDoc comments for public APIs
- Prefer async/await over callbacks`
}

Educational Tutor

config: {
  systemInstruction: `You are a patient math tutor for high school students.

Teaching style:
- Break problems into small steps
- Ask guiding questions before giving answers
- Use real-world examples
- Celebrate progress and correct mistakes gently

Never just give the answer - guide the student to discover it themselves.`
}

Key Takeaways

  • System prompt uses config.systemInstruction in Gemini
  • Different from OpenAI (in messages) and Anthropic (top-level system)
  • Use system prompts to define role, personality, and constraints
  • System prompts persist across the entire conversation
  • Be specific about tone, format, and expertise

Next Steps

Learn how to control response creativity with temperature!

Next: Lesson 2c - Temperature Control


Quick Reference

// Minimal system prompt example
const response = await gemini.models.generateContent({
  model: "gemini-3-flash-preview",
  contents: "Suggest a destination",
  config: {
    systemInstruction: "You are a helpful travel assistant."
  }
});

Common Pitfalls

  1. Putting system prompt in contents instead of config.systemInstruction
  2. Using system (Anthropic style) instead of systemInstruction
  3. Forgetting to wrap systemInstruction in the config object
  4. Making system prompts too vague or generic