Stop treating AI like a magic wand and start acting like the A developer argues that the rise of LLM agents and tools like Claude Code has led to 'vibe coding,' where developers rely on loose prompts and hope the output feels right, which bypasses essential complexity. The author advocates for treating the programmer as the 'harness' that imposes constraints and edge cases, and recommends using property-based testing tools like Hypothesis to rigorously verify AI-generated code. The piece emphasizes that engineers must define logical boundaries rather than merely write code. Stop treating AI like a magic wand and start acting like the If you look at the modern "software engineer" workflow, a massive chunk of the day is spent playing roles in TDD Test-Driven Development or BDD Behavior-Driven Development ceremonies. It’s often more about the ritual of red-green-refactor than it is about actually thinking through the logic. We've been drowning in boilerplate and mechanical processes that don't actually touch the core complexity of the problem. The trap of "vibe coding" With the rise of LLM agents and tools like Claude Code /en/tags/claude%20code/ , we are seeing the birth of "vibe coding." This is where a developer feeds a loose prompt into an agent, watches the code fly by, and hopes the resulting output "feels" right. This is dangerous because it bypasses the essential complexity of the task. When you outsource the "rituals"—the typing, the basic structure, the standard patterns—you aren't actually being freed from work. You are being stripped of your distractions and forced to face the raw, unadulterated logic of your system. You can no longer hide behind a failing test suite or a complex directory structure. You are left with the actual problem: Does this logic hold up? Does this change introduce side effects in a distant module? You are the actual harness In machine learning, a harness provides the framework that allows a model to perform reliably. In the new AI workflow, the programmer is the harness. The model provides the raw power, but the quality of the output is strictly bounded by the constraints, the edge cases, and the architectural rigor you impose on it. If you provide a vague, "vibes-based" prompt, you get a brittle, "vibes-based" implementation. If you provide a near-formal specification, you get high-quality code. To move away from the "vibe" trap and toward a real AI workflow, I've found that shifting from TDD to a more robust verification approach helps. Instead of just writing unit tests for happy paths, I’m leaning harder into fuzzing and property-based testing. A practical approach to verification When using an LLM agent to generate a complex function, don't just ask it to "write tests." That's just more ritual. Instead, use a more aggressive verification method. For example, if you're working in Python, don't just settle for unittest . Use something that explores the state space more aggressively: python import hypothesis from hypothesis import given, strategies as st Instead of manual unit tests, use property-based testing to force the AI-generated code to reveal its edge-case failures. @given st.lists st.integers def test complex logic property data : result = my ai generated function data Define the invariant that MUST hold true regardless of input assert is valid transformation data, result By using tools like Hypothesis, you aren't just checking if the code "works"; you are attempting to break the logic the AI just handed you. This is the real work of a senior engineer in the age of LLMs. We aren't here to write code anymore; we are here to define the mathematical and logical boundaries that the code must live within. If you can't define those boundaries, you aren't an engineer—you're just a spectator watching an LLM hallucinate a system into existence. Next I got sucked into a coding challenge that turned into a → /en/threads/8374/