@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.
- package/.claude-plugin/plugin.json +12 -0
- package/.mcp.json +9 -0
- package/README.md +355 -0
- package/dist/api.d.ts +21 -0
- package/dist/api.js +73 -0
- package/dist/auth.d.ts +60 -0
- package/dist/auth.js +246 -0
- package/dist/engage-memory.d.ts +63 -0
- package/dist/engage-memory.js +354 -0
- package/dist/index-dev.d.ts +2 -0
- package/dist/index-dev.js +17 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +8 -0
- package/dist/server.d.ts +1 -0
- package/dist/server.js +499 -0
- package/dist/skills.d.ts +11 -0
- package/dist/skills.js +97 -0
- package/dist/tools/auth.d.ts +30 -0
- package/dist/tools/auth.js +124 -0
- package/dist/tools/blueprint-commit.d.ts +174 -0
- package/dist/tools/blueprint-commit.js +286 -0
- package/dist/tools/bootstrap.d.ts +64 -0
- package/dist/tools/bootstrap.js +246 -0
- package/dist/tools/campaigns.d.ts +589 -0
- package/dist/tools/campaigns.js +892 -0
- package/dist/tools/cells.d.ts +58 -0
- package/dist/tools/cells.js +48 -0
- package/dist/tools/context.d.ts +88 -0
- package/dist/tools/context.js +271 -0
- package/dist/tools/csv-domains.d.ts +73 -0
- package/dist/tools/csv-domains.js +464 -0
- package/dist/tools/csv-linkedin.d.ts +102 -0
- package/dist/tools/csv-linkedin.js +712 -0
- package/dist/tools/direct-campaigns.d.ts +240 -0
- package/dist/tools/direct-campaigns.js +250 -0
- package/dist/tools/engage-bootstrap.d.ts +94 -0
- package/dist/tools/engage-bootstrap.js +205 -0
- package/dist/tools/engage-discovery.d.ts +78 -0
- package/dist/tools/engage-discovery.js +150 -0
- package/dist/tools/engage-memory.d.ts +181 -0
- package/dist/tools/engage-memory.js +143 -0
- package/dist/tools/engage-state.d.ts +72 -0
- package/dist/tools/engage-state.js +62 -0
- package/dist/tools/enrichment.d.ts +167 -0
- package/dist/tools/enrichment.js +174 -0
- package/dist/tools/flow-preflight.d.ts +68 -0
- package/dist/tools/flow-preflight.js +138 -0
- package/dist/tools/framework.d.ts +44 -0
- package/dist/tools/framework.js +153 -0
- package/dist/tools/interaction-mode.d.ts +27 -0
- package/dist/tools/interaction-mode.js +102 -0
- package/dist/tools/leads.d.ts +2417 -0
- package/dist/tools/leads.js +2307 -0
- package/dist/tools/linkedin.d.ts +210 -0
- package/dist/tools/linkedin.js +229 -0
- package/dist/tools/navigation.d.ts +91 -0
- package/dist/tools/navigation.js +381 -0
- package/dist/tools/one-off.d.ts +229 -0
- package/dist/tools/one-off.js +273 -0
- package/dist/tools/processing.d.ts +70 -0
- package/dist/tools/processing.js +56 -0
- package/dist/tools/prompts.d.ts +211 -0
- package/dist/tools/prompts.js +210 -0
- package/dist/tools/provider-preflight.d.ts +21 -0
- package/dist/tools/provider-preflight.js +59 -0
- package/dist/tools/readiness.d.ts +261 -0
- package/dist/tools/readiness.js +510 -0
- package/dist/tools/rows.d.ts +126 -0
- package/dist/tools/rows.js +105 -0
- package/dist/tools/rubrics.d.ts +497 -0
- package/dist/tools/rubrics.js +681 -0
- package/dist/tools/senders.d.ts +44 -0
- package/dist/tools/senders.js +69 -0
- package/dist/tools/sequencer.d.ts +127 -0
- package/dist/tools/sequencer.js +194 -0
- package/dist/tools/tables.d.ts +35 -0
- package/dist/tools/tables.js +36 -0
- package/dist/tools/verify-row.d.ts +36 -0
- package/dist/tools/verify-row.js +38 -0
- package/dist/tools/workspaces.d.ts +140 -0
- package/dist/tools/workspaces.js +139 -0
- package/dist/utils/workspace-root.d.ts +1 -0
- package/dist/utils/workspace-root.js +39 -0
- package/package.json +46 -0
- package/skills/building-gtm-tables/SKILL.md +216 -0
- package/skills/building-gtm-tables/core/auto-execute.yaml +19 -0
- package/skills/building-gtm-tables/core/blueprint-schema.json +72 -0
- package/skills/building-gtm-tables/references/brief-to-blueprint.md +334 -0
- package/skills/building-gtm-tables/references/column-type-catalog.md +318 -0
- package/skills/building-gtm-tables/references/common-blueprints.fixtures.ts +199 -0
- package/skills/building-gtm-tables/references/common-blueprints.md +44 -0
- package/skills/building-gtm-tables/references/failure-taxonomy.md +197 -0
- package/skills/building-gtm-tables/references/uat-seed-prompts.md +37 -0
- package/skills/building-gtm-tables/references/verify-loop.md +74 -0
- package/skills/campaign-messages/SKILL.md +173 -0
- package/skills/campaign-messages/flow.v1.json +75 -0
- package/skills/craft-message/SKILL.md +401 -0
- package/skills/create-campaign/ARCHITECTURE.md +232 -0
- package/skills/create-campaign/DISCUSS.md +296 -0
- package/skills/create-campaign/FLOW_ASCII.md +240 -0
- package/skills/create-campaign/HOST-PARITY-CHECKLIST.md +49 -0
- package/skills/create-campaign/README.md +142 -0
- package/skills/create-campaign/SKILL.md +286 -0
- package/skills/create-campaign/context/README.md +67 -0
- package/skills/create-campaign/context/_TEMPLATE.md +12 -0
- package/skills/create-campaign/context/context.md +35 -0
- package/skills/create-campaign/context/learnings.md +16 -0
- package/skills/create-campaign/context/registry.json +19 -0
- package/skills/create-campaign/core/flow.v1.json +217 -0
- package/skills/create-campaign/core/policy.md +191 -0
- package/skills/create-campaign/core/providers/apollo.json +35 -0
- package/skills/create-campaign/core/providers/prospeo.json +34 -0
- package/skills/create-campaign/core/providers/registry.json +31 -0
- package/skills/create-campaign/core/providers/sales-nav.json +37 -0
- package/skills/create-campaign/core/providers/signal-discovery.json +42 -0
- package/skills/create-campaign/references/brief-template.md +64 -0
- package/skills/create-campaign/references/campaign-quality.md +84 -0
- package/skills/create-campaign/references/copy-calibration-examples.md +120 -0
- package/skills/create-campaign/references/offer-patterns.md +108 -0
- package/skills/create-campaign/references/provider-selection-strategy.md +212 -0
- package/skills/create-campaign/references/question-examples.md +167 -0
- package/skills/create-campaign/references/token-fill-examples.md +81 -0
- package/skills/create-campaign-brief/ARCHITECTURE.md +72 -0
- package/skills/create-campaign-brief/DISCUSS.md +64 -0
- package/skills/create-campaign-brief/README.md +176 -0
- package/skills/create-campaign-brief/SKILL.md +537 -0
- package/skills/create-campaign-brief/references/brief-synthesis-rules.md +100 -0
- package/skills/create-campaign-brief/references/brief-template.md +220 -0
- package/skills/create-campaign-brief/references/campaign-idea-options.md +30 -0
- package/skills/create-campaign-brief/references/copy-appendix-template.md +62 -0
- package/skills/create-campaign-brief/references/draft-lifecycle.md +23 -0
- package/skills/create-campaign-brief/references/examples/MANIFEST.json +89 -0
- package/skills/create-campaign-brief/references/examples/briefs/clover.md +223 -0
- package/skills/create-campaign-brief/references/examples/briefs/galley.md +222 -0
- package/skills/create-campaign-brief/references/examples/briefs/gelee.md +220 -0
- package/skills/create-campaign-brief/references/examples/briefs/hey-digital.md +234 -0
- package/skills/create-campaign-brief/references/examples/briefs/persona.md +231 -0
- package/skills/create-campaign-brief/references/examples/briefs/revvix.md +220 -0
- package/skills/create-campaign-brief/references/examples/briefs/sellable-dev.md +220 -0
- package/skills/create-campaign-brief/references/examples/briefs/superposition.md +233 -0
- package/skills/create-campaign-brief/references/examples/briefs/superpower.md +219 -0
- package/skills/create-campaign-brief/references/examples/briefs/westpark-villas.md +220 -0
- package/skills/create-campaign-brief/references/icp-lock-question-bank.md +43 -0
- package/skills/create-campaign-brief/references/messaging-inputs.md +58 -0
- package/skills/create-campaign-brief/references/output-acceptance-rubric.md +62 -0
- package/skills/create-campaign-brief/references/phase75-active-runtime-message-pack.md +248 -0
- package/skills/create-campaign-brief/references/phase75-canonical-brief-template.md +319 -0
- package/skills/create-campaign-brief/references/phase75-good-brief-and-messaging-examples.md +445 -0
- package/skills/create-campaign-brief/references/quick-research-protocol.md +39 -0
- package/skills/create-campaign-brief/references/reference-sheet-protocol.md +60 -0
- package/skills/create-campaign-brief/references/zero-shot-iteration-rules.md +66 -0
- package/skills/create-campaign-v2/SKILL.md +1619 -0
- package/skills/create-campaign-v2/core/auto-execute.README.md +219 -0
- package/skills/create-campaign-v2/core/auto-execute.yaml +121 -0
- package/skills/create-campaign-v2/core/flow.v2.json +1643 -0
- package/skills/create-campaign-v2/core/policy.md +82 -0
- package/skills/create-campaign-v2/references/ai-tells.md +253 -0
- package/skills/create-campaign-v2/references/approval-gate-framing.md +346 -0
- package/skills/create-campaign-v2/references/draft-lifecycle.md +110 -0
- package/skills/create-campaign-v2/references/escalation-ladder.md +119 -0
- package/skills/create-campaign-v2/references/filter-leads.md +495 -0
- package/skills/create-campaign-v2/references/final-handoff-contract.md +176 -0
- package/skills/create-campaign-v2/references/gold-standard-message-examples.md +394 -0
- package/skills/create-campaign-v2/references/gold-standard-message-patterns.md +314 -0
- package/skills/create-campaign-v2/references/gold-standard-message-validation-example.md +212 -0
- package/skills/create-campaign-v2/references/lead-validation-preview.md +172 -0
- package/skills/create-campaign-v2/references/parallel-critique-protocol.md +368 -0
- package/skills/create-campaign-v2/references/sample-validation-loop.md +289 -0
- package/skills/create-campaign-v2/references/step-13-import-leads.md +151 -0
- package/skills/create-campaign-v2/references/step-15-re-cascade.md +90 -0
- package/skills/create-campaign-v2/references/thomas-revision-filters.md +521 -0
- package/skills/create-campaign-v2/references/thomas-variant-selection.md +202 -0
- package/skills/create-campaign-v2/references/tier-routing-matrix.md +66 -0
- package/skills/create-campaign-v2/references/validation-criteria.md +367 -0
- package/skills/create-campaign-v2/references/watch-link-handoff.md +106 -0
- package/skills/create-campaign-v2-validation/SKILL.md +296 -0
- package/skills/create-post/SKILL.md +1308 -0
- package/skills/create-rubric/SKILL.md +251 -0
- package/skills/engage/SKILL.md +549 -0
- package/skills/engage/core/README.md +23 -0
- package/skills/engage/core/proven-searches.json +11 -0
- package/skills/engage/core/style-guide.template.md +47 -0
- package/skills/engage/core/tracked-people.json +10 -0
- package/skills/enrich-prospects/SKILL.md +97 -0
- package/skills/find-leads/SKILL.md +467 -0
- package/skills/generate-messages/SKILL.md +2361 -0
- package/skills/interview/SKILL.md +132 -0
- package/skills/interview/core/ENGAGE_STYLE_GUIDE.template.md +54 -0
- package/skills/interview/core/ICP.template.md +54 -0
- package/skills/interview/core/VOICE_PROFILE.template.md +101 -0
- package/skills/providers/apollo.md +520 -0
- package/skills/providers/prospeo.md +398 -0
- package/skills/providers/sales-nav.md +372 -0
- package/skills/providers/signal-discovery.md +495 -0
- package/skills/research/SKILL.md +258 -0
- package/skills/research/config.json +9 -0
- package/skills/research/override.md +13 -0
- package/skills/research-prospect/SKILL.md +99 -0
- package/skills/research-sender/SKILL.md +158 -0
- 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.
|