Guide to AI-assisted engineering
Proven techniques and workflows to maximize AI coding tool adoption and developer productivity
Justin Reock
Deputy CTO
Rolling out AI code assistants is becoming a key priority for many technology organizations. Despite significant enthusiasm around these tools, achieving widespread developer adoption and optimal usage remains challenging.
Industry research consistently highlights a critical barrier: AI-driven coding requires new techniques many developers do not know yet. Without clear instructions and best practices, developers struggle to integrate these tools efficiently into their workflows, especially when time is limited.
This guide addresses these challenges directly. Drawing from interviews and empirical data collected from AI-savvy engineers across various organizations, it provides concrete strategies for developers on how to leverage the benefits of AI assistants, along with guidance for leaders contained in the appendix. While large language models (LLMs) offer transformative potential for productivity, their impact is contingent on thoughtful adoption. Organizations investing in AI technology must prioritize educating and supporting their developers to unlock the full value of these innovations.
In addition to developer enablement, ongoing measurement of AI adoption and impact is critical for maximizing ROI from AI code assistants. For guidance on how to measure AI’s impact on productivity, see How to Measure GenAI Adoption and Impact. GenAI assistants have the capacity to be transformative productivity boosters, but just like any other technology investment, success requires diligence and advocacy.
How to use this guide
This guide is split into three sections, each of which can augment and enhance utilization and integration of AI code assistants into daily workflows. Each section is meant to be utilized in a specific way, as described below:
- Part 1—AI Prompting Techniques - Coding assistants, just like any other tool, can be used optimally or suboptimally depending on the experience and knowledge of the user. This section illustrates some of the practices used by advanced AI users to elicit the best responses from GenAI models.
- Part 2—Recommended Use Cases - Here, the top ten most valuable use cases for AI are outlined, according to self-reported stack ranking of use cases based on perceived time savings. Distribute these use cases to individual engineers, and ensure that users are not blocked from taking advantage of them.
- Leadership strategies for encouraging AI use - (Found in Appendix Section 1) Meant for engineering leaders who will distribute this guide to their developers, this section will outline the behaviors and responsibilities of leadership for driving success of AI initiatives within an organization.
PART 1: AI Prompting Techniques
Best practices for maximizing AI code assistants’ value
Before promoting specific use cases for GenAI code assistants, first realize that there are optimal and suboptimal ways to engage with this technology. The modes and format in which we prompt code assistants can be the difference between mediocre and truly invaluable results. This section is based on interviews with senior leaders across multiple companies who have successfully rolled these assistants out to their organizations and seen positive results, and will outline some of the most important practices.
1.1 Meta-prompting
Meta-prompting is the technique of embedding instructions within a prompt to help a model understand how to approach and respond to the task. Meta-prompting is both art and science, and deserves its own guide. The essence of meta-prompting lies in understanding that as “human” as the output of these assistants can seem, fundamentally they are still being generated by code algorithms and the format in which they are prompted can make a big difference in the usefulness of the output created, especially for more complex prompting and when utilizing a reasoning model.
Note that meta-prompting can also incorporate metaprogramming techniques, such as using a structured prompt to ask the LLM to create an even more precise and efficacious prompt, similar to the examples in below sections on Prompt-chaining or recursive prompting and Brainstorming and planning.
Meta-prompting can reduce the need for back-and-forth clarifications with the model, and give you more control over the output from the model. To create a good meta-prompt, think about the structure of your prompt and which details will be most useful to create the right output.
As an example, instead of a simple prompt like:
❌ Don't
Fix this Spring Boot error: [error details]
Consider structuring the prompt in a way that lays out a complete explanation in a desired format, such as:
✅ Do
Debug the following Spring Boot error: [paste error details]
- Identify and explain the root cause.
- Provide a fixed version of the problematic code.
- Suggest best practices to prevent similar issues in the future.
Output should follow this format:
Error Message & Stack Trace (Summarized).Root Cause Analysis (Explain why the error happened).Fixed Code (With comments).Preventive Measures (Best practices to avoid this issue).
1.2 Prompt-chaining or recursive prompting
One of the most powerful best practices that can be utilized is to create a full workflow rather than a single prompt, where the output of one prompt becomes the input to another. You can chain multiple tasks together that build on the previous output, and even switch model types in between.
A textbook example of this is to start with an assistant brainstorming conversationally, and then take the transcript of that conversation and use it as input to create a blueprint or design specification. That design specification can then be fed into a reasoning model to break the specification into individual units of work, and those units can even be fed into a code generating model to create a code outline.
As an example, you can start with an LLM optimized for chat, such as ChatGPT 4o, and prompt the model to have a conversation about solving a particular problem. You can then feed the transcript of that discussion into a reasoning model, such as ChatGPT o1, to develop a step-by-step blueprint to create the application.
A simple example of this could be:
✅ Do
I am a mobile developer, and you are a senior React Native architect. Let’s have a brainstorming session where you ask me one question at a time about the following requirements, and come up with a specification. I have a mobile application that currently uses two separate code bases and build processes for iOS and Android. I want to migrate this app to React Native so that I can unify the codebase and build process.
The LLM will then ask you a series of questions about the app, as it gathers information to produce a blueprint.
As an example, the first question the LLM asks might be:
1. What are the main features and functionalities of your existing mobile app across both iOS and Android?
(Think screens, workflows, integrations, and anything that might differ between platforms.)
After a series of questions, one at a time as specified, the LLM will let you know that it has reached its final question, with output such as:
14. Final question (for now): Are you targeting just phones, or does the app also need to support tablets or other form factors?
Once you answer the final question, the LLM will build a blueprint specification:
App Overview
Purpose: Remote control of Linux servers via persistent SSH sessions.
Current Setup: Separate native codebases for iOS and Android.
Goal: Unify codebase and build process using React Native.
Authentication
Password-based and SSH key authentication.
Credentials can be stored using secure storage APIs.
No biometric unlock at present.
Functionality
Connect to server using hostname + auth.
Maintain persistent SSH session using libssh.
Execute UNIX commands from a predefined palette with parameters.
Display command output as a scrollable text log.
Use of clipboard functionality (e.g., copy/paste commands).
You can then use this specification with a reasoning model to create a step-by-step process, including prompt examples, which can be followed to create the app. Meta-prompting can ensure that the output follows a repeatable process.
For another example of this, see the Brainstorming and Planning example in the use cases section of this guide.
1.3 One-shot or few-shot vs. zero-shot prompting
Similar to meta-prompting, providing examples of the kind of output you are looking for can result in much more accurate and comprehensive results from the assistant. This can help the model learn from existing examples and provide better structure in its output. A zero-shot prompt simply asks the assistant to produce some output without scoped precedent, whereas a one-shot (providing a single output example) or a few-shot (providing multiple examples) can save multiple cycles of refining and improving answers.
Instead of a simple prompt like:
❌ Don't
Write a Spring Boot REST API with a /hello endpoint
Which will output a fairly generic code structure that may not contain necessary layers and practices.
Instead consider a prompt such as:
✅ Do
Here is an example of a structured REST API design:
@RestController
@RequestMapping("/users")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping("/{id}")
public ResponseEntity<UserDTO> getUser(@PathVariable Long id) {
return ResponseEntity.ok(userService.getUser(id));
}
}
Now generate a HelloController that:
Uses a HelloService layer.Returns a DTO instead of plain strings.Follows RESTful response conventions (ResponseEntity, proper status codes).
1.4 System prompt updates for better accuracy
Most enterprise AI solutions will allow you to update the “system prompt” that underlies every prompt sent to the assistant. This prompt can be as simple as “You are a friendly and helpful code assistant focused mainly on Java and Spring techniques” to a long prompt built to contain a full list of practices that make sense for the engineering team. This is almost like templating, in that the rules contained in this prompt will be applied to every prompt sent into the assistant.
One of the most effective ways to use this system prompt is by creating a feedback loop between users of the assistant and the model owners who configure the assistant platform organizationally. When the model creates inaccurate or suboptimal output, in many cases that output can be corrected going forward by changing the system prompt.
💡 PRO TIP: Establish a feedback process where developers can report bad model behavior, in the form of a ticket or some asynchronous feedback mechanism like a Slack channel, and let that inform the model owners to update the system prompt to achieve better accuracy.
Much like updates to assets like linting configuration and other code style guides, continuous feedback and improvement of system prompts will lead to long-term improvements in accuracy and reliability.
1.5 Multi-model or adversarial engineering
A great benefit of using AI models to help with your work is that, at least at this point, they have absolutely no ego or attachment to the work that they have produced. So, they can objectively compare solutions across multiple models and tell you whether they believe their own solution is inferior or superior to other solutions from other models. You can accomplish this by following a basic workflow like:
- Define the task – Choose a bug-fixing problem (e.g., a faulty factorial function in Java).
- Prompt both AI models – Ask Model A and Model B (and C, D, E, etc, if you like) to fix the bug.
- Adversarial cross-testing – Feed each model’s output into the other AI for evaluation, asking the model if the solution is correct
- Evaluate feedback – Identify which model catches more issues or optimizes the code.
- Declare a winner – Decide based on correctness, robustness, and performance insights.
You aren’t limited to two models here if you really want to extract the best solution. You can feed the solutions to as many models as you want, and you will get objective analysis over which model produced the best results.
1.6 Multi-context: use images and voice prompting
There are more ways to engage with copilots than just typing in prompts. Participants reported that voice-to-text prompting can speed up code assistant usage by 30% or more. Using images such as flow charts and roadmap visualizations can reduce the amount of prompting and typing considerably.
💡 PRO TIP: The best generative AI users don’t limit themselves to simple text chat. If you are planning to brainstorm a code spec from a requirements document, consider prompting the assistant using uploaded diagram images from the document instead of describing the process. And when conversing with an AI agent, remember that using voice and microphone input can speed up tasks considerably.
Let’s say you wanted to create a React app to implement the following decision tree:

