The industry is all abuzz with AI this and AI that. Vibe coding is getting a tremendous amount of attention. It purports to be a panacea for non-technical people allowing them to go from raw idea to working application in a matter of hours – or even minutes depending on how ‘click-baity’ the article is.

There are also a lot of people pontificating that AI will replace software engineers and even some showing stats that since the AI explosion open software engineering roles have decreased dramatically. While the stats may be accurate (questionable), the root causes may or may not be related to the advancements in AI.

The reality is that the current AI coding tools will NOT replace software engineers. As you’ll see throughout this post, the amount of oversight needed to produce not only a working application, but one that was written with best practices in mind to be secure, maintainable, and extensible, requires diliegence on the part of the engineer. A truly production ready application cannot today be built purely by vibe coding.

Why am I doing this?

I am personally looking at AI from a different perspective when it comes to software engineering. Rather than looking at it as a means to reducing head count, I believe it holds promise in making existing teams more productive. How many of us have counterparts on the business side that are putting ever increasing pressure on our teams to deliver more, with higher quality, in a shorter period of time? I’d argue all (or nearly all) of us.


In this post, I’ll be sharing my personal first time experience with “vibe coding” using VS Code to create an application. I wanted to understand the limits of what the tools are capable of. To begin with, I set a goal for myself – let the agent generate all the code. Yes, you heard that right. All the code.

Now you may say or be thinking, “That’s a recipe for disaster.” On some level, without foreknowledge of programming and application architecture, that sentiment is well-founded. Had I blindly accepted everything that the agent created, it would have indeed been a mess. But as you’ll see, by treating the agent like a paired programmer, I was able to overcome the agent’s limitations.

As we go through my process, I’ll explain where the tools just got things wrong altogether. I’ll also discuss areas of weakness that I found along the way – of which there are a few.


The App

In my current role as a Principal Software Solutions Architect, I work at a company that delivers software solutions that manage things like hunting & fishing, vessel registrations, licensing, etc. For this reason, I chose to build an application that I have called “Camping Time”. The premise is based on the ability for camp site administrators to set up camp sites for reservation, campers to come and search for camp sites, make a reservation, and make a payment (simulated). Naturally, it includes some cross-cutting concerns like user management. Initially, I’ve kept the number of use cases limited, but plan to expand in the future.

I started the project with a pretty basic architecture. It’s an Angular SPA with a .NET Web API backend. I am hosting the application on Azure using App Services. Early on, for local development, I started with a SQLite database, but pretty quickly converted to using Azure SQL Database, but the overall application architecture remained simple: SPA with a monolithic .NET backend, which also serves the client app from the default endpoint. From a cloud infrastructure perspective, I started the project from day one with Infrastructure-as-Code using Terraform.

Over time, I have extended the architecture significantly. I wanted to test the tool’s ability to properly implement advanced design patterns like CQRS and Event Sourcing – not because the application needed it, but since this is a learning exercise, I wanted to test its ability to properly implement the design.


Requirements

As part of my initial project set up, using the copilot-instructions.md file, I established some architecture guidelines in terms of:

  1. Architecture – including tech stack choice and early design decisions, i.e., modular monolith app with Vertical Slice Architecture (VSA).
  2. Project Structure – I wanted the various aspects of code, docs, scripts, etc. organized a particular way.
  3. Development guidelines – stylistic, convention-based, best practices
  4. Testing – unit testing for business logic, integration testing for more complex, hard-to-unit-test code.
  5. Code quality – including use of async/await, secure coding, naming conventions, and proper exception & error handling.

It is probably obvious, but if I were pure vibe coding as someone without a software background, most of these concerns would be unknown to me. The result would be an application with many issues and would almost certainly not be production worthy.


Prerequisites

For this work, I’m using VS Code version 1.104 which is the latest version as of this writing. I’m using a paid version of GitHub Copilot version 1.372.0. I’m using a number of other VS Code extensions, some for convenience, some because they are required. Here’s the full list I’m currently using:

        "ms-dotnettools.csharp",
        "ms-dotnettools.csdevkit",
        "ms-vscode.vscode-node-azure-pack",
        "angular.ng-template",
        "bradlc.vscode-tailwindcss",
        "esbenp.prettier-vscode",
        "ms-vscode.vscode-jest",
        "ms-playwright.playwright",
        "formulahendry.dotnet-test-explorer",
        "hashicorp.terraform",
        "ms-python.python",
        "hediet.vscode-drawio",
        "davidanson.vscode-markdownlint",
        "ms-edgedevtools.vscode-edge-devtools",
        "gingerturtle.html-preview-pro",
        "ms-mssql.mssql",
        "ms-mssql.sql-database-projects-vscode",
        "ms-mssql.sql-bindings-vscode",
        "ms-vscode.vscode-node-azure-pack",
        "hediet.vscode-drawio"

