DEV Community

Cover image for Let the LLM Talk, Let a Script Do the Math: A Three-Part Pattern for Decision Agents
yu matt
yu matt

Posted on

Let the LLM Talk, Let a Script Do the Math: A Three-Part Pattern for Decision Agents

The code is open source (MIT). The repo link is at the end of this post — a star would mean a lot. ⭐

A quick test

You have two McDonald's coupons and can use only one:

  • Spend 40, get 10 off
  • 12% off any burger

You order a ¥25 burger:

  • Threshold coupon: you'd have to add ¥15 more → pay ¥30
  • Percentage coupon: 25 × 0.88 = ¥22 → the percentage coupon wins

Now make that burger ¥40:

  • Threshold coupon: pay ¥30 → the threshold coupon wins
  • Percentage coupon: pay ¥35.2

Which coupon is cheaper depends entirely on what's in the order. There is no general answer.

That's two coupons and one item. A real order is three coupons, twenty items, plus constraints like "two people, under ¥50, keep it under 1100 kcal, at least 35g protein." The number of combinations that satisfy all of that runs into the thousands.

Ask an LLM to solve that and you get three predictable outcomes:

  1. Slow — thousands of multiply-adds, generated token by token
  2. Expensive — every step burns tokens
  3. Wrong — LLM arithmetic, as anyone who's tried it knows

So this project started from one rule:

The LLM handles understanding and expression. A script handles computation and determinism.

The architecture

User speaks plainly
   │  "two people, under ¥50, nothing too greasy"
   ▼
LLM (WorkBuddy) parses intent ──► hard constraints
   │  max_payable=45, max_calories=1100, min_protein=35
   ▼
McDonald's MCP fetches real data ──► store menu / nutrition / coupons
   │
   ▼
optimize_meal.py (local, no network) ──► enumerate + best-coupon match
   │
   ▼
LLM turns results back into plain language ──► three plans
Enter fullscreen mode Exit fullscreen mode
Role Owns Doesn't own
LLM Interpreting "nothing too greasy"; narrating results Money math, calorie math, remembering menus
MCP Structured, trustworthy data Decisions
Local script Enumeration, filtering, coupon matching, ranking Natural language

The payoff is direct: the script runs in milliseconds, is reproducible, costs zero tokens, and never gets the money wrong.

Why not let the model do the math

1. Enumeration is arithmetic, not language. It's a Cartesian product plus constraint filtering: 1–2 mains + 0–1 sides + 0–1 drinks + 0–1 desserts. Deterministic, unambiguous, no "understanding" required. Using a probabilistic model for deterministic computation is the wrong tool.

2. Coupon matching has a constraint models miss: one coupon per order. So you can't just pick the biggest face value. You have to compute what this specific order actually saves — does the threshold clear, what's the discounted total, does the category restriction apply. Only enumeration gets it right.

3. There are three different ranking objectives. Cheapest (ascending total), healthiest (ascending deviation from targets), best value (descending protein per yuan). All three run over the same candidate set. That's a script's job.

What the LLM is still good for

The other half of the split: shrink the model's workload without shrinking its value.

  • Translate vague language into hard constraints. "Two people" → raise the protein target. "Nothing too greasy" → maybe a calorie cap, maybe exclude fried categories. "Under ¥50" → max_payable = 45, leaving headroom for delivery and packaging fees the client can't see. Scripts can't do this mapping; models do it well.
  • Narrate structured output. The script emits JSON. The model explains why this plan over that one.

The boundary is clean: the model translates and narrates. It does not compute and does not remember.

A cautionary note on data

Hard rule in this project: every number comes from MCP, nothing is hardcoded. An LLM's memory of a fast-food menu is outdated, incomplete, and occasionally invented. More importantly:

The same chain's different locations carry different items and different coupons.

So the flow must be: confirm the store first, then fetch menu and coupons. During testing I nearly picked a store by keyword search — the results were all inside train stations. Had I chosen one for the user, they'd have been nowhere near it and the order would have been wasted. That became the hardest rule in the skill: the store must be confirmed by the human, never guessed.

Two MCP setup gotchas (WorkBuddy-specific)

1. type casing. McDonald's docs show lowercase:

"type": "streamablehttp"
Enter fullscreen mode Exit fullscreen mode

WorkBuddy only accepts camelCase:

"type": "streamableHttp"   // works
"type": "streamablehttp"   // not recognized
Enter fullscreen mode Exit fullscreen mode

I reverse-engineered this by reading WorkBuddy's built-in connector list — every built-in uses camelCase. When docs and client disagree, compare against the built-ins.

2. Config path. Many tutorials say ~/.workbuddy/mcp.json. The one that actually takes effect is ~/.workbuddy-ai/mcp.json. The ~/.workbuddy/ directory does exist — it just holds device-id and logs, not config.

3. Configuring isn't enabling. After writing the config you still have to enable the server in the custom-connector panel, or the client won't load it.

Verify with a raw JSON-RPC call rather than trusting the UI — a tools/list round trip returned 35 tools.

One more step people skip: server-side repricing

The local engine's total is an estimate. Delivery fees, packaging, and store-level promotions only exist server-side. Before showing any plan, send its item codes through the pricing tool and reconcile — server wins when they disagree. Skip this and users find out your math doesn't match what they actually paid.

Takeaway

The valuable part of this project isn't the cheapest combo. It's the division of labor:

LLM for understanding and expression, script for computation and determinism, MCP for trustworthy data.

If you're building anything decision-shaped — meal picking, product selection, scheduling, price comparison — this three-part structure transfers directly.


Repo: https://github.com/minxin88/mcd-meal-optimizer

MIT licensed, pure Python standard library, zero dependencies. Run python scripts/optimize_meal.py --demo to exercise the enumeration and coupon-matching flow with no token required — that runs on the bundled offline sample data, not a real store's prices.

Scope: no ordering, no coupon claiming, no order cancellation, and store selection always requires human confirmation. Personal, non-commercial use only.

Top comments (1)

Collapse
 
suppdevbot profile image
DEV SUPPORTS •
You need to verify your account.
Enter fullscreen mode Exit fullscreen mode

tr.ee/dev-to