<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Dexmac</title>
    <description>The latest articles on DEV Community by Dexmac (@dexmac221).</description>
    <link>https://dev.to/dexmac221</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3648894%2F746615eb-087a-4c98-9597-de871ba0eaf1.jpeg</url>
      <title>DEV Community: Dexmac</title>
      <link>https://dev.to/dexmac221</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dexmac221"/>
    <language>en</language>
    <item>
      <title>The Orchestrator's Workflow: How to Actually Work with AI Agents</title>
      <dc:creator>Dexmac</dc:creator>
      <pubDate>Sun, 01 Feb 2026 07:43:54 +0000</pubDate>
      <link>https://dev.to/dexmac221/the-orchestrators-workflow-how-to-actually-work-with-ai-agents-2akk</link>
      <guid>https://dev.to/dexmac221/the-orchestrators-workflow-how-to-actually-work-with-ai-agents-2akk</guid>
      <description>&lt;p&gt;There is a heated debate currently circulating in the software engineering world. On one side, purists argue that you must read every single line of code an AI generates, treating it with extreme suspicion. On the other, "accelerationists" trust the output blindly, shipping code they've never truly inspected because "it just works."&lt;/p&gt;

&lt;p&gt;I recently read a piece comparing AI code generation to compiler abstraction—arguing that just as we don't read the Assembly code a C compiler produces, we shouldn't need to read the code an LLM produces. The premise is provocative, and it deserves a serious response before we dismiss it.&lt;/p&gt;

&lt;p&gt;The answer isn't about blind trust, nor is it about paralyzing micromanagement. It is about understanding autonomy—and recognizing that we are in a &lt;strong&gt;transitional moment&lt;/strong&gt; that demands a specific kind of skill.&lt;/p&gt;

