ARTICLE (Markdown)
From Programming Languages to AI Agents: Every Abstraction Creates New Debt
"If you don’t know assembly, you’ll never be a good programmer."
That one’s been around for a while... When high-level languages began to emerge, some people turned up their noses, thinking that programming away from the metal was "betraying the movement." Personally, I’ve always pictured a few old-school programmers wearing cloaks and wizard hats.
Today, the discussion has taken on a new form:
"If you use Copilot, ChatGPT, Cursor, Claude Code, or any other coding agent, you’ll never really learn."
The idea here is simple: generative AI is not just a super-autocomplete. Large language models (or LLMs, for short) and coding agents are new layers in the software engineering onion — just as high-level languages, frameworks, and the cloud once were.
And, like every good abstraction, they solve some old problems while arriving with those famous technical debts included for free.
I invite you, dear reader, to put on your engineering glasses and look at AI not as an antagonist or a miracle solution, but as yet another layer that changes the battlefield, so to speak.
There will be no "AI replacing developers" narrative or tool comparisons here. Instead, we’ll explore the technical responsibility that comes with this new layer: what to do with what AI generates and what kind of debt it can bring.
We’ll revisit the history of other software abstractions and, at the very end, face this reality: the problem is not that AI writes code, but accepting it without understanding or validating it.
If you want to see the original version of this idea in another format, it was also published as an article on DWCorp’s Arandu platform under "From Programming Languages to AI Agents: Every Abstraction Creates New Debt".
TL;DR

- AI (LLMs and coding agents) is a new programming abstraction, not just an IDE feature.
- Every abstraction brings productivity gains and new debts (trust, validation, security, authorship, and maintenance).
- The risk is not using AI, but accepting generated code without understanding, testing, and reviewing it.
- AI does not automatically turn anyone into a senior engineer; it amplifies practices that already existed on the team.
- Using AI responsibly means treating it like a very fast junior pair: useful, but in need of supervision.
1. AI Isn’t Just Autocomplete; It’s a New Programming Abstraction
These days, opening an IDE often means having some kind of AI companion:
- Copilot suggesting entire blocks of code;
- ChatGPT or Claude Code explaining a tricky function;
- Cursor rewriting entire modules already;
- Coding agents attempting to take over several files at once.
It’s tempting to think that all of this is just about "typing faster." But something deeper is happening.
Just as:
- high-level languages abstracted away hardware;
- frameworks abstracted infrastructure and protocol details;
- the cloud abstracted racks, data centers, cables, and switches...
LLMs and coding agents are beginning to abstract parts of programming itself. You move away from how to write every line and start saying what you want to exist in the code.
It’s not merely an "intelligent autocomplete." It’s more like saying:
"Here’s the requirement. Build something that seems to solve it."
And with every new layer of abstraction comes the same old story:
- gain: construction becomes faster;
- cost: new debts emerge.
The rest of this article explores how this new AI layer changes the engineering game — and what kind of technical debt it can cause if we use it without judgment.
2. A Timeline of Abstractions: Every Solution Brought New Debt
Before focusing on AI, let’s take a quick look at the line of abstractions that has passed in front of us. It’s always the same: we move up a level, gain power, and also create new ways to get things wrong.
2.1. From Low-Level Languages to High-Level Languages
We moved from a world where everything was built with assembly or C, close to the operating system, to Java, C#, Python, Ruby, Go, Kotlin, and their peers.
Clear gains:
- much faster development;
- portability across platforms;
- more expressive and readable code;
- reusable libraries for practically everything.
But the bill came due.
New debts:
- we don’t always know what the compiler or runtime is doing behind the scenes;
- bugs only appear in production, and we don’t know why;
- a dangerous culture emerged:
- "if it compiles, it’s correct."
This is a classic example of trust debt: we trust the intermediary and stop validating.
2.2. Frameworks and ORMs: Eliminating Repetition, Creating Coupling
Frameworks and ORMs soon followed. Spring, Rails, Django, ASP.NET, Hibernate, Entity Framework — the party was on.
Gains:
- productivity through the roof: CRUDs, routing, validation, and dependency injection served on a platter;
- less boilerplate, more focus on business rules;
- conventions aligning the team without endless discussion.
And here comes the bill:
New debts:
- terrible queries hidden behind attractive APIs;
- difficulty optimizing without understanding the generated SQL;
- strong coupling to the framework ("if you want to switch, you’ll practically have to rewrite the system");
- "magic" that works until... it doesn’t anymore.
The typical trade-off here is:
Speed now vs. fine-grained control and flexibility later.
2.3. Cloud and DevOps: Infrastructure as a Service, Complexity as a Contract
Then infrastructure left the rack and moved to AWS, Azure, GCP, and their peers.
Gains:
- scaling without buying physical servers;
- deployment automation, pipelines, and observability;
- teams focusing more on the product and less on hardware.
And the debts?
- surprise costs from leaving a huge cluster running;
- vendor lock-in;
- complex network and security topologies;
- incidents involving half the internal system and half a managed service.
Once again, the abstraction increases power but hides complexity behind contracts.
2.4. AI Joins the Line: Another Layer on Top of Everything
This is where AI enters as a new programming abstraction:
- it is not a total rupture;
- it is another step toward raising the level of the "language" with which we interact with computers.
Instead of programming everything yourself, you delegate part of the responsibility to an AI agent.
The trade-off is different now:
- less effort spent writing;
- more effort spent verifying.
3. What Changes with AI as a Programming Abstraction?

