Flask Creator's Conversation: Why We Need to Slow Down in the AI Coding Era

Flask's creator and Pi's author argue engineers must slow down as AI Agents accelerate code output.
Flask creator Armin Ronacher and Pi author Mario Zechner discuss why the AI coding era demands more deliberate thinking. They explore how Agents produce complexity without feeling pain, why code quality declines despite faster output, the MCP vs CLI architecture debate, open source's struggle with intentionless PRs, and the engineering wisdom of deliberately injecting friction into development workflows.
In a time when AI coding tools are advancing at breakneck speed, a conversation between two veteran engineers stands out for its sobriety. Armin Ronacher, creator of the Flask framework, and Mario Zechner, author of the minimalist coding Agent "Pi," had a candid discussion on a technical podcast about a counterintuitive topic: when AI can produce code at ten times the speed, what we truly need might be to "slow down."
Flask is one of the most popular lightweight web frameworks in the Python ecosystem, created by Armin in 2010. It follows a "micro-framework" design philosophy—an extremely minimal core that supports virtually all web development needs through extension mechanisms. Armin is also the author of the Jinja2 template engine and the Click command-line utility library, and currently serves as Director of Engineering at Sentry. His design philosophy for developer tools—simplicity, composability, predictability—has profoundly influenced the entire Python community and gives him a unique perspective on AI coding tools.
Both are European engineers (both from Austria) with over twenty years of experience. They are deep users of AI coding tools and clear-eyed observers of their limitations. This article distills the most valuable insights from their conversation.
The Birth of Pi: Starting from Disappointment with Claude Code
Pi is a minimalist, self-modifying coding Agent developed by a single person, and has quietly become the engine behind the popular personal AI assistant OpenClaw. Its creation stems from Mario's dissatisfaction with existing AI coding tools.
Mario was once a devoted Claude Code enthusiast, even "evangelizing" it everywhere. He admired the Agentic search that Claude Code enabled—giving the Agent direct file system access, which "killed all previous index-based and AST-based approaches." To explain: traditional code search and understanding tools (like Language Server Protocol implementations) rely on pre-built AST (Abstract Syntax Tree) indexes to implement features like go-to-definition and find-references. An AST is a tree-structured representation of source code that compilers and IDEs use to understand code's syntactic structure. The revolutionary aspect of Agentic search is that it lets AI directly read and understand raw files, bypassing the limitations of these pre-built indexes—no need to know the project structure in advance, and no constraint from specific language toolchains. But as the team iterated rapidly, Claude Code became increasingly unstable.

"They inject things into the context behind your back," Mario complained. "A workflow that used to work suddenly breaks because there's a system reminder you can't even see in the UI." He even reverse-engineered Claude Code's obfuscated JavaScript and built a service tracking its system prompt evolution (cchistory.mariosechner.at). This behavior reveals a common problem with commercial AI tools: system prompts are a hidden instruction layer that controls model behavior. Users can't directly view or modify them, and vendors frequently adjusting these instructions causes the same user prompt to produce drastically different results at different times.
For Mario, development tools should be as stable and reliable as a hammer: "I don't want my hammer cracking in a different place every day." After trying AMP, Droid (too expensive), and open code (also tampers behind the scenes), he decided to build his own.
Minimal Core and Self-Modification Capability
Pi's core is extremely lean—just read, write, edit, and bash tools. Its power lies in extensibility: the entire minimal core provides numerous hook points, and users can plug in through a simple TypeScript module running in the same Node process. This design pattern echoes Unix tool philosophy—each component does one thing and does it well, with complex functionality achieved through composition rather than bloating the core.
Most interestingly, Pi can modify itself. It doesn't have MCP support? Users just have Pi write MCP support into Pi. It doesn't have plan mode? Armin wrote five plan mode implementations before discovering plan mode was "completely useless." Non-technical users can even have Pi rewrite its own TUI interface to suit their needs.
Mario believes this points to the future: "Software will self-modify according to users' intentions and needs." This concept of adaptive software isn't entirely new—Emacs and Smalltalk environments embodied similar ideas decades ago—but AI's addition enables non-programmers to participate in this customization, which is a qualitative leap.
Agents Don't Feel Pain, But Human Engineers Do
One of the most profound insights from the conversation came from the discussion about "pain."

