AI Genie Factory: How Alpura Shipped 90+ Databricks Apps With One AGENTS.md
At DATA+AI Summit 2026, Marvin Nahmias from Alpura presented something I haven’t seen before: a production-tested methodology for shipping enterprise Databricks apps at scale using AI code generation.
The result: 90+ apps across Finance, Sales, Operations, and Marketing — most built in days, some in hours.
The core insight is deceptively simple:
“AI generates code. Not architecture.” — Marvin Nahmias, DAIS 2026
You can’t just tell Genie Code “build me a sales dashboard.” You’ll get working code, but it won’t follow your team’s patterns, won’t use your semantic layer, won’t respect your governance rules. Every app becomes a one-off.
The AI Genie Factory solves this by defining architecture as constraints before code generation begins.
What Is Genie Code Agent Mode?
Before diving into the factory methodology, let’s establish what we’re building on.
Genie Code is Databricks’ AI coding assistant — think Copilot, but deeply integrated with the Databricks platform. It understands Unity Catalog, Delta Live Tables, MLflow, and the entire Lakehouse stack.
Agent mode is the key upgrade. Unlike Chat mode (which just generates code snippets), Agent mode:
- Plans multi-step solutions
- Retrieves relevant assets from your workspace
- Runs code and uses outputs to improve results
- Fixes errors automatically
- Loads skills — domain-specific knowledge packets — when relevant to the task
Skills are the mechanism that makes the factory work. They’re markdown files with instructions, examples, and patterns that Genie Code loads automatically based on what you’re asking it to do.
The Factory Architecture
The AI Genie Factory is a two-layer constraint system:
AGENTS.md → Always-on guardrails (~6,000 chars)
Platform rules, stack choices, error handling, logging
skills/ → Domain skills loaded on demand
UX patterns, pipeline templates, testing scaffolds
AGENTS.md is loaded into every Genie Code session. It contains the non-negotiable rules: what runtime to use, how to structure layers, what’s forbidden.
Skills are loaded only when relevant. Ask Genie Code to build a DLT pipeline? It loads @dlt-pipeline. Ask for a dashboard? It loads @databricks-dashboard and @ui-ux-patterns.
This separation is crucial. You want error handling rules applied to every generation. You don’t want 50KB of DLT documentation bloating the context when someone’s building a simple notebook.
What’s In AGENTS.md?
The published AGENTS.md encodes Alpura’s platform rules:
Global Rules
All applications must:
- Run on Databricks (Databricks Apps for web apps, Notebooks for exploratory, DLT for pipelines)
- Read only from Gold layer Unity Catalog tables in UI-facing apps
- Reference all tables using three-part naming: catalog.schema.table
- Separate data, logic, and UI into distinct layers — no layer may contain logic from another
- Apply central KPI definitions from the semantic layer — never recalculate a KPI that exists
- Respect Unity Catalog RBAC/ACLs — never bypass access controls
What’s Forbidden
Forbidden:
- Business logic in UI layer
- SQL outside the data access module
- Hardcoded values (catalog names, table names, thresholds)
- Reading from Bronze or Silver tables in UI-facing apps
- Redefining KPIs that exist in the semantic layer
- Bypassing Unity Catalog governance
Error Handling Contracts
Every data access call must be wrapped in try/except. Every exception must be logged before raising. Custom exception classes (DataAccessError, LogicError) are defined at the top of data.py.
The file includes exact code patterns:
# Data layer pattern (Databricks Apps — WorkspaceClient, NO spark):
try:
w = WorkspaceClient()
result = w.statement_execution.execute_statement(
warehouse_id=warehouse_id,
statement="SELECT * FROM catalog.schema.table",
wait_timeout="30s",
)
if result.status.state.value != "SUCCEEDED":
raise DataAccessError(f"Query failed: {result.status.error.message}")
# ...
except DataAccessError:
raise
except Exception as e:
logger.error(f"Failed to load catalog.schema.table: {e}")
raise DataAccessError(f"Table unavailable: catalog.schema.table") from e
When Genie Code generates a Databricks App, it follows this pattern exactly. Not because it’s smart — because the constraint is explicit.
The Skills System
Skills are where domain knowledge lives. The factory ships six:
| Skill | What It Does |
|---|---|
@ui-ux-patterns | Design tokens, shadows, typography, KPI cards, chart functions |
@databricks-app | File layers, app.yaml, OAuth M2M, deployment, debug checklist |
@databricks-dashboard | AI/BI Lakeview dashboards, dataset SQL, widget config, scheduling |
@dlt-pipeline | Bronze/Silver/Gold, Auto Loader, CDC, SCD2, streaming |
@data-access | sql-connector + Config(), Unity Catalog, batching, DataAccessError |
@testing-scaffold | pytest, mocked dbsql.connect(), pandas logic tests |
Each skill follows the Agent Skills open standard — the same spec that Claude, Copilot, and other AI coding assistants support.
Example: The databricks-app Skill
The @databricks-app skill defines the exact file structure every app must follow:
my-app/
├── app.py ← Orchestrator: layout, callbacks, CONFIG dict
├── data.py ← Data layer: sql-connector reads only
├── logic.py ← Logic layer: pandas transforms, aggregations
├── ui.py ← UI layer: Plotly figures, Dash/Streamlit components
├── _logger.py ← Structured logger
├── app.yaml ← Deployment manifest
├── requirements.txt ← Dependencies
└── APP.md ← App spec
It includes the exact authentication pattern for Databricks Apps (using databricks-sql-connector with Config() for OAuth M2M), the startup sequence that won’t block health checks, and a debug checklist for when things go wrong.
When you tell Genie Code to build an app, it loads this skill and generates code that matches your team’s patterns — not some generic structure it learned from training data.
How Deployment Works
The repo includes a deploy.sh script that uploads everything via the Databricks CLI:
# Deploy to your personal Genie Code folder
./deploy.sh
# Deploy workspace-wide (requires admin)
./deploy.sh --workspace
The script uploads:
AGENTS.md→.assistant/instructions.md(Genie Code’s instructions file)- Each skill →
.assistant/skills/<skill-name>.md
After deployment, Genie Code picks up the constraints immediately. No restart needed.
The Constraint Priority Stack
The factory enforces a clear hierarchy:
| Priority | Source | Purpose |
|---|---|---|
| 1 | GLOBAL_RULES.md | Platform law — never overridden |
| 2 | STACK.md | Technology choices — never redefined per app |
| 3 | modules/error_handling.md | Error contracts — never overridden |
| 4 | modules/logging.md | Logging standard — never overridden |
| 5 | @data-access skill | Connection patterns, batching |
| 6 | @ui-ux-patterns skill | Design system |
| 7 | @databricks-app skill | App architecture |
| 8 | APP.md | App-specific spec — only what’s unique |
Higher-priority constraints are never overridden by lower ones. An app spec can define which tables to query, but it can’t redefine how error handling works.
Why This Works
The factory methodology works because it treats AI code generation as a constraint satisfaction problem, not a creative writing exercise.
Without constraints: You prompt Genie Code for a dashboard. It generates something that works but doesn’t follow your patterns. Another developer prompts for a similar dashboard. They get different code structure. Every app is a snowflake.
With constraints: Every app follows the same file structure, uses the same error handling, respects the same governance rules. Developers focus on what’s unique to their app (tables, filters, business logic) instead of reinventing infrastructure.
The 90+ apps at Alpura share common DNA. When someone needs to debug an app they didn’t build, they know where to look.
Real Use Cases From Alpura
Alpura is one of Mexico’s largest dairy companies. Here’s what they actually built with this methodology:
Finance
- DBU Spend Monitor — Tracks Databricks unit consumption across teams, alerts on budget thresholds
- Cost Allocation Dashboard — Breaks down compute costs by department, project, and user
- Financial KPI Explorer — Revenue, margin, and cash flow visualizations from Gold layer tables
Sales
- Territory Performance — Regional sales metrics with drill-down by salesperson
- Customer Segmentation — RFM analysis dashboards pulling from unified customer profiles
- Forecast vs Actuals — Compares ML-generated forecasts against real sales data
Operations
- Fleet Tracking — Delivery route efficiency metrics (Alpura runs a massive distribution network)
- Inventory Levels — Stock monitoring across distribution centers
- Production Line Monitoring — OEE dashboards connected to manufacturing data
Marketing
- Campaign Performance — ROI tracking across marketing channels
- Customer Journey — Funnel visualization from acquisition to retention
- Promotion Effectiveness — A/B test result dashboards
The key insight: these aren’t 90 completely different applications. They’re variations on a theme — KPI cards, time-series charts, filterable tables — built from the same patterns. The factory methodology means each new app inherits the right structure automatically.
A sales dashboard and a finance dashboard both need:
- Data access layer with error handling
- Gold table queries with proper three-part naming
- Plotly charts with consistent styling
- Logging for debugging
The factory encodes all of that once. Developers focus on what’s unique: which tables, which filters, which KPIs.
Getting Started
The repo includes two example apps:
- NYC Taxi Explorer — Uses
samples.nyctaxi.trips, works in any Unity Catalog workspace with zero permissions - DBU Spend Monitor — Uses
system.billing.usage, requires system tables to be enabled
The recommended workflow:
- Run
./deploy.shto upload constraints and skills - Fill out
templates/APP_TEMPLATE.mdfor your app - Use
templates/PROMPT_TEMPLATE.mdas your Genie Code prompt - @mention relevant skills:
@databricks-app @ui-ux-patterns build the app per the spec below
How This Compares to Other Approaches
The Typical Enterprise AI Coding Setup
Most teams using AI code generation today follow one of these patterns:
Pattern 1: Ad-hoc prompting
- Developer opens Copilot/Claude/Cursor
- Writes a prompt describing what they want
- Gets code, manually adjusts to fit team conventions
- Repeat for next feature
Problem: Every developer’s output is different. No shared patterns. Knowledge doesn’t compound.
Pattern 2: Template repos
- Team maintains starter templates (cookiecutter, yeoman, etc.)
- Developer clones template, fills in blanks
- AI assists with individual components
Problem: Templates are static. They don’t adapt to context. AI doesn’t know about your templates unless you paste them into every prompt.
Pattern 3: Custom GPTs / RAG over docs
- Team builds a GPT with company docs in knowledge base
- Or sets up RAG over internal documentation
- Developer queries the enhanced AI
Problem: Good for Q&A, but doesn’t enforce constraints on generated code. AI “knows” your patterns but doesn’t “follow” them reliably.
The Factory Approach
The AI Genie Factory is different because constraints are loaded into the generation context, not just available for reference:
| Approach | Knowledge | Enforcement |
|---|---|---|
| Ad-hoc prompting | None | None |
| Template repos | Static templates | Manual |
| Custom GPT / RAG | Docs available | Advisory |
| Factory (AGENTS.md + Skills) | Live context | Automatic |
When Genie Code generates a Databricks App, it doesn’t just “know” that you use databricks-sql-connector — the skill includes the exact code pattern, and the agent follows it.
How Claude Code / Cursor Users Do This
If you’re using Claude Code or Cursor instead of Databricks Genie Code, you’re probably already familiar with similar patterns:
CLAUDE.md / AGENTS.md files — Same concept as the factory’s AGENTS.md. Global rules loaded into every session. We covered the Karpathy CLAUDE.md which encodes four principles for avoiding common AI coding pitfalls.
Agent Skills (agentskills.io) — The open standard that both Genie Code and Claude support. Skills are markdown files with instructions and code patterns. The factory’s skills follow this exact spec.
Cursor Rules — Cursor’s .cursorrules file serves a similar purpose to AGENTS.md. Project-specific constraints that shape every generation.
The factory methodology is Databricks-specific in implementation, but the architecture is universal:
Always-on constraints (AGENTS.md / CLAUDE.md / .cursorrules)
└── Domain skills (loaded when relevant)
└── App-specific spec (what's unique to this task)
What We Do at The Menon Lab
Our own setup follows similar principles:
- AGENTS.md in the workspace root with session management, memory protocols, and tool preferences
- SOUL.md for persona and communication style
- skills/ directory with domain-specific instructions (blogging workflow, GitHub operations, etc.)
- HEARTBEAT.md for periodic tasks
The key insight is the same: define constraints explicitly, layer them by scope, let the AI work within guardrails instead of hoping it guesses right.
The Bigger Picture
This is the same pattern we’ve seen work everywhere AI code generation succeeds at enterprise scale:
- Define architecture as explicit constraints — not assumptions
- Layer constraints by scope — always-on rules vs. domain-specific knowledge
- Use the same spec format the AI tools expect — Agent Skills, CLAUDE.md, etc.
- Version control your constraints — they’re code, treat them that way
The AI Genie Factory is Databricks-specific, but the methodology isn’t. If you’re using Claude Code, Cursor, or any AI coding assistant at enterprise scale, the same principles apply: AI generates code, not architecture. Define the architecture first.
GitHub: mexmarv/ai-genie-factory
Presented at: DATA+AI Summit 2026
License: MIT
Our Contribution: The Memory Layer
After seeing this talk at DAIS, we submitted a contribution to extend the factory methodology: a memory-layer skill that lets prompts learn from experience.
The Problem: Skills are static. They encode patterns you already know. But what about patterns you discover through production feedback? When your PII redaction keeps missing phone extensions, that learning is stuck in someone’s head — not in the system.
Our Contribution: PR #1 — Memory Layer Skill adds:
- Memory schema in Unity Catalog (decisions, patterns, feedback)
- MemoryLayer class that retrieves relevant context before generation
- Learning pipeline that extracts patterns from accumulated feedback
- Confidence scoring with temporal decay for stale patterns
The core idea: every time you correct the AI, that correction becomes future context. Prompts evolve automatically as the system learns.
# Before: Static prompt
prompt = "Redact PII from clinical notes..."
# After: Memory-enhanced prompt
context = memory.retrieve("pii_redaction")
enhanced_prompt = f"""
{prompt}
Learned patterns:
- Phone extensions (x1234) need special handling
- Keep facility names (not patient PII)
- Brother/sister names in family history are PII
"""
This bridges the gap between the factory’s skills (what you designed) and production reality (what you learned).
The contribution is pending review. If you use the Genie Factory, check it out and let us know what patterns your team has learned.
ThinkCreate.AI: We build memory infrastructure for AI systems. If you’re interested in bringing this pattern to your stack, reach out at thinkcreate.ai.