Skip to content
Notis
The Emails an AI Assistant Owes You: How Notis Uses Customer.io

The Emails an AI Assistant Owes You: How Notis Uses Customer.io

Agents fail quietly. Here is the full inventory of operational emails Notis sends through Customer.io, and why triggers belong in code while copy belongs in the ESP.

Here is an underrated way to lose a user: your AI assistant silently stops working, and the first they hear about it is when they wonder why nothing happened last Tuesday.

Agents fail quietly. Integrations expire. Cards decline. Automations get paused. None of that is visible inside a chat thread, because the chat thread is exactly where nothing is happening.

So at Notis we treat operational email as part of the product, and Customer.io runs it.

The Emails an AI Assistant Owes You: How Notis Uses Customer.io — figure 1

The split: our backend owns when, Customer.io owns what

The design rule is boring and it has held up well.

Notis decides the trigger. Our Python backend knows that a subscription payment failed, that an automation hit a credit limit and paused, that a connected integration's token expired, that a sandbox is about to be cleaned up, that a channel got orphaned when someone changed phone numbers. Those are facts only the backend has.

Customer.io owns the message. Templates, copy, layout, localisation, sending. Each of our transactional sends carries a message identifier that maps to a template on their side, posted to their EU send endpoint.

That separation means I can rewrite the wording of a payment-failure email at 11pm without touching a deploy. And it means the backend code reads like a list of product events rather than a list of HTML strings.

What's actually in the inventory

We keep a canonical list of every operational email the product can send, and last verified it against the Customer.io workspace on 18 August 2026. A sample of what's in there:

  • trial ending, with the upsell
  • an automation paused because it ran out of credits
  • a specific subject or automation paused by the system
  • a channel disabled, or orphaned
  • payment failed, subscription canceled
  • an integration disconnected, or a batch of integrations expired
  • an on-demand charge that failed
  • a usage warning as someone approaches a limit
  • a sandbox scheduled for deletion
  • a team invitation
  • email alias verification
  • terminal delivery failure, when we've given up retrying a message to you

Read that list as a product spec rather than a mailing list. Every item is a moment where the assistant's state and the user's mental model have diverged, and the only fix is to say so.

The one I'd single out is terminal delivery failure. Notis replies over WhatsApp, iMessage, Telegram and email. Sometimes delivery to a channel permanently fails — a number gets blocked, a session expires, a provider restriction kicks in. The user's experience is "the assistant ignored me." Emailing them about it is the difference between a bug report and a churn event.

The Emails an AI Assistant Owes You: How Notis Uses Customer.io — figure 2

Why not just send them ourselves

We already have an email channel. Notis replies to you by email through a different provider entirely. So why add Customer.io?

Because those are different jobs wearing the same clothes.

Channel email is a conversation. It has to thread correctly, preserve references, carry attachments, and arrive as a reply from your assistant. Lifecycle email is a notice. It has to render well in every client, be editable by a non-engineer, be suppressible, and be auditable.

Conflating them is how you end up with a system where changing the footer of a billing notice requires a backend release, and where an unsubscribe on marketing accidentally suppresses a payment-failure alert. Keeping them separate costs one more vendor and saves a category of incident.

For the record, we also keep founder outreach in a third place. Three email systems sounds like too many until you notice they have three different failure modes.

The discipline that makes this work

One inventory, verified against the live workspace. A list of emails in a doc is fiction within a month. Ours gets checked against the actual Customer.io workspace, with a date attached. If a template exists and nothing triggers it, that's a finding. If code references a message ID that isn't there, that's an outage waiting for the right Tuesday.

Every operational email should be actionable. "Something went wrong" is not a notification, it's an anxiety generator. Each one should say what happened, what it means for work in flight, and the one thing to click.

Send from the region your users are in. We post to Customer.io's EU endpoint. For a Swiss-operated product with European users, that's not a nice-to-have.

If you're building an agent product

The thing nobody tells you: the more autonomous your product, the more email it owes people.

A tool that only acts when clicked needs almost no lifecycle messaging — the user was right there. An assistant that runs automations, holds integrations, spends credits and works while you sleep accumulates a long list of states you can silently be in. Each one needs a way to reach you outside the product.

So:

  1. Enumerate the silent-failure states first. Every one is an email.
  2. Split conversational delivery from lifecycle notification. Different tools, different reliability requirements.
  3. Keep triggers in code, copy in the ESP. Your future self will edit the copy far more often than the trigger.
  4. Audit the inventory on a date and write the date down.

Notis is founder-led and still expanding what the assistant can do on its own. The more it does unattended, the more it matters that it tells you when it can't.

Customer.io is how it tells you. Worth a look if your product does things while nobody's watching.

is the founder of Mind the Flo, an Agentic Studio specialized into messaging and voice agents.

Related posts