Genairus logoGenAI-R-Us
Genairus logoGenAI-R-Us
The Generator Epiphany: A Hybrid Approach
AILLMCode GenerationSmithyCapacitorFluxAutomation
Part 3 of 6 in My Software Factory

The Generator Epiphany: A Hybrid Approach

Scott

The Right Tool for the Job

In the last article, I was trapped. My software factory, powered by a committee of LLMs, was expensive, inconsistent, and was failing to deliver on its promise. The core of my frustration was distilled into a single question: "Why am I paying a non-deterministic, creative AI to be completely deterministic?"

This question was the key. I was trying to force a tool designed for creativity and probability—an LLM—to produce the most rigid, predictable, and uncreative code imaginable: boilerplate. The server setup, the client libraries, the API data structures—this code should be identical every single time. It should be a solved problem.

The epiphany was realizing I was ignoring decades of software engineering best practice. For problems that are well-defined and require deterministic output, we don't use a creative process; we use a generator.

The New Hybrid Workflow

This realization led to a complete redesign of my software factory. I threw out the "all-LLM" approach and embraced a hybrid model that assigns tasks to the right tool. The new workflow is built on a clear separation of concerns:

  1. Define the Contracts with Universal Meta-Languages. Instead of describing my APIs, data models, and UIs in prose, I now define them formally using universal modeling languages:

    • Smithy - Protocol-agnostic interface definition for APIs. Defines resources, operations, and service contracts.
    • Capacitor - Universal data modeling language for database-agnostic schemas. Defines tables, fields, and relationships.
    • Flux - AI-first UI modeling language for cross-platform interfaces. Defines components once, generates for any framework.
  2. Generate the Boilerplate with Deterministic Tools. This is the crucial step. Each meta-language has powerful code generators. At build time, my factory uses these generators to create all the boilerplate code:

    • From Smithy: HTTP server stubs, request/response serialization, client libraries, API validation.
    • From Capacitor: Database schemas (SQL/NoSQL), migration scripts, type-safe data access clients.
    • From Flux: Framework-native UI components for React, Vue, SwiftUI, Jetpack Compose, and more. This code is never checked into source control. It's a build artifact. It's always perfectly in sync with the definitions because it's generated from them. It is 100% consistent and costs zero tokens to create.
  3. Use LLMs for the Creative "Plugin" Points. With all the boilerplate handled, what's left? The actual business logic. This is the creative, valuable work that is unique to my service. The generated code provides clear, well-defined "plugin" points—interfaces or abstract classes—where my business logic needs to go. This is where I now point my LLMs. I ask a specialized agent to write the specific code that implements the interface, such as:

    • "Implement the SaveWidget operation using the Capacitor-generated data client."
    • "Implement the GetUserProfile operation by calling the UserService and transforming the response."
    • "Connect the Flux-generated ProfileCard component to the user profile API endpoint."

The Results: Harmony, Speed, and Savings

The impact of this hybrid approach was immediate and dramatic.

  • Consistency: My codebase became perfectly consistent. All services built by the factory share the exact same structure, serialization logic, and client interaction patterns because they are all generated from the same core toolset.
  • Cost: My token costs plummeted. Instead of paying an LLM to churn out thousands of lines of boilerplate, I am now only paying for it to generate the small, specific, high-value business logic.
  • Speed: Development became incredibly fast. I can define a new API in Smithy, a data model in Capacitor, or a UI in Flux, and within seconds, have fully functional, type-safe code ready for me to plug in the logic. The tedious, error-prone work is gone.

I had finally found the right balance. I was no longer fighting the nature of the tools. I was using a deterministic generator for deterministic work and a creative AI for creative work.

In the next article, I'll put this new, efficient factory to the test with a real-world project, starting with just a high-level vision and seeing how the factory can automate the entire process from documentation all the way to a development plan.