Rather than describe each option and resulting outcome, you can upload the image to the LLM and provide a prompt similar to the following:
Implement the attached decision tree visually in React. Create a graphical interface that draws a button for each decision option, and then outputs one of the answers based on the selections made by the user once the final option is selected.
Which will output a code solution similar to the following:
import React, { useState } from "react";
function DecisionTree() {
// Tracks which decision question to show and the user's selections
const [step, setStep] = useState(0);
const [indoorsOrOutdoors, setIndoorsOrOutdoors] = useState(null);
const [aloneOrGroup, setAloneOrGroup] = useState(null);
const [finalAnswer, setFinalAnswer] = useState("");
// Resets all choices (optional helper function)
const reset = () => {
setStep(0);
setIndoorsOrOutdoors(null);
setAloneOrGroup(null);
setFinalAnswer("");
};
// Once we have "indoors/outdoors" and "alone/group," we decide the final activity
const decideActivity = (io, ag) => {
let activity = "";
if (io === "indoors" && ag === "alone") {
activity = "Read a Book";
} else if (io === "indoors" && ag === "group") {
activity = "Play a Board Game";
} else if (io === "outdoors" && ag === "alone") {
activity = "Take a Run";
} else if (io === "outdoors" && ag === "group") {
activity = "Play Pickleball";
}
setFinalAnswer(activity);
setStep(3); // move to final step
};
// Renders the appropriate step
const renderStep = () => {
if (step === 0) {
return (
<div>
<h2>Will I be Indoors or Outdoors?</h2>
<button
onClick={() => {
setIndoorsOrOutdoors("indoors");
setStep(1);
}}
>
Indoors
</button>
<button
onClick={() => {
setIndoorsOrOutdoors("outdoors");
setStep(1);
}}
>
Outdoors
</button>
</div>
);
}
// After choosing Indoors/Outdoors, we ask "Alone or in a Group?"
if (step === 1) {
return (
<div>
<h2>Am I Alone or In a Group?</h2>
<button
onClick={() => {
setAloneOrGroup("alone");
decideActivity(indoorsOrOutdoors, "alone");
}}
>
Alone
</button>
<button
onClick={() => {
setAloneOrGroup("group");
decideActivity(indoorsOrOutdoors, "group");
}}
>
Group
</button>
</div>
);
}
// Final step: show the result
if (step === 3) {
return (
<div>
<h2>Your Activity:</h2>
<p>{finalAnswer}</p>
<button onClick={reset}>Start Over</button>
</div>
);
}
};
return (
<div style={{ margin: "2rem" }}>
<h1>What Should I Do Today?</h1>
{renderStep()}
</div>
);
}
export default DecisionTree;
Of course, this is a relatively simple example meant for illustrative purposes, but advanced reasoning models can interpret much more complicated diagrams with remarkable accuracy.
1.7 Understand determinism and non-determinism
Embracing and understanding determinism in generative AI solutions is crucial for ensuring the right level of consistency, predictability, and reliability of outputs based on use case. Generative AI models operate on the principle of token-based probability distributions, where each generated token (i.e. a word, sub-word, or even a single character) is influenced by prior context and model parameters. Determinism can be controlled using temperature, a system parameter that adjusts the randomness of token selection.
A lower temperature (i.e., “0.1” as opposed to “0.9”) makes the model more deterministic by favoring high-probability tokens, leading to consistent and repeatable outputs. Conversely, a higher temperature (i.e., “0.9” or above) increases randomness, fostering creativity but reducing predictability. Applying AI best practices involves selecting appropriate settings based on the intended use case.
💡 PRO TIP: For scenarios requiring high reliability, such as code generation, low-temperature settings ensure consistency, enabling repeatable results across multiple prompts. Conversely, creative applications, like brainstorming assistants, benefit from higher temperatures and diverse sampling strategies to encourage novel solutions.
By carefully learning about and managing these parameters, organizations can optimize generative AI solutions for both precision and adaptability.
PART 2: Recommended Use Cases
The top 10 most valuable use cases for AI
This section outlines the top ten most valuable use cases for AI according to self-reported stack ranking of use cases based on perceived time savings. It’s recommended that leaders distribute these use cases to individual engineers, and ensure that users are not blocked from taking advantage of them.
Additionally, the techniques in this section include prompting examples as well as sample code output. The examples span a range of popular languages, and similar results can be produced with any mainstream language.
Below are the most time saving use cases for AI code assistants, as self-reported by our research partners. See Appendix II for more details on the research methodology and scoring. This sample is based on a survey of developers who have self-reported at least an hour of time savings a week using AI assistants.

