Prompt Anatomy
The three components
| Component | What it does | Without it |
|---|---|---|
| Role | Tells the AI who it should act like (expert, teacher, reviewer, tester) | Generic and may miss domain-specific knowledge |
| Context | Tells the model what it needs to know (tech stack, project details, constraints, goals) | Correct answer for the wrong situation |
| Constraint | Tells the model what it must not do (format, scope, length, audience) | Verbose, off-topic, or wrong format output |
Before and after
Without structure:
"Explain dependency injection."
With Role / Context / Constraint:
"You are a senior Java developer [Role]. I'm onboarding a junior onto a Spring Boot project that uses constructor injection throughout [Context]. Explain dependency injection in 3 bullet points, no code, aimed at someone who knows OOP but not Spring [Constraint]."
The second prompt produces a targeted, actionable answer. The first produces a textbook definition.
Anti-patterns to avoid
| Anti-pattern | Problem | Fix |
|---|---|---|
| Open-ended ask | "Help me with my code" | Specify what kind of help, which file, what outcome |
| No format constraint | "Summarize this article" | "Summarize in 5 bullet points, max 2 lines each" |
| Assumed context | "Fix the bug" | Paste the code, the error, and the expected behavior |
| Stacked questions | One prompt asking 5 unrelated things | One prompt, one goal |
Prompt techniques
1. Be Specific, Not Vague
- Vague prompts force the agent to guess. Specific prompts give it a target.
- Name files, functions, and components. Say exactly what "better" means.
Bad: "Make the form better."
Good: "Add email format validation to the signup form in
src/components/SignupForm.tsx using the existing
validateInput utility. Show an error message below
the field when the format is invalid."2. Provide Context Upfront
- Start with context before instructions. Include tech stack, constraints, and key patterns at the top.
- This reduces wrong assumptions and improves accuracy.
Bad: "Add caching to the API."
Good: "This is an Express.js REST API using PostgreSQL. The
GET /api/products endpoint is slow (~2s). Add in-memory
caching with a 5-minute TTL using the node-cache package
that's already in package.json. Follow the pattern used
in routes/categories.ts."3. Use Constraints
- State what the agent must not change or do.
- They are especially important in refactoring, where the agent may otherwise modify unrelated code.
Bad: "Refactor the user service."
Good: "Refactor UserService to use async/await instead of
callbacks. Don't change the public API — existing callers
should work without modification. Don't modify the
database schema or migration files."4. Decompose Complex Tasks
- Break large tasks into smaller steps. If unsure how, ask the agent to decompose it.
- One step at a time works better than one big request. After each step, review before continuing.
Bad: "Build user authentication for the app."
Good: "Let's add user authentication. Start with step 1:
create a users table migration with email, password_hash,
and created_at columns using our existing Knex setup.
Don't implement login or registration yet — just the
schema."5. Show Examples (Few-Shot)
- When you need a specific format or style, include an example. Examples are clearer than long descriptions.
- This is few-shot prompting: the model follows the pattern you show.
Bad: "Write tests for the order service."
Good: "Write tests for OrderService.calculateTotal(). Follow
the same pattern used in tests/cart.test.ts — use
describe/it blocks, create fixtures with the
buildTestOrder helper, and assert with expect().toBe().
Here's an example of what a test looks like:
it('applies discount when total exceeds 100', () => {
const order = buildTestOrder({ items: [{ price: 120 }] });
expect(OrderService.calculateTotal(order)).toBe(108);
});"6. Ask for Reasoning (Chain-of-Thought)
- For complex or judgment-based tasks, ask the agent to think before acting.
- This is the chain-of-thought technique. It improves analysis and helps catch bad assumptions before they become code.
Bad: "Fix the performance issue."
Good: "The /api/dashboard endpoint takes 8 seconds to respond.
Before making changes, analyze the route handler in
routes/dashboard.ts and explain what's causing the
slowdown. List your top 3 hypotheses, then propose a
fix for the most likely cause."7. Assign a Role
- Give the agent a clear role or persona.
- This focuses its perspective and standards.
Bad: "Review this code."
Good: "As a senior backend engineer focused on security,
review the authentication middleware in
src/middleware/auth.ts. Look for common vulnerabilities:
token validation issues, missing rate limiting,
information leakage in error responses."Exercise: Rewrite a Bad Prompt
Here's a poorly structured prompt. Rewrite it using the techniques from the section above.
The bad prompt:
"The app is broken on mobile. Fix it and make sure it looks good."Think about: What's missing? What would the agent need to know? What constraints should you add?
Suggested rewrite
"The checkout page (src/pages/Checkout.tsx) overflows horizontally
on screens narrower than 375px. The order summary table doesn't
wrap properly. Fix the responsive layout using the existing Tailwind
breakpoint utilities (sm:, md:) — don't add custom CSS media queries.
Test that it works at 375px and 320px widths. Don't change the
desktop layout."Notice what changed: a specific file, a specific problem, a specific technology, clear constraints, and a way to verify the fix.