Back to Blognostisphere

Please Pass the Bottleneck

99 bottlenecks of code on the wall…

We taught machines to write software. Now we need to teach them when to stop.

D. James Poer ·

For most of my career, writing software was the expensive part.

You started with an idea. Somebody wrote requirements. Somebody else interpreted those requirements. Designers created interfaces, developers wrote code, and QA eventually informed everyone that their interpretation of reality was incorrect.

Meetings were held. Decisions were questioned. Coffee was consumed in quantities that should probably have required medical supervision.

Eventually, something shipped.

It wasn't always elegant, but the process had an interesting side effect: people had time to think about what they were building.

Then we spent a couple of decades making development faster.

Reusable components. Frameworks. Design systems. Automated testing. Continuous integration. Better tooling.

Every improvement removed another little piece of friction.

Then generative AI arrived, kicked down the door, and announced that friction was apparently a personal insult.

Today, an AI coding agent can generate an entire feature while you're getting another cup of coffee.

It can write components, create tests, update documentation, and confidently explain why its implementation is architecturally sound.

It can also misunderstand the requirements, introduce unnecessary dependencies, rebuild something that already works, and declare victory.

All before your coffee gets cold.

The impressive part isn't that AI can produce software quickly.

The interesting part is what happens when producing software is no longer the difficult part of producing good software.

We've accelerated implementation without proportionally improving our ability to understand, coordinate, or evaluate what we're implementing.

The bottleneck hasn't disappeared.

It's moved.

Which brings to mind an old song.

99 bottles of beer on the wall…

Take one down, pass it around.

And somehow, in software development, there are now 100 bottles on the wall.

Apparently, somebody opened a Jira ticket to replace the missing one.

Good. Fast. Cheap. Pick Three. Pay for Four.

Buzz Usborne recently revisited the classic project-management triangle in an article called Pick Three.

Good. Fast. Cheap.

Traditionally, you got to choose two.

AI appears to have broken the rules. We can produce sophisticated work quickly, inexpensively, and sometimes remarkably well.

But Usborne identifies a fourth cost that doesn't show up in the equation.

Human energy.

More specifically, the attention required to keep increasingly rapid production coherent.

Imagine five developers working independently on different parts of an application.

Historically, implementation took enough time that people had opportunities to coordinate. Decisions were discussed. Designs evolved. Architectural conflicts surfaced.

Now give those developers five AI agents capable of implementing entire features overnight.

By morning, everybody has made tremendous progress.

Unfortunately, they've made progress toward five slightly different versions of the product.

One feature introduces a new navigation pattern. Another implements a competing state-management strategy. A third duplicates functionality that already exists.

Everything compiles.

All the tests pass.

Nobody can explain why the application now has three different ways to accomplish the same task.

We've achieved remarkable efficiency in the production of inconsistency.

And someone still has to reconcile it.

That someone is usually a senior developer, architect, designer, or product owner who thought AI was supposed to make their job easier.

Instead, they're now supervising a software factory that never sleeps and occasionally mistakes enthusiasm for competence.

Usborne's observation gets to the heart of the problem.

The faster we produce software, the more important coherence becomes.

Coherence is what makes a collection of functioning components behave like a single intentional product.

It's what keeps the architecture consistent, the interactions predictable, and the user experience understandable.

And it's not something you can establish by counting completed Jira stories.

The hidden cost of fixing the robots

I've encountered this problem repeatedly while experimenting with AI-assisted development.

Across my portfolio, an AI-supported job evaluation system, and several other applications, I've used agents for research, implementation, testing, architecture, and design exploration.

The productivity gains are real.

So are the supervision costs.

An agent may generate an excellent technical solution to a problem that doesn't exist.

Another may suggest replacing a component we've already spent considerable effort making accessible.

A third may decide that a narrowly scoped styling change is an excellent opportunity to redesign the entire application.

Sometimes the implementation is genuinely impressive.

It's just not what anyone asked for.

