From vibe coding to harness engineering
Tools14 min read

From vibe coding to harness engineering

How harness engineering architecture and verification pipelines keep probabilistic AI agents deterministic and distributed data consistent in regulated finance.

The demo on the screen was nothing short of astonishing.

3 TiersDeterministic harness barriers
0%Dual-write inconsistency defect rate
100%ADR architecture sync
96.5%Automated gate pass rate

We handed a state-of-the-art AI agent a few lines of natural-language prompt, and in under three minutes a plausible Spring Boot application poured out like a waterfall: Kafka event producers and consumers, an account-opening workflow, and handlers for fund-investment messages.

When we ran the build command in the terminal, a green success message appeared. Executives and planners cheered as events flowed back and forth between local Docker containers. It felt as if all the pain of complex software engineering had vanished, and a magical age had begun in which a few words of natural language could conjure a huge financial system.

Vibe coding (running on gut feeling)

  • Improvised code generation from natural-language prompts
  • Plausible but fragile exception handling built on standard patterns
  • Missing distributed transactions and regulatory compliance
  • Unclear accountability when a production failure occurs

Harness engineering (deterministic control)

  • Precise specification through reverse questioning (Grill Me)
  • Automatically enforced schema contract verification and static security linting
  • Transactional outbox pattern and guaranteed distributed consistency
  • Real-time sync between ADR architecture decision records and code

But that excitement shattered the moment it crossed the threshold of a financial institution’s enterprise architecture review room.

The questions from the principal infrastructure architect and the security auditor standing at the whiteboard were cold. “When a transient network disconnection hits the Kafka broker, how do you guarantee consistency between the database transaction and the message publication?” “Which article and clause of the financial regulatory compliance guidelines does your retry backoff policy, which isolates failed event publications into a dead letter queue, comply with?” “Where is the evidence that this code does not cause dual-write anomalies in a distributed environment?”

A suffocating silence filled the room. Those thousands of lines of fluently generated code had flawless syntax and a plausible structure on the surface, yet they did not contain a single line of the meticulous reliability patterns and regulatory requirements that an enterprise environment demands.

It was the moment the glamorous illusion of vibe coding collided head-on with cold enterprise reality.


The plausibility trap and the absolute determinism that regulated environments demand

The essence of vibe coding, which is shaking the software industry worldwide, is “rapid prototyping by feel and intuition.” Developers skip strict architecture specifications and the discipline of test-driven development (TDD), chatting with an AI agent and quickly pulling out code in rough shape.

For a startup landing page, a personal toy project, or a one-off internal tool, this approach delivers explosive productivity. You can produce visible results in a few hours without any elaborate design.

But in highly regulated environments such as banking, insurance, payments, healthcare, and aviation, vibe coding is not a blessing but a spark for disaster.

Large language models are probabilistic machines by nature. A model only statistically computes the most plausible combination of tokens to follow the given context. It imitates the most common standard design patterns, the most generic exception-handling constructs, and the most ordinary function-call structures from hundreds of millions of lines in public open-source repositories.

The problem is that what a regulated environment requires is not “plausibility” but “absolute deterministic certainty.”

In financial systems, software quality is not measured by “does it work?” It is measured by “in any extreme failure scenario, is the failure state safely isolated within a range that can be mathematically proven?”

Thanks to the vast knowledge scraped from GitHub, an AI model can write Kafka template code in an instant. But it has no understanding of the semantics of a specific financial institution’s internal security architecture standards, audit-log traceability rules, and strict distributed transaction policies, all established over a decade of financial incidents and regulatory audits.

As a result, the output of vibe coding is nothing more than a “plausible implementation of a basic problem.” On the outside it wears the veneer of modern reactive streams and microservice architecture, but peel it open and it is a minefield of vulnerabilities where resilience to failures in distributed environments and transaction isolation levels are completely missing.


The power of reverse questioning to carve away requirement ambiguity

The first breakthrough the development team adopted to use agents in real engineering within regulated environments was a reverse framework that makes the agent interrogate the developer before it writes any code. In practice, this is called the Grill Me Technique.

