DEV Community

LePhuongTrung
LePhuongTrung

Posted on

I Built an "AI Meal Planner." It Almost Produced a Nutritionally Invalid Plan.

Google I/O Writing Challenge Submission

Last week, my constraint-optimization engine suggested I live on nothing but protein powder and frozen peas for 7 days to stay under my $27/week budget. It wasn't trying to be funny; it was a logical failure in my multi-step agentic workflow.

I’m a NestJS engineer. I thought I could solve "budget meal prep" with a clean schema and a prompt. I was wrong. Building this for the Google I/O 2026 challenge wasn't about building a demo; it was about fixing a system that kept breaking in the messiest ways possible.

1. The "Failure" Moment: The Gap Between Logic and Reality

My initial MVP was simple: feed the API a budget, get back a JSON list of meals.

The Failure: The model hallucinated prices based on global averages, not my local market. My engine accepted the hallucinated price as "ground truth," resulting in a plan that was technically within budget but nutritionally invalid (missing critical micronutrients).

The Insight: AI isn't an "optimizer"; it's a "generator." I had to shift my architecture from a Single-Prompt Request to a Multi-Step Validation Loop.

2. Quantitative Results: Measuring the Drift

I didn't just "fix" the prompts; I implemented a hard constraint-validation layer. Here is how the system improved after I introduced the Zod-based Fallback Strategy:

Measuring the Drift

3. The Implementation: Failing Safely

I learned that you cannot JSON.parse() your way to a production app. My agentic workflow now treats AI output as "untrusted input."

// The Reality: Handling LLM non-determinism in NestJS
async optimizeBudget(budget: number): Promise<MealPlan> {
  try {
    const raw = await this.gemini.ask(budget);
    // Schema validation ensures we never crash on malformed AI output
    return MealPlanSchema.parse(JSON.parse(raw)); 
  } catch (e) {
    // When AI reasoning drifts, we don't return an invalid plan. 
    // We pivot to a deterministic "safe-mode" heuristic.
    console.error("AI reasoning drift detected, falling back to deterministic heuristic.");
    return this.staticMealService.getFallbackPlan(budget);
  }
}
Enter fullscreen mode Exit fullscreen mode

4. What Google I/O 2026 Taught Me

This year’s I/O keynotes shifted my perspective on "Deterministic Agentic Workflows."

  • Serverless is a feature: I moved my reasoning logic to Cloud Run. During Sunday-night traffic spikes, the system auto-scales. I only pay for compute when the agent is actually "thinking."
  • Firestore as the Ambient Glue: By using Firestore, my meal plan isn't just a web app state—it’s an ambient data stream that syncs instantly to my mobile device. It’s the "ambient computing" vision I saw on stage, applied to my own grocery list.

5. Conclusion: The Real Goal

The goal was never just to build an AI meal planner. It was to build a system that fails safely.

As developers, we are moving into an era where AI is no longer a "nice-to-have" feature; it is a core dependency. If we cannot build systems that fail gracefully when the LLM hallucinates, we aren't building software—we're just building technical debt.

The Live Mess: lephuongtrung

Top comments (0)