DEV Community

Cover image for Generic AI Outreach Is a Context Problem
SpurIQ Engineering
SpurIQ Engineering

Posted on

Generic AI Outreach Is a Context Problem

I want to show you two outputs from the same model.

Same LLM. Same temperature. Same system prompt structure. Same signal: a company just posted three new SDR job listings.

Output A:

"Saw you're hiring salespeople. We help teams like yours hit quota faster. Worth a quick chat?"

Output B:

"Adding three SDRs usually shifts the pressure from finding people to making them productive fast, because ramp time quietly becomes your biggest variable once you're past the first hire. Happy to show you how we help teams replicate what their best reps do before the new cohort has their first bad month."

The model didn't get smarter between those two outputs. The prompt got better. Specifically: the context changed.

Output A came from a prompt that said: "The company is hiring salespeople. Write a personalized opening line."

Output B came from a prompt that said: "Signal: company posted 3 SDR job listings. ICP rule: target companies scaling sales teams past 5 reps where headcount growth precedes process maturity. Persona: VP of Sales, primary concern is ramp time and rep replication. Proof point: we help encode how your best reps sell so new hires can follow the same pattern. Signal hypothesis: SDR expansion usually surfaces the rep replication problem within 60 days. Write an opening line that connects the signal to the persona's problem using this hypothesis."

Same signal. Completely different inputs. Completely different outputs. And the difference has almost nothing to do with the model.

Why Generic Output Is a Context Failure

There's a tendency to blame the model when AI-generated outreach sounds robotic or generic. I've been in enough of those conversations, "the AI just can't get our tone" or "it always sounds like a template", to know that this is almost never true.

Generic output is almost always a context failure. The model is doing exactly what you asked it to do: producing something that makes sense given what it was told. If what it was told is shallow, the output is shallow. If you feed it a bare signal and ask for personalization, you get the weakest possible version of personalization, the kind that just confirms you could see the data.

"Saw you're hiring salespeople" is technically personalized. It references a real thing about a real company. But it's not relevant. It doesn't connect the observation to anything the recipient actually cares about. It's a sentence that says "I have access to your hiring data" rather than "I understand what that hiring data means for you right now."

The reason most AI-generated outreach sounds the same isn't the model. It's that most prompts contain the same amount of context: not much.

What the Context Assembly Step Actually Involves

If generic output is a context failure, the fix isn't a better model. It's a better context assembly step that runs before generation.

Here's what that step actually needs to retrieve for a single signal-to-message generation:

1. The ICP rule that matches this account.

Not the general ICP slide ("mid-market SaaS, growing GTM teams"). The specific, encoded condition that qualified this account for outreach: what size, what signals had to be present, what exclusions had to be absent. This tells the model why this account is worth reaching at all, not in marketing language, but in checkable logic.

python
icp_rule = {
  "segment": "SaaS companies scaling past 5 sales reps",
  "qualifiers": [
    "headcount_growth_rate > 30% YoY",
    "no_existing_sales_enablement_tooling",
    "sdr_to_ae_ratio_above_threshold"
  ],
  "disqualifiers": ["existing_client", "competitor", "no_outbound_motion"],
  "rationale": "headcount growth before process maturity creates rep replication problem"
}
Enter fullscreen mode Exit fullscreen mode

That rationale line, the "why this account" reason, is what the model needs to write something meaningful. Without it, the model is guessing at the connection between the signal and why you're reaching out.

2. The persona priority for this contact.

The same signal means different things to different people at the same account. A new SDR job posting is a rep replication problem for the VP of Sales, a headcount cost problem for the CFO, and an onboarding infrastructure problem for the RevOps lead.

persona = {
  "title": "VP of Sales",
  "primary_concern": "ramp time and rep replication",
  "secondary_concern": "showing early wins to board before next review",
  "what_they_don_t_want": "another tool the team won't use"
}
Enter fullscreen mode Exit fullscreen mode

This isn't a buyer persona slide. It's the specific set of things the model needs to know to write for this person and not for a generic sales leader.

3. The signal hypothesis.

This is the piece most prompts skip entirely, and it's the most important one. The hypothesis is the business interpretation of the signal, not what you observed, but what the observation likely means for this persona right now.

signal_hypothesis = {
  "signal": "3 new SDR job postings",
  "observation": "company is expanding its outbound sales team",
  "implication": "headcount growth usually precedes process maturity gap by 30-60 days",
  "persona_problem": "new SDRs ship without knowing how top reps work; 
                       first 90 days sets the pattern they keep forever"
}
Enter fullscreen mode Exit fullscreen mode

When the model gets this, it doesn't have to infer the connection between hiring and why you're reaching out. The connection is explicit. The model's job becomes writing, expressing an idea that's already been formed, rather than reasoning from scratch about what an SDR job posting might mean.

4. The proof mapping.