Getting Started

I chose to approach this a little differently than perhaps the general Vibe Coder. I am treating the agent like a paired programmer. I intend to work alongside the agent. To be clear, so far, it operates somewhat like a junior or intermediate programmer. Keep your expectations aligned with this in mind.

Like any good architect or software engineer will tell you, it is often understated how important it is to be clear with requirements up front. If you can’t articulate how something should be built before you build it, you’ll regret it later.

I gave the agent specific instructions on various aspects of the project. This includes things like:

  1. Application architecture patterns
  2. Technology choices
  3. Use of 3rd party dependencies
  4. Naming conventions
  5. Code structure

Anything that you want the agent to explicitly follow, should be given as instructions to the agent. It’s important to set guardrails. Again, if you don’t explicitly call these guidelines out, the agent will make assumptions. Sometimes it gets it right, other times it won’t. The agent will guess what you want if you’re not explicit. Chances are good, it will get it wrong. So it’s better to be explicit about the things you expect.

Your first step will be to create a copilot-instructions.md file and fill in your details. This file lives in a .github folder at the root of your project. See https://docs.github.com/en/copilot/tutorials/customization-library/custom-instructions/your-first-custom-instructions for more details on how to do this.

Below is the opening section of my copilot-instructions.md file.

We are pair programming to develop a camping reservations application. The goal is to collaboratively write high-quality code that adheres to the project's architecture and design principles.
If you are unsure about any aspect of the code or the requirements, please ask for clarification before proceeding.

- Before making any changes, discuss the changes first and get full details on the requirements. Do not take action without first discussing proposed changes.
- Explicitly ask for clarification on requirements if they are not clear.
- Outline a plan for the changes, including the architecture and design (if applicable), and implementation details. The plan should include a step-by-step breakdown of the changes.
- When starting new work which requires code changes, create a new git branch for those changes.
- After we agree on the architecture and design, generate the code in small, manageable chunks.
- Ensure that all code changes are accompanied by appropriate tests (if applicable).
- Verify the code by running tests and ensuring they pass and for the infrastructure, ensure the Terraform code is valid and can be applied without errors.
- Once the changes are reviewed and approved, update the project documentation, including the architecture diagrams and technology radar.
- When you complete requested changes and they are approved, update the copilot documentation with context, results, and other relevant details.

Some important things of note here:

  1. I established a working relationship with the agent, in other words I want to pair program with it. I’ll give it instructions, but I’ll review its work as we go, specify where it got things wrong, and give it hints as to what it should be looking at or for.
  2. I expect high quality code – subjective, I know…But this becomes important later as we’ll see that the agent will consult with external sources on matters of best practices. This is helpful if you have a general idea of how something should work but don’t know specifics.
  3. I want to incorporate testing as part of the development process. This is an area where the agent seems to have a lot of strength.
  4. I want documentation to be part of the project – including architecture docs, diagrams, etc. This is also an area where the agent can be particularly powerful.

The copilot-instructions.md is invaluable in establishing a “contract” between me and the agent.

💥However, and this is important to understand, even with the instructions, the agent will sometimes forget and will ignore an instruction. It forgot some details that I had included in my instructions. I had to remind the agent about that. It happily apologized for the oversight and corrected the things it got wrong. One in particular was that I wanted it to discuss all changes before actually making them. It forgot this instruction the most. The key takeaway is that you can’t just blindly accept the output from the agent. You must review the output and guide the changes you expect it to make.💥


The Experience So Far

Scaffolding

When starting the project, having established the set of instructions I want the agent to follow, the first few rounds of coding went quickly and relatively painlessly. I quickly saw gaps in my instructions, made updates, and corrected the agent. It made changes according to my feedback. This felt very conversational. ✅

The initial scaffolding of the project was done well and quickly. After giving the agent an initial set of domain contexts that I wanted to include in my functionality, it produced working code for those areas. It generally followed my instructions for code structure, etc. ✅

A Working Dev Environment