Ordinary developers hand an agent an ambiguous user story as is: “When a customer opens an account, publish a welcome event and leave an audit log.”

A model that receives this prompt starts writing code immediately. But behind this short sentence hide dozens of critical architectural decisions.

  • If a write lock is held on the database where the audit log is stored, should the account-opening transaction also roll back, or should the log be isolated asynchronously?
  • If publishing the welcome event fails, how many times should it retry at most, and what is the upper bound of the exponential backoff in seconds?
  • Should the Kafka partition key be the customer identifier, the account number, or the branch code?

The agent does not know these trade-offs, so it finishes the code with the most ordinary and risky defaults.

Traditional prompt (vague request)

  • Tossing in a single line of user story
  • Improvised code built on the agent's arbitrary assumptions
  • Plausible but fragile defaults everywhere
  • Instantly rejected in the enterprise audit meeting

Reverse questioning technique (Grill Me)

  • The agent stops coding and fires back a dozen or so questions
  • Network-failure rollback, internal audit rules, idempotency key verification
  • Clear technical decisions drawn out of the engineer
  • Code generated from a flawless, precise specification

Applying the reverse questioning technique completely flips the workflow. When the developer enters a requirement, the agent immediately refuses to write code and switches into system analyst mode.

Preloaded with the architecture guidelines and best-practice documents registered in the company’s Confluence wiki, the agent relentlessly presses on edge cases the developer never specified, distributed failure scenarios, and internal regulatory compliance, and fires back a dozen or so sharp questions.

Three core question areas of the reverse questioning (Grill Me) pipeline

  1. Distributed failure boundaries: Whether the DB rolls back when the Kafka broker is down, and the upper bound of the exponential retry backoff
  2. Internal regulatory compliance: Whether financial audit-log retention rules (identifier hashing and immutable storage) are met
  3. Ordering strategy: Message ordering guarantees and idempotency identifier design when partition keys collide

The developer answers the agent’s questions one by one, carving the vague business logic into a sharp technical specification (Spec). Through this process, the loose one-liner “publish an account-opening event” is transformed into a robust, dozens-of-pages architecture blueprint in which the distributed transaction boundaries, the exception taxonomy, and the idempotency key policy are all defined without gaps.

Filtering out design flaws before typing a single line of code is the first gate that turns an agent from a mere typist into a true engineering partner.


The deterministic harness architecture that wraps a probabilistic language model

A perfected specification does not mean you can leave the agent unattended. The probabilistic nature of language models does not change. Even given the same prompt and the same specification, a model produces subtly different code depending on temperature and sampling seed. Sometimes it hallucinates a nonexistent method instead of a well-tested library, and sometimes it quietly violates internal conventions.

This is where the key concept of the harness (a safety belt and control gear) comes in.

Harness engineering refers to a software control architecture that firmly confines the output of a probabilistically fluctuating language model within the frame of deterministic rule-sets that allow zero margin of error.

Three-tier deterministic harness barrier architecture that confines probabilistic AI output Figure 1. A three-tier deterministic harness barrier structure that surrounds the output of a probabilistic AI agent with contract verification, security linting, and a Testcontainers sandbox

As soon as the agent generates code, and before any human reads it, the harness runs three layers of automated verification pipelines.

The first layer is static contract verification. It mechanically checks whether the generated code complies 100% with the predefined Kafka event Avro schema or OpenAPI specification. If even a single character of a field name differs or a required metadata header is missing, the code is discarded immediately.

The second layer is security and architecture rule linting. SonarQube and the company’s internal static analyzer exhaustively check whether the agent added an external library on its own, wrote plaintext communication code that is not encrypted, or called system calls that violate financial security regulations.

The third layer is real integration simulation based on Testcontainers. It spins up a real Kafka broker and database in a local virtual environment, induces network latency and forced shutdowns, and verifies by execution whether the code correctly defends distributed transactions.