3.1. The Difference Between "Typing Less" and "Thinking Differently"
With AI generating code, initial architecture, tests, and documentation, the bottleneck changes:
- before: "how am I going to implement this?";
- now: "how can I make sure this is correct, secure, and sustainable?"
AI is not just an autocomplete. It becomes something like:
- "build this authentication module";
- "refactor this service into microservices";
- "create tests for this class."
This requires a different kind of reasoning from developers. You are no longer just building; you are specifying, auditing, and correcting a system that "builds" for you.
3.2. Specify Better, Review Better

Imagine:
"Implement JWT authentication in this Spring Boot project."
The AI generates something that looks impressive:
- well-formatted code;
- well-organized endpoints;
- payload examples.
However:
- does it follow your company’s security policies?
- is it aligned with the system?
- does it meet the non-functional requirements?
"I don’t know" cannot be the answer here.
The developer’s role changes from:
- "I’ll implement everything" to
- "I’ll specify, then check whether what came back matches the context."
The metaphor is:
Treat AI as a very fast, very confident intern.
It gets many things right, but review is essential.
3.3. AI as a Steroid-Enhanced Compiler
Think of AI as an "anabolic compiler."
- The compiler translates from a high-level language into an executable.
- AI translates from natural language into code.
In both cases:
- you move up a level;
- you delegate the translation to a tool.
The more you delegate, the more you need to be able to:
- read the result;
- identify inconsistencies;
- test quickly.
If you don’t understand what the compiler or the AI is doing, you’re in deep trouble.
4. The New Debts Created by AI (No Drama, but with Realism)
Let’s be clear: every abstraction creates new debts. AI is no different. The point is not whether you have debt, but which debts you are acquiring without even realizing it.
4.1. Trust Debt: It Looks Right vs. It Is Right
AI tools are dangerously convincing.
The code:
- compiles;
- works on the happy path;
- looks well made.
This activates a bias:
"If it looks good, it must be correct."
But underneath, there may be:
- outdated APIs;
- subtle logic errors;
- concurrency and security issues.
For example, AI generates pagination for an API:
- it works for common cases;
- but ignores details such as stable ordering and large volumes of data.
This is correctness debt. The code is "almost right" — and that "almost" is what gets you.
4.2. Validation Debt: Do Tests Become Optional?
Teams without a testing culture can get worse with AI:
- before: little code, few tests;
- now: lots of code, the same few tests.
The trap:
"Let the AI generate the tests."
But:
- tests only cover the happy path;
- edge cases are ignored;
- tests only validate what has already been built.
Good practices:
- run tests after accepting the code;
- manually validate edge cases;
- review suggested tests.
If tests become "something the AI handles on its own," we have validation debt.
4.3. Security Debt: Copying Without Context Is an Invitation to Vulnerabilities
AI often bases security-related answers on:
- generic examples;
- outdated patterns;
- simplistic assumptions.
Common risks include:
- incomplete input sanitization;
- "tutorial-style" authentication configurations making it into production;
- sensitive data in logs.
AI helps, but it does not replace security reviews or company policies.
Copying an "out-of-the-box" solution without adapting it creates security debt.
4.4. Authorship Debt: Who Will Understand This Code Six Months from Now?
Another kind of debt is authorship debt.
The scenario:
- a piece of code generated by AI;
- accepted in a hurry;
- nobody understands it deeply.
Six months later:
- a critical bug appears;
- nobody wants to touch it because they don’t understand it;
- refactoring takes too long because nobody feels responsible.
To prevent this:
- document technical decisions;
- record the rationale;
- someone needs to be responsible for understanding the code.
If everything is "nobody’s code," maintenance becomes a problem.
4.5. Maintenance Debt: Scaling Bad Code Becomes Cheaper
Without AI, a careless developer can already cause plenty of damage. With AI, they can do much more in less time.
That is what makes AI a culture amplifier:
- if the team already accepted poor code;
- AI simply accelerates the chaos.
It’s common to see "miraculous" sprints:
- lots of apparent delivery;
- velocity shoots up;
- the backlog is empty.
Then the bill arrives:
- regression bugs;
- new features take longer;
- fear of refactoring.
The old trade-off:
Immediate speed vs. future maintenance cost.
5. AI Doesn’t Create Good or Bad Engineers — It Amplifies What Already Exists
5.1. The Thoughtful Developer vs. the Developer on Autopilot
Same scenario, two different developers using the same AI.
Developer A (thoughtful):
- uses AI to generate tests and check their understanding;
- questions and adapts the result to the system’s context;
- rewrites when necessary.
Developer B (on autopilot):
- copies the first answer;
- doesn’t run tests;
- doesn’t review.
Same tool. The result:
- Developer A: productivity increases and quality is maintained;
- Developer B: apparent productivity increases, but debt grows.
AI does not turn anyone into a senior engineer. It widens the gap between good and bad practices.
5.2. The Illusion of Instant Seniority
It is a mistake to think that AI "gives senior powers" to anyone:
- a junior with AI writes "sophisticated" code;
- it may even pass reviews if everyone is on autopilot.
But what distinguishes a senior engineer?
- understanding architectural trade-offs;
- reading logs and stack traces;
- designing good interfaces between modules;
- handling failures in production.
None of that comes "for free" with AI.
Seniority remains tied to judgment, not the amount of code produced.
5.3. Where Software Engineering Remains Irreplaceable
There are things AI does not do well:
- understanding business constraints;
- knowing organizational legacy and internal politics;
- negotiating with stakeholders and cutting scope.
AI is excellent at:
- suggesting alternatives;
- automating tasks;
- explaining legacy code.
The decision every team needs to make is:
Will we use AI’s time for more real engineering
or to fill the backlog with irrelevant features?
6. How to Use AI as an Abstraction with Technical Responsibility
This is not a prompt engineering guide, but these attitudes help.
6.1. Treat AI as a Very Fast Junior Pair
A useful practice:
Don’t accept from AI what you wouldn’t accept from an intern.
This includes:
- untested code in critical areas;
- a complete lack of logging or metrics;
- disregard for project standards;
- use of libraries the team does not adopt.
If you wouldn’t let a junior developer "merge directly into main," don’t do it with AI.
6.2. Always Validate: Tests, Observability, and Review Remain Essential
Some principles matter even more now:
- no change without running tests;
- human review of generated code whenever possible;
- a minimum security check for anything external;
- care with code that handles sensitive data.
The temptation to think "if it compiles and the happy path works, it’s ready" increases with AI, but that is precisely where you need more:
- sound automated tests;
- observability (logs, metrics, and traces);
- careful review.
6.3. Explain the System to the AI — and to Yourself
One interesting side effect is that good prompts require clarity.
For AI to help, explain:
- the system’s context;
- constraints;
- examples and edge cases.
Many times, you realize that there are:
- poorly defined requirements;
- confusing domain flows.
For example:
When describing a flow to request a refactoring, you realize that three services modify the same state.
That exercise alone is already a gain, even before accepting generated code.
6.4. Team Culture: Clear Agreements on AI Use