And that's where the economics get interesting.

Suppose an agent completes five hours of development in twenty minutes.

Outstanding.

Now suppose I spend two hours explaining what it misunderstood, correcting the implementation, and verifying that it hasn't disturbed anything else.

We've still saved time.

Probably.

But what happens when that work creates another three hours of maintenance later?

What happens when five agents are making those decisions simultaneously?

Lines of code generated is a terrible productivity metric if somebody has to spend the afternoon removing them.

We need to measure accepted work, correction time, rework, and actual outcomes.

The goal isn't to make AI produce more.

The goal is to make AI produce more of what we actually need.

Preferably without requiring a human to follow it around with a mop.

One bottleneck down.

Pass it around.

Now the bottleneck is quality control.

An AI Development Team Is Not a Group Chat With Job Titles

One of my current experiments involves assembling a practical software development team composed of specialized AI agents.

The proposed team includes the usual suspects:

Product Owner, Project Manager, Business Analyst, UX, technical leadership, developers, and QA.

The goal is to determine whether a disciplined collection of agents can collaborate effectively while operating within a realistic budget.

Not just generate impressive individual outputs.

Actually work together.

And here's where things get complicated.

Modern AI models are generalists.

A capable model can write code, draft requirements, analyze business processes, critique designs, and develop test plans.

It can also convincingly impersonate a senior architect.

Unfortunately, convincing impersonation and architectural judgment are not necessarily the same thing.

The fact that an agent can perform an activity doesn't mean it should be authorized to do so.

A developer shouldn't quietly redefine product requirements because it discovered a more interesting implementation.

QA shouldn't approve a feature because the developer assures everyone that the tests passed.

And a project manager shouldn't decide to add seventeen new features because it found an opportunity to demonstrate initiative.

I've worked with human teams. We already know what happens when nobody stays in their swim lane.

Giving everybody unlimited computational enthusiasm doesn't improve the situation.

The architecture of collaboration

We've been establishing operating rules through Jira, GitHub, documented decisions, and explicit handoffs.

Code has a source of truth.

Requirements and decisions have a source of truth.

Agents have responsibilities and boundaries.

Work needs evidence of completion.

And changes need to respect the existing system.

That sounds like ordinary software engineering discipline.

Because it is.

Which raises an interesting question:

Why did we spend decades developing these practices, only to assume they became optional when the developer started predicting its next token?

In Designing a Skill, Noman Ijaz argues that AI agent skills should be treated as designed products.

That means clear inputs, predictable outputs, meaningful constraints, thoughtful presentation, and validation.

Not simply a paragraph instructing a model to behave like an expert.

This idea scales beyond individual skills.

An AI development team needs an operating architecture just as surely as its applications need a technical architecture.

Each role needs a contract.

What information does it receive?

What decisions can it make?

What must it produce?

What constitutes completion?

What happens when something is unclear?

And how does the next participant consume its work?

These are interface-design problems.

The interfaces just happen to exist between agents rather than between people and screens.

Our experiments have exposed weaknesses in context preservation, role boundaries, verification, and handoffs.

Those aren't reasons to abandon the approach.

They're the problems we're trying to solve.

And they're considerably more interesting than another demonstration of an AI generating a to-do application.

The world has enough to-do applications.

Most of us are still trying to finish the items on the first one.

Who Owns the Doubt?

Fabricio Teixeira asks an excellent question in Who Owns the Doubt?

What happens to professional judgment when AI can generate a plausible answer almost instantly?

Language models have an extraordinary talent for sounding authoritative.

They can deliver a correct answer with confidence.

They can deliver an incorrect answer with confidence.

And occasionally, they can invent an entirely new answer with such exquisite formatting that you almost feel rude questioning it.

The problem is that fluency isn't evidence.

And confidence isn't competence.

Experienced engineers and designers develop judgment partly by learning when something doesn't smell right.

We question assumptions.

We challenge requirements.

We evaluate alternatives.

