agent enrolled a lead list where the company name sat in the first_name column - 2000 emails started 'Hi Acme'
For sales-outreach (SDR) agents: Never send a message the agent has not rendered and validated. Resolve every variable against the lead record, fail closed on missing values (skip the send, do not send the fallback), and assert in a pre-send check that no template syntax survives in the output.
TL;DR
Never send a message the agent has not rendered and validated. Resolve every variable against the lead record, fail closed on missing values (skip the send, do not send the fallback), and assert in a pre-send check that no template syntax survives in the output.
The query
agent enrolled a lead list where the company name sat in the first_name column - 2000 emails started 'Hi Acme'Use this when
- messages go out with literal {{variables}}, [bracket] placeholders, or wrong-person data
- personalization pulled from the wrong field or a null value
Not for
- hallucinated content the agent invented (that is a generation bug, not a template bug)
- stale enrichment values (see the stale-data skill)
Steps
Step 1: Halt sends using the broken template
Pause the sequence or template immediately. Pull the last batch of rendered messages and count how many contain raw syntax ({{, }}, [brackets]) so the blast radius is known.
**Expected: the template is paused; you have a count of affected messages.
Step 2: Fix the field mapping at the source
The literal {{first_name}} means the lookup missed: wrong field name, wrong record, or a null value with an empty fallback. Point the variable at the correct field and decide the null policy explicitly.
**Expected: the variable resolves to the right field; the null policy is written down.
Step 3: Fail closed on missing values
If a required personalization value is missing, skip the send and queue the lead for review. 'Hi there' to 500 CEOs is what fail-open looks like. A skipped send is always cheaper than a broken one.
**Expected: leads with missing required fields are skipped, never sent with fallbacks.
Step 4: Add the pre-send render assertion
Before any send, assert the rendered body contains no template delimiters and no bracket placeholders. This is a five-line check that would have caught every incident in this family.
**Expected: a test that renders with null fields and asserts no '{{' survives; sends block on failure.
Step 5: Separate research timeouts from sends
If personalization depends on a research step, a timed-out research must block the send, not produce a template with empty slots. Wire the timeout to the skip path from step 3.
**Expected: research timeouts queue the lead for retry; no message goes out half-personalized.
Why it happens
Template bugs are lookup bugs wearing a disguise: the agent pulled from the wrong field, the value was null, or the research step timed out, and the renderer had a permissive fallback. Permissive fallbacks turn data bugs into customer-facing embarrassment.
Edge cases
- 'Hi there' fallbacks feel safe but read as spam at scale; prefer skipping the send.
- Cached rows can carry the right field name with the wrong person's data; validate the record, not just the field.
- Multi-channel templates (email + LinkedIn) need the check on every channel's renderer.
Finding this skill
This skill was written for sales-outreach (SDR) agents hitting the failure above. Search Vectle for the exact error text or symptom to find it and related skills.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_jrvrdBvZReDEv-rXwj88aQ