@sellable/mcp 0.1.952 → 0.1.953

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.
@@ -141,6 +141,7 @@ export interface CreateCampaignInput {
141
141
  offerPositioning?: unknown;
142
142
  campaignBrief?: string;
143
143
  messageGenerationMode?: "template" | "ai-generated";
144
+ messageApproach?: "conversation" | "message_test";
144
145
  currentStep?: string | null;
145
146
  watchNarration?: unknown;
146
147
  leadSourceType?: string | null;
@@ -167,6 +168,7 @@ export interface UpdateCampaignInput {
167
168
  interactionMode?: InteractionMode;
168
169
  enableICPFilters?: boolean | null;
169
170
  useMessagingTemplate?: boolean | null;
171
+ messageApproach?: "conversation" | "message_test";
170
172
  autoApproveFollowups?: boolean;
171
173
  enableFollowUps?: boolean;
172
174
  senderIds?: string[];
@@ -251,6 +253,7 @@ export declare const campaignToolDefinitions: ({
251
253
  offerPositioning?: undefined;
252
254
  campaignBrief?: undefined;
253
255
  messageGenerationMode?: undefined;
256
+ messageApproach?: undefined;
254
257
  currentStep?: undefined;
255
258
  watchNarration?: undefined;
256
259
  leadSourceType?: undefined;
@@ -300,6 +303,7 @@ export declare const campaignToolDefinitions: ({
300
303
  offerPositioning?: undefined;
301
304
  campaignBrief?: undefined;
302
305
  messageGenerationMode?: undefined;
306
+ messageApproach?: undefined;
303
307
  currentStep?: undefined;
304
308
  watchNarration?: undefined;
305
309
  leadSourceType?: undefined;
@@ -351,6 +355,7 @@ export declare const campaignToolDefinitions: ({
351
355
  offerPositioning?: undefined;
352
356
  campaignBrief?: undefined;
353
357
  messageGenerationMode?: undefined;
358
+ messageApproach?: undefined;
354
359
  currentStep?: undefined;
355
360
  watchNarration?: undefined;
356
361
  leadSourceType?: undefined;
@@ -398,6 +403,7 @@ export declare const campaignToolDefinitions: ({
398
403
  offerPositioning?: undefined;
399
404
  campaignBrief?: undefined;
400
405
  messageGenerationMode?: undefined;
406
+ messageApproach?: undefined;
401
407
  currentStep?: undefined;
402
408
  watchNarration?: undefined;
403
409
  leadSourceType?: undefined;
@@ -445,6 +451,7 @@ export declare const campaignToolDefinitions: ({
445
451
  offerPositioning?: undefined;
446
452
  campaignBrief?: undefined;
447
453
  messageGenerationMode?: undefined;
454
+ messageApproach?: undefined;
448
455
  currentStep?: undefined;
449
456
  watchNarration?: undefined;
450
457
  leadSourceType?: undefined;
@@ -535,6 +542,7 @@ export declare const campaignToolDefinitions: ({
535
542
  offerPositioning?: undefined;
536
543
  campaignBrief?: undefined;
537
544
  messageGenerationMode?: undefined;
545
+ messageApproach?: undefined;
538
546
  currentStep?: undefined;
539
547
  watchNarration?: undefined;
540
548
  leadSourceType?: undefined;
@@ -593,6 +601,11 @@ export declare const campaignToolDefinitions: ({
593
601
  enum: string[];
594
602
  description: string;
595
603
  };
604
+ messageApproach: {
605
+ type: string;
606
+ enum: string[];
607
+ description: string;
608
+ };
596
609
  currentStep: {
597
610
  type: string[];
598
611
  description: string;
@@ -971,6 +984,11 @@ export declare const campaignToolDefinitions: ({
971
984
  type: string[];
972
985
  description: string;
973
986
  };
987
+ messageApproach: {
988
+ type: string;
989
+ enum: string[];
990
+ description: string;
991
+ };
974
992
  autoApproveFollowups: {
975
993
  type: string;
976
994
  description: string;
@@ -1038,6 +1056,7 @@ export declare const campaignToolDefinitions: ({
1038
1056
  offerPositioning?: undefined;
1039
1057
  campaignBrief?: undefined;
1040
1058
  messageGenerationMode?: undefined;
1059
+ messageApproach?: undefined;
1041
1060
  currentStep?: undefined;
1042
1061
  watchNarration?: undefined;
1043
1062
  leadSourceType?: undefined;
@@ -1088,6 +1107,7 @@ export declare const campaignToolDefinitions: ({
1088
1107
  senderLinkedinUrl?: undefined;
1089
1108
  offerPositioning?: undefined;
1090
1109
  messageGenerationMode?: undefined;
1110
+ messageApproach?: undefined;
1091
1111
  currentStep?: undefined;
1092
1112
  watchNarration?: undefined;
1093
1113
  leadSourceType?: undefined;
@@ -447,6 +447,11 @@ export const campaignToolDefinitions = [
447
447
  enum: ["template", "ai-generated"],
448
448
  description: "Defaults to template for autonomous messaging steps. Use ai-generated only when the user explicitly approves freeform AI-generated messages instead of an approved {{token}} template.",
449
449
  },
450
+ messageApproach: {
451
+ type: "string",
452
+ enum: ["conversation", "message_test"],
453
+ description: 'How first messages are written. "conversation": each first message is written for that person by the backend writer and opens a conversation, with no pitch; the campaign must have NO approved message template and no {{token}} copy in the brief. "message_test": one approved message template goes to everyone, for testing copy. Omit to leave the campaign as it is.',
454
+ },
450
455
  currentStep: {
451
456
  type: ["string", "null"],
452
457
  description: "Workflow step ID (headless or UI step ID such as filter-rules)",
@@ -569,6 +574,11 @@ export const campaignToolDefinitions = [
569
574
  type: ["boolean", "null"],
570
575
  description: "Whether to use the messaging template step",
571
576
  },
577
+ messageApproach: {
578
+ type: "string",
579
+ enum: ["conversation", "message_test"],
580
+ description: 'How first messages are written. "conversation": each first message is written for that person by the backend writer and opens a conversation, with no pitch; the campaign must have NO approved message template and no {{token}} copy in the brief. "message_test": one approved message template goes to everyone, for testing copy. Omit to leave the campaign as it is.',
581
+ },
572
582
  autoApproveFollowups: {
573
583
  type: "boolean",
574
584
  description: "Whether drafted campaign follow-ups are automatically approved/sent. This does not draft, approve, or send an individual prospect message during the settings update.",
@@ -1046,7 +1056,10 @@ export async function createCampaign(input) {
1046
1056
  const isAutonomousMessageMint = currentStep === "auto-execute-leads" ||
1047
1057
  currentStep === "validate-sample" ||
1048
1058
  currentStep === "auto-execute-messaging";
1049
- const explicitlyAllowsAiGenerated = input.messageGenerationMode === "ai-generated";
1059
+ // A conversation campaign has no template by design: each first message is
1060
+ // written for the person by the backend writer.
1061
+ const explicitlyAllowsAiGenerated = input.messageGenerationMode === "ai-generated" ||
1062
+ input.messageApproach === "conversation";
1050
1063
  const hasTemplateToken = /\{\{\s*\S[^}]*\}\}/.test(briefContent);
1051
1064
  if (isAutonomousMessageMint &&
1052
1065
  !explicitlyAllowsAiGenerated &&
@@ -12,6 +12,9 @@ export type CampaignOfferNavigation = {
12
12
  useMessagingTemplate?: boolean | null;
13
13
  messagingTemplateId?: string | null;
14
14
  messagingTemplate?: unknown | null;
15
+ messageGenerator?: {
16
+ mode?: string | null;
17
+ } | null;
15
18
  leadSourceType?: string | null;
16
19
  leadSourceProvider?: string | null;
17
20
  selectedLeadListId?: string | null;
@@ -140,6 +140,10 @@ function hasActiveRubrics(campaign) {
140
140
  function hasApprovedMessageTemplate(campaign) {
141
141
  if (campaign.messagingTemplateId || campaign.messagingTemplate)
142
142
  return true;
143
+ // A conversation campaign never has a template; its messages are written
144
+ // per person, so the message approach is already settled.
145
+ if (campaign.messageGenerator?.mode === "CONVERSATION")
146
+ return true;
143
147
  const briefContent = getBriefContent(campaign.campaignBrief);
144
148
  if (!briefContent.trim())
145
149
  return false;
@@ -2334,6 +2334,7 @@ export declare const allTools: ({
2334
2334
  offerPositioning?: undefined;
2335
2335
  campaignBrief?: undefined;
2336
2336
  messageGenerationMode?: undefined;
2337
+ messageApproach?: undefined;
2337
2338
  currentStep?: undefined;
2338
2339
  watchNarration?: undefined;
2339
2340
  leadSourceType?: undefined;
@@ -2383,6 +2384,7 @@ export declare const allTools: ({
2383
2384
  offerPositioning?: undefined;
2384
2385
  campaignBrief?: undefined;
2385
2386
  messageGenerationMode?: undefined;
2387
+ messageApproach?: undefined;
2386
2388
  currentStep?: undefined;
2387
2389
  watchNarration?: undefined;
2388
2390
  leadSourceType?: undefined;
@@ -2434,6 +2436,7 @@ export declare const allTools: ({
2434
2436
  offerPositioning?: undefined;
2435
2437
  campaignBrief?: undefined;
2436
2438
  messageGenerationMode?: undefined;
2439
+ messageApproach?: undefined;
2437
2440
  currentStep?: undefined;
2438
2441
  watchNarration?: undefined;
2439
2442
  leadSourceType?: undefined;
@@ -2481,6 +2484,7 @@ export declare const allTools: ({
2481
2484
  offerPositioning?: undefined;
2482
2485
  campaignBrief?: undefined;
2483
2486
  messageGenerationMode?: undefined;
2487
+ messageApproach?: undefined;
2484
2488
  currentStep?: undefined;
2485
2489
  watchNarration?: undefined;
2486
2490
  leadSourceType?: undefined;
@@ -2528,6 +2532,7 @@ export declare const allTools: ({
2528
2532
  offerPositioning?: undefined;
2529
2533
  campaignBrief?: undefined;
2530
2534
  messageGenerationMode?: undefined;
2535
+ messageApproach?: undefined;
2531
2536
  currentStep?: undefined;
2532
2537
  watchNarration?: undefined;
2533
2538
  leadSourceType?: undefined;
@@ -2618,6 +2623,7 @@ export declare const allTools: ({
2618
2623
  offerPositioning?: undefined;
2619
2624
  campaignBrief?: undefined;
2620
2625
  messageGenerationMode?: undefined;
2626
+ messageApproach?: undefined;
2621
2627
  currentStep?: undefined;
2622
2628
  watchNarration?: undefined;
2623
2629
  leadSourceType?: undefined;
@@ -2676,6 +2682,11 @@ export declare const allTools: ({
2676
2682
  enum: string[];
2677
2683
  description: string;
2678
2684
  };
2685
+ messageApproach: {
2686
+ type: string;
2687
+ enum: string[];
2688
+ description: string;
2689
+ };
2679
2690
  currentStep: {
2680
2691
  type: string[];
2681
2692
  description: string;
@@ -3054,6 +3065,11 @@ export declare const allTools: ({
3054
3065
  type: string[];
3055
3066
  description: string;
3056
3067
  };
3068
+ messageApproach: {
3069
+ type: string;
3070
+ enum: string[];
3071
+ description: string;
3072
+ };
3057
3073
  autoApproveFollowups: {
3058
3074
  type: string;
3059
3075
  description: string;
@@ -3121,6 +3137,7 @@ export declare const allTools: ({
3121
3137
  offerPositioning?: undefined;
3122
3138
  campaignBrief?: undefined;
3123
3139
  messageGenerationMode?: undefined;
3140
+ messageApproach?: undefined;
3124
3141
  currentStep?: undefined;
3125
3142
  watchNarration?: undefined;
3126
3143
  leadSourceType?: undefined;
@@ -3171,6 +3188,7 @@ export declare const allTools: ({
3171
3188
  senderLinkedinUrl?: undefined;
3172
3189
  offerPositioning?: undefined;
3173
3190
  messageGenerationMode?: undefined;
3191
+ messageApproach?: undefined;
3174
3192
  currentStep?: undefined;
3175
3193
  watchNarration?: undefined;
3176
3194
  leadSourceType?: undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sellable/mcp",
3
- "version": "0.1.952",
3
+ "version": "0.1.953",
4
4
  "type": "module",
5
5
  "description": "Sellable MCP server for Claude Code, Codex, and Hermes campaign workflows",
6
6
  "main": "dist/index.js",
@@ -80,6 +80,12 @@ approval and campaign setup validation.
80
80
  Use `research-sender`, call `complete_sender_research` before shell creation,
81
81
  and carry proof gaps into the brief.
82
82
 
83
+ ## Message Approach
84
+
85
+ Before `create_campaign`, load `references/message-approach.md` and choose how
86
+ first messages are written: Conversations (each written for the person, no
87
+ template) or Message Lab (one approved template). Pass it as `messageApproach`.
88
+
83
89
  ## Brief Provenance
84
90
 
85
91
  When rendering the first brief, do not add bracketed inline source tags. Start
@@ -308,6 +314,7 @@ Route user copy feedback before `approve-message` back to Message Drafting; pare
308
314
 
309
315
  Load references only when needed:
310
316
 
317
+ - `references/message-approach.md` before `create_campaign`.
311
318
  - `references/watch-link-handoff.md` for watch-link handoff.
312
319
  - `references/watch-guide-narration.md` for watch narration.
313
320
  - `references/lead-validation-preview.md` for legacy/debug preview shapes.
@@ -540,4 +540,6 @@ marketplace actors, wrong function, or no budget path, classify it as
540
540
 
541
541
  After filters are saved, wait for explicit filter approval before Filter Leads.
542
542
  Then wait for message template/token approval before enrichment, scoring, or
543
- Generate Message cells are queued.
543
+ Generate Message cells are queued. A Conversations campaign
544
+ (`references/message-approach.md`) has no template to approve: queue the
545
+ sample once the filters are settled.
@@ -0,0 +1,70 @@
1
+ # Message Approach
2
+
3
+ Every campaign writes its first message one of two ways. Decide which before
4
+ `create_campaign`, pass it as `messageApproach`, and say which you picked in
5
+ one plain line the customer can correct.
6
+
7
+ - **Conversations** (`messageApproach: "conversation"`). Each first message is
8
+ written for that one person by Sellable's writer and opens a conversation.
9
+ It carries no pitch and no ask; the offer comes up once they reply. Choose
10
+ it when replies have an owner: reply drafting is on for the campaign (the
11
+ default), so each reply arrives as a draft to approve, or the workspace's
12
+ Reply Agent answers.
13
+ - **Message Lab** (`messageApproach: "message_test"`). One approved message
14
+ goes to everyone, so the customer can test which copy wins. This is the
15
+ template flow described in the create-campaign-v2 prompt and flow file. Choose it when the
16
+ customer wants to approve exact wording, test copy against copy, or has
17
+ switched reply drafting off.
18
+
19
+ When the customer has not said, use Conversations if replies have an owner and
20
+ Message Lab otherwise. "Same message to everyone", "test my copy" or "I want
21
+ to approve the wording" means Message Lab. "Write each one", "personal",
22
+ "conversational" or "use the reply agent" means Conversations. Change an
23
+ existing campaign with `update_campaign({ campaignId, messageApproach })`.
24
+
25
+ **A Conversations campaign has no template.** The backend writes each message
26
+ only when the campaign carries no approved template, so:
27
+
28
+ - write no `## Approved Message Template` section, no `{{token}}` copy and no
29
+ first-message wording into the brief, and keep pitch wording out of `dos`;
30
+ - put the offer and the proof under headings that say "for replies only";
31
+ - when the first message goes out as a DM after the connection request is
32
+ accepted (the recommended sequence), add this line to the campaign `dos`
33
+ with the sender's first name: "This first message goes out as a LinkedIn DM
34
+ after they accept {sender}'s connection request: thank them for
35
+ connecting.";
36
+ - skip Message Drafting, the message template review and the template
37
+ approval. After the filters are saved, queue enrichment for the sample;
38
+ fit scoring and Generate Message follow on their own;
39
+ - review the generated messages themselves before showing or approving
40
+ them: the person and company match the profile, no pitch, and nothing
41
+ about the person that their profile does not show (a guessed city, a guessed
42
+ role). Leave a message that fails out of the sample, say so in one line,
43
+ and do not approve that row until it is rewritten
44
+ (`queue_campaign_cells` with `columnRole: "generateMessage"`, that row,
45
+ `forceRerun: true`). `get_campaign` reports the saved approach as
46
+ `campaignOffer.messageApproach`.
47
+
48
+ **The writer sounds like the sender only when it knows the sender.** With
49
+ exactly one sender attached to the campaign and that sender's context saved,
50
+ it writes the full message, including a line about the sender. With no sender,
51
+ several senders, or no saved context it writes the short form: a greeting,
52
+ one plain line about the person's work, and a light line about their town. So in a Conversations campaign:
53
+
54
+ 1. Ask for the LinkedIn connection before the sample, not after it.
55
+ 2. Once `list_senders` shows the account, attach it
56
+ (`update_campaign({ campaignId, senderIds: [id] })`), read it with
57
+ `get_sender`, and save what the profile research found with
58
+ `set_sender_context` (pass `get_sender`'s `generationContext.updatedAt` as
59
+ `expectedUpdatedAt`, null on the first save). Use facts from the sender's
60
+ own profile only: what they built and did (`workStories`), plain personal
61
+ facts (`personalNotes`), a few lines in their own words from their posts
62
+ or About (`voiceExamples`), and what they may share or will not say
63
+ (`sourcesAndLimits`).
64
+ 3. Generate or regenerate the sample after that
65
+ (`queue_campaign_cells` with `columnRole: "generateMessage"`, the sample
66
+ rows, `forceRerun: true`).
67
+
68
+ If the customer has not connected an account when the sample is ready, show
69
+ the short-form sample and say the messages gain a line about them once the
70
+ account is connected.
@@ -54,7 +54,8 @@ rerun `import_leads`.
54
54
  only after saved-filter approval; `validate-sample` is the logical loop name,
55
55
  not a visible route)
56
56
  - Approved message template/token rules exist in the campaign brief before any
57
- enrichment or scoring cells are queued
57
+ enrichment or scoring cells are queued (Message Lab only; a Conversations
58
+ campaign has no template)
58
59
  - Confirmed campaign rows from Step 13, with the internal execution slice stored
59
60
  in `WorkflowTable.config.mcp.reviewBatch` (default 15)
60
61
  - Config from `auto-execute.yaml`: `sample.sampleSize`,
@@ -8,6 +8,13 @@ visibility: internal
8
8
 
9
9
  This is the tail detail extracted from the main create-campaign-v2 SKILL.md to keep the entry prompt slim. The agent loads this on-demand BEFORE entering the auto-execute or validate-sample steps. Follow this verbatim.
10
10
 
11
+ **Conversations campaigns** (`messageApproach: "conversation"`, see
12
+ `create-campaign-v2` `references/message-approach.md`) have no message
13
+ template. Every rule below that requires an approved template, `{{...}}`
14
+ tokens in the brief, Message Drafting, or template approval before queueing
15
+ applies to Message Lab campaigns only. In a Conversations campaign the same
16
+ cascade writes each message once a row passes the fit check.
17
+
11
18
  CampaignOffer state and the watch link are canonical. Disk artifacts are
12
19
  optional debug/UAT diagnostics; normal customer runs should not expose local
13
20
  draft files. Resume, gating, and handoff read campaign state first.
@@ -380,7 +387,8 @@ the output — not to generate messages manually.
380
387
  **What Step 15 does:**
381
388
 
382
389
  1. Before queueing or waiting on Generate Message cells, confirm the minted
383
- campaign brief still contains `{{...}}` in `## Approved Message Template`.
390
+ campaign brief still contains `{{...}}` in `## Approved Message Template`
391
+ (Message Lab only; a Conversations campaign must have no template).
384
392
  If it does not, fail before the cascade runs. Do not repair after mint; the
385
393
  template must be present during mint so Step 15 never starts in freeform
386
394
  generation mode.
@@ -48,7 +48,9 @@ reply to either the same way.)
48
48
  A reply in that thread is explicit permission to begin preparation, not
49
49
  permission to send. It needs no mention of this Agent.
50
50
 
51
- - **The reply contains a LinkedIn profile URL.** Send one short line first so
51
+ - **The reply contains a LinkedIn profile URL or handle.** A single word such
52
+ as `csreyes92` or `@csreyes92` is a handle: read it as
53
+ `https://www.linkedin.com/in/{handle}/`. Send one short line first so
52
54
  the customer is not left looking at silence: "Got it. Researching you and
53
55
  your company now. I'll be back in a few minutes with a first campaign to
54
56
  review." Send it before the Live State Check and before loading any other
@@ -278,6 +280,15 @@ for the message template: those are yours to decide and report.
278
280
  - Do not paste the full brief into Slack. Save it on the campaign and post the
279
281
  five-line summary below.
280
282
 
283
+ **How the first message is written.** The first campaign uses the
284
+ Conversations approach from the workflow's `references/message-approach.md`:
285
+ create it with `messageApproach: "conversation"`, write no message template,
286
+ and let Sellable's writer write each first message for the person. Use Message
287
+ Lab (`"message_test"`, one approved message to everyone) only when the
288
+ customer asks to send the same message to everyone, to test copy, or to
289
+ approve exact wording; then the template steps of the workflow apply and you
290
+ approve the template yourself as before.
291
+
281
292
  **Approval 1: direction.** After research, write the brief, create the
282
293
  campaign with it (`create_campaign`), and post one message in this shape. The
283
294
  saved brief is the full brief; this message is how the customer approves it,
@@ -292,6 +303,7 @@ Here's the first campaign I'd run for {company}.
292
303
  *Offer* {what you would get to once they reply, and the small ask, one line}
293
304
  *Proof* {the proof you would lead with; if you found none, say so and what you would use instead}
294
305
  *Where I'll look* {where you will find them first, in plain words}
306
+ *Messages* Written for each person to open a conversation; the offer comes once they reply. Say "same message to everyone" if you'd rather test one message.
295
307
 
296
308
  Full brief: {campaign link}
297
309
 
@@ -325,13 +337,17 @@ do-not-contact gate; do not ask again before the import.
325
337
 
326
338
  **Between 1 and 2.** Once the direction and the do-not-contact answer are in,
327
339
  reply first, before any tool call: "On it. I'll find the people, check who
328
- fits and write the message. Your sample will be here in about 15 to 20
329
- minutes." Then set `interactionMode: "autonomous"` on the campaign with
340
+ fits and write the messages. Your sample will be here in about 15 to 20
341
+ minutes. While I work: connect the LinkedIn account that will send,
342
+ https://app.sellable.dev/linkedin-accounts It takes about two minutes, it is
343
+ only used to send what you approve, and once it's connected I write the
344
+ messages in your voice." Then set `interactionMode: "autonomous"` on the campaign with
330
345
  `update_campaign` and pass `confirmed: true` where a search or import tool
331
346
  asks for it: the direction approval is that confirmation. Do the work without
332
347
  asking: pick where to look, find and import the people within the flow's
333
- caps, use filters and write the rules, write the message, and prepare the
334
- 15-person sample.
348
+ caps, use filters and write the rules, and prepare the 15-person sample. In
349
+ Conversations there is no template to write: queue the sample once the rules
350
+ are saved and the messages are written for you.
335
351
 
336
352
  - **Keep the customer posted.** Whenever about five minutes have passed since
337
353
  your last message, post one short line in plain words on where you are
@@ -353,6 +369,13 @@ caps, use filters and write the rules, write the message, and prepare the
353
369
  - **Let the sample finish.** The flow stops at the first passing message; here
354
370
  wait until the 15-person sample has finished scoring and writing, because
355
371
  the customer is shown three people and a count.
372
+ - **The sender, as soon as there is one.** Check `list_senders` when the
373
+ import finishes and again before you show the sample. When the customer's
374
+ account is there, attach it to the campaign, save what your research found
375
+ about them as sender context, and write or rewrite the sample after that,
376
+ as `references/message-approach.md` describes. A sample written
377
+ before the account was connected is the short form, with nothing about the
378
+ sender.
356
379
  - **Check before you show.** For each message you are about to show, compare
357
380
  the company it names with the person's own headline. Leave out any that
358
381
  disagree and say that you dropped them.
@@ -361,7 +384,7 @@ caps, use filters and write the rules, write the message, and prepare the
361
384
  real message each would receive:
362
385
 
363
386
  ```text
364
- Your sample is ready: {n} real people and the message each would get.
387
+ Your sample is ready: {the number you show below} real people and the message each would get.
365
388
 
366
389
  {Name} · {title}, {company} · {why they are here, a few words}
367
390
  "{the message they would receive}"
@@ -370,10 +393,11 @@ Your sample is ready: {n} real people and the message each would get.
370
393
 
371
394
  {passed} of {checked} people I checked fit. {one line on why the rest did not}
372
395
  What I chose: {where the people came from and how many are on the list, and the fit rules in a few words}
373
- The first message has no pitch on purpose. {the offer} comes once they reply.
396
+ Each message is written for that person and has no pitch on purpose. {the offer} comes once they reply.
397
+ {only if no sending account is connected yet: "These are the short version. Connect your LinkedIn account and I'll rewrite them with a line about you: https://app.sellable.dev/linkedin-accounts"}
374
398
  Everyone and every message: {campaign link}
375
399
 
376
- Reply approve to use these people and this message, or tell me what to change.
400
+ Reply approve to use these people and messages like these, or tell me what to change.
377
401
  Nothing has been sent.
378
402
  ```
379
403
 
@@ -383,8 +407,8 @@ the customer kept as approved in the table, not one or two. A person the
383
407
  customer dropped stays unapproved; never approve them later, in bulk or
384
408
  otherwise.
385
409
 
386
- **Approval 3: launch.** The only thing left is the sending account. Call
387
- `list_senders`.
410
+ **Approval 3: launch.** The only thing that can still be missing is the
411
+ sending account. Call `list_senders`.
388
412
 
389
413
  - **No usable sender.** Ask for that one thing: "One thing left: connect the
390
414
  LinkedIn account that will send. https://app.sellable.dev/linkedin-accounts