Skip to content
Writing Effective Prompts

Writing Prompts That Work ✍️

The prompt for a coding agent is not a magic formula to recite. It is how you structure a request so the model has the information it needs without having to guess. The difference between a mediocre and an effective prompt is not the number of words: it is the amount of useful information per word.

A good prompt does not ask the agent to be smart: it gives the agent what it needs so it does not have to be.

The four elements 🧩

An optimized prompt for an implementation task explicitly defines four elements:

Element What it contains Example
GOAL What the code must do, the functional result Implement user session handling in src/auth/session.ts
CONSTRAINTS Non-negotiable rules, what must NOT be touched RS256-signed JWTs; do not modify the UserStore interface
TARGET FILES Files to create or modify Create src/auth/session.ts, update src/auth/index.ts
CRITERIA How to verify the result Unit tests in tests/auth/session.test.ts; pnpm test green

The model has one question in mind when it reads your prompt: “what exactly is being asked of me, and how will I know I am done?”. The four elements are the answer.

Good and bad example ⚖️

The fastest way to understand is to see the difference. The vague prompt:

“Add user session handling to the backend and make sure it is secure.”

The result will be plausible, generic code, almost certainly not aligned with your conventions. Here is the directive version:

1
2
3
4
5
6
GOAL: Implement user session handling in src/auth/session.ts.
CONSTRAINTS: JWTs signed with asymmetric RS256 keys. DO NOT modify the existing
UserStore interface in src/types/user.ts.
TARGET FILES: Create src/auth/session.ts and update src/auth/index.ts.
CRITERIA: Generate unit tests in tests/auth/session.test.ts for expired tokens.
Verify that pnpm test passes.

It is not longer, it is denser. Every line removes a decision the agent would otherwise have made on its own — and made poorly.

The 3S pattern 📌

A mnemonic shortcut so you never forget pieces:

  • Situation — the minimum indispensable context: project, stack, business constraint.
  • Specification — what the code must do exactly, including error conditions and edge cases.
  • Standard — style, architectural patterns, testing conventions. Ideally these already live in the repository instructions and are not repeated on every request.

The beauty of 3S is that it forces you to separate what is task-specific (goes in the prompt) from what is project-constant (goes in the repository). Repeating in the prompt what is already in AGENTS.md does not help: it burns tokens and confuses priorities.

Breaking tasks down 🔪

A big task should not be entrusted to a big prompt. It is broken into a sequence of small requests, each with its own validation cycle:

  1. first the structure (“propose the module structure and the interfaces”);
  2. then the implementation module by module;
  3. then the tests;
  4. finally the complete verification.

Asking for everything in one shot (“implement the complete payment module”) produces long, unverifiable code that is expensive to fix. Asking in steps produces a result you can check at every intersection.

Controlling output volume 🎛️

Output costs more than input: every useless word is waste. For write-only tasks, the prompt can end with “code only, no explanations”. For questions, “answer as a bulleted list”. For exploratory tasks, “cite files with path and line for every claim”.

These small constraints are not stylistic whims: they reduce output volume, shorten sessions and force the agent to be precise instead of eloquent.

Iterate instead of rewriting 🔁

The first output is rarely the right one, and that is fine. The mistake is starting over with a brand-new prompt every time. The correct technique is iteration with scope narrowing:

  • if part of the result is wrong, confine the fix to that part (“the error case in session.ts does not handle the expired token; fix only that”);
  • if the result is on the right track but with the wrong style, point out the standard and repeat the operation;
  • if the second attempt still fails on the same point, bake the negative outcome in as an explicit constraint (“the previous attempt failed because X; avoid X”).

Iterating on the error is faster and cheaper than starting over, and it produces progressively more precise prompts.

Reusable prompts and a team library 🗃️

For recurring tasks — test generation, checklist code review, module scaffolding — the prompt should be standardized and versioned, not rewritten by hand every time:

  • save prompts as .prompt.md (or your tool’s convention, such as slash command folders);
  • invoke them by name, not by copy-paste;
  • the library grows in value: every PR review is a better prompt for everyone;
  • before reinventing, check the community: adapting an existing prompt is almost always faster than starting from scratch.

A shared prompt library has the same effect as a well-maintained AGENTS.md: the team works with the same rules even when it does not have them in mind.

When NOT to use this recipe ⛔

  • Context matters more than the prompt: a perfect prompt with empty context produces generic code. Context quality first, phrasing second.
  • It is not an infallible formula: if the agent keeps failing on one part of the codebase, the problem might be code readability, not the prompt.
  • It does not replace validation: the prompt defines the criteria, it does not verify them. The proof remains build, test and lint.

Final checklist ✅

  • Did I define goal, constraints, target files and acceptance criteria?
  • Did I include only relevant context, without pasting whole files?
  • Does the standard (stack, style) live in the repository, not in the prompt?
  • Did I break the big task into steps with intermediate validation?
  • Did I control output volume (“code only”)?
  • If something went wrong, did I iterate with scope narrowing instead of rewriting?
  • Is the prompt that worked saved in the team library?

Further reading 📚

Last updated on