Programming with AI
ENRU
3.2

Anatomy of a prompt

context, goal, constraints, definition of done

What it is

A good prompt has four parts: context, goal, constraints and a definition of done. This is not a form to fill in every time — it is a list of what the AI has to learn from somewhere. If you don't say it, it will guess, and the guess will be the industry average rather than yours.

This article is the foundation of all of chapter 3. What follows are ready-made templates for particular tasks, and every one of them is built from these four parts.

The four parts

PartAnswersWhat happens if you skip it
Contextwhere, and in which projectthe AI writes code "from scratch", not fitted to yours
Goalwhat the result should beyou get something similar, but not it
Constraintswhat must not be doneit rewrites extra things, adds dependencies
Definition of donehow to know it is finished"finished" arrives earlier than it should

What it looks like in code

Take a live task: a Telegram bot needs a limit on how often commands can be sent.

Don't
Add spam protection to the bot

The prompt looks clear, and it contains none of the four parts. What the AI will decide for you: which framework, what limit, where to keep the counters, what to reply to the user, whether to count commands or messages, whether to touch the existing handlers. Six decisions, none of them yours.

Now the same thing with the four parts:

Better
Context: bot on aiogram 3, file handlers/commands.py.
Handlers are functions with the @router.message decorator.
Data is stored in SQLite via aiosqlite, module db.py.

Goal: rate-limit commands — no more than 5 commands per minute
from one user.

Constraints:
- no new dependencies, only what is already in requirements.txt
- don't change the existing handlers, do it as separate middleware
- keep the state in memory, don't write to the database

Done when: the sixth command within a minute gets the reply
"Too fast, wait a moment" and a warning goes to the log.
All other commands work as before.

The second prompt is ten times longer and saves an hour of rework.

How to know there is enough context

Context is what the AI cannot see. If it works inside the project (an agent in the terminal), it reads the files itself and context shrinks to "where to look". In a chat with no access to the code, context has to come from your words or from a pasted file.

The minimum that is needed almost always:

  • the language, the framework and the version — aiogram 3, not just aiogram;
  • the file or module to work in;
  • how similar problems are already solved in the project.

The third point is underrated. It matters more than the first two: it is what makes the AI write in the project's style rather than its own.

The definition of done

The most-skipped part and the most useful. A definition of done is a checkable condition, not a wish.

Not a definitionA definition
"so that it works well""the sixth command within a minute is refused"
"reliable""on a dropped connection it retries three times, then logs"
"fast""a reply in under a second with 100 users"
"nice-looking""buttons in two rows, labels no longer than 20 characters"

It does two things. First, the AI knows when to stop. Second, you get a way to check the result without reading the code — you just check the condition.

What to tell the AI

The four parts do not have to be a list. In short tasks they fit in a paragraph:

Prompt
In utils/text.py add a function that splits a long message
into chunks of 4096 characters at paragraph boundaries, without
breaking words. No external libraries. Done when a 10,000-character
text yields 3 chunks and joining the chunks equals the original.

All four are there: context (utils/text.py), goal (a splitting function), constraint (no libraries), definition of done (10,000 characters → 3 chunks, rejoining matches).

For a large task the same four parts unfold into a mini-spec — article 3.15.

What to look for

Too much context is harmful too. Dump the whole project and the important part drowns. Give what relates to the task and point at the rest in one line.

Phrase constraints as "don't", not "only". "Use only the standard library" is sometimes read as a preference. "Don't add new dependencies" works more reliably.

A definition you cannot check is not a definition. If you don't know how you will check the result, the task is not fully stated. That is a signal to go back to step 1 of the working cycle, not to keep writing the prompt.

The framework version decides more than it seems. aiogram 2 and aiogram 3 are incompatible, React changed its approach after hooks, Flutter changes its API across major versions. Don't name the version and you get code for whichever one was most plentiful in training.

Cheat sheet

  • Four parts: context, goal, constraints, definition of done.

  • Context is what the AI can't see. Always: framework, version, file.

  • Write constraints as "don't do", not "only do".

  • A definition of done must be checkable: a condition, not an adjective.

  • If you don't know how you'll check the result, the task isn't stated yet.

  • A missing part gets filled in by the AI.