{
  "slug": "outreach-sequencer",
  "title": "Building an outreach sequencer for managers who don't write copy",
  "words": 2546,
  "score": "49/50",
  "anonymisation": "L0",
  "article": "> **In brief**\n>\n> - Sending tools assume a competent operator: they provide infrastructure, while the missing layer is usually expertise.\n> - Encode the expert as a pipeline: model research, one human gate where judgement matters, then a deterministic last mile for the step that must never be wrong.\n> - A reputationally dangerous model output gets a structural fence, not a politer prompt: hedged bands, schema-validated at two boundaries, surfaced only inside the approval gate.\n> - The model never writes sending-tool syntax; an injection function substitutes it and throws on unknown tokens, which turns zero wrong tokens into a contract instead of a hope.\n\nWe recently built an internal tool for GoStudent, the tutoring group, that writes cold-email campaigns for the managers of its 100-plus physical centres. The users are not marketers. Most of them had already tried cold email, produced sequences they could not judge, and quietly stopped. The tool's job is to be the copywriter they do not have: it researches the audience, drafts the sequence in the manager's language, and hands back something that drops cleanly into whatever sending tool that manager already uses.\n\nThe build produced two design problems we think are worth writing up properly. One is about safety: the research step wanted to estimate what parents can afford, and an AI writing wealth assumptions about families is a newspaper headline waiting to happen. The other is about reliability: merge fields have to come out in each manager's exact sending-tool syntax every single time, in a tool operated by people who cannot debug a broken campaign. The two problems pulled in opposite directions, one toward more human judgement and one toward less, and the shape of the final system falls directly out of how we resolved each. This post walks through both, plus the smaller decisions and surprises along the way.\n\n## The channel was dormant, not broken\n\nGoStudent's offline business runs tutoring centres under three brands: Studienkreis in Germany, LernQuadrat in Austria, and GoCampus. Each centre has a manager, and for that manager, outbound acquisition is one duty among many. The internal persona shorthand during the build was blunt: someone who struggles to connect WhatsApp Web to a phone. The description sounds unkind, but it set the design constraint everything else had to survive.\n\nNow look at what the channel actually demands of that person. A working cold-email operation needs audience selection, persona research, copy that lands in the local market's register, a sequence structure with sensible timing, and merge-field tokens in the exact syntax of the sending tool. The managers had access to the standard stack: Smartlead, Instantly, Lemlist, Apollo, Clay. Every one of those products assumes a competent operator. They provide infrastructure. The missing layer was expertise, and a manager who cannot evaluate the output cannot improve it with any amount of tooling.\n\nThis diagnosis inverted the usual build. We did not build sending, scheduling, warm-up, or deliverability, and the tool does not touch inboxes at all. Every manager keeps their existing sender. What we built is the layer the market does not sell: the strategist and copywriter, encoded as a pipeline. The manager's job shrinks to editing.\n\n## The shape of the system\n\nThe tool is an internal web app behind Google sign-in. Managers span many email domains, so a single-workspace rule was impossible; a database allowlist is the gate instead. A one-time setup wizard captures two things: the centre (location, offering, context) and the manager's sender variables, meaning how their particular sending tool writes its merge fields. Generation is hard-blocked until both exist, because every downstream guarantee depends on them.\n\nAfter setup, a campaign runs through five stages:\n\n```\nresearch        Sonnet + live web search builds an audience persona\n   ↓\napproval gate   a human reads and edits the research   ← the judgement step\n   ↓\ngenerate        Sonnet drafts the sequence from the approved persona\n   ↓\ninject          a pure function substitutes the manager's exact\n                merge-field syntax; unknown token → throw\n   ↓\nexport          a Google Doc lands in the manager's own Drive\n```\n\nAll model work runs inside a durable background-job engine (Inngest). That sounds like plumbing but is a product decision: a manager who closes a laptop lid mid-generation loses nothing, and the approval gate can hold for days without a process hanging anywhere. The stack around it is deliberately boring: Next.js on Vercel, Postgres on Supabase in Frankfurt, Prisma, Auth.js with JWT sessions. The app speaks 7 languages; the launch set was six until the stakeholder added Italian mid-project. Per-brand theming resolves server-side, so a Studienkreis manager and a LernQuadrat manager each see their own brand from first login without ever choosing a skin.\n\nTwo constraints shaped the model layer. First, an operator instruction fixed the model choice, verbatim from the build log: \"Pls only ever use Sonnet models.\" Our own architecture review had recommended a stronger model for the research step, so the override is worth being honest about. It is the kind of trade real projects make: one model everywhere is simpler to reason about and cheaper, and the quality bar gets checked at an acceptance gate anyway. Second, prompt caching does real work here. The static scaffolding of the generation prompts is cached, which takes roughly 90 percent off those input tokens, and the projected model spend for the whole estate came out at 50 to 300 dollars a month. We also wired a stop-and-escalate trigger into the design. A sustained cost above about 2 dollars per sequence, or a trajectory past about 300 dollars a month, halts the pipeline and pages a human rather than quietly burning budget.\n\nWe sequenced the build risk-first. Before any interface existed, the generation pipeline ran headless behind a script with cost logging from the very first call. Model quality, live-web-research reliability, and cost at volume were the three unknowns that could have killed the project, so they were surfaced in week one rather than discovered under a finished UI. The initial arc took days rather than months, with a three-week extension following, and the test suite grew from 302 unit tests at the baseline to 344 plus a critical-path end-to-end test by the end.\n\nTo make this concrete, here is what a manager actually types, taken from one of our launch fixtures. A Munich centre offers maths and German tutoring at 29 euros per 45 minutes, and wants to reach parents in the weeks before mid-year report cards. That is the entire input. Audience strategy, persona, tone, structure, and tokens all come out the other end.\n\n## Design problem one: the field that could have ended up in a newspaper\n\nThe research stage originally wanted a number for likely monthly household income. The reasoning is legitimate: affordability genuinely changes what a good sequence should say, how it should frame pricing, and which offer leads. The risk is also obvious. An AI system publishing wealth estimates about specific audiences, on behalf of a tutoring company that serves families, is one screenshot away from a stereotyping story. We considered dropping the field entirely and rejected that too, because the information does real work.\n\nThe fix was structural, and we want to stress that word, because the reflex in most AI products is a politer prompt. Prompts are requests. We wanted a fence. Four decisions built it:\n\n1. **The number became a band.** No numeric income estimate exists anywhere in the system. The field is a hedged, qualitative affordability band, and the hedging is not a stylistic habit but a validated format.\n2. **Schema validation enforces the hedge at two boundaries.** The research layer validates the band's shape when the model produces it, and the approval route validates it again before anything is stored. A model that emits a numeric guess fails validation twice, which is belt and braces by design.\n3. **The band hides behind a disclosure.** In the approval screen it sits collapsed, so seeing it is a deliberate act rather than ambient exposure.\n4. **It only exists inside the human gate.** The band never reaches generated copy directly; it informs the sequence through the persona a human has consciously accepted or edited.\n\nThe gate itself is designed against approval theatre. Research on automation bias finds that users who like automation tend to over-approve it ([Bias in the Loop, arXiv:2509.08514](https://arxiv.org/abs/2509.08514)). We took that seriously rather than treating the human step as a legal fig leaf. The primary button stays disabled until all four research fields have actually been seen. Everything on the screen is inline-editable, so approve-with-edits is the path of least resistance rather than a power-user trick. The gate is also, not coincidentally, the cheap place to fail: research is the inexpensive call and generation the expensive one, so a persona rejected at the gate saves the money as well as the embarrassment.\n\n## Design problem two: zero wrong tokens as a contract\n\nThe second problem sounds small until you sit with it. Merge fields must come out in the manager's exact sending-tool syntax, every time. One malformed token does not fail loudly at send time; it mail-merges garbage into a prospect's inbox, inside the one tool the manager cannot debug. For a user who cannot evaluate output, silent corruption is the worst failure class there is.\n\nSo the model is never allowed to write tool syntax at all. It emits canonical markers only, and a pure function performs the substitution at the end of the pipeline. The shape of the mechanism, with illustrative tokens:\n\n```\nmodel writes:     \"Sie erreichen uns hier: {{canonical:CALENDAR}}\"\nmanager config:   CALENDAR → the syntax their sending tool expects\ninjected output:  the same sentence, exact tool syntax substituted\nunknown token:    injection throws; the campaign never exports\n```\n\nBecause the injector fails loudly on anything it does not recognise, \"zero wrong tokens\" stops being a hope about model behaviour and becomes a property of the system. The set of tokens that can reach an exported document is closed and tested. Our build notes phrased it in a way we still like: the fail-loud guarantee is what makes zero wrong tokens a contract instead of a hope.\n\nThere is one deliberate softening. Models and template authors both drift toward natural-language tokens, writing things like <<Calendar>> instead of the canonical form, so a small alias map absorbs the near-misses. We keep the map narrow and review additions by hand, because every alias weakens the closed-set guarantee a little.\n\n## What surprised us\n\n**The cheap decision was the better product.** Multi-audience campaigns were specced as a schema migration: turn the sequence's single audience column into an array. The cheaper path was to leave the column singular and fan out N parallel single-audience jobs grouped under one campaign. We took it for cost reasons and discovered the output was better: one sequence per audience, each separately editable and separately tunable, instead of a single blended sequence trying to speak to everyone. We went in expecting a compromise and came out with the design we would now recommend.\n\n**A constraint routed around itself.** Voice input was requested after the Sonnet-only rule was set, and speech-to-text would normally mean adding a transcription model. Instead the browser's own Web Speech API does the transcription and Sonnet only does structured extraction from the transcript. The constraint held and the feature shipped.\n\n**The users renamed the product.** Managers never said \"sequence\" in real usage. They said \"campaign\", so a full terminology sweep renamed the concept across the product.\n\n**Embedded work finds small truths.** Studienkreis's brand colour had been cited wrong in our own design documents for a week. Red, not blue. Not a profound error, just a typical one.\n\n## Speeds, ceilings, and honest numbers\n\nA manager gets four speeds, and the spread matters more than any single figure:\n\n| mode | wall clock | what it skips |\n|---|---|---|\n| full research | ~60 s of model time | nothing: live web research + human gate |\n| quick, from scratch | ~10 s | the human gate (research still runs) |\n| quick + fast mode | faster still | web search too; the model works from its own knowledge |\n| template path | <100 ms | the model entirely: one database transaction |\n\nThe template path is the one we point at in design discussions: when a manager picks a pre-baked campaign, no model is called at all, and the whole operation is a single atomic transaction. Sometimes the right amount of AI in a pipeline is none. The zero-model path also happens to make the tool feel instant in the place where beginners start.\n\nThe ceilings, stated plainly because they are real. Background concurrency sits at 5 on the current vendor plan, where the architecture had targeted 10 to 30; that cap is a billing tier, not a design property, but today it is the number. The spend cap is checked when a job is enqueued, not mid-flight, so a manager standing at the cap can overshoot it on a single multi-audience campaign. Generation progress reaches the browser by polling every 1.5 seconds rather than streaming. And admins can observe everything while mutating nothing, which is enforced the boring, reliable way: the write methods do not exist in the admin data-access layer, and a runtime test asserts they never appear.\n\nWe cannot show business results yet. The acceptance gate for launch is stakeholder sign-off on 10 sample sequences spanning the audiences and all 7 languages. Usage logging is built into every generation precisely so the next version of this write-up can report real reply rates, real per-sequence cost, and which audiences the fan-out design actually helps.\n\n## The transferable part\n\nIf a channel sits dormant in your company even though the tools are licensed and the will exists, run the diagnosis before buying anything else: is the missing layer infrastructure, or expertise? The vendors sell the first. If your people cannot evaluate the output, the gap is the second, and a tool that assumes a skill your people do not have is a cost, not a capability.\n\nAnd if you do encode the expert into a pipeline, the shape that worked here generalises to most operational AI we build:\n\n1. Let the model do the research and the drafting, where breadth beats judgement.\n2. Put one human gate exactly where judgement matters, and design it for active review: reveal the risky field deliberately, keep everything editable, make approve-with-edits the easy path.\n3. Make the last mile deterministic. Whatever step must never be wrong should not be probabilistic at all: closed token sets, validation at every boundary, and a function that throws rather than guesses.\n\n## Common questions\n\n**Why not use the AI writer built into Smartlead or Instantly?** Those writers assume the operator can already judge audience strategy, structure and copy quality. GoStudent's centre managers could not, which was the actual gap. This tool owns strategy and drafting end to end, then exports to whatever sender each manager already uses, so no sending infrastructure gets replaced.\n\n**What does the human gate actually approve?** The persona research: audience description, buying context, the hedged affordability band, and tone. The approve button stays disabled until all four fields have been seen, every field is editable inline, and generation only runs from a persona a human has accepted or corrected.\n\n**Could this pattern work outside tutoring?** The shape is not tutoring-specific: model research, one human gate where judgement matters, deterministic injection for the step that must never be wrong. Prompts, languages, audiences and sender-variable mappings live in configuration rather than code, so adapting it is mostly configuration work.\n\nA system built this way is quiet. It sends nothing, and its best moment is a centre manager exporting a campaign they could not have written and did not have to. Most of the operational AI we build ends up with this shape, and we have come to treat that as a good sign.\n\nantonio@brutal.ai reads every reply.\n",
  "frontmatter": {
    "title": "Building an outreach sequencer for managers who don't write copy",
    "slug": "outreach-sequencer",
    "description": "Cold email sat dormant across GoStudent's 100-plus tutoring centres. The missing layer was expertise, not tooling. Here is how we built the copywriter into a pipeline.",
    "archetype": "build-story",
    "solution_id": "gostudent-outreach-sequencer",
    "pillar": "workflow-automation",
    "reader": "technical-peer, readable by coo-ops-leader",
    "language": "en",
    "anonymisation_level": "L0",
    "publish_date": "",
    "canonical": "",
    "internal_links": [
      "semantic-layer"
    ],
    "key_takeaways": [
      "Sending tools assume a competent operator: they provide infrastructure, while the missing layer is usually expertise.",
      "Encode the expert as a pipeline: model research, one human gate where judgement matters, then a deterministic last mile for the step that must never be wrong.",
      "A reputationally dangerous model output gets a structural fence, not a politer prompt: hedged bands, schema-validated at two boundaries, surfaced only inside the approval gate.",
      "The model never writes sending-tool syntax; an injection function substitutes it and throws on unknown tokens, which turns zero wrong tokens into a contract instead of a hope."
    ],
    "sources": [
      "01-intake/examples/filled-intake-B.md"
    ],
    "visual_briefs": [
      "gostudent-sequencer-v1"
    ],
    "cta_variant": "plain-address",
    "opening_move": "what-we-built",
    "skeleton": "build-story",
    "register": "v2-engineering-essay",
    "target_query": "how to build an AI cold email tool for non-marketers",
    "author": "Antonio Marques, Brutal AI",
    "updated": "",
    "external_citations": [
      "https://arxiv.org/abs/2509.08514"
    ],
    "faq": [
      {
        "q": "Why not use the AI writer built into Smartlead or Instantly?",
        "a": "Those writers assume the operator can already judge audience strategy, structure and copy quality. GoStudent's centre managers could not, which was the actual gap. This tool owns strategy and drafting end to end, then exports to whatever sender each manager already uses."
      },
      {
        "q": "What does the human gate actually approve?",
        "a": "The persona research: audience description, buying context, the hedged affordability band, and tone. The approve button stays disabled until all four fields have been seen, every field is editable inline, and generation only runs from a persona a human has accepted or corrected."
      },
      {
        "q": "Could this pattern work outside tutoring?",
        "a": "The shape is not tutoring-specific: model research, one human gate where judgement matters, deterministic injection for the step that must never be wrong. Prompts, languages, audiences and sender-variable mappings live in configuration rather than code, so adapting it is mostly configuration work."
      }
    ]
  },
  "jsonld": {
    "@context": "https://schema.org",
    "@graph": [
      {
        "@type": "Article",
        "headline": "Building an outreach sequencer for managers who don't write copy",
        "description": "Cold email sat dormant across GoStudent's 100-plus tutoring centres. The missing layer was expertise, not tooling. Here is how we built the copywriter into a pipeline.",
        "inLanguage": "en",
        "author": {
          "@type": "Person",
          "name": "Antonio Marques, Brutal AI"
        },
        "publisher": {
          "@type": "Organization",
          "name": "Brutal AI",
          "url": "https://brutal.ai",
          "sameAs": [
            "https://www.linkedin.com/company/brutal-ai"
          ]
        },
        "wordCount": 2546
      },
      {
        "@type": "FAQPage",
        "mainEntity": [
          {
            "@type": "Question",
            "name": "Why not use the AI writer built into Smartlead or Instantly?",
            "acceptedAnswer": {
              "@type": "Answer",
              "text": "Those writers assume the operator can already judge audience strategy, structure and copy quality. GoStudent's centre managers could not, which was the actual gap. This tool owns strategy and drafting end to end, then exports to whatever sender each manager already uses."
            }
          },
          {
            "@type": "Question",
            "name": "What does the human gate actually approve?",
            "acceptedAnswer": {
              "@type": "Answer",
              "text": "The persona research: audience description, buying context, the hedged affordability band, and tone. The approve button stays disabled until all four fields have been seen, every field is editable inline, and generation only runs from a persona a human has accepted or corrected."
            }
          },
          {
            "@type": "Question",
            "name": "Could this pattern work outside tutoring?",
            "acceptedAnswer": {
              "@type": "Answer",
              "text": "The shape is not tutoring-specific: model research, one human gate where judgement matters, deterministic injection for the step that must never be wrong. Prompts, languages, audiences and sender-variable mappings live in configuration rather than code, so adapting it is mostly configuration work."
            }
          }
        ]
      },
      {
        "@type": "BreadcrumbList",
        "itemListElement": [
          {
            "@type": "ListItem",
            "position": 1,
            "name": "Blog",
            "item": "https://brutal.ai/blog"
          },
          {
            "@type": "ListItem",
            "position": 2,
            "name": "Building an outreach sequencer for managers who don't write copy"
          }
        ]
      }
    ]
  },
  "derivatives": "# derivatives: outreach-sequencer\n\nDrafts only; nothing auto-posts. Numbers trace to `filled-intake-B.md`.\n\n## linkedin\n\n### draft 1: closer\nCold email didn't fail at GoStudent's 100-plus tutoring centres for lack of tooling.\n\nIt failed for lack of a copywriter. Managers tried the channel, produced sequences they couldn't judge, and quietly gave up. The licences were fine. The words were the problem.\n\nEvery tool in the standard stack (Smartlead, Instantly, Lemlist, Apollo, Clay) assumes a competent operator. It hands you infrastructure. The missing layer was expertise.\n\nSo instead of another sending platform, we built the copywriter into a pipeline: AI research, one human approval gate, generation, and a deterministic last mile for the part that must never be wrong.\n\nThe full build story, including the feature that could have ended up in a newspaper:\n\n{{POST_URL}}\n\n### draft 2: architect\nThe most important function in this build throws exceptions on purpose.\n\nMerge fields must come out in each manager's exact sending-tool syntax. One wrong token breaks a campaign inside the one tool a non-technical manager can't debug.\n\nSo the model never writes tool syntax. It emits canonical markers only. A pure function substitutes the manager's real syntax at the end, and on any unknown token it throws. Zero wrong tokens becomes a contract instead of a hope.\n\nSame philosophy on the risky part: persona research wanted a \"likely income\" field. It became a hedged affordability band, schema-validated at two boundaries, visible only inside the human approval gate.\n\nDraft with a model. Approve with a human. Make the last mile deterministic.\n\n{{POST_URL}}\n\n### draft 3: operator\nThe persona brief for this tool was one blunt sentence: someone who struggles to connect WhatsApp Web to a phone.\n\nThat person runs a tutoring centre. Outreach is one duty among ten. Every sending tool on the market assumes they can write audience strategy, personas, copy and token syntax in their local language. They can't, and they shouldn't have to.\n\nThe system we built makes them the editor, not the author. Their whole job: describe the centre once, pick an audience, approve the research, read the emails, export to their own Drive.\n\nThe interface even gets quieter as they get competent: coaching that's dismissible and state-aware, because help on run 1 must not patronise on run 50.\n\nHow it works, and what it deliberately refuses to do:\n\n{{POST_URL}}\n\n## newsletter\n\n**Subject:** The tools were fine. The copywriter was missing.\n\n**Body:**\nGoStudent's offline network of 100-plus centres had every sending tool and a dormant cold-email\nchannel. The gap was never infrastructure: centre managers, non-marketers with ten other\nduties, couldn't produce or judge the sequences the tools assumed they could. We built the\nmissing expertise into a pipeline: AI research, one human approval gate, and a merge-field\ninjector that throws on any token it doesn't recognise, so campaigns can't silently break.\nThe build story, including its near-miss with a reputational landmine: {{POST_URL}}\n\n## sales snippet\n\nIf a channel sits dormant in your company even though the tools are paid for, the missing layer\nis probably expertise, not software. We build that layer in: AI drafts grounded in research, one\nhuman gate where judgement matters, and a deterministic last mile so the step that must never be\nwrong cannot be. Managers keep the tools they already use.\n\nmetric: template path under 100 ms, one database transaction, zero model calls (measured in build)\n\n## x thread\n\n1. GoStudent: 100+ tutoring centres, every sending tool licensed, cold email dead. The missing piece wasn't software. It was a copywriter.\n2. The user persona, verbatim from the build docs: someone who struggles to connect WhatsApp Web to a phone. Now ask them for a 5-step sequence in their local language with correct merge tokens.\n3. Smartlead, Instantly, Lemlist, Apollo, Clay: all assume a competent operator. Infrastructure was never the gap. Expertise was.\n4. So the build inverted: no sending, managers keep their tools. AI persona research → one mandatory human gate → generation → deterministic merge-field injection → export to their own Drive.\n5. The dangerous part: research wanted \"likely monthly income\". It shipped as a hedged affordability band, schema-validated at two boundaries, shown only inside the approval gate. Structure beats politeness.\n6. The trustable part: the model never writes tool syntax. It emits canonical markers; a pure function injects the real syntax and THROWS on unknown tokens. A contract, not a hope.\n7. Honest limits: business results not yet measured; sign-off gate is 10 samples across 7 languages; concurrency capped at 5 by the vendor plan. Design truths today, numbers next. {{POST_URL}}\n\n## stage-10 notes (working)\n\n- one-sentence-paragraph soft warnings accepted: social hook lines by design.\n",
  "exportedAt": "2026-07-27T16:32:42.733Z"
}