Software development in 2026 feels like chasing a moving target.
Every day brings a new "revolutionary" model, a new tool, and a new feature that promises to change everything. Most teams are drowning in the noise and are fundamentally lost on what the actual job of an engineer is anymore.
At the same time, frontier tokens are getting more and more expensive with every model release. Every thinking process can now burn $100s of dollars without meaningfully producing any output
Burning thousands of dollars in API costs has become a bragging right for vibe coders.
So where is up and down in this crazy new world?
To find our footing, we have to start with a few hard truths – axioms we can no longer ignore:
The Axioms
Axiom 1: The Output Gap
We have lost the race on raw output. Even if you want to argue "craft" or "human touch," the sheer volume of agentic code wins by default. If your workflow relies on a human hand-rolling logic, you are the bottleneck.
Axiom 2: The Imperfection/Cost Paradox
Models will never be perfect. They will continue to hallucinate and struggle with the inherent ambiguity of human intent. But while "perfect" models are seeing astronomical cost hikes, "8/10" capability models are becoming 50x cheaper. The smart money is on building systems where the cheap models can succeed.
Axiom 3: The Entropy Constraint
Constraints are mercy. If we limit the possibility space, the LLM finds the solution faster. Language and architecture aren't just "preferences"; they are the primary drivers of complexity. A language with too many "styles" and "best practices" is just an invitation for an agent to fail.
Axiom 4: The Feedback Loop
Feedback loops are the only way to turn a random output into a solution. Clear, binary pass/fail signals allow an agent to iterate toward correctness faster and cheaper. Without well-defined acceptance criteria, you are just rolling the dice.
---
The Consequences
If you accept these axioms, the reality of our industry becomes very clear.
First, if you are still "assisted" coding while a co-pilot suggests completions, you are already being outperformed by the person letting an agent drive the entire build. Manual coding, even when boosted, is simply too slow for the current scale of production.
This equally holds true for looking at the output of an agent that is doing the coding for you.
Few activities can be as mentally draining and yet completely useless as watching an agent think and code.
If you rely on intervention to make your agent succeed, you are doing it wrong. The meme status of having your laptop half open to let your agent run is already a sign that you’re behind. Your agents need to run headless on a server, and only report success via pull requests. Everything else is just wasting your time.
Secondly, zero-shot development of complex systems is a fantasy. Asking an agent to build something abstract in a random language with a random architecture is the fastest way to create an unmaintainable, fragile nightmare. It's a shortcut that leads straight into a dead end.
The new job isn't writing the code; it's defining the constraints and the feedback loops that make the code's success inevitable.
Language and architecture choices
If we accept the fact that we are not writing any of the code itself, the question for the optimal language moves away from personal preference to simply the "best tool for the job."
Let's start with a provocative statement: For almost all projects today, *Golang is the clear default choice.*
The reasoning is purely pragmatic. While Python and JavaScript were designed to make human typing easier through "flexibility," that same flexibility is a liability for an LLM. High-entropy languages allow for infinite ways to solve a problem, most of which are legacy garbage or "clever" hacks. For an agent, this is a hallucination minefield.
Go's constraints are its superpower. Its strict static typing, mandatory error handling, and native race detectors act as a rigid cage for the agent's logic. A compiler warning in Go is a precise, actionable instruction for an LLM to self-correct; an "undefined" error in Node is a forensic guessing game.
From a runtime perspective, the comparison is lopsided. Node.js is a browser engine in a trench coat, trapped by V8’s arbitrary *4GB memory ceiling* and single-threaded event loop. Under the heavy memory pressure of modern AI workloads, Node thrashes and dies. Go manages memory much better and saturates every core on the machine natively, without the "worker thread" hacks that agents consistently botch.
Finally, we have to talk about the "5-year survival test." NPM is a liability, a fragile supply chain of CVEs and libraries that change syntax every minor version (moving from Webpack to Vite to Bun every other week). A project built on that stack is an organic mess that rots in months. Go produces a single, statically linked binary. It has no node_modules drift and no runtime version conflicts. Because the training data for Go is famously boring and idiomatic, the agent isn't pulling from a 20-year dumpster fire of deprecated patterns; it's pulling from a uniform, functional standard.
In the agentic era, you don't pick a language for its "vibes." You pick the one that acts as the most reliable target for an 8/10 model to hit every single time. That is Go.
While writing this, Golang has added a whole new set of features around Generics that dilute the spirit of the language and add layers of abstraction I cannot recommend using for the purpose of having agents write code. So I would strictly add instructions to the agents not to use any of those features and stick to idiomatic Go prior to those additions.
What is my job then?
The job of a software engineer has shifted from producing implementation to providing acceptance criteria for an agent to fulfill.
So once we decided on the most constrained architecture that can get the job done, we need to explain to the agent what output is good and what we want the software to actually do.
Fundamentally, this means we are back to test-driven development. Just that now we are not even writing the tests ourselves.
But let's take a step back and talk about different testing strategies first and what we actually need.
The easiest way to test is to use the unit testing feature of the language we use. The problem here is that this is way too close to the implementation itself. While certainly not a bad idea to instruct our agent to use unit testing and keep test coverage at a consistently high level, this does not solve our problem for a few reasons.
First off, we should not care about what classes, functions or other details are chosen to produce the "correct" output. And we cannot produce a set of unit tests without defining these things in one way or the other. Another problem is the fact that it is trivial for our coding agent to make the same mistake or misunderstanding twice, once in the implementation, once in the test and claim success.
So we need to get further away from the actual implementation. A perfect test is basically treating our software as a black box. We cannot rely on any knowledge about how the software works, only on its observable behavior.
As an example, I've written a testing framework called Dojo (https://github.com/elmacnifico/dojo) that takes this idea and implements it as a transparent wrapper that "taps the wire" and tracks any calls of the software under testing. Meaning any HTTP, database or queue request gets intercepted, inspected and can be evaluated as fail pass criteria either by a static test or an LLM-powered evaluator.
The advantage is that we run the exact same code path as we would in production. Our implementation is not aware it is being tested.
This way we can focus on describing how we expect the code to behave when interacting with APIs or databases and thus describe what we need the agent to implement.
Given a sufficiently strict testing suite, we can completely ignore implementation details and let the agent run headless until it finds a passing variation and makes a pull request.
Of course, this means that our tests need to include things like performance metrics as well as security testing for authentication and other basic functions.
The next step is to wrap all this into a working, reliable CI pipeline that can give any headless agent a proper testing environment.
Once this is established, your job becomes making these constraints 1% better every day. To be more precise in guiding the model to find the correct solution.
Where to next?
Of course, this can only be a starting point on how to set up your software development strategy for the future.
However, I believe that these guiding principles will hold beyond the next big model release.
Until we entirely hand over all steps of software development to an agent, humans will need to express their wishes as exact as possible.
And as much hype as zero-shot demos can produce, the reality of maintaining and continuously developing software that can serve as the base of a multi-million-dollar business will not change quite that quickly.
About EWOR
We back the top tech founders globally with up to €500,000 and bespoke mentorship by unicorn founders.
Learn MoreFollow Us


.png)
.png)
