
AI Tooling in Non-Greenfield Codebases
It’s 2025 and if you work as a software engineer, you probably have access to an AI coding assistant at work. In this blog, I’ll share with you my experience working on a project to change the API endpoints of an existing codebase while making heavy use of an AI code assistant.
Table of contents
There’s a lot to be said about research showing the capability of AI code assistants on the day to day work of a software engineer. It’s clear as mud. Many people also have their own experience of working with AI tooling causing massive headaches with ‘AI Slop’ that is difficult to understand and only tangentially related to the original problem they were trying to address; filling up their codebase and making it impossible for them to actually understand what it is (or is supposed to be) doing.
I was part of the Split team that was acquired by Harness in Summer 2024. I had been maintaining an API wrapper for the Split APIs for a few years at this point.This allowed our users to take their existing python codebases and easily automate management of Split feature flags, users, groups, segments and other administrative entities. We were getting about 12–13,000 downloads per month. Not something that gets an enormous amount of traffic but not bad for someone who’s not officially on a Software Engineering team.
The architecture of the Python API client is that instantiating it constructs a client class that shares an API Key and optional base url configuration. Each API is served by what is called a ‘microclient’, which essentially handles the appropriate behavior of that endpoint, returning a resource of that type during create, read, and update commands.

API Client Architecture

Example showing the call sequence of instantiating the API Client and making a list call
As part of the migration of Split into the Harness platform, Split will be deprecating some of its API endpoints — these — such as Users and Groups — will proceed to be maintained in the future under the banner of the Harness Platform. Split Customers are going to be migrated to have their Split App accessed from within Harness, and so Users, Groups, and Split Projects will proceed to be managed in Harness, meaning that Harness endpoints will have to be used.

How to mate the API Client with the proper endpoints for customers post Harness Migration?
With respect to API keys, the Split API keys will continue to work for existing endpoints, and after migration to harness they will still be able to work. Harness API keys will work for everything and be required for Harness endpoints post-migration.

