Iterate progressively
On this page
Iterative development with AI
It’s tempting to ask for everything in a single prompt. But with grok-build-0.1, as with any code model, an iterative approach yields better results. You build progressively, validating each step before moving to the next.
Why iterate?
The limits of a single prompt
A prompt that asks to create a complete authentication system with JWT, refresh tokens, middleware, routes, tests, and documentation will produce a voluminous output that’s difficult to verify and likely incomplete in some areas.
The advantage of iteration
Breaking the same request into steps changes three things, and they reinforce each other. You verify each step before continuing: an error in the foundations—a poor data structure choice, a shaky function signature—is corrected when it costs only five minutes, rather than propagating through all the subsequently generated code. You adjust course along the way: if the first iteration reveals an architecture problem, you address it before going further, exactly as in a design review. And you keep the model focused: a short, targeted prompt systematically produces better responses than a sprawling specification where the model must arbitrate between ten requirements on its own—each turn poses only one question, and it answers it well.
Iteration strategy
Step 1: The foundation
Start with the basic structure, without the details:
“Create the users table schema with Drizzle ORM: id, email, passwordHash, createdAt. Add the corresponding TypeScript types.”
Validate, test, then move on.
Step 2: Business logic
Add the logic on the validated foundation:
“Now, create the registration service in @src/services/auth.ts. It must hash the password with bcrypt, check that the email doesn’t already exist, and insert the user. Use the @src/db/schema.ts schema we just created.”
Step 3: Refinement
Once the logic is in place, refine:
“Add input validation with Zod on the registration service. The email must be valid, the password must have at least 8 characters with an uppercase letter and a digit.”
Step 4: Edge cases
Finally, handle the edge cases:
“What happens if the database connection fails during registration? Add appropriate error handling with clear user messages.”
Referencing previous failures
Iteration also includes learning from errors. If a model suggestion doesn’t work, say so explicitly:
“The previous solution doesn’t work because TypeORM doesn’t support this syntax in version 0.3. The error is: [paste error]. Propose a compatible alternative.”
The model uses this information to avoid reproducing the same error and to better understand your environment.
Adjusting context along the way
Iteration has a less visible but equally valuable benefit: context refines over turns. You discover during development that a configuration file drives the behavior you’re modifying—add it in the next turn. A constraint you hadn’t identified emerges—the middleware must also handle API keys, not just JWTs—specify it when it becomes relevant. An initial hypothesis proves false—correct it explicitly rather than letting the model continue building on it. In a single monolithic prompt, all these discoveries would arrive too late.
“Actually, the authentication middleware must also handle API keys in addition to JWTs. Here is the current key format in @src/config/api-keys.ts.”
When to ask for everything at once
Iteration isn’t always necessary. For simple, well-defined tasks, a single prompt suffices:
- Rename a variable throughout a file
- Convert a callback to async/await
- Add TypeScript types to an existing JavaScript function
- Generate a unit test for a pure function
Key takeaways
- Break complex requests into progressively validated steps
- Each iteration builds on the previous one after verification
- Reference previous errors to avoid repetitions
- Adjust context as discoveries are made
- Simple tasks do not require iteration