The next area that I tackled was the creation of the Terraform that I wanted to create to get the Azure resources spun up to support development and testing. I will give the agent credit here. ✅

➡️ Note: This is an area where the use of agentic AI really shines (in my opinion). If you are new or unfamiliar with a tool, framework, language, etc., this can be a game changer. Assuming you have at least some ideas around how things should be done, the rate of acceleration for you will be incredible. That has certainly been true for me with Terraform.

While I understood the principles of Terraform, I hadn’t written a lot of it – and certainly not from a production point of view. I knew how I wanted the Terraform project structured – modularly – and I knew what I wanted the results to be in terms of resource groups and placement of resources in those, but I was unsure of the specifics of the Terraform configuration. I also paid close attention to the resulting resources that were created. Some of the default configuration choices the agent made didn’t align with my expectations – mainly around security – so I guided the agent towards changes, which it made.

Interestingly, the more troublesome issues I encountered here were NOT agentic in nature – they were limitations in the azurerm support for newer services such as the newly released Redis managed service. It handled it well though. Making use of Azure’s MCP server and docs, it was able to navigate the new features and capabilities and produced well-structured, maintainable Terraform.

Testing

One early area that was a bit painful was in writing integration tests. The agent initially took a simplistic approach to test data generation. It made assumptions about the isolation of tests. ❌

Test failures were mostly due to overlap in test data that was causing tests to fail. I asked it for its opinion on how to solve this (I already knew the answer) and it got it right. It incorporated Bogus into the test project to generate random test data and this resolved the issue. Other areas that the agent’s first pass at writing tests was not successful was in the context of parallel test execution. Some of the test failed due to state related issues during parallel execution. To the agent’s credit, it quickly figured that out, amended the tests, and got things to be green across the board. ✅


MCP Support

A powerful addition to the Copilot agent experience is the integration with various MCP servers – both commercially sourced like Microsoft’s, but you can also build and consume your own.

In my case, I used a number of Microsoft’s MCP servers, including their Microsoft Docs for code sample searches. This is powerful 💥 As published code samples are improved over time, this will help to ensure that the agent is creating code based on well-established and accepted patterns. I would expect that over time, as the MCP server offerings grows, so too will the agent’s abilities.


Tips

Here are some things that I learned from my experience that led to better outcomes.

  1. Keep your chat’s focused. Don’t try to solve all of your issues at once in the same chat. Ask the agent to do a specific task, iterate on that task with the help of the agent, and when you’re satisfied, start a new chat.
  2. Rely on source control! I can’t understate the value of this. By using Git to manage the changes made by the agent, you get an easy button to undo anything the agent does that you don’t agree with. You can quickly roll back changes and start over if needed.
  3. Keep refining your copilot-instructions.md as you go. As you see deficiencies in the results, make additions or changes to this file. The agent does a pretty good job of keep up with these changes, especially if you follow #1.
  4. Don’t blindly trust the agent. Every task you give it should be followed up with a code review. You’d do this with a junior or intermediate software engineer, and you should do it with the agent too.
  5. Ask questions! The best results I had came from a discussion with the agent. Ask it for options. Discuss these with the agent and pick the option you like best.
  6. Ask the agent to discuss all changes and make an implementation plan before it proceeds with the code. In the more recently releases of Copilot, the agent will use this to formulate a todo list and a plan for the implementation. The results are markedly better.
  7. Use the newly released allowed commands capability to whitelist commands that the agent will run on your behalf. 💥But most importantly, don’t do this blindly! 💥 Be careful what you whitelist. Be selective. Allow it to do what you consider safe, but don’t allow auto-execution of anything that you consider unsafe. For example, you may want to control when it runs terraform apply. Or certain bash scripts.

Wrapping Up

In summary, I would say that if you aren’t using AI tools like VS Code + GitHub Copilot you and your team are missing out. Used pragmatically, it has the potential to dramatically boost your productivity.

These tools are constantly improving. With the explosive growth and adoption of MCP, the capabilities of the agent are constantly expanding and improving.

Pick a small project like I did to get your feet wet. I encourage you to try out different models. They exhibit different behavior and your results will vary. Newer releases of Copilot now does auto selection of a model based on what you are trying to do. This should make the results even better, but I haven’t yet tried this feature out.

And finally…don’t wait! Start experimenting with these tools today.


If you found this post informative, please considering subscribing to get new posts delivered to your inbox.

Leave a comment

Trending