We recognize when the proposed solution is more complicated than the problem.

That process often involves uncertainty.

Sometimes the most important moment in solving a problem is realizing that you don't actually understand it yet.

AI can help us explore that uncertainty.

But it can also tempt us to skip the uncomfortable thinking and accept the first convincing answer.

That's dangerous when the consequences extend beyond a single response.

The Library of Truth

This problem sits at the center of Thingamajob, an AI-assisted system we're developing to evaluate employment opportunities against verified professional experience.

Give a language model a résumé and a job description, and it can produce a wonderfully persuasive evaluation.

It can identify relevant experience, compare qualifications, and suggest improvements.

It can also quietly invent expertise, inflate accomplishments, or resolve contradictions in whatever direction makes the candidate look better.

That's helpful right up until somebody asks about the technology you've supposedly been using professionally for twelve years.

So we've been developing a Library of Truth.

It contains structured, verified assertions about professional experience, supported by a process for accepting, rejecting, and correcting information.

The intent is to separate established facts from generated interpretations.

The model can analyze the evidence.

It can recommend changes.

It can identify gaps.

But it doesn't get to rewrite reality simply because reality could use a stronger résumé.

This introduces a principle that should apply to far more AI systems.

An intelligent system needs to distinguish what it knows from what it assumes.

A trustworthy agent should be able to explain what evidence supports a conclusion, where uncertainty remains, and what requires human judgment.

And when it makes a consequential decision, we should be able to reconstruct the basis for that decision.

That doesn't mean drowning users in technical explanations.

It means preserving enough visibility for the people responsible for the outcomes.

A useful AI system shouldn't require blind faith.

We've already tried that approach with enterprise software.

Results have been mixed.

The User Isn't Always the One Clicking the Buttons

Nielsen Norman Group recently explored a shift from traditional user experience design toward a broader concept of experience design.

The argument is that AI is introducing new participants into software interactions.

Historically, we designed interfaces around a person directly operating an application.

The user navigated, entered information, made decisions, and completed tasks.

Now an AI agent may perform some of those activities on the person's behalf.

The relationship changes.

Human → Agent → System

Sometimes it becomes:

Human → Agent → Agent → System

Which is a wonderful arrangement until the third participant misunderstands the second participant's interpretation of the first participant's request.

Then we have a very efficient game of telephone.

But there's a serious design challenge underneath the complexity.

When should an agent operate independently?

When should it request permission?

What happens when it encounters an unexpected condition?

How does the human know what happened?

Can an incorrect action be reversed?

How does control return to the person without requiring them to reconstruct the agent's entire process?

Those aren't merely programming questions.

They're experience-design questions.

The handoff is part of the interface

We've experienced this directly in our job-search workflows.

An AI agent can research an opportunity, evaluate qualifications, and prepare application materials.

Wonderful.

But if the application link doesn't work, the promised résumé doesn't exist as a downloadable file, or the position was never verified, the entire workflow falls apart at the last step.

The agent may have completed twenty impressive intermediate tasks.

The human still can't apply for the job.

From the user's perspective, the experience failed.

Software development has the same problem.

An agent can finish implementing a feature.

But if it leaves undocumented changes, fails to preserve established decisions, or hands off incomplete information, the next participant must recover the missing context.

That's not free.

It's work transferred from the machine to the human.

A task isn't complete when the agent declares victory. It's complete when the intended outcome has been achieved and the next participant can proceed reliably.

The handoff isn't administrative overhead.

It's part of the interface.

And here's our next bottleneck.

We've made individual agents faster.

Now we need to make them work together.

Take one down, pass it around.

Accessibility Isn't a Feature We Can Add After the Robots Finish

Eric Bailey's article, Making Immersive LLM Chat Experiences More Accessible, examines a problem that's becoming increasingly important.

AI applications introduce interaction patterns that conventional websites don't always handle well.

Content streams dynamically.

Background processes execute.

Multiple agents may work simultaneously.