One relevant proof point that connects the hypothesis to something you actually solve. Not the full pitch deck, the single most relevant thing you can say about this problem.

proof_point = "We help sales teams encode how their best reps sell, 
               the ICP rules, signal interpretations, and messaging, 
               so new hires follow the same pattern from day one 
               instead of inventing their own"
Enter fullscreen mode Exit fullscreen mode

Assembly complete. Now the generation prompt looks like this:

The Reusable Prompt Template

You are writing a single opening line for an outbound email.

ACCOUNT CONTEXT
---------------
Signal observed: {signal_description}
ICP qualification reason: {icp_rule.rationale}

PERSONA CONTEXT
---------------
Contact title: {persona.title}
Primary concern: {persona.primary_concern}
What they don't want to hear: {persona.what_they_dont_want}

SIGNAL HYPOTHESIS
-----------------
Observation: {signal_hypothesis.observation}
Business implication: {signal_hypothesis.implication}
Persona-specific problem: {signal_hypothesis.persona_problem}

PROOF CONTEXT
-------------
Most relevant proof point: {proof_point}

TASK
----
Write one opening line (1–2 sentences) that:
- Starts from the signal hypothesis, not the raw signal
- Connects the observation to the persona's specific problem
- Does not pitch the product; create the opening only
- Sounds like a human wrote it after reading about this company
- Does not begin with "I noticed" or "Saw that you"

OUTPUT: One opening line only. No subject line. No sign-off.
Enter fullscreen mode Exit fullscreen mode

The difference between this and a bad prompt isn't the instructions at the bottom. It's the four context blocks above them. The instructions are almost identical to what you'd find in any generic outreach prompt. The context is what produces a different output.

Signal Scoring vs. Signal Interpretation

There's a distinction worth naming explicitly because it's where a lot of well-intentioned systems go wrong.

Signal scoring answers: who do we reach out to, and in what order? It's a prioritization problem. An account that shows three signals simultaneously scores higher than one showing a single signal. You build a matrix, assign weights, rank the queue.

Signal interpretation answers: what do we say when we reach out? It's a messaging problem. And the answer depends entirely on which signal is most relevant to this specific persona, which is not the same as which signal has the highest aggregate score.

An account might score highly because it has a funding event, an executive hire, and an SDR job posting all firing simultaneously. But for the VP of Sales you're reaching, the SDR job posting is the one that connects to their specific problem. The funding event might be more salient for the CFO. The executive hire is more relevant to the founder. Signal scoring collapses all of that into a single number. Signal interpretation has to disaggregate it back out.

This is where most AI-powered outreach breaks down even after you've solved the context assembly problem. The system passes all available signals to the generation step and asks the model to pick the best one. Sometimes it does. More often it tries to reference all of them and produces something that's technically comprehensive and contextually incoherent.

The cleaner approach: run interpretation before generation. Decide which signal is most relevant to this persona before the generation prompt is built. Pass only that signal, with its hypothesis, to the model. Let the model write, not choose.

This is what turning a signal into a business hypothesis actually means in practice. It's not a generation step. It's a reasoning step that happens before generation, so the model has something real to express rather than something vague to infer.

The Persistent Context Problem

One thing the prompt template above doesn't solve: where does the context come from?

The ICP rule, the persona priorities, the signal hypothesis library, the proof mapping, none of that exists in the signal feed. It has to be built, maintained, and retrieved at generation time. If it lives in a Notion doc that someone updates occasionally, you'll get inconsistent context in the prompt and inconsistent output. If it's stale, if the ICP shifted last quarter and nobody updated the rule, you'll get context that's technically present but factually wrong, which is worse than no context because the model will generate confidently from it.

This is the argument for what I'd call persistent company context, a structured store of the things the model needs to know every time it generates for your company. Not a knowledge base for humans to read. A machine-readable store of ICP rules, persona definitions, signal hypotheses, and proof mappings that the context assembly step retrieves from before every generation call.

The Revenue Brain concept that SpurIQ is building around is essentially this, not a generation layer but a context layer that everything reads from before acting. The idea is worth reading about independently of the product, because the problem it's solving is real regardless of who solves it.

If you're building an AI-assisted outreach system and your context lives in a spreadsheet someone updates manually, that's your bottleneck. Not the model, not the prompt template, not the generation parameters. The context.

What to Actually Do With This

If you're working on this problem right now, the most useful thing you can do is run the A/B test yourself.

Take any signal your system currently processes. Write the bare prompt your system uses today. Run it. Then build the four-context version, ICP rule, persona priority, signal hypothesis, proof mapping and run it with the same signal.

The output difference tells you where your context gap is. Usually it's the hypothesis: the reasoning step between "observed X" and "which means Y for this person." That's the hardest piece to encode because it requires the most domain knowledge, and it's the one that produces the most disproportionate improvement in output quality when you get it right.

The model isn't the problem. The context is. And context, unlike model capability, is something you can control completely.

Top comments (0)