Context Driven Development – Agentic Coding

Like most people, I started playing with AI on my phone with a web agent. Gemini on a Samsung Galaxy 24 to be specific. At first, just question and answer, then I began wondering about adopting AI to develop software. I wanted more than just glorified code completion. It was only natural that I would wander on to Gemini CLI in my search. It had a free tier available with my Google account and was a simple npm package install.

I installed Gemini CLI on my M4 mac mini and proceeded to play with a small HTML/JavaScript/CSS frontend UI running with a Rails RESTful API backend. What most term “Vibe” coding. It was eye opening. I was able to produce a RESTful CRUD interface in a generated Rails project. This was powerful but something that Rails could already somewhat perform via a model and controller generator. Then I asked Gemini to generate the client CRUD user interface given the RESTful API data. I was amazed and hooked when it successfully created the html and javascript to utilize the API.

There was a looming, nagging, problem with this “vibe” coding. It wasn’t reproducible! Agile development has taught us much about the software process and shouldn’t be forgotten in the AI era. In fact, it should be reinforced! The first lesson to remember is incremental development. “You’ll find that coding in increments helps you refine and structure the code as you go along. The code is less likely to become complicated or messy; you build the code based on the on-going feedback from writing and testing in increments.”1 Incremental development relies on iteration management that incorporates definition and scope. They lead to reproducible sprints and audit ability. All missing without some form of structure to the agentic coding process.

Gemini Conductor

Enter Conductor, an extension to Gemini CLI. I first learned of Conductor in a Google Developer Blog post. The post, “Conductor: Introducing context-driven development for Gemini CLI”, defines the process of storing your projects context in the codebase. Specifically, defining the keeping of context as a managed artifact stored in persistent Markdown files. These artifacts become part of the codebase via inclusion in the repository.

After installing Gemini CLI and the Conductor extension I ran /conductor:setup on both of my projects. This results in the creation of Product, Tech Stack, and Workflow documents. These establish the project context through introspection of the existing project code base.

Rails 8 RESTful API Context

HTML/JavaScript/CSS UI Context

Now that we had “context”, it was time to define an iteration. Conductor works on a Track concept for an iteration. One defines a /conductor:newTrack in order to establish an iteration to be performed by the agent. After completion of the track definition, a track Specification, as well as a track Implementation Plan have been generated.

The first track in each of my projects was fairly simple. The Rails project needed User Registration and Authentication. A user model existed along with a login that issued a JWT. This would basically be RESTful CRUD of the user model.

The front end had a simple menu protected by JWT validation. The login landing page called the login API, received the JWT, and redirected to the main menu page. It was ready for a Logout Feature that would delete the JWT and return to the initial login landing page.

With Track’s defined, one could now /conductor:implement in order to execute the Implementation Plan’s. The agent utilizes the workflow context to execute the track plan according to the specification and the rest of the project context. The workflow followed a TDD approach by developing test cases and then fulfilling them with code generation. Manual verification direction were generated that identified curl testing of the endpoint in the Rails project. The HTML/Javascript components generated manual user interface manipulation for verification testing.

Interestingly, Conductor, or should I say the agent, picked up on the missing Javascript test harness defined in the project context. It added the necessary components and committed them to the repository tagged as a conductor chore, before beginning implementation on the Logout Feature track.

After the code has been generated and committed, a /conductor:review process can be run. This was mostly overview and generated some linting type issues. Upon completion of the review process, the track can be archived.

Experience Conducting

I’ve completed four iterations with Conductor on the backend, including the addition of Domain end point, a nested Domain Account end point, and a Landing Page. The front end has a half dozen iterations including an About Me page, a Domains page, a Domain Accounts nesting page, Adding the JWT to the about me profile, Globalizing the API End Points, and Dockerization. They’ve been deployed with Kamal into a live environment.

The Landing Page iteration actually caught that the project had been generated as an API only application and made the necessary adjustments to the configuration files. The remaining iterations envisioned include Signup with Confirmation and Password Reset by Email. It can also use a progressive navigation bar for the menu on mobile devices.

Gemini has been caught hallucinating once with improper testing information for an end point. It became confused between users and accounts. This was somewhat deliberate on my part, recognizing the pattern that the model had likely been trained on, along with the slight variation in context for our use case.

It also over committed files to the repository on two occasions that would have caused a breach of the application secrets. On both occasions I rolled back the repository by deleting the branch and re-implementing the iteration. It was a lesson in repository management, both having a repository branched with the track defined, as well as implementing the appropriate .gitignore settings for production secrets files.

Conclusions

A code branch with the track definition becomes the first level of reproducibility. The actual coding implementation becomes reproducible based upon the track specifications. A more macro level of this occurs with the archival process. The iterations taken to arrive at the product have been captured in the conductor archive and stored in the repository along with the codebase!

The most important take way from learning Conductor has been the Meta programming. Using Gemini to generate the track specification essentially becomes meta programming of the development process. The implementation process becomes a guided journey on fulfilling the specifications.

I’ve also found myself looking at old behavioral driven development books like Cucumber2, as well as interface design patterns like Designing Social Interfaces3 . This is in an effort to more accurately articulate the domain model and user experience as context to the ai agent and model. The conclusion would be the flattening of the development space with less emphasis on language syntax and patterns, and more emphasis on architecture and design articulation.

  1. Venkat Subramaniam and Andy Hunt, Practices of an Agile Developer (The Pragmatic Bookshelf, 2006), 116 ↩︎
  2. Matt Wynne and Aslak Hellesoy, The Cucumber Book (The Pragmatic Bookshelf, 2012) ↩︎
  3. Christian Crumlish & Erin Malne, Designing Social Interfaces, (O’Reilly, 2009) ↩︎

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top