I'm stopping Kube.ist as a full product. Its scope has grown too large, and I'm already taking its smaller agents into client work.
It feels a bit like finishing a TV series I've been deeply invested in, there's that “what now?” feeling after having this thing to come back to for so long. Stopping leaves me deflated and a bit lost for a few days. I still care about the work in those agents. I've put effort into keeping them efficient, careful with permissions and economical with memory, and I can see uses for them beyond the platform they came from. Each has a job I can keep improving, though I don't want to make rescuing every file an obligation. I'm keeping the pieces that have another job to do.
A smaller thing to ask a client to adopt
One client runs in the cloud and another has its own machines. Both already have tools they know.
I'm realising how much adopting the platform asks of a client. There's installation, access, integration and a new set of things to understand. I might only be helping with a release. Why am I explaining a whole way to run applications?
The jobs keep coming up. Releases to get out, systems to connect, builds needing to patch files safely.
An agent gives me a smaller conversation. Here is the job it does, here is what it needs access to, and here is how it connects to what you already run. We can get on with the job. No platform to adopt along the way.
Easier to sell. And it's easier for me to finish. Does the agent do the job the client needs? I can work towards an answer. The whole platform keeps supplying another thing to build.
Let the workflow request the change
One agent I'm already reusing for clients handles CI/CD patches to Git. The workflow requests the change, and the agent performs the repository write. No write credentials for the workflow.
What may the request change?
A build produces a new application image, but suppose Git's deployment configuration still names the old one. The build requests an update to that reference. The agent handles the request and writes the change to Git, then the client's existing GitOps tooling follows the commit. What is the build allowed to ask for?
The permissions keep my attention because a Git change can become a production change. The workflow needs an image update. With repository write credentials, it could change more than the image reference.
The agent needs to authorise the request. Is this caller allowed to ask for that update?
The image request needs permission for that update. Arbitrary repository edits must stay outside it. Moving a credential into another process only helps if that process restricts what the caller can ask it to do.
I can explain permission to request a release update. A smaller job than handing over the repository keys.
One agent, different clients
I use hexagonal architecture in the patch agent. It's also called ports and adapters. The core handles requests and decides which updates are allowed, a port says which operations I need, and an adapter connects them to the client's pipeline and repository. A repository integration brings credentials, API calls and its library's own types, so putting those in an adapter lets me work on the update rules without carrying the provider through every part of the job. A client can bring a different connection and still use the same patch service for the same requested job. I can keep working on those rules once, wherever the request comes from.
These are microservices in the client's infrastructure. I think of each as an extensible monolith. Its behaviour and integrations stay in one program, with boundaries between them. I can change and check the task there without arranging several releases to make it work again.
Go suits these agents. I started Kube.ist with a Node.js backend, then wrote more supporting tools in Go. Now I can hand over an executable, with little else needed around it.
A suitable statically linked binary can run in a scratch container image, with supporting files such as HTTPS certificates. Docker's Go guide shows the approach. There's no distribution, shell or package manager in the image, and the process uses the host's kernel.
I don't want a slightly different copy for every client, I'd have to remember which got which fix, then do the work again elsewhere. A fix to request processing can reach every client using the agent when they upgrade, while each keeps its own deployment and permissions.
I appreciate a service whose installation instructions don't involve installing five more services.
I'm tempted to draw interfaces for every service a client might use. I'd be back to designing a platform before delivering the job. I'll add an adapter when there is something to connect. Otherwise I'll rebuild Kube.ist one adapter at a time.
Space to think
Shrinking the image is the easy bit. Once the program starts, its work and runtime decide how much memory it uses, so keeping the agent focused matters there too.
I'm continuing with these agents in client work. There's a job to deliver now, and I can improve the same program as new needs turn up.
Letting the larger project end gives me space to think. After those deflated few days, I can start asking what comes next and get some energy back for it. I still get to build the tools that interest me, without dragging everything I imagined for Kube.ist into the next project.