2.1 Stack trace analysis
AI-powered stack trace interpretation quickly identifies root causes of errors, saving time diagnosing and fixing runtime issues. Make it a knee-jerk reaction any time a stack trace is generated with an error to ask the code assistant to explain the error, rather than manually parsing it.
Prompt Example:
Analyze this Java stack trace and suggest the root cause and potential fixes:
[Insert stack trace and additional error detail if appropriate]
2.2 Refactoring existing code
AI-assisted restructuring of legacy code improves readability and efficiency, enabling large-scale, consistent refactoring. Before manually refactoring code, see what suggestions are made by a code assistant.
Prompt example:
Refactor this Java function to improve readability and efficiency: [Insert longer explanation, context, and code]
2.3 Mid-loop code generation
Use AI to generate scoped blocks of code by providing a code outline or function description and asking the AI to finish the work.
Prompt example:
Complete this Java function: [Example Function and additional context, metaprompts, etc]
2.4 Test case generation
Rapidly generates test cases to ensure robust code coverage, reducing manual effort.
Prompt example:
Select "Generate Tests" from the Copilot inline menu, or you can use a prompt like:
"Generate JUnit test cases for the following Java class: [Insert class]"
This approach may send TDD fans into a tailspin, but, don’t worry, you can take the opposite approach as well! You can design your tests first if you’d rather, and then feed those tests into a similar prompt:
Create a code outline for a Java class that will pass the following JUnit tests:
[paste in tests]
You can then use mid-loop code generation to take the code further.
2.5 Learning new techniques
AI assisted learning accelerates onboarding to new frameworks and libraries. You can ask the code assistant to explain various aspects of the code and get friendly results.
Prompt example:
I have five years of experience writing Java and Spring. Show me how to create a Java 24 virtual thread in Spring.
2.6 Complex query writing (SQL, Regex, CLI Commands)
Sometimes developers will need to generate complex patterns or queries such as regular expression patterns or SQL queries. Rather than context switch to a different coding or pattern framework, AI coding assistants can generate code-native expressions for you.
Example prompt:
Step 1: Create a regular expression that will parse timestamps, usernames, IP addresses, user actions, and transaction ids from log data in this format:
[2025-03-14 12:35:29] INFO User: jdoe | IP: 192.168.1.10 | Action: LOGIN_SUCCESS | TXN: A12B3C
Step 2: Generate Java code that will integrate this Regex
2.7 Code documentation
Once you’ve finished writing some code, a code assistant can help you comment that code for better understandability and readability. It can also generate actual documentation in markup formats like AsciiDoc and LaTeX.
Example commenting prompt:
Generate useful comments for this code to make the code easier to understand:
[Example Code]
Example documentation prompt:
Generate documentation for this code in AsciiDoc markup format for this code meant to be read by other developers.
2.8 Brainstorming and planning
Using a generative AI tool to plan out your work can be very effective, especially when using a recursive workflow as described in the workflows and prompting techniques section above.
💡 PRO TIP: You can begin with a discussion about your work, and from that, generate a code spec and even a scaffolded project.
Example prompt 1 (remember that voice prompting is faster than typing!):
I am a product manager and you are a senior software architect. Let's have a brainstorming session where you ask me one question at a time about these requirements, and come up with a specification that I can hand to a software developer. I want to design an application that will create an ElasticSearch index for a large table stored in Cassandra. Help me design a bulletproof, zero-loss system to do this.
As powerful as this process is already at this stage, especially when realizing that it is entirely autonomous to the developer, we can take this workflow even further by scaffolding code from this specification, and then use mid-loop code generation on that scaffolding to generate a draft of the application code itself.
💡 PRO TIP: This approach, now commonly referred to by many as “vibe coding,” can take us from a straightforward conversation with an assistant to a full code outline with minimal work left to do to refine the code by the developer.
2.9 Initial feature scaffolding
With any coding task, sometimes the hardest part is just getting started, understanding how your application outline will be shaped, and coming up with an initial set of classes or functions. With minimal prompting, a code assistant can help you frame your work.
Example prompt:
Create the code outline for a Java application that will listen on a Kafka topic and create a multicast pattern to a Postgres endpoint, a RESTful POST endpoint, and an SMTP endpoint.
2.10 Code explanation
Rather than pore over unfamiliar code or try to chase down the initial authors of the code, a code assistant can provide valuable insights into the functionality of existing code. This can be especially helpful when trying to interpret code in frameworks you may be less familiar with.
Example prompt:
Explain the purpose of each annotation in this Spring Boot controller class:
[Insert code]
Closing
By strategically adopting AI code assistants and integrating effective best practice and workflows, engineering teams can maximize the ROI from their GenAI investments. Leaders should prioritize structured prompting, AI-assisted debugging, and automation of repetitive coding tasks. Measuring impact and encouraging AI adoption will lead to long-term efficiency gains.
Next steps:
- Utilize this guide as a reference for integrating AI into your development workflows.
- Determine a method for measuring and evaluating GenAI impact, such as DX’s GenAI Impact Reports. For more guidance, see How to Measure GenAI Adoption and Impact.
- Share this guide with leadership, and ask them to cascade practices and use cases.
- Track and measure AI adoption and iterate on best practices, using our GenAI Impact survey template can be a great place to start
Appendix I: Leadership strategies for encouraging AI use
Successful deployment of transformational technology always starts from the top, and AI code assistants are no exception. As a leader in your organization, you can proactively engage in the following behaviors and habits to drive widespread adoption and longevity.
Strategy | Description |
|---|---|
Executive buy-in | If you are an executive, encourage adoption and education from the top down. If not, find an executive sponsor who will support this initiative and keep them informed of metrics and rollout progress. |
Unblock usage | Make sure that there are no impediments to using code assistants for the use cases called out in this document. Proactively seek ways to limit barriers to adoption, including running models on-premise and training locally on code repositories. |
Evangelism of metrics | Measure GenAI impact using tools such as DX's GenAI impact reporting. Advertise and evangelize these metrics to teams. Showcase teams with particularly good adoption and velocity improvements to drive healthy competition |
Reduce fear of AI | Frame AI adoption as a force multiplier for performance, unlocking organizational capabilities. Remind engineers that these tools are meant to augment capabilities and transcend what was possible before, not replace jobs. |
Compliance and trust | Validate AI-generated code through human oversight and verification. Ensure proper testing gates exist to limit change failures. If your culture already embraces test-driven design, then continue that practice and continue to run your battery of linting and testing against output code. |
Employee success | Developers who leverage AI will outperform those who resist adoption. Remind engineers that this is an opportunity to learn about techniques that are likely to benefit them for the remainder of their careers. |
Elevate non-builders in the organization | Why pay a full stack developer to work on tasks of relatively low sophistication, when you could augment someone like a product manager with an AI assistant and produce the same work? Not only can this be more cost-effective per resource, it can also reduce operational friction by skipping the translation step of explaining project requirements to development teams. |
Appendix II: Research methodology and partners
Systems data and LinkedIn polling was used to discover heavy AI code assistant users, and those users were surveyed directly using DX Studies for DX users, and Google Forms for non-DX users. Several interviews were conducted from S-level leaders of large enterprise teams who have successfully rolled out code assistants.
Participant questionnaires
Whether through a Google Form or a DX study, participants are asked the following questions:
- Rank your top five AI assistant use cases in terms of your perceived time savings with each. Example: 1) Unit test case generation 2) Stack trace analysis 3) Code documentation 4) Learning new techniques 5) Refactoring existing code"
- Describe your typical AI code assistant workflow. Example: “Ideate a spec using conversational prompts → Feed the spec to a reasoning model to create a plan → Feed the plan to a codegen model to create the source → Test using normal conventions.”
- Which AI use cases have you found valuable in terms of improving the efficiency and quality of your code? “Example: Vulnerability detection, optimization of existing code, comment generation”
Responses to question #1 were then graded on a numeric descending point scale, and those points were tallied and used to stack rank the use cases. For instance, responses to question 1 were tallied as 5, 4, 3, 2, and 1 points respectively, where response number 1 was given 5 points, response two given 4, and so on.
Research partners
DX would like to specifically thank the following beta readers and research partners who took part in the above survey and asked to be named in this study:
- André Nabais of Sparksoft
- Bruce Gruenbaum of Intagere, LLC
- Edward Schauman-Haigh of Odevo
- Levi Geinert of IT Revolution
- Mrina Sugosh of TinyMCE
- Paul Wedzielewski of Fiserv
We also want to extend our thanks to the dozens of participants who wished to remain anonymous, without whom this study would have been much less comprehensive.