Put the guarantee in the delivery layer.
Scheduled jobs, in-app actions, and campaign rules can all trigger messages at the same time. A duplicate is a visible failure for the customer.
I keyed delivery on a deduplication identifier, so the guarantee lives in one place instead of relying on every caller to get it right.