Does Every Step Need AI? A Practical Workflow Review A developer's workflow review argues that teams should reserve AI models only for steps requiring genuine interpretation, using a Gmail-to-CRM-to-Telegram handoff as an illustrative design in which sender matching, attachment checks, owner lookup and notifications stay deterministic while only ambiguous natural-language intent goes to a model. The piece cites IEA projections that global data-centre electricity use could rise from 485 TWh in 2025 to 950 TWh in 2030 and Google's estimate of 0.24 Wh for a median Gemini Apps text prompt, while cautioning neither figure can be used to calculate a specific workflow's footprint. It also references OpenAI's guidance to check whether a deterministic solution suffices before committing to an agent. A customer email arrives, and your team needs to identify the sender, update a record, and notify the right person. Putting an AI model between every step may look like automation, but it also creates decisions you have to pay for, test, and supervise. The better question is simpler: which step actually requires interpretation? Student protesters interrupted an NVIDIA panel during NYC Climate Week, raising concerns about data-centre environmental impacts and the company’s business ties with Israel. Al Jazeera’s report https://www.aljazeera.com/video/newsfeed/2026/9/26/student-protesters-disrupt-nvidia-ai-climate-panel establishes that those concerns were raised; the interruption does not measure the footprint of your email automation or independently establish the protesters’ claims. The panel’s title was “ Confronting the data center energy crisis https://www.greenpeace.org/international/story/86131/green-ai-or-greenwashing-why-nvidia-cant-compute-its-way-out-of-the-climate-crisis/?trk=article-ssr-frontend-pulse x-social-details comments-action comment-text .” It is a useful prompt for a builder’s question: if a software step does not need a model, why call one? The wider electricity figures explain why this matters without answering that question for you. The International Energy Agency projects https://www.iea.org/reports/key-questions-on-energy-and-ai/executive-summary global data-centre electricity consumption rising from 485 TWh in 2025 to 950 TWh in 2030 . Those figures cover data centres overall, not AI alone, and the later figure is a projection. They cannot tell you how much electricity a particular customer-email workflow uses. Likewise, Google’s point-in-time analysis https://cloud.google.com/blog/products/infrastructure/measuring-the-environmental-impact-of-ai-inference estimated 0.24 Wh for the median Gemini Apps text-generation prompt in May 2025. Google cautions that the finding does not describe every text prompt or predict future performance. It would be misleading to multiply that figure by your email count and call the result your workflow’s footprint: your model, prompts, hosting, and number of calls may differ. You can inspect something directly: whether each call has a necessary job. That is an engineering review, not a climate calculation. A model is useful when a step must interpret variable language or produce a judgment that an explicit rule cannot reliably express. A saved-address lookup, an attachment check, and delivery to a known notification channel are ordinary software operations. Treating all of them as AI tasks makes the workflow harder to explain and test. Consider a Gmail-to-CRM-to-Telegram handoff. This is an illustrative design, not a measured client run : | Workflow step | First implementation to try | Why | |---|---|---| | Match sender to a customer | Exact lookup against approved addresses | The matching criterion is explicit. | | Check for an attachment | Read the message’s attachment metadata | The answer is already structured. | | Find the assigned owner | Read the customer record | The routing source is the CRM, not the email’s prose. | | Interpret “Please hold the next delivery until we sort out the previous charge” | Model proposes a category and concise summary | The message expresses an intent and an exception in natural language. | | Change billing or cancel an order | Authorized human approval, followed by a controlled action | A proposed interpretation is not permission to make a consequential change. | | Notify the owner | Integration call to the configured destination | Notification is an action, not a language decision. | This distinction follows practical agent-design guidance. OpenAI advises checking whether a deterministic solution would suffice https://cdn.openai.com/business-guides-and-resources/a-practical-guide-to-building-agents.pdf?file=a-practical-guide-to-building-agents.pdf before committing to an agent. Google Cloud likewise recommends considering non-agentic designs https://docs.cloud.google.com/architecture/choose-design-pattern-agentic-ai-system?hl=en for predictable or highly structured work. Do not turn that advice into “rules are always better.” A rule that catches the exact phrase “hold the next delivery” may miss “pause the shipment” or mistake a quoted email thread for a new request. A model may handle those variations better, but its output still needs a defined destination. If it cannot confidently establish what the customer wants, the destination is a review queue—not an invented CRM update. The safest implementation makes the model’s authority narrow: it may propose an interpretation , while application code controls routing and a person approves consequential changes. Write that boundary into the workflow before connecting live inboxes, CRM records, or chat destinations. Here is a small Python example showing the decision boundary. It uses injected lookup, classification, and notification functions so you can test the behavior without sending real customer data anywhere. It is not a drop-in Gmail or Telegram integration. python from dataclasses import dataclass from typing import Callable @dataclass class Message: sender: str | None body: str has attachment: bool @dataclass class Proposal: category: str summary: str def handle message message: Message, , find customer: Callable str , dict | None , classify: Callable str , Proposal , notify: Callable str, str , None , interpretation required: bool, - dict: events = model calls = 0 Do not pass an unmatched sender's message to a model by default. if not message.sender: return {"status": "human review", "reason": "missing sender", "model calls": model calls, "events": events} customer = find customer message.sender events.append "customer lookup" if customer is None: return {"status": "human review", "reason": "unknown sender", "model calls": model calls, "events": events} owner channel = customer.get "owner channel" if not owner channel: return {"status": "human review", "reason": "missing owner", "model calls": model calls, "events": events} events.append "attachment check" attachment note = "Attachment present" if message.has attachment else "No attachment" if interpretation required: This example expects Proposal but does not validate its type or contents. Check the injected classifier separately for side effects. proposal = classify message.body model calls += 1 events.append "message classification" Treat the proposal as untrusted. Route it for approval. notify owner channel, f"Review requested. {attachment note}." events.append "review notification" return { "status": "human review", "reason": "interpretation requires approval", "proposal": proposal, "model calls": model calls, "events": events, } notify owner channel, f"Customer message received. {attachment note}." events.append "routine notification" return {"status": "notified", "model calls": model calls, "events": events} The important detail is not the Python syntax. The handle message function shown here does not call a record-update or order-cancellation function. That does not establish what the injected classify , find customer , or notify functions can do: check their implementations and permissions separately. The example expects a Proposal , but it does not check its type or contents at runtime. Add validation before relying on classifier output. interpretation required also needs an honest source. It could come from a workflow configuration that says a particular inbox is used for requests requiring review. It should not be set to False merely because the sender is known: a known customer can still write an urgent exception. If the workflow must understand every incoming body to decide whether it contains an exception, classification itself may be a justified model step. Test that decision rather than hiding it behind a keyword rule. Before deploying this pattern, add strict validation at the classifier boundary. Accept only known categories, limit the summary to the fields the reviewer needs, and reject malformed output into human review. Keep credentials and destination IDs in configuration, not in message text or model instructions. NIST’s AI Risk Management Framework https://airc.nist.gov/airmf-resources/airmf/5-sec-core/ calls for human-oversight processes to be defined, assessed, and documented; a vague promise that “someone will check it” is not an implementation. A rule should replace a model call only when it preserves the workflow’s required outcome on representative inputs. “The rule ran successfully” is not enough if a delivery-hold request disappears into a routine notification. Start by writing down what the workflow must complete: identify the customer, put the message in front of its owner, and flag requests that may affect an order or a charge. Then run both the current approach and the proposed rule through the same set of examples. Include routine messages, missing fields, unknown senders, forwarded threads, ambiguous requests, and messages that mention an exception without clearly requesting action. For each example, record three separate results: That separation prevents a common reporting mistake. A model can produce a plausible category while the notification fails. A rule can route correctly while failing to flag an exception. Neither is a completed workflow. Use a table during review, even if the production system uses structured logs: | Input condition | Expected treatment | Failure to look for | |---|---|---| | Known sender, routine message | Notify assigned owner | Duplicate or misrouted notification | | Known sender, request to pause delivery | Propose interpretation; request approval | Automatic order change | | Sender missing | Human review | Guessing a customer from message text | | Sender not in approved records | Human review | Sending message content to the wrong owner | | Customer has no assigned channel | Human review | Silently dropping the message | | Quoted older request in a new thread | Review in context | Treating quoted text as a fresh instruction | Keep the examples with the workflow as regression tests. When routing rules, prompt instructions, or CRM fields change, rerun them. An initially successful demo is not evidence that the automation still behaves correctly after the surrounding business process changes. OpenAI’s workflow-evaluation guidance https://academy.openai.com/public/clubs/champions-ecqup/resources/ai-use-case-discovery-and-prioritizer-2026-05-07 recommends starting with an observable workflow problem and assessing frequency, reach, friction, repeatability, and business relevance. That is a better starting point than asking how many agents you can add. To evaluate an AI-enabled workflow, log each execution’s input, model calls, actions, exceptions, and final disposition. Conceal sensitive customer information in the review copy, and use actual execution logs before claiming a rule reduced calls or improved completion. A useful execution record identifies the workflow and run, then records whether a customer lookup succeeded, whether classification was invoked, whether a notification was sent, and whether the case reached human review. It should distinguish attempted actions from confirmed actions. If the notification service rejects a request, “notification attempted” is not “owner notified.” Review one call at a time. Ask what information it received, what decision it supported, and what would happen without it. Replace it with a lookup or condition only when the test cases show that the alternative holds up—including the exception cases. Keep the model where interpretation is genuinely required. If the revised workflow makes fewer model calls, you can accurately report fewer calls in that workflow . You cannot automatically report a particular dollar saving, emissions reduction, water saving, or electricity reduction. Those claims require separate measurements and assumptions about the model and infrastructure. A call counter is operational evidence, not a climate calculator. For an email-to-operations workflow like this example, send consequential or uncertain cases to a person. I’m Lazar Milićević, a senior engineer who builds practical AI automations for solopreneurs and small teams.