Systems Lab

Agent skill

outreach-expert

Advises on outreach setup up to (and only up to) the send button: domain and mailbox strategy, SPF/DKIM/DMARC, warmup, sender rotation, deliverability diagnosis, bounce handling and sequence hygiene.

activeSelf-containedDeclared tools3,399 words

Filed under Outbound email.

From richapiai/gtm-skills · 34 skill entries · 0 · pushed 2026-09-18

What it does when it runs

Advises on outreach setup up to (and only up to) the send button: domain and mailbox strategy, SPF/DKIM/DMARC, warmup, sender rotation, deliverability diagnosis, bounce handling and sequence hygiene. Use when asked "my emails go to spam", "how do I warm up a domain", "SPF DKIM DMARC", "how many mailboxes", "sender rotation", "how many steps in the sequence", "bounces are climbing", or "review my sending setup". It never sends, warms, or configures anything — sending execution is outside this pack permanently. (richapi-gtm)

Automated analysis of the skill and the 0 files bundled beside it. A skill’s own description is written to be selected by an agent, so it describes the job and not the dependencies.

Keys and connectors you must supply
None found.
Hosts it reaches
No third-party host appears in the skill or its bundled files.
Tool permissions it declares
  • Bash(richapi-skills-preflight:*)
  • Read
Actions present in the files
shell

Ask about outreach-expert

Opens your assistant with this page's verified links already in the prompt.

Is this safe to install?ClaudeChatGPT
Adapt it to my stackClaudeChatGPT
What else do I need for it to workClaudeChatGPT
Rather ask a human? Talk to Cheetah
git clone --depth 1 --filter=blob:none --sparse https://github.com/richapiai/gtm-skills.git /tmp/gtm-skills
git -C /tmp/gtm-skills sparse-checkout set "skills/outreach-expert"
mkdir -p ~/.claude/skills/outreach-expert
cp -R "/tmp/gtm-skills/skills/outreach-expert/." ~/.claude/skills/outreach-expert/

Picked up without a restart. A project skill of the same name is shadowed by your personal one. For one repository only, swap ~/.claude/skills for .claude/skills. Claude Code docs ↗

Or take the whole library

This repo ships a .claude-plugin manifest, so Claude Code can install all 34 skills at once. Plugin skills are invoked as /<plugin>:<skill>, so they never collide with your own.

/plugin marketplace add richapiai/gtm-skills
/plugin

The folder is the same in every client that implements the format — 46 of them — so if yours is not above, only the destination changes.

Reproduced in full from richapiai/gtm-skills/blob/c1a5d5881be89b65b155d772aef4b491aef3354e/skills/outreach-expert/SKILL.md, which is licensed MIT (repository). 3,399 words, 17 headings.

Outreach setup — everything up to the send button

A bad sending configuration does not fail loudly. It burns a domain: reputation decays over weeks, replies stop arriving, and by the time anyone notices, the fix is buying new domains and waiting out a warmup. That is an expensive, slow, entirely preventable failure, and preventing it is what this skill is for.

What it is not for is sending. Read the next section before anything else, because the gap it describes is permanent and this skill is useless if a user misreads it.

The one thing this skill cannot do, and never will

It does not send. Nothing in this skill causes an email to leave. There is no sending endpoint in _lib/api-catalog.json — every endpoint in this pack reads data; none of them delivers a message. That is deliberate and it is permanent. The README lists sending execution under External forever, for a reason worth restating in full: owning sending means owning spam complaints. A data API that also sends inherits every customer's list hygiene, and one bad sender takes down the shared reputation of everyone else on it.

That same section puts four more things permanently outside this pack, and all four are things an outreach advisor gets asked for:

  • Inbox hosting. The pack does not create, own or operate mailboxes.
  • Warmup execution. Warmup is sending. This skill can tell you what a ramp should look like; it cannot run one, and no part of this pack can.
  • LinkedIn actions — profile views, connection requests, DMs. ToS risk, and out permanently. An earlier version of this skill claimed the pack could drive the LinkedIn half of a multi-channel play "when paired with the automation layer". There is no automation layer, there never was one in this pack, and that sentence is the reason this section is this long.
  • Dialer and live calling, and direct mail.

