"A lot of AI is ultimately software engineering with different vocabulary and a little bit of non-determinism," posits Jason Davenport, a sentiment echoed by Aja Hammerly, both from Google Cloud Tech. Their recent "AI Agent Dance Off" on the "Real Terms for AI" series offered a compelling whiteboard comparison of two distinct architectural approaches to building AI coding agents. The discussion, aimed at demystifying the complexities of AI development for a discerning audience of founders, VCs, and AI professionals, centered on leveraging Large Language Models (LLMs) for task planning, developing effective code generation and evaluation loops, and integrating contextual information to enhance agent performance, particularly through the lens of Test-Driven Development (TDD).
Aja's initial design for an AI coding agent presented a straightforward, almost intuitive, workflow. A user's prompt, such as "build a calculator," initiates the process, leading an LLM to formulate a plan. This plan then flows into a "Gen Code" module, which generates the necessary code. The generated code proceeds to an "Exec Code" function for execution. Crucially, any errors or output from the execution phase are fed back directly to the "Gen Code" module, creating an iterative loop for refinement until the code ideally functions as intended. Once a successful result is achieved, it cycles back to the original LLM and then to the user, culminating in a seemingly happy outcome.
However, this seemingly elegant simplicity quickly revealed potential vulnerabilities. Jason astutely probed the limitations of such a direct feedback loop, questioning what happens if the "Gen Code" and "Exec Code" modules become trapped in an infinite loop of errors and attempted fixes. More fundamentally, he asked, "what happens if the generated code doesn't actually address what we've asked for in our original plan?" This highlights a critical insight: a purely reactive, error-correction loop, without higher-level oversight, risks producing functionally correct but ultimately irrelevant code. Aja acknowledged these issues, proposing a modification where errors and outputs loop back to the central LLM itself, enabling the agent to evaluate progress, adjust its overarching plan, and provide more informed input for code generation. This introduces a necessary layer of meta-cognition, allowing the agent to self-correct at a strategic level, rather than merely tactical.
Jason’s architectural paradigm, while sharing foundational principles with Aja’s, immediately introduced a more robust and nuanced approach by emphasizing context and a multi-tiered evaluation strategy. He starts by augmenting the initial prompt with comprehensive "Context," encompassing the existing codebase, established rules, and Model Context Protocol (MCP) elements. This critical step provides the LLM with the necessary background knowledge upfront, preventing the agent from operating in a vacuum. As Jason articulated, "a junior dev isn't going to be able to write good code if they don't know what I'm actually expecting." This initial contextualization is a key insight, ensuring the AI agent possesses the equivalent of institutional knowledge before embarking on a task.
Following this contextualization, Jason's LLM is tasked with formulating a "high-level plan," breaking down complex coding tasks into manageable, sequential steps. This foresight addresses the inherent complexity of real-world development, acknowledging that "any reasonably complex coding task isn't going to be just a single-step to actually get there." Each step of this high-level plan then enters a localized "Plan -> Eval -> Execute" loop, similar in concept to Aja's refined model. The "Execute" phase in Jason’s design is empowered by a suite of tools, including Java, linting, formatting, style checkers, and direct execution capabilities, reflecting the diverse requirements of modern software development.
