@sellable/mcp 0.1.150 → 0.1.152
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/README.md +4 -3
- package/agents/post-find-leads-filter-scout.md +5 -4
- package/agents/post-find-leads-message-scout.md +17 -16
- package/agents/source-scout-linkedin-engagement.md +6 -5
- package/agents/source-scout-prospeo-contact.md +4 -4
- package/agents/source-scout-sales-nav.md +4 -4
- package/dist/index-dev.js +0 -0
- package/dist/index.js +0 -0
- package/dist/tools/cells.js +1 -1
- package/dist/tools/leads.d.ts +36 -3
- package/dist/tools/leads.js +83 -71
- package/dist/tools/prompts.d.ts +1 -0
- package/dist/tools/prompts.js +10 -9
- package/dist/tools/registry.d.ts +17 -0
- package/dist/tools/rubrics.js +23 -20
- package/package.json +1 -1
- package/skills/create-campaign/SKILL.md +64 -61
- package/skills/create-campaign-v2/SKILL.md +50 -55
- package/skills/create-campaign-v2/SOUL.md +16 -13
- package/skills/create-campaign-v2/core/auto-execute.README.md +16 -17
- package/skills/create-campaign-v2/core/auto-execute.yaml +8 -7
- package/skills/create-campaign-v2/core/flow.v2.json +84 -156
- package/skills/create-campaign-v2/core/policy.md +13 -12
- package/skills/create-campaign-v2/references/approval-gate-framing.md +11 -11
- package/skills/create-campaign-v2/references/filter-leads.md +5 -4
- package/skills/create-campaign-v2/references/lead-validation-preview.md +2 -2
- package/skills/create-campaign-v2/references/sample-validation-loop.md +32 -27
- package/skills/create-campaign-v2/references/step-13-import-leads.md +29 -28
- package/skills/create-campaign-v2/references/watch-guide-narration.md +27 -28
- package/skills/create-campaign-v2-tail/SKILL.md +44 -44
- package/skills/create-rubric/SKILL.md +5 -5
- package/skills/find-leads/SKILL.md +2 -2
- package/skills/generate-messages/SKILL.md +2 -1
- package/skills/providers/prospeo.md +3 -3
- package/skills/providers/sales-nav.md +7 -7
- package/skills/providers/signal-discovery.md +11 -11
- package/skills/create-campaign-v2/references/message-review-safety-gate.md +0 -162
|
@@ -51,8 +51,8 @@ Create and save a comprehensive lead scoring rubric that:
|
|
|
51
51
|
|
|
52
52
|
## Rubric Validation + Results
|
|
53
53
|
|
|
54
|
-
- `mcp__sellable__get_rows_minimal` - Read
|
|
55
|
-
- `mcp__sellable__queue_cells` - Queue only bounded `enrichCellId` values
|
|
54
|
+
- `mcp__sellable__get_rows_minimal` - Read first review/process sample cell IDs
|
|
55
|
+
- `mcp__sellable__queue_cells` - Queue only bounded sample `enrichCellId` values
|
|
56
56
|
- `mcp__sellable__wait_for_rubric_results` - Poll pass-rate results
|
|
57
57
|
|
|
58
58
|
`check_rubric` is legacy/recovery only. Do not use it in normal
|
|
@@ -207,8 +207,8 @@ update_campaign({
|
|
|
207
207
|
|
|
208
208
|
This triggers the campaign sync and moves the user to the filter-leads step where they can see the campaign table with scoring columns.
|
|
209
209
|
|
|
210
|
-
For normal create-campaign-v2 runs, the caller should
|
|
211
|
-
|
|
210
|
+
For normal create-campaign-v2 runs, the caller should queue only the first
|
|
211
|
+
review/process sample enrichment cells after message approval. For standalone
|
|
212
212
|
rubric editing, ask the user if we should kick off enrichment for a sample:
|
|
213
213
|
|
|
214
214
|
"ICP filtering enabled — you should see the leads table with scoring columns now. Want me to run enrichment on the first 5 leads to check pass rates?"
|
|
@@ -219,7 +219,7 @@ rubric editing, ask the user if we should kick off enrichment for a sample:
|
|
|
219
219
|
## Phase 5: Enrich + Score a Sample
|
|
220
220
|
|
|
221
221
|
1. Call `get_rows_minimal({ tableId, limit: 5 })` or use the caller-provided
|
|
222
|
-
|
|
222
|
+
review/process sample rows.
|
|
223
223
|
2. Call `queue_cells({ tableId, cellIds })` with only pending/error
|
|
224
224
|
`enrichCellId` values. Do not pass `icpCellId` values or full-table cells;
|
|
225
225
|
the workflow cascade handles downstream ICP scoring after enrichment.
|
|
@@ -162,9 +162,9 @@ Execution flow:
|
|
|
162
162
|
- `campaignOfferId`
|
|
163
163
|
- `sourceLeadListId` (or omit to use `selectedLeadListId`)
|
|
164
164
|
- `jobId` (from `import_leads` when available; omit for direct CSV lead lists)
|
|
165
|
-
- `
|
|
165
|
+
- `reviewBatchLimit: 15` for the first review/process sample
|
|
166
166
|
9. For campaign-builder flows, `confirm_lead_list` owns the watched move to
|
|
167
|
-
`filter-choice` after the
|
|
167
|
+
`filter-choice` after the first review/process sample exists. Then run:
|
|
168
168
|
- `wait_for_campaign_table_ready({ campaignId })`
|
|
169
169
|
- `get_campaign_context({ campaignId, refresh: true })`
|
|
170
170
|
- `get_rows_minimal({ tableId: workflowTableId, limit: 10, page: 1 })`
|
|
@@ -28,7 +28,8 @@ You craft messages in one of two modes:
|
|
|
28
28
|
### Mode 0: Message Draft Builder Branch
|
|
29
29
|
|
|
30
30
|
Use this mode when create-campaign-v2 starts the background Message Draft
|
|
31
|
-
Builder after `confirm_lead_list`
|
|
31
|
+
Builder after `confirm_lead_list` copies source rows and the first
|
|
32
|
+
review/process sample exists.
|
|
32
33
|
This is not the row-cell generation path.
|
|
33
34
|
|
|
34
35
|
Inputs must come from the parent thread or scoped MCP/product tools for the
|
|
@@ -62,14 +62,14 @@ search_prospeo({
|
|
|
62
62
|
- Pass `searchId` on subsequent pages to paginate.
|
|
63
63
|
- Use `import_leads` with `provider: \"prospeo\"` and the `searchId` to create a lead list and start import.
|
|
64
64
|
- **IMPORTANT:** If `import_leads` returns `needsModeSelection: true`, use `AskUserQuestion` to ask "add to existing leads or replace?" Do NOT assume.
|
|
65
|
-
- Default source target is about
|
|
65
|
+
- Default source import target is about 1,000 source contacts. Use the provider cap internally when the raw pool is larger; do not present that cap as the customer-facing plan unless it is reached.
|
|
66
66
|
- Apply the campaign source planning floor: the sampled/projected good-fit rate
|
|
67
67
|
after cleanup should be at least 10%. Prospeo is the terminal fallback; if the
|
|
68
68
|
best reasonable Prospeo lane is still below 10%, tighten the ICP/source
|
|
69
69
|
direction instead of switching to another provider.
|
|
70
|
-
- After the list finishes and the user confirms it looks good, call `confirm_lead_list` with the `jobId` and
|
|
70
|
+
- After the list finishes and the user confirms it looks good, call `confirm_lead_list` with the `jobId` and `reviewBatchLimit: 15` to copy confirmed rows into the campaign table and use the first 15 as the review/process sample.
|
|
71
71
|
- `import_leads` owns the watched move to `confirm-lead-list` after a lead list/job exists.
|
|
72
|
-
- `confirm_lead_list` owns the watched move to `filter-choice` after
|
|
72
|
+
- `confirm_lead_list` owns the watched move to `filter-choice` after confirmed campaign rows exist.
|
|
73
73
|
- Post-confirm readback order is required:
|
|
74
74
|
1. `wait_for_campaign_table_ready({ campaignId })`
|
|
75
75
|
2. `get_campaign_context({ campaignId, refresh: true })` then `get_rows_minimal(...)` for recommendation
|
|
@@ -354,9 +354,9 @@ Step 4 - Final Search + Confirm:
|
|
|
354
354
|
What would you like?"
|
|
355
355
|
|
|
356
356
|
User: "Save it"
|
|
357
|
-
→ import_leads({campaignOfferId: "cmp_xxx", searchId: "search_xxx", targetLeadCount:
|
|
357
|
+
→ import_leads({campaignOfferId: "cmp_xxx", searchId: "search_xxx", targetLeadCount: 1000})
|
|
358
358
|
→ (wait for lead list to finish, ask user to confirm)
|
|
359
|
-
→ confirm_lead_list({campaignOfferId: "cmp_xxx", jobId: "<jobId from import_leads>",
|
|
359
|
+
→ confirm_lead_list({campaignOfferId: "cmp_xxx", jobId: "<jobId from import_leads>", reviewBatchLimit: 15})
|
|
360
360
|
→ wait_for_campaign_table_ready({campaignId: "cmp_xxx"})
|
|
361
361
|
→ get_campaign_context({campaignId: "cmp_xxx", refresh: true}) + get_rows_minimal(...)
|
|
362
362
|
</iteration_example>
|
|
@@ -378,17 +378,17 @@ User: "Save it"
|
|
|
378
378
|
Call after user selects a search to save
|
|
379
379
|
**IMPORTANT:** If response returns `needsModeSelection: true`, use `AskUserQuestion` to ask "add to existing leads or replace?" Do NOT assume.
|
|
380
380
|
|
|
381
|
-
- `confirm_lead_list` -
|
|
382
|
-
Parameters: campaignOfferId, sourceLeadListId (optional), currentStep (optional)
|
|
381
|
+
- `confirm_lead_list` - Copy confirmed lead list into campaign table
|
|
382
|
+
Parameters: campaignOfferId, sourceLeadListId (optional), reviewBatchLimit (optional, default 15), currentStep (optional)
|
|
383
383
|
Only call after user confirms the list looks good
|
|
384
|
-
Owns the filter-choice beat after
|
|
384
|
+
Owns the filter-choice beat after campaign rows exist; process only the first 15 review rows until later approvals
|
|
385
385
|
</mcp_tools>
|
|
386
386
|
|
|
387
387
|
<limits>
|
|
388
388
|
- 25 results per page
|
|
389
389
|
- Maximum 100 pages (2,500 leads)
|
|
390
|
-
- Default source target: about
|
|
391
|
-
|
|
390
|
+
- Default source import target: about 1,000 source contacts. The provider cap is
|
|
391
|
+
internal; do not present it as the customer-facing plan unless it is reached.
|
|
392
392
|
- Maximum 5 search calls per session
|
|
393
393
|
- If user needs more than 2,500: explain limit, suggest splitting by region
|
|
394
394
|
</limits>
|
|
@@ -450,15 +450,16 @@ to say **yes**.
|
|
|
450
450
|
|
|
451
451
|
For `create-campaign-v2` after the user has already approved the lead-source
|
|
452
452
|
decision, that approval is the explicit confirmation to materialize the approved
|
|
453
|
-
source list and then
|
|
453
|
+
source list and then copy the confirmed source rows into the campaign. In that
|
|
454
454
|
tail flow, follow `create-campaign-v2-tail`: call
|
|
455
455
|
`select_promising_posts({ campaignOfferId, selectionMode: "replace",
|
|
456
456
|
selections, headlineICPCriteria })`, then call
|
|
457
457
|
`import_leads({ campaignOfferId, provider: "signal-discovery",
|
|
458
|
-
|
|
458
|
+
targetEngagerCount, maxPostsToScrape })` for the approved
|
|
459
459
|
source-capacity plan without asking for another yes/no gate. Then
|
|
460
|
-
`confirm_lead_list
|
|
461
|
-
table
|
|
460
|
+
`confirm_lead_list({ reviewBatchLimit: 15 })` copies confirmed source rows into
|
|
461
|
+
the campaign table and returns the first 15 review/process rows. Do not confuse
|
|
462
|
+
the source-candidate target with the review sample size.
|
|
462
463
|
If the completed source scrape comes back below the approved source-candidate
|
|
463
464
|
target, do not call `confirm_lead_list`; select more posts, rerun source
|
|
464
465
|
discovery, or move to Sales Nav.
|
|
@@ -474,9 +475,8 @@ the source-list materialization.
|
|
|
474
475
|
```json
|
|
475
476
|
import_leads({
|
|
476
477
|
"campaignOfferId": "cmp_xxx",
|
|
477
|
-
"
|
|
478
|
-
"
|
|
479
|
-
"maxPostsToScrape": 5
|
|
478
|
+
"targetEngagerCount": 1500,
|
|
479
|
+
"maxPostsToScrape": 3
|
|
480
480
|
})
|
|
481
481
|
```
|
|
482
482
|
|
|
@@ -488,13 +488,13 @@ After the lead list finishes and the user confirms it looks good, call:
|
|
|
488
488
|
confirm_lead_list({
|
|
489
489
|
"campaignOfferId": "cmp_xxx",
|
|
490
490
|
"jobId": "<jobId from import_leads>",
|
|
491
|
-
"
|
|
491
|
+
"reviewBatchLimit": 15
|
|
492
492
|
})
|
|
493
493
|
```
|
|
494
494
|
|
|
495
495
|
Then run post-confirm routing in this order:
|
|
496
496
|
|
|
497
|
-
1. `confirm_lead_list` owns the watched move to `filter-choice` after
|
|
497
|
+
1. `confirm_lead_list` owns the watched move to `filter-choice` after confirmed campaign rows exist; do not call `update_campaign` to fix that step.
|
|
498
498
|
2. `wait_for_campaign_table_ready({ campaignId: "cmp_xxx" })`
|
|
499
499
|
3. `get_campaign_context({ campaignId: "cmp_xxx", refresh: true })` then `get_rows_minimal(...)`
|
|
500
500
|
|
|
@@ -516,8 +516,8 @@ Then run post-confirm routing in this order:
|
|
|
516
516
|
5. Standalone Signal Discovery flow: ask for explicit confirmation to import
|
|
517
517
|
leads (e.g., "Does this look right? Should I import leads now?").
|
|
518
518
|
`create-campaign-v2` tail flow: if the user already approved the source
|
|
519
|
-
decision, that approval is the import confirmation for the
|
|
520
|
-
|
|
519
|
+
decision, that approval is the import confirmation for the source list and
|
|
520
|
+
first review sample; do not ask again.
|
|
521
521
|
6. If confirmation exists, call `import_leads`. If not, refine
|
|
522
522
|
selections/criteria and ask again.
|
|
523
523
|
7. When the lead list finishes and the user confirms it looks good, call
|
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
# Message Review Safety Gate
|
|
2
|
-
|
|
3
|
-
Use this reference for `create-campaign-v2` message review only in two cases:
|
|
4
|
-
when these rules are embedded inside the `post-find-leads-message-scout` agent
|
|
5
|
-
prompt, or when the host cannot launch that agent and the parent thread needs a
|
|
6
|
-
self-contained safety gate. It is the campaign-launch subset of
|
|
7
|
-
`generate-messages`: enough to prove a truthful first-send message, rendered
|
|
8
|
-
token examples, and an approval decision without loading the full long-form
|
|
9
|
-
message-generation prompt into the main Claude/Codex thread.
|
|
10
|
-
|
|
11
|
-
In a normal installed Claude/Codex session, the message scout owns these rules.
|
|
12
|
-
The parent-thread asset is a compatibility safety path, not a fast-mode prompt
|
|
13
|
-
or a shortcut. Do not load the full `generate-messages` subskill in this flow. If
|
|
14
|
-
the safety gate is missing a needed campaign-specific rule or the draft fails
|
|
15
|
-
quality gates, stop at `revise-messaging` with the exact missing rule/failure
|
|
16
|
-
instead of pulling the long prompt into the main thread.
|
|
17
|
-
|
|
18
|
-
## Required Workflow
|
|
19
|
-
|
|
20
|
-
1. Read the live campaign basis: campaign id, campaign revision or
|
|
21
|
-
`campaignUpdatedAt`, campaign brief content, selected source decision,
|
|
22
|
-
selected lead list/source state, `workflowTableId`, imported review-batch
|
|
23
|
-
row ids/hash, and any saved rubric/filter summary supplied by the parent.
|
|
24
|
-
2. Pick 2-3 sample rows from the imported review-batch rows, preferring rows
|
|
25
|
-
that pass the saved rubrics or are likely to pass. Do not invent new rows.
|
|
26
|
-
3. Build the message from the approved campaign brief, selected source context,
|
|
27
|
-
sampled rows, and explicit user answers. Use only proof that appears in that
|
|
28
|
-
live basis. Unsupported reply-rate, meeting-rate, ROI, revenue, and
|
|
29
|
-
customer-logo claims are blocked.
|
|
30
|
-
4. Return a compact message recommendation to the parent thread. Do not write
|
|
31
|
-
local markdown/json artifacts in normal customer runs; emit debug artifacts
|
|
32
|
-
only when the parent explicitly asks for debug/UAT output.
|
|
33
|
-
5. Render the customer-facing message review in chat before asking for approval.
|
|
34
|
-
Keep chat lightweight: show the tokenized template and one strong rendered
|
|
35
|
-
good-fill example only. Do not print the token notes table, omit/fallback
|
|
36
|
-
example, or bad-fill analysis in chat unless the user explicitly asks.
|
|
37
|
-
After approval, the parent persists template, token rules, fallback guidance,
|
|
38
|
-
and bad-fill avoidance notes into campaign state with `update_campaign_brief`.
|
|
39
|
-
6. Ask exactly `approve-message` or `revise-messaging`. Do not import, queue,
|
|
40
|
-
attach sequence, or start before `approve-message`.
|
|
41
|
-
|
|
42
|
-
## Required Message Recommendation Sections
|
|
43
|
-
|
|
44
|
-
- `Status`
|
|
45
|
-
- `Mode`
|
|
46
|
-
- `Lead Sample Basis`
|
|
47
|
-
- `Strongest Reply Reason`
|
|
48
|
-
- `Campaign Element Pool`
|
|
49
|
-
- `Gold Standard Strategy Map`
|
|
50
|
-
- `Current Campaign Translation`
|
|
51
|
-
- `Token Fill Rules`
|
|
52
|
-
- `Token Adherence Table`
|
|
53
|
-
- `Angle Drafts`
|
|
54
|
-
- `Kill / Combine Review`
|
|
55
|
-
- `Finalizer Pass`
|
|
56
|
-
- `Gold-Standard Quality Gate`
|
|
57
|
-
- `Skeptical Prospect Review`
|
|
58
|
-
- `Winner Gate`
|
|
59
|
-
- `Selected Winner`
|
|
60
|
-
- `Findings`
|
|
61
|
-
- `Recommendation`
|
|
62
|
-
|
|
63
|
-
Keep this recommendation concise. It should prove the reasoning path, not
|
|
64
|
-
reproduce the full framework.
|
|
65
|
-
|
|
66
|
-
## Message Quality Gates
|
|
67
|
-
|
|
68
|
-
- The selected winner must be one first outbound send only. No post-accept DM,
|
|
69
|
-
follow-up, cadence branch, or sequence copy.
|
|
70
|
-
- The message must explain what the product is and what it does in plain
|
|
71
|
-
language before asking for a call.
|
|
72
|
-
- The message must use a truthful buyer-side reply reason, not just sender
|
|
73
|
-
biography.
|
|
74
|
-
- If using a template, include at least one supported `{{token}}` and show a
|
|
75
|
-
complete rendered good-fill example and complete rendered omit/fallback
|
|
76
|
-
example.
|
|
77
|
-
- Do not use internal tokens such as `{{profile_signal}}` in customer-facing
|
|
78
|
-
copy.
|
|
79
|
-
- Do not put bracketed instructions in the message body, such as `[ROW_BRIDGE]`,
|
|
80
|
-
`[insert]`, `[generated]`, or any instruction for a later model to fill.
|
|
81
|
-
- Optional row-specific personalization must be grounded in a row field or
|
|
82
|
-
omitted entirely. Never use generic filler like "your work" or "your team."
|
|
83
|
-
- Engagement-source personalization is a special case, not the default opener.
|
|
84
|
-
Do not write `saw you {{engagement_context}} on {{post_context}}`, `saw you
|
|
85
|
-
reacted to`, `saw you engaging with`, or equivalent source-citation copy as a
|
|
86
|
-
default hook. Only refer to the prospect's engagement when the line is
|
|
87
|
-
self-aware and low-certainty, for example `not sure if this is too specific,
|
|
88
|
-
but the [topic] thread felt close enough to send`. Otherwise omit the
|
|
89
|
-
engagement signal and use role/company/problem context.
|
|
90
|
-
- Subject lines should be short, buyer-relevant, and specific. Avoid
|
|
91
|
-
`quick question`, `demo`, `founder call`, sender names, and generic `outbound`.
|
|
92
|
-
- If the message is plausible but not ready to send, set
|
|
93
|
-
`Recommendation: revise-messaging`.
|
|
94
|
-
|
|
95
|
-
## Internal Message Recommendation
|
|
96
|
-
|
|
97
|
-
The message scout or parent safety gate should still produce complete internal
|
|
98
|
-
review data: token-fill rules, one rendered omit/fallback example, and bad-fill
|
|
99
|
-
avoidance notes. This data is for campaign-brief persistence and safety checks,
|
|
100
|
-
not for the default chat approval packet.
|
|
101
|
-
|
|
102
|
-
## Customer-Facing Message Review
|
|
103
|
-
|
|
104
|
-
Render this in chat before asking. Use Markdown structure so the approval target
|
|
105
|
-
is visually scannable and low-overhead:
|
|
106
|
-
|
|
107
|
-
````markdown
|
|
108
|
-
Status: message-review
|
|
109
|
-
|
|
110
|
-
## Message Template
|
|
111
|
-
|
|
112
|
-
**Subject**
|
|
113
|
-
|
|
114
|
-
```text
|
|
115
|
-
{{tokenized_subject}}
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
**Body**
|
|
119
|
-
|
|
120
|
-
```text
|
|
121
|
-
{{tokenized_message_body}}
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
## Rendered Example
|
|
125
|
-
|
|
126
|
-
### Example
|
|
127
|
-
|
|
128
|
-
Good token fill:
|
|
129
|
-
|
|
130
|
-
```text
|
|
131
|
-
Subject: ...
|
|
132
|
-
|
|
133
|
-
Hey First,
|
|
134
|
-
|
|
135
|
-
...
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
## Recommendation
|
|
139
|
-
|
|
140
|
-
**My take:** ...
|
|
141
|
-
|
|
142
|
-
**Suggested adjustment:** ...
|
|
143
|
-
|
|
144
|
-
**Question:** approve-message or revise-messaging?
|
|
145
|
-
|
|
146
|
-
**Recommendation:** approve-message
|
|
147
|
-
````
|
|
148
|
-
|
|
149
|
-
Formatting requirements:
|
|
150
|
-
|
|
151
|
-
- Put the tokenized template and rendered example in fenced `text` blocks
|
|
152
|
-
so chat gives them a distinct background.
|
|
153
|
-
- The chat example must contain a complete rendered subject + body, not a
|
|
154
|
-
bullet list of token names or a single bridge-line fragment.
|
|
155
|
-
- Do not show `Good omit / fallback`, `Bad fill to avoid`, or `Token Notes` in
|
|
156
|
-
the default chat approval packet. Keep those in the internal recommendation
|
|
157
|
-
and persist them to the campaign brief after approval.
|
|
158
|
-
- Keep reasoning outside the code blocks so the blocks are easy to inspect and
|
|
159
|
-
approve.
|
|
160
|
-
|
|
161
|
-
`My take` and `Suggested adjustment` must be specific. The adjustment can be
|
|
162
|
-
"approve as-is, or revise once to X if you want Y"; it must not be empty.
|