My Practical AI-Assisted Engineering Workflow
The review loops, context boundaries, and verification habits I use to make AI useful without giving up engineering judgment.
Sources
- https://airc.nist.gov/airmf-resources/airmf/5-sec-core/
- https://owasp.org/www-project-top-10-for-large-language-model-applications/
- https://owasp.org/www-project-top-10-for-large-language-model-applications/2_0_vulns/LLM06_ExcessiveAgency.html
- https://developers.google.com/search/docs/fundamentals/using-gen-ai-content
Article details
Context for reading and verifying this note.
Creation context: AI assisted with research, structure, or drafting. Rizky Romadon reviewed the sources, technical claims, examples, and final publishing decision.
The Short Version
AI is most useful in my engineering workflow when it reduces the cost of examining a problem without taking ownership of the decision. I use it to map unfamiliar code, challenge a design, organize a debugging investigation, propose test cases, and turn engineering notes into documentation.
The workflow is not “prompt, accept, merge.” It is a loop:
- Define the decision I need to make.
- Give the model only the context required for that decision.
- Ask for evidence, risks, and alternatives before asking for code.
- Approve a bounded change.
- Inspect the diff and verify the behavior with normal engineering tools.
- Record what was decided and what remains uncertain.
This article describes how I apply that loop. It is based on the workflows I have documented on this blog, including using ChatGPT for technical design and database documentation and using Claude Code for a numbered refactoring review.
The Workflow Changed When I Separated Discovery From Editing
My early prompts often mixed several jobs together: understand the repository, decide what was wrong, design a solution, edit files, and report the result. That is convenient, but it makes review difficult because the model is discovering the problem while expanding the diff.
The more reliable pattern is to separate discovery from authorization.
In my Claude Code refactoring review loop, I first asked for a SonarQube-style report with numbered findings. Claude did not receive permission to fix the entire report. I reviewed the evidence for each item, chose a number, and authorized only that change. The number became a stable unit for discussion, implementation, verification, and rejection.
That experience gave me a reusable rule:
An AI finding is a review input. It is not permission to change the system.
The same separation works outside refactoring. During architecture work, the first output can be a list of constraints and unresolved questions. During debugging, it can be a map of hypotheses and missing observations. During documentation, it can be an outline that exposes gaps before prose is written.
I Start With a Decision, Not a Role Prompt
“Act as a senior engineer” may influence tone, but it does not define success. I get better results when the prompt names the decision the output must support.
For example:
Decision I need to make:
Should this payment callback be handled synchronously or accepted and processed
asynchronously?
Context:
- callbacks can be retried by the provider
- the database write must be idempotent
- the client needs a response within three seconds
- operations needs a manual replay path
Do not write code yet.
Return:
1. assumptions you inferred
2. failure modes for each option
3. data consistency consequences
4. observations or measurements still missing
5. a recommendation with conditions that would change itThis output is easier to review than a generic architecture answer. It gives me assumptions to correct and conditions to verify. It also prevents a recommendation from hiding behind “best practice.”
My Context Pack Has Four Parts
A model cannot distinguish a real constraint from an accidental omission unless I make the difference clear. I therefore try to provide four types of context.
| Context | What I include | What it prevents |
|---|---|---|
| Objective | The decision or artifact I need | A broad answer solving the wrong problem |
| Evidence | Relevant code, errors, schemas, or notes | Advice detached from the current system |
| Constraints | Compatibility, security, latency, and scope | A clean-looking but unusable solution |
| Output contract | Required sections and stop conditions | Unbounded edits and hard-to-review prose |
I do not paste the whole repository by default. I start with the entry point, relevant types, tests, and configuration. If the answer depends on a caller or dependency not supplied, I want the model to request it rather than guess.
The quality of the context pack matters more than making the prompt long. A large prompt can contain more noise and more sensitive material while still omitting the one business rule that controls the decision.
Five Modes I Use Deliberately
I get more consistent results when I know which mode of assistance I am requesting.
1. Code cartography
The goal is to build a map before changing anything.
Useful outputs include:
- entry points and call paths;
- state changes and transaction boundaries;
- external dependencies;
- authorization decisions;
- tests that currently describe the behavior;
- questions the code alone cannot answer.
I ask for file and symbol references so every claim can be checked.
2. Design pressure testing
Here I already have one or two possible designs. The model's job is to find the conditions under which each design fails.
I ask it to compare options across data integrity, failure recovery, deployment, observability, security, and migration cost. I do not ask for an abstract winner. The output should explain which constraint makes one option preferable.
3. Diagnostic organization
When debugging, I use AI to structure the investigation rather than select a random fix. A representative prompt is:
Symptom:
Duplicate payment events appear after provider retries.
Known observations:
- callback requests share a provider transaction ID
- the event consumer is at-least-once
- duplicates are intermittent
Produce a diagnostic plan with:
- hypotheses ordered by evidence required, not confidence theater
- the log, metric, query, or trace that would test each hypothesis
- a safe reproduction strategy
- changes that must not be made before the cause is knownThis example is representative, not a claim about a specific production incident. Its value is the shape: every hypothesis needs an observation that could disprove it.
4. Bounded implementation
Only after discovery do I authorize a change. I name the allowed files or finding ID, compatibility constraints, verification commands, and a stop condition.
For a refactor, “smallest coherent change” is more useful than “improve the code.” For a new feature, the output contract may require a test first, then implementation, then a diff summary. If the model discovers a larger problem, it should report it without expanding scope.
5. Documentation conversion
I often have useful raw material that is difficult to revisit: design notes, DDL, meeting decisions, review comments, or a debugging timeline. AI can help convert that material into a technical design document, decision record, ERD description, or runbook.
My TSD, ERD, and database documentation workflow works because the database definition remains the evidence. The model organizes and explains it; it does not become the source of truth.
I Use a Risk Ladder for Permissions
Not every AI action deserves the same level of review. I use a simple risk ladder.
| Level | Example | My default control |
|---|---|---|
| Read | Summarize code or documentation | Verify important references |
| Propose | Produce a report, plan, or patch suggestion | Review evidence before action |
| Edit | Modify repository files | Limit scope and inspect the diff |
| Execute | Run tests, build, or safe diagnostics | Approve known commands and inspect output |
| External effect | Deploy, publish, delete, or send | Require explicit authorization at action time |
The boundaries become more important as tools gain agency. OWASP's guidance on excessive agency recommends minimizing functionality, permissions, and autonomy, and requiring approval for high-impact actions. NIST's AI Risk Management Framework similarly emphasizes defined human-AI roles, oversight, testing, and documented responsibilities.
In practice, this means a read-only code review can be broad, while an edit request should be narrow. A generated deployment plan is not permission to deploy. A draft message is not permission to send it.
Sensitive Context Is a Data-Handling Decision
I do not paste secrets, access tokens, private keys, unredacted customer data, or confidential production payloads into a prompt. That rule sounds obvious, but engineering context often contains sensitive information indirectly: log lines, database exports, stack traces, screenshots, internal hostnames, and support tickets.
Before sharing context, I ask:
- Is this information necessary for the decision?
- Can identifiers or values be replaced without losing the behavior?
- Does the selected tool and account have an approved data-handling policy?
- Can I reproduce the issue using a synthetic fixture?
- Will the generated output itself contain sensitive material?
OWASP identifies sensitive-information disclosure as a core LLM application risk. A prompt instruction such as “do not reveal secrets” is not a substitute for minimizing the data sent in the first place.
Verification Is Part of the Prompt and Part of My Work
I ask the model to propose verification, but I do not outsource the judgment about whether verification is sufficient.
For a backend change, the evidence may include:
- focused unit or integration tests;
- compilation and static analysis;
- an API compatibility check;
- a database migration review;
- a diff restricted to the approved files;
- logs or metrics that would validate production behavior;
- a manual check of the failure path.
The strongest question is not “did the tests pass?” It is “which risk does each test address, and which risk remains untested?” A passing suite can still miss serialization compatibility, authorization, concurrency, or operational recovery.
My checklist for reviewing AI-generated code before merge treats generated code like any other change: domain behavior, data integrity, failure modes, security boundaries, and operations still require human review.
I Keep an Evidence Ledger for Larger Tasks
For multi-step work, I keep a small table in the report or task notes:
| Claim or change | Evidence | Status | Remaining uncertainty |
|---|---|---|---|
| Callback is idempotent | Unique constraint plus integration test | Verified | Provider ID reuse policy |
| Refactor preserves API | Contract test and unchanged schema | Verified | Downstream undocumented clients |
| Timeout is appropriate | Current latency distribution | Pending | Peak-period behavior |
This prevents a polished summary from flattening verified facts, assumptions, and open questions into the same level of confidence. It also makes human review faster because the reviewer can focus on the unresolved column.
What I Still Do Manually
I remain responsible for:
- deciding whether the problem is worth solving;
- supplying the business context the repository does not contain;
- checking that quoted code and documentation are current;
- approving changes and external effects;
- reading the final diff;
- selecting meaningful tests;
- accepting compatibility and operational risk;
- correcting or rejecting the output.
AI can produce a plausible explanation for almost any direction. Engineering judgment is the work of deciding which direction fits the actual system and proving that the change behaves as intended.
A Reusable Session Template
This is the compact template I now adapt:
Objective:
State the decision or artifact needed.
Evidence supplied:
List code, logs, schemas, tests, or documentation.
Constraints:
List compatibility, security, operational, and scope limits.
Current phase:
Discovery | proposal | implementation | verification | documentation
Required output:
Name the sections, evidence format, and verification expectations.
Authorization:
State whether file edits or commands are allowed.
Stop condition:
State exactly where the assistant must stop and return control.The template is intentionally plain. Its purpose is to make the working agreement visible.
Closing Principle
My practical AI-assisted workflow is built around separation: evidence from inference, discovery from editing, proposal from authorization, and implementation from verification.
The more capable the tool becomes, the more valuable those distinctions become. I want AI to make investigation cheaper and alternative thinking easier. I do not want it to make responsibility ambiguous.