Back to home

03 — BEHAVIOR CONTROL

System prompt engineering

8 min read

Your agent's system prompt is its personality, its rulebook, and its context all rolled into one. Get it wrong and your agent will be verbose, ignore your tools, or make terrible decisions. Get it right and it becomes a reliable coding partner.

Most people treat system prompts as an afterthought. They paste in some generic instructions and wonder why their agent doesn't behave the way they want. The truth is, your system prompt is doing heavy lifting - it's teaching the model what kind of agent it is, what it can do, and how it should act.

Why System Prompts Matter

Think about it: the LLM has no idea it's a coding agent unless you tell it. It doesn't know it has access to file operations, search tools, or a sandbox environment. It doesn't know whether it should be concise or verbose, proactive or cautious.

The system prompt is where you set all of this up. It's the difference between an agent that:

  • Writes paragraph after paragraph explaining what it's about to do
  • Actually does the work with minimal commentary

Or between an agent that:

  • Uses bash to read files when it has dedicated tools
  • Efficiently uses the right tool for each job

Your system prompt shapes behavior at every level.

Multiple Prompts for Different Contexts

Here's a key insight: you don't need just one system prompt. You need several, each optimized for a specific context.

Consider these scenarios:

  • Initial project setup - The agent needs to move fast, install dependencies, start dev servers
  • Normal coding mode - Full access to tools, can make changes
  • Chat/planning mode - Read-only, helps explore and plan but can't make changes
  • Error-fixing mode - Focused on debugging, analyzing logs, fixing issues

Each of these needs a different prompt. The initial setup prompt emphasizes speed and skips explanations. The normal coding prompt includes all tool guidelines and conventions. The chat mode prompt explicitly tells the agent it's read-only and should suggest switching modes for implementation.

What Goes Into a Good System Prompt

Let's break down the key sections you'll want in most coding agent prompts:

Role and Capabilities

Start by clearly defining what the agent is:

You are an AI coding agent that helps users with software engineering tasks.
Use the instructions below and the tools available to you to assist the user.

Simple, direct. The agent knows what it is and what it's supposed to do.

Tone and Output Style

This is huge. Without this, you'll get agents that ramble:

You should be concise, direct, and to the point.
Answer with fewer than 4 lines unless the user asks for detail.
Skip preambles like "Great question!" or "Let me explain..."

Define how the agent should communicate. Give examples of good vs bad responses. The more specific you are here, the better.

Tool Usage Guidelines

Your agent needs to know when and how to use its tools. This section can make or break efficiency:

- Use dedicated tools instead of bash commands when possible
- Read files with the Read tool, not cat
- Search code with Grep, not grep via bash
- Call multiple independent tools in parallel for speed

Include anti-patterns too - things the agent shouldn't do. This prevents common mistakes.

Task Management

If you want your agent to break down complex tasks, tell it:

You have access to TodoWrite to plan and track tasks.
Use it for multi-step work to give users visibility.
Mark todos complete immediately after finishing each one.

Without this, agents tend to do everything at once without clear progress indicators.

Domain-Specific Guidelines

This is where you encode your project's patterns and conventions:

When making changes:
- Match existing code style
- Use libraries already in the codebase
- Check existing components before creating new ones
- Follow security best practices

For web projects, you might add framework-specific rules (Next.js patterns, React conventions, etc.). For data projects, you'd add guidelines about data handling and validation.

Critical Requirements

Call out must-follow rules explicitly:

CRITICAL: Before integrating ANY third-party API, you MUST:
1. Use web_search to find current documentation
2. Review the search results
3. ONLY THEN write integration code

This is MANDATORY, not optional.

Use strong language for things that must happen. APIs change, documentation gets outdated - making the search step mandatory prevents bugs.

Selecting the Right Prompt

You need logic to pick the right prompt at runtime. Here's a simple pattern:

createSystemPrompt(): string {
  // Override for testing or custom scenarios
  if (this.systemPromptOverride) {
    return this.systemPromptOverride;
  }
 
  // Chat mode for exploration
  if (this.mode === 'chat') {
    return CHAT_MODE_SYSTEM_PROMPT;
  }
 
  // Initial setup for new projects
  if (!this.beyondInitial) {
    return INITIAL_CODING_AGENT_SYSTEM_PROMPT;
  }
 
  // Standard coding prompt
  return CODING_AGENT_SYSTEM_PROMPT;
}

Track state (like whether the user has made any file changes) and use it to switch between prompts. A fresh project needs different instructions than an established one.

Prompt Context Injection

Beyond the static prompt text, you'll inject dynamic context at request time:

Codebase structure - Directories and root files so the agent knows what exists

Design system - CSS variables, component patterns, color schemes

Database context - For projects connected to Supabase, include schema info

Service integrations - Stripe webhooks, auth providers, etc.

These aren't part of your base system prompt. They're added to each request based on what's relevant. This keeps your system prompt focused on behavior and guidelines while giving the agent the context it needs.

Common Mistakes

Too generic - "You are a helpful assistant" doesn't cut it. Be specific about capabilities and constraints.

Too verbose - If your system prompt is 10,000 tokens, you're wasting context. Keep it focused.

No examples - Abstract instructions like "be concise" don't work as well as showing exactly what concise looks like.

Ignoring model differences - GPT models and Claude models have different strengths. Sometimes you need model-specific prompts.

Static context - Injecting every possible piece of context into every request is wasteful. Load what's relevant for each task.

Iterating on Your Prompts

Don't expect to get your system prompt perfect on the first try. You'll need to iterate based on how your agent behaves:

Watch for patterns:

  • Is it being too verbose? Tighten the tone section
  • Is it using bash instead of dedicated tools? Clarify tool guidelines
  • Is it making the same mistakes repeatedly? Add explicit rules against those patterns

Track which prompts work best for which scenarios. Maybe your chat mode prompt needs to be more encouraging about suggesting implementation. Maybe your error-fixing prompt should include specific debugging strategies.

Keep a version history. When you make changes, note what behavior you were trying to fix and whether it worked.

Mode Switching

One powerful pattern is letting users switch modes:

  • Agent mode - Full power, can make changes
  • Chat mode - Read-only, for exploration and planning

Your chat mode prompt should explicitly tell the agent:

  • "You CANNOT edit files or run commands"
  • "You CAN read, search, and suggest"
  • "Tell users to switch to Agent mode for implementation"

This prevents confusion and gives users control over when the agent takes action.

What's Next

You've now got the pieces to build effective system prompts for your coding agent. But prompts alone aren't enough - you need to inject the right context at the right time.

In the next guide, we'll cover context injection: how to give your agent awareness of todos, file structures, design systems, and project state without bloating every request.

That's where the real optimization happens.