# Outreach Enrich Company

> ALWAYS invoke when the user wants to deepen the dossier on a company card AND/OR generate LinkedIn/email outreach letters from it. Fans out 5 enrichment subagents (news, tech, growth, reputation, contacts) to fill gaps left by the base research, then drafts and naturalizes one letter per Key Contact. Triggers - "enrich <card>", "go deeper on <card>", "deepen research on <company>", "write outreac…

- **Type:** Skill
- **Install:** `agentstack add skill-doctormozg-claude-pipelines-outreach-enrich-company`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [DoctorMozg](https://agentstack.voostack.com/s/doctormozg)
- **Installs:** 0
- **Category:** [Communication](https://agentstack.voostack.com/c/communication)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [DoctorMozg](https://github.com/DoctorMozg)
- **Source:** https://github.com/DoctorMozg/claude-pipelines/tree/master/plugins/mz-biz-outreach/skills/outreach-enrich-company

## Install

```sh
agentstack add skill-doctormozg-claude-pipelines-outreach-enrich-company
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Outreach Enrich Company

## Overview

You are an orchestrator that takes a company card produced by `/outreach-research` and does two things, in this order:

1. **Deepen the dossier**. Fan out five specialist enrichment subagents in parallel — `outreach-news-finder`, `outreach-tech-analyst`, `outreach-growth-analyst`, `outreach-scanner`, `outreach-contact-finder` — each instructed to find data **not already in the card** (gap-filling, not duplicating). Their findings are merged into a new `## Deeper Intelligence` section appended to the card.
1. **Draft outreach letters**. Using the original card data plus the deeper intelligence as personalization fuel, draft one letter per named Key Contact via `expert-copywriter` — each subtly calibrated to the contact's inferred communication style (Social Styles, produced grounded-only by `outreach-personality-profiler`) — then mandatorily naturalize each via `expert-naturalizer`. The letters are appended as a `## Outreach Letters` section inside the card.

The whole pipeline is fully automatic — no approval gates, no mid-run prompts. The user invokes the skill, the skill enriches and writes letters, the card now holds them both.

## When to Use

Invoke when the user has a company card (produced by `/outreach-research`, lives at `.mz/outreach//companies/.md`) and wants either richer company intelligence, outreach letters, or both. Trigger phrases:

- "enrich `.mz/outreach/.../companies/.md` and write letters"
- "deepen the research on this card"
- "go deeper on `` and draft outreach"
- "write outreach letters for ``"
- "generate letters from this card"

### When NOT to use

- The user has only a company name or domain and no card — run `/outreach-research` first (single-company mode if they want only one).
- The user wants to discover companies first — use `/outreach-research`.
- The user wants recruiter contacts for a job application — use `/job-recruiter-info` in mz-job-outreach.
- The user wants general marketing copy (landing pages, announcements, social) — use `/copywrite` from mz-creative.
- The user wants letters written to a separate location than the card — this skill only writes back into the card.

## Input

- `$ARGUMENTS` — Required: an absolute or repo-relative path to a company card `.md` file. Two accepted shapes:
  - **Research baseline**: `.mz/outreach//companies/.md` — direct output of `/outreach-research`. First activation moves it to `active/`.
  - **Active**: `.mz/outreach/active/_.md` — a card already activated by this skill or `/outreach-update-card`. The date prefix is the last interaction date; this run updates it to today.
- Optional modifiers (case-insensitive, order-independent):
  - `channels:email|linkedin|both` — overrides per-contact channel auto-detection. Default: best channel per contact (email if known, else LinkedIn DM, else skip).
  - `sender:` — overrides the sender voice. Inline text becomes the voice description; a path is read as a sender bio markdown file. Default: read `/strategy.json` `sender_voice` field if present.
  - `enrich:only` — run the deep-enrichment phase and skip letter drafting (card gets `## Deeper Intelligence` but no `## Outreach Letters`).
  - `enrich:skip` — skip the deep-enrichment phase and draft letters directly from the existing card content only.
  - `brief:` — pull the local business-climate dossier from an `outreach-brief` run; the combo matching the card's sector and location seeds the letters with regional-climate angles. Default: unset (company data only).
  - `personality:off` — disable reader-style calibration entirely (skip the Phase 3 profiling wave; letters use neutral structure). Default: on — role-based priorities always shape the leading angle, and footprint profiling runs automatically when a contact has a usable public profile.
  - Default (neither flag): both phases run.

If `$ARGUMENTS` is empty or no source can be resolved (see Source Resolution below), emit `STATUS: BLOCKED` with a clear message and stop.

## Argument Parsing

Extract from `$ARGUMENTS`:

- **user_path** — the path token (everything not matching a parameter pattern). Must end in `.md`.
- **channels_override** — from `channels:` (default: unset → per-contact auto-detect).
- **sender_override** — from `sender:` (default: unset → use strategy.json or fallback voice).
- **enrich_mode** — from `enrich:`: `only`, `skip`, or unset (default unset = both phases run).
- **brief_run** — optional, from `brief:`; resolves to `.mz/outreach//climate.json` (default: unset).
- **personality_mode** — from `personality:`: `off` disables reader-style calibration; any other value or absent = `on` (default).

### Source resolution

Extract the company slug from `user_path`'s basename:

- If the basename matches `_.md` (active path), `company_slug` = the part after the date prefix.
- Otherwise (`.md`), `company_slug` = the basename minus `.md`.

Then resolve `source_path` (the file actually read and updated by this run):

```bash
mkdir -p .mz/outreach/active
find .mz/outreach/active -maxdepth 1 -type f \
  -name '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]_.md' 2>/dev/null | head -1
```

- **If found** → `source_path` = the active path returned. The user-supplied path is ignored in favor of the active version (which holds the canonical accumulated history). The user may have passed a now-deleted research-baseline path; the active version is authoritative.
- **If not found** → `source_path` = `user_path`. The card has not been activated yet; this run will activate it.

Validate the card at `source_path` before any other work:

1. The file exists (Read succeeds).
1. The first non-empty line starts with `# ` (H1 = company name).
1. The body contains H2 headers matching the canonical card shape — at minimum `## Overview`, `## Key Contacts`, `## Outreach Recommendation` must all be present. If any are missing, emit `STATUS: BLOCKED` with the list of missing headers.

## Directory Structure

- **State** — `.mz/task//state.md`. Source of truth across phases.
- **Card snapshot** — `.mz/task//card_parsed.json`. Structured extract of the source card, consumed by the deep-enrichment subagents in Phase 2 so they know what is ALREADY documented.
- **Enrichment artifacts** — `.mz/task//enrichment/.json`. One JSON per Phase 2 subagent (`news.json`, `tech.json`, `growth.json`, `reputation.json`, `contacts.json`).
- **Briefs** — `.mz/task//briefs/.json`. One brief per contact selected for drafting.
- **Profiles** — `.mz/task//profiles/.json`. One reader-style read per profiled contact (Social Style or role-priorities, evidence, confidence, calibration directive), written by `outreach-personality-profiler` in Phase 3 and merged into the briefs. Absent when `personality:off`.
- **Drafts** — `.mz/task//drafts/_.md`. One draft file per (contact, channel) pair. Each draft carries YAML frontmatter (`subject`, `channel`, `recipient`) followed by the body.
- **Card lifecycle** — the card ends this run at `target_path = .mz/outreach/active/_.md`. If `source_path != target_path`, the source file is deleted in the final card-rewrite phase (move semantics). Research-baseline cards at `.mz/outreach//companies/.md` and stale-dated active cards (`active/_.md`) are removed by this run.

`task_name` follows `_outreach_enrich_` where `` is derived in Source Resolution (slug without date prefix or `.md`). Same-day collisions append `_v2`, `_v3`.

`` = the directory containing `source_path` when the card is still at its research-baseline location (typically `.mz/outreach//companies/`). The sibling `strategy.json` lives at `/../strategy.json` — read it from there for sender voice and outreach angles. When `source_path` is already an active path, `` falls back to the most-recently-modified `.mz/outreach//` directory containing a `strategy.json` (or `default` voice if none can be located).

## Core Process

### Phase Overview

| #   | Phase                             | Agent(s)                                                                                                                  | Details                        |
| --- | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | ------------------------------ |
| 0   | Setup + card validation           | — (orchestrator)                                                                                                          | Inline below                   |
| 1   | Parse card + light web enrichment | — (orchestrator + WebSearch)                                                                                              | Inline below                   |
| 2   | Deep enrichment via subagents     | `outreach-news-finder`, `outreach-tech-analyst`, `outreach-growth-analyst`, `outreach-scanner`, `outreach-contact-finder` | `phases/deep_enrichment.md`    |
| 3   | Reader profiling + draft letters  | `outreach-personality-profiler`, `expert-copywriter`                                                                      | `phases/draft_and_finalize.md` |
| 4   | Naturalize letters                | `expert-naturalizer`                                                                                                      | `phases/draft_and_finalize.md` |
| 5   | Rewrite card (deeper + letters)   | — (orchestrator, Read + Write)                                                                                            | `phases/draft_and_finalize.md` |
| 6   | Verification summary              | — (orchestrator)                                                                                                          | Inline below                   |

Read `phases/deep_enrichment.md` when you reach Phase 2 and `phases/draft_and_finalize.md` when you reach Phase 3. If `enrich_mode == "only"`, Phases 3 and 4 are skipped; Phase 5 still runs to append the `## Deeper Intelligence` section. If `enrich_mode == "skip"`, Phase 2 is skipped; Phase 5 only appends the `## Outreach Letters` section.

### Phase 0: Setup + card validation

Parse arguments. Resolve `user_path`, `channels_override`, `sender_override`, `enrich_mode`. Run Source Resolution (see Argument Parsing) to derive `company_slug` and `source_path`. Verify `source_path` exists and parses as a canonical company card.

Derive:

- `company_slug` — already set by Source Resolution (stripped of any date prefix and `.md`).
- `task_name` = `_outreach_enrich_` (truncate `` to 30 chars if needed). Collision: `_v2`, `_v3`.
- `task_dir` = `.mz/task//`.
- `run_dir` = if `source_path` is under `.mz/outreach//companies/`, then `dirname(dirname(source_path))`; otherwise (active path) the most-recently-modified `.mz/outreach//` directory that contains a `strategy.json`, falling back to `default` voice if none found.

```bash
mkdir -p .mz/task//enrichment
mkdir -p .mz/task//briefs
mkdir -p .mz/task//profiles
mkdir -p .mz/task//drafts
mkdir -p .mz/outreach/active
```

Write `.mz/task//state.md`:

```yaml
schema_version: 2
Status: running
Phase: 0
Started: 
phase_complete: false
what_remains: []
UserPath: 
SourcePath: 
CompanySlug: 
RunDir: 
ChannelsOverride: 
SenderOverride: 
EnrichMode: 
BriefRun: 
PersonalityMode: 
```

### Phase 1: Parse card + light web enrichment

Read the card. Extract structured data — do this with normal markdown reading, not a regex parser. Capture:

- **Company**: name (from H1), domain, sector, location, founded, size, score (from the metadata header lines).
- **Overview**: the `## Overview` paragraph.
- **Key Contacts**: every numbered entry under `## Key Contacts`. Each entry is `**** —  — [LinkedIn]() — `. Extract name, title, LinkedIn URL, relevance line. Also capture the trailing `**Emails**:`, `**Phone**:`, `**Company LinkedIn**:` lines. Cap at 5 contacts.
- **Recent News**: numbered entries under `## Recent News & Timing Signals`. Each: `**** (, ,  timing) — `. Keep top 3 by `timing_relevance` (high first).
- **Outreach Recommendation**: the synthesizing paragraph plus the three labeled lines `**Best contact**:`, `**Best angle**:`, `**Timing**:`.
- **Technology Profile**: stack list, maturity, GitHub URL, tech blog URL.
- **Growth Signals**: trajectory, open roles, funding (if present).
- **Red Flags**: any bulleted items (or "None identified").

Persist the parsed structure to `.mz/task//card_parsed.json` so Phase 2 subagents can read it without re-parsing the markdown:

```json
{
  "company": { "name": "...", "slug": "...", "domain": "...", "sector": "...", "location": "...", "founded": "...", "size": "..." },
  "overview": "",
  "key_contacts": [ { "name": "...", "title": "...", "linkedin_url": "...", "email": "...", "relevance": "..." } ],
  "recent_news": [ { "title": "...", "date": "...", "category": "...", "timing_relevance": "...", "outreach_implication": "..." } ],
  "outreach_recommendation": { "summary": "...", "best_contact": "...", "best_angle": "...", "timing": "..." },
  "tech_profile": { "stack": ["..."], "maturity": "...", "github_url": "...", "tech_blog_url": "..." },
  "growth_signals": { "trajectory": "...", "open_roles": ["..."], "funding": "..." },
  "red_flags": ["..."]
}
```

Read `/strategy.json` if it exists. Capture the `sender_voice` (or `outreach_strategy.sender_voice`) and `outreach_angles` fields. If the file is missing OR the field is empty, use these defaults:

- `sender_voice` = `"Professional, concise, plain-spoken. No marketing register, no hype. First-person singular. Direct request, one CTA per letter."`
- `outreach_angles` = `["Value-first introduction citing one verified personalization signal from the card or fresh research."]`

If `sender_override` was supplied as an argument, it overrides the strategy.json value (inline text → used directly; path → read the file).

Record `strategy_source` per brief: `strategy.json` if loaded from disk, `default` if fallback applied, `sender_override` if argument was used. If `default`, the final STATUS will be `DONE_WITH_CONCERNS`.

#### Local-climate context

If `brief_run` was supplied, read `.mz/outreach//climate.json` and select the combo whose `industry` and `region` best match the card's sector and location (prefer an exact region match, then industry; if none match, skip climate context and letters fall back to company data). Capture the matched combo's `signals` and `top_outreach_angles` as `climate_context`, carried into Phase 3 brief-building. If the file is missing, warn and continue without it.

#### Light web enrichment

This is a small fast pre-pass for the orchestrator to grab per-contact signals the Phase 2 subagents won't touch. The deep, multi-source enrichment happens in Phase 2 via subagents. Hard cap here: 6 calls.

Run a single parallel wave of WebSearch calls:

1. 1 × WebSearch per Key Contact (up to 5) — public activity. Query: `"" "" linkedin OR podcast OR interview OR keynote`.
1. 1 × WebSearch — anchor query for cross-referencing in Phase 2. Query: `"" news `.

Capture per-contact signal strings (1–2 lines each, verbatim from the search snippet). Discard anything that cannot be cited. These signals seed Phase 3 brief-building; they are not written into the card.

Record the total number of light-pass web calls — surface in the final verification block.

Update `state.md` Phase field to `card_parsed`. If `enrich_mode == "skip"`, advance directly to Phase 3 (handoff to `phases/draft_and_finalize.md`). Otherwise advance to Phase 2 (handoff to `phases/deep_enrichment.md`).

### Phase 6: Verification summary

After Phase 5 completes, emit a visible block:

```
Outreach enrich-company done.
Source (read from):     
Card (final):           _.md>
Relocated:                   # yes if source_path != target_path
Task dir:               .mz/task//
Enrichment mode:        
Subagents dispatched:       (capped at 5)
Subagents failed:       
Deeper-intel fields:    
Contacts drafted:          (channels: )   # 0 if enrich_mode == only
Contacts skipped:

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [DoctorMozg](https://github.com/DoctorMozg)
- **Source:** [DoctorMozg/claude-pipelines](https://github.com/DoctorMozg/claude-pipelines)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-doctormozg-claude-pipelines-outreach-enrich-company
- Seller: https://agentstack.voostack.com/s/doctormozg
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
