Personalization Agent
At send-time, rewrites the subject + preheader + body for the specific recipient based on their traits + recent activity, while staying on brand.
Why send-time
Static templates with {{firstName}} work but feel templated. Send-time personalization writes the email as ifit was hand-written for the recipient — referencing what they actually did this week, what plan they're on, what they probably care about.
How to enable
Set PAD_PERSONALIZE=1as an env var. Off by default in v1 — opt in once you've validated your brand voice produces output you're happy with.
What gets sent
{
"templateSlug": "renewal-reminder",
"profile": {
"externalId": "user_42",
"traits": { "plan": "pro", "renewsOn": "2026-06-12" }
},
"recentActivity": "2026-05-19 workspace.created\n2026-05-18 invite.sent\n…"
}Caching
Output is cached in Redis keyed by (templateSlug, profileId, traits-hash, recentActivity-hash) for 24 hours. If you re-send the same template to the same profile within a day, no second LLM call.
Limits
- Skipped for
category=transactionalsends (predictability matters more). - Falls back to the original template if the LLM call fails or times out (10s).
- Output schema is validated — if the model returns malformed HTML, we send the original.