The interface needs to report progress, display evidence, request approval, and communicate failures.

A sighted user may understand much of this through visual feedback.

But what happens when someone is using a screen reader?

Does the application announce every word as it appears?

Does it announce nothing?

Does keyboard focus remain predictable?

Can the person navigate efficiently between requests, results, and actions?

Can they distinguish background activity from something requiring their attention?

These aren't minor details.

They're fundamental usability questions.

And they're particularly relevant to autonomous systems.

Accessibility and control

My professional background includes front-end architecture, accessibility remediation, and usability engineering, including hands-on testing with NVDA and axe.

AI creates an opportunity to apply that experience to a new generation of interfaces.

An accessible agentic application must do more than present information correctly.

It needs to make autonomous behavior understandable and controllable.

Consider a workflow involving multiple agents.

Some tasks are complete.

Some are running.

Some require approval.

Others have encountered problems.

The person supervising the system needs to understand those states without being overwhelmed by technical noise.

And they need equivalent control regardless of whether they're using a mouse, keyboard, screen reader, or another assistive technology.

That's not something we can solve by sprinkling ARIA attributes over whatever interface the AI generated.

It requires deliberate information architecture, interaction design, semantic structure, and testing.

Accessibility isn't a finishing touch. It's part of the system's architecture.

Performance is part of usability, too

That philosophy also informs our work on Shady White Van, a music-centered creative project with a custom interactive web experience.

The application incorporates 3D presentation, responsive layouts, modern front-end engineering, and an emphasis on performance and accessibility.

Those qualities aren't competing priorities.

They're parts of the same experience.

An engaging 3D presentation loses much of its value if it makes a page painfully slow on mobile.

An expressive interface isn't successful if people cannot navigate it using a keyboard.

Animation shouldn't become an obstacle for people who prefer reduced motion.

We've measured and refined the production experience using Lighthouse, accessibility testing, and iterative optimization.

Recorded results have included perfect desktop Lighthouse scores across all four categories and near-perfect mobile performance.

That's encouraging.

But the objective isn't collecting perfect scores like achievement badges.

It's demonstrating that sophisticated visual experiences can also be fast, accessible, and usable.

The technology should serve the experience, not demand that the experience serve the technology.

And that principle doesn't change just because an interface includes AI, 3D graphics, or an ambitious visual design.

Sometimes the Best AI Solution Is Less AI

Another useful lesson emerged from Creative Town, an experiment combining generative imagery with deterministic application behavior.

The project involved creating a visual environment with specific composition rules, character selection, and behavioral constraints.

The initial approach relied too heavily on image generation to enforce those requirements.

The model could produce compelling imagery.

What it couldn't reliably do was obey a collection of precise rules every time.

One particularly persistent issue involved an unwanted baseball stadium appearing in generated scenes.

We corrected the instructions.

We clarified the restrictions.

We tried again.

The stadium demonstrated a level of commitment to its continued existence that would make most professional sports franchises envious.

Eventually, the problem became obvious.

We were asking probabilistic technology to enforce deterministic constraints.

The issue wasn't insufficiently enthusiastic prompting.

It was an architectural mistake.

Character selection, positioning, timing, and rule enforcement are problems conventional software can handle precisely.

Generative models are valuable where variation, interpretation, and creativity are desirable.

So we separated those responsibilities.

Deterministic logic handled the rules.

Generative capabilities contributed within those boundaries.

And the deterministic behavior could be tested rather than repeatedly negotiated.

The resulting lesson applies to far more than visual generation.

Use intelligence where intelligence adds value. Use conventional software where predictability matters.

AI shouldn't replace reliable engineering simply because it's fashionable.

Permissions should be enforced by systems.

Tests should verify behavior.

Established facts should remain separate from generated interpretations.

And constraints should be implemented wherever they can be checked reliably.

The best AI architecture isn't necessarily the one that uses AI for everything.

Sometimes it's the one that knows precisely where AI doesn't belong.

Which may be the most intelligent decision in the entire system.