So this skill produces decisions, checks and a written setup review. Every one of them is executed by the user, inside their own sending tool, under their own domain reputation. Say that at the end of every session rather than letting a confident plan imply it has been put into effect.

What it spends

Nothing. This skill owns no endpoints — _lib/endpoint-owners.yaml assigns it none, which is right: deliverability advice is reasoning, and the two data checks that genuinely help before a send already belong to skills that own them and price them. It makes zero paid calls. Law 3 asks that every paid call be named and costed before it runs; naming none is how this skill satisfies it.

The pack's real pre-send contributions, and who owns them:

CheckOwner
Verify each address before it is ever mailed/enrich-waterfall — the email_verifier hop
Separate role, free and disposable addresses/list-hygiene — identify_email_type
Drop dead domains before they bounce/list-hygiene
Decide the list may be contacted at all/comply

Route to those. Do not re-implement them here, and do not describe their cost — the catalog is the source of truth for that and it changes.

Inference mode — local, always

Mode: local inference only. Zero LLM hops.

ai_enrich is not in this skill's endpoint set and never will be. Reading a DMARC record, spotting that a subject line has three brackets in it, or noticing that a sequence has no break-up step is reasoning over text in front of you, and this pack already runs inside a model that does that for free. Paying an endpoint to re-read a sentence you were handed is the waste local inference exists to stop.

Neither permitted exception reaches this skill. Perplexity web grounding does not apply: a live deliverability question is answered by the user's own sender dashboards and DNS, not by a web search — and where a vendor's current documentation genuinely is the answer, the honest move is to tell the user to read it. Batch scale does not apply: there is no per-row work here at all. A sending setup is one configuration, not a list.

Before anything else

richapi-skills-preflight
  • API_KEY_SET: no — not a blocker. No paid call happens in this skill. Say so rather than sending the user off for a key.
  • SUPPRESSION: STOP — not a blocker for the advice, and a hard blocker for the send. A suppression check that could not run is not a passing check (law 5). If the user is about to configure a real campaign, ./setup now is cheaper than discovering it at launch.
  • CATALOG_OK: no — regenerate with richapi catalog gen before naming any endpoint, even in passing. An endpoint name should be read, never recalled.

Step 1 — name which of the six questions this is

Outreach questions arrive tangled. Answer the load-bearing one first and stack the rest; a reply that covers all six covers none.

BucketSounds like
Infrastructurenew domain, mailbox count, SPF/DKIM/DMARC, tracking domain, rotation
Deliverability diagnosis"we're in spam", replies dried up, bounces climbing
Sequence hygienehow many steps, what cadence, when to stop, break-up
Copysubject lines, first lines, merge tags and their fallbacks
Tool selectionwhich sending platform, what to look for in one
Complianceunsubscribe, consent, records. Route it — see below

Step 2 — infrastructure, in dependency order

Infrastructure is the only part of outreach where the ordering is not a matter of taste. Each item below is a precondition for the one after it, and doing them out of order wastes the warmup.

  1. Sending domains are separate from the primary domain. A blocklisting on the company's main domain takes support, billing and inbound sales with it. Cold sending happens from lookalike domains that can be abandoned.
  2. Authentication is complete on every sending domain before a single message goes out. SPF must list every service that sends as the domain, and only those. DKIM must be published and verifiable — dig txt <selector>._domainkey.<domain> is the check, and running it is the difference between believing it works and knowing. DMARC starts in monitoring mode (p=none) with a reporting address someone reads, moves to p=quarantine once the reports are clean, and never starts at p=reject on a live domain.
  3. Click tracking uses a dedicated tracking domain, not the sending platform's shared one. On a shared tracking host your links inherit the reputation of everyone else using it, and you cannot see or influence that.
  4. Then, and only then, warmup. Warming an unauthenticated domain teaches the receivers nothing except that an unauthenticated domain is sending.
  5. Volume scales by adding mailboxes, never by raising per-mailbox volume. Rotation distributes a day's sends across mailboxes so that no single one exceeds a safe rate. At the very top that rate is 50 (gates.yaml:skills.outreach_expert.max_sends_per_mailbox_per_day), and step 5 says where the number comes from and how much to trust it. Mailboxes needed is daily volume divided by that ceiling, rounded up, with the per-mailbox figure kept well under it on anything new.

