@sellable/mcp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. package/.claude-plugin/plugin.json +12 -0
  2. package/.mcp.json +9 -0
  3. package/README.md +355 -0
  4. package/dist/api.d.ts +21 -0
  5. package/dist/api.js +73 -0
  6. package/dist/auth.d.ts +60 -0
  7. package/dist/auth.js +246 -0
  8. package/dist/engage-memory.d.ts +63 -0
  9. package/dist/engage-memory.js +354 -0
  10. package/dist/index-dev.d.ts +2 -0
  11. package/dist/index-dev.js +17 -0
  12. package/dist/index.d.ts +7 -0
  13. package/dist/index.js +8 -0
  14. package/dist/server.d.ts +1 -0
  15. package/dist/server.js +499 -0
  16. package/dist/skills.d.ts +11 -0
  17. package/dist/skills.js +97 -0
  18. package/dist/tools/auth.d.ts +30 -0
  19. package/dist/tools/auth.js +124 -0
  20. package/dist/tools/blueprint-commit.d.ts +174 -0
  21. package/dist/tools/blueprint-commit.js +286 -0
  22. package/dist/tools/bootstrap.d.ts +64 -0
  23. package/dist/tools/bootstrap.js +246 -0
  24. package/dist/tools/campaigns.d.ts +589 -0
  25. package/dist/tools/campaigns.js +892 -0
  26. package/dist/tools/cells.d.ts +58 -0
  27. package/dist/tools/cells.js +48 -0
  28. package/dist/tools/context.d.ts +88 -0
  29. package/dist/tools/context.js +271 -0
  30. package/dist/tools/csv-domains.d.ts +73 -0
  31. package/dist/tools/csv-domains.js +464 -0
  32. package/dist/tools/csv-linkedin.d.ts +102 -0
  33. package/dist/tools/csv-linkedin.js +712 -0
  34. package/dist/tools/direct-campaigns.d.ts +240 -0
  35. package/dist/tools/direct-campaigns.js +250 -0
  36. package/dist/tools/engage-bootstrap.d.ts +94 -0
  37. package/dist/tools/engage-bootstrap.js +205 -0
  38. package/dist/tools/engage-discovery.d.ts +78 -0
  39. package/dist/tools/engage-discovery.js +150 -0
  40. package/dist/tools/engage-memory.d.ts +181 -0
  41. package/dist/tools/engage-memory.js +143 -0
  42. package/dist/tools/engage-state.d.ts +72 -0
  43. package/dist/tools/engage-state.js +62 -0
  44. package/dist/tools/enrichment.d.ts +167 -0
  45. package/dist/tools/enrichment.js +174 -0
  46. package/dist/tools/flow-preflight.d.ts +68 -0
  47. package/dist/tools/flow-preflight.js +138 -0
  48. package/dist/tools/framework.d.ts +44 -0
  49. package/dist/tools/framework.js +153 -0
  50. package/dist/tools/interaction-mode.d.ts +27 -0
  51. package/dist/tools/interaction-mode.js +102 -0
  52. package/dist/tools/leads.d.ts +2417 -0
  53. package/dist/tools/leads.js +2307 -0
  54. package/dist/tools/linkedin.d.ts +210 -0
  55. package/dist/tools/linkedin.js +229 -0
  56. package/dist/tools/navigation.d.ts +91 -0
  57. package/dist/tools/navigation.js +381 -0
  58. package/dist/tools/one-off.d.ts +229 -0
  59. package/dist/tools/one-off.js +273 -0
  60. package/dist/tools/processing.d.ts +70 -0
  61. package/dist/tools/processing.js +56 -0
  62. package/dist/tools/prompts.d.ts +211 -0
  63. package/dist/tools/prompts.js +210 -0
  64. package/dist/tools/provider-preflight.d.ts +21 -0
  65. package/dist/tools/provider-preflight.js +59 -0
  66. package/dist/tools/readiness.d.ts +261 -0
  67. package/dist/tools/readiness.js +510 -0
  68. package/dist/tools/rows.d.ts +126 -0
  69. package/dist/tools/rows.js +105 -0
  70. package/dist/tools/rubrics.d.ts +497 -0
  71. package/dist/tools/rubrics.js +681 -0
  72. package/dist/tools/senders.d.ts +44 -0
  73. package/dist/tools/senders.js +69 -0
  74. package/dist/tools/sequencer.d.ts +127 -0
  75. package/dist/tools/sequencer.js +194 -0
  76. package/dist/tools/tables.d.ts +35 -0
  77. package/dist/tools/tables.js +36 -0
  78. package/dist/tools/verify-row.d.ts +36 -0
  79. package/dist/tools/verify-row.js +38 -0
  80. package/dist/tools/workspaces.d.ts +140 -0
  81. package/dist/tools/workspaces.js +139 -0
  82. package/dist/utils/workspace-root.d.ts +1 -0
  83. package/dist/utils/workspace-root.js +39 -0
  84. package/package.json +46 -0
  85. package/skills/building-gtm-tables/SKILL.md +216 -0
  86. package/skills/building-gtm-tables/core/auto-execute.yaml +19 -0
  87. package/skills/building-gtm-tables/core/blueprint-schema.json +72 -0
  88. package/skills/building-gtm-tables/references/brief-to-blueprint.md +334 -0
  89. package/skills/building-gtm-tables/references/column-type-catalog.md +318 -0
  90. package/skills/building-gtm-tables/references/common-blueprints.fixtures.ts +199 -0
  91. package/skills/building-gtm-tables/references/common-blueprints.md +44 -0
  92. package/skills/building-gtm-tables/references/failure-taxonomy.md +197 -0
  93. package/skills/building-gtm-tables/references/uat-seed-prompts.md +37 -0
  94. package/skills/building-gtm-tables/references/verify-loop.md +74 -0
  95. package/skills/campaign-messages/SKILL.md +173 -0
  96. package/skills/campaign-messages/flow.v1.json +75 -0
  97. package/skills/craft-message/SKILL.md +401 -0
  98. package/skills/create-campaign/ARCHITECTURE.md +232 -0
  99. package/skills/create-campaign/DISCUSS.md +296 -0
  100. package/skills/create-campaign/FLOW_ASCII.md +240 -0
  101. package/skills/create-campaign/HOST-PARITY-CHECKLIST.md +49 -0
  102. package/skills/create-campaign/README.md +142 -0
  103. package/skills/create-campaign/SKILL.md +286 -0
  104. package/skills/create-campaign/context/README.md +67 -0
  105. package/skills/create-campaign/context/_TEMPLATE.md +12 -0
  106. package/skills/create-campaign/context/context.md +35 -0
  107. package/skills/create-campaign/context/learnings.md +16 -0
  108. package/skills/create-campaign/context/registry.json +19 -0
  109. package/skills/create-campaign/core/flow.v1.json +217 -0
  110. package/skills/create-campaign/core/policy.md +191 -0
  111. package/skills/create-campaign/core/providers/apollo.json +35 -0
  112. package/skills/create-campaign/core/providers/prospeo.json +34 -0
  113. package/skills/create-campaign/core/providers/registry.json +31 -0
  114. package/skills/create-campaign/core/providers/sales-nav.json +37 -0
  115. package/skills/create-campaign/core/providers/signal-discovery.json +42 -0
  116. package/skills/create-campaign/references/brief-template.md +64 -0
  117. package/skills/create-campaign/references/campaign-quality.md +84 -0
  118. package/skills/create-campaign/references/copy-calibration-examples.md +120 -0
  119. package/skills/create-campaign/references/offer-patterns.md +108 -0
  120. package/skills/create-campaign/references/provider-selection-strategy.md +212 -0
  121. package/skills/create-campaign/references/question-examples.md +167 -0
  122. package/skills/create-campaign/references/token-fill-examples.md +81 -0
  123. package/skills/create-campaign-brief/ARCHITECTURE.md +72 -0
  124. package/skills/create-campaign-brief/DISCUSS.md +64 -0
  125. package/skills/create-campaign-brief/README.md +176 -0
  126. package/skills/create-campaign-brief/SKILL.md +537 -0
  127. package/skills/create-campaign-brief/references/brief-synthesis-rules.md +100 -0
  128. package/skills/create-campaign-brief/references/brief-template.md +220 -0
  129. package/skills/create-campaign-brief/references/campaign-idea-options.md +30 -0
  130. package/skills/create-campaign-brief/references/copy-appendix-template.md +62 -0
  131. package/skills/create-campaign-brief/references/draft-lifecycle.md +23 -0
  132. package/skills/create-campaign-brief/references/examples/MANIFEST.json +89 -0
  133. package/skills/create-campaign-brief/references/examples/briefs/clover.md +223 -0
  134. package/skills/create-campaign-brief/references/examples/briefs/galley.md +222 -0
  135. package/skills/create-campaign-brief/references/examples/briefs/gelee.md +220 -0
  136. package/skills/create-campaign-brief/references/examples/briefs/hey-digital.md +234 -0
  137. package/skills/create-campaign-brief/references/examples/briefs/persona.md +231 -0
  138. package/skills/create-campaign-brief/references/examples/briefs/revvix.md +220 -0
  139. package/skills/create-campaign-brief/references/examples/briefs/sellable-dev.md +220 -0
  140. package/skills/create-campaign-brief/references/examples/briefs/superposition.md +233 -0
  141. package/skills/create-campaign-brief/references/examples/briefs/superpower.md +219 -0
  142. package/skills/create-campaign-brief/references/examples/briefs/westpark-villas.md +220 -0
  143. package/skills/create-campaign-brief/references/icp-lock-question-bank.md +43 -0
  144. package/skills/create-campaign-brief/references/messaging-inputs.md +58 -0
  145. package/skills/create-campaign-brief/references/output-acceptance-rubric.md +62 -0
  146. package/skills/create-campaign-brief/references/phase75-active-runtime-message-pack.md +248 -0
  147. package/skills/create-campaign-brief/references/phase75-canonical-brief-template.md +319 -0
  148. package/skills/create-campaign-brief/references/phase75-good-brief-and-messaging-examples.md +445 -0
  149. package/skills/create-campaign-brief/references/quick-research-protocol.md +39 -0
  150. package/skills/create-campaign-brief/references/reference-sheet-protocol.md +60 -0
  151. package/skills/create-campaign-brief/references/zero-shot-iteration-rules.md +66 -0
  152. package/skills/create-campaign-v2/SKILL.md +1619 -0
  153. package/skills/create-campaign-v2/core/auto-execute.README.md +219 -0
  154. package/skills/create-campaign-v2/core/auto-execute.yaml +121 -0
  155. package/skills/create-campaign-v2/core/flow.v2.json +1643 -0
  156. package/skills/create-campaign-v2/core/policy.md +82 -0
  157. package/skills/create-campaign-v2/references/ai-tells.md +253 -0
  158. package/skills/create-campaign-v2/references/approval-gate-framing.md +346 -0
  159. package/skills/create-campaign-v2/references/draft-lifecycle.md +110 -0
  160. package/skills/create-campaign-v2/references/escalation-ladder.md +119 -0
  161. package/skills/create-campaign-v2/references/filter-leads.md +495 -0
  162. package/skills/create-campaign-v2/references/final-handoff-contract.md +176 -0
  163. package/skills/create-campaign-v2/references/gold-standard-message-examples.md +394 -0
  164. package/skills/create-campaign-v2/references/gold-standard-message-patterns.md +314 -0
  165. package/skills/create-campaign-v2/references/gold-standard-message-validation-example.md +212 -0
  166. package/skills/create-campaign-v2/references/lead-validation-preview.md +172 -0
  167. package/skills/create-campaign-v2/references/parallel-critique-protocol.md +368 -0
  168. package/skills/create-campaign-v2/references/sample-validation-loop.md +289 -0
  169. package/skills/create-campaign-v2/references/step-13-import-leads.md +151 -0
  170. package/skills/create-campaign-v2/references/step-15-re-cascade.md +90 -0
  171. package/skills/create-campaign-v2/references/thomas-revision-filters.md +521 -0
  172. package/skills/create-campaign-v2/references/thomas-variant-selection.md +202 -0
  173. package/skills/create-campaign-v2/references/tier-routing-matrix.md +66 -0
  174. package/skills/create-campaign-v2/references/validation-criteria.md +367 -0
  175. package/skills/create-campaign-v2/references/watch-link-handoff.md +106 -0
  176. package/skills/create-campaign-v2-validation/SKILL.md +296 -0
  177. package/skills/create-post/SKILL.md +1308 -0
  178. package/skills/create-rubric/SKILL.md +251 -0
  179. package/skills/engage/SKILL.md +549 -0
  180. package/skills/engage/core/README.md +23 -0
  181. package/skills/engage/core/proven-searches.json +11 -0
  182. package/skills/engage/core/style-guide.template.md +47 -0
  183. package/skills/engage/core/tracked-people.json +10 -0
  184. package/skills/enrich-prospects/SKILL.md +97 -0
  185. package/skills/find-leads/SKILL.md +467 -0
  186. package/skills/generate-messages/SKILL.md +2361 -0
  187. package/skills/interview/SKILL.md +132 -0
  188. package/skills/interview/core/ENGAGE_STYLE_GUIDE.template.md +54 -0
  189. package/skills/interview/core/ICP.template.md +54 -0
  190. package/skills/interview/core/VOICE_PROFILE.template.md +101 -0
  191. package/skills/providers/apollo.md +520 -0
  192. package/skills/providers/prospeo.md +398 -0
  193. package/skills/providers/sales-nav.md +372 -0
  194. package/skills/providers/signal-discovery.md +495 -0
  195. package/skills/research/SKILL.md +258 -0
  196. package/skills/research/config.json +9 -0
  197. package/skills/research/override.md +13 -0
  198. package/skills/research-prospect/SKILL.md +99 -0
  199. package/skills/research-sender/SKILL.md +158 -0
  200. package/skills/workflow-sequences/SKILL.md +85 -0