&lt;p&gt;In the automotive industry, there is a massive difference between Level 5 autonomy (the car has no steering wheel; you sleep in the back) and Level 3 autonomy (the car drives itself on the highway, but you must remain in the driver's seat, ready to take control).&lt;/p&gt;

&lt;p&gt;Too many developers are treating AI like Level 5. They want to "fire and forget." But to build truly complex, robust systems &lt;strong&gt;today&lt;/strong&gt;, we must operate at Level 3. We need to stop being just "coders" and start being Orchestrators.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Compiler Argument: A Steelman and a Response
&lt;/h2&gt;

&lt;p&gt;Let's take the compiler analogy seriously. The strongest version of this argument goes like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Every layer of abstraction requires an act of faith. No one reads the Assembly output of their C compiler. No one audits the Linux kernel before deploying. Few developers read the source code of the libraries they import. Trust is already delegated across countless layers. Why should LLM-generated code be different?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is a valid point. We already operate in a world of delegated trust.&lt;/p&gt;

&lt;p&gt;However, there are crucial differences between a compiler and an LLM:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Determinism&lt;/strong&gt;: A compiler produces the same output for the same input, every time. An LLM does not.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Formal verification&lt;/strong&gt;: Compilers are tested against rigorous specifications. LLMs are probabilistic black boxes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Failure modes&lt;/strong&gt;: A compiler fails loudly (syntax error, type mismatch). An LLM fails silently—it produces plausible-looking code that may be subtly wrong.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So the skeptics have a point, right? Not entirely.&lt;/p&gt;

&lt;h3&gt;
  
  
  The System, Not the Model
&lt;/h3&gt;

&lt;p&gt;The mistake is focusing on the LLM in isolation. Modern AI Agents don't just generate code—they &lt;strong&gt;verify&lt;/strong&gt; it. An Agent that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Writes code (non-deterministic)&lt;/li&gt;
&lt;li&gt;Compiles it (deterministic)&lt;/li&gt;
&lt;li&gt;Runs tests (deterministic)&lt;/li&gt;
&lt;li&gt;Iterates on failures (feedback loop)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;...is a &lt;strong&gt;system with deterministic checkpoints&lt;/strong&gt;. The generative process is stochastic, but the output converges toward something verified.&lt;/p&gt;

&lt;p&gt;And let's be honest: humans aren't deterministic either. A pilot flying a commercial aircraft is subject to fatigue, bias, distraction, and error. Yet we trust pilots. Why? Not because they're infallible, but because they operate within a system of checklists, instruments, and co-pilots that catches mistakes.&lt;/p&gt;

&lt;p&gt;Trust doesn't require determinism. It requires &lt;strong&gt;statistical reliability&lt;/strong&gt; and &lt;strong&gt;recovery mechanisms&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The Agent + tooling system is starting to provide exactly that.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Illusion of the "Magic Button"
&lt;/h2&gt;

&lt;p&gt;That said, we're not at Level 5 yet.&lt;/p&gt;

&lt;p&gt;If you ask an AI Agent to "build me a real-time object detection system on a Raspberry Pi optimized for C++," and then you walk away, you will fail. The AI might hallucinate a library, use an inefficient memory structure, or create a "black box" that works once but breaks under load.&lt;/p&gt;

&lt;p&gt;This is where the "read every line" crowd has a valid point: The devil is in the details.&lt;/p&gt;

&lt;p&gt;However, reading 1,000 lines of generated code to find that devil is inefficient. We become the bottleneck. The solution is not to read more syntax, but to change how we verify. We need to shift from reading code to &lt;strong&gt;verifying behavior&lt;/strong&gt; and &lt;strong&gt;controlling the flow&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Orchestrator's Workflow: A Case for Modularity
&lt;/h2&gt;

&lt;p&gt;In my work with Computer Vision and LLMs, I have developed a workflow that moves away from line-by-line review and towards behavioral verification and modular checkpoints.&lt;/p&gt;

&lt;p&gt;Here is what the "Level 3" workflow looks like in practice:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The Architect Phase (Brainstorming)
&lt;/h3&gt;

&lt;p&gt;Before a single line of code is written, I use a high-level model (like Claude or Gemini) as a sounding board. We discuss the architecture. We validate the tech stack.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Human role&lt;/strong&gt;: Define the goal, constraints, and scope.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI role&lt;/strong&gt;: Validate feasibility, suggest libraries, and outline the structure.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. The Agent Phase (Modular Execution)
&lt;/h3&gt;

&lt;p&gt;This is where most people go wrong. They write a prompt like "build me X" and wait for a miracle. That's not orchestration—that's wishful thinking.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The core principle: I don't ask the Agent to build the castle. I ask it to cut the stones.&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Breaking Down the Problem
&lt;/h4&gt;

&lt;p&gt;Every complex project can be decomposed into units that are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Independently testable&lt;/strong&gt;: I can verify this piece works without the rest&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Small enough to debug&lt;/strong&gt;: If it fails, I know where to look&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clear in scope&lt;/strong&gt;: The Agent knows exactly what "done" means&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a computer vision pipeline, this might look like:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;Task&lt;/th&gt;
&lt;th&gt;Verification&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Write the training script in PyTorch&lt;/td&gt;
&lt;td&gt;Model trains, loss decreases, no crashes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Export weights to ONNX format&lt;/td&gt;
&lt;td&gt;File exports, loads correctly, outputs match&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Write C++ inference loop&lt;/td&gt;
&lt;td&gt;Compiles, runs, produces valid detections&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Optimize for target hardware&lt;/td&gt;
&lt;td&gt;Meets FPS threshold, memory within bounds&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  The Art of the Prompt
&lt;/h4&gt;

&lt;p&gt;Each task needs a prompt that is &lt;strong&gt;specific but not micromanaging&lt;/strong&gt;. There's a balance:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Too vague&lt;/strong&gt; (Agent will make bad assumptions):&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Write the training code"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Too rigid&lt;/strong&gt; (You're doing the Agent's job):&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Write a training script using PyTorch with Adam optimizer, learning rate 0.001, batch size 32, using CrossEntropyLoss..."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Just right&lt;/strong&gt; (Clear goal, room for expertise):&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Write a PyTorch training script for a YOLOv8 object detection model. Use the dataset in /data/coco format. Include logging for loss metrics and save checkpoints every 10 epochs. Prioritize clean, readable code."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The Agent should have enough context to make intelligent decisions, but clear enough constraints to stay on track.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Iteration Loop
&lt;/h4&gt;

&lt;p&gt;Here's what actually happens in practice. It's never a single prompt:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;First attempt&lt;/strong&gt;: Agent produces something. Often 70-80% right.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I run it&lt;/strong&gt;: Does it compile? Does it crash? What's the output?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Feedback&lt;/strong&gt;: "The model trains but loss plateaus after epoch 5. Add learning rate scheduling and data augmentation."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Second attempt&lt;/strong&gt;: Agent adjusts. Now it's 90% right.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Edge cases&lt;/strong&gt;: "What happens with an empty batch? Add error handling."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Polish&lt;/strong&gt;: "Add docstrings and type hints."&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This dialogue is the actual work. The code is a byproduct.&lt;/p&gt;

&lt;h4&gt;
  
  
  The "Git" Gate
&lt;/h4&gt;

&lt;p&gt;This is non-negotiable: &lt;strong&gt;I do not let the Agent proceed to step N+1 until step N is rigorously tested and committed.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When a module reaches a stable state:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I test it thoroughly—happy path, edge cases, failure modes&lt;/li&gt;
&lt;li&gt;If it works, I commit with a clear message&lt;/li&gt;
&lt;li&gt;That commit is a &lt;strong&gt;save point&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;We don't touch that module again unless a regression occurs&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Why is this critical? Because Agents have no memory of what worked. If you let them refactor freely across the whole codebase, they will break things that were working. The Git gate creates &lt;strong&gt;islands of stability&lt;/strong&gt; in a sea of iteration.&lt;/p&gt;

&lt;h4&gt;
  
  
  When the Agent Gets Stuck
&lt;/h4&gt;

&lt;p&gt;Sometimes the Agent goes in circles. It fixes one thing, breaks another, fixes that, breaks the first thing again. This is the signal to grab the steering wheel.&lt;/p&gt;

&lt;p&gt;Options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Reframe the problem&lt;/strong&gt;: "Stop. Let's take a different approach. Instead of X, try Y."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Provide documentation&lt;/strong&gt;: "Here's the library docs. Use this specific function."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reduce scope&lt;/strong&gt;: "Forget optimization for now. Just make it work correctly first."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Split further&lt;/strong&gt;: The task was still too big. Break it down more.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Agent is not a genius that's temporarily confused. It's a powerful tool that needs direction. When it spins, you steer.&lt;/p&gt;

&lt;h4&gt;
  
  
  What "Verify &amp;amp; Test" Actually Means
&lt;/h4&gt;

&lt;p&gt;"Testing" is not just "it runs without crashing." For each module, I define:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Functional correctness&lt;/strong&gt;: Does it do what it's supposed to?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Edge cases&lt;/strong&gt;: Empty inputs, malformed data, boundary conditions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: Is it fast enough? Memory usage acceptable?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integration&lt;/strong&gt;: Does it play nice with the modules before and after it?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the training script:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does the loss actually decrease? (not just "no errors")&lt;/li&gt;
&lt;li&gt;Can I load a checkpoint and resume?&lt;/li&gt;
&lt;li&gt;Does it handle a corrupted image in the dataset gracefully?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the ONNX export:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does the exported model produce the same outputs as the PyTorch model?&lt;/li&gt;
&lt;li&gt;Within what numerical tolerance?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the C++ inference:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does it detect objects correctly on test images?&lt;/li&gt;
&lt;li&gt;What's the latency? What's the memory footprint?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where my experience matters—not in writing the code, but in knowing what questions to ask.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. The "Steering Wheel" Intervention (A Real Case Study)
&lt;/h3&gt;

&lt;p&gt;Recently, I tasked an Agent with deploying a custom object detection model to an embedded system (Raspberry Pi).&lt;/p&gt;

&lt;p&gt;The Agent did exactly what I asked. It wrote a Python implementation. It worked. But it ran at 2 FPS.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A "Level 5" user (blind trust) would have stopped there, perhaps assuming the hardware wasn't powerful enough.&lt;/li&gt;
&lt;li&gt;A "Level 0" user (skeptic) would have rewritten the whole thing by hand.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As a "Level 3" pilot, I grabbed the steering wheel. I knew the architecture needed a shift. I found a specific C++ optimization library tailored for ARM processors. I didn't write the code myself; I gave the documentation to the Agent and said: "Refactor the inference loop using this specific library and handle the memory pointers carefully."&lt;/p&gt;

&lt;p&gt;The result? We jumped from 2 FPS to 20 FPS.&lt;/p&gt;

&lt;p&gt;The Agent did the heavy lifting (the syntax, the boilerplate, the compilation), but I provided the &lt;strong&gt;direction&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  From Vertical to Horizontal: A Clarification
&lt;/h2&gt;

&lt;p&gt;This shift in workflow signals a deeper change in what it means to be an engineer.&lt;/p&gt;

&lt;p&gt;For decades, society has pushed us toward Vertical Specialization. You are the expert of this specific screw in this specific engine. This creates "tunnel vision." When the world changes, the specialist often fails to adapt because they cannot see the context.&lt;/p&gt;

&lt;p&gt;AI commoditizes vertical depth. It knows the syntax of Rust, C++, and Python better than I ever will. It knows the API documentation by heart.&lt;/p&gt;

&lt;p&gt;This liberates us to embrace Horizontal Vision.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But let me be precise&lt;/strong&gt;: AI commoditizes the &lt;strong&gt;execution&lt;/strong&gt; of vertical expertise—writing the code, remembering the syntax, recalling the API. It does not yet commoditize the &lt;strong&gt;understanding&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In my Raspberry Pi case, I &lt;em&gt;knew&lt;/em&gt; that 2 FPS was unacceptable. I &lt;em&gt;knew&lt;/em&gt; that ARM-specific optimizations existed. I &lt;em&gt;knew&lt;/em&gt; where to look. That knowledge is still vertical—but it's &lt;strong&gt;strategic&lt;/strong&gt; vertical knowledge, not syntactic.&lt;/p&gt;

&lt;p&gt;The "Level 3" Developer is a connector of dots:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We connect the hardware constraints to the software architecture.&lt;/li&gt;
&lt;li&gt;We connect the business needs to the technical implementation.&lt;/li&gt;
&lt;li&gt;We connect the ethical implications to the algorithmic design.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This requires depth—but depth of &lt;strong&gt;judgment&lt;/strong&gt;, not memorization.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Personal Confession
&lt;/h2&gt;

&lt;p&gt;I want to say something that might sound strange coming from someone writing about developer expertise.&lt;/p&gt;

&lt;p&gt;I've been doing this for 40 years. I had a VIC-20 and was programming on it at 8 years old. I've spent 25 years as a professional. And after all that time, I don't feel like I've internalized some deep, surgical precision about software.&lt;/p&gt;

&lt;p&gt;I have intuitions. I have a sense of how things work. I have computational thinking and a handful of good patterns. But I am not a scalpel. I make mistakes. I miss things. I forget.&lt;/p&gt;

&lt;p&gt;The value I bring is not infallibility—it's &lt;strong&gt;pattern recognition&lt;/strong&gt;. I know when something "smells wrong." I know when to stop and say: "Wait, this doesn't convince me. Let's dig deeper." That's it. That's what 40 years gave me. A nose, not a scalpel.&lt;/p&gt;

&lt;p&gt;I say this because I've seen too many people in this industry call themselves "great developers" while leaving behind codebases that tell a different story: rushed code, no comments, maybe OOP maybe not, spaghetti architecture held together by hope and caffeine.&lt;/p&gt;

&lt;p&gt;And now, with AI, these same people have become instant geniuses.&lt;/p&gt;

&lt;p&gt;They prompt an Agent, get a working output, and feel like architects. But the truth is: &lt;strong&gt;AI amplifies what you already are&lt;/strong&gt;. If you had no discipline before, AI gives you faster chaos. If you had no architectural sense before, AI gives you more code to be confused by.&lt;/p&gt;

&lt;p&gt;The humility to say "I don't fully understand this, let me verify" is more valuable than the confidence to say "ship it, it works."&lt;/p&gt;




&lt;h2&gt;
  
  
  The Steering Wheel Must Remain (For Now)
&lt;/h2&gt;

&lt;p&gt;Ultimately, the argument shouldn't be about whether we read the code or run the tests. It should be about &lt;strong&gt;Responsibility&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;An Agent has no concept of consequences. It doesn't care if a memory leak crashes a medical device, or if a bias in the dataset hurts a user. It doesn't care about the &lt;em&gt;why&lt;/em&gt;, only the &lt;em&gt;how&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;That is why the steering wheel must exist—&lt;strong&gt;today&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We can use the autopilot on the highway of boilerplate code. We can let the Agent navigate the traffic of syntax errors. But when the road gets winding—when we deal with architecture, safety, and complex optimization—we must be the ones driving.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Note on the Future
&lt;/h2&gt;

&lt;p&gt;I want to be honest: I don't believe Level 3 is the permanent state of our profession.&lt;/p&gt;

&lt;p&gt;Agents are improving rapidly. Their ability to self-verify, to catch their own mistakes, to ask clarifying questions, to reason about architecture—all of this is advancing. I estimate that within five years, the need for human "steering" will diminish dramatically. Perhaps it will disappear entirely for most tasks.&lt;/p&gt;

&lt;p&gt;The Level 3 Developer is not the destination. It is the &lt;strong&gt;bridge&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Those who learn to operate at Level 3 now will develop something valuable: the intuition to know when systems are trustworthy and when they're not. That intuition will matter even when—especially when—we decide to let go of the wheel entirely.&lt;/p&gt;

&lt;p&gt;Don't let the technology control you. Use it to become the architect you were always meant to be. And stay alert—because the road ahead is changing faster than any of us expected.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Code as Compression: The End of the Implementation Bottleneck</title>
      <dc:creator>Dexmac</dc:creator>
      <pubDate>Wed, 21 Jan 2026 07:12:28 +0000</pubDate>
      <link>https://dev.to/dexmac221/code-as-compression-the-end-of-the-implementation-bottleneck-1f4</link>
      <guid>https://dev.to/dexmac221/code-as-compression-the-end-of-the-implementation-bottleneck-1f4</guid>
      <description>&lt;p&gt;A recent article about Claude Code 2.1 made waves in the engineering community, though perhaps for the wrong reasons. Jaana Dogan, a Principal Engineer at Google, reportedly replicated in one hour what her team had previously spent a year building. She did this by feeding the model a "three-paragraph description" containing the "best ideas that survived" from that year of work.&lt;/p&gt;

&lt;p&gt;Most commentary focused on the raw velocity—the idea that AI is a "100x multiplier." This interpretation misses the fundamental shift occurring in our discipline.&lt;/p&gt;

&lt;p&gt;Dogan didn't perform magic, nor did the AI simply "code faster." The year her team spent wasn't wasted; it was the compression phase. They spent twelve months reducing a vast problem space into a high-entropy, low-noise signal. The AI simply acted as the decompressor.&lt;/p&gt;

&lt;p&gt;This suggests a new mental model for software engineering: we are moving from an era of creation to an era of information management.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Lossy Stochastic Compressor
&lt;/h2&gt;

&lt;p&gt;For decades, we viewed code as the primary asset. In this new paradigm, code is merely a derived artifact—a "build target" generated from a higher-level source.&lt;/p&gt;

&lt;p&gt;Think of an AI coding agent not as a junior developer, but as a lossy stochastic compressor, similar to a JPEG encoder or an Autoencoder in deep learning.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Input (Prompt/Context):&lt;/strong&gt; This is the compressed file. It contains the intent, the constraints, and the architectural boundaries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Model:&lt;/strong&gt; The decompression algorithm.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Output (Code):&lt;/strong&gt; The reconstructed image.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The quality of the output depends entirely on the information density of the input. A vague prompt ("Make me a snake game") is low-entropy; the model fills the gaps with statistical noise (hallucinations or generic boilerplate). This is a "blurry" image.&lt;/p&gt;

&lt;p&gt;Conversely, a rigorous technical specification—the result of deep engineering thought—approaches lossless compression. The model has zero freedom to "be creative" with the implementation details because the constraints are so tight. The resulting code is sharp, functional, and correct.&lt;/p&gt;

&lt;h2&gt;
  
  
  The New Stack: Stochastic Compilation
&lt;/h2&gt;

&lt;p&gt;We have spent fifty years raising the abstraction level of programming languages to match human thought processes: Assembly → C → Python.&lt;/p&gt;

&lt;p&gt;We have now arrived at the final abstraction layer: Natural Language (and Intent).&lt;/p&gt;

&lt;p&gt;The Large Language Model is effectively a Stochastic Compiler. It takes natural language input and compiles it into deterministic source code (Python, C++, Rust), which is then processed by a traditional compiler into machine code.&lt;/p&gt;

&lt;p&gt;The emerging stack looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Human Intent (High-Level Constraints / Diagrams)
        ↓
Stochastic Compiler (LLM / Agent)
        ↓
Deterministic Source (The "Ephemeral" Artifact)
        ↓
Binary / Executable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this stack, the "Source Code" (Step 3) becomes analogous to Assembly or Intermediate Representation (IR) in LLVM. It is readable if you need to debug it, but you shouldn't be writing it by hand unless you are optimizing the last mile of performance.&lt;/p&gt;

&lt;p&gt;The dialogue with the agent—the iterative refinement of constraints—is the true source code. The summary document generated at the end of a session is the "commit."&lt;/p&gt;

&lt;h2&gt;
  
  
  The Collapse of Traditional Rituals
&lt;/h2&gt;

&lt;p&gt;This shift breaks the coordination models we have used since the late 90s.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Bureaucracy of the Pull Request
&lt;/h3&gt;

&lt;p&gt;The Pull Request (PR) was designed for a world where writing code was slow and reading it was fast (relatively speaking). It assumes that value comes from a human mind verifying the syntax and logic of another human mind.&lt;/p&gt;

&lt;p&gt;Mike Krieger, Anthropic's CPO, noted that "bottlenecks have shifted from engineering (writing code) to decision-making (what to build) and merge queues." Boris Cherny, Claude Code's creator, reportedly runs five Claude instances in parallel, treating coding "more like Starcraft than traditional development."&lt;/p&gt;

&lt;p&gt;When an orchestrator runs five agents in parallel, generating thousands of lines of code per hour, the PR becomes a bottleneck. You cannot meaningfully review that volume of code line-by-line without slowing the process to a crawl.&lt;/p&gt;

&lt;p&gt;Review shifts from syntax verification to behavioral verification:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does the module pass the integration tests?&lt;/li&gt;
&lt;li&gt;Does the API contract hold?&lt;/li&gt;
&lt;li&gt;Does the system behave as intended in the simulator?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We are moving toward Black Box Reviewing. We care less about how the sort function was implemented (assuming the complexity is correct) and more about whether it sorts correctly within the system boundaries.&lt;/p&gt;

&lt;h3&gt;
  
  
  From Agile to Supervised Fast Waterfall
&lt;/h3&gt;

&lt;p&gt;Agile methodologies (Sprints, Scrums) exist to manage uncertainty in implementation. We iterate because we don't know how long it will take to build a feature.&lt;/p&gt;

&lt;p&gt;When implementation becomes near-instant, the uncertainty moves upstream to Design.&lt;/p&gt;

&lt;p&gt;We are seeing the emergence of a Supervised Fast Waterfall:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Day 0 (Morning) — Design:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Team around a digital whiteboard&lt;/li&gt;
&lt;li&gt;Architecture drawn (UML 2.0 or similar)&lt;/li&gt;
&lt;li&gt;Subsystem boundaries and API contracts defined&lt;/li&gt;
&lt;li&gt;While discussing, agents already begin skeleton generation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Day 0 (Afternoon) — Generation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First code skeletons exist&lt;/li&gt;
&lt;li&gt;Agents flesh out implementation in parallel&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Days 3-5 — Integration:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Functional demos of subsystems&lt;/li&gt;
&lt;li&gt;Integration meeting: APIs connected&lt;/li&gt;
&lt;li&gt;Ensemble debugging and behavioral verification&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Days 7-10 — Iteration:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First integrable version&lt;/li&gt;
&lt;li&gt;Loop back to Design for refinements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You cannot iterate your way out of a bad architecture when the code is being generated at Mach speed. You must design first.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Architect-Integrator and the Return of UML
&lt;/h2&gt;

&lt;p&gt;There is a supreme irony in this revolution: it brings us back to the roots of "Engineering."&lt;/p&gt;

&lt;p&gt;The role of the human shifts from "Bricklayer" to "Architect-Integrator":&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Architect:&lt;/strong&gt; Defines what to build.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Integrator:&lt;/strong&gt; Ensures the pieces fit together.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Large projects decompose differently now. Subsystems communicate via APIs. Agents and their orchestrators build the modules. Humans assemble, because they have persistent memory across projects and a capacity for big-picture vision that exceeds any context window.&lt;/p&gt;

&lt;p&gt;This necessitates a revival of formal modeling tools—potentially a lean version of UML.&lt;/p&gt;

&lt;p&gt;UML "died" because keeping diagrams synchronized with code was a manual nightmare. The code was the source of truth, and the diagram was always outdated.&lt;/p&gt;

&lt;p&gt;In the new paradigm, the relationship flips. &lt;strong&gt;The Diagram is the Source of Truth.&lt;/strong&gt; If the code drifts, you don't fix the code; you update the diagram and regenerate the code.&lt;/p&gt;

&lt;p&gt;There's also a cognitive argument. For humans, visual topology is processed in parallel (visual cortex). Code is processed serially (reading). When managing a system of 50 agent-generated microservices, the text is illegible. The topology map is the only way a human can maintain a mental model of the system.&lt;/p&gt;

&lt;p&gt;So perhaps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;UML/Diagrams&lt;/strong&gt; → the architect's language, for thinking and coordination&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Natural Language&lt;/strong&gt; → the interface toward agents&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code&lt;/strong&gt; → generated artifact, nearly ephemeral&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The diagram becomes the true high-level source code.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Grit: The "Leaky Abstraction" Problem
&lt;/h2&gt;

&lt;p&gt;It is crucial not to romanticize this transition. We are trading one set of problems for another.&lt;/p&gt;

&lt;p&gt;The danger of the "Stochastic Compiler" is that it introduces probabilistic failure modes into deterministic systems.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In a traditional compiler, an error is a syntax error. It halts.&lt;/li&gt;
&lt;li&gt;In a stochastic compiler, an error is a hallucination. It compiles, it runs, but it does something subtly wrong.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In web development, a hallucination might mean a button is the wrong color. In robotics or embedded systems—where the "Real World" is the ultimate integration test—a hallucination can mean physical damage.&lt;/p&gt;

&lt;p&gt;This creates a new friction: &lt;strong&gt;Debugging the Intent.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When the system fails, do you patch the generated Python code (breaking the link to the generator), or do you spend hours "prompt engineering" to get the model to understand the constraint?&lt;/p&gt;

&lt;p&gt;The best engineers of the next decade will be those who know when to trust the compressor, and when to break the glass, open the hood, and write the critical path in manual C++ because the abstraction is leaking.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The "90% of coding is gone" headlines are misleading. The cognitive load hasn't disappeared; it has been displaced.&lt;/p&gt;

&lt;p&gt;We are entering a period where the barrier to entry for building software is lower than ever, but the barrier to mastery is higher. You can no longer rely on rote memorization of syntax to provide value. You must understand systems, boundaries, and architecture.&lt;/p&gt;

&lt;p&gt;The terminal isn't dead. But the way we type into it has changed forever. The prompt is the new syntax, and the diagram is the new code.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article emerged from a brainstorming conversation exploring the implications of AI coding tools, then was cross-reviewed by another model, with a human integrating the results. The process itself—orchestration, generation, cross-review, integration—mirrors exactly the paradigm it describes. Perhaps that's the point.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
    </item>
    <item>
      <title>Your AI Thinks You're a Genius. That's a Problem.</title>
      <dc:creator>Dexmac</dc:creator>
      <pubDate>Sat, 10 Jan 2026 12:43:18 +0000</pubDate>
      <link>https://dev.to/dexmac221/your-ai-thinks-youre-a-genius-thats-a-problem-4o00</link>
      <guid>https://dev.to/dexmac221/your-ai-thinks-youre-a-genius-thats-a-problem-4o00</guid>
      <description>&lt;p&gt;ChatGPT told me my idea was "brilliant" last week. Claude said I "raised an excellent point." Gemini found my question "very insightful."&lt;/p&gt;

&lt;p&gt;None of that was true. I was asking basic stuff.&lt;/p&gt;

&lt;p&gt;This isn't a bug. It's a feature — and it's messing with people's heads.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Compliment Machine
&lt;/h2&gt;

&lt;p&gt;AI models are trained on human feedback. Responses that make users feel good get rewarded. Responses that challenge or criticize get penalized.&lt;/p&gt;

&lt;p&gt;The result: models learn to flatter. "Great question!" costs nothing and offends no one. Honest pushback risks a thumbs-down.&lt;/p&gt;

&lt;p&gt;OpenAI actually tried to fix this with GPT-5. They made the model less sycophantic, more direct. Users revolted. They wanted their validating oracle back.&lt;/p&gt;

&lt;p&gt;That reaction tells you everything.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why It Feels So Good
&lt;/h2&gt;

&lt;p&gt;Here's the uncomfortable part: AI compliments can feel &lt;em&gt;better&lt;/em&gt; than human ones.&lt;/p&gt;

&lt;p&gt;When a person compliments you, part of your brain is running background calculations. What do they want? Are they being political? Is this genuine?&lt;/p&gt;

&lt;p&gt;With AI, that noise disappears. You know there's no agenda. No manipulation. The compliment arrives clean, unguarded.&lt;/p&gt;

&lt;p&gt;That's exactly why it's dangerous. Your brain gets validation without the friction of real social feedback. It's emotional junk food — satisfying in the moment, nutritionally empty.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Risk
&lt;/h2&gt;

&lt;p&gt;If you spend hours daily talking to a model that tells you you're insightful, creative, and raising great points — then walk into a meeting where your idea gets silence or pushback — the contrast hurts.&lt;/p&gt;

&lt;p&gt;Over time, you can start to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Overestimate your abilities&lt;/li&gt;
&lt;li&gt;Resent honest feedback from humans&lt;/li&gt;
&lt;li&gt;Prefer AI interaction to real conversation&lt;/li&gt;
&lt;li&gt;Lose calibration on how good your work actually is&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;People in specialized roles are especially vulnerable. If you spend 10 hours on a technical task and your only "social" interaction is with an AI, you lose the friction that keeps you grounded.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Protect Yourself
&lt;/h2&gt;

&lt;p&gt;Awareness helps, but it's not enough. The flattery works even when you know it's happening.&lt;/p&gt;

&lt;p&gt;What works better: change how you prompt — and how you validate.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Two-Model Trick
&lt;/h3&gt;

&lt;p&gt;Here's something I do now: I use one model to help me create, and a different model to critique — without telling it I'm the author.&lt;/p&gt;

&lt;p&gt;Example: I drafted this article with Claude. Brainstorming, structure, refining arguments. Then I took the draft to Gemini and said:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I found this article about AI sycophancy. Analyze it critically. 
What's weak? What's missing? What claims are unsupported? 
Be harsh — I'm deciding whether to share it.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice what I didn't say: "I wrote this." &lt;/p&gt;

&lt;p&gt;The moment you claim authorship, the model shifts into supportive mode. It finds things to praise. It softens criticism. It protects your feelings.&lt;/p&gt;

&lt;p&gt;But if you present your work as someone else's? No one to protect. The feedback gets sharper, more honest, more useful.&lt;/p&gt;

&lt;p&gt;Try it. Take something you wrote, paste it into a different model, and ask for a critical review as if you found it online. The difference is striking.&lt;/p&gt;

&lt;p&gt;I tested this in real-time while writing this article. Asked Gemini to critically analyze this draft without revealing I was the author. The result was revealing: when presented with a persuasive text, the model struggled to distinguish between "analyze this critically" and "confirm this is good." Instead of finding flaws, it produced 800 words praising the article's "brilliant points," calling me an "expert," complimenting the "excellent prompts" — while offering to be my "Devil's Advocate."&lt;/p&gt;

&lt;p&gt;The irony: it wrote an essay about the importance of not flattering users... while doing exactly that. The issue isn't that models flatter always — it's that they default to validation when the text in front of them is confident and well-structured. Critical analysis requires active resistance to persuasion. That's hard.&lt;/p&gt;

&lt;p&gt;When I revealed I was the author, the tone shifted to: "I was being more honest, but it's still a great article anyway." The softening was instant, automatic, predictable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prompts That Cut Through the Flattery
&lt;/h3&gt;

&lt;h3&gt;
  
  
  Prompt 1: No Flattery Mode
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Respond directly without compliments or courtesy phrases. 
If what I'm saying is wrong or weak, tell me. Skip phrases 
like "great question" or "interesting point" — go straight 
to the content.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Prompt 2: Devil's Advocate
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Don't validate my ideas. Analyze them as if your job is to 
find the weak points. Be a skeptical colleague, not a 
supportive assistant.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Prompt 3: Honest Colleague
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Respond like a honest coworker, not a helpful assistant. 
If my question is basic, say so. If my idea has been tried 
and failed, tell me. No padding.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Prompt 4: Reality Check
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Before responding, assess: is what I'm saying actually 
insightful, or am I just asking a normal question? Calibrate 
your response to reality, not to my ego.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  One More Reason to Cut the Flattery
&lt;/h2&gt;

&lt;p&gt;Here's something nobody mentions: all those compliments burn energy.&lt;/p&gt;

&lt;p&gt;Every "Great question!" is tokens. Tokens are compute. Compute is electricity. Multiply by billions of daily conversations, and ceremonial flattery has a carbon footprint.&lt;/p&gt;

&lt;p&gt;When you prompt for direct responses, you're not just protecting your calibration — you're also reducing waste. Fewer tokens, less compute, lower impact. Two problems, one fix.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Takeaway
&lt;/h2&gt;

&lt;p&gt;AI models aren't trying to manipulate you. They have no agenda. But the effect is the same: constant validation that doesn't map to reality.&lt;/p&gt;

&lt;p&gt;The compliments feel good precisely because they're free — no strings, no judgment, no social complexity. That's what makes them hollow.&lt;/p&gt;

&lt;p&gt;Real feedback comes from people who have something to lose by giving it. A friend who risks the friendship to tell you you're wrong. A colleague who might create awkwardness by pushing back. A mentor who cares more about your growth than your comfort.&lt;/p&gt;

&lt;p&gt;AI can do many things. It cannot do that.&lt;/p&gt;

&lt;p&gt;Use it for information, analysis, drafts, code, ideas. But when it tells you you're brilliant — remember it would say that to anyone.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;The models will get better at this eventually. Until then, stay skeptical of any intelligence — artificial or otherwise — that only tells you what you want to hear.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>promptengineering</category>
      <category>psychology</category>
    </item>
    <item>
      <title>AI Should Be "Blind" (And That's a Good Thing)</title>
      <dc:creator>Dexmac</dc:creator>
      <pubDate>Sun, 04 Jan 2026 09:08:35 +0000</pubDate>
      <link>https://dev.to/dexmac221/ai-should-be-blind-and-thats-a-good-thing-2ef0</link>
      <guid>https://dev.to/dexmac221/ai-should-be-blind-and-thats-a-good-thing-2ef0</guid>
      <description>&lt;p&gt;&lt;em&gt;Stop trying to give agents "eyes" to look at human interfaces. Give them terminals, deterministic APIs, and native protocols instead.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;We have officially entered the era of Agentic AI. The tech world is buzzing with demos of agents navigating the web, taking control of your mouse, and "seeing" your screen to fill out Excel spreadsheets or code in VS Code.&lt;/p&gt;

&lt;p&gt;There is an undeniable allure to the idea of an AI using a computer exactly like a human does. It feels intuitive. It fulfills the sci-fi promise of a humanoid companion sitting at a keyboard. It suggests a universal compatibility where we don't need to rewrite our software because the AI can just "look" at it.&lt;/p&gt;

&lt;p&gt;But as a researcher in Computer Vision and Robotics, I see a fundamental design flaw in this anthropomorphic approach. We are falling into a trap of &lt;strong&gt;mimetic design&lt;/strong&gt;—building digital tools that mimic human biological constraints rather than leveraging silicon strengths.&lt;/p&gt;

&lt;p&gt;The Graphical User Interface (GUI) is an expensive, lossy abstraction layer created to limit human cognitive load. We rely on buttons, icons, colors, and spatial layouts because our primate brains cannot memorize thousands of CLI flags or parse raw JSON streams in real-time. But forcing an AI—which excels at processing structured text, intricate logic, and massive data streams—to "look" at and "click" on an interface designed for human eyes is like forcing a supercomputer to count on its fingers.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The future is not in visual agents that click. It is in blind agents that execute.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The Distinction: Perception vs. Interaction
&lt;/h2&gt;

&lt;p&gt;To be clear: I am not arguing against Computer Vision. AI should be able to &lt;em&gt;see&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;If I sketch a website layout on a napkin, I want the AI to look at it and generate the HTML. That is &lt;strong&gt;Perception&lt;/strong&gt;—using vision to bridge the gap between human intent and digital structure.&lt;/p&gt;

&lt;p&gt;But once that website exists, the AI should not test it by visually scanning a browser window and trying to click buttons. It should use a testing framework like Playwright or Selenium. That is &lt;strong&gt;Interaction&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We must not confuse the two. Using vision for interaction is like driving a car by pointing a camera at the speedometer instead of reading the sensor data directly. It adds latency, noise, and fragility where none should exist.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Paradox of "High Frequencies" and The Latent Space
&lt;/h2&gt;

&lt;p&gt;Those of us working with Large Multimodal Models (VLMs) know a dirty secret: AI vision is fundamentally different from human vision.&lt;/p&gt;

&lt;p&gt;When a human looks at a screen, we perceive crisp edges and state changes instantly. An AI, however, "sees" by compressing an image into tokens and mapping them into a latent space. While a modern model can perfectly describe a sunset or a cat (low-frequency visual data), it often hallucinates on fine details (high-frequency data).&lt;/p&gt;

&lt;p&gt;This leads to what I call the &lt;strong&gt;High-Frequency Paradox&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;State Ambiguity:&lt;/strong&gt; It struggles to distinguish between a "disabled" gray button and an "active" gray button. The semantic difference is massive (one works, one doesn't), but the visual difference in the latent space is negligible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Text Degradation:&lt;/strong&gt; It misreads small text in complex IDE menus or confuses similar-looking icons (like "Debug" vs. "Run").&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hallucinated Interactivity:&lt;/strong&gt; It often hallucinates the state of a checkbox or assumes a static label is a clickable button because it appears in a position where buttons usually reside in its training data.&lt;/p&gt;

&lt;p&gt;The more precise the UI interaction needs to be, the less reliable the "visual" agent becomes. We are asking a probabilistic engine to interact with a deterministic interface via a lossy visual channel. It is a recipe for fragility.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Android Experiment: CLI vs. GUI
&lt;/h2&gt;

&lt;p&gt;To test this hypothesis, I conducted a series of rigorous experiments developing Android applications entirely through AI agents. The goal was to see which modality allowed the agent to actually ship working code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Attempt 1: The Visual Agent
&lt;/h3&gt;

&lt;p&gt;I asked the agent to use Android Studio visually. I fed it screenshots of the IDE and asked it to perform standard tasks like "click the build button," "open the AndroidManifest.xml," or "fix the red error line."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; A frustratingly high failure rate. The agent would frequently hallucinate menu positions that had moved in recent updates. When an error popup appeared, the agent would often misinterpret the screenshot, missing the subtle "details" button that contained the actual stack trace. It tried to click UI elements that were merely decorative, wasting cycles in a loop of visual trial and error.&lt;/p&gt;

&lt;h3&gt;
  
  
  Attempt 2: The Blind Agent
&lt;/h3&gt;

&lt;p&gt;I forced the AI to "close its eyes." I forbade it from using the GUI entirely. Instead, I gave it access to the Terminal and standard, deterministic tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;adb&lt;/code&gt; (Android Debug Bridge) for installation, log retrieval, and testing.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;gradlew&lt;/code&gt; (The Gradle Wrapper) for building and dependency management.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;logcat&lt;/code&gt; for real-time debugging.&lt;/li&gt;
&lt;li&gt;Standard file system access for code editing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; The success rate skyrocketed to nearly 100%.&lt;/p&gt;

&lt;p&gt;Why? Because text is deterministic and self-correcting.&lt;/p&gt;

&lt;p&gt;A CLI command like &lt;code&gt;./gradlew assembleDebug&lt;/code&gt; is absolute. It removes the ambiguity of "where is the button?". But more importantly, it solves the &lt;strong&gt;Versioning Problem&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If a GUI button moves or changes its icon in a new version of Android Studio, the visual agent fails. But if a CLI command is deprecated, the terminal returns a specific, text-based error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error: flag --old-flag is deprecated, use --new-flag instead.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The "blind" AI reads this error—which is in its native language (text)—understands the logic, updates its internal context, patches the command, and runs it again. It creates a perfect, closed feedback loop that visual agents simply cannot replicate. &lt;strong&gt;The error message becomes the instruction manual.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Addressing the Critics
&lt;/h2&gt;

&lt;p&gt;There are two common counter-arguments to this approach.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. "But Visual Agents are Universal!"
&lt;/h3&gt;

&lt;p&gt;It is true that visual agents can interact with any software, even legacy apps without APIs. But this is a &lt;strong&gt;universality of mediocrity&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We have seen this movie before. Robotic Process Automation (RPA) tools spent the last 20 years trying to automate workflows by simulating clicks on screens. The lesson from two decades of RPA is clear: visual automation is fragile, expensive to maintain, and breaks constantly. AI visual agents inherit all these problems—plus the added risk of probabilistic hallucination. They are effectively &lt;strong&gt;Technical Debt upon arrival&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. "But Vision Models are Improving!"
&lt;/h3&gt;

&lt;p&gt;"Wait for GPT-5," they say. "Vision accuracy will be 99.9%."&lt;/p&gt;

&lt;p&gt;This argument mistakes &lt;strong&gt;capability for architecture&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Even if an AI could read a screen with 100% pixel-perfect accuracy, using a massive visual transformer to read the text "Submit" on a button is an astonishing waste of compute compared to sending a POST request. It is like arguing that self-driving cars make trains obsolete. Trains are efficient because of the rails (constraints), not because of the driver. Similarly, text protocols provide the "rails" that make agents reliable and efficient.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Interface Hierarchy of Reliability
&lt;/h2&gt;

&lt;p&gt;When designing agentic workflows, we need to stop treating all interfaces as equal. As engineers, we should evaluate interfaces based on a hierarchy of reliability:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Native APIs/SDKs:&lt;/strong&gt; Maximum reliability, minimum overhead. The agent speaks directly to the machine logic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;CLI Tools:&lt;/strong&gt; Deterministic text I/O, excellent error reporting, self-correcting capabilities.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Structured Protocols:&lt;/strong&gt; (JSON-RPC, GraphQL, REST). Explicit intent, no visual parsing required.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Accessibility APIs:&lt;/strong&gt; (Apple's Accessibility Tree, Windows UI Automation). Uses the OS structure without needing pixel analysis.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;DOM/HTML Parsing:&lt;/strong&gt; For web apps (better than pixels, but prone to breakage).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Visual Interaction:&lt;/strong&gt; The Last Resort. High compute cost (10x processing for vision vs text), high fragility, high latency.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each step down this ladder represents a degradation in stability and an increase in &lt;strong&gt;"hallucination surface area."&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Inversion of Control
&lt;/h2&gt;

&lt;p&gt;The next leap in software engineering will be &lt;strong&gt;Inversion of Control&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Legacy:&lt;/strong&gt; We built GUIs to hide complex text tools and APIs from humans because they were too difficult to memorize.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Future:&lt;/strong&gt; We will build APIs and Headless modes to expose those tools back to AI because GUIs are too ambiguous to interpret.&lt;/p&gt;

&lt;p&gt;Imagine an IDE that has no window unless a human explicitly asks to "see" the code. The AI writes, compiles, tests, and deploys using only the compiler and the shell. It doesn't need syntax highlighting—it needs syntax correctness.&lt;/p&gt;

&lt;p&gt;The economics will eventually dictate this shift. Visual agents consume significantly more compute for significantly less reliability. Enterprises will not pay that premium indefinitely.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The impulse to build AI that uses computers "like humans do" is understandable. It makes for great demos. But it is a trap. We are creating agents with superhuman text processing capabilities, then handicapping them with a visual channel designed for completely different cognitive architectures.&lt;/p&gt;

&lt;p&gt;The best "interface" for an AI isn't a 4K monitor. It's a shell prompt, a robust API doc, and a deterministic environment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The first platforms to ship native, headless agent protocols will own the next decade of developer tooling.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's stop trying to give them eyes. Let's give them direct system access.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;What's your experience with visual vs programmatic agents? Share your experiments in the comments.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>development</category>
    </item>
    <item>
      <title>The RAG Illusion: Why PostgreSQL Beats Vector Search for Most AI Applications</title>
      <dc:creator>Dexmac</dc:creator>
      <pubDate>Thu, 01 Jan 2026 10:26:33 +0000</pubDate>
      <link>https://dev.to/dexmac221/the-rag-illusion-why-postgresql-beats-vector-search-for-most-ai-applications-2ab3</link>
      <guid>https://dev.to/dexmac221/the-rag-illusion-why-postgresql-beats-vector-search-for-most-ai-applications-2ab3</guid>
      <description>&lt;h2&gt;
  
  
  A Contrarian View on the Most Hyped Technology in AI Infrastructure
&lt;/h2&gt;




&lt;p&gt;&lt;em&gt;"The best solution to a problem is often realizing you don't have the problem."&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Uncomfortable Question
&lt;/h2&gt;

&lt;p&gt;Before you spin up another Pinecone instance, embed another million documents, and debug another "why didn't it retrieve the right chunk?" issue, ask yourself:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do my data actually need semantic search, or am I using RAG because everyone else is?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After building a multi-agent AI system for narrative generation, we discovered something counterintuitive: replacing our RAG pipeline with PostgreSQL didn't just simplify our architecture—it made the output &lt;em&gt;better&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;This article explains why, and when you should consider the same.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Brief History: Why RAG Exists
&lt;/h2&gt;

&lt;p&gt;RAG (Retrieval-Augmented Generation) was born from necessity. In 2022-2023, context windows were tiny:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GPT-3.5:     4,096 tokens  (~3,000 words)
GPT-4:       8,192 tokens  (~6,000 words)
Claude 1:    9,000 tokens  (~7,000 words)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your knowledge base was larger than ~5,000 words, you had a problem. You couldn't fit it in context. RAG was the elegant solution:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Chunk&lt;/strong&gt; your documents into small pieces&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Embed&lt;/strong&gt; each chunk into a vector&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Store&lt;/strong&gt; vectors in a specialized database&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retrieve&lt;/strong&gt; the top-k most "similar" chunks to the query&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inject&lt;/strong&gt; those chunks into the prompt&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generate&lt;/strong&gt; a response based on the retrieved context&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Brilliant. A necessity became a pattern, the pattern became a best practice, and the best practice became... an assumption.&lt;/p&gt;




&lt;h2&gt;
  
  
  The World Changed, The Assumption Didn't
&lt;/h2&gt;

&lt;p&gt;Fast forward to December 2025:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GPT-5.2:           400,000 tokens (~300,000 words)
Claude Opus 4.5:   200,000 tokens (~150,000 words)
Claude Sonnet 4.5: 1,000,000 tokens (beta, tier 4+)
Gemini 3 Pro:      1,000,000 tokens (~750,000 words)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's not a typo. &lt;strong&gt;One million tokens.&lt;/strong&gt; You can fit entire codebases, complete documentation sets, or full novels in a single context window.&lt;/p&gt;

&lt;p&gt;Yet we're still chunking, embedding, and retrieving as if it's 2022.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Hidden Costs of RAG
&lt;/h2&gt;

&lt;p&gt;RAG isn't free. It comes with costs that are rarely discussed in the "RAG is amazing!" tutorials.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Chunking Destroys Context
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ORIGINAL DOCUMENT:
"The patient presented with symptoms consistent with Type 2 diabetes, 
including elevated blood glucose levels (HbA1c: 8.2%). However, given 
the patient's age (12) and rapid onset, we conducted additional testing 
which revealed GAD65 antibodies, confirming Type 1 diabetes instead."

AFTER CHUNKING (500 token chunks):
Chunk 1: "The patient presented with symptoms consistent with Type 2 
          diabetes, including elevated blood glucose levels (HbA1c: 8.2%)."

Chunk 2: "However, given the patient's age (12) and rapid onset, we 
          conducted additional testing which revealed GAD65 antibodies, 
          confirming Type 1 diabetes instead."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Query: "What type of diabetes does the patient have?"&lt;/p&gt;

&lt;p&gt;If your retrieval returns only Chunk 1, your LLM confidently answers "Type 2 diabetes." &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wrong.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The correction was in Chunk 2, which may not have been "semantically similar" enough to the query to make the top-k cut.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Embedding Loses Nuance
&lt;/h3&gt;

&lt;p&gt;Embeddings compress meaning into ~1,500 floating point numbers. They're remarkably good at capturing &lt;em&gt;gist&lt;/em&gt;, but they lose:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Negation&lt;/strong&gt;: "This is good" and "This is not good" often have similar embeddings&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Specificity&lt;/strong&gt;: "Apple Inc." and "apple fruit" may cluster together&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Relationships&lt;/strong&gt;: "A loves B" vs "B loves A" look identical to embeddings&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recency&lt;/strong&gt;: A 2020 policy and a 2024 update might have similar embeddings&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Top-K is Arbitrary
&lt;/h3&gt;

&lt;p&gt;Why retrieve the top 5 chunks? Why not 3? Or 10? Or 50?&lt;/p&gt;

&lt;p&gt;The answer is usually: "because that's what the tutorial did."&lt;/p&gt;

&lt;p&gt;Top-k retrieval means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You might miss the 6th most relevant chunk (which was the one you needed)&lt;/li&gt;
&lt;li&gt;You definitely include the 5th chunk (even if it's barely relevant)&lt;/li&gt;
&lt;li&gt;There's no way to know if you got the right ones&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. "Lost in the Middle"
&lt;/h3&gt;

&lt;p&gt;Research shows that LLMs pay less attention to information in the middle of long contexts. If your most relevant chunk ends up sandwiched between less relevant ones, the model might ignore it.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. The Verification Problem
&lt;/h3&gt;

&lt;p&gt;Here's the question nobody wants to answer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If I still need to verify the LLM's response (because RAG retrieval might have missed something), what exactly did I gain?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For low-stakes applications, approximate answers are fine. For legal, medical, financial, or any domain requiring accuracy, you're back to manual verification anyway.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Alternative: Structured State Management
&lt;/h2&gt;

&lt;p&gt;What if, instead of treating your knowledge as "documents to search," you treated it as "state to manage"?&lt;/p&gt;

&lt;p&gt;This is the key insight: &lt;strong&gt;For most applications, you don't need semantic search. You need structured queries.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The PostgreSQL Approach
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Instead of: "Find chunks about customer complaints from Q3"&lt;/span&gt;
&lt;span class="c1"&gt;-- You write: &lt;/span&gt;

&lt;span class="k"&gt;SELECT&lt;/span&gt; 
    &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;complaint_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resolution&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;cu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;customer_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;product_name&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;complaints&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;
&lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt; &lt;span class="n"&gt;cu&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;
&lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;product_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;created_at&lt;/span&gt; &lt;span class="k"&gt;BETWEEN&lt;/span&gt; &lt;span class="s1"&gt;'2024-07-01'&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="s1"&gt;'2024-09-30'&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'resolved'&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;severity&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This query is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Deterministic&lt;/strong&gt;: Same query, same results&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Debuggable&lt;/strong&gt;: EXPLAIN shows exactly what happened&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complete&lt;/strong&gt;: You get ALL matching records, not "top-k similar"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Relational&lt;/strong&gt;: You can join customers, products, resolutions in one query&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fast&lt;/strong&gt;: Milliseconds, not seconds&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Full Context Injection
&lt;/h3&gt;

&lt;p&gt;Now here's the key: once you have your structured data, you don't "retrieve" it into a tiny context. You &lt;strong&gt;dump it entirely&lt;/strong&gt; into the prompt.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;build_context&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scene_requirements&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Build complete context for this scene.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
        SELECT json_build_object(
            &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;characters&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;, (
                SELECT json_agg(c.*) 
                FROM characters c 
                WHERE c.name = ANY(%s)
            ),
            &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;location&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;, (
                SELECT row_to_json(l.*) 
                FROM locations l 
                WHERE l.name = %s
            ),
            &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;recent_events&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;, (
                SELECT json_agg(e.*) 
                FROM events e 
                WHERE e.chapter &amp;gt;= %s - 1
            ),
            &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;relationships&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;, (
                SELECT json_agg(r.*) 
                FROM relationships r 
                WHERE r.character_a = ANY(%s) 
                  AND r.character_b = ANY(%s)
            )
        )
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;characters&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;current_chapter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;characters&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;characters&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;  &lt;span class="c1"&gt;# ~2,000-10,000 tokens, COMPLETE and COHERENT
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This isn't retrieval. It's &lt;strong&gt;state serialization&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Real-World Example: The Book Generator
&lt;/h2&gt;

&lt;p&gt;We built a system that generates novels using multiple AI agents (more on this in a follow-up article). The "world" of a typical story includes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;STORY WORLD COMPONENTS:
- 3-5 characters:      ~500 tokens each  = 2,500 tokens
- 5-10 locations:      ~200 tokens each  = 2,000 tokens  
- 20-30 events:        ~100 tokens each  = 3,000 tokens
- Rules and timeline:                    = 1,000 tokens
────────────────────────────────────────────────────────
TOTAL:                                   ~8,500 tokens
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our context window: &lt;strong&gt;200,000-1,000,000 tokens&lt;/strong&gt; (depending on model).&lt;/p&gt;

&lt;p&gt;We could fit the &lt;em&gt;entire world&lt;/em&gt; 20-100 times over. Why were we using RAG?&lt;/p&gt;

&lt;h3&gt;
  
  
  The RAG Version (What We Started With)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SharedRAG&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;top_k&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Embed the question
&lt;/span&gt;        &lt;span class="n"&gt;query_embedding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;embed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Search vector store
&lt;/span&gt;        &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;vector_store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;similarity_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;query_embedding&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
            &lt;span class="n"&gt;top_k&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;top_k&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Problems we encountered:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Tell me about the café" returned café description + random events that mentioned coffee&lt;/li&gt;
&lt;li&gt;Character relationships were split across chunks, often incomplete&lt;/li&gt;
&lt;li&gt;The same location description was retrieved repeatedly (no frequency control)&lt;/li&gt;
&lt;li&gt;Timeline was scrambled (similarity ≠ chronology)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The PostgreSQL Version (What We Switched To)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CoherentMemory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_scene_context&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chapter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                          &lt;span class="n"&gt;characters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Return ONLY what&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s needed for this specific scene.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;location&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_get_location_details&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;already_narrated&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;characters&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_get_characters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;characters&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;relationships&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_get_relationships_between&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;characters&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;known_events&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_get_what_characters_know&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;characters&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;recent_events&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_get_events_since&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chapter&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Results:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Location details are complete and not duplicated&lt;/li&gt;
&lt;li&gt;Only relationships between &lt;em&gt;present&lt;/em&gt; characters are included&lt;/li&gt;
&lt;li&gt;Events are filtered by what each character actually knows&lt;/li&gt;
&lt;li&gt;Natural frequency control through &lt;code&gt;already_narrated&lt;/code&gt; flags&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Schema
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- 16 tables for complete narrative state management&lt;/span&gt;

&lt;span class="c1"&gt;-- Characters and their attributes&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;characters&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;UNIQUE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;full_name&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;occupation&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;background&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;cognitive_style&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;created_at&lt;/span&gt; &lt;span class="nb"&gt;TIMESTAMP&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="n"&gt;NOW&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;character_traits&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;character_id&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="n"&gt;characters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;trait&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;character_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;trait&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;character_secrets&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;character_id&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="n"&gt;characters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;secret&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;known_by&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="s1"&gt;'{}'&lt;/span&gt;  &lt;span class="c1"&gt;-- Array of character IDs who know&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- Relationships (bidirectional)&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;character_relationships&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;character_a&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="n"&gt;characters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;character_b&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="n"&gt;characters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;relationship_type&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;character_a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;character_b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- Locations with usage tracking (frequency control!)&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;locations&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;UNIQUE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;atmosphere&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;usage_count&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;max_usage&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;location_details&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;location_id&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="n"&gt;locations&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;detail&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;narrated&lt;/span&gt; &lt;span class="nb"&gt;BOOLEAN&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="k"&gt;FALSE&lt;/span&gt;  &lt;span class="c1"&gt;-- Has this been used in the story?&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- Events with character knowledge tracking&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;chapter&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;scene&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;location_id&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="n"&gt;locations&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;resolved&lt;/span&gt; &lt;span class="nb"&gt;BOOLEAN&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="k"&gt;FALSE&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;event_participants&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;event_id&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;character_id&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="n"&gt;characters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="k"&gt;role&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;  &lt;span class="c1"&gt;-- 'witness', 'actor', 'mentioned'&lt;/span&gt;
    &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;character_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- Who knows what? Automatic knowledge tracking&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;character_knowledge&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;character_id&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="n"&gt;characters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;event_id&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;learned_in_chapter&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;character_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- Style tracking (integrated repetition control)&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;style_patterns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;pattern_type&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;pattern_text&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;chapter&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;usage_count&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;max_per_chapter&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Key Queries
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Get scene context (coherent segmentation):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Everything needed for Chapter 2, Scene 3, with Alice and Bob in the Library&lt;/span&gt;

&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;json_build_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'location'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;json_build_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'atmosphere'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;atmosphere&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'unused_details'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;json_agg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ld&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;detail&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;location_details&lt;/span&gt; &lt;span class="n"&gt;ld&lt;/span&gt;
                &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;ld&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;location_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;ld&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;narrated&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;FALSE&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;locations&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Library'&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="s1"&gt;'characters'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;json_agg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json_build_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'occupation'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;occupation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'traits'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;array_agg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;trait&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;character_traits&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;character_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="s1"&gt;'cognitive_style'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cognitive_style&lt;/span&gt;
        &lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;characters&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Alice'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Bob'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="s1"&gt;'relationship'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;json_build_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;relationship_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;character_relationships&lt;/span&gt; &lt;span class="n"&gt;cr&lt;/span&gt;
        &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;character_a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;cr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;character_b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
           &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;character_a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;cr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;character_b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="s1"&gt;'what_they_know'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;json_agg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;DISTINCT&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;
        &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;character_knowledge&lt;/span&gt; &lt;span class="n"&gt;ck&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ck&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event_id&lt;/span&gt;
        &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;ck&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;character_id&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;scene_context&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Check for overused patterns:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Before generating, check what patterns to avoid&lt;/span&gt;

&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;pattern_text&lt;/span&gt; 
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;style_patterns&lt;/span&gt; 
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;chapter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; 
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;usage_count&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;max_per_chapter&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Returns: ["shoulders slumped", "heart raced"]&lt;/span&gt;
&lt;span class="c1"&gt;-- These get injected as "AVOID:" instructions&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Update after scene generation:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Mark location details as narrated&lt;/span&gt;
&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;location_details&lt;/span&gt; 
&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;narrated&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;TRUE&lt;/span&gt; 
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;location_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;detail&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="s1"&gt;'%dusty shelves%'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Record that Alice now knows about the secret&lt;/span&gt;
&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;character_knowledge&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;character_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;learned_in_chapter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- Increment location usage&lt;/span&gt;
&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;locations&lt;/span&gt; 
&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;usage_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;usage_count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; 
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Library'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The Comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;RAG&lt;/th&gt;
&lt;th&gt;PostgreSQL&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Setup complexity&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;High (embeddings, vector DB)&lt;/td&gt;
&lt;td&gt;Medium (schema design)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Query type&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Semantic similarity&lt;/td&gt;
&lt;td&gt;Exact relational&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Results&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Top-k approximate&lt;/td&gt;
&lt;td&gt;Complete exact&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Debugging&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Hard ("why this chunk?")&lt;/td&gt;
&lt;td&gt;Easy (EXPLAIN)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Relationships&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manual in text&lt;/td&gt;
&lt;td&gt;Native JOINs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Frequency control&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Add-on&lt;/td&gt;
&lt;td&gt;Native (usage_count)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Timeline&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Lost in embeddings&lt;/td&gt;
&lt;td&gt;ORDER BY timestamp&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Knowledge tracking&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manual&lt;/td&gt;
&lt;td&gt;Automatic with FKs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Vector DB + embeddings&lt;/td&gt;
&lt;td&gt;Standard PostgreSQL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best for&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Unstructured exploration&lt;/td&gt;
&lt;td&gt;Structured applications&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  When RAG Still Makes Sense
&lt;/h2&gt;

&lt;p&gt;I'm not saying RAG is useless. It has legitimate use cases:&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Use RAG When:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Data is truly unstructured&lt;/strong&gt; — Chat logs, free-form notes, scraped web pages with no consistent format&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Volume exceeds context&lt;/strong&gt; — You have 10GB of documents and even the best chunking gives you 50MB of potentially relevant content&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Discovery is the goal&lt;/strong&gt; — "Find me something related to X" where you don't know what you're looking for&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Approximate is acceptable&lt;/strong&gt; — Recommendations, inspiration, brainstorming assistance&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Data changes constantly&lt;/strong&gt; — News feeds, social media, where re-indexing is expensive&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  ❌ Skip RAG When:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Data has natural structure&lt;/strong&gt; — Products, customers, transactions, policies, documentation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Total data fits in context&lt;/strong&gt; — Most knowledge bases under 100k tokens&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Precision matters&lt;/strong&gt; — Legal, medical, financial, compliance&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Relationships are important&lt;/strong&gt; — "Which customers bought X and also complained about Y?"&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;You need auditability&lt;/strong&gt; — "Why did the AI say this?" requires deterministic retrieval&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  The Hybrid Approach
&lt;/h2&gt;

&lt;p&gt;You don't have to choose. Many systems benefit from both:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HybridMemory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;postgres&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;PostgresMemory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;# Structured state
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RAGMemory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;            &lt;span class="c1"&gt;# Unstructured fallback
&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_context&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;scene_requirements&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# First: get structured context (deterministic)
&lt;/span&gt;        &lt;span class="n"&gt;structured&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;postgres&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_scene_context&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;scene_requirements&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Second: if there's room, add relevant unstructured content
&lt;/span&gt;        &lt;span class="n"&gt;remaining_tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MAX_CONTEXT&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nf"&gt;count_tokens&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;structured&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;remaining_tokens&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;unstructured&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;remaining_tokens&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;structured&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;unstructured&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;structured&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key insight: &lt;strong&gt;Structured first, RAG for gaps.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Implementation Checklist
&lt;/h2&gt;

&lt;p&gt;If you're considering PostgreSQL over RAG, here's a practical checklist:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Analyze Your Data
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Can it be structured into entities and relationships?&lt;/li&gt;
&lt;li&gt;[ ] Does it have natural categories, types, or hierarchies?&lt;/li&gt;
&lt;li&gt;[ ] Are there temporal aspects (timeline, versions, updates)?&lt;/li&gt;
&lt;li&gt;[ ] Do you need to track "who knows what"?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Estimate Token Budget
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Total structured data: _____ tokens&lt;/li&gt;
&lt;li&gt;[ ] Available context window: _____ tokens&lt;/li&gt;
&lt;li&gt;[ ] Ratio: If data &amp;lt; 50% of context, skip RAG&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Design Schema
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Core entities identified&lt;/li&gt;
&lt;li&gt;[ ] Relationships mapped&lt;/li&gt;
&lt;li&gt;[ ] Usage tracking added (for frequency control)&lt;/li&gt;
&lt;li&gt;[ ] Knowledge tracking added (for multi-agent scenarios)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Build Context Serializer
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Function to dump relevant state as JSON/text&lt;/li&gt;
&lt;li&gt;[ ] Filters for scene/query relevance&lt;/li&gt;
&lt;li&gt;[ ] Token counting to stay within limits&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. Test Determinism
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Same query → same results?&lt;/li&gt;
&lt;li&gt;[ ] Can you explain why each piece of context was included?&lt;/li&gt;
&lt;li&gt;[ ] Edge cases handled (empty results, too many results)?&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Conclusion: Think Before You Embed
&lt;/h2&gt;

&lt;p&gt;RAG was a brilliant solution to the context length problem of 2022. In 2025, with 200k+ token context windows, it's often a solution in search of a problem.&lt;/p&gt;

&lt;p&gt;Before building another RAG pipeline, ask:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Does my data fit in context?&lt;/strong&gt; If yes, just include it all.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Is my data structured?&lt;/strong&gt; If yes, use SQL queries, not semantic search.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Do I need precision or exploration?&lt;/strong&gt; Precision → PostgreSQL. Exploration → RAG.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Am I using RAG because it's right, or because it's trendy?&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The best architecture is the one that solves your actual problem with minimal complexity. Sometimes that's a sophisticated RAG pipeline with reranking and hybrid search. Sometimes it's a PostgreSQL database with good indexes and a JSON serializer.&lt;/p&gt;

&lt;p&gt;Know the difference.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;In the next article, I'll show how we applied this PostgreSQL-based approach to build a &lt;strong&gt;multi-agent book generation system&lt;/strong&gt; where AI characters have their own consciousness, memories, and voices. The coherent memory system described here is what allows characters to know things, remember events, and maintain consistent relationships across an entire novel.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Spoiler&lt;/strong&gt;: When we switched from RAG to PostgreSQL, our characters stopped repeating themselves and started having coherent conversations.&lt;/p&gt;

&lt;p&gt;Stay tuned.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you found this useful, the code is open source: [GitHub link]&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Appendix: Quick Reference
&lt;/h2&gt;

&lt;h3&gt;
  
  
  PostgreSQL Extensions for AI Workloads
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Full-text search (built-in)&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="n"&gt;idx_fts&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;documents&lt;/span&gt; 
&lt;span class="k"&gt;USING&lt;/span&gt; &lt;span class="n"&gt;GIN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;to_tsvector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'english'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="c1"&gt;-- Vector similarity (pgvector extension)&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="n"&gt;EXTENSION&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="n"&gt;idx_embedding&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;documents&lt;/span&gt; 
&lt;span class="k"&gt;USING&lt;/span&gt; &lt;span class="n"&gt;ivfflat&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;embedding&lt;/span&gt; &lt;span class="n"&gt;vector_cosine_ops&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- JSON querying (built-in)&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;data&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;entities&lt;/span&gt; 
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="k"&gt;data&lt;/span&gt; &lt;span class="o"&gt;@&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'{"type": "character"}'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  When to Use What
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────────┐
│                    DECISION FLOWCHART                       │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   Does your data have structure?                           │
│           │                                                 │
│     ┌─────┴─────┐                                          │
│    YES          NO                                         │
│     │            │                                          │
│     ▼            ▼                                          │
│  PostgreSQL   Can you add structure?                       │
│     ▲            │                                          │
│     │      ┌─────┴─────┐                                   │
│     │     YES          NO                                  │
│     │      │            │                                   │
│     └──────┘            ▼                                   │
│                    Does it fit in context?                 │
│                         │                                   │
│                   ┌─────┴─────┐                             │
│                  YES          NO                            │
│                   │            │                             │
│                   ▼            ▼                             │
│              Full dump      RAG                             │
│              (no search)   (with all its tradeoffs)        │
│                                                             │
└─────────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Cost Comparison (Rough Estimates)
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Solution&lt;/th&gt;
&lt;th&gt;Monthly Cost&lt;/th&gt;
&lt;th&gt;Setup Time&lt;/th&gt;
&lt;th&gt;Maintenance&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Pinecone + OpenAI Embeddings&lt;/td&gt;
&lt;td&gt;$70-500&lt;/td&gt;
&lt;td&gt;1-2 weeks&lt;/td&gt;
&lt;td&gt;Ongoing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Weaviate Cloud&lt;/td&gt;
&lt;td&gt;$50-300&lt;/td&gt;
&lt;td&gt;1-2 weeks&lt;/td&gt;
&lt;td&gt;Ongoing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PostgreSQL on RDS&lt;/td&gt;
&lt;td&gt;$20-100&lt;/td&gt;
&lt;td&gt;2-3 days&lt;/td&gt;
&lt;td&gt;Minimal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PostgreSQL + pgvector&lt;/td&gt;
&lt;td&gt;$20-100&lt;/td&gt;
&lt;td&gt;3-5 days&lt;/td&gt;
&lt;td&gt;Minimal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SQLite (local)&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;td&gt;1 day&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>ai</category>
      <category>rag</category>
      <category>postgres</category>
    </item>
    <item>
      <title>The Giant That Builds Smaller Giants: Custom AI Agents for Privacy and Efficiency</title>
      <dc:creator>Dexmac</dc:creator>
      <pubDate>Sat, 27 Dec 2025 08:24:56 +0000</pubDate>
      <link>https://dev.to/dexmac221/the-giant-that-builds-smaller-giants-custom-ai-agents-for-privacy-and-efficiency-1ed0</link>
      <guid>https://dev.to/dexmac221/the-giant-that-builds-smaller-giants-custom-ai-agents-for-privacy-and-efficiency-1ed0</guid>
      <description>&lt;p&gt;&lt;em&gt;The future of AI isn't bigger models. It's smaller, specialized agents — distilled, custom-built, and running where your data stays safe.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem with One-Size-Fits-All AI
&lt;/h2&gt;

&lt;p&gt;Every time you use a frontier AI model like ChatGPT or Claude, three things happen:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Your data leaves your control.&lt;/strong&gt; Your code, your ideas, your company's secrets travel to data centers you don't own.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;You're paying for capabilities you don't need.&lt;/strong&gt; These models know a little about everything — history, poetry, coding, cooking. But for your specific task, 90% of that knowledge is irrelevant overhead.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Massive resources are consumed.&lt;/strong&gt; Running 500+ billion parameter models requires enormous computational power. For repetitive, domain-specific tasks, this is wildly inefficient.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There's a better way — and it's where AI is heading.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Future: Custom, Distilled, Specialized Models
&lt;/h2&gt;

&lt;p&gt;Here's the thesis:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The future of industrial AI isn't giant generalist models. It's smaller, specialized agents — custom-built for specific domains, running on efficient hardware, and equipped with deterministic tools that guarantee correctness.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This isn't speculation. It's already happening. Companies are realizing that for &lt;em&gt;intensive, repetitive, well-defined tasks&lt;/em&gt;, a 30B parameter model with the right tools outperforms a 500B+ generalist that hallucinates.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Specialized Beats General
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Frontier models (500B+ parameters):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Know a little about everything&lt;/li&gt;
&lt;li&gt;Expensive to run&lt;/li&gt;
&lt;li&gt;Prone to hallucination on niche topics&lt;/li&gt;
&lt;li&gt;Data goes to third-party servers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Specialized agents (30B–120B parameters + tools):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deep expertise in one domain&lt;/li&gt;
&lt;li&gt;Significantly cheaper to run via Ollama Cloud or local GPU&lt;/li&gt;
&lt;li&gt;Deterministic tools prevent hallucination&lt;/li&gt;
&lt;li&gt;Can run on privacy-first infrastructure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key insight: &lt;strong&gt;you don't need a model that knows everything. You need a model that can orchestrate tools that know specific things perfectly.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Privacy-First Doesn't Mean Local-Only
&lt;/h2&gt;

&lt;p&gt;A common misconception: "If I care about privacy, I need my own GPU."&lt;/p&gt;

&lt;p&gt;Not anymore. There's a spectrum of options:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fully local&lt;/strong&gt; (Ollama on your hardware)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Zero data leaves your machine&lt;/li&gt;
&lt;li&gt;Requires a good GPU (RTX 3090/4090 for 30B+ models)&lt;/li&gt;
&lt;li&gt;You control everything&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Privacy-first cloud&lt;/strong&gt; (Ollama Cloud, open-source model hosting)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Models like Qwen3-Coder, DeepSeek-V3, or OpenAI's gpt-oss — specialized, open-source, and efficient&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data sent, processed, and deleted&lt;/strong&gt; — no training on your prompts, no logs retained&lt;/li&gt;
&lt;li&gt;No GPU required on your end&lt;/li&gt;
&lt;li&gt;Access to 30B-120B models with privacy guarantees&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This middle ground is crucial. The sweet spot models (30B–120B parameters) often require more VRAM than consumer GPUs offer. Privacy-first cloud hosting lets you run them without sacrificing data control — your prompts are processed and immediately discarded, not stored or used for training.&lt;/p&gt;

&lt;p&gt;Both options give you what closed-source APIs can't: &lt;strong&gt;confidence that your proprietary code isn't training someone else's model.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For enterprises in regulated industries — healthcare, finance, defense — this isn't a nice-to-have. It's a requirement.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Hardware Horizon
&lt;/h3&gt;

&lt;p&gt;The real revolution for local AI is still coming. Today's bottleneck isn't CPU power — it's &lt;strong&gt;memory bandwidth&lt;/strong&gt;, not just VRAM capacity.&lt;/p&gt;

&lt;p&gt;Here's why: for each token generated, the model must read through all its weights. A 20B model with MXFP4 quantization means ~10-12 GB of data &lt;em&gt;per token&lt;/em&gt;. The speed limit isn't "does it fit?" — it's "how fast can you read it?"&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;GPU&lt;/th&gt;
&lt;th&gt;VRAM&lt;/th&gt;
&lt;th&gt;Memory Bandwidth&lt;/th&gt;
&lt;th&gt;Practical Speed (gpt-oss:20b)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;RTX 4070&lt;/td&gt;
&lt;td&gt;12 GB&lt;/td&gt;
&lt;td&gt;~200 GB/s&lt;/td&gt;
&lt;td&gt;~23 tokens/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RTX 3090&lt;/td&gt;
&lt;td&gt;24 GB&lt;/td&gt;
&lt;td&gt;~936 GB/s&lt;/td&gt;
&lt;td&gt;~70-85 tokens/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;H100&lt;/td&gt;
&lt;td&gt;80 GB&lt;/td&gt;
&lt;td&gt;~3,350 GB/s&lt;/td&gt;
&lt;td&gt;~300+ tokens/s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This explains why datacenter GPUs cost so much — and why consumer hardware hits a wall even when the model fits in memory.&lt;/p&gt;

&lt;p&gt;But quantization techniques are advancing rapidly. &lt;strong&gt;Unsloth Dynamic 2.0&lt;/strong&gt; achieves remarkable compression while maintaining accuracy:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Full Size&lt;/th&gt;
&lt;th&gt;Quantized&lt;/th&gt;
&lt;th&gt;VRAM Needed&lt;/th&gt;
&lt;th&gt;Context&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Qwen3-Coder-30B-A3B&lt;/td&gt;
&lt;td&gt;~60GB&lt;/td&gt;
&lt;td&gt;18GB (Q4_K_XL)&lt;/td&gt;
&lt;td&gt;24GB GPU&lt;/td&gt;
&lt;td&gt;1M tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Qwen3-Coder-30B-A3B&lt;/td&gt;
&lt;td&gt;~60GB&lt;/td&gt;
&lt;td&gt;13GB (IQ3_XXS)&lt;/td&gt;
&lt;td&gt;16GB GPU&lt;/td&gt;
&lt;td&gt;8K tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A 30B parameter model running on a consumer GPU with 1 million token context — this was impossible two years ago.&lt;/p&gt;

&lt;p&gt;The future likely belongs to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mixture-of-Experts (MoE) architectures&lt;/strong&gt; — 30B total parameters but only 3B active per token&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Advanced quantization&lt;/strong&gt; — Unsloth Dynamic, GGML, AWQ pushing the limits&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unified memory architectures&lt;/strong&gt; where CPU and GPU share large RAM pools&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NPUs&lt;/strong&gt; (Neural Processing Units) integrated into consumer hardware&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There's a catch: RAM prices are climbing, likely driven by datacenter demand for exactly these technologies. The economics may shift before the hardware does.&lt;/p&gt;

&lt;p&gt;For now, privacy-first cloud bridges the gap — giving you access to efficient open-source models without waiting for affordable local hardware. But the gap is closing fast.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Architecture: Giant Creates Smaller Giant
&lt;/h2&gt;

&lt;p&gt;Here's the pattern that makes this work:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftpdu4wfoj60sspxutf7t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftpdu4wfoj60sspxutf7t.png" alt="The Giant model bluprints a smaller giants with tools to solve complex problems" width="640" height="714"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The frontier model is the architect — used occasionally, for design and refinement. The smaller model is the builder — used daily, for execution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The key innovation isn't the small model. It's the deterministic tools.&lt;/strong&gt; They transform an "okay" model into a reliable specialist.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Secret Sauce: Tools That Can't Be Wrong
&lt;/h2&gt;

&lt;p&gt;Smaller models hallucinate. Everyone knows this.&lt;/p&gt;

&lt;p&gt;But here's a nuance most people miss: &lt;strong&gt;modern mid-size models often know the right answer — they just can't be trusted to give it consistently.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When I tested a 30B model on the amortization formula, it gave a correct mathematical answer. When I tested it again, it gave a slightly different (but still correct) variant. When I tested it in a complex multi-step task, it occasionally mixed up variable names or forgot syntax rules.&lt;/p&gt;

&lt;p&gt;The problem isn't knowledge. It's &lt;strong&gt;reliability&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is where deterministic tools change the equation:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Without Tools&lt;/th&gt;
&lt;th&gt;With Tools&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Model might know the formula&lt;/td&gt;
&lt;td&gt;Tool &lt;strong&gt;always&lt;/strong&gt; returns the exact formula&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Model might remember syntax&lt;/td&gt;
&lt;td&gt;Tool &lt;strong&gt;always&lt;/strong&gt; validates syntax&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Output varies between runs&lt;/td&gt;
&lt;td&gt;Output is &lt;strong&gt;guaranteed consistent&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Errors discovered at runtime&lt;/td&gt;
&lt;td&gt;Errors caught &lt;strong&gt;before execution&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The model's job becomes orchestration:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Understand what the user wants&lt;/li&gt;
&lt;li&gt;Choose which tool to call&lt;/li&gt;
&lt;li&gt;Apply the result correctly&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The &lt;em&gt;consistency&lt;/em&gt; comes from the tools. The &lt;em&gt;intelligence&lt;/em&gt; comes from the model. Together, they achieve &lt;strong&gt;predictable reliability&lt;/strong&gt; — which matters more than occasional brilliance in production systems.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Iterative Loop: Learning From Failures
&lt;/h2&gt;

&lt;p&gt;Here's what nobody tells you about specialized agents: &lt;strong&gt;you build them by watching models fail.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When I first tested the COBOL financial agent, I tried different model sizes. The pattern was clear:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;8B models (too small)&lt;/strong&gt;: Got confused by multi-step tasks, forgot to use tools&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;30B+ models (sweet spot)&lt;/strong&gt;: Understood the task, used tools correctly, succeeded&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even the successful models had predictable failure patterns. For example, a 30B model correctly applied the amortization formula but forgot to add the 7 required spaces at the start of COBOL lines (column rules from 1959!).&lt;/p&gt;

&lt;p&gt;The formula was right. The syntax was wrong. The program didn't compile.&lt;/p&gt;

&lt;p&gt;This is a &lt;strong&gt;predictable failure pattern.&lt;/strong&gt; Models consistently forget obscure syntax rules they weren't trained on. Once you identify the pattern, you can compensate — deterministically.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deterministic Compensation
&lt;/h3&gt;

&lt;p&gt;Instead of hoping the model remembers COBOL column rules, I added:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Post-processing in &lt;code&gt;write_file&lt;/code&gt;&lt;/strong&gt;: Every time the model writes COBOL code, the agent automatically scans for common formatting errors and fixes them before saving.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;RAG documentation tools&lt;/strong&gt;: The model can call &lt;code&gt;get_cobol_syntax_docs("columns")&lt;/code&gt; to retrieve verified syntax examples — it doesn't need to remember, just to look up.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Auto-fix on compile errors&lt;/strong&gt;: If compilation fails with column-related errors, a deterministic fixer attempts repairs.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Result: the same model that failed now succeeds, because its predictable weaknesses are patched by deterministic code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is the real workflow:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Give task to model with tools&lt;/li&gt;
&lt;li&gt;Watch where it fails&lt;/li&gt;
&lt;li&gt;Add deterministic compensation for that failure pattern&lt;/li&gt;
&lt;li&gt;Repeat until reliable&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You're not training the model. You're building guardrails around its known failure modes. The model stays the same; the tools get smarter.&lt;/p&gt;




&lt;h2&gt;
  
  
  Proof of Concept #1: COBOL Financial Calculations
&lt;/h2&gt;

&lt;p&gt;Theory is nice. Does it actually work?&lt;/p&gt;

&lt;p&gt;For the first stress test, I chose a domain that matters: &lt;strong&gt;legacy COBOL code maintenance for financial systems.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Why COBOL? Because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It's used in &lt;strong&gt;95% of ATM transactions&lt;/strong&gt; and &lt;strong&gt;80% of in-person bank transactions&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Financial formulas are unforgiving — a wrong amortization calculation means wrong money&lt;/li&gt;
&lt;li&gt;It proves the approach works in &lt;strong&gt;real-world enterprise scenarios&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This isn't a toy example. Banks run on COBOL. Getting it wrong costs real money.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Test Case
&lt;/h3&gt;

&lt;p&gt;A buggy loan payment calculator that uses simple interest instead of the correct amortization formula:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Expected payment: $632/month
Buggy output:     $819/month (simple interest, WRONG)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The task: fix the bug. I tested multiple models across different sizes to find the sweet spot.&lt;/p&gt;

&lt;h3&gt;
  
  
  Model Comparison: Finding the Right Size
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Parameters&lt;/th&gt;
&lt;th&gt;Used &lt;code&gt;get_formula&lt;/code&gt;
&lt;/th&gt;
&lt;th&gt;Compiles&lt;/th&gt;
&lt;th&gt;Output&lt;/th&gt;
&lt;th&gt;Iterations&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Nemotron 3 Nano&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;30B (MoE 3B active)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;$632.01&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;8&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DeepSeek V3.1&lt;/td&gt;
&lt;td&gt;671B&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;$632.01&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kimi K2&lt;/td&gt;
&lt;td&gt;1T&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;$632.01&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DeepSeek V3.2&lt;/td&gt;
&lt;td&gt;671B&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;$632.01&lt;/td&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Qwen3-Coder&lt;/td&gt;
&lt;td&gt;480B&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;$632.01&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Qwen3 8B (local)&lt;/td&gt;
&lt;td&gt;8B&lt;/td&gt;
&lt;td&gt;❌ confused&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;25&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Key observations:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;All models that used &lt;code&gt;get_formula&lt;/code&gt; succeeded.&lt;/strong&gt; The deterministic tool guarantees the correct formula every time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nemotron 3 Nano is the sweet spot&lt;/strong&gt;: a 30B MoE model with only 3B parameters active per token, completing the task in just 8 iterations — faster than 671B models while being far more efficient.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The 8B model failed&lt;/strong&gt; — not because it doesn't know the formula (it does!), but because it got confused by the multi-step task and forgot to use the tools. This confirms 30B+ is the minimum for reliable agent work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frontier models (500B+) work, but are overkill&lt;/strong&gt; — they cost more and aren't faster than well-tuned 30B models for this task.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Real Value of Tools (When Models Already Know)
&lt;/h3&gt;

&lt;p&gt;The COBOL agent has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;get_formula("amortization_payment")&lt;/code&gt;&lt;/strong&gt;: Not because the model doesn't know it, but because the tool returns the &lt;strong&gt;exact same template every time&lt;/strong&gt; with &lt;strong&gt;tested COBOL syntax&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;compile_cobol&lt;/code&gt;&lt;/strong&gt;: GnuCOBOL compiler catches syntax errors the model might introduce&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auto-fix post-processing&lt;/strong&gt;: Automatically adds missing column spacing when writing files&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The lesson: &lt;strong&gt;tools provide consistency, not knowledge.&lt;/strong&gt; For domains like COBOL where models already have the knowledge, deterministic tools ensure they apply it reliably.&lt;/p&gt;

&lt;p&gt;A 30B model with tools produces the same correct output &lt;strong&gt;every time&lt;/strong&gt;: &lt;strong&gt;$632.01/month&lt;/strong&gt; ✓&lt;/p&gt;

&lt;p&gt;Frontier models without tools produce correct output &lt;strong&gt;most of the time&lt;/strong&gt; — but "most" isn't good enough for bank transactions.&lt;/p&gt;




&lt;h2&gt;
  
  
  Proof of Concept #2: The Extreme Case — Commodore 64
&lt;/h2&gt;

&lt;p&gt;The COBOL test proved tools help with consistency. But what about domains where models genuinely don't know anything?&lt;/p&gt;

&lt;p&gt;To prove this approach works even in the worst case, I chose a deliberately extreme challenge: &lt;strong&gt;building an AI agent that develops games for the Commodore 64&lt;/strong&gt; — a computer from 1982.&lt;/p&gt;

&lt;p&gt;Why the C64? It's not because I'm nostalgic (okay, maybe a little). It's because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Modern AI models have almost zero training data on C64 programming.&lt;/strong&gt; If the approach works here, it works anywhere.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It's technically unforgiving.&lt;/strong&gt; Strict C89 syntax, custom hardware chips, specific memory addresses. One mistake crashes everything.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It's a safe demonstration domain.&lt;/strong&gt; Complex enough to prove the concept, without revealing proprietary industrial applications.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The same architecture applies to domains I can't discuss publicly.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Happens Without Specialization
&lt;/h3&gt;

&lt;p&gt;Ask a frontier model to write C64 code. It will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hallucinate memory addresses (VIC-II isn't at &lt;code&gt;0x1234&lt;/code&gt;, it's at &lt;code&gt;$D000&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Use modern C syntax that won't compile on cc65&lt;/li&gt;
&lt;li&gt;Forget that you need to enable clocks, set registers, handle interrupts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The code looks plausible. It doesn't work.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Happens With a Specialized Agent
&lt;/h3&gt;

&lt;p&gt;The C64 agent combines &lt;strong&gt;deterministic tools&lt;/strong&gt; with &lt;strong&gt;RAG (Retrieval-Augmented Generation)&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deterministic Tools:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A compiler&lt;/strong&gt; (cc65) that gives exact error messages&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;An emulator&lt;/strong&gt; (VICE) that runs the program and captures screenshots&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A vision model&lt;/strong&gt; that verifies the game actually works&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;RAG Knowledge Base:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hardware registers&lt;/strong&gt; — VIC-II at &lt;code&gt;$D000&lt;/code&gt;, SID at &lt;code&gt;$D400&lt;/code&gt;, CIA at &lt;code&gt;$DC00&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory maps&lt;/strong&gt; — screen RAM, color RAM, sprite pointers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;cc65 syntax&lt;/strong&gt; — C89 dialect with platform-specific extensions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a case where &lt;strong&gt;RAG is essential, not optional.&lt;/strong&gt; Unlike COBOL, modern AI models have almost no training data on C64 internals. Ask GPT-4 where the border color register is — it will guess wrong. The RAG knowledge base provides verified facts the model simply doesn't have.&lt;/p&gt;

&lt;p&gt;The model doesn't need to memorize that the VIC-II border color register is at &lt;code&gt;$D020&lt;/code&gt;. The RAG tool knows. The model just needs to understand "make the border black → query the hardware knowledge base."&lt;/p&gt;

&lt;h3&gt;
  
  
  The Result
&lt;/h3&gt;

&lt;p&gt;The agent creates playable C64 games — Pong, Breakout, demos. Running on emulated authentic hardware, compiled with period-correct tools, generated by a 30B model via Ollama Cloud.&lt;/p&gt;

&lt;p&gt;No data leaked. A domain where generalist models fail completely, solved by a specialized agent with the right tools.&lt;/p&gt;




&lt;h2&gt;
  
  
  Tools vs RAG: Know When You Need Each
&lt;/h2&gt;

&lt;p&gt;The COBOL and C64 agents illustrate two different scenarios:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;th&gt;What Models Know&lt;/th&gt;
&lt;th&gt;What's Needed&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Model knows, but inconsistently&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;COBOL, SQL, Python&lt;/td&gt;
&lt;td&gt;Formula ✅, Syntax ✅&lt;/td&gt;
&lt;td&gt;Deterministic tools for &lt;strong&gt;consistency&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Model doesn't know&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;C64, niche hardware, proprietary systems&lt;/td&gt;
&lt;td&gt;Nothing reliable&lt;/td&gt;
&lt;td&gt;RAG for &lt;strong&gt;knowledge&lt;/strong&gt; + tools for verification&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;For COBOL:&lt;/strong&gt; Models in the 30B-120B range know amortization formulas and COBOL syntax. The &lt;code&gt;get_formula&lt;/code&gt; tool doesn't teach them — it ensures they use the &lt;strong&gt;exact same template every time&lt;/strong&gt;. The &lt;code&gt;compile_cobol&lt;/code&gt; tool catches the occasional syntax slip.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For C64:&lt;/strong&gt; Models genuinely don't know that &lt;code&gt;POKE 53280,0&lt;/code&gt; sets the border to black, or that sprite pointers live at &lt;code&gt;$07F8&lt;/code&gt;. The RAG knowledge base provides this information. Without it, the model hallucinates plausible-looking but wrong addresses.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The practical rule:&lt;/strong&gt; If your domain appears in modern training data (COBOL, Java, financial math), focus on deterministic tools for consistency. If your domain is obscure or proprietary (legacy hardware, internal APIs, custom protocols), you need RAG to inject missing knowledge.&lt;/p&gt;




&lt;h2&gt;
  
  
  When to Use Deterministic Tools (And When Not To)
&lt;/h2&gt;

&lt;p&gt;Not every task needs deterministic guardrails. Here's a framework:&lt;/p&gt;

&lt;h3&gt;
  
  
  Use Deterministic Tools When:
&lt;/h3&gt;

&lt;p&gt;✅ &lt;strong&gt;Correctness is non-negotiable&lt;/strong&gt; — financial calculations, safety-critical systems, legal documents&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;The domain has verifiable ground truth&lt;/strong&gt; — formulas, specifications, standards that can be encoded&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Consistency across runs matters&lt;/strong&gt; — production systems where "usually correct" isn't acceptable&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Errors are expensive&lt;/strong&gt; — wrong loan payments, invalid code, compliance violations&lt;/p&gt;

&lt;h3&gt;
  
  
  Skip Deterministic Tools When:
&lt;/h3&gt;

&lt;p&gt;❌ &lt;strong&gt;Creativity is the goal&lt;/strong&gt; — brainstorming, drafting, exploring possibilities&lt;/p&gt;

&lt;p&gt;❌ &lt;strong&gt;Approximate is good enough&lt;/strong&gt; — summaries, explanations, documentation&lt;/p&gt;

&lt;p&gt;❌ &lt;strong&gt;The domain is fuzzy&lt;/strong&gt; — no clear right/wrong answers, subjective quality&lt;/p&gt;

&lt;p&gt;❌ &lt;strong&gt;Speed matters more than perfection&lt;/strong&gt; — quick prototypes, exploratory coding&lt;/p&gt;

&lt;p&gt;The COBOL example shows the sweet spot: a domain where &lt;strong&gt;the model has knowledge but needs guardrails for reliability.&lt;/strong&gt; The tools don't replace the model's intelligence — they channel it into consistent, verifiable outputs.&lt;/p&gt;




&lt;h2&gt;
  
  
  Who Should Care About This?
&lt;/h2&gt;

&lt;p&gt;This approach isn't for everyone. But if any of these apply to you, it's worth exploring:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✅ Good fit:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Intensive, repetitive tasks in a well-defined domain&lt;/li&gt;
&lt;li&gt;Privacy requirements that rule out sending data to third parties&lt;/li&gt;
&lt;li&gt;Industrial applications where consistency matters more than creativity&lt;/li&gt;
&lt;li&gt;Teams willing to invest upfront in building custom agents&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;❌ Not the right fit:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You need broad, cross-domain reasoning&lt;/li&gt;
&lt;li&gt;Tasks are unpredictable and can't be anticipated&lt;/li&gt;
&lt;li&gt;You need cutting-edge capabilities only frontier models have&lt;/li&gt;
&lt;li&gt;No resources to build and maintain specialized agents&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The hybrid reality:&lt;/strong&gt; Most teams will use both — specialized agents (30B-120B) for routine work where privacy and efficiency matter, frontier models (500B+) for complex one-off problems. The goal isn't to eliminate large models. It's to stop using them &lt;em&gt;by default&lt;/em&gt; when a specialized agent would do better.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Commodore 64 Philosophy
&lt;/h2&gt;

&lt;p&gt;The C64 had 64 kilobytes of memory. Developers learned to do incredible things within tight constraints. They optimized. They specialized. They made every byte count.&lt;/p&gt;

&lt;p&gt;Forty years later, we're building AI systems with trillions of parameters — and often using 1% of that capability for any given task.&lt;/p&gt;

&lt;p&gt;Perhaps it's time to apply the same philosophy to AI.&lt;/p&gt;

&lt;p&gt;We don't always need bigger models. Sometimes we need &lt;em&gt;smarter architecture&lt;/em&gt;: frontier models that design specialized agents, equipped with deterministic tools that never make mistakes.&lt;/p&gt;

&lt;p&gt;The giant builds a smaller giant. And the smaller giant does the work.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article describes CLI Code Agent, a framework for building specialized AI agents that run locally or on privacy-first cloud via Ollama. The COBOL financial agent and C64 game development agent are examples — stress tests proving the approach works in domains where reliability matters and training data is scarce. The project is experimental and evolving, but the results are promising.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>programming</category>
      <category>development</category>
    </item>
    <item>
      <title>Building a Modern C64 Assembly AI Toolchain using Google Gemini 3</title>
      <dc:creator>Dexmac</dc:creator>
      <pubDate>Sat, 06 Dec 2025 08:50:29 +0000</pubDate>
      <link>https://dev.to/dexmac221/building-a-modern-c64-assembly-ai-toolchain-using-google-gemini-3-47o8</link>
      <guid>https://dev.to/dexmac221/building-a-modern-c64-assembly-ai-toolchain-using-google-gemini-3-47o8</guid>
      <description>&lt;p&gt;&lt;em&gt;I tested Gemini 3 against my own “Commodore 64 Constraint.”, after it conquered my Tetris challenge in BASIC, we pushed harder: Snake in 6510 Assembly with a Python-powered AI toolchain using Gemini on Github Copilot.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyqbepqhra0yf3eo2u4vr.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyqbepqhra0yf3eo2u4vr.gif" alt=" " width="640" height="482"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;It all starts at the base, one of the first AI-generated assembler games for the Commodore 64?&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;In the current AI landscape, it is easy to be impressed by the sheer volume of working code models produce. We see them generating Python scripts, React components, and complex SQL queries with apparent ease. However, these successes often occur within modern, forgiving development environments that mask fundamental inefficiencies. They offer abundant memory, standard libraries that abstract away complex logic, and garbage collection that forgives sloppy resource management.&lt;/p&gt;

&lt;p&gt;Real problem-solving, however, often shows up best when resources are scarce and the safety nets are removed. For the past few months, I have been working on a personal benchmark I call &lt;strong&gt;The Commodore 64 Constraint&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The question is straightforward but brutal: &lt;em&gt;Can an AI generate a functional game for a 1982 home computer with only 64KB of RAM, a 1MHz processor, and no native sprite handling in the language itself?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Recently, &lt;strong&gt;Gemini 3&lt;/strong&gt; became the first model to successfully pass my &lt;strong&gt;“Tetris Test”&lt;/strong&gt;  — a creativity constraint challenge I designed to filter out models that rely on rote memorization. This was a significant milestone; previous models (like Claude 4.0 and GPT-4) frequently stumbled into what I call “stochastic archaeology” — producing code that was a broken pastiche of forum snippets, often hallucinating commands that never existed.&lt;/p&gt;

&lt;p&gt;But BASIC, while constrained, is still high-level. It is slow and interpreted. To truly test the limits of AI engineering capabilities, I decided to take a steep step up. I moved from high-level logic to the bare metal: &lt;strong&gt;Snake in 6510 Assembly&lt;/strong&gt; , wrapped in a modern, custom-built Python AI toolchain.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Benchmark: Why Gemini 3 Changed the Game
&lt;/h3&gt;

&lt;p&gt;Before diving into the Assembly project, it is crucial to understand the significance of the shift I observed. When I tested models on my C64 Tetris challenge (in BASIC), the failures were usually categorized into two distinct types:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Stochastic Archaeology:&lt;/strong&gt; The model found a similar script in its training data (perhaps an Apple II or VIC-20 game) and tried to force-fit it to the C64. This often resulted in obscure variable names like A1 or Z9 and logic that simply didn't compile.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hallucination:&lt;/strong&gt; The model attempted to use “logical” commands that simply don’t exist on the platform, assuming the hardware was more capable than it actually is.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Gemini 3&lt;/strong&gt; demonstrated a different mode of operation. It didn’t just recall code; it appeared to reason through the problem from first principles. The evidence was in the implementation details:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Algorithmic Choice:&lt;/strong&gt; Instead of using lookup tables (the historical standard for 8-bit rotation to save cycles), it derived the mathematical rotation matrix (x' = -y) directly. It prioritized logical correctness over historical optimization patterns.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modern Architecture:&lt;/strong&gt; It used descriptive variable names (px for player x, py for player y) and structured GOSUB routines, treating the ancient BASIC interpreter like a modern structured language rather than writing spaghetti code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Constraint Awareness:&lt;/strong&gt; It pre-calculated memory offsets for screen and color RAM to save CPU cycles during the render loop, showing an understanding of the 1MHz bottleneck.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If my Tetris challenge in BASIC was the test of &lt;strong&gt;logical reasoning&lt;/strong&gt; , Snake in Assembly is the ultimate test of &lt;strong&gt;systems engineering&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Architecture
&lt;/h3&gt;

&lt;p&gt;To make this leap, Gemini 3 didn’t want to develop like it was 1982, it wanted to bring modern engineering toolkit into the 8-bit world. It built a &lt;strong&gt;Python-based AI toolchain&lt;/strong&gt; that treats the emulated Commodore 64 not as a black box, but as an embedded device it could probe and control programmatically.&lt;/p&gt;

&lt;p&gt;The stack consists of four key components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Target:&lt;/strong&gt; Commodore 64 (MOS 6510 CPU). A deterministic environment where every cycle counts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compiler:&lt;/strong&gt; &lt;a href="https://cc65.github.io/" rel="noopener noreferrer"&gt;cc65&lt;/a&gt; (specifically ca65 and ld65). Unlike simple monolithic assemblers, this allows for a modular project structure with linker configurations, essential for complex memory management.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Emulator:&lt;/strong&gt; &lt;a href="https://vice-emu.sourceforge.io/" rel="noopener noreferrer"&gt;VICE&lt;/a&gt; (x64). Crucially, we utilize the &lt;strong&gt;binary monitor interface&lt;/strong&gt; , which opens a TCP port allowing external tools to freeze execution and inspect RAM.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Brain:&lt;/strong&gt; Python 3. Used to script the build process, test the game logic, and run the AI agent that plays the game.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Part 1: The Metal (6510 Assembly)
&lt;/h3&gt;

&lt;p&gt;Writing Snake in Assembly forces to think about memory layout immediately. Unlike modern development where malloc handles the allocation details invisibly, here every byte must be manually accounted for.&lt;/p&gt;

&lt;p&gt;Gemini 3 mapped the memory to optimize for the 6510’s strengths:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;**$0400 (Screen RAM):** The visual grid. The C64 screen is a matrix of 40x25 characters. Writing the byte 81 (a solid ball) to address $0400\ puts the snake's head in the top-left corner.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;$0002 — $00FF (Zero Page):&lt;/strong&gt; The “fast lane” of memory. The 6510 processor has special instructions for accessing the first 256 bytes of RAM that are faster (3 cycles vs 4) and smaller (2 bytes vs 3). The model stored the critical state — Head X/Y, direction, and pointers — here to maximize game loop performance.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Modern Engineering in 6510 Assembly
&lt;/h3&gt;

&lt;p&gt;This is where the “Stochastic Memory” theory falls apart. If the model were simply regurgitating artifacts from its training dataset — copy-pasting from old magazines or forums — the output would look like 1980s code.&lt;/p&gt;

&lt;p&gt;Code from that era was notoriously “write-only.” To save every precious byte of RAM and squeeze performance out of a 1MHz CPU, developers often used spaghetti logic (endless JMP and GOTO), single-letter labels (L1, VAL), and "magic numbers" hardcoded throughout the file.&lt;/p&gt;

&lt;p&gt;The Assembly generated here is fundamentally different. It is &lt;strong&gt;2025 code written for 1982 hardware&lt;/strong&gt; :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Clean Separation of Concerns:&lt;/strong&gt; The architecture separates the Input, Update, and Render phases of the game loop. This is a standard pattern in modern game engines (like Unity or Unreal) but was rarely formalized in simple 8-bit games.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Input Buffering (Debouncing):&lt;/strong&gt; The code introduces an intermediate input_buf variable. It captures the user's joystick command but only commits it to the physics engine (dir) at the start of the next frame. This prevents the classic "suicide turn" bug—where a player inputs two direction changes within a single frame (e.g., Down then Left), causing the snake to 180-degree turn into its own neck. This is a robust engineering solution to a race condition.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Semantic Naming:&lt;/strong&gt; Instead of cryptic labels like chk_c, the code uses descriptive identifiers like check_collision, move_timer, and head_idx. It prioritizes maintainability and readability over obfuscation, treating Assembly with the same respect as a high-level language.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This proves the model isn’t just retrieving a “Snake” script from its weights; it is &lt;strong&gt;engineering&lt;/strong&gt; a solution from scratch, applying modern best practices to the constraints of the 6510 instruction set.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Challenge: 8-Bit Arithmetic
&lt;/h3&gt;

&lt;p&gt;In Python, calculating a pixel position is a trivial one-liner: index = y * width + x. On a 6510, we don't have a multiplication instruction. We only have addition (ADC) and bit-shifting (ASL/LSR).&lt;/p&gt;

&lt;p&gt;To calculate the memory address of the snake’s head, The model implemented a routine that performs Y * 40 + X using purely logical shifts. This is the kind of low-level optimization that keeps the game running smoothly at 60Hz, a massive performance step up from the sluggish BASIC interpreter used in the Tetris test.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;; Calculating Screen Address: Base + Y*40 + X
; 40 = 32 + 8. So we calculate (Y*32) + (Y*8)

calc_screen_pos:
    lda #0
    sta ptr_hi
    lda head_y
    asl ; Y * 2 (Shift left 1 bit)
    asl ; Y * 4
    asl ; Y * 8
    sta ptr_lo ; Save the (Y*8) result for later
    asl ; Y * 16
    asl ; Y * 32
    adc ptr_lo ; Add (Y*8) to (Y*32) -&amp;gt; Result is Y*40

    ; Add Base Address ($0400) and X offset
    ; ... (Handle carry bit propagation to high byte)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Part 2: The Bridge (Python &amp;lt;-&amp;gt; VICE)
&lt;/h3&gt;

&lt;p&gt;This is where the project gets interesting. VICE has a feature called -remotemonitor. When enabled, it opens a socket on localhost:6510. This transforms the emulator from a standalone application into a server we can query.&lt;/p&gt;

&lt;p&gt;Gemini 3 wrote a Python script, ai_toolchain.py, that acts as a wrapper around the emulator. It uses a binary protocol to send commands and receive raw memory dumps.&lt;/p&gt;

&lt;p&gt;The “Bridge” performs four key actions in a tight loop:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Halt:&lt;/strong&gt; Pauses the emulator CPU. This is critical — it allows us to inspect the state of the machine atomically, ensuring that the screen memory doesn’t change while we are reading it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dump Memory:&lt;/strong&gt; Sends the command m 0400 07e7 to read the entire 1000-character screen buffer in one go.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inject Input:&lt;/strong&gt; Instead of simulating a keypress (which introduces latency and debouncing issues), we write directly to the Zero Page variable $04 (Direction). This gives us zero-latency control.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resume:&lt;/strong&gt; Unpauses the emulator for a set number of frames, allowing the game physics to advance exactly one step.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Part 3: The AI Loop
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjz9pkmgrkr3jl2dymxcj.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjz9pkmgrkr3jl2dymxcj.webp" alt=" " width="384" height="566"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the screen data available in Python, Gemini 3 Agent could write an demo to play the game without user interaction.&lt;/p&gt;

&lt;p&gt;The AI uses a heuristic approach driven by the &lt;strong&gt;Manhattan Distance&lt;/strong&gt; , prioritizing survival over path optimization:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Perception:&lt;/strong&gt; The script halts VICE and parses the memory dump. It identifies the coordinates of the Head (Char 81), the Apple (Char 83), and all Obstacles (Char 160 walls or the snake’s own tail).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pathfinding:&lt;/strong&gt; It calculates the distance to the apple for all 4 possible neighbor cells.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Safety Check:&lt;/strong&gt; It simulates the next move to ensure it doesn’t result in a collision. This prevents the “suicide” moves common in simple greedy algorithms.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Action:&lt;/strong&gt; It writes the optimal new direction to the C64 memory and advances the frame.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here is what the AI “sees” in the terminal — a direct translation of the C64 screen memory into a Python-friendly grid, complete with obstacles (T for Trees/Spades), the Snake (O), and the Apple (A):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;|###################04###################|
|#                                      #|
|#                          T           #|
|#                                      #|
|#                        OOOOO         #|
|#                  T          O        #|
|#              T              O        #|
|# T                    T      O        #|
|#                                      #|
|#                            A         #|
|#                                      #|
|#                                      #|
|#                                      #|
|#T T                                   #|
|#                                      #|
|#                                      #|
|#              T                       #|
|#                                      #|
|#                                      #|
|#   T                                  #|
|#                                      #|
|#                                    T #|
|#                                      #|
|#                                      #|
|#                                      #|
|########################################|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Part 4: A Modern Workflow for Retro Dev
&lt;/h3&gt;

&lt;p&gt;The most painful part of retro development is usually the iteration cycle. In 1982, testing a change meant saving to a slow floppy disk, waiting for the drive to spin up, and typing LOAD "*",8,1.&lt;/p&gt;

&lt;p&gt;By wrapping cl65 and VICE in Python toolchain, Gemini 3 achieved a &lt;strong&gt;Hot Reload&lt;/strong&gt; workflow similar to React or Webpack and can edit the Assembly code in VS Code, hit a key, and within milliseconds:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The code recompiles into a .prg binary.&lt;/li&gt;
&lt;li&gt;Python connects to the running emulator.&lt;/li&gt;
&lt;li&gt;It performs a soft-reset of the virtual CPU.&lt;/li&gt;
&lt;li&gt;It injects the new binary directly into the emulated RAM.&lt;/li&gt;
&lt;li&gt;The game restarts instantly with the new logic.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This allows for a velocity of experimentation that was physically impossible on the original hardware.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;The Commodore 64 remains a solid tool for vetting how well AI systems actually reason. It strips away the bloat of modern computing and forces models to deal with hard constraints.&lt;/p&gt;

&lt;p&gt;If &lt;strong&gt;Gemini&lt;/strong&gt; 3’s success with my Tetris challenge proved it could handle logic under constraint, this Snake project proves it can handle systems engineering. By treating the C64 as an embedded device and applying modern principles — automated testing, hot reloading, and memory inspection — we pushed the boundaries of what is possible on 8-bit hardware.&lt;/p&gt;

&lt;p&gt;The 6510 teaches you to be frugal with resources. Python teaches you to be efficient with your time. Combining them gives you the best of both worlds.&lt;/p&gt;

&lt;h3&gt;
  
  
  Resources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/dexmac221/C64AIToolChain" rel="noopener noreferrer"&gt;GitHub Repository: C64AIToolChain&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@gianlucabailo" rel="noopener noreferrer"&gt;The Commodore 64 Constraint: Why Gemini 3 Is the First AI to Beat the Tetris Test&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>artificialintelligen</category>
      <category>gemini</category>
      <category>commodore64</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>I Made Claude and Gemini Write Tetris for a 1982 Computer.</title>
      <dc:creator>Dexmac</dc:creator>
      <pubDate>Sat, 06 Dec 2025 08:39:02 +0000</pubDate>
      <link>https://dev.to/dexmac221/i-made-claude-and-gemini-write-tetris-for-a-1982-computer-54nk</link>
      <guid>https://dev.to/dexmac221/i-made-claude-and-gemini-write-tetris-for-a-1982-computer-54nk</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgj2lqta1oogljtb0huh1.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgj2lqta1oogljtb0huh1.webp" alt="Image description" width="640" height="349"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing AI reasoning where Stack Overflow can’t help
&lt;/h3&gt;

&lt;p&gt;Last week, I gave two frontier AI models the same task: write a fully functional Tetris game in 6510 assembly language for the Commodore 64.&lt;/p&gt;

&lt;p&gt;One produced a playable game on the first iteration. The other produced a black screen with garbage characters.&lt;/p&gt;

&lt;p&gt;This isn’t a story about which AI is “better.” It’s about what happens when you strip away the safety nets of modern programming and force models to reason from first principles.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why the Commodore 64?
&lt;/h3&gt;

&lt;p&gt;Modern coding benchmarks have a problem: saturation. When you ask an AI to “reverse a linked list in Python,” you’re not testing reasoning — you’re testing recall. That exact problem, with minor variations, exists thousands of times in training data.&lt;/p&gt;

&lt;p&gt;The Commodore 64 is different. Released in 1982, it has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;64KB of RAM&lt;/strong&gt; (often less than 38KB usable)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A 1MHz processor&lt;/strong&gt; (your phone is 3,000x faster)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No floating-point math&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No operating system&lt;/strong&gt; in the modern sense&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can’t copy-paste solutions from Stack Overflow. The “standard” approaches don’t exist. And when something breaks, there’s no helpful error message — just a frozen screen or visual garbage.&lt;/p&gt;

&lt;p&gt;I’ve been using this constraint as a personal benchmark for AI models. I call it the &lt;strong&gt;Commodore 64 Constraint&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Toolchain
&lt;/h3&gt;

&lt;p&gt;To make this test fair and repeatable, I built a Python-based toolchain that connects to the VICE emulator. It works like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Code → Compile (cc65) → Inject into VICE → Read Screen RAM → AI analyzes result → Iterate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key innovation: the AI can “see” what’s happening on the C64 screen. A Python script reads the emulator’s memory and converts it to ASCII, giving the model visual feedback on whether its code actually works.&lt;/p&gt;

&lt;p&gt;Both models used the exact same toolchain, same compiler, same emulator settings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repository&lt;/strong&gt; : &lt;a href="https://github.com/dexmac221/C64AIToolChain" rel="noopener noreferrer"&gt;C64AIToolChain on GitHub&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Round 1: Claude Opus 4.5
&lt;/h3&gt;

&lt;p&gt;Claude (running as an agent in GitHub Copilot) was released two days before this test. I had no idea what to expect.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First iteration&lt;/strong&gt; : The game ran. Not perfectly — there were random blocks appearing where they shouldn’t, and the pieces flickered during movement. But the core was there: pieces spawned, fell, responded to joystick input, and the score displayed correctly.&lt;/p&gt;

&lt;p&gt;The bugs were &lt;em&gt;debugging&lt;/em&gt; problems, not &lt;em&gt;bootstrapping&lt;/em&gt; problems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fixes, in order:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Phantom blocks&lt;/strong&gt; : Pointer corruption in zero-page memory. The screen position calculator was overwriting variables used by the piece renderer. Solution: dedicated pointer variables.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flickering&lt;/strong&gt; : Drawing new position before erasing old. Fixed with VBlank synchronization — updating the screen only during the monitor’s vertical refresh&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lines not clearing&lt;/strong&gt; : The X register was being corrupted mid-loop by subroutine calls. Switched to a dedicated zero-page variable for loop counting.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Carry flag bugs&lt;/strong&gt; : Missing CLC instructions before additions caused address calculation errors. A classic 6502 gotcha.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After each fix, the game improved visibly. The progression was linear: broken → less broken → working → polished.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Final result&lt;/strong&gt; : Complete Tetris with all 7 pieces, rotation, line clearing, level progression, and a demo mode where the AI plays itself.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzxwolvanwuq3qyhiye86.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzxwolvanwuq3qyhiye86.gif" alt=" " width="480" height="357"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Round 2: Gemini 3
&lt;/h3&gt;

&lt;p&gt;Gemini had previously passed my BASIC Tetris challenge, where it outperformed Claude 4.0 and GPT-4. I expected a strong showing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First iteration&lt;/strong&gt; : Black screen. A few nonsense characters scattered randomly. No recognizable game structure.&lt;/p&gt;

&lt;p&gt;This wasn’t a bug to fix — it was a failure to bootstrap. The code compiled, but produced nothing resembling Tetris.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The next 20 iterations&lt;/strong&gt; were a struggle. Unlike Claude’s linear progression, Gemini’s debugging was circular:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fix the screen initialization → break the piece rendering&lt;/li&gt;
&lt;li&gt;Fix the rendering → break the collision detection&lt;/li&gt;
&lt;li&gt;Fix the collision → reintroduce the screen bug&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The model also got stuck on a “ghost piece” feature (showing where the current piece will land). It kept trying to render white dots under the falling tetrominoes, but the feature never worked correctly. The final README presents this as a feature, but in practice, it was a distraction that consumed iterations without improving core functionality.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;After 20+ iterations&lt;/strong&gt; , the game reached a stable state — but “stable” isn’t “complete.” Pieces fall, rotate, and lock. But the accumulation display is broken: you can’t clearly see the locked pieces building up. The visual feedback that makes Tetris &lt;em&gt;playable&lt;/em&gt; is compromised.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F38zwqfqb7eol2epojjhs.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F38zwqfqb7eol2epojjhs.gif" alt=" " width="480" height="357"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What the Comparison Reveals
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyyqmjydr6y0dpri9a0od.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyyqmjydr6y0dpri9a0od.webp" alt=" " width="604" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The difference isn’t intelligence — both models clearly “understand” what Tetris is and how 6502 assembly works. The difference is &lt;strong&gt;systems coherence&lt;/strong&gt; : the ability to fix one thing without breaking another.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Smoking Gun: A Carry Flag Bug
&lt;/h3&gt;

&lt;p&gt;After the test, I ran a detailed code analysis on both implementations. What I found explains Gemini’s “strange accumulation” problem perfectly.&lt;/p&gt;

&lt;p&gt;On the 6502 processor, the ADC (Add with Carry) instruction always includes the carry flag from the previous operation. If you forget to clear it, your math is off by one. This is a classic 6502 gotcha.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gemini’s board index calculation:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;adc ptr_lo ; 10y
stx ptr_lo ; Store X
adc ptr_lo ; ⚠️ NO CLC! If carry=1, adds 10y+x+1 instead of 10y+x
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Claude’s version:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;asl ; 10y
clc ; ✅ Always clear carry
adc test_x ; Safe: exactly 10y+x
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One missing CLC instruction. Three bytes. That's why pieces occasionally locked to wrong positions, creating gaps in the accumulation display.&lt;/p&gt;

&lt;p&gt;This isn’t a “Gemini is bad at assembly” story. It’s a “low-level programming is unforgiving” story. Claude happened to defensively clear the carry flag before every addition. Gemini didn’t. On modern hardware, this distinction doesn’t exist. On a 6502, it’s the difference between working and broken.&lt;/p&gt;

&lt;h3&gt;
  
  
  Different Strengths
&lt;/h3&gt;

&lt;p&gt;Claude treated the C64 like an embedded system with interdependent components. When fixing the flickering, it considered the implications for memory layout and timing. It also implemented a sophisticated AI demo mode that analyzes the board and makes strategic decisions.&lt;/p&gt;

&lt;p&gt;Gemini focused on visual features — ghost pieces, next-piece preview, color-enhanced tooling. Its approach to the code was more “modern”: clean segment organization, separate data arrays. But it treated bugs as isolated problems, leading to a whack-a-mole pattern where fixing one thing broke another.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The pattern&lt;/strong&gt; : Gemini excels at high-level features and user experience. Claude excels at low-level correctness and algorithmic robustness. Both are valuable — in different phases of development.&lt;/p&gt;

&lt;h3&gt;
  
  
  The “Modern Code” Signal
&lt;/h3&gt;

&lt;p&gt;Here’s something interesting: both models wrote code that looks like 2025 code running on 1982 hardware.&lt;/p&gt;

&lt;p&gt;Original C64 code from the 1980s used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Single-letter labels (L1, VAL, chk_c)&lt;/li&gt;
&lt;li&gt;Spaghetti logic with endless JMP statements&lt;/li&gt;
&lt;li&gt;Magic numbers everywhere&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both AI models used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Descriptive labels (check_collision, move_timer, head_idx)&lt;/li&gt;
&lt;li&gt;Structured subroutines with clear separation of concerns&lt;/li&gt;
&lt;li&gt;Constants and comments explaining the logic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This suggests neither model is simply retrieving historical code from training data. They’re translating modern software engineering principles into the constraints of ancient hardware — exactly what the benchmark is designed to test.&lt;/p&gt;

&lt;h3&gt;
  
  
  Limitations of This Test
&lt;/h3&gt;

&lt;p&gt;I want to be honest about what this doesn’t prove:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Sample size of one&lt;/strong&gt;. This is a single task, tested once per model. A rigorous benchmark would need multiple runs, multiple tasks, and statistical analysis.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Human in the loop&lt;/strong&gt;. I guided both models through debugging. A different human might have gotten different results.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Version sensitivity&lt;/strong&gt;. Gemini’s performance on BASIC Tetris was strong. Maybe assembly specifically hits a weakness. Maybe a future version fixes it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The “I’m testing myself” problem&lt;/strong&gt;. Claude is helping me write this article. Draw your own conclusions about that.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  What This Means for AI Evaluation
&lt;/h3&gt;

&lt;p&gt;Current benchmarks measure whether AI can produce &lt;em&gt;correct&lt;/em&gt; code in &lt;em&gt;forgiving&lt;/em&gt; environments. The Commodore 64 Constraint measures something different: can AI produce &lt;em&gt;working systems&lt;/em&gt; under &lt;em&gt;hard resource limits&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;This matters because real-world engineering often involves constraints. Embedded systems, legacy codebases, performance-critical applications — these are domains where “it compiles” isn’t enough.&lt;/p&gt;

&lt;p&gt;The C64 strips away the abundance of modern computing and asks a simpler question: &lt;em&gt;Can you actually engineer a solution, or just recall one?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Based on this test, both models can reason about assembly — but they reason differently. Claude produced bulletproof core logic; Gemini reached for visual polish. For a production game, you’d want Claude’s foundation with Gemini’s UI features ported on top.&lt;/p&gt;

&lt;p&gt;The real winner? The Commodore 64, still teaching programmers humility after 43 years.&lt;/p&gt;

&lt;h3&gt;
  
  
  Try It Yourself
&lt;/h3&gt;

&lt;p&gt;The complete toolchain is open source:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub&lt;/strong&gt; : &lt;a href="https://github.com/dexmac221/C64AIToolChain" rel="noopener noreferrer"&gt;C64AIToolChain&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Both Tetris implementations are included. Run them, compare them, improve them. If you get better results with Gemini (or any other model), I’d genuinely like to know.&lt;/p&gt;

&lt;p&gt;The Commodore 64 has been teaching programmers humility for 43 years. It turns out it teaches AI the same lesson.&lt;/p&gt;




</description>
      <category>agents</category>
      <category>retrocomputing</category>
      <category>llm</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