Step 3 — the metrics that decide whether to keep sending

Open rate is not one of them. Since Apple Mail Privacy Protection began prefetching tracking pixels, open rate measures Apple's prefetcher on any list with a meaningful share of Apple clients, which is most B2B lists. Optimising it optimises a proxy for nothing.

Four numbers matter, and the pack has an opinion about three of them:

SignalWhere the threshold lives
Positive reply rateThe hero metric. No pack threshold; it is a target, not a gate
Hard bounce rategates.yaml:quality_stops.verification_max_hard_bounce_pct
Verification fail rate on the source listgates.yaml:quality_stops.verification_max_fail_rate_pct
Spam complaint rategates.yaml:skills.outreach_expert.spam_complaint_max_pct, measured on the receiver's own postmaster tooling and nowhere else

The first two gate keys are not decoration: they are the same thresholds /campaign-review enforces before /launch will write anything. A list that fails them is not a deliverability problem to be tuned around — it is a sourcing problem, and continuing to send it is how a domain gets burned to prove a point that was already proven.

Step 4 — diagnosing a live deliverability problem

Cheapest check first, because the cheap ones are also the most common causes.

  1. Authentication. Re-verify SPF, DKIM and DMARC on the domain that is actually sending, not the one that was set up. A service added later that is missing from SPF is the single most common cause.
  2. Blocklists. Check the sending domain and the sending IPs.
  3. List quality. Re-run /list-hygiene over the list. If the hard-bounce rate is over gates.yaml:quality_stops.verification_max_hard_bounce_pct, stop sending it; nothing about the sending configuration will fix a bad list.
  4. Warmup state. Read the sender's own warmup dashboard. A ramp that was paused and never resumed looks exactly like a healthy one in every other view, and a ramp shorter than gates.yaml:skills.outreach_expert.warmup_min_days has not finished however healthy it looks.
  5. Send rate per mailbox. Divide yesterday's volume by the number of live mailboxes and compare it with gates.yaml:skills.outreach_expert.max_sends_per_mailbox_per_day. Rotation makes a total look fine while one mailbox carries most of it.
  6. Reputation at the receiver. Google Postmaster Tools and Microsoft SNDS report what the receiver actually thinks, which is the only opinion that decides delivery.
  7. Only then, copy and content. Modern filters are statistical, not keyword lists, so the old spam-word folklore is mostly cargo cult. What genuinely still hurts: tracked links on first contact, image-heavy HTML, URL shorteners, attachments on a cold first message, and a display name that does not match the reply-to domain.

If the answer is "pause and re-warm", say that plainly. It is a slow, boring, correct answer and users talk themselves out of it because it costs weeks.

Step 5 — the four numbers this skill refuses to hand-type, and reads from a key

An outreach advisor wants to say "warm for this many days" and "cap each mailbox at this many sends a day". This skill says both, and it says neither from memory: the values live in _lib/gates.yaml under this skill's namespace, where one edit updates every reader and every number carries its source, the date it was last checked, and its confidence.

RuleValueKey
Per-mailbox daily ceiling50 sends per mailbox per daygates.yaml:skills.outreach_expert.max_sends_per_mailbox_per_day
Warmup minimum21 days of ramp before real trafficgates.yaml:skills.outreach_expert.warmup_min_days
Spam complaint ceiling0.1% of delivered mailgates.yaml:skills.outreach_expert.spam_complaint_max_pct
Unsubscribe ceiling1% of delivered mailgates.yaml:skills.outreach_expert.unsubscribe_max_pct