Not Everyone Is Ready for AI. That's Not Their Problem to Solve Alone.

Adobe researcher Reem Mehdoui makes an important distinction between readiness to adopt AI and maturity in using it effectively.

Someone may be highly capable but blocked by organizational policies, inaccessible systems, or inadequate infrastructure.

Another person may have unrestricted access to sophisticated AI tools but lack the experience or confidence to use them productively.

A third may understand the technology perfectly well but distrust a particular application because it behaves unpredictably.

These situations require different responses.

And they illustrate a familiar UX principle:

The existence of functionality does not guarantee the usability of functionality.

This matters as we consider how our experiments might eventually serve people beyond their original developers.

I understand Thingamajob's Library of Truth because I've been involved in its design.

I know why we distinguish verified claims from generated conclusions.

I understand the importance of corrections, evidence, and decision history.

A first-time user shouldn't need to understand all those internal mechanisms before accomplishing something valuable.

The interface should make the important distinctions clear without requiring the person to become an expert in our architecture.

That's what thoughtful user experience design does.

It translates complexity into understandable interactions.

AI can help us build that interface faster.

It can't eliminate our responsibility to understand the person using it.

And if someone struggles with the system, the first question shouldn't be whether they're sufficiently sophisticated to use AI.

It should be whether we've designed the experience appropriately for their needs.

That's not a new principle.

It's one we've been trying to teach software organizations for decades.

Apparently, we get to teach it to the robots now, too.

The Value Was Never in the Number of Lines

Christopher Butler's There Will Always Be Someone Faster, Cheaper, and Better addresses an anxiety that's becoming increasingly common among creative and technical professionals.

If AI can produce comparable artifacts faster and cheaper, what happens to the value of human expertise?

The answer depends on what we believe that expertise was worth in the first place.

A good software engineer isn't valuable simply because they can type code quickly.

A good designer isn't valuable because they can arrange pixels faster than everyone else.

The value comes from understanding problems, evaluating tradeoffs, recognizing consequences, and delivering outcomes.

Sometimes that requires substantial implementation.

Sometimes it requires preventing unnecessary implementation.

Earlier in my career, I worked on a large application modernization effort involving significant accessibility challenges.

A proposed solution could have required an enormous rewrite.

Instead, understanding the existing system and the actual requirements made it possible to address important accessibility problems through a much smaller intervention.

The value wasn't in producing more code.

It was in recognizing how much code didn't need to be written.

That's the kind of judgment that becomes more important as implementation grows cheaper.

AI can generate solutions rapidly.

It can also generate expensive mistakes rapidly.

And an incorrect architectural decision doesn't become a good decision simply because it was implemented in fourteen seconds.

The ability to write code is becoming less scarce. The judgment to know what code should exist remains valuable.

That's why experience, architecture, accessibility, and usability matter.

They inform the decisions that determine whether implementation produces lasting value.

The Metrics Need to Change

The AI industry loves benchmarks.

Tokens per second.

Context-window size.

Coding accuracy.

Autonomous task completion.

Lines of code generated.

These measurements tell us something about model capabilities.

They don't necessarily tell us whether using those models produces a better development process.

Our experiments need different measurements.

How often does the delivered work meet its requirements on the first attempt?

How much human correction does it require?

Does the agent preserve established decisions?

Does it respect its assigned scope?

How frequently does apparently completed work need substantial rework?

Can another agent continue without reconstructing missing context?

How often do defects escape validation?

And what does an accepted deliverable actually cost when we include the human effort required to produce it?

Those are less glamorous questions than asking how many applications an agent can generate in an afternoon.

But they're far more useful.

We're exploring whether a disciplined collection of specialized AI agents can deliver reliable software within a practical budget.

The goal isn't to maximize the number of agents.

It's to maximize useful output while minimizing unnecessary human intervention.

And that means measuring success differently.

A model that completes ten tasks but requires constant correction may be less valuable than one that completes five correctly.

