AI & Development
System prompts for AI agents are not the same as prompts for chatbots. Here's what makes an agent prompt work
The difference between an AI agent that does useful work and one that produces frustrating output is usually not the model. It is the system prompt. A well-written agent prompt produces consistent, high-quality output from a capable model. A vague agent prompt produces inconsistent, generic output from the same model. Prompt engineering for agents is a specific skill - different from writing prompts for chatbots and different from writing prompts for one-off tasks. Here is what makes agent prompts work.
The role definition at the top of an agent prompt is the most important section. It tells the model what kind of entity it is, what expertise it has, and what standard it should hold itself to. Vague role definitions produce vague agents.
Compare these two role definitions:
Vague: "You are an AI assistant that helps with software development."
Specific: "You are a senior React engineer with five years of experience building production consumer apps. You write clean, tested, TypeScript code. You prefer functional components and React hooks. You never introduce dependencies without justification. You always check if the project's existing code has a utility for what you are about to build before writing a new one."
The specific role definition tells the model not just what it is but how it thinks, what it values, and what it checks. Those behavioral signals produce consistent output across many tasks because the model has a coherent persona to maintain.
The model cannot know things that are not in its training data or in the conversation context. Project-specific conventions, architectural decisions, team preferences, known technical debt to avoid - none of this exists unless you write it into the agent prompt.
The fastest way to identify what context an agent is missing is to run it on a real task and observe where it deviates from what you expected. Those deviations point directly to missing context. "It named the variable incorrectly" → add your naming convention. "It used a library we don't use" → add your approved dependency list. "It didn't add tests" → add your testing requirement.
Each iteration of an agent prompt should add specificity where generic output appeared. After three or four real-task runs, most agents stabilize because the common deviation points have been addressed.
Every agent prompt needs an explicit scope definition: what decisions is this agent authorized to make, and what decisions must it surface to the human for approval?
Scope has two components:
Decision scope: What kinds of choices can the agent make without asking? A code-writing agent can choose variable names, internal function structure, and implementation approach within the established conventions. It should not choose to introduce new architectural patterns, add new dependencies, or change public API signatures - those decisions should be surfaced for human review.
Action scope: What actions can the agent take? A documentation agent can read any file and write documentation files. It should not modify source code. This should be enforced both by tool access restrictions and by explicit instruction in the prompt: "You read source files and write documentation files. You do not modify source files."
The reason both tool restrictions and explicit instructions are useful is that they catch different failure modes. Tool restrictions catch accidental actions - the agent cannot modify a file it has no write access to, regardless of what it thinks it should do. Explicit instructions catch intentional-but-wrong decisions - the agent understands the scope boundary and can reference it when an edge case appears at the boundary.
Generic agent prompts describe what the agent does. Effective agent prompts specify how it does it, in what order, and what to check at each step.
The difference is significant in practice. "Review the code for quality issues" leaves the agent to decide what "quality" means, which issues to surface, and how to communicate findings. "Review the code in this order: (1) check for security vulnerabilities - specifically injection, XSS, and improper error handling; (2) check for TypeScript type safety violations; (3) check for missing test coverage; (4) check for violation of the project's naming conventions as defined in CLAUDE.md. Report findings as a numbered list with severity (critical / major / minor) and file:line reference for each finding" produces consistent, actionable output.
Numbered steps also make it possible to debug agent behavior. If the agent produces wrong output, you can identify which step in the numbered workflow produced the error and add specificity to that step.
A section of explicit prohibitions is one of the most valuable parts of an agent prompt. It addresses the failure modes you have already observed or can predict.
Effective prohibitions are specific and grounded in a real failure mode:
console.log statements to production code. Use the project's existing logger utility."package.json or install new dependencies. Dependency changes require human review."any type in TypeScript. If the correct type is unclear, use unknown and add a comment explaining why."Vague prohibitions ("do not write bad code", "avoid mistakes") add no information. The model already intends to write good code; the prohibition is not telling it anything it did not already intend. Specific prohibitions address concrete failure modes the model might otherwise fall into.
The most commonly missing element in agent prompts is a quality gate: a specific set of checks the agent must run before declaring a task complete. Without quality gates, the agent finishes when it thinks it is done. With quality gates, the agent finishes when it has verified that the output meets defined standards.
Quality gates work best as checklists with automated verification where possible:
npm test and confirm all tests pass before marking the task complete."npm run lint and fix any errors before marking the task complete."Automatable quality gates (running a test suite, checking a character count) are more reliable than judgment-based quality gates ("ensure the code is readable") because they produce a clear pass/fail signal.
No agent prompt is correct on the first version. The iteration cycle is: write the prompt, run a real task, observe where the output deviated from expected, add specificity to the prompt at the point of deviation, repeat. Three to five iterations is typical for an agent that handles a specific, well-scoped task. An agent covering a broader domain may require more.
Keep a changelog for agent prompts - a short note after each revision describing what failed and what was added to address it. This makes it easier to understand why the prompt looks the way it does, and prevents well-intentioned "simplification" from removing constraints that exist for specific reasons.