After interviewing over 30 engineering teams, Armin found that adoption of AI coding tools has seen "explosive growth," accompanied by a widespread decline in code quality. The reason isn't that people want to write worse code—it's that staying within good boundaries itself requires effort.
He drew an analogy from personal experience: during Xbox One game development, the entire team had to rally to "de-slop" a human-written matchmaker system—what should have been only 6 valid states had exploded into a massive state machine with 16 booleans. This touches on a classic software engineering problem: a state machine is a fundamental model for managing system behavior, where a system transitions between a finite number of states based on inputs. When poorly designed, the number of states grows exponentially—16 booleans can theoretically produce 2^16 (65,536) state combinations, the vast majority of which are meaningless or unreachable. This "state explosion" is a classic manifestation of software complexity spiraling out of control, and a core challenge long studied in the field of formal verification.
"Agentic code feels just like this—it should be a clearly defined system, but in reality it says 'Oh, config can't load? Let me catch that and load the default config,' and your code ends up way more complex than it should be." This behavior in software engineering is called "over-application of defensive programming"—every exception path is silently handled rather than surfacing errors. On the surface the code won't crash, but in reality it masks design flaws, letting problems explode at deeper, harder-to-debug levels.
The key distinction: Human engineers feel pain; Agents don't.
"When a codebase becomes too complex, human engineers feel the problems it causes," Mario pointed out. "And it's precisely this pain that drives refactoring and rewrites. Agents don't care at all—they just keep piling on complexity."
Another human trait is "learning and retaining learning." You can review a new engineer's code, and after a few months you can trust them. But Agents don't learn this way—"You can stuff a lot into an Agent, build memory systems, but that's not the same as human learning." The core difference here is that human learning is a structured knowledge internalization process. Engineers don't just memorize specific code patterns—they abstract principles and flexibly apply them in entirely new scenarios. Current Agent memory systems—whether Retrieval-Augmented Generation (RAG) based on vector databases, or context injection based on rules files—are fundamentally information retrieval rather than true learning. RAG works by converting text into high-dimensional vectors and retrieving the most similar fragments at query time. It can find relevant information but cannot truly understand causal relationships between pieces of information or reason creatively in unseen situations.
Good Engineers Know How to Say "No"
Armin raised a sharp point: "A good engineer is one who frequently says 'no.'" Saying "no" controls complexity. But with Agents it's exactly the opposite—"You say, I want this, and this, and this, because I don't have to type it myself, don't have to think about it myself. Throw a prompt at the little machine and it spits out something that looks about right. Good enough. And that's where all the problems start."
This stands in stark contrast to the famous "YAGNI" principle (You Aren't Gonna Need It) in software engineering. YAGNI is one of the core principles of Extreme Programming (XP), arguing against implementing features just because they "might be needed someday." When implementation cost approaches zero (having an Agent generate it), this principle's constraining power drops dramatically. But implementation cost is just the tip of the iceberg—maintenance cost, cognitive burden, and system complexity are the real price.
Senior engineers are in demand precisely because they have "battle scars"—they've been burned, they've felt pain, so they can make judgments that avert disaster.
The New Dilemma for Open Source: Intentionless Pull Requests
As the underlying engine of OpenClaw, Pi is bombarded with AI-auto-generated issues and pull requests. Mario even built a tool that embeds issues into 3D space so he can see clusters of similar problems and batch-close them. This visualization method leverages text embedding technology—converting each issue's text into a high-dimensional vector, then mapping to 3D space through dimensionality reduction algorithms (like t-SNE or UMAP) so that semantically similar issues naturally cluster together.

His solution is quite clever: automatically close all PRs from unfamiliar accounts, then leave a comment asking the person to open an issue in human language, no longer than one screen. "It turned out that Agents can't see the comments posted by my GitHub workflow, so this became a perfect filter—blocking Agents while protecting humans." This works because most AI Agents operate on GitHub through API calls, and comments generated by GitHub Actions don't automatically appear in certain API views, forming a natural "Turing test."
Armin identified the core issue: these PRs have "absolutely no intent behind them"—the person who dispatched the machine doesn't care about it, may not even know it exists. Traditional open source works because "people gather energy around hard problems," but now open source has become "just throwing things at the wall." This phenomenon reflects a fundamental challenge facing the open source community: the value of open source was never just the code itself, but the human intent, design decisions, and ongoing maintenance commitment behind it. When AI can generate PRs at zero cost, the review burden on open source maintainers increases dramatically while the signal-to-noise ratio plummets. This parallels the "tragedy of the commons" in economics—when the individual cost of action approaches zero, public resources (in this case, maintainers' attention) get overconsumed.
Interestingly, Mario is relatively optimistic about this. He believes the number of long-surviving open source projects hasn't really changed—"We just have a bunch more projects that die after two days." Projects with real vitality still depend on long-term human investment, community building, and ecosystem cultivation. "What's changed is just the mechanical parts."
MCP or CLI: The Architecture Debate in AI Coding Tools
On the MCP vs. CLI debate, both lean toward CLI, though neither takes an absolute stance.
MCP (Model Context Protocol) is an open protocol released by Anthropic in late 2024, designed to standardize how large language models connect to external tools and data sources. It uses a client-server architecture communicating via JSON-RPC, allowing AI models to call external APIs, databases, file systems, etc. MCP abstracts external capabilities into three primitives—"tools," "resources," and "prompts"—aiming to become the universal standard for AI applications connecting to the outside world, similar to USB-C's standardization of hardware interfaces. Before MCP, each AI application needed to implement integration logic separately for each external service, creating N×M integration complexity; MCP aims to simplify this to N+M—each AI client implements the MCP protocol once, and each service provides one MCP server.

