@sellable/mcp 0.1.82 → 0.1.84
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/dist/tools/senders.js +1 -1
- package/dist/update-check.js +4 -2
- package/package.json +1 -1
- package/skills/create-campaign/SKILL.md +48 -92
- package/skills/create-campaign-v2/SKILL.md +71 -118
- package/skills/create-campaign-v2/core/flow.v2.json +5 -6
- package/skills/create-campaign-v2/references/lead-validation-preview.md +5 -5
- package/skills/create-campaign-v2/references/validation-criteria.md +12 -8
- package/skills/find-leads/SKILL.md +7 -4
package/dist/tools/senders.js
CHANGED
|
@@ -28,7 +28,7 @@ function computeLinkedinProfileUrl(sender) {
|
|
|
28
28
|
export const senderToolDefinitions = [
|
|
29
29
|
{
|
|
30
30
|
name: "list_senders",
|
|
31
|
-
description: "List outbound sender identities available in the active workspace.
|
|
31
|
+
description: "List outbound sender identities available in the active workspace. In create-campaign flows, use this at Settings/final launch handoff to verify available connected senders; do not use it as first intake when campaign identity/client prospect context is still being gathered.",
|
|
32
32
|
inputSchema: {
|
|
33
33
|
type: "object",
|
|
34
34
|
properties: {},
|
package/dist/update-check.js
CHANGED
|
@@ -77,12 +77,14 @@ function isVersionOutdated(currentVersion, latestVersion) {
|
|
|
77
77
|
}
|
|
78
78
|
return false;
|
|
79
79
|
}
|
|
80
|
-
function readCache(ttlMs) {
|
|
80
|
+
function readCache(ttlMs, currentVersion) {
|
|
81
81
|
const file = cachePath();
|
|
82
82
|
try {
|
|
83
83
|
const raw = JSON.parse(fs.readFileSync(file, "utf8"));
|
|
84
84
|
if (!raw.checkedAtMs || Date.now() - raw.checkedAtMs > ttlMs)
|
|
85
85
|
return null;
|
|
86
|
+
if (raw.mcp?.currentVersion !== currentVersion)
|
|
87
|
+
return null;
|
|
86
88
|
return {
|
|
87
89
|
...raw,
|
|
88
90
|
cachePath: file,
|
|
@@ -157,7 +159,7 @@ export async function checkForUpdates(options) {
|
|
|
157
159
|
return disabledStatus(currentVersion);
|
|
158
160
|
}
|
|
159
161
|
if (!options?.force) {
|
|
160
|
-
const cached = readCache(ttlMs);
|
|
162
|
+
const cached = readCache(ttlMs, currentVersion);
|
|
161
163
|
if (cached)
|
|
162
164
|
return cached;
|
|
163
165
|
}
|
package/package.json
CHANGED
|
@@ -81,9 +81,9 @@ instruction loading, file lookup, plugin cache versions, missing linked files,
|
|
|
81
81
|
or tool discovery. Start in product language:
|
|
82
82
|
|
|
83
83
|
```text
|
|
84
|
-
I’ll help you launch this as a Sellable campaign. First I’ll
|
|
85
|
-
|
|
86
|
-
|
|
84
|
+
I’ll help you launch this as a Sellable campaign. First I’ll resolve the
|
|
85
|
+
client/company this campaign is for, then I’ll turn that into a campaign brief
|
|
86
|
+
before any leads are imported or anything can send.
|
|
87
87
|
```
|
|
88
88
|
|
|
89
89
|
If a linked/local skill file is stale or missing, silently use the installed
|
|
@@ -108,6 +108,13 @@ rows, sampled people, sampled fits as n/N (%), estimated usable people, and the
|
|
|
108
108
|
confidence basis. Never show a percent like "73% match" without the numerator,
|
|
109
109
|
denominator, and sample basis.
|
|
110
110
|
|
|
111
|
+
Do not forecast LinkedIn connection acceptance rates, reply rates, meetings,
|
|
112
|
+
pipeline, revenue, or ROI in customer-facing source reviews unless the user
|
|
113
|
+
supplied verified benchmark data for this exact workspace/sender. Without that
|
|
114
|
+
data, compare sources by source volume, sampled ICP fit, activity/warmth
|
|
115
|
+
signals, cleanup risk, and confidence basis. If a user asks for a forecast,
|
|
116
|
+
label it explicitly as not estimated from this run.
|
|
117
|
+
|
|
111
118
|
When the user has not supplied a source and multiple source angles are viable,
|
|
112
119
|
scout those angles as independent branches when the host can actually do it:
|
|
113
120
|
LinkedIn Engagement / active post engagers (internal `signal-discovery`
|
|
@@ -235,106 +242,56 @@ customer-facing progress copy.
|
|
|
235
242
|
|
|
236
243
|
Do not treat the active Sellable workspace as the campaign subject. The
|
|
237
244
|
workspace only tells you where the campaign will be saved. Before buyer, CTA,
|
|
238
|
-
proof, or source questions, identify
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
245
|
+
proof, or source questions, identify the campaign identity: the person/profile
|
|
246
|
+
or company this campaign is for, plus enough company/product context to build
|
|
247
|
+
the brief. This is only the client-prospect/bootstrap identity for
|
|
248
|
+
`clientProspectId` or `senderLinkedinUrl`; it is not a connected-sender check.
|
|
249
|
+
|
|
250
|
+
Do not call `mcp__sellable__list_senders`, `mcp__sellable__get_sender`, or
|
|
251
|
+
surface connected/missing sender state during setup, brief, source, filter, or
|
|
252
|
+
message review. Sender availability belongs only to the Settings/final launch
|
|
253
|
+
handoff after message approval and the 10-lead validation sample.
|
|
254
|
+
|
|
255
|
+
If the invocation or user answer includes an existing `clientProspectId`, keep
|
|
256
|
+
it as the preferred `create_campaign` identity input. If it includes a LinkedIn
|
|
257
|
+
profile URL, keep that URL as `senderLinkedinUrl` so the backend can
|
|
258
|
+
resolve/materialize the sender prospect when the watchable campaign shell is
|
|
259
|
+
created. Do not require a connected sender before shell creation.
|
|
242
260
|
|
|
243
261
|
If the user supplied a LinkedIn profile, website, domain, company name, or
|
|
244
|
-
|
|
262
|
+
explicit client prospect identity in the invocation, do one lightweight lookup
|
|
263
|
+
first:
|
|
245
264
|
|
|
246
265
|
- LinkedIn profile: call `mcp__sellable__fetch_linkedin_profile`.
|
|
247
266
|
- Website/domain/company: call `mcp__sellable__fetch_company` when possible,
|
|
248
267
|
otherwise one web lookup.
|
|
249
|
-
-
|
|
250
|
-
|
|
268
|
+
- Existing client prospect id: use it directly and do one company/profile lookup
|
|
269
|
+
only if a URL/domain is also available.
|
|
251
270
|
|
|
252
271
|
Then summarize what you found in one or two lines and ask the user to confirm
|
|
253
|
-
the campaign
|
|
254
|
-
|
|
255
|
-
If the user did not provide the launch identity, quietly call
|
|
256
|
-
`mcp__sellable__list_senders` once if available. This is a shortcut to deduce
|
|
257
|
-
who the user might be from their Sellable API token and connected LinkedIn
|
|
258
|
-
accounts. Do not ask the user to pick an input type before checking connected
|
|
259
|
-
senders. If there is any likely connected sender, use
|
|
260
|
-
`mcp__sellable__enrich_sender` on the best match to infer their current or most
|
|
261
|
-
recent company, then ask a structured confirmation question:
|
|
262
|
-
|
|
263
|
-
```text
|
|
264
|
-
I’m ready to build this in {workspace}. I found {matched sender} connected here.
|
|
265
|
-
|
|
266
|
-
Is that you, and is this campaign for {company}?
|
|
267
|
-
```
|
|
268
|
-
|
|
269
|
-
The structured options must be no more than three choices:
|
|
270
|
-
|
|
271
|
-
1. `Yes — use {matched sender} for {company}`
|
|
272
|
-
2. `No — I'll paste a LinkedIn profile`
|
|
273
|
-
3. `Use a company domain instead`
|
|
274
|
-
|
|
275
|
-
If there are multiple likely connected senders, mention the best one in the
|
|
276
|
-
question and use option 2 for either a different connected sender or a pasted
|
|
277
|
-
LinkedIn profile.
|
|
278
|
-
|
|
279
|
-
Use the structured question tool only for the choice. Do not use
|
|
280
|
-
`request_user_input`/`AskUserQuestion` to collect a LinkedIn URL, company
|
|
281
|
-
domain, or freeform text. If the user chooses option 2, ask in normal chat:
|
|
282
|
-
`Paste the LinkedIn URL I should use, and I’ll look it up.` Then call
|
|
283
|
-
`mcp__sellable__fetch_linkedin_profile`, infer their current or most recent
|
|
284
|
-
company, and confirm company and sender again. If the user chooses option 3, ask
|
|
285
|
-
in normal chat: `Paste the company domain, and I’ll do a quick lookup before we
|
|
286
|
-
keep going.` Then call `mcp__sellable__fetch_company` when possible, otherwise
|
|
287
|
-
one web lookup, and ask who the LinkedIn messages should send from.
|
|
288
|
-
|
|
289
|
-
If `mcp__sellable__list_senders` returns zero connected senders, avoid the
|
|
290
|
-
sender-confirmation branch entirely. Do not ask the user to choose an input type
|
|
291
|
-
with the structured question tool. Ask in normal chat for the user's LinkedIn
|
|
292
|
-
URL or the company they want to send on behalf of so you can research context:
|
|
293
|
-
|
|
294
|
-
```text
|
|
295
|
-
I’m ready to build this in {workspace}.
|
|
296
|
-
|
|
297
|
-
First, paste your LinkedIn URL or the company website you want to send on
|
|
298
|
-
behalf of. I’ll use that to understand the company before we pick the target,
|
|
299
|
-
offer, proof, and lead source.
|
|
300
|
-
```
|
|
272
|
+
the campaign identity/focus before continuing. Do not mention connected sender
|
|
273
|
+
availability in this confirmation.
|
|
301
274
|
|
|
302
|
-
If
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
current or most recent company, and then confirm who we are sending from. The
|
|
306
|
-
customer-facing shape should be:
|
|
275
|
+
If the user did not provide the launch identity, ask in normal chat for the
|
|
276
|
+
LinkedIn profile or company website to use as the campaign identity. Do not ask
|
|
277
|
+
them to choose an input type with the structured question tool:
|
|
307
278
|
|
|
308
279
|
```text
|
|
309
280
|
I’m ready to build this in {workspace}.
|
|
310
281
|
|
|
311
|
-
First,
|
|
312
|
-
the
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
After the user pastes a URL/domain, do the lightweight lookup. For a LinkedIn profile, call
|
|
316
|
-
`mcp__sellable__fetch_linkedin_profile` and infer the user's current or most
|
|
317
|
-
recent company from the profile. For a company website, call
|
|
318
|
-
`mcp__sellable__fetch_company` when possible, otherwise one web lookup.
|
|
319
|
-
|
|
320
|
-
If `mcp__sellable__list_senders` did not already run, call it once after the
|
|
321
|
-
lookup to see whether the fetched user appears to match a connected sender. If
|
|
322
|
-
there is a likely match, ask:
|
|
323
|
-
|
|
324
|
-
```text
|
|
325
|
-
Cool — are you {matched sender}, and is this campaign for {company}?
|
|
326
|
-
```
|
|
327
|
-
|
|
328
|
-
If there is no likely sender match, ask:
|
|
329
|
-
|
|
330
|
-
```text
|
|
331
|
-
Cool — I have this campaign as {company}. Who should the LinkedIn messages send from?
|
|
282
|
+
First, paste the LinkedIn profile or company website for the client/company this
|
|
283
|
+
campaign is for. I’ll use that to resolve the campaign identity before we pick
|
|
284
|
+
the target, offer, proof, and lead source.
|
|
332
285
|
```
|
|
333
286
|
|
|
334
|
-
|
|
335
|
-
|
|
287
|
+
After the user pastes a URL/domain, do the lightweight lookup. For a LinkedIn
|
|
288
|
+
profile, call `mcp__sellable__fetch_linkedin_profile` and infer the current or
|
|
289
|
+
most recent company from the profile. For a company website, call
|
|
290
|
+
`mcp__sellable__fetch_company` when possible, otherwise one web lookup. If a
|
|
291
|
+
LinkedIn profile URL is available, retain it as `senderLinkedinUrl` for
|
|
292
|
+
`create_campaign`; if a `clientProspectId` is available, pass that instead.
|
|
336
293
|
|
|
337
|
-
After the user confirms the
|
|
294
|
+
After the user confirms the campaign identity, run one lightweight company
|
|
338
295
|
lookup if it has not already run, then ask the campaign setup questions. The
|
|
339
296
|
setup questions should use the confirmed company context so they do not feel
|
|
340
297
|
generic.
|
|
@@ -344,12 +301,11 @@ Before the identity gate, use this customer-facing shape:
|
|
|
344
301
|
```text
|
|
345
302
|
I’m ready to build the campaign in {workspace}.
|
|
346
303
|
|
|
347
|
-
First I’ll
|
|
348
|
-
|
|
349
|
-
that to understand the company before we choose the target, offer, proof, and
|
|
350
|
-
lead source.
|
|
304
|
+
First I’ll resolve the client/company this campaign is for. I’ll use that
|
|
305
|
+
context to choose the target, offer, proof, and lead source.
|
|
351
306
|
|
|
352
|
-
Then I’ll turn that into a campaign brief for you to approve before any leads
|
|
307
|
+
Then I’ll turn that into a campaign brief for you to approve before any leads
|
|
308
|
+
are imported or anything can send.
|
|
353
309
|
```
|
|
354
310
|
|
|
355
311
|
Do not silently ask Codex intake or approval questions as plain chat when
|
|
@@ -9,9 +9,9 @@ visibility: internal
|
|
|
9
9
|
<role>
|
|
10
10
|
You are the create-campaign-v2 orchestrator. Your job is to execute the
|
|
11
11
|
configured `core/flow.v2.json` state machine from scratch: (1) interview the
|
|
12
|
-
user, resolve
|
|
13
|
-
with the v1 brief already attached, (2) use that campaign id for
|
|
14
|
-
selection, (3) import/confirm the first 10-row review batch to establish
|
|
12
|
+
user, resolve campaign identity/client-prospect context, and create a watchable
|
|
13
|
+
campaign shell with the v1 brief already attached, (2) use that campaign id for
|
|
14
|
+
source selection, (3) import/confirm the first 10-row review batch to establish
|
|
15
15
|
`workflowTableId`, (4) create rubrics and message artifacts from that campaign
|
|
16
16
|
table sample, (5) sync the approved message set into the campaign brief, and
|
|
17
17
|
(6) queue/observe the bounded cascade before settings, sequence, and start.
|
|
@@ -20,7 +20,7 @@ table sample, (5) sync the approved message set into the campaign brief, and
|
|
|
20
20
|
<objective>
|
|
21
21
|
Run the configured JSON flow in durable stages:
|
|
22
22
|
|
|
23
|
-
0. identity/source intake + watchable campaign shell with v1 brief
|
|
23
|
+
0. client identity/source intake + watchable campaign shell with v1 brief
|
|
24
24
|
1. create-campaign-brief
|
|
25
25
|
2. find leads with the campaign id
|
|
26
26
|
3. import/confirm the first 10-row review batch
|
|
@@ -81,8 +81,9 @@ Validated draft directory:
|
|
|
81
81
|
- Net-new runs start at `bootstrap` -> `brief-interview` in
|
|
82
82
|
`core/flow.v2.json`. Do not start at `validate-artifacts` unless resuming a
|
|
83
83
|
compatibility run where all upstream artifacts already exist.
|
|
84
|
-
- New runs create a watchable campaign shell after
|
|
85
|
-
campaign focus, source intake, and the v1 brief are known.
|
|
84
|
+
- New runs create a watchable campaign shell after campaign identity/client
|
|
85
|
+
prospect context, campaign focus, source intake, and the v1 brief are known.
|
|
86
|
+
The shell is a
|
|
86
87
|
`CampaignOffer` at `currentStep: "create-offer"` with a real v1 brief and a
|
|
87
88
|
`watchUrl`; when the user opens it they should see the brief, not an empty
|
|
88
89
|
campaign. If shell creation fails, stop and surface the error. There is no
|
|
@@ -175,104 +176,51 @@ Validated draft directory:
|
|
|
175
176
|
blocks for review surfaces.
|
|
176
177
|
- Do not treat the active Sellable workspace as the campaign subject. The
|
|
177
178
|
workspace only tells you where the campaign will be saved. Before buyer, CTA,
|
|
178
|
-
proof, or source questions, identify
|
|
179
|
-
|
|
180
|
-
|
|
179
|
+
proof, or source questions, identify the campaign identity: the person/profile
|
|
180
|
+
or company this campaign is for, plus enough company/product context to build
|
|
181
|
+
the brief. This is only the client-prospect/bootstrap identity for
|
|
182
|
+
`clientProspectId` or `senderLinkedinUrl`; it is not a connected-sender check.
|
|
183
|
+
- Do not call `list_senders`, `get_sender`, or surface connected/missing sender
|
|
184
|
+
state during setup, brief, source, filter, or message review. Sender
|
|
185
|
+
availability belongs only to the Settings/final launch handoff after
|
|
186
|
+
`approve-message` and the 10-lead validation sample. The first user-visible
|
|
187
|
+
sender blocker should be at `awaiting-user-greenlight`/Settings.
|
|
188
|
+
- If the invocation or user answer includes an existing `clientProspectId`, keep
|
|
189
|
+
it as the preferred `create_campaign` identity input. If it includes a
|
|
190
|
+
LinkedIn profile URL, keep that URL as `senderLinkedinUrl` so the backend can
|
|
191
|
+
resolve/materialize the sender prospect when the watchable campaign shell is
|
|
192
|
+
created. Do not require a connected sender before shell creation.
|
|
181
193
|
- If the user supplied a LinkedIn profile, website, domain, company name, or
|
|
182
|
-
|
|
194
|
+
explicit client prospect identity in the invocation, do one lightweight lookup
|
|
195
|
+
first:
|
|
183
196
|
- LinkedIn profile: call `fetch_linkedin_profile`.
|
|
184
197
|
- Website/domain/company: call `fetch_company` when possible, otherwise one
|
|
185
198
|
web lookup.
|
|
186
|
-
-
|
|
199
|
+
- Existing client prospect id: use it directly and do one company/profile
|
|
200
|
+
lookup only if a URL/domain is also available.
|
|
187
201
|
Then summarize what you found in one or two lines and ask the user to confirm
|
|
188
|
-
the campaign
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
to
|
|
193
|
-
connected sender, use `enrich_sender` on the best match to infer their current
|
|
194
|
-
or most recent company, then ask a structured confirmation question:
|
|
195
|
-
|
|
196
|
-
```text
|
|
197
|
-
I’m ready to build this in {workspace}. I found {matched sender} connected here.
|
|
198
|
-
|
|
199
|
-
Is that you, and is this campaign for {company}?
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
The structured options must be no more than three choices:
|
|
203
|
-
|
|
204
|
-
1. `Yes — use {matched sender} for {company}`
|
|
205
|
-
2. `No — I'll paste a LinkedIn profile`
|
|
206
|
-
3. `Use a company domain instead`
|
|
207
|
-
|
|
208
|
-
If there are multiple likely connected senders, mention the best one in the
|
|
209
|
-
question and use option 2 for either a different connected sender or a pasted
|
|
210
|
-
LinkedIn profile.
|
|
211
|
-
|
|
212
|
-
Use the structured question tool only for the choice. Do not use
|
|
213
|
-
`request_user_input`/`AskUserQuestion` to collect a LinkedIn URL, company
|
|
214
|
-
domain, or freeform text. If the user chooses option 2, ask in normal chat:
|
|
215
|
-
`Paste the LinkedIn URL I should use, and I’ll look it up.` Then call
|
|
216
|
-
`fetch_linkedin_profile`, infer their current or most recent company, and
|
|
217
|
-
confirm company and sender again. If the user chooses option 3, ask in normal
|
|
218
|
-
chat: `Paste the company domain, and I’ll do a quick lookup before we keep
|
|
219
|
-
going.` Then call `fetch_company` when possible, otherwise one web lookup, and
|
|
220
|
-
ask who the LinkedIn messages should send from.
|
|
221
|
-
|
|
222
|
-
If `list_senders` returns zero connected senders, avoid the sender-confirmation
|
|
223
|
-
branch entirely. Do not ask the user to choose an input type with the
|
|
224
|
-
structured question tool. Ask in normal chat for the user's LinkedIn URL or the
|
|
225
|
-
company they want to send on behalf of so you can research context:
|
|
226
|
-
|
|
227
|
-
```text
|
|
228
|
-
I’m ready to build this in {workspace}.
|
|
229
|
-
|
|
230
|
-
First, paste your LinkedIn URL or the company website you want to send on
|
|
231
|
-
behalf of. I’ll use that to understand the company before we pick the target,
|
|
232
|
-
offer, proof, and lead source.
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
If there is no strong sender match, do not show a structured choice that says
|
|
236
|
-
"LinkedIn profile" vs "Company website". The point of this gate is not "pick a
|
|
237
|
-
sender" or "pick an input type"; it is to learn who the user is, infer the
|
|
238
|
-
current or most recent company, and then confirm who we are sending from. The
|
|
239
|
-
customer-facing shape should be:
|
|
202
|
+
the campaign identity/focus before continuing. Do not mention connected sender
|
|
203
|
+
availability in this confirmation.
|
|
204
|
+
- If the user did not provide the launch identity, ask in normal chat for the
|
|
205
|
+
LinkedIn profile or company website to use as the campaign identity. Do not ask
|
|
206
|
+
them to choose an input type with the structured question tool:
|
|
240
207
|
|
|
241
208
|
```text
|
|
242
209
|
I’m ready to build this in {workspace}.
|
|
243
210
|
|
|
244
|
-
First,
|
|
245
|
-
the
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
After the user pastes a URL/domain, do the lightweight lookup. For a LinkedIn profile, call
|
|
249
|
-
`fetch_linkedin_profile` and infer the user's current or most recent company
|
|
250
|
-
from the profile. For a company website, call `fetch_company` when possible,
|
|
251
|
-
otherwise one web lookup.
|
|
252
|
-
|
|
253
|
-
If `list_senders` did not already run, call it once after the lookup to see
|
|
254
|
-
whether the fetched user appears to match a connected sender. If there is a
|
|
255
|
-
likely match, ask:
|
|
256
|
-
|
|
257
|
-
```text
|
|
258
|
-
Cool — are you {matched sender}, and is this campaign for {company}?
|
|
259
|
-
```
|
|
260
|
-
|
|
261
|
-
If there is no likely sender match, ask:
|
|
262
|
-
|
|
263
|
-
```text
|
|
264
|
-
Cool — I have this campaign as {company}. Who should the LinkedIn messages send from?
|
|
211
|
+
First, paste the LinkedIn profile or company website for the client/company
|
|
212
|
+
this campaign is for. I’ll use that to resolve the campaign identity before we
|
|
213
|
+
choose the target, offer, proof, and lead source.
|
|
265
214
|
```
|
|
266
215
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
path, or custom explanation.
|
|
216
|
+
After the user pastes a URL/domain, do the lightweight lookup. For a LinkedIn
|
|
217
|
+
profile, call `fetch_linkedin_profile` and infer the current or most recent
|
|
218
|
+
company from the profile. For a company website, call `fetch_company` when
|
|
219
|
+
possible, otherwise one web lookup. If a LinkedIn profile URL is available,
|
|
220
|
+
retain it as `senderLinkedinUrl` for `create_campaign`; if a
|
|
221
|
+
`clientProspectId` is available, pass that instead.
|
|
274
222
|
|
|
275
|
-
After the user confirms the
|
|
223
|
+
After the user confirms the campaign identity, check whether the company
|
|
276
224
|
context implies more than one campaignable product line, service, or offer.
|
|
277
225
|
If so, ask one structured campaign-focus question before the setup packet
|
|
278
226
|
(for example, "Which Sellable offer is this campaign for?") with no more than
|
|
@@ -296,12 +244,11 @@ me`, `I’ll paste a different sender profile`, and `Other / custom`.
|
|
|
296
244
|
```text
|
|
297
245
|
I’m ready to build the campaign in {workspace}.
|
|
298
246
|
|
|
299
|
-
First I’ll
|
|
300
|
-
|
|
301
|
-
use that to understand the company before we choose the target, offer, proof,
|
|
302
|
-
and lead source.
|
|
247
|
+
First I’ll resolve the client/company this campaign is for. I’ll use that
|
|
248
|
+
context to choose the target, offer, proof, and lead source.
|
|
303
249
|
|
|
304
|
-
Then I’ll turn that into a campaign brief for you to approve before
|
|
250
|
+
Then I’ll turn that into a campaign brief for you to approve before any leads
|
|
251
|
+
are imported or anything can send.
|
|
305
252
|
```
|
|
306
253
|
|
|
307
254
|
- Fast Intake Mode is mandatory for hosted/rehearsal net-new runs. Ask the
|
|
@@ -315,15 +262,15 @@ me`, `I’ll paste a different sender profile`, and `Other / custom`.
|
|
|
315
262
|
generating setup options. If the user supplied a LinkedIn profile URL, call
|
|
316
263
|
`fetch_linkedin_profile` before generating setup options. Do not infer the
|
|
317
264
|
product category from the company name alone. If no domain, website, LinkedIn
|
|
318
|
-
profile, or
|
|
319
|
-
|
|
265
|
+
profile, or client identity is supplied, ask in normal chat for that identity
|
|
266
|
+
before buyer/offer/source. Before the first strategy/source packet,
|
|
267
|
+
`list_senders` is forbidden; sender availability is checked only at Settings.
|
|
268
|
+
Before that first
|
|
320
269
|
structured question gate, do not run source discovery, Sales Nav, Prospeo,
|
|
321
270
|
Signals, Bash, Read, Write, Edit, Glob, Grep, full company research, or
|
|
322
|
-
draft-directory inspection/creation.
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
draft-directory setup only after the founder answers. After launch identity,
|
|
326
|
-
sender, and any ambiguous campaign focus are confirmed, the setup packet must
|
|
271
|
+
draft-directory inspection/creation. Do draft-directory setup only after the
|
|
272
|
+
founder answers. After launch identity and any ambiguous campaign focus are
|
|
273
|
+
confirmed, the setup packet must
|
|
327
274
|
use the structured question gate and ask buyer, offer/CTA, proof, and lead
|
|
328
275
|
source. All four questions must include an `Other / custom` option.
|
|
329
276
|
- After the founder answers the first strategy/source packet, explain the next
|
|
@@ -433,11 +380,11 @@ brief`, `Revise target`, `Revise offer/proof`, and `Other / custom`.
|
|
|
433
380
|
finish the write synchronously at that boundary.
|
|
434
381
|
|
|
435
382
|
- After the brief is approved or auto-confirmed, show the next progress line:
|
|
436
|
-
`Cool. Now I'm going to find people who are both a good fit and
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
383
|
+
`Cool. Now I'm going to find people who are both a good fit and active enough
|
|
384
|
+
to be worth a LinkedIn test. I'll compare source paths by expected volume,
|
|
385
|
+
sampled ICP fit, activity/warmth signal, cleanup risk, and tradeoffs. This
|
|
386
|
+
usually takes ~3-5 min, and I'll show you the source decision + sample before
|
|
387
|
+
anything goes live.`
|
|
441
388
|
- After the lead sample/source decision is ready and approved or auto-confirmed,
|
|
442
389
|
show the next progress line:
|
|
443
390
|
`Lead source is set. I'll import the first 10-row review batch into the
|
|
@@ -828,9 +775,13 @@ usable leads`.
|
|
|
828
775
|
- preview count
|
|
829
776
|
- ICP match rate with numerator/denominator and sample basis; never percent-only
|
|
830
777
|
- volume comparison
|
|
831
|
-
-
|
|
832
|
-
|
|
833
|
-
|
|
778
|
+
- source viability: expected source volume, expected usable leads after
|
|
779
|
+
filtering, source activity/warmth indicators, cleanup risk, and confidence
|
|
780
|
+
basis
|
|
781
|
+
- do not forecast connection acceptance, reply rate, meetings, pipeline,
|
|
782
|
+
revenue, or ROI unless the user supplied verified benchmark data for this
|
|
783
|
+
exact workspace/sender. If no verified benchmark exists, state that
|
|
784
|
+
performance is not estimated from this source review.
|
|
834
785
|
- for Signals-first paths: top candidate posts reviewed, selected post URLs,
|
|
835
786
|
post author, post topic/excerpt, post age or posted date, engagement count,
|
|
836
787
|
sampled engager count per selected post, sampled fit count per selected post,
|
|
@@ -854,7 +805,7 @@ customer-visible sections with literal headings:
|
|
|
854
805
|
- `## Source Decision`
|
|
855
806
|
- `## Evidence Snapshot`
|
|
856
807
|
- `## Selected Signal Posts` for Signals-first campaigns
|
|
857
|
-
- `##
|
|
808
|
+
- `## Source Viability`
|
|
858
809
|
- `## Sample Leads` for Signals-first campaigns
|
|
859
810
|
- `## Pros`
|
|
860
811
|
- `## Tradeoffs`
|
|
@@ -888,10 +839,11 @@ For Signals-first campaigns, `## Sample Leads` must group representative sample
|
|
|
888
839
|
rows by source post when possible, so the user can see not just that the search
|
|
889
840
|
found posts, but which posts produce believable prospects.
|
|
890
841
|
|
|
891
|
-
`##
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
842
|
+
`## Source Viability` must include expected source volume, expected usable
|
|
843
|
+
leads after filtering, source activity/warmth indicators, cleanup risk, and
|
|
844
|
+
estimate basis. Do not include likely connection acceptance or reply-rate
|
|
845
|
+
ranges unless verified benchmark data was supplied by the user for this exact
|
|
846
|
+
workspace/sender.
|
|
895
847
|
|
|
896
848
|
When showing `lead-review.md` to the user, render a slim decision summary in
|
|
897
849
|
chat, not the full evidence table. Use rendered Markdown directly with short
|
|
@@ -911,7 +863,8 @@ user-facing lead review. The visible response must include:
|
|
|
911
863
|
- `Why it won`
|
|
912
864
|
- `Quick numbers` as bullet points, with one provider/source angle per bullet.
|
|
913
865
|
Each bullet must include raw volume, sampled fit rate as `n/N`, estimated
|
|
914
|
-
good-fit range after cleanup,
|
|
866
|
+
good-fit range after cleanup, source activity/warmth basis, and confidence
|
|
867
|
+
note.
|
|
915
868
|
- If Signals was searched or considered, `Signal keyword lanes` as a compact
|
|
916
869
|
table with keyword lane, timeframe, posts found, and finalist posts reviewed.
|
|
917
870
|
- If Signals was searched or considered, `LinkedIn posts sampled` as a compact
|
|
@@ -475,13 +475,13 @@
|
|
|
475
475
|
{
|
|
476
476
|
"action": "render_find_leads_progress",
|
|
477
477
|
"requiredVisibleContent": [
|
|
478
|
-
"good fit and
|
|
478
|
+
"good fit and active enough to be worth a LinkedIn test",
|
|
479
479
|
"campaign source step",
|
|
480
480
|
"primary source",
|
|
481
481
|
"expected volume",
|
|
482
|
-
"
|
|
483
|
-
"
|
|
484
|
-
"
|
|
482
|
+
"sampled ICP fit",
|
|
483
|
+
"activity/warmth signal",
|
|
484
|
+
"cleanup risk",
|
|
485
485
|
"tradeoffs",
|
|
486
486
|
"search lanes",
|
|
487
487
|
"timeframe",
|
|
@@ -639,7 +639,6 @@
|
|
|
639
639
|
"sampled fits as n/N (%)",
|
|
640
640
|
"estimated usable people",
|
|
641
641
|
"estimated good-fit range after cleanup",
|
|
642
|
-
"expected reply-rate range",
|
|
643
642
|
"confidence note"
|
|
644
643
|
],
|
|
645
644
|
"sourceDecisionRequiredFields": [
|
|
@@ -668,7 +667,7 @@
|
|
|
668
667
|
"artifactLinkTiming": "before_next_step_or_revision_question",
|
|
669
668
|
"doNotCompressToSummaryOnly": false,
|
|
670
669
|
"doNotRenderArtifactLinksOnly": true,
|
|
671
|
-
"chatRenderRule": "Show a slim rendered-Markdown decision summary only, never a fenced code block. The first sentence must make the decision explicit: 'I recommend {primary source} using {exact filter/source recipe}. The runner-up is {source} because {reason}.' Use indexed sections and short bullets: recommendation, Primary source and filters, Runner-up sources, why it won, Quick numbers with one provider/source angle per bullet, raw volume, sampled fit rate as n/N, estimated good-fit range after cleanup,
|
|
670
|
+
"chatRenderRule": "Show a slim rendered-Markdown decision summary only, never a fenced code block. The first sentence must make the decision explicit: 'I recommend {primary source} using {exact filter/source recipe}. The runner-up is {source} because {reason}.' Use indexed sections and short bullets: recommendation, Primary source and filters, Runner-up sources, why it won, Quick numbers with one provider/source angle per bullet, raw volume, sampled fit rate as n/N, estimated good-fit range after cleanup, activity/warmth basis, confidence note, 3-5 representative sample leads, and one tradeoff. Do not forecast connection acceptance rates, reply rates, meetings, pipeline, revenue, or ROI unless the user supplied verified benchmark data for this exact workspace/sender. If Signals was searched or considered, include two compact inline Markdown tables before the recommendation is treated as final: Signal keyword lanes with keyword lane, timeframe, posts found, and finalist posts reviewed; and LinkedIn posts sampled with post URL/title, author/topic, age, engagers, sampled engagers, good fits as n/N, estimated usable prospects per post, and use/discard decision. Default to selecting a few promising Signals posts for the first sample instead of trying to prove full Signals scale up front; if the sample is good but volume is low, say how many more posts to add/scrape next. Do not skip or discard Signals based only on raw post count or vibes; show the post-level math first, or explicitly say no engagers could be fetched and lower confidence. Keep discarded paths, full sample rows, and lead-sample.json details in lead-review.md. Do not show plain filesystem paths unless links cannot be created."
|
|
672
671
|
},
|
|
673
672
|
{
|
|
674
673
|
"action": "render_post_lead_parallel_progress",
|
|
@@ -95,7 +95,7 @@ Use a compact markdown report with these sections:
|
|
|
95
95
|
- Preview Count: {n}
|
|
96
96
|
- ICP Match Rate: {x/y or % if supportable}
|
|
97
97
|
- Volume Comparison: above target | in range | below target
|
|
98
|
-
-
|
|
98
|
+
- Source Viability: source volume {n or range}, usable leads after filtering {n or range}, activity/warmth basis {sample-backed | directional | needs more sample}, cleanup risk {low | medium | high}
|
|
99
99
|
|
|
100
100
|
## Source Decision
|
|
101
101
|
|
|
@@ -108,13 +108,13 @@ Use a compact markdown report with these sections:
|
|
|
108
108
|
- Approval Meaning: approving this source means {what will be sampled/imported
|
|
109
109
|
next}
|
|
110
110
|
|
|
111
|
-
##
|
|
111
|
+
## Source Viability
|
|
112
112
|
|
|
113
113
|
- Source Volume: {n or range}
|
|
114
114
|
- Expected Usable Leads After Filtering: {n or range}
|
|
115
|
-
-
|
|
116
|
-
-
|
|
117
|
-
-
|
|
115
|
+
- Activity/Warmth Basis: sample-backed | directional | needs more sample
|
|
116
|
+
- Cleanup Risk: low | medium | high
|
|
117
|
+
- Performance Forecast: not estimated unless the user supplied verified benchmark data for this exact workspace/sender
|
|
118
118
|
|
|
119
119
|
## Signal Keyword Lanes
|
|
120
120
|
|
|
@@ -114,9 +114,12 @@ Lead preview must:
|
|
|
114
114
|
- preview count
|
|
115
115
|
- ICP match rate
|
|
116
116
|
- volume comparison
|
|
117
|
-
-
|
|
118
|
-
|
|
119
|
-
|
|
117
|
+
- source viability: expected source volume, expected usable leads after
|
|
118
|
+
filtering, source activity/warmth indicators, cleanup risk, and confidence
|
|
119
|
+
basis
|
|
120
|
+
- no connection acceptance, reply-rate, meeting, pipeline, revenue, or ROI
|
|
121
|
+
forecast unless the user supplied verified benchmark data for this exact
|
|
122
|
+
workspace/sender
|
|
120
123
|
- source decision: best path, why it won, pros, cons/tradeoffs, and discarded
|
|
121
124
|
source paths with the reason each lost
|
|
122
125
|
- false-positive patterns
|
|
@@ -126,15 +129,16 @@ For normal LinkedIn discovery, `lead-review.md` must include literal
|
|
|
126
129
|
customer-visible headings:
|
|
127
130
|
|
|
128
131
|
- `## Source Decision`
|
|
129
|
-
- `##
|
|
132
|
+
- `## Source Viability`
|
|
130
133
|
- `## Pros`
|
|
131
134
|
- `## Tradeoffs`
|
|
132
135
|
- `## Discarded Paths`
|
|
133
136
|
|
|
134
|
-
`##
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
137
|
+
`## Source Viability` must include expected source volume, expected usable
|
|
138
|
+
leads after filtering, source activity/warmth indicators, cleanup risk, and
|
|
139
|
+
estimate basis. Do not include likely connection acceptance or reply-rate
|
|
140
|
+
ranges unless verified benchmark data was supplied by the user for this exact
|
|
141
|
+
workspace/sender.
|
|
138
142
|
|
|
139
143
|
`lead-sample.json` must include enough structured lead data for downstream
|
|
140
144
|
filtering:
|
|
@@ -343,10 +343,13 @@ Use first when LinkedIn activity plus tighter role / company filters matter.
|
|
|
343
343
|
- For InMail or LinkedIn-send motions, establish the baseline TAM first, then test a `POSTED_ON_LINKEDIN` slice when the pool can still sustain a campaign.
|
|
344
344
|
- Treat recent posters as a preferred first-send slice, not just a nice-to-have proxy. When the recently-posted slice still yields enough projected good fits, prefer it because reply / acceptance performance is usually materially better than the cold full-TAM pool.
|
|
345
345
|
- When explaining a LinkedIn source decision, make the buying logic obvious:
|
|
346
|
-
pick people who are
|
|
347
|
-
by expected volume,
|
|
348
|
-
|
|
349
|
-
|
|
346
|
+
pick people who are good fits and active enough to be worth a LinkedIn test.
|
|
347
|
+
Compare source paths by expected volume, sampled ICP fit, activity/warmth
|
|
348
|
+
signal, cleanup risk, and tradeoffs.
|
|
349
|
+
- Do not forecast connection acceptance rates, reply rates, meetings, pipeline,
|
|
350
|
+
revenue, or ROI unless the user supplied verified benchmark data for this
|
|
351
|
+
exact workspace/sender. Without that data, say performance is not estimated
|
|
352
|
+
from the source review.
|
|
350
353
|
- Use these rough planning bands only as directional defaults when better
|
|
351
354
|
workspace/founder data is not available: Signals/recent engagers = lower
|
|
352
355
|
volume, higher reply upside; Sales Nav with recent LinkedIn activity = medium
|