Why these are values when a credit price may never be one. Law 1 forbids a hand-typed number because prices reprice quarterly — the pack's own proof is phone_finder, which repriced more than eight-fold inside four months, and the catalog is the only place its cost may be read. That is an argument about volatility, and it does not carry to receiver policy: per-mailbox send ceilings, warmup ramps and complaint thresholds are conventions revised on a scale of years, and the bulk-sender requirements that reset the field landed once, in early 2024. So the file holds them as numbers, and law 1 still holds where it was aimed — not one credit number appears in this skill.

What that does not buy is certainty, and the honest caveat survives the numbers. This skill executes nothing; every figure above is advice the user applies inside their own sending tool, under their own domain reputation. Only one of the four has a published receiver source (the complaint ceiling, from the bulk-sender requirements and readable only in the receiver's own postmaster tooling). The other three are platform convention, pinned at the conservative end of their range. So state the number, name the key it came from, and tell the user to check it against the current published guidance of the platform they actually send from — that guidance wins, in both directions. A confident wrong number here costs a domain.

Step count and spacing are not on that list on purpose. Those belong to /sequence-builder, which owns the cadence and holds its own keys under its own namespace. Two skills carrying the same threshold under two names is how one of them silently goes stale.

Step 6 — sequence hygiene, which is not sequence design

/sequence-builder designs the cadence: how many steps, how far apart, on which channel, and what each step is for. Do not redesign it here. What belongs here is the narrow set of sequence properties that decide whether the messages arrive at all:

  • Plain text on first contact. Signatures, images and tracking pixels on a cold first message are a deliverability cost paid for a reporting benefit that Apple Mail Privacy Protection already destroyed.
  • Tracking off, or on a dedicated domain, for step one. Same reasoning as step 2.
  • Every merge tag has a fallback. An empty merge in a subject line is the clearest possible signal that nobody read this before it went out. Validate that the list has a value for every tag before the campaign is configured — /list-hygiene is where that check lives.
  • A defined end. A cadence with no last step keeps mailing people who have already decided, and their complaints are what the receiver measures.
  • Reply handling is staffed. A campaign nobody answers produces complaints instead of meetings, and complaints are the metric that closes a domain.

Personalisation depth should match deal size rather than ambition, and /personalize owns that decision and the evidence behind it.

Compliance is a gate, and it is not this skill

Do not restate compliance rules here. /comply is the gate; it returns a verdict and a stop from it ends the run. The regimes it has rule sets for are exactly gates.yaml:skills.comply.jurisdictions, and a jurisdiction with no rule set is a refusal, not a pass.

Three points are genuinely sender-configuration questions and belong here:

  • Every cold message needs a working unsubscribe path. CAN-SPAM requires an opt-out request be honoured within 10 business days.
  • An unsubscribe must suppress across the whole account, not one sequence. Feed it back into the pack's suppression store or the next list will re-import them.
  • A one-click list-unsubscribe header is now effectively mandatory for bulk senders at the large receivers. It is a sender setting; check it is on.

Anything else (consent basis, records, retention) route to /comply. Neither skill is legal advice. This one enforces nothing at all; it advises, and a regulator reads the statute rather than this file.

Step 7 — report what was decided, and what did not happen

Close every session with both halves:

  • Decided: the domain and mailbox plan, the authentication state, the metrics being watched and their thresholds, the sequence changes.
  • Not done: no DNS record was changed, no mailbox was created, no warmup was started, no message was sent, and nothing was configured in any sending tool. Those are all the user's to perform.

If a campaign is genuinely ready to go out, the route is /campaign-review for the verdict and then /launch, which writes the file the sending tool reads — and only against a PASS verdict no older than gates.yaml:skills.campaign_review.verdict_max_age_hours. This skill does not write that file and must not be asked to.

Step 7b — the standing rules the user has already set

Before advising, read gtm/preferences.jsonl for sequence-scoped rules and gtm/profile.yaml for sender. Advice that contradicts a decision the user already made and recorded is advice they have to spend a turn rejecting, and it erodes trust in everything else in the session.

Where a standing rule and this skill's recommendation genuinely conflict, say so explicitly — name the rule, name the recommendation, and let the user decide. Do not quietly follow the rule, and do not quietly override it. A recorded decision deserves an argument, not a silent edit.

unreadable is a STOP. absent is normal and not worth more than a sentence.

Step 8 — check what the stack can already reach

Advice the user cannot execute is advice that does not land. Once the recommendations exist, work the ladder in docs/destination-handoff.md against the tools named in them:

  1. An MCP server for the sender, the DNS provider or the inbox provider, available in this session. If the DNS provider is reachable, the SPF/DKIM/DMARC records in Step 2 stop being a checklist the user retypes and become something they can verify in place. Name the tool and ask; do not change a DNS record because you can.
  2. The provider's API docs or Postman collection. For a deliverability diagnosis this is often the fastest route to the number that settles it — bounce classification, per-domain reputation, sending limits.
  3. Neither. Give the manual path, which for DNS and warmup is the normal one anyway, and say what you checked.

Nothing here moves the send button. This skill's boundary is unchanged: it advises up to the send and never sends, and an available integration does not extend that.

What this skill will not do

  • It will not send anything, ever. No endpoint in this pack delivers a message. Sending execution is External forever because owning sending means owning spam complaints. Every plan produced here is executed by the user in their own tool.
  • It will not warm a domain or a mailbox. Warmup is sending. It can describe a ramp; it cannot run one.
  • It will not host, create or configure an inbox, and it will not touch DNS. It tells the user which records to check and how to check them.
  • It will not take a LinkedIn action. Profile views, connection requests and DMs are out permanently on ToS grounds. Any earlier claim that this pack automates them was wrong.
  • It will not dial anyone or post physical mail. Both are permanently out.
  • It will not design the sequence. Step count, spacing and channel belong to /sequence-builder. This skill only rules on the parts of a cadence that decide whether the messages are delivered.
  • It will not write the sender export. /launch is the sole writer of that artifact, bound to a PASS verdict and the list's content hash. A second writer would make every review upstream of it advisory.
  • It will not clear a list for sending. /comply does that and can refuse a campaign this skill helped design.
  • It will not spend credits. It owns no endpoints and makes no paid calls.
  • It will not type a warmup ramp, a per-mailbox volume or a complaint threshold from memory. Those four values live in _lib/gates.yaml under this skill's namespace and are read from there, with the key named alongside every one of them.
  • It will not present those four as settled fact. Three of them are platform convention pinned at the conservative end of a range, not published receiver policy, and the pack cannot measure any of them. The current guidance of the platform the user sends from outranks this file, and the skill says so every time it quotes one.

Related

  • /list-hygiene — normalisation, dead domains and address typing; the cheapest deliverability work there is
  • /enrich-waterfall — finds and verifies the addresses, with a dry-run plan and a per-hop cost
  • /comply — the hard gate on whether a contact may be contacted
  • /campaign-review — the verdict a list needs before any outbound artifact exists
  • /launch — the sole writer of the sender-format export, and the last point at which the pack can still refuse
  • /sequence-builder — owns the cadence itself: step count, spacing, channel and the sender-native copy skeleton
  • /personalize — how much personalisation the deal size actually justifies
  • /measure — reads what came back, once the user has the campaign running in their own tool
  • /crm-sync-expert — the storage-side counterpart: mapping, dedupe keys and what a CRM silently damages, also advisory
  • /richapi-gtm — the router and the session receipt
  • The stated boundary, in full: ../../ROADMAP.md

Other skills for the same job

Different authors, same problem. Matched on the words in the skill name, across every library in the catalogue except this one.

Need help setting it up?

This page tells you what outreach-expert does and what it needs. Cheetah builds the agent setup it runs inside: data, CRM, sequencing and the guardrails.

Book a call →

The directory stays free. There is nothing gated behind this.