The agent receives the failure error logs the harness emits directly as feedback, and loops, fixing its own code until every test passes. Instead of being worn out watching the agent’s capricious output, the human developer is elevated to the position of a systems architect who designs and manages the ironclad verification system called the harness.


The Kafka outbox pattern and the automated gate that verifies distributed consistency

One of the most notorious failure scenarios in regulated environments is the dual-write inconsistency problem, which occurs when the database write and the message broker publication are separate.

For example, suppose the database transaction that deducts a customer’s account balance commits successfully, and right after that a brief network blip occurs, so the Kafka message “balance deduction complete” never reaches the broker and is lost. What happens then? A major financial incident erupts in which the ledger and the event stream are permanently out of sync.

The critical risk of dual-write inconsistency in finance
If a database update and a Kafka publication are simply called in sequence, a network failure right after the DB commit changes the data but permanently loses the event, collapsing consistency. In regulated financial environments, atomic isolation is essential: the change and the event must be committed together to an outbox table inside a single local transaction.

Nine out of ten pieces of code written by typical vibe coding fall into this trap. They naively call the Kafka template’s send function side by side inside the service method that updates the database.

Rather than relying on human eyeballing to catch this kind of architectural flaw, harness engineering runs a template gate that enforces the Transactional Outbox Pattern at the framework level.

Flow diagram of the transactional outbox pattern’s atomic local transaction and CDC relay delivery Figure 2. An outbox flow in which the business ledger and the event are stored atomically within a local database transaction, and CDC asynchronously relays them to Kafka

// Example of a transactional outbox pattern entity enforced by the harness
@Entity
@Table(name = "outbox_events")
public class OutboxEvent {
    @Id
    private UUID id;
    
    @Column(nullable = false)
    private String aggregateType;
    
    @Column(nullable = false)
    private String aggregateId;
    
    @Column(nullable = false)
    private String type;
    
    @Column(columnDefinition = "jsonb", nullable = false)
    private String payload;
    
    @Column(nullable = false)
    private Instant createdAt;
    
    @Enumerated(EnumType.STRING)
    private OutboxStatus status; // PENDING, PUBLISHED, FAILED
}

When the agent writes business logic and the harness’s static analyzer detects a statement that calls a Kafka producer directly, it immediately refuses to compile.

Instead, it forces the business data change and the event message to be recorded atomically in the outbox_events table within the same local database transaction. The standard harness then provides a structure in which a separate dedicated change data capture (CDC) daemon or a reliable polling relay guarantees safe delivery to the message broker.

In the integration test stage, the harness pipeline runs a chaos engineering script that forcibly shuts down the Kafka container right after the database commit. It empirically verifies that the business transaction is safely preserved even while Kafka is dead, and that the messages piled up in the outbox are recovered and delivered without losing a single one once Kafka restarts.

Only when such a robust engineering gate stands behind it can AI-generated code withstand live traffic in a production environment.


The pipeline that syncs architecture decision records with the codebase in real time

One of the most common chronic ailments in traditional software organizations is the “gap between documents and code.” At the start of a project, elegant architecture design documents and diagrams are neatly packed into Confluence, but after months of emergency patches and repeated vibe coding, the code drifts in a completely different direction from the documents.

Measured comparison of regulatory audit readiness metrics between vibe coding and harness engineering Figure 3. A comparison of schema compliance rate and dual-write defect rate between vibe coding and harness engineering, measured in a financial enterprise POC environment