Armin's core critique: MCP essentially stuffs things into context for processing. "It fills up your context very quickly," and it's non-composable—to merge outputs from two MCP servers, data must pass through the context and be transformed by the model itself. Understanding the context window concept is key here: it's the total token limit a large language model can process at once, currently ranging from 128K-200K tokens for mainstream models. All Agent reasoning, code understanding, and generation must happen within this window, forming a hard ceiling on Agent capability. When MCP tools return large amounts of structured data, context space is rapidly consumed, leaving less and less room for actual reasoning. More critically, the model's information processing quality isn't uniformly distributed across the context window—research shows a "Lost in the Middle" phenomenon, where models process information at the beginning and end of context better while the middle tends to get ignored.
CLI, on the other hand, is a pipe: the model only sees the final result and can freely process data. This is also the approach behind Cloudflare's "code mode"—exposing MCP servers as TypeScript functions and letting the model write code to call and compose them. This approach inherits the classic Unix philosophy of "small tools composed through pipes"—each tool does one thing and does it well, tools connect through standard input/output streams to achieve powerful composability. In the AI coding context, CLI pipes' advantage is that data processing happens outside model reasoning—the model can write a script to fetch, filter, and transform data, bringing only the final refined result into context, dramatically improving context utilization efficiency.
Mario traced how MCP went off track: it was originally built for consumer chat applications to connect to external services, which is a perfectly valid use case. The problem arose when large companies mapped entire OpenAPI specs into massive tool sets—"that's garbage." And models start breaking down at 12-20 tools. This limitation stems from the attention mechanism of large language models—when there are too many available tools, the model must evaluate all candidate tools' applicability at each decision point. Attention gets diluted, causing selection accuracy to drop significantly, frequently picking wrong tools or passing incorrect parameters. Some research suggests this is fundamentally a combinatorial optimization problem, where increasing tool numbers causes the search space to expand exponentially.
However, both acknowledge that MCP has found genuine product-market fit in enterprise environments—particularly in solving the authentication (auth) problem. In enterprise settings, OAuth flows, API key management, and permission control are among the thorniest issues when integrating external services. MCP's standardized auth layer allows enterprises to securely expose internal systems to AI assistants without implementing authentication logic separately for each tool. "The right tool for the right job."
Why the AI Coding Era Demands Slowing Down
The conversation's culminating point is Armin's blog post titled "We All Need to Slow the F Down."
Mario did some simple math: if an Agent can produce ten times your code output in a day, that also means ten times the bugs. Even if the error rate is halved, that's still five times more. Now imagine a "dark factory"—hundreds of Agents simultaneously doing this to your codebase. What happens? The "dark factory" concept borrows from manufacturing's "lights-out manufacturing"—fully unattended automated production lines. In a software engineering context, it refers to scenarios where large numbers of AI Agents continuously produce code without human supervision—some startups are already experimenting with this model, having Agents work around the clock on development tasks in parallel. It's worth noting that even in physical manufacturing, fully unattended factories are extremely rare—most "smart factories" still require humans for monitoring, quality inspection, and exception handling. Software is more abstract and harder to test than physical products; expecting fully autonomous code factories to operate reliably may be even more unrealistic than the manufacturing analogy suggests.
The deeper problem is that complexity is the Agent's own worst enemy. Agents work effectively within approximately 200,000 tokens of context window at most. When the code they produce becomes too voluminous for them to read into context, they can no longer obtain all the context needed for new tasks—this is precisely where garbage code comes from. This creates a vicious cycle: low-quality code generated by Agents increases codebase complexity, and increased complexity reduces the Agent's ability to understand the codebase, which in turn produces even lower-quality code. In systems theory, this cycle is called a "positive feedback loop"—not positive in the good sense, but self-reinforcing deviation. The only way to break this cycle is to introduce external intervention—human review and refactoring.
Moreover, Agents' knowledge comes from the internet—"there are pearls, but also massive amounts of slop." Machine learning models converge toward the mean, and that mean isn't the few carefully crafted projects but the vast ocean of cargo cult and bandwagon code. "Cargo cult programming" as a concept originates from post-WWII South Pacific islanders who mimicked American military behavior—building runways, wearing uniforms—hoping planes would return. In software engineering, it refers to mechanically imitating surface forms without understanding underlying principles—like copy-pasting design patterns without understanding their applicable scenarios, or introducing complex microservice architectures in projects that don't need them just because "big companies do it." Since large language models learn from massive amounts of internet code—filled with tutorial code, Stack Overflow quick fixes, and open source projects of wildly varying quality—model output naturally converges toward this "mean" rather than the few thoughtfully designed architectures. The nature of statistical learning means models are more likely to output patterns that appear frequently in training data, and high-quality code is precious precisely because it's scarce.
The Engineering Wisdom of Deliberately Injecting Friction
Armin also raised the concept of "friction." Before AI, codebases had a kind of "reverse channel"—when things were going wrong, engineers could feel that friction. Excellent engineering practices deliberately inject friction to force thinking: high-severity services require multiple code reviews, configuration changes need director approval. These seem bureaucratic but mean you don't get woken up at 3 AM.
This philosophy has deep theoretical foundations in software engineering. Google's engineering practices include a famous principle: "Make the right thing easy and the wrong thing hard." Type systems are a form of compile-time friction—they force developers to think about data shapes and interface contracts while writing code, catching at compile time errors that might otherwise occur at runtime. Similarly, immutable data structures prevent an entire class of hard-to-track concurrency bugs by prohibiting in-place modification—you can't modify data, only create new versions. This adds friction during coding but eliminates entire categories of potential defects. Rust's ownership system is another classic example: through strict compile-time checks, it forces developers to solve memory safety issues during the coding phase. The learning curve is steep (high friction), but in exchange you get a guarantee of zero runtime memory errors. These design decisions appear to limit development freedom but actually trade small upfront friction for major downstream safety.
"But there's a tendency now to eliminate all friction so Agents can be as autonomous as possible," Armin said. "There's a trap hidden here." When we remove code review requirements, bypass type checking, and skip integration tests to make Agent workflows smoother, we're simultaneously dismantling the safety nets that decades of software engineering practice have built.
Mario's own approach is to "refactor ruthlessly"—because refactoring pulls him into the codebase, forcing him to understand structure rather than line-by-line syntax. "Staying in the code is the only way to keep a codebase high-quality and low-complexity." Even though this goes against the prevailing wisdom of "burning through tokens." Martin Fowler pointed out in his classic book Refactoring that the value of refactoring lies not only in improving code structure but in being the most effective way to understand existing systems—by personally changing how code is organized, you're forced to deeply understand the reasons and consequences of every design decision.
Conclusion: The Irreplaceability of Human Judgment
Armin described the pace of this field in "dog years"—ask him what things will look like in a year, and "it's like seven years." This acceleration makes any prediction extremely difficult.
But both share a core conviction: AI should be used to automate the things we hate doing and that it does well, thereby freeing up time for humans to think about what should actually be built. Not to build an army of Agents, throw a big spec at them, and pray for good results.
"I'm not worried about dark factories, software is dead, SaaS is dead—any of that," Mario said. "I believe it's just part of the hype machine, and it will self-correct."
For everyone caught in this wave, the value of this conversation may lie precisely here: machines can move at breakneck speed, but quality, responsibility, and judgment still need to be guarded by humans who can feel pain.
Related articles

Tailcat: Tailscale's Official Decentralized Minimalist Networking Solution
Tailcat is Tailscale's official decentralized networking project that strips control plane dependencies, offering self-hosting users a more autonomous, privacy-focused WireGuard mesh experience.

Configuring OpenTelemetry Logs in Rails: From Integration to Production
Learn how to configure OpenTelemetry logs in Rails, covering OTel SDK setup, trace context injection, structured log export, and performance optimization for seamless log-trace correlation.

4DOF Robotic Arm DIY Tutorial: A Progressive Guide from Potentiometer Control to Inverse Kinematics
Complete guide to building a 4DOF robotic arm: from potentiometer control to Python serial communication, inverse kinematics, PyBullet simulation, and vision-based grasping for Arduino robotics beginners.