Now the fun begins
I had some great help from the former Split (now Harness FME) PMM and Engineering teams who took on the task of actually feeding me the relevant APIs from the Harness API Docs. This gave me a good starting point to understand what I might need to do.
Essentially to have similar control over Harness’s Role Based Access Control (RBAC) and Project information just as we did in Split — I’d need to utilize the following Harness APIs
- Users
- Groups
- Projects
- Invites (to invite users)
- Role Assignments
- Roles
- Resource Groups
- Tokens
- API Keys
- Service Accounts
Not all Split accounts will be migrating at once to the Harness platform — this will be over a period of a few months. This means that we will have to support both API access styles for at least some period of time. I also know that I still have my normal role at Harness supporting onboarding customers using our FME SDKs and don’t have a lot of free time to re-write an API client from scratch, so I got to thinking about what my options were.
Mode Select
I really wanted to make the API transition as seamless as possible for my API client users. So the first thing I figured was that I would need a way to determine if the API key being used was from a migrated account. Unfortunately, after discussing with some folks there simply wasn’t going to be time for building out an endpoint like this for what will be, at most, a period of a few months. As such my first design decision was how to determine which ‘mode’ the Client was going to use, the existing mode with access to the older Split API endpoints, or the ‘new’ mode with those endpoints deprecated and a collection of new Harness endpoints available.
I decided this was going to be done with a variable on instantiation. Since the API client’s constructor signature already included an object as its argument, this I thought would be pretty straightforward.
Eg:
python
split_client = get_client({apikey: 'your-api-key'
/* Syntax highlighting for code blocks */ .hljs-keyword { color: #569cd6; font-weight: bold; } .hljs-string { color: #ce9178; } .hljs-number { color: #b5cea8; } .hljs-comment { color: #6a9955; font-style: italic; } .hljs-function { color: #dcdcaa; } .hljs-variable { color: #9cdcfe; } .hljs-type { color: #4ec9b0; } .hljs-built_in { color: #4fc1ff; } .hljs-operator { color: #d4d4d4; } .hljs-punctuation { color: #d4d4d4; } .hljs-attr { color: #92c5f8; } .hljs-property { color: #9cdcfe; } .hljs-title { color: #dcdcaa; } .hljs-class { color: #4ec9b0; } .hljs-meta { color: #569cd6; } .hljs-literal { color: #569cd6; } .hljs-symbol { color: #ce9178; } .hljs-regexp { color: #d16969; } .hljs-link { color: #3794ff; text-decoration: underline; } .hljs-selector-tag { color: #569cd6; } .hljs-selector-id { color: #ffd700; } .hljs-selector-class { color: #d7ba7d; } .hljs-addition { color: #4fc1ff; background-color: rgba(79, 193, 255, 0.1); } .hljs-deletion { color: #f85149; background-color: rgba(248, 81, 73, 0.1); }
Would then have an additional option for:
python
split_client = get_client({apikey: 'your-api-key'
/* Syntax highlighting for code blocks */ .hljs-keyword { color: #569cd6; font-weight: bold; } .hljs-string { color: #ce9178; } .hljs-number { color: #b5cea8; } .hljs-comment { color: #6a9955; font-style: italic; } .hljs-function { color: #dcdcaa; } .hljs-variable { color: #9cdcfe; } .hljs-type { color: #4ec9b0; } .hljs-built_in { color: #4fc1ff; } .hljs-operator { color: #d4d4d4; } .hljs-punctuation { color: #d4d4d4; } .hljs-attr { color: #92c5f8; } .hljs-property { color: #9cdcfe; } .hljs-title { color: #dcdcaa; } .hljs-class { color: #4ec9b0; } .hljs-meta { color: #569cd6; } .hljs-literal { color: #569cd6; } .hljs-symbol { color: #ce9178; } .hljs-regexp { color: #d16969; } .hljs-link { color: #3794ff; text-decoration: underline; } .hljs-selector-tag { color: #569cd6; } .hljs-selector-id { color: #ffd700; } .hljs-selector-class { color: #d7ba7d; } .hljs-addition { color: #4fc1ff; background-color: rgba(79, 193, 255, 0.1); } .hljs-deletion { color: #f85149; background-color: rgba(248, 81, 73, 0.1); }
Now — I was thinking and questioning how I would implement this.
Recently, Harness Employees were given access to Windsurf IDE with Claude AI. I figured since I could use the help that I would sign on and that this would help me build out my code changes faster.
I had used Claude, ChatGPT, DeepSeek, and various other AI assistants through their websites for small scale problem solving (eg — fill in this function, help me with this error, write me a shell script that does XYZ) but never actually worked with something integrated into the IDE.
So I fired up Windsurf and put in a pretty ambitious prompt to see what it was capable of doing.
Split has been acquired by harness and now the harness apis will be used for some of these endpoints. I will need to implement a seperate ‘harness_mode’ boolean that is passed in at the api constructor. In harness mode there will be new endpoints available and the existing split endpoints for users, groups, restrictions, all endpoints except ‘get’ for workspaces, and all endpoints for apikeys when the type == ‘admin’ will be deprecated. I will still need to have the apikey endpoint available for type==’client_side’ and ‘server_side’ keys.
It then whirred to work, and, quite frankly. I was really impressed with the results. However — It didn’t quite understand what I wanted. The harness endpoints are completely different in structure and methods (and in base url). The result was that I’d get the microclients to have harness methods and harness placeholders in the URLs but this wasn’t going to work. I should have told the AI that I really want different microclients and different resources for Harness. I reverted the changes and went back to the drawing board. (but I’ll get back to this later)
python
class
/* Syntax highlighting for code blocks */ .hljs-keyword { color: #569cd6; font-weight: bold; } .hljs-string { color: #ce9178; } .hljs-number { color: #b5cea8; } .hljs-comment { color: #6a9955; font-style: italic; } .hljs-function { color: #dcdcaa; } .hljs-variable { color: #9cdcfe; } .hljs-type { color: #4ec9b0; } .hljs-built_in { color: #4fc1ff; } .hljs-operator { color: #d4d4d4; } .hljs-punctuation { color: #d4d4d4; } .hljs-attr { color: #92c5f8; } .hljs-property { color: #9cdcfe; } .hljs-title { color: #dcdcaa; } .hljs-class { color: #4ec9b0; } .hljs-meta { color: #569cd6; } .hljs-literal { color: #569cd6; } .hljs-symbol { color: #ce9178; } .hljs-regexp { color: #d16969; } .hljs-link { color: #3794ff; text-decoration: underline; } .hljs-selector-tag { color: #569cd6; } .hljs-selector-id { color: #ffd700; } .hljs-selector-class { color: #d7ba7d; } .hljs-addition { color: #4fc1ff; background-color: rgba(79, 193, 255, 0.1); } .hljs-deletion { color: #f85149; background-color: rgba(248, 81, 73, 0.1); }
OpenAPI
My second Idea was to attempt to generate some API code from the Harness API docs themselves. Harness’s API docs have an OpenAPI specification available, and there are tools that can be used to generate API clients out of these specifications. However, it became clear to me that the tooling to create APIs from OpenAPI specifications isn’t easily filterable. Harness has nearly 300 API endpoints for the rich collection of modules and features that it has. Harness’s nearly 10 MB OpenAPI spec would actually crash the OpenAPI generator — it was too big. I spent some time working on code to strip out and filter the OpenAPI Spec JSON just to the endpoints I needed.
Here, the AI tooling was also helpful. I asked
how can I filter a openapi json by either tag or by endpoint resource path?
can this also remove components that aren’t part of the endpoints with tags
could you also have it remove unused tags
But the problem ended up being that the OpenAPI spec is actually more complex then I initially thought, including references, parameters and dependencies for objects. So it wasn’t going to be as simple as passing in my endpoints I need and proceeding to send them to the API Generator.
I kept attempting to run the filter script generated and then proceeded to run the generator. I did a few loops of attempting to run the script, getting an error, and sending it back to the AI assistant.
By the end I did seem to get a script that could do filtering, but filtering down to just what I needed ended up being still too big for the OpenAPI generator. You can see that code here
For a test, I did start generating with just one endpoint (harness_user) and reviewing the python generated code. One thing that was clear after reviewing the file was that it was just structured so wildly differently from the API Client that I already have. Also there are dozens of warnings inside of the generated code to not make any changes or updates to it. Moreover, I was not familiar with the codebase
python
"""
Generated by OpenAPI Generator (https://openapi-generator.tech)
Do not edit the class manually.
"""
/* Syntax highlighting for code blocks */ .hljs-keyword { color: #569cd6; font-weight: bold; } .hljs-string { color: #ce9178; } .hljs-number { color: #b5cea8; } .hljs-comment { color: #6a9955; font-style: italic; } .hljs-function { color: #dcdcaa; } .hljs-variable { color: #9cdcfe; } .hljs-type { color: #4ec9b0; } .hljs-built_in { color: #4fc1ff; } .hljs-operator { color: #d4d4d4; } .hljs-punctuation { color: #d4d4d4; } .hljs-attr { color: #92c5f8; } .hljs-property { color: #9cdcfe; } .hljs-title { color: #dcdcaa; } .hljs-class { color: #4ec9b0; } .hljs-meta { color: #569cd6; } .hljs-literal { color: #569cd6; } .hljs-symbol { color: #ce9178; } .hljs-regexp { color: #d16969; } .hljs-link { color: #3794ff; text-decoration: underline; } .hljs-selector-tag { color: #569cd6; } .hljs-selector-id { color: #ffd700; } .hljs-selector-class { color: #d7ba7d; } .hljs-addition { color: #4fc1ff; background-color: rgba(79, 193, 255, 0.1); } .hljs-deletion { color: #f85149; background-color: rgba(248, 81, 73, 0.1); }
Either manually or attempting via an AI assistant, stitching these together was not going to be easy, so I stashed this idea as well.
As an aside, I think this is worth noting, that an AI code assistant can’t help you when you don’t even know how to really specify what exactly you want and what your outcome is going to look like. I needed to have a better understanding of what I was trying to accomplish
Further Design Review
One of the things I had in my mind was that I really wanted to make the transition as seamless as possible. However, once my idea of the automated mode select was dashed, I still thought I could, through heroic effort, automate the creation of the existing Split python classes via the Harness APIs.
I had a deep dive into this idea and really came back with the result that it would simply be too burdensome to implement and not really give the users what they need.
For example — to create an API Key in Split, we just had one API endpoint with a json body:
json
{
/* Syntax highlighting for code blocks */ .hljs-keyword { color: #569cd6; font-weight: bold; } .hljs-string { color: #ce9178; } .hljs-number { color: #b5cea8; } .hljs-comment { color: #6a9955; font-style: italic; } .hljs-function { color: #dcdcaa; } .hljs-variable { color: #9cdcfe; } .hljs-type { color: #4ec9b0; } .hljs-built_in { color: #4fc1ff; } .hljs-operator { color: #d4d4d4; } .hljs-punctuation { color: #d4d4d4; } .hljs-attr { color: #92c5f8; } .hljs-property { color: #9cdcfe; } .hljs-title { color: #dcdcaa; } .hljs-class { color: #4ec9b0; } .hljs-meta { color: #569cd6; } .hljs-literal { color: #569cd6; } .hljs-symbol { color: #ce9178; } .hljs-regexp { color: #d16969; } .hljs-link { color: #3794ff; text-decoration: underline; } .hljs-selector-tag { color: #569cd6; } .hljs-selector-id { color: #ffd700; } .hljs-selector-class { color: #d7ba7d; } .hljs-addition { color: #4fc1ff; background-color: rgba(79, 193, 255, 0.1); } .hljs-deletion { color: #f85149; background-color: rgba(248, 81, 73, 0.1); }
However, Harness has a very rich RBAC model and with multiple modules has a far more flexible model of Service Accounts, API Keys, and individual tokens. Harness’s model allows for easy key rotation and allows the API key to really be more of a container for the actual token string that is used for authentication in the APIs.
Shown more simply in the diagrams below:

Observe the difference in structure of API Key authentication and generation
Now the Python microclient for generating API keys for Split currently makes calls structured like so:
python
ws = client.workspaces.find("Defaults"
/* Syntax highlighting for code blocks */ .hljs-keyword { color: #569cd6; font-weight: bold; } .hljs-string { color: #ce9178; } .hljs-number { color: #b5cea8; } .hljs-comment { color: #6a9955; font-style: italic; } .hljs-function { color: #dcdcaa; } .hljs-variable { color: #9cdcfe; } .hljs-type { color: #4ec9b0; } .hljs-built_in { color: #4fc1ff; } .hljs-operator { color: #d4d4d4; } .hljs-punctuation { color: #d4d4d4; } .hljs-attr { color: #92c5f8; } .hljs-property { color: #9cdcfe; } .hljs-title { color: #dcdcaa; } .hljs-class { color: #4ec9b0; } .hljs-meta { color: #569cd6; } .hljs-literal { color: #569cd6; } .hljs-symbol { color: #ce9178; } .hljs-regexp { color: #d16969; } .hljs-link { color: #3794ff; text-decoration: underline; } .hljs-selector-tag { color: #569cd6; } .hljs-selector-id { color: #ffd700; } .hljs-selector-class { color: #d7ba7d; } .hljs-addition { color: #4fc1ff; background-color: rgba(79, 193, 255, 0.1); } .hljs-deletion { color: #f85149; background-color: rgba(248, 81, 73, 0.1); }
To replicate this would mean that I would have to have the client in ‘Harness Mode’ create a Service Account, API Key, and Token all at the same time, and automatically map the roles to a created service account, being seamless to the user.
This is a tall task, and being pragmatic, I don’t see that as a real sustainable solution for developers using my library as they get more familiar with the Harness platform. They’re going to want to use Harness objects natively.
This is especially true with the delete method of the current client,
python
client.apikeys.delete_apikey(''
/* Syntax highlighting for code blocks */ .hljs-keyword { color: #569cd6; font-weight: bold; } .hljs-string { color: #ce9178; } .hljs-number { color: #b5cea8; } .hljs-comment { color: #6a9955; font-style: italic; } .hljs-function { color: #dcdcaa; } .hljs-variable { color: #9cdcfe; } .hljs-type { color: #4ec9b0; } .hljs-built_in { color: #4fc1ff; } .hljs-operator { color: #d4d4d4; } .hljs-punctuation { color: #d4d4d4; } .hljs-attr { color: #92c5f8; } .hljs-property { color: #9cdcfe; } .hljs-title { color: #dcdcaa; } .hljs-class { color: #4ec9b0; } .hljs-meta { color: #569cd6; } .hljs-literal { color: #569cd6; } .hljs-symbol { color: #ce9178; } .hljs-regexp { color: #d16969; } .hljs-link { color: #3794ff; text-decoration: underline; } .hljs-selector-tag { color: #569cd6; } .hljs-selector-id { color: #ffd700; } .hljs-selector-class { color: #d7ba7d; } .hljs-addition { color: #4fc1ff; background-color: rgba(79, 193, 255, 0.1); } .hljs-deletion { color: #f85149; background-color: rgba(248, 81, 73, 0.1); }
The Harness method for deleting a token takes the token identifier, not the token itself, making this signature impossible to reproduce with Harness’s APIs. And even if I could delete a token, would I want to delete the token and keep the service account and api key? Would I need to replicate the role assignment and roles that Split has? Much of this is very undefined.
Wanting to keep things as straightforward and maintainable as possible, along with trying to move to understanding the world in Harness’s API Schema, I had a design decision in my head.
We were going to have ‘Harness Mode’ for the APIs that will explicitly deprecate the Split API microclients and resources and will then activate a separate client that will use Harness API endpoints and resources. The endpoints that are unchanged will still use the Split endpoints and API keys.

Back to AI
Now that I’ve got a better understanding of how I want to design this, I felt like I could create a better prompt.
Split has been acquired by harness and now the harness apis will be used for some of these endpoints. I will need to implement a seperate ‘harness_mode’ boolean that is passed in at the api constructor. In harness mode there will be new endpoints available and the existing split endpoints for users, groups, restrictions, all endpoints except ‘get’ for workspaces, and all endpoints for apikeys when the type == ‘admin’ will be deprecated. I will still need to have the apikey endpoint available for type==’client_side’ and ‘server_side’ keys. Make seperate microclients in harness mode for the following resources:
harness_user, harness_project, harness_group, role, role_assignment, service_account, and token
Ensure that that the harness_mode has a seperate harness_token key that it uses. It uses x-api-key as the header for auth and not bearer authentication
Claude then whirred away and this was with much better results here. With the separate microclients I had a much better structure to build my code with. This also helped me with understanding of how I thought I would continue building.

The next thing I asked it to do was to create resources for all of my microclient objects.

The next thing I did was a big mistake. I asked it to create tests for me for all of my microclients and resources. Creating the tests at this time before I had finished implementing my code means that the AI doesn’t know which one is right or not. So I spent a lot of time troubleshooting issues with tests until I just decided to delete all of my test files and create the tests much later in my development cycle. Once I had the designs for the microclients and resources reasonably implemented, I went forth and had it write the tests for me. DO NOT have the AI write BOTH your tests and your code before you have the chance to review either of them, or you will be in a world of pain and be spending hours trying to figure out what you actually want.
After the Magic
This was an enormous time saver for me. Having the project essentially built with custom scaffolding for me was just amazing.
The next thing I was going to do was fill in the resources. The resources were essentially a schema with an init call to pull the endpoints in and accessors to get the fields from the data.
The schemas I was able to pull from the apidocs.harness.io site pretty easily.
Here’s an example of the AI generated code for the harness group resource.
python
from
/* Syntax highlighting for code blocks */ .hljs-keyword { color: #569cd6; font-weight: bold; } .hljs-string { color: #ce9178; } .hljs-number { color: #b5cea8; } .hljs-comment { color: #6a9955; font-style: italic; } .hljs-function { color: #dcdcaa; } .hljs-variable { color: #9cdcfe; } .hljs-type { color: #4ec9b0; } .hljs-built_in { color: #4fc1ff; } .hljs-operator { color: #d4d4d4; } .hljs-punctuation { color: #d4d4d4; } .hljs-attr { color: #92c5f8; } .hljs-property { color: #9cdcfe; } .hljs-title { color: #dcdcaa; } .hljs-class { color: #4ec9b0; } .hljs-meta { color: #569cd6; } .hljs-literal { color: #569cd6; } .hljs-symbol { color: #ce9178; } .hljs-regexp { color: #d16969; } .hljs-link { color: #3794ff; text-decoration: underline; } .hljs-selector-tag { color: #569cd6; } .hljs-selector-id { color: #ffd700; } .hljs-selector-class { color: #d7ba7d; } .hljs-addition { color: #4fc1ff; background-color: rgba(79, 193, 255, 0.1); } .hljs-deletion { color: #f85149; background-color: rgba(248, 81, 73, 0.1); }
I did a few things here — I had the AI generate for me a generalizable getter and dict export from the schema itself — essentially allowing me to just copy and paste the schema into the resource and have it auto-generate the methods that it needs to have.
Here’s an example of that code for the harness user class.
python
from
/* Syntax highlighting for code blocks */ .hljs-keyword { color: #569cd6; font-weight: bold; } .hljs-string { color: #ce9178; } .hljs-number { color: #b5cea8; } .hljs-comment { color: #6a9955; font-style: italic; } .hljs-function { color: #dcdcaa; } .hljs-variable { color: #9cdcfe; } .hljs-type { color: #4ec9b0; } .hljs-built_in { color: #4fc1ff; } .hljs-operator { color: #d4d4d4; } .hljs-punctuation { color: #d4d4d4; } .hljs-attr { color: #92c5f8; } .hljs-property { color: #9cdcfe; } .hljs-title { color: #dcdcaa; } .hljs-class { color: #4ec9b0; } .hljs-meta { color: #569cd6; } .hljs-literal { color: #569cd6; } .hljs-symbol { color: #ce9178; } .hljs-regexp { color: #d16969; } .hljs-link { color: #3794ff; text-decoration: underline; } .hljs-selector-tag { color: #569cd6; } .hljs-selector-id { color: #ffd700; } .hljs-selector-class { color: #d7ba7d; } .hljs-addition { color: #4fc1ff; background-color: rgba(79, 193, 255, 0.1); } .hljs-deletion { color: #f85149; background-color: rgba(248, 81, 73, 0.1); }
Once this was done for all of my resources, I had the AI create tests for these resources and went through a few iterations before my tests passed.
Microclients
The microclients were a bit more challenging. Partly because of how the methods were really fundamentally different in many cases between the Split and Harness way of managing these HTTP resources.
There was more manual work here and not as much automation. That being said, the AI had a lot of helpful autocompletes.
For example, in the harness_user microclient class, the default list of endpoints looked like this
bash
_endpoint = { 'list'
If I were to change one of them to the proper endpoint (ng/api/user) and then press tab it will automatically fix the other endpoints — small things like that really added up when I was going through and manually setting up things like endpoints, looping over the returned array from a GET endpoint. The AI tooling really helps speed up the implementation.
Once I had the microclients finished, I had the AI create tests and worked through running them, ensuring that we had coverage and the tests made sense and covered all of the microclient endpoints (including pagination for the list endpoints)
Base Client
The last thing to clean up now was the base client. The AI created a separate main harness_apiclient that would be instantiated when harness mode was enabled. I had to review the deprecation code to ensure that deprecation warnings were indeed only fired when specified. I also cleaned up and removed some extraneous code around supporting other base urls, and set the proper harness base url.
I proceeded to ask AI to allow me to pass in an account_identifier since many of the harness endpoints require that — allowing me to make it easier so that you didn’t need to pass that field in each time for every microclient request.
rust
def get_client
Grand Finale
Finally, I had the AI write me a comprehensive test script that would test all endpoints in both harness mode and split mode. I ran this with a Harness account and a Split account to ensure success. I fixed a few minor issues but ultimately it worked very well and seemed extremely straightforward and easy to use.
Lessons Learned
After this whole project I would like to let the reader depart with a few learnings. First of which is that your AI assistant still requires you to have a good sense of code smell. If something looks wrong or your implementation in your head would be different, always feel free to back up and revert the changes it makes. Better to be safe than sorry.
You really need to have the design in your head and constantly be comparing it to what the AI is building for you when you ask it questions. Don’t just accept it — interrogate it. Save and commit often so that you can revert to known states.
Do not have it create both your tests and implementations at the same time. Only have it do one until you are finished with it and then have it do the other.
You do not want to just keep asking it for things without an understanding of what you want the outcome to look like. Keep your hand on the revert button and don’t be afraid to revert to earlier parts of your conversation with the AI. If you do not review the code coming out of your AI assistant you will be in a world of trouble. Coding with an AI assistant still uses those Senior/Staff Software Engineer skillsets, perhaps even more than ever due to the sheer volume of code that is possible to generate. Design is more important than ever.
If you’re familiar with the legend of John Henry — he was a railroad worker who challenged a steam drilling machine with his hammer. With an AI assistant I really feel like I’ve been given a steam driller. Like this is the way to huge gains in efficiency in the production of software.

Learn how to work with your robot and be successful
I’m very excited for the future and how AI code assistants will grow and become part and parcel of the standard workflow for software development. I know it saved me a lot of time and from a lot of frustration and headaches.