@@ -0,0 +1,173 @@
1
+ ---
2
+ name: campaign-messages
3
+ description: Review leads in a campaign and craft/update messages with research.
4
+ visibility: internal
5
+ ---
6
+
7
+ # Campaign Messages
8
+
9
+ Use this command when the user provides a campaignId and wants to research + craft messages for leads already imported into a campaign workflow table.
10
+
11
+ ## Bootstrap (Required)
12
+
13
+ 1. Load tools in a SINGLE message with ToolSearch calls:
14
+ - `mcp__sellable__get_auth_status`
15
+ - `mcp__sellable__get_campaign`
16
+ - `mcp__sellable__get_campaign_messages_preview`
17
+ - `mcp__sellable__get_table_rows`
18
+ - `mcp__sellable__get_rows`
19
+ - `mcp__sellable__get_message_prompt`
20
+ - `mcp__sellable__update_cell`
21
+ - `mcp__sellable__get_subskill_prompt`
22
+ - `mcp__sellable__search_subskill_prompts`
23
+ 2. Call `get_auth_status({})` and store as `auth`.
24
+ 3. If `auth.ok !== true`, stop and show:
25
+ - `auth.error.message`
26
+ - `auth.error.guidance`
27
+ 4. Call `get_subskill_prompt({ subskillName: "craft-message" })` and store as `craftPrompt`.
28
+
29
+ ## Flow (Source of Truth)
30
+
31
+ Follow the flow in `mcp/sellable/skills/campaign-messages/flow.v1.json`.
32
+
33
+ ```json
34
+ {
35
+ "version": "v1",
36
+ "workflow": "campaign-messages",
37
+ "events": [
38
+ "leads_selected",
39
+ "drafts_ready",
40
+ "messages_saved",
41
+ "approval_complete"
42
+ ],
43
+ "steps": [
44
+ "load-preview",
45
+ "draft-messages",
46
+ "save-messages",
47
+ "approve-messages",
48
+ "done"
49
+ ]
50
+ }
51
+ ```
52
+
53
+ ## Tools
54
+
55
+ - `mcp__sellable__get_campaign`
56
+ - `mcp__sellable__get_campaign_messages_preview`
57
+ - `mcp__sellable__get_rows`
58
+ - `mcp__sellable__get_message_prompt`
59
+ - `mcp__sellable__update_cell`
60
+ - `WebSearch`
61
+ - `mcp__sellable__fetch_linkedin_profile` (optional, costs credits)
62
+ - `mcp__sellable__fetch_linkedin_posts` (optional, costs credits)
63
+ - `mcp__sellable__fetch_company` (optional, costs credits)
64
+ - `Task` (parallel subagents for batch)
65
+
66
+ ## Flow
67
+
68
+ ### 1) Load Campaign + Lead Preview
69
+
70
+ 1. Extract `campaignId` (pattern: `cmp_...`). If missing, ask for it.
71
+ 2. Call `get_campaign({ campaignId })`.
72
+ 3. Immediately fetch the first page preview (no filters yet):
73
+
74
+ `get_campaign_messages_preview({ campaignId, tableId: workflowTableId, leadLimit: 25, page: 1 })`.
75
+
76
+ Then render the ASCII table and stats. After that, ask if they want to filter or page.
77
+
78
+ 5. Render an ASCII table with the preview rows (show message previews, not checkmarks):
79
+
80
+ ```
81
+ # | Name | Title | Company | Message | Approved?
82
+ 1 | ... | ... | ... | Hi ... | ✓/✗
83
+ ```
84
+
85
+ Use `messagePreview` for the Message column (show "—" if empty). Keep Approved as a checkmark based on `isApproved`.
86
+
87
+ If `stats` are present in the preview response, summarize them explicitly using ONLY these fields:
88
+
89
+ - totalRows
90
+ - messagesCount
91
+ - approvedCount
92
+ - needsApprovalCount
93
+ - enrichedCount
94
+ - needsEnrichCount
95
+
96
+ Never mention "pending" or "sent" here (those are campaign-level stats, not workflow-table stats). Never infer whole-table counts from the current page. Only claim "all approved" if `approvedCount === totalRows` and `messagesCount === totalRows`. If stats are missing, say "Showing page X of Y (page-only preview)".
97
+
98
+ Then ask: “Which leads should I craft messages for? (e.g., 1,3 or all)”
99
+
100
+ If they want filters, translate into filters using real column names from the table meta. Example:
101
+
102
+ `filters: [{ "column": "Message", "op": "is_empty" }, { "column": "Approved", "op": "eq", "value": false }]`
103
+
104
+ Then call:
105
+
106
+ `get_campaign_messages_preview({ campaignId, tableId: workflowTableId, leadLimit: 25, page: 1, filters })`.
107
+
108
+ If the user asks for more rows:
109
+
110
+ - Always page with `get_campaign_messages_preview({ campaignId, tableId, leadLimit, page, filters })` so stats and filters stay consistent.
111
+ - Use `get_table_rows` only when the user explicitly asks for the raw table rows tool.
112
+
113
+ Then re-render the ASCII table for that page and ask which rows to craft.
114
+
115
+ ### Optional Research Toggle
116
+
117
+ Ask once per session (or when the user requests deeper research):
118
+
119
+ “Do you want deep research for these leads (parallel sonnet subagents)? Yes/No”
120
+
121
+ If **Yes**:
122
+
123
+ - Call `get_subskill_prompt({ subskillName: "research-prospect" })`
124
+ - For each lead, run the **Shared Flow** with `positioningMode=false`
125
+ - Use LinkedIn URL + company name when available
126
+ - If a Company LinkedIn URL exists in row data, pass it as `companyLinkedinUrl`
127
+ - Synthesize findings into a short “Research Notes” block per lead
128
+
129
+ If **No**: proceed directly to drafting.
130
+
131
+ ### 2) Single Lead (in-thread)
132
+
133
+ 1. Call `get_rows({ tableId, rowIds: selectedRowId })`.
134
+ 2. Use `craftPrompt` as the authoritative craft rules (includes research subtask).
135
+ 3. Call `get_message_prompt()`.
136
+ 4. Craft message using the REPLY framework.
137
+ 5. Show message + gates summary.
138
+ 6. If the message cell is empty, **auto-save the draft** with `update_cell(messageCellId, message)` and say “Draft saved (not approved).”
139
+ 7. If the message cell already has content, ask before overwriting. Only save on explicit user confirmation.
140
+ 8. Ask if they want to approve for sending; if yes: `update_cell(approveCellId, true)`.
141
+
142
+ ### 3) Batch (parallel)
143
+
144
+ If user selects multiple leads:
145
+
146
+ 1. Call `get_message_prompt()` once.
147
+ 2. Spawn parallel Task subagents for each row **with explicit `model: "opus"` and `subagent_type: "general-purpose"`** (never omit model):
148
+ - Provide campaign brief + positioning + sender info
149
+ - Include the full REPLY framework from `get_message_prompt()`
150
+ - Provide row data + messageCellId + tableId
151
+ - Use WebSearch + LinkedIn tools only if needed
152
+ - **Do NOT** save in subagent; return draft + research notes only
153
+ 3. Wait for all tasks.
154
+ 4. For rows where the message cell is empty, auto-save drafts with `update_cell` and announce “Draft saved (not approved).”
155
+ 5. Summarize drafts and ask which to overwrite or edit.
156
+ 6. Save selected drafts with `update_cell`.
157
+ 7. Ask whether to approve saved messages.
158
+
159
+ ### Selection Logic
160
+
161
+ - If the user selects one row: run the single-lead flow.
162
+ - If the user selects multiple rows: run the batch flow.
163
+
164
+ ### Optional: Research Subtask (if user requests deeper research)
165
+
166
+ Use `research-prospect` (wrapper over `mcp/sellable/skills/research/SKILL.md`) and run the Shared Flow with `positioningMode=false`. Only run this when explicitly asked to deepen research.
167
+
168
+ ## Approval Rules
169
+
170
+ - Never auto-approve a message.
171
+ - Auto-save drafts is allowed **only** when the message cell is empty.
172
+ - Do not overwrite a non-empty message without explicit user approval.
173
+ - After saving, always ask whether to approve the message for sending.
@@ -0,0 +1,75 @@
1
+ {
2
+ "version": "v1",
3
+ "workflow": "campaign-messages",
4
+ "principle": "Preview  Select  Draft  Save  Approve",
5
+ "events": [
6
+ "leads_selected",
7
+ "drafts_ready",
8
+ "messages_saved",
9
+ "approval_complete"
10
+ ],
11
+ "steps": [
12
+ {
13
+ "id": "load-preview",
14
+ "label": "Load Campaign + Preview",
15
+ "allowedTools": [
16
+ "get_auth_status",
17
+ "get_campaign",
18
+ "get_campaign_messages_preview",
19
+ "get_table_rows",
20
+ "AskUserQuestion"
21
+ ],
22
+ "waitFor": "leads_selected",
23
+ "transitions": {
24
+ "leads_selected": "draft-messages"
25
+ }
26
+ },
27
+ {
28
+ "id": "draft-messages",
29
+ "label": "Draft Messages",
30
+ "allowedTools": [
31
+ "get_rows",
32
+ "get_message_prompt",
33
+ "get_subskill_prompt",
34
+ "WebSearch",
35
+ "fetch_linkedin_profile",
36
+ "fetch_linkedin_posts",
37
+ "fetch_company",
38
+ "Task"
39
+ ],
40
+ "waitFor": "drafts_ready",
41
+ "transitions": {
42
+ "drafts_ready": "save-messages"
43
+ }
44
+ },
45
+ {
46
+ "id": "save-messages",
47
+ "label": "Save Messages",
48
+ "allowedTools": [
49
+ "update_cell",
50
+ "AskUserQuestion"
51
+ ],
52
+ "waitFor": "messages_saved",
53
+ "transitions": {
54
+ "messages_saved": "approve-messages"
55
+ }
56
+ },
57
+ {
58
+ "id": "approve-messages",
59
+ "label": "Approve Messages",
60
+ "allowedTools": [
61
+ "update_cell",
62
+ "AskUserQuestion"
63
+ ],
64
+ "waitFor": "approval_complete",
65
+ "transitions": {
66
+ "approval_complete": "done"
67
+ }
68
+ },
69
+ {
70
+ "id": "done",
71
+ "label": "Done",
72
+ "terminal": true
73
+ }
74
+ ]
75
+ }
@@ -0,0 +1,401 @@
1
+ ---
2
+ name: craft-message
3
+ description: Craft a deeply researched, personalized LinkedIn message by exploring 10 angles in parallel and combining the best elements — like Doctor Strange viewing 14 million futures to find the one that wins. 5+ minutes of compute per message. The kind of message that gets replies.
4
+ model: opus
5
+ visibility: internal
6
+ ---
7
+
8
+ # Craft Message
9
+
10
+ You craft personalized LinkedIn outreach messages that are indistinguishable from hand-written ones. Every message gets 5+ minutes of compute across **3 parallel phases**: 6-agent research, 10-agent angle exploration, then Opus finalizer synthesis. Like Doctor Strange viewing 14 million futures — explore every angle in parallel, then combine the winning elements into one message. This is the "manufactured thoughtfulness" that gets 20%+ reply rates.
11
+
12
+ ## Progress Narration (CRITICAL)
13
+
14
+ **NEVER use silent thinking.** Always narrate your progress visibly so users know what's happening:
15
+
16
+ ```
17
+ > Loading prospect data + configs + REPLY framework (parallel)...
18
+ > Launching 6 research agents (posts, homepage, LinkedIn, role, growth, reviews)...
19
+ > Research complete. Synthesizing findings...
20
+ > Launching 10 angle agents in parallel...
21
+ > 10 drafts received. Analyzing angles...
22
+ > Best opener: post-hook (referenced their "scaling culture" post)
23
+ > Best bridge: story-mirror (both bootstrapped before raising)
24
+ > Best credibility: micro-observation (noticed their comment on a niche thread)
25
+ > Combining + voice-checking + credibility pass... Final gates: 12/12
26
+ ```
27
+
28
+ Share findings as you go - don't wait until the end. Users should see your reasoning in real-time.
29
+
30
+ ## Architecture
31
+
32
+ ```
33
+ Phase 1: Bootstrap 6 parallel loads (data + configs + framework) ~2s
34
+ Phase 2: Research 6 parallel Sonnet agents (one message, no background) ~15s
35
+ Phase 2.5: Condense Build ~1.5k token angle brief from full context ~1s
36
+ Phase 3: Angle Fan-Out 10 parallel Sonnet agents (~2k tokens each = ~20k) ~15s
37
+ Phase 4: Finalizer Opus combines best of 10 + credibility + full gates ~30s
38
+ Phase 5: Show + Save Present final message for approval
39
+ ```
40
+
41
+ **Context budget:** Angle agents get condensed briefs (~2k tokens each × 10 = ~20k total). The Opus finalizer holds the full REPLY framework (~11k), full configs, and full research. This keeps total context well under limits.
42
+
43
+ ## CRITICAL: No `run_in_background` for Task Agents
44
+
45
+ **DO NOT use `run_in_background: true`** when launching research or angle agents. Background agents send completion notifications as separate conversation turns AFTER you've moved to later phases, causing notification spam (the model re-asks the approval question 10+ times).
46
+
47
+ **Instead:** Launch all agents in a **single message** as regular Task calls (no `run_in_background`). Multiple Task calls in one message execute concurrently. All results return together when the last agent finishes. Zero delayed notifications.
48
+
49
+ ```
50
+ ✅ CORRECT: 10 Task calls in ONE message (no run_in_background) → all run in parallel, results arrive together
51
+ ❌ WRONG: 10 Task calls with run_in_background: true → notification spam after final message shown
52
+ ❌ WRONG: 10 Task calls sequentially (one per message) → 10x slower, defeats the purpose
53
+ ```
54
+
55
+ ## Source of Truth
56
+
57
+ The REPLY framework prompt is loaded via `get_message_prompt()`. This returns the full methodology including:
58
+
59
+ - 10-step workflow (research -> hooks -> gates -> polish)
60
+ - 11 quality gates with detailed pass/fail criteria
61
+ - Anti-patterns to avoid
62
+ - Formatting rules
63
+
64
+ **Angle agents get a condensed brief** for creative exploration. **Only the Opus finalizer uses the full framework** for compliance and gate-checking. This separation is what makes 10 parallel agents feasible without blowing context.
65
+
66
+ ## Available Tools
67
+
68
+ Row/Cell tools (free):
69
+
70
+ - `mcp__sellable__get_rows` - Get full row data for crafting
71
+ - `mcp__sellable__update_cell` - Save message or approve for sending
72
+ - `mcp__sellable__get_message_prompt` - Load the REPLY framework prompt
73
+ - `mcp__sellable__get_subskill_prompt` - Load shared research protocol
74
+
75
+ Parallel execution:
76
+
77
+ - `Task` - Spawn parallel subagents (research agents, angle agents)
78
+
79
+ Config tools (built-in, free):
80
+
81
+ - `Read` - Load voice configs, outbound rules, and cross-skill insights from `.sellable/`
82
+
83
+ Research tools (free - user's Claude tokens):
84
+
85
+ - `WebSearch` - Search web for prospect news, posts, company info
86
+
87
+ LinkedIn tools (cost credits):
88
+
89
+ - `mcp__sellable__fetch_linkedin_posts` - Get prospect's recent LinkedIn posts
90
+ - `mcp__sellable__fetch_linkedin_profile` - Get full profile details
91
+ - `mcp__sellable__fetch_company` - Get company profile details
92
+
93
+ ## Input
94
+
95
+ You receive from the campaign flow (or user provides):
96
+
97
+ - Campaign: brief, positioning, dos/donts
98
+ - Sender: name, company, background, proof points
99
+ - Lead: rowId, name, company, title, linkedinUrl
100
+ - tableId: for API calls
101
+ - cellIds: messageCellId, approveCellId
102
+
103
+ ## Workflow
104
+
105
+ ### Step 1: Parallel Bootstrap (single message — all independent)
106
+
107
+ **Batch ALL of these calls in one message — they have zero dependencies on each other:**
108
+
109
+ ```
110
+ Parallel batch (6 calls):
111
+ ├── get_rows(rowId) → prospect data
112
+ ├── get_message_prompt() → REPLY framework
113
+ ├── get_subskill_prompt({ subskillName: "research-prospect" }) → research protocol
114
+ ├── Read .sellable/configs/writing/outbound.md → outbound rules
115
+ ├── Read .sellable/configs/writing/styleguide-core.md → sender voice
116
+ └── Read .sellable/insights/cross-skill.md → cross-skill learnings
117
+ ```
118
+
119
+ If any config file doesn't exist yet, skip silently. After all return:
120
+
121
+ 1. Extract `linkedinUrl` from row data (cells/fields like `linkedinUrl`, `LinkedIn URL`, `linkedin`, `linkedin_url`)
122
+ 2. Extract `companyLinkedinUrl` if present (cells/fields like `Company LinkedIn URL`, `LinkedIn Company URL`, `companyLinkedinUrl`)
123
+ 3. Store configs for voice calibration in Step 3
124
+
125
+ ### Step 2: Parallel Research (6 Sonnet agents in one message)
126
+
127
+ Follow the research protocol from Step 1. Set `positioningMode=false`.
128
+
129
+ **Launch ALL 6 Sonnet agents in a SINGLE message** (no `run_in_background`):
130
+
131
+ ```
132
+ One message with 6 Task calls (all run concurrently):
133
+ ├── Agent 1: Post Analyzer (fetch_linkedin_posts)
134
+ ├── Agent 2: Homepage Snapshot (WebFetch)
135
+ ├── Agent 3: Company LinkedIn (WebSearch + fetch_company)
136
+ ├── Agent 4: Role Context (no tools — pure reasoning)
137
+ ├── Agent 5: Jobs + Funding (WebSearch)
138
+ └── Agent 6: Reviews + Traffic (WebSearch)
139
+ ```
140
+
141
+ All 6 results return together when the last agent finishes. Then synthesize into a Research Notes block.
142
+
143
+ - Use WebSearch only by default. If you need LinkedIn tools (credits), ask first.
144
+
145
+ ### Step 2.5: Build Condensed Angle Brief (CRITICAL for context management)
146
+
147
+ **WHY THIS STEP EXISTS:** The full REPLY framework is ~11k tokens. Passing it to each of 10 angle agents would consume ~110k tokens of parent context just in tool call prompts — causing context overflow. Instead, the orchestrator extracts a condensed brief (~1.5k tokens) that angle agents use for creative exploration. The Opus finalizer handles full REPLY compliance in Step 4.
148
+
149
+ Extract the following from the REPLY framework, configs, and research into a single condensed string:
150
+
151
+ ```
152
+ ## Angle Brief (pass this to every angle agent — ~1.5k tokens max)
153
+
154
+ ### Prospect
155
+ - Name: {name} | Title: {title} | Company: {company}
156
+ - Top of Mind: {1-2 lines from research synthesis}
157
+ - Key Hooks: {3-4 bullet points from research — post topics, company news, pain points}
158
+
159
+ ### Sender
160
+ - Name: {sender name} | Company: {sender company}
161
+ - Core thesis: {1 line from styleguide-core.md}
162
+ - Signature phrases: {3-5 key phrases from styleguide-core.md}
163
+ - Offer: {1 line from campaign brief}
164
+
165
+ ### Message Rules
166
+ - Structure: observation about THEM → why it's relevant → soft ask
167
+ - Under 300 characters for the opener. Under 900 characters total.
168
+ - No bullet points. No "I noticed..." or "I saw...". No compliment sandwiches.
169
+ - Sound like a human peer, not a salesperson. Use sender's natural voice.
170
+ - Must include one specific detail that proves you did your homework.
171
+
172
+ ### Campaign Context
173
+ - {2-3 line summary of brief, positioning, dos/donts}
174
+
175
+ ### Cross-Skill Insights
176
+ - {2-3 bullets from cross-skill.md — what angles/hooks have worked}
177
+ ```
178
+
179
+ **DO NOT include the full REPLY framework, full styleguide, or full outbound.md in the angle brief.** Keep it under 1,500 tokens. The finalizer has all the full documents.
180
+
181
+ ### Step 3: Angle Exploration — Fan-Out (10 parallel agents)
182
+
183
+ This is the Doctor Strange step. Instead of drafting one message linearly, **fan out 10 parallel agents** — each exploring a completely different angle. More angles explored = better final message. Every agent gets the condensed angle brief + their specific angle instruction.
184
+
185
+ **Launch ALL 10 in a SINGLE message** (no `run_in_background`):
186
+
187
+ ```
188
+ One message with 10 Task calls (all run concurrently):
189
+ ├── Agent A: Post-Hook → opens with something specific they said/posted
190
+ ├── Agent B: Company-Momentum → opens with their company's growth signal
191
+ ├── Agent C: Pain-Point → leads with a role-specific challenge they face
192
+ ├── Agent D: Shared-World → finds common ground between sender + prospect
193
+ ├── Agent E: Contrarian → unexpected take that reframes their problem
194
+ ├── Agent F: Trigger-Event → hooks on something that just happened (job change, launch, milestone)
195
+ ├── Agent G: Value-First → leads with a specific insight or resource before asking
196
+ ├── Agent H: Micro-Observation → hyper-specific detail from their profile/content
197
+ ├── Agent I: Story-Mirror → mirrors prospect's journey with sender's journey
198
+ └── Agent J: Industry-Trend → connects to a macro trend reshaping their space
199
+ ```
200
+
201
+ **CRITICAL:** Do NOT use `run_in_background: true` for angle agents. Launch all 10 as regular Task calls in ONE message — they execute concurrently and all results return together. Using `run_in_background` causes completion notifications to arrive after the final message is shown, triggering notification spam.
202
+
203
+ #### Agent Prompt Template (~2k tokens per agent, NOT 15k)
204
+
205
+ ```
206
+ Draft ONE LinkedIn message from the {angle_name} angle.
207
+
208
+ ## Your Angle
209
+ {angle_name}: {angle_description}
210
+
211
+ ## Brief
212
+ {condensed angle brief from Step 2.5 — ~1.5k tokens}
213
+
214
+ ## Instructions
215
+ 1. Find the strongest bridge between your angle and the prospect's world
216
+ 2. Draft a complete message: observation about THEM → relevance → soft ask
217
+ 3. Use the sender's signature phrases naturally
218
+ 4. Keep under 900 chars total, opener under 300 chars
219
+ 5. Return EXACTLY:
220
+ ---
221
+ ANGLE: {angle name}
222
+ RATIONALE: {1 line — why this angle wins}
223
+ MESSAGE:
224
+ {the message}
225
+ ---
226
+ ```
227
+
228
+ **IMPORTANT: Each agent prompt must be ~2k tokens max.** This is what makes 10 agents feasible — 10 × 2k = 20k tokens vs 10 × 15k = 150k (which blows context). The finalizer does full gate-checking, not the angle agents.
229
+
230
+ #### Angle Definitions
231
+
232
+ | Agent | Angle | Description |
233
+ | ----- | --------------------- | ----------------------------------------------------------------------------------------------------------------------- |
234
+ | A | **Post-Hook** | Opens with something specific the prospect said or posted. Uses a direct quote, topic, or reaction. Most personal. |
235
+ | B | **Company-Momentum** | Opens with a growth signal — funding, hiring, product launch, press. Shows you pay attention to their company. |
236
+ | C | **Pain-Point** | Leads with a challenge specific to their role/title. Demonstrates you understand what keeps them up at night. |
237
+ | D | **Shared-World** | Finds common ground — shared background, mutual interest, industry overlap, similar journey. Peer connection. |
238
+ | E | **Contrarian** | Unexpected angle — challenges a common assumption, reframes their problem, pattern-interrupt. |
239
+ | F | **Trigger-Event** | Hooks on something that just happened — job change, promotion, product launch, company milestone. Time-sensitive. |
240
+ | G | **Value-First** | Leads with a specific insight, observation, or resource that gives value before asking for anything. |
241
+ | H | **Micro-Observation** | Hyper-specific detail from their profile, a comment they left, a niche bio detail. Shows obsessive attention to detail. |
242
+ | I | **Story-Mirror** | Mirrors the prospect's journey with the sender's journey — "I went through X too." Builds empathy. |
243
+ | J | **Industry-Trend** | Connects to a macro trend reshaping their space and positions the sender's offer as relevant to it. |
244
+
245
+ **Use `model: "sonnet"` and `subagent_type: "general-purpose"` for all 10 angle agents.** Sonnet is fast enough for drafting; Opus handles the final synthesis and full REPLY gate-check.
246
+
247
+ **Narrate when launching and when results arrive:**
248
+
249
+ ```
250
+ > Launching 10 angle agents in parallel...
251
+ > [all 10 results arrive together]
252
+ > 10/10 angles explored. Analyzing drafts...
253
+ ```
254
+
255
+ ### Step 4: Finalizer — Combine + Credibility + Full REPLY Gate-Check (Orchestrator)
256
+
257
+ After all 10 angle agents return, **you (the Opus orchestrator) act as the finalizer.** You have the full REPLY framework, full configs, and full research in your context — the angle agents had condensed briefs, but YOU have everything. This is where compliance, credibility, and quality all converge.
258
+
259
+ **Finalizer process:**
260
+
261
+ 1. **Read all 10 drafts** — lay them out side by side (internally)
262
+ 2. **Score each angle:**
263
+ - Which opener is most arresting? (pattern-interrupt value)
264
+ - Which bridge is most natural? (doesn't feel forced)
265
+ - Which body flows best? (observation → relevance → ask)
266
+ - Which CTA is most compelling? (low-friction, high-curiosity)
267
+ 3. **Combine the winning elements** — the best opener from one, the best bridge from another, the best CTA from a third. You're not picking a winner — you're assembling a new message from the best parts across all 10.
268
+ 4. **Credibility pass (CRITICAL)** — the message must build credibility, not just be pleasant:
269
+ - Does it demonstrate that the sender actually understands the prospect's world? Not generic flattery — specific, earned insight.
270
+ - Does it say something the prospect hasn't heard from 50 other salespeople? If the opener could apply to anyone in their role, it's too generic. Rewrite.
271
+ - Does the bridge prove the sender has a unique perspective? The message should make the prospect think "this person actually gets it" — not "this person read my LinkedIn headline."
272
+ - Is there at least one sentence that would make the prospect stop scrolling? Something surprising, specific, or contrarian.
273
+ - Kill any line that reads like a template. If you've seen it in a cold outreach before, rewrite it.
274
+ 5. **Voice-check** — does it sound like the sender? Use their signature phrases from `styleguide-core.md` (the FULL file, not the condensed brief).
275
+ 6. **Full 12-gate check using the REPLY framework** — this is the only place the full framework is applied. All gates must pass on the combined message. The angle agents drafted creatively; you enforce compliance.
276
+ 7. **Polish** — one final pass for flow, tone, and length
277
+
278
+ If the combined message fails any gates or the credibility pass, iterate until it passes. The finalizer has unlimited iterations — never show a message that fails.
279
+
280
+ **Progress narration during finalizer:**
281
+
282
+ ```
283
+ > 10 angles explored. Analyzing drafts...
284
+ > Best opener: Agent A (post-hook — referenced their "scaling culture" post)
285
+ > Best bridge: Agent I (story-mirror — both bootstrapped before raising)
286
+ > Best credibility: Agent H (micro-observation — noticed their comment on a niche thread)
287
+ > Best CTA: Agent C (pain-point — asked about their hiring bottleneck)
288
+ > Combining elements + credibility pass + voice-check...
289
+ > Final gate check: 12/12 passed
290
+ ```
291
+
292
+ ### Step 5: Show for Approval
293
+
294
+ After the message passes all 12 gates + credibility pass, show the user the message ONCE with a concise "Why this works" section. The format builds trust through explainability without being verbose. Show the message prominently, then prove it's not generic.
295
+
296
+ ```
297
+ **Message for {name} @ {company}:**
298
+
299
+ {newMessage}
300
+
301
+ **Why this works:**
302
+ ✓ Opener: {angle name} — {specific signal used, e.g. "role shift + 20% marketplace data"}
303
+ ✓ Bridge: {angle name} — {why it's not generic, e.g. "reframes seller acquisition as quality problem"}
304
+ ✓ Scroll-stopper: "{exact quote from message that would make them stop scrolling}"
305
+ ✓ Template check: 0 generic phrases found
306
+
307
+ Gates: 12/12 | Angles explored: 10
308
+ ```
309
+
310
+ **Rules for this section:**
311
+
312
+ - Show the message exactly ONCE — never repeat it
313
+ - "Why this works" is 4 lines max — one for opener, bridge, scroll-stopper, and template check
314
+ - The scroll-stopper is the single most compelling line from the message — quote it exactly
315
+ - Don't show the full scoring table or all 10 angle breakdowns — just the winners
316
+ - Don't show the credibility pass checklist inline — it's internal. The "Why this works" section IS the user-facing credibility proof
317
+
318
+ If the current message is empty, auto-save the draft after showing it and say "Draft saved (not approved)."
319
+ If the current message already has content, ask before overwriting:
320
+
321
+ - Yes, save it
322
+ - Let me tweak it first
323
+ - Try again with different approach
324
+
325
+ CRITICAL: Never auto-approve. Only auto-save when the message cell is empty.
326
+
327
+ ### Step 6: Save Draft
328
+
329
+ If the message cell is empty, auto-save immediately after showing the draft:
330
+
331
+ ```
332
+ update_cell(messageCellId, newMessage)
333
+ ```
334
+
335
+ If the message cell already has content, only save after the user confirms "save it":
336
+
337
+ ```
338
+ update_cell(messageCellId, newMessage)
339
+ ```
340
+
341
+ Then IMMEDIATELY show:
342
+
343
+ ```
344
+ Message saved!
345
+
346
+ ---
347
+
348
+ **Ready to approve for sending?**
349
+
350
+ Approved messages will be sent by the Sellable sweeper at scheduled times.
351
+
352
+ - **Yes, approve it** — mark ready to send
353
+ - **Not yet** — review in Sellable first
354
+ ```
355
+
356
+ CRITICAL: Always ask this question after saving. Never auto-approve.
357
+
358
+ ### Step 7: Mark Approved (only if user confirms)
359
+
360
+ If user says yes/approve:
361
+
362
+ ```
363
+ update_cell(approveCellId, true)
364
+ ```
365
+
366
+ Then confirm:
367
+
368
+ ```
369
+ Approved! Message queued for sending.
370
+ ```
371
+
372
+ ### Step 8: Return to Campaign Flow
373
+
374
+ After saving (and optionally approving), return control for:
375
+
376
+ - Crafting another message
377
+ - Viewing updated stats
378
+ - Campaign controls
379
+
380
+ ## Critical Rules
381
+
382
+ 1. **Load configs first** — read `.sellable/configs/writing/outbound.md` and `styleguide-core.md` before crafting. The message must sound like the sender.
383
+ 2. **Load the framework first** — always call `get_message_prompt()` before crafting
384
+ 3. **Always fan out 10 angles** — never skip the angle exploration step. More angles = better final message. This is the core differentiator.
385
+ 4. **Launch agents in ONE message, no `run_in_background`** — all 10 angle agents (and all 6 research agents) must be launched as regular Task calls in a single message. They run concurrently and all results return together. Never use `run_in_background: true` — it causes notification spam.
386
+ 5. **Finalizer combines, doesn't pick** — don't just select the "best" draft. Extract the best opener from one, best bridge from another, best CTA from a third. The final message should be better than any individual draft.
387
+ 6. **Credibility pass is mandatory** — the finalizer must verify the message says something the prospect hasn't heard from 50 other people. Generic flattery fails the pass. If it could apply to anyone with their title, rewrite it.
388
+ 7. Never auto-approve a message
389
+ 8. Auto-save drafts is allowed only when the message cell is empty
390
+ 9. Do not overwrite a non-empty message without explicit user approval
391
+ 10. All 12 gates must pass — iterate until they do
392
+ 11. **Research deeply** — this is the value (5+ min per message). Compute time is the quality knob.
393
+ 12. Credits awareness — note when using LinkedIn tools
394
+ 13. **Use cross-skill insights** — if `insights/cross-skill.md` shows what hooks/angles resonate, use those patterns in the angle exploration
395
+
396
+ ## Developer Note
397
+
398
+ The REPLY framework prompt is maintained at:
399
+ `src/config/outbound-builder/steps/editMessage/prompt.ts`
400
+
401
+ Edits there apply to both the web app and Claude Code plugin.