Plenty of advice on prompting for code reads like a list of principles you are supposed to absorb and somehow apply. That is useful for understanding, but it does not tell you what to actually do when you sit down with a real task in front of you. This article is the opposite: a sequence of steps you can follow in order, today, on whatever you are working on.
The process below works for a single function or a multi-file feature. It does not assume a particular tool or language. What it assumes is that you want repeatable results instead of rolling the dice each time. Follow the steps in order, and the quality of your output becomes a function of your effort rather than luck.
Read the whole sequence once, then keep it nearby for your next few tasks. After a handful of repetitions the steps stop being a checklist and become how you naturally think about the work.
Step One: Define the Task in Plain Terms
Before you open any tool, write down what you want in one or two sentences—not as a prompt yet, just as a clear statement for yourself.
State the Behavior, Not the Implementation
Describe what the code should do, not how it should do it. "Validate that a string is a well-formed phone number for US numbers" is a behavior. "Use a regex" is an implementation choice you can leave to the model or specify later. Starting from behavior keeps you from over-constraining before you understand the problem.
Identify the Inputs and Outputs
Name exactly what goes in and what comes out. For our phone validator: input is a string, output is true or false. This sounds trivial, but writing it down forces you to notice ambiguities—does the input include the country code? What about extensions?—before they become bugs.
Step Two: Gather the Context the Model Needs
Now collect the information the model cannot infer. This is the step beginners skip and experts never do.
Pull the Relevant Existing Code
If the new code has to fit into an existing project, find the one or two functions it will sit beside or call into, and have them ready to paste. The model will match their style and structure. Do not paste your whole file—just the pieces that matter.
Note the Environment
Write down the language and version, the framework, and any libraries the model should use or avoid. "TypeScript 5, no external dependencies" is a different request from "TypeScript 5, you may use a validation library." Being explicit here prevents the model from reaching for tools you do not want. The framework article organizes this context-gathering into a reusable structure.
Step Three: Assemble the Prompt
With your task defined and context gathered, build the actual prompt by stacking the pieces in a clear order.
Lead With the Instruction
Start with a direct command: "Write a function that..." Put the core ask first so it does not get buried. Follow it immediately with the inputs, outputs, and behavior you defined in step one.
Attach Context and Constraints
After the instruction, add your context: "Here is an existing function from our codebase for style reference," followed by the code. Then list your constraints as a short bulleted set—error handling, edge cases, libraries allowed or banned, and the response format you want. A clean structure here is:
- The instruction and the behavior
- The environment and example code
- The constraints and edge cases
- The output format you expect back
Step Four: Send It and Read the Result
Submit the prompt, then resist the urge to immediately copy the code into your project.
Read Every Line
Go through the output line by line. You are checking three things: does it do what you asked, does it match your project's style, and does it contain anything suspicious like a function call you do not recognize. Reading first is faster than debugging later. The examples article shows what these reads catch in practice.
Note What's Missing or Wrong
Rather than fixing problems yourself right away, make a quick mental or written list of what is off. You will feed this back to the model in the next step, which is usually faster than hand-editing.
Step Five: Iterate With Specific Feedback
The first result is a draft. Refine it with targeted feedback instead of vague complaints.
Feed Back Errors Verbatim
If you ran the code and got an error, paste the exact error message and ask the model to fix it. The error text tells the model precisely where its assumptions broke. This is the single most reliable way to converge on working code.
Correct One Thing at a Time
If multiple things are wrong, address them in focused turns rather than one sprawling message. "The validation is right, but it should also reject numbers shorter than ten digits" is easy for the model to handle cleanly. A long list of mixed corrections tends to produce partial fixes.
Step Six: Verify Against Reality
Working in the chat is not the same as working in your project. Close the loop.
Run It With Real Inputs
Execute the code with actual values, including the edge cases you identified in step one. For our phone validator, try a valid number, an invalid one, an empty string, and something with letters in it. If any case fails, return to step five.
Generate Tests Alongside
Ask the model to write tests for the code it produced, then read those tests critically—make sure they actually check the behavior you care about and are not just asserting that the code does whatever it happens to do. Mistakes in this verification step are covered in 7 Common Mistakes.
Step Seven: Capture What Worked
Once the code is correct and integrated, take thirty seconds to lock in the gain.
Save the Prompt if It's Reusable
If the task was something you will do again—a type of endpoint, a kind of migration, a class of utility—save the prompt as a template. Next time you fill in the specifics instead of starting from scratch.
Record the Surprises
If the model consistently got something wrong until you added a particular instruction, note that instruction. These hard-won additions become the difference between an average prompt and one that works the first time.
Frequently Asked Questions
How long should this whole process take?
For a small function, a couple of minutes. The defining and gathering steps take seconds once you are used to them, and they save far more time than they cost by preventing rounds of correction. For larger features, the same steps stretch out but the proportions stay similar.
Can I skip steps for simple tasks?
Yes. A throwaway one-liner does not need context gathering or test generation. The full sequence is for code that has to be correct and fit a real project. Match the rigor to the stakes.
What if the model keeps getting it wrong after several tries?
Stop patching and restart. Open a fresh prompt that includes everything you learned during the failed attempts. Accumulated confusion in a long thread is real, and a clean start with better context usually beats a tenth correction.
Do I need to gather context if my tool sees my files?
Less, but not zero. Editor-integrated tools reduce manual context, but pointing them at the specific functions and stating constraints still improves results. The tool handling file access does not replace stating what you actually want.
Key Takeaways
- Define the task as behavior with explicit inputs and outputs before opening any tool.
- Gather the specific existing code and environment details the model cannot infer on its own.
- Assemble the prompt in a clear order: instruction, context, constraints, expected output format.
- Read every line of the result before running it, checking correctness, style, and anything suspicious.
- Iterate with verbatim error messages and one focused correction at a time.
- Verify against real inputs and edge cases, then save reusable prompts and record hard-won fixes.