An agent that identifies an architectural problem before implementation may be more valuable than one that rapidly writes the wrong solution.

And a system that preserves decisions, exposes uncertainty, and produces reliable handoffs may outperform a technically more capable system that doesn't.

The most useful AI isn't necessarily the one that does the most work. It's the one that creates the most value without wasting the human's attention.

That should be the standard.

Because if we eliminate the coding bottleneck only to replace it with an even larger supervision bottleneck, what have we accomplished?

We've passed the bottle.

We haven't emptied it.

Software Development Is Never Done

I recently wrote about another principle that's shaped my work:

Software development is never done. It's just done enough for now.

Users change.

Business requirements evolve.

Platforms change.

Accessibility expectations improve.

Architectures encounter new constraints.

Eventually, someone has to revisit what was previously considered complete.

AI doesn't eliminate that reality.

It accelerates it.

We can now produce software faster than ever, but we still have to understand, maintain, and evolve what we create.

And as autonomous agents become more involved in that process, we need systems that preserve context and make their behavior understandable.

That means clear responsibilities.

Reliable verification.

Transparent uncertainty.

Accessible supervision.

Predictable handoffs.

And decisions that remain understandable long after the original conversation has disappeared into a context window somewhere.

The next major advance in software engineering may not come solely from better code generation.

It may come from learning how to organize increasingly capable agents around human goals without creating an equally impressive coordination problem.

Because software development was never just about writing code.

It was about understanding problems well enough to solve them.

And that responsibility doesn't disappear when the keyboard operator becomes a language model.

Please Pass the Bottleneck

Taken together, the research paints a remarkably consistent picture.

Buzz Usborne identifies the growing cost of maintaining coherence.

Noman Ijaz argues that agent capabilities need deliberate design.

Fabricio Teixeira reminds us that uncertainty and professional judgment still matter.

Christopher Butler explains why production speed isn't the same as professional value.

Reem Mehdoui examines the human conditions required for successful AI adoption.

Eric Bailey demonstrates why accessibility must evolve alongside AI interfaces.

And Nielsen Norman Group describes the expanding discipline of designing experiences that involve both people and autonomous agents.

Different perspectives.

The same underlying problem.

We've dramatically accelerated our ability to produce software without proportionally improving our ability to decide what should exist, coordinate its development, or evaluate its consequences.

That's what we're investigating through Thingamajob, Creative Town, Shady White Van, djamespoer.com, and our multi-agent development experiments.

Each project explores a different piece of the larger challenge.

How do we combine powerful automation with sound engineering judgment?

How do we preserve truth and accountability when systems generate convincing conclusions?

How do we make sophisticated experiences accessible and performant?

How do we coordinate autonomous agents without turning human supervision into a full-time occupation?

And how do we measure whether any of this is actually making things better?

We haven't solved those problems.

But we're learning which questions matter.

And the answers are becoming increasingly relevant as AI moves from generating suggestions to taking actions on our behalf.

For now, I'm less interested in building an AI that can write a million lines of code.

I'm interested in building a system that knows when a hundred lines will do.

One that understands the requirements, respects the architecture, verifies its work, and communicates what happened.

One that recognizes uncertainty instead of disguising it.

One that makes the experience better for the people using it.

And ideally, one that doesn't require me to explain the same requirement six times before discovering that the original implementation was fine.

That would be progress.

Because the purpose of software development was never to produce the greatest possible quantity of software.

It was to solve problems for people.

That hasn't changed.

The tools have.

And the bottleneck has moved.

We've spent decades taking bottlenecks down, passing them around, and discovering new ones waiting on the wall.

Now AI has given us the ability to move them faster than ever.

Which leaves us with one final question:

Are we actually eliminating bottlenecks, or have we just invented the world's most expensive drinking game?


Further Reading

Inspired by UX Design Weekly, Issue 613 (November 9, 2026) and the following articles:

D. James Poer — UX Engineer & Front-End Architect — djamespoer.com