To solve this problem, harness engineering builds a two-way automatic synchronization system for architectural decision records (ADRs) into the agent’s work loop.

  1. 1. Requirement changeRecord new policies and trade-offs in the Confluence architecture wiki
  2. 2. Repository syncAuto-update the /docs/adr/*.md Markdown files inside Git
  3. 3. Context injectionAutomatically inject the latest ADR constraints into the agent prompt
  4. 4. Architecture verificationDetect ADR-violating code (timeouts, packages) automatically with ArchUnit tests
  5. 5. Automatic integration completeUpdate the Azure DevOps story status and approve a safe PR merge

When a new feature is added or an existing policy changes, the development team first records its background, trade-offs, and the chosen technical approach concisely in an ADR document. An example is a specification like “Decision 0014: For external payment gateway integration, set the circuit breaker’s failure threshold to 50% and standardize the wait time at 10 seconds.”

Every time it starts work, the agent first reads the ADR directory inside the repository. It then also writes ArchUnit test code that verifies the code it is writing does not contradict previously agreed architectural decisions.

If the agent arbitrarily changes a timeout value in violation of an ADR decision or references a disallowed package, the architecture conformance test in the CI pipeline fails immediately and blocks the pull request (PR) merge at the source.

It is a complete virtuous cycle: when code changes, the document is updated, and when the document changes, the code is enforced. Documentation stops being a side chore that sneaks up on developers and becomes a precision steering mechanism that guides the powerful engine called the agent onto the right track.


The paradigm shift from running on gut feeling to verifiable system control

The shift from vibe coding to harness engineering is not a simple swap of development tools. It is a fundamental paradigm shift in the identity and responsibility of the software engineer.

The developer of the past was closer to a “craftsman” who spent all day designing classes, wrestling with syntax errors, and typing code line by line on a keyboard.

When the age of vibe coding arrived, some predicted that developers would degrade into “lazy managers” who merely give agents orders and skim the results.

But the truth confirmed on the front lines of regulated environments was the opposite. The further an agent’s coding ability outpaces human typing speed, the more the real competence required of engineers evolves away from the skill of writing code toward the architectural competence of defining system boundaries and designing verification systems.

  • Deep computer science knowledge to detect potential concurrency defects and memory leaks among the tens of thousands of lines of code a model pours out.
  • Domain analysis skills to relentlessly probe the ambiguity of business requirements and forge them into precise specifications.
  • Infrastructure control to build multi-layered test harnesses and static analysis pipelines that block probabilistic hallucinations at the source.

An organization that lacks these core engineering competencies and is intoxicated only by the drug-like speed of vibe coding will soon be buried under a huge heap of unmaintainable technical debt.

Conversely, an engineering organization with a solid harness in hand can land safe innovation in production faster than a startup, even behind the thick walls of regulation and compliance.


Core architectural principles for adopting AI agents in regulated environments

In the end, the message of the shift from vibe coding to harness engineering is clear. No matter how fast and fluent an AI agent’s probabilistic code generation is, in an enterprise environment where not a single consistency breakdown is tolerated, it is the deterministic harness surrounding the code that decides the system’s survival.

The core engineering principles an organization must put in place first to safely land AI agent workflows in real financial and public regulatory environments are as follows.

  1. Establish the specification-first principle and a reverse questioning (Grill Me) loop
    Do not start implementing right away from a single ambiguous user story line. Have the agent ask back about edge cases, such as distributed transaction boundaries, exception-handling taxonomy, and audit-log retention clauses, based on internal architecture guidelines, and enter the implementation phase only after a gap-free, precise specification has been agreed.

  2. Enforce architecture patterns at the framework level
    To prevent dual-write inconsistency between Kafka and the database, templatize the transactional outbox pattern, and connect schema contract testing and static security analysis to the CI pipeline gates. When code written by the agent violates internal architecture rules, automatically return a failure and put the agent into a self-correction loop.

  3. Two-way synchronization of architectural decision records (ADRs) and code
    To prevent a gap between wiki documents and the actual codebase, continuously feed the ADR Markdown documents inside the repository to the agent as its latest context. Mechanically verify the layer reference rules specified in the ADRs with tools like ArchUnit to block architectural erosion at the source.

Software engineering in the age of generative AI is not a race over how fast you can type code. The success of an enterprise depends on how firmly you can contain the output of probabilistically fluctuating intelligence within deterministic rules and an automated verification system. Going beyond vibe coding that runs on gut feeling to design a controllable harness is the true direction modern enterprise architecture must take.

#Vibe Coding#Harness Engineering#AI Agents#Kafka#Architecture