@sellable/mcp 0.1.149 → 0.1.150
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 +8 -4
- package/agents/source-scout-prospeo-contact.md +12 -5
- package/agents/source-scout-sales-nav.md +13 -3
- package/dist/tools/leads.d.ts +2 -1
- package/dist/tools/leads.js +162 -15
- package/dist/tools/prompts.js +3 -3
- package/dist/tools/registry.d.ts +9 -1
- package/dist/tools/rows.d.ts +1 -0
- package/dist/tools/rows.js +2 -0
- package/dist/tools/rubrics.d.ts +55 -23
- package/dist/tools/rubrics.js +95 -10
- package/package.json +1 -1
- package/skills/create-campaign/SKILL.md +51 -23
- package/skills/create-campaign/core/providers/apollo.json +4 -2
- package/skills/create-campaign/core/providers/prospeo.json +3 -2
- package/skills/create-campaign/references/provider-selection-strategy.md +66 -25
- package/skills/create-campaign-v2/SKILL.md +60 -24
- package/skills/create-campaign-v2/SOUL.md +11 -7
- package/skills/create-campaign-v2/core/flow.v2.json +67 -40
- package/skills/create-campaign-v2/references/sample-validation-loop.md +9 -5
- package/skills/create-campaign-v2/references/step-13-import-leads.md +10 -4
- package/skills/create-campaign-v2/references/step-15-re-cascade.md +12 -7
- package/skills/create-campaign-v2/references/watch-guide-narration.md +16 -13
- package/skills/create-campaign-v2-tail/SKILL.md +24 -16
- package/skills/providers/apollo.md +8 -1
- package/skills/providers/prospeo.md +11 -1
- package/skills/providers/sales-nav.md +1 -1
- package/skills/research/config.json +9 -0
|
@@ -53,7 +53,29 @@ Activity Filters (use one or both):
|
|
|
53
53
|
|
|
54
54
|
Sales Nav works without these filters too -- just expect lower reply rates.
|
|
55
55
|
|
|
56
|
-
### 3.
|
|
56
|
+
### 3. Prospeo (HIRING / ACCOUNT / VERIFIED-CONTACT EXPANSION)
|
|
57
|
+
|
|
58
|
+
Prospeo is the main lane when the user's direction points to database filters
|
|
59
|
+
that LinkedIn sources do not expose.
|
|
60
|
+
|
|
61
|
+
USE WHEN:
|
|
62
|
+
|
|
63
|
+
- Hiring-led targeting: companies actively hiring specific roles
|
|
64
|
+
- Named-account or domain-list targeting
|
|
65
|
+
- Broad persona expansion where verified contact coverage matters
|
|
66
|
+
- You need `company_job_posting_hiring_for`,
|
|
67
|
+
`company_job_posting_quantity`, funding, headcount, or domain filters
|
|
68
|
+
|
|
69
|
+
SKIP WHEN:
|
|
70
|
+
|
|
71
|
+
- The campaign is mainly about fresh LinkedIn activity or engagement warmth
|
|
72
|
+
- Signal Discovery can clearly produce enough ICP-fit engagers
|
|
73
|
+
|
|
74
|
+
WHY: Prospeo is the only current provider with company job-posting filters by
|
|
75
|
+
role. Sales Nav is stronger for recent LinkedIn activity, but not for
|
|
76
|
+
hiring-by-role filtering.
|
|
77
|
+
|
|
78
|
+
### 4. Apollo (LAST RESORT FOR VOLUME)
|
|
57
79
|
|
|
58
80
|
Large database but leads may not be active on LinkedIn.
|
|
59
81
|
|
|
@@ -74,25 +96,30 @@ Is your ICP LinkedIn-active (founders, sales, marketing, GTM, engineers)?
|
|
|
74
96
|
NO -> Sales Navigator + POSTED_ON_LINKEDIN (4x reply rates)
|
|
75
97
|
NO -> Sales Navigator (with or without POSTED_ON_LINKEDIN)
|
|
76
98
|
|
|
99
|
+
Need hiring-by-role filters? -> Prospeo (has company job-posting filters)
|
|
77
100
|
Need tech stack targeting? -> Apollo (has technology filters)
|
|
78
|
-
Have specific company names? -> Sales Navigator or
|
|
101
|
+
Have specific company names/domains? -> Sales Navigator for small lists or Prospeo with domainFilterId
|
|
79
102
|
```
|
|
80
103
|
|
|
81
104
|
## ICP-to-Provider Quick Reference
|
|
82
105
|
|
|
83
|
-
| ICP Type | Recommended | Why
|
|
84
|
-
| ------------------------- | ---------------- |
|
|
85
|
-
| Founders, CEOs | Signal Discovery | Highly active on LinkedIn, lots of founder content
|
|
86
|
-
| Sales/GTM leaders | Signal Discovery | Very active, tons of sales content
|
|
87
|
-
| Marketing leaders | Signal Discovery | Active, lots of marketing content
|
|
88
|
-
| Engineers/DevOps | Signal Discovery | Active on tech discussions, open source
|
|
89
|
-
| Enterprise CTOs | Sales Navigator | Less public engagement, use POSTED_ON_LINKEDIN
|
|
90
|
-
| Procurement/Ops | Sales Navigator | Rarely engage publicly
|
|
91
|
-
| Few specific companies | Sales Navigator | Use CURRENT_COMPANY filter (lookup each company)
|
|
92
|
-
|
|
|
93
|
-
|
|
|
94
|
-
|
|
95
|
-
|
|
106
|
+
| ICP Type | Recommended | Why |
|
|
107
|
+
| ------------------------- | ---------------- | -------------------------------------------------- |
|
|
108
|
+
| Founders, CEOs | Signal Discovery | Highly active on LinkedIn, lots of founder content |
|
|
109
|
+
| Sales/GTM leaders | Signal Discovery | Very active, tons of sales content |
|
|
110
|
+
| Marketing leaders | Signal Discovery | Active, lots of marketing content |
|
|
111
|
+
| Engineers/DevOps | Signal Discovery | Active on tech discussions, open source |
|
|
112
|
+
| Enterprise CTOs | Sales Navigator | Less public engagement, use POSTED_ON_LINKEDIN |
|
|
113
|
+
| Procurement/Ops | Sales Navigator | Rarely engage publicly |
|
|
114
|
+
| Few specific companies | Sales Navigator | Use CURRENT_COMPANY filter (lookup each company) |
|
|
115
|
+
| Hiring-led targeting | Prospeo | Has company job-posting filters by role |
|
|
116
|
+
| Company domain list (ABM) | Prospeo | Uses `domainFilterId` for domain targeting |
|
|
117
|
+
| Tech stack users | Apollo | Has technology filters |
|
|
118
|
+
|
|
119
|
+
**Default:** Try Signal Discovery first only when there is no stronger source
|
|
120
|
+
direction and the ICP is plausibly active in public LinkedIn conversations. Fall
|
|
121
|
+
back to Sales Navigator if ICP is too niche. Use Prospeo first when the ask is
|
|
122
|
+
hiring-led, account/domain-led, or broad verified-contact expansion.
|
|
96
123
|
|
|
97
124
|
## ABM / Account-Based Targeting
|
|
98
125
|
|
|
@@ -103,10 +130,10 @@ When user has a list of target companies:
|
|
|
103
130
|
- Requires looking up each company individually
|
|
104
131
|
- Can combine with POSTED_ON_LINKEDIN for active users
|
|
105
132
|
|
|
106
|
-
- **Many companies (domain list):** Use
|
|
107
|
-
- Supports
|
|
108
|
-
- Example:
|
|
109
|
-
- Trade-off: No POSTED_ON_LINKEDIN equivalent, so
|
|
133
|
+
- **Many companies (domain list):** Use Prospeo with `domainFilterId`
|
|
134
|
+
- Supports large domain filters through `load_csv_domains` or `save_domain_filters`
|
|
135
|
+
- Example: create a domain filter for `stripe.com`, `notion.so`, and `figma.com`, then pass `domainFilterId` into `search_prospeo`
|
|
136
|
+
- Trade-off: No POSTED_ON_LINKEDIN equivalent, so LinkedIn activity warmth may be lower
|
|
110
137
|
|
|
111
138
|
## Recommendation Templates
|
|
112
139
|
|
|
@@ -141,6 +168,19 @@ Here's why:
|
|
|
141
168
|
Should I search for active {icp} on Sales Navigator?
|
|
142
169
|
```
|
|
143
170
|
|
|
171
|
+
**Prospeo (hiring-led ICP):**
|
|
172
|
+
|
|
173
|
+
```
|
|
174
|
+
Since this campaign depends on companies actively hiring for **{roleThemes}**, I'd recommend **Prospeo** first.
|
|
175
|
+
|
|
176
|
+
Here's why:
|
|
177
|
+
- Prospeo can filter companies by open-role themes using job-posting filters
|
|
178
|
+
- We can pair those hiring signals with founder, GTM, recruiting, or revenue-owner contacts
|
|
179
|
+
- Sales Nav is useful for LinkedIn activity and referrals, but it cannot filter companies by hiring role
|
|
180
|
+
|
|
181
|
+
Should I search Prospeo for companies hiring {roleThemes} and the right hiring-owner contacts?
|
|
182
|
+
```
|
|
183
|
+
|
|
144
184
|
**Apollo (tech stack targeting):**
|
|
145
185
|
|
|
146
186
|
```
|
|
@@ -154,17 +194,17 @@ Here's why:
|
|
|
154
194
|
Should I search Apollo for {techStack} users?
|
|
155
195
|
```
|
|
156
196
|
|
|
157
|
-
**
|
|
197
|
+
**Prospeo ABM (company domains):**
|
|
158
198
|
|
|
159
199
|
```
|
|
160
|
-
Since you have a **list of target
|
|
200
|
+
Since you have a **list of target company domains**, I'd recommend **Prospeo** with a domain filter.
|
|
161
201
|
|
|
162
202
|
Here's why:
|
|
163
|
-
-
|
|
203
|
+
- Prospeo is the campaign-default path for supplied company-domain lists
|
|
204
|
+
- We'll create a `domainFilterId` from the CSV or pasted domains before searching
|
|
164
205
|
- We can find decision-makers at your exact target accounts
|
|
165
|
-
- Just share the domains (e.g., stripe.com, notion.so) and I'll find your ICP at those companies
|
|
166
206
|
|
|
167
|
-
Note:
|
|
207
|
+
Note: LinkedIn activity warmth may be lower than Signal Discovery or Sales Nav with POSTED_ON_LINKEDIN, so we should inspect the first review batch before scaling.
|
|
168
208
|
|
|
169
209
|
Can you share your target company domains?
|
|
170
210
|
```
|
|
@@ -179,7 +219,8 @@ Do not hardcode provider options. Build them from the framework:
|
|
|
179
219
|
- If user already has some other list shape that does not fit those CSV paths -> proceed with provider selection
|
|
180
220
|
- If the user specifies a provider or research plan -> treat that as a hard override
|
|
181
221
|
- Else if `providerPreference` override exists -> recommend that provider
|
|
182
|
-
- Else use the decision hierarchy above
|
|
222
|
+
- Else use the decision hierarchy above only when there is no stronger source
|
|
223
|
+
direction (Signal Discovery -> Sales Nav -> Prospeo -> Apollo)
|
|
183
224
|
2. Build options from `providerOrder` and `framework.providers[providerId].askOption`
|
|
184
225
|
3. Mark the recommended option by appending " (Recommended)" if needed
|
|
185
226
|
|
|
@@ -49,9 +49,10 @@ for debug output.
|
|
|
49
49
|
12. Sync the approved template into the campaign brief.
|
|
50
50
|
13. After message approval, keep the watched app on Filter Leads while the
|
|
51
51
|
bounded enrichment/filter cascade starts.
|
|
52
|
-
14. Move to Messages only after at least one review row passes
|
|
53
|
-
review
|
|
54
|
-
|
|
52
|
+
14. Move to Messages only after at least one review row passes and one generated
|
|
53
|
+
message is ready for review. Do not wait for a stronger sample once that
|
|
54
|
+
first passing message exists; review it, then hand off to Settings, sender,
|
|
55
|
+
sequence, and explicit launch greenlight.
|
|
55
56
|
|
|
56
57
|
There is no normal approval-packet, commit-gate, atomic-mint, or local
|
|
57
58
|
artifact-validation step. Those belong only to legacy validation/rehearsal
|
|
@@ -125,6 +126,16 @@ Default source order when the user has not supplied a source:
|
|
|
125
126
|
3. broader Sales Nav role/title filters
|
|
126
127
|
4. Prospeo account/contact expansion
|
|
127
128
|
|
|
129
|
+
Use that order only when the brief has no stronger sourcing constraint. If the
|
|
130
|
+
campaign is hiring-led, asks for companies actively hiring specific roles, asks
|
|
131
|
+
for open-role/job-posting signals, or needs verified contacts at companies with
|
|
132
|
+
those hiring signals, start with Prospeo. Prospeo supports
|
|
133
|
+
`company_job_posting_hiring_for` and `company_job_posting_quantity`; Sales Nav
|
|
134
|
+
does not provide hiring-by-role filters. For those campaigns, Signal Discovery
|
|
135
|
+
can be a conversation-signal check if relevant hiring posts are likely, and
|
|
136
|
+
Sales Nav is a LinkedIn activity/referral fallback rather than the main hiring
|
|
137
|
+
filter.
|
|
138
|
+
|
|
128
139
|
Before any provider prompt, search, source scout, or signal-discovery call,
|
|
129
140
|
show a short source-plan gate and ask for approval. This first approval
|
|
130
141
|
authorizes source scouting/search only. The gate must say, in plain language:
|
|
@@ -161,14 +172,30 @@ the target engager/source-candidate volume, the bounded campaign review-batch
|
|
|
161
172
|
size, the cleanup risk, and the fallback if the selected posts look wrong. The
|
|
162
173
|
approval label must describe the action with the count, such as "Approve
|
|
163
174
|
scraping 3 Signal Discovery posts?" For Sales Nav or Prospeo, the label should
|
|
164
|
-
name the specific search/import lane. Do not call
|
|
165
|
-
`confirm_lead_list` until this second source-action approval
|
|
175
|
+
name the specific search/import lane and source lead count. Do not call
|
|
176
|
+
`import_leads` or `confirm_lead_list` until this second source-action approval
|
|
177
|
+
is granted.
|
|
178
|
+
|
|
179
|
+
For Sales Nav and Prospeo, do not ask to import only the 25-row review batch at
|
|
180
|
+
the source-action gate. First-page samples are for source math: compute sampled
|
|
181
|
+
fit after conservative cleanup, project how many good-fit prospects the raw
|
|
182
|
+
pool can yield, and keep refining filters while the projected good-fit pool is
|
|
183
|
+
below the campaign target (normally about 150+ usable prospects unless the
|
|
184
|
+
campaign/source defaults say otherwise). Once the lane clears the target, ask
|
|
185
|
+
approval to materialize the source list with
|
|
186
|
+
`targetLeadCount = min(rawResultCount, providerMax, ceil(targetGoodFitLeads /
|
|
187
|
+
projectedFitRateAfterCleanup))`. After that source list is ready,
|
|
188
|
+
`confirm_lead_list` imports only the bounded review batch into the campaign
|
|
189
|
+
table for fit and message review.
|
|
190
|
+
|
|
166
191
|
After the user approves this concrete source-action gate, do not show the
|
|
167
192
|
Source Recommendation again and do not ask another source approval question.
|
|
168
193
|
Acknowledge once, then call `import_leads` immediately with the approved source
|
|
169
|
-
math. For
|
|
170
|
-
|
|
171
|
-
|
|
194
|
+
math. For Sales Nav/Prospeo, pass `targetLeadCount` as the approved source-list
|
|
195
|
+
export count, not the review-batch size. For Signal Discovery, pass
|
|
196
|
+
`provider: "signal-discovery"`, `targetEngagerCount`, `maxPostsToScrape`, and
|
|
197
|
+
`confirmed: true`; the tool owns moving the watch UI to source-list progress
|
|
198
|
+
after a lead-list/job id exists.
|
|
172
199
|
|
|
173
200
|
For Signal Discovery, use this compact source-action approval shape after
|
|
174
201
|
selected posts exist:
|
|
@@ -181,7 +208,7 @@ Use Signal Discovery first.
|
|
|
181
208
|
**Good-fit target:** ~150 prospects after cleanup, enrichment, and filters<br>
|
|
182
209
|
**Source-candidate plan:** scrape ~1,000 raw engagers using a conservative 15% fit-rate assumption<br>
|
|
183
210
|
**Planning floor:** continue only when sampled/projected fit is at least 10% after cleanup; below that, switch to Sales Nav recent activity<br>
|
|
184
|
-
**Review checkpoint:**
|
|
211
|
+
**Review checkpoint:** after the source list exists, clone only the bounded review batch into the campaign for fit and message review<br>
|
|
185
212
|
|
|
186
213
|
### Selected posts
|
|
187
214
|
|
|
@@ -202,8 +229,9 @@ This gives enough volume to work toward ~150 good-fit prospects, while
|
|
|
202
229
|
keeping the source tied to people already engaging with Claude Code outbound /
|
|
203
230
|
AI-native sales workflows.
|
|
204
231
|
|
|
205
|
-
**First pass:** build the source list
|
|
206
|
-
batch so we can inspect
|
|
232
|
+
**First pass:** build the source list at the approved source-candidate target,
|
|
233
|
+
then clone only the bounded review batch into the campaign so we can inspect
|
|
234
|
+
fit and messages before sending.
|
|
207
235
|
|
|
208
236
|
**Fallback:** if sampled/projected fit falls below 10%, or if the review batch
|
|
209
237
|
is too vendor-heavy, agency-heavy, or off-ICP, switch to Sales Nav recent
|
|
@@ -213,7 +241,11 @@ activity.
|
|
|
213
241
|
A source recommendation must show concrete evidence: source lane, filters or
|
|
214
242
|
recipe, raw volume, sample size, sampled fits as n/N plus percentage/range,
|
|
215
243
|
estimated usable prospects, cleanup risk, runner-up, and what approval
|
|
216
|
-
authorizes.
|
|
244
|
+
authorizes. For Sales Nav/Prospeo it must also show source export math:
|
|
245
|
+
`rawResultCount`, `sampledFitRate`, conservative projected fit rate,
|
|
246
|
+
`targetLeadCount` for the source list, and projected good-fit count from that
|
|
247
|
+
export. If projected good-fit count is below target, the recommendation is to
|
|
248
|
+
refine or broaden filters, not to import a 25-row batch.
|
|
217
249
|
|
|
218
250
|
Supplied profile CSVs, company/domain CSVs, pasted domains, and existing
|
|
219
251
|
Sellable lead lists are supported, but keep provider mechanics out of the first
|
|
@@ -222,24 +254,28 @@ customer-facing source-choice labels.
|
|
|
222
254
|
## Post-Lead Workstreams
|
|
223
255
|
|
|
224
256
|
After `confirm_lead_list` imports a non-empty bounded review batch and
|
|
225
|
-
`get_rows_minimal({ tableId: workflowTableId })` proves rows exist,
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
the
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
Builder
|
|
235
|
-
|
|
257
|
+
`get_rows_minimal({ tableId: workflowTableId })` proves rows exist, ask the
|
|
258
|
+
filter-choice question immediately. Do not call
|
|
259
|
+
`get_post_find_leads_scout_registry`, load filter/message subskill prompts, or
|
|
260
|
+
spawn post-lead workers before that question. The only customer-facing work
|
|
261
|
+
before the question should be a short review-batch summary and the choice:
|
|
262
|
+
add filters, skip filters, or revise source.
|
|
263
|
+
|
|
264
|
+
If the user chooses filters, then load the post-lead registry/reference needed
|
|
265
|
+
for filtering and start the Lead Fit Builder. Also start the Message Draft
|
|
266
|
+
Builder in the background from the same campaign/table basis as soon as the
|
|
267
|
+
filter-choice answer is known. If the user skips filters, move the watched app to
|
|
268
|
+
Messages and run the Message Draft Builder there. Debug markdown/json artifacts
|
|
269
|
+
are optional only.
|
|
236
270
|
|
|
237
271
|
When the user chooses filters, immediately call
|
|
238
272
|
`update_campaign({ campaignId, enableICPFilters: true, currentStep: "create-icp-rubric", watchNarration })`
|
|
239
273
|
before rubric thinking or branch work. The watched app should move to Filter
|
|
240
274
|
Rules quickly. After `save_rubrics`, the watched app should move to
|
|
241
275
|
`apply-icp-rubric` / Filter Leads so the user can see the saved filters are
|
|
242
|
-
ready
|
|
276
|
+
ready and wait there for the background message agent. Tell the user explicitly
|
|
277
|
+
that a message agent is drafting the first-message template while enrichment,
|
|
278
|
+
filtering, and Generate Message cells remain blocked.
|
|
243
279
|
|
|
244
280
|
Lead Fit Builder persists production rubrics with `save_rubrics` when filters
|
|
245
281
|
are enabled. It must not require `brief.md`, `lead-review.md`, or
|
|
@@ -274,14 +274,18 @@ keep the output numeric but do not claim the source scout was parallel or
|
|
|
274
274
|
surface install status to the customer.
|
|
275
275
|
|
|
276
276
|
For post-lead work, call `get_post_find_leads_scout_registry` after
|
|
277
|
+
the user chooses filters, not before the filter-choice question. After
|
|
277
278
|
`confirm_lead_list` imports a non-empty bounded review batch and
|
|
278
|
-
`get_rows_minimal` proves rows exist
|
|
279
|
-
immediately
|
|
280
|
-
|
|
281
|
-
filters
|
|
282
|
-
|
|
283
|
-
is
|
|
284
|
-
message
|
|
279
|
+
`get_rows_minimal` proves rows exist, ask add-filters vs skip-filters
|
|
280
|
+
immediately. Once the user answers, start `post-find-leads-message-scout` /
|
|
281
|
+
message generation from the same campaign/table basis. If the user chooses
|
|
282
|
+
filters, also start `post-find-leads-filter-scout`, move the browser to Filter
|
|
283
|
+
Rules, save rubrics, then keep the browser on Filter Leads while the message
|
|
284
|
+
recommendation is reviewed. If the user skips filters, move the browser to
|
|
285
|
+
Messages/message review. The join gate is live branch readiness: saved rubrics
|
|
286
|
+
or a resolved skip-filter choice, plus a message recommendation grounded in the
|
|
287
|
+
same campaign/table basis. Enrichment, filtering, and product Generate Message
|
|
288
|
+
cells still wait for template approval.
|
|
285
289
|
|
|
286
290
|
Only promise parallel post-lead work when parallel work actually started. If the
|
|
287
291
|
host cannot or should not launch background branches, say the real sequence:
|
|
@@ -588,20 +588,9 @@
|
|
|
588
588
|
]
|
|
589
589
|
},
|
|
590
590
|
{
|
|
591
|
-
"action": "
|
|
592
|
-
"
|
|
593
|
-
"
|
|
594
|
-
"requiresNonEmptyRows": true,
|
|
595
|
-
"mustRunBefore": [
|
|
596
|
-
"filter-choice question",
|
|
597
|
-
"filter approval",
|
|
598
|
-
"save_rubrics"
|
|
599
|
-
],
|
|
600
|
-
"mode": "background_when_host_supports_subagents",
|
|
601
|
-
"fallback": "if no real background branch can start, say the real sequence and do not claim background drafting is running",
|
|
602
|
-
"toolCallRequiredInBranch": "get_subskill_prompt({ subskillName: \"generate-messages\", offset, limit }) until hasMore=false",
|
|
603
|
-
"runtimeProofTransport": "CampaignOffer.watchNarration.workerDetails.messageDraftBuilder",
|
|
604
|
-
"purpose": "start the provisional message draft from the imported review batch immediately; do not defer this to filter approval"
|
|
591
|
+
"action": "summarize_review_batch_and_advance_to_filter_choice",
|
|
592
|
+
"purpose": "ask filter choice immediately; no post-lead registries, filter refs, or message prompts first",
|
|
593
|
+
"maxCustomerCopyLines": 4
|
|
605
594
|
}
|
|
606
595
|
],
|
|
607
596
|
"requiredCampaignState": [
|
|
@@ -611,8 +600,6 @@
|
|
|
611
600
|
],
|
|
612
601
|
"allowedTools": [
|
|
613
602
|
"get_subskill_prompt",
|
|
614
|
-
"get_subskill_asset",
|
|
615
|
-
"get_post_find_leads_scout_registry",
|
|
616
603
|
"import_leads",
|
|
617
604
|
"wait_for_lead_list_ready",
|
|
618
605
|
"confirm_lead_list",
|
|
@@ -620,16 +607,18 @@
|
|
|
620
607
|
"get_rows_minimal",
|
|
621
608
|
"update_campaign",
|
|
622
609
|
"AskUserQuestion",
|
|
623
|
-
"request_user_input"
|
|
624
|
-
"Task",
|
|
625
|
-
"spawn_agent"
|
|
610
|
+
"request_user_input"
|
|
626
611
|
],
|
|
627
612
|
"doNotAllow": [
|
|
613
|
+
"get_post_find_leads_scout_registry",
|
|
614
|
+
"Task",
|
|
615
|
+
"spawn_agent",
|
|
628
616
|
"list_senders",
|
|
629
617
|
"queue_cells",
|
|
630
618
|
"start_campaign",
|
|
631
619
|
"enrich_with_prospeo",
|
|
632
|
-
"bulk_enrich_with_prospeo"
|
|
620
|
+
"bulk_enrich_with_prospeo",
|
|
621
|
+
"save_rubrics"
|
|
633
622
|
],
|
|
634
623
|
"waitFor": "review_batch_imported",
|
|
635
624
|
"transitions": {
|
|
@@ -659,6 +648,13 @@
|
|
|
659
648
|
]
|
|
660
649
|
}
|
|
661
650
|
],
|
|
651
|
+
"hardRules": [
|
|
652
|
+
"ask_filter_choice_immediately_after_review_batch_import",
|
|
653
|
+
"do_not_call_get_subskill_prompt_before_filter_choice",
|
|
654
|
+
"do_not_call_get_subskill_asset_before_filter_choice",
|
|
655
|
+
"do_not_call_get_post_find_leads_scout_registry_before_filter_choice",
|
|
656
|
+
"do_not_spawn_post_lead_agents_before_filter_choice"
|
|
657
|
+
],
|
|
662
658
|
"requiredCampaignState": [
|
|
663
659
|
"campaignId",
|
|
664
660
|
"campaignBrief",
|
|
@@ -672,6 +668,11 @@
|
|
|
672
668
|
"get_campaign_navigation_state"
|
|
673
669
|
],
|
|
674
670
|
"doNotAllow": [
|
|
671
|
+
"get_subskill_prompt",
|
|
672
|
+
"get_subskill_asset",
|
|
673
|
+
"get_post_find_leads_scout_registry",
|
|
674
|
+
"Task",
|
|
675
|
+
"spawn_agent",
|
|
675
676
|
"create_campaign",
|
|
676
677
|
"list_senders",
|
|
677
678
|
"import_leads",
|
|
@@ -693,7 +694,7 @@
|
|
|
693
694
|
},
|
|
694
695
|
{
|
|
695
696
|
"id": "post-lead-workstreams",
|
|
696
|
-
"label": "Filter
|
|
697
|
+
"label": "Filter workstream",
|
|
697
698
|
"onEnter": [
|
|
698
699
|
{
|
|
699
700
|
"action": "persist_add_filters_approval",
|
|
@@ -715,17 +716,18 @@
|
|
|
715
716
|
},
|
|
716
717
|
"mustRunBefore": [
|
|
717
718
|
"get_post_find_leads_scout_registry",
|
|
718
|
-
"
|
|
719
|
+
"launch_lead_fit_builder_after_filter_choice",
|
|
719
720
|
"save_rubrics"
|
|
720
721
|
]
|
|
721
722
|
},
|
|
722
723
|
{
|
|
723
724
|
"tool": "get_post_find_leads_scout_registry",
|
|
724
|
-
"purpose": "load canonical post-lead worker names"
|
|
725
|
+
"purpose": "load canonical post-lead worker names only after the user has chosen filters"
|
|
725
726
|
},
|
|
726
727
|
{
|
|
727
|
-
"action": "
|
|
728
|
+
"action": "launch_lead_fit_builder_after_filter_choice",
|
|
728
729
|
"mode": "parallel_when_host_supports_subagents",
|
|
730
|
+
"target": "post-find-leads-filter-scout",
|
|
729
731
|
"inputs": [
|
|
730
732
|
"campaignId",
|
|
731
733
|
"campaignBrief",
|
|
@@ -734,9 +736,16 @@
|
|
|
734
736
|
"reviewBatchRowIds/hash",
|
|
735
737
|
"filterChoice"
|
|
736
738
|
],
|
|
737
|
-
"stateSource": "
|
|
738
|
-
"debugFilesOptionalOnly": true
|
|
739
|
-
|
|
739
|
+
"stateSource": "live campaign/table",
|
|
740
|
+
"debugFilesOptionalOnly": true
|
|
741
|
+
},
|
|
742
|
+
{
|
|
743
|
+
"action": "launch_message_draft_builder_after_filter_decision",
|
|
744
|
+
"mode": "parallel_when_host_supports_subagents",
|
|
745
|
+
"target": "post-find-leads-message-scout",
|
|
746
|
+
"when": "filters_enabled",
|
|
747
|
+
"doesNotQueueCells": true,
|
|
748
|
+
"customerNarration": "Say message agent is drafting."
|
|
740
749
|
},
|
|
741
750
|
{
|
|
742
751
|
"action": "save_filter_rubrics_to_campaign",
|
|
@@ -793,10 +802,13 @@
|
|
|
793
802
|
"hardRules": [
|
|
794
803
|
"after_save_rubrics_currentStep_must_be_apply-icp-rubric",
|
|
795
804
|
"do_not_move_browser_to_messages_until_filter_leads_step_is_current_or_filters_are_explicitly_skipped",
|
|
796
|
-
"
|
|
805
|
+
"no_post_lead_worker_or_deep_prompt_before_filter_choice",
|
|
806
|
+
"lead_fit_builder_starts_only_after_filters_enabled",
|
|
807
|
+
"msg_draft_after_filter_choice",
|
|
808
|
+
"msg_draft_no_cells"
|
|
797
809
|
],
|
|
798
810
|
"transitions": {
|
|
799
|
-
"post_lead_workstreams_ready": "message-
|
|
811
|
+
"post_lead_workstreams_ready": "message-generation",
|
|
800
812
|
"revise_leads": "find-leads",
|
|
801
813
|
"revise_rubric": "filter-rubric",
|
|
802
814
|
"revise_messaging": "message-generation",
|
|
@@ -865,14 +877,23 @@
|
|
|
865
877
|
"id": "message-generation",
|
|
866
878
|
"label": "Message generation",
|
|
867
879
|
"onEnter": [
|
|
880
|
+
{
|
|
881
|
+
"action": "set_message_review_visible_step_by_filter_choice",
|
|
882
|
+
"tool": "update_campaign",
|
|
883
|
+
"branchRules": [
|
|
884
|
+
"yes: currentStep=apply-icp-rubric; wait on Filter Leads",
|
|
885
|
+
"no: currentStep=messages; message review"
|
|
886
|
+
],
|
|
887
|
+
"watchNarration.stage": "fit-message"
|
|
888
|
+
},
|
|
868
889
|
{
|
|
869
890
|
"action": "run_or_reconcile_message_draft_builder",
|
|
870
891
|
"target": "post-find-leads-message-scout",
|
|
871
892
|
"toolCallRequiredBeforeDraft": [
|
|
872
893
|
"get_subskill_prompt({ subskillName: \"generate-messages\", offset, limit }) until hasMore=false",
|
|
873
|
-
"
|
|
894
|
+
"parent approval uses references/message-review-safety-gate.md only"
|
|
874
895
|
],
|
|
875
|
-
"stateSource": "campaignBrief,
|
|
896
|
+
"stateSource": "campaignBrief, source, selectedLeadListId, workflowTableId, review-batch row ids/hash",
|
|
876
897
|
"outputState": "messageDraftRecommendation"
|
|
877
898
|
}
|
|
878
899
|
],
|
|
@@ -887,11 +908,12 @@
|
|
|
887
908
|
"get_subskill_asset",
|
|
888
909
|
"get_campaign",
|
|
889
910
|
"get_rows_minimal",
|
|
911
|
+
"update_campaign",
|
|
890
912
|
"AskUserQuestion",
|
|
891
913
|
"request_user_input"
|
|
892
914
|
],
|
|
893
915
|
"toolRules": [
|
|
894
|
-
"
|
|
916
|
+
"Message Draft Builder loads full get_subskill_prompt({ subskillName: \"generate-messages\" }) from live state. Parent approval uses message-review-safety-gate only.",
|
|
895
917
|
"Do not use brief.md, lead-review.md, or lead-sample.json as required live state; those files are optional debug context only.",
|
|
896
918
|
"The compact messageDraftRecommendation must return templateRecommendation, tokenFillRules, renderedSample, concerns, status, basisToken, outputAt, outputHash, and error or retry detail.",
|
|
897
919
|
"If campaign/source/table/review-batch basis does not match, classify the output stale or blocked."
|
|
@@ -902,7 +924,6 @@
|
|
|
902
924
|
"save_rubrics",
|
|
903
925
|
"import_leads",
|
|
904
926
|
"confirm_lead_list",
|
|
905
|
-
"update_campaign",
|
|
906
927
|
"queue_cells",
|
|
907
928
|
"start_campaign",
|
|
908
929
|
"generate_messages"
|
|
@@ -1124,8 +1145,14 @@
|
|
|
1124
1145
|
"cellSource": "pending_generate_message_cells_for_passing_rows using approved_campaign_brief_template"
|
|
1125
1146
|
},
|
|
1126
1147
|
{
|
|
1127
|
-
"tool": "
|
|
1128
|
-
"purpose": "
|
|
1148
|
+
"tool": "wait_for_rubric_results",
|
|
1149
|
+
"purpose": "wait_for_first_passing_generated_message",
|
|
1150
|
+
"requiredValues": {
|
|
1151
|
+
"includeRows": false,
|
|
1152
|
+
"minPassedCount": 1,
|
|
1153
|
+
"minMessagesCount": 1
|
|
1154
|
+
},
|
|
1155
|
+
"readVia": "stats_only_tool_result"
|
|
1129
1156
|
},
|
|
1130
1157
|
{
|
|
1131
1158
|
"action": "observe_generate_message_results",
|
|
@@ -1169,25 +1196,24 @@
|
|
|
1169
1196
|
"currentStep": "auto-execute-messaging",
|
|
1170
1197
|
"watchNarration.stage": "review-ready"
|
|
1171
1198
|
},
|
|
1172
|
-
"watchNarrationRule": "Say
|
|
1199
|
+
"watchNarrationRule": "Say the first passing generated message is ready in Messages; next is review before Settings."
|
|
1173
1200
|
},
|
|
1174
1201
|
{
|
|
1175
1202
|
"action": "ask_generated_message_review_choice",
|
|
1176
1203
|
"uses": "request_user_input",
|
|
1177
1204
|
"choices": [
|
|
1178
|
-
"Approve generated
|
|
1205
|
+
"Approve generated message and continue to Settings",
|
|
1179
1206
|
"Revise filters",
|
|
1180
1207
|
"Revise message template",
|
|
1181
1208
|
"Pause here"
|
|
1182
|
-
]
|
|
1183
|
-
"rule": "Do not advance to Settings until the generated review-batch messages have been reviewed and approved."
|
|
1209
|
+
]
|
|
1184
1210
|
}
|
|
1185
1211
|
],
|
|
1186
1212
|
"allowedTools": [
|
|
1187
1213
|
"get_subskill_asset",
|
|
1188
1214
|
"get_rows_minimal",
|
|
1189
1215
|
"queue_cells",
|
|
1190
|
-
"
|
|
1216
|
+
"wait_for_rubric_results",
|
|
1191
1217
|
"update_campaign",
|
|
1192
1218
|
"AskUserQuestion",
|
|
1193
1219
|
"request_user_input"
|
|
@@ -1201,6 +1227,7 @@
|
|
|
1201
1227
|
"hardRules": [
|
|
1202
1228
|
"critique_failure_never_escalates",
|
|
1203
1229
|
"critique_sample_size_bounded_by_config",
|
|
1230
|
+
"first_passing_generated_message_unblocks_review",
|
|
1204
1231
|
"critics_fixed_at_targeting_copy_voice",
|
|
1205
1232
|
"synthesis_enforces_phase_84_token_contract",
|
|
1206
1233
|
"opus_reserved_for_highest_value_subset",
|
|
@@ -60,9 +60,10 @@ auto-revise leads.
|
|
|
60
60
|
explicit batch count anyway so future larger expansion batches do not
|
|
61
61
|
accidentally stop early
|
|
62
62
|
(see §Known Tool Behaviors #3)
|
|
63
|
-
- minPassedCount=1 means one passing filtered row unblocks Step 15
|
|
64
|
-
|
|
65
|
-
before
|
|
63
|
+
- minPassedCount=1 means one passing filtered row unblocks Step 15 Generate
|
|
64
|
+
Message observation. Step 15 then waits only for one generated message
|
|
65
|
+
(`minMessagesCount=1`) before review. Do not wait for all sample rows to
|
|
66
|
+
finish before messages start.
|
|
66
67
|
|
|
67
68
|
7. call `wait_for_rubric_results` with `includeRows=false`; extract ONLY:
|
|
68
69
|
- ready: boolean
|
|
@@ -101,7 +102,9 @@ auto-revise leads.
|
|
|
101
102
|
10. branch:
|
|
102
103
|
if passInSample >= 1:
|
|
103
104
|
proceed to Step 15 (auto-execute-messaging) with currently passing rows
|
|
104
|
-
so Generate Message can start without waiting for the full sample
|
|
105
|
+
so Generate Message can start without waiting for the full sample. Once
|
|
106
|
+
one passing generated message is ready, stop for user review instead of
|
|
107
|
+
waiting for a stronger sample.
|
|
105
108
|
else:
|
|
106
109
|
diagnose (see Brief-vs-List Diagnosis below)
|
|
107
110
|
revisionRound += 1
|
|
@@ -179,7 +182,8 @@ processing makes the experience feel frozen.
|
|
|
179
182
|
|
|
180
183
|
Workaround: treat timeout stats as a partial sample. If at least one row has
|
|
181
184
|
passed, move to Step 15 and observe or queue Generate Message for the passing
|
|
182
|
-
rows
|
|
185
|
+
rows; Step 15 stops when one generated message is ready. If zero rows have
|
|
186
|
+
passed and no active processing is visible, stop at
|
|
183
187
|
`Status: sample-needs-revision` before Settings. Show the completed / passed /
|
|
184
188
|
pending counts and ask whether to revise source, revise filter/rubric, or wait
|
|
185
189
|
once only if active processing is still visible.
|
|
@@ -106,7 +106,7 @@ fills the source lead list; it does **not** clone rows into the campaign table:
|
|
|
106
106
|
```text
|
|
107
107
|
import_leads({
|
|
108
108
|
campaignOfferId,
|
|
109
|
-
targetLeadCount: <sourceCandidateTarget
|
|
109
|
+
targetLeadCount: <sourceCandidateTarget from approved good-fit math>,
|
|
110
110
|
// Signal Discovery only:
|
|
111
111
|
targetEngagerCount: <ceil(targetGoodFitLeads / sampledFitRateAfterCleanup)>,
|
|
112
112
|
maxPostsToScrape: <postsNeeded from approved math>
|
|
@@ -114,9 +114,15 @@ import_leads({
|
|
|
114
114
|
```
|
|
115
115
|
|
|
116
116
|
Provider is inherited from the selected source decision (not re-selected here)
|
|
117
|
-
and should already be saved on the campaign before import.
|
|
118
|
-
|
|
119
|
-
|
|
117
|
+
and should already be saved on the campaign before import. For Sales Nav and
|
|
118
|
+
Prospeo, `<sourceCandidateTarget>` is not the 25-row review batch. It is the
|
|
119
|
+
source-list export/materialization count from the approved source math:
|
|
120
|
+
`min(rawResultCount, providerMax, ceil(targetGoodFitLeads /
|
|
121
|
+
projectedFitRateAfterCleanup))`. If projected good fits remain below the target
|
|
122
|
+
(often about 150+ usable prospects unless the campaign/source defaults specify
|
|
123
|
+
otherwise), return to find-leads and refine filters before import. Response
|
|
124
|
+
returns `{ imported, skipped, duplicates }` — surface all three to the
|
|
125
|
+
escalation logic so dedup ratios are visible.
|
|
120
126
|
|
|
121
127
|
For Signal Discovery, do not scrape every currently selected/promoted sample
|
|
122
128
|
post by default. Before `import_leads`, reconcile selected posts with the
|