Each team needs to answer:
- Where can we use AI more freely?
- Where is its use restricted (for security, compliance, or criticality reasons)?
- How should we document AI-generated sections?
- What is our review and testing process for AI-generated code?
Overly strict restrictions create friction. A free-for-all creates debt.
AI use should not be an individual decision, but part of team agreements.
6.5. Update Fundamental Skills, Don’t Abandon Them
AI is not an excuse to abandon fundamentals. In fact, some become more important:
- careful code reading;
- system design and domain modeling;
- automated testing;
- solid security and performance practices.
AI can help you:
- ask for explanations of concepts;
- generate examples;
- compare approaches;
but it is essential to truly understand.
7. Conclusion: Code Can Be Generated — Responsibility Cannot
The history of software engineering shows that AI is another layer in the abstraction stack:
- high-level languages abstracted the machine;
- frameworks and ORMs abstracted repetitive details;
- the cloud abstracted physical infrastructure;
- now, AI is beginning to abstract parts of programming.
In every case:
- we gained productivity;
- we created debt.
With AI, the debts appear in:
- trust ("it looks right vs. it is right");
- validation (optional tests);
- security (generic patterns without context);
- authorship (code without an owner);
- maintenance (scaling poor code).
The problem is not that AI writes code.
It is accepting code without understanding, testing, or validating it.
Using AI responsibly means:
- reviewing it as the owner (because you are);
- questioning its answers, especially confident ones;
- strengthening your foundations so you can better evaluate suggestions;
- adjusting your practices to this new reality.
AI writes quickly.
The debt it creates or avoids still depends on who signs off on it.
To continue the conversation, exchange experiences, and see how others are dealing with this in practice, follow the Software Craftsmanship Brasília community at Join the SCCB community and also check out upcoming events and technical meetups.
Next Steps
Here are some practical ideas for your day-to-day work:
- Observe your own AI use for a week
- Note the types of tasks for which you use it most: generating code, explaining, refactoring, or testing.
-
Reflect on where you are being thoughtful and where you are simply "accepting because it looks good."
-
Set up an experiment as a team
- Choose one part of the system in which to use AI deliberately, with clear review and testing criteria.
-
After one or two sprints, discuss what improved and what got worse.
-
Strengthen one technical foundation
- Choose a topic (testing, domain design, or basic security) and use AI as a study aid — but don’t accept everything without checking.
-
Try explaining what you learned back to someone else, either in writing or in conversation.
-
Review at least one AI-generated section in a real system
- Pick a piece of code you know was created with AI.
-
Reread it, refactor it, write better tests, and document the technical decisions.
-
Discuss AI’s role in your team’s workflow
- Bring the topic to a retrospective or an internal tech talk.
- Talk openly about concerns, expectations, and recommended practices for using AI as a new programming abstraction.



