@agifyai/leadify-mcp 9.7.2 → 9.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -505,7 +505,8 @@ moment pour une personne, avec au plus un message Gmail et un message ou une
505
505
  invitation LinkedIn. Aucune séquence ni étape future. Le MCP ne contacte jamais
506
506
  Gmail ou Unipile pour envoyer : Leadify contrôle et exécute les dépôts acceptés.
507
507
 
508
- `get_mcp_runtime_info` annonce les 16 capacités du paquet et les versions serveur
508
+ `get_mcp_runtime_info` annonce les 30 capacités du paquet, les 13 modules du
509
+ contexte de rédaction (`outreach.contextModules`) et les versions serveur
509
510
  attendues. `probe_outreach: true` vérifie en plus le contrat des programmes dans
510
511
  l'organisation choisie, sans lire de prospect. `PROGRAM_CONTRACT_VERIFIED` ne
511
512
  prouve ni les autres routes ni une autorisation commerciale. Chaque réponse
@@ -533,7 +534,9 @@ Les tests de contrat et de transport sont dans `test/agent-outreach.test.mjs` ;
533
534
  | Sélection avant pagination | `query_outreach_prospects` | R | POST A/prospects/query | filtres complets, pages, erreurs |
534
535
  | Résumé d'une personne | `get_outreach_prospect_summary` | R | GET A/prospects/:leadId | identité explicite |
535
536
  | Historique des contacts | `get_outreach_contact_history` | R | GET A/contacts/:leadId | comptes accessibles, couverture |
536
- | Contexte frais de rédaction | `get_outreach_prospect_context` | R | GET C/people/:leadId/context | contrat, versions, état prêt ou attente |
537
+ | Contexte de rédaction, entrée légère | `get_outreach_context_summary` | R | GET C/people/:leadId/context/summary | versions, état prêt ou attente, 13 modules avec taille et empreinte, `decisionContext` |
538
+ | Contexte de rédaction, un module | `get_outreach_context_<module>` (13 outils) | R | GET C/people/:leadId/context/modules/:module | module, empreinte, `readAt`, curseur pour `signals` et `history` |
539
+ | Contexte entier (ancien) | `get_outreach_prospect_context` | R | GET C/people/:leadId/context | contrat, versions ; environ 90 Ko, à éviter |
537
540
  | Fil exact | `get_outreach_thread` | R | GET C/people/:leadId/thread | account_key, thread_id, curseur |
538
541
  | Décisions présentes | `submit_outreach_messages` | W | POST A/messages/batch | schéma, texte intact, reprises, lot partiel |
539
542
  | Messages de cette clé | `list_outreach_messages` | read + organisation | GET A/messages | pagination, projection sûre |
@@ -578,7 +581,9 @@ Gmail confirmé, sans message Gmail en attente ou inconnu. Les invitations sont
578
581
  comptées séparément. `replies_to_handle` sélectionne les réponses à traiter dans
579
582
  leur propre fil. `filters.signal_filter` accepte `detected_since`,
580
583
  `detected_before`, `levels` (`STRONG`, `GOLDEN`, `CRITICAL`) et `scope`
581
- (`PERSON`, `COMPANY`, `BOTH`). L'absence d'historique connu n'est pas la preuve
584
+ (`PERSON`, `COMPANY`, `BOTH`). `filters.qualified: true` garde les personnes
585
+ dont la qualification est terminée ; `filters.qualification_levels` (`hot`,
586
+ `warm`, `cold`, de une à trois valeurs) filtre la température (PRD-2650). L'absence d'historique connu n'est pas la preuve
582
587
  qu'une personne n'a jamais été contactée.
583
588
 
584
589
  La sélection expire après dix minutes. Passer son `nextCursor` dans `cursor` avec
@@ -587,10 +592,55 @@ droits est refusé ; aucun redémarrage caché n'a lieu. Programmes, messages et
587
592
  conversations utilisent `after_id` pour leur page suivante. Les événements et les
588
593
  fils utilisent `cursor`. Les curseurs sont opaques et ne doivent pas être inventés.
589
594
 
590
- `get_outreach_prospect_summary` est un résumé. Avant d'écrire, lire
591
- `get_outreach_prospect_context`, vérifier `readiness.ready`, puis les fils exacts
592
- nécessaires avec `get_outreach_thread`. Un corps indisponible ou un simple extrait
593
- ne vaut pas une conversation complète. Le contexte n'effectue aucune qualification.
595
+ `get_outreach_prospect_summary` est un résumé de la sélection, pas le contexte de
596
+ rédaction. Avant d'écrire, lire `get_outreach_context_summary`, vérifier
597
+ `readiness.ready`, puis chaque module dans l'ordre de `readOrder`, puis les fils
598
+ exacts nécessaires avec `get_outreach_thread`. Un corps indisponible ou un simple
599
+ extrait ne vaut pas une conversation complète. Le contexte n'effectue aucune
600
+ qualification.
601
+
602
+ #### Contexte de rédaction par modules (PRD-2632)
603
+
604
+ La lecture entière `get_outreach_prospect_context` pèse près de 90 Ko. Un agent dont
605
+ l'exécution écarte tout résultat d'outil de plus de 50 000 caractères (Hermès) ne la
606
+ voit jamais. Elle est conservée mais déconseillée : lire le sommaire, puis un module
607
+ à la fois. Toutes ces réponses sont en JSON compact, sur une seule ligne.
608
+
609
+ `get_outreach_context_summary` rend, en quelques Ko : les identifiants, `readiness`,
610
+ les huit `versions`, `contextVersion`, `factsVersion`, `readAt`, `readOrder`, la liste
611
+ des treize modules (`module`, `version` = empreinte, `characters`, `pages`, `purpose`),
612
+ les `warnings` (module trop grand, historique incomplet) et `decisionContext`, le bloc
613
+ à recopier dans le `context` de chaque décision déposée.
614
+
615
+ Les treize outils `get_outreach_context_<module>`, dans l'ordre de lecture utile :
616
+
617
+ | Module | Contenu | Pages |
618
+ |---|---|---|
619
+ | `prospect` | identité, coordonnées, langue, poste | 1 |
620
+ | `company` | employeur et fiches entreprise qualifiées | 1 |
621
+ | `workspace` | choix du groupe : persona, verticale, offre, expéditeur, appel à l'action | 1 |
622
+ | `company_brain` | Company Brain de l'organisation qui prospecte | 1 |
623
+ | `vertical` | verticale du persona | 1 |
624
+ | `offers` | offre retenue (trois au plus) | 1 |
625
+ | `persona` | persona et son contrat de rédaction | 1 |
626
+ | `playbook` | playbook commercial publié | 1 |
627
+ | `qualification` | fiche de qualification de la personne | 1 |
628
+ | `signals` | signaux récents, le plus récent d'abord | curseur |
629
+ | `history` | messages échangés avec leur texte, fils connus | curseur |
630
+ | `crm` | statut CRM, exclusion, réception, prise en main humaine | 1 |
631
+ | `authorization` | état du programme, plafonds, expéditeurs, droits | 1 |
632
+
633
+ Chaque réponse contient `module`, `version` (l'empreinte du module), `readAt`, `data`
634
+ et `page` (null, ou `nextCursor` à repasser tel quel dans `cursor`). Un module paginé
635
+ rend son en-tête avec la première page seulement ; une page tient sous environ
636
+ 25 000 caractères. Si `version` diffère de celle du sommaire, le contexte a changé
637
+ entre deux lectures : repartir du sommaire. Un curseur lié à une empreinte périmée est
638
+ refusé (`VERSION_CONFLICT`).
639
+
640
+ Au dépôt, `context.modules` reprend `decisionContext.modules` à l'identique (les treize
641
+ empreintes). Il est facultatif pour les anciens clients et strict quand il est présent.
642
+ Les huit `versions` restent obligatoires. Si une empreinte a bougé depuis la lecture,
643
+ Leadify refuse avec `CONTEXT_STALE` et nomme les modules (`CONTEXT_MODULE_CHANGED:<module>`).
594
644
 
595
645
  ### Dépôt et reprise
596
646
 
@@ -601,7 +651,9 @@ et `messages` (1 à 2, un par canal).
601
651
 
602
652
  Le contexte transmis comporte `contract_version: "agent-writing-context.v1"`,
603
653
  `context_version`, `facts_version`, `read_at` et l'objet `versions` exact reçu du
604
- serveur. Les clés de cet objet restent inchangées, dont `contactState`. Un message
654
+ serveur. Les clés de cet objet restent inchangées, dont `contactState`. Quand la
655
+ rédaction vient du contexte par modules, `modules` (les treize empreintes de
656
+ `decisionContext.modules`) l'accompagne. Un message
605
657
  contient `channel`, `action`, `sender_id`, `account_key`, `recipient`, `subject`,
606
658
  `body`, `thread_id`, `expected_inbound_id`, `technical_parts` (signature et
607
659
  unsubscribe). Les champs nullables doivent être présents. Une réponse désigne
@@ -2,7 +2,13 @@ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { type LeadifyClient } from "../client.js";
3
3
  import { type ToolResult } from "../types.js";
4
4
  export declare const OUTREACH_MCP_CONTRACT = "leadify-outreach-mcp.v1";
5
- export declare const OUTREACH_TOOL_NAMES: readonly ["list_outreach_programs", "get_outreach_program_context", "query_outreach_prospects", "get_outreach_prospect_summary", "get_outreach_contact_history", "get_outreach_prospect_context", "get_outreach_thread", "submit_outreach_messages", "list_outreach_messages", "get_outreach_message", "cancel_outreach_message", "list_outreach_events", "acknowledge_outreach_events", "get_outreach_reception_health", "list_outreach_conversations", "get_outreach_conversation"];
5
+ /** PRD-2632 : writing context read in pieces. Same order as the server's `readOrder`. */
6
+ export declare const OUTREACH_CONTEXT_MODULES: readonly ["prospect", "company", "workspace", "company_brain", "vertical", "offers", "persona", "playbook", "qualification", "signals", "history", "crm", "authorization"];
7
+ export type OutreachContextModule = typeof OUTREACH_CONTEXT_MODULES[number];
8
+ /** Only these modules are long lists the server pages; every other module is one answer. */
9
+ export declare const OUTREACH_CONTEXT_PAGED_MODULES: readonly ["signals", "history"];
10
+ export declare const OUTREACH_CONTEXT_TOOL_NAMES: readonly ["get_outreach_context_summary", "get_outreach_context_prospect", "get_outreach_context_company", "get_outreach_context_workspace", "get_outreach_context_company_brain", "get_outreach_context_vertical", "get_outreach_context_offers", "get_outreach_context_persona", "get_outreach_context_playbook", "get_outreach_context_qualification", "get_outreach_context_signals", "get_outreach_context_history", "get_outreach_context_crm", "get_outreach_context_authorization"];
11
+ export declare const OUTREACH_TOOL_NAMES: readonly ["list_outreach_programs", "get_outreach_program_context", "query_outreach_prospects", "get_outreach_prospect_summary", "get_outreach_contact_history", "get_outreach_prospect_context", "get_outreach_context_summary", "get_outreach_context_prospect", "get_outreach_context_company", "get_outreach_context_workspace", "get_outreach_context_company_brain", "get_outreach_context_vertical", "get_outreach_context_offers", "get_outreach_context_persona", "get_outreach_context_playbook", "get_outreach_context_qualification", "get_outreach_context_signals", "get_outreach_context_history", "get_outreach_context_crm", "get_outreach_context_authorization", "get_outreach_thread", "submit_outreach_messages", "list_outreach_messages", "get_outreach_message", "cancel_outreach_message", "list_outreach_events", "acknowledge_outreach_events", "get_outreach_reception_health", "list_outreach_conversations", "get_outreach_conversation"];
6
12
  export declare const OUTREACH_SERVER_CONTRACTS: {
7
13
  readonly program: "1.0.0";
8
14
  readonly selection: "1.0.0";
@@ -3,8 +3,17 @@ import { getClient } from "../client.js";
3
3
  import { LeadifyApiError, toolResult, toolError, handleToolError } from "../types.js";
4
4
  import { identifier, scope, querySchema, queryBody, submitSchema, decisionBody, acknowledgeSchema } from "./agent_outreach_schemas.js";
5
5
  export const OUTREACH_MCP_CONTRACT = "leadify-outreach-mcp.v1";
6
+ /** PRD-2632 : writing context read in pieces. Same order as the server's `readOrder`. */
7
+ export const OUTREACH_CONTEXT_MODULES = ["prospect", "company", "workspace", "company_brain", "vertical", "offers", "persona", "playbook",
8
+ "qualification", "signals", "history", "crm", "authorization"];
9
+ /** Only these modules are long lists the server pages; every other module is one answer. */
10
+ export const OUTREACH_CONTEXT_PAGED_MODULES = ["signals", "history"];
11
+ export const OUTREACH_CONTEXT_TOOL_NAMES = ["get_outreach_context_summary", "get_outreach_context_prospect", "get_outreach_context_company",
12
+ "get_outreach_context_workspace", "get_outreach_context_company_brain", "get_outreach_context_vertical", "get_outreach_context_offers",
13
+ "get_outreach_context_persona", "get_outreach_context_playbook", "get_outreach_context_qualification", "get_outreach_context_signals",
14
+ "get_outreach_context_history", "get_outreach_context_crm", "get_outreach_context_authorization"];
6
15
  export const OUTREACH_TOOL_NAMES = ["list_outreach_programs", "get_outreach_program_context", "query_outreach_prospects",
7
- "get_outreach_prospect_summary", "get_outreach_contact_history", "get_outreach_prospect_context", "get_outreach_thread",
16
+ "get_outreach_prospect_summary", "get_outreach_contact_history", "get_outreach_prospect_context", ...OUTREACH_CONTEXT_TOOL_NAMES, "get_outreach_thread",
8
17
  "submit_outreach_messages", "list_outreach_messages", "get_outreach_message", "cancel_outreach_message", "list_outreach_events",
9
18
  "acknowledge_outreach_events", "get_outreach_reception_health", "list_outreach_conversations", "get_outreach_conversation"];
10
19
  export const OUTREACH_SERVER_CONTRACTS = { program: "1.0.0", selection: "1.0.0", context: "agent-writing-context.v1", receipt: "agent-message-receipt.v1", journal: "1.0.0" };
@@ -52,11 +61,29 @@ export function projectOutreachMessage(data) {
52
61
  });
53
62
  return result;
54
63
  }
64
+ /** One line of JSON: the writing-context tools are read by a runtime that sets aside results above 50,000 characters. */
65
+ const compactResult = (data) => ({ content: [{ type: "text", text: JSON.stringify(data) }] });
66
+ const CONTEXT_MODULE_DESCRIPTION = {
67
+ prospect: "WHO the person is: identity, contact details, language, job title (the employer is in the company module).",
68
+ company: "Her EMPLOYER: the employer record and the qualified company cards (each with its document).",
69
+ workspace: "WHICH choices were made for this group: selected persona, vertical and offer, sender, call to action, plus workspace status and schema readiness. The long texts are in company_brain, vertical, offers, persona and playbook.",
70
+ company_brain: "The Company Brain of the organisation that prospects: who it is, positioning, vocabulary allowed or forbidden. Read it before writing a word.",
71
+ vertical: "The VERTICAL attached to the persona: target market and its content.",
72
+ offers: "The OFFER(S) retained for this group (three at most): what is sold and its limits.",
73
+ persona: "The PERSONA written to: who she is, her writing contract and description.",
74
+ playbook: "The published sales PLAYBOOK (GTM) of the organisation.",
75
+ qualification: "What is KNOWN about the person: qualification document, freshness, failures and any refresh requested. Read the company module for the company cards.",
76
+ signals: "WHY NOW: recent signals about the person and her company, newest first. Paged.",
77
+ history: "What was ALREADY SAID: messages exchanged with their text, known threads, the program's own messages, coverage. Newest first. Paged.",
78
+ crm: "CRM situation, exclusion and contact state: commercial status, reception, human takeover, thread-read readiness, last confirmed outbound and inbound. Check it before any first contact.",
79
+ authorization: "What is PERMITTED: program state, caps, senders and the key's rights, with the authorization revision to copy into the decision.",
80
+ };
55
81
  export function registerAgentOutreachTools(server, client = getClient()) {
56
- function register(name, description, schema, action, write = false) {
82
+ function register(name, description, schema, action, write = false, compact = false) {
57
83
  server.registerTool(name, { description: description + readNotice, inputSchema: schema,
58
84
  annotations: { readOnlyHint: !write && name !== "query_outreach_prospects", destructiveHint: false, idempotentHint: name !== "query_outreach_prospects", openWorldHint: true } }, (async (input) => { try {
59
- return toolResult(await action(schema.parse(input)));
85
+ const data = await action(schema.parse(input));
86
+ return compact ? compactResult(data) : toolResult(data);
60
87
  }
61
88
  catch (e) {
62
89
  return outreachError(e);
@@ -64,11 +91,28 @@ export function registerAgentOutreachTools(server, client = getClient()) {
64
91
  }
65
92
  register("list_outreach_programs", "List compact accessible autonomous outreach programs and the server contract version. Pagination: pass nextCursor unchanged as after_id.", z.object({ organization_id: identifier, after_id: identifier.optional(), limit: z.number().int().min(1).max(50).default(25) }).strict(), async (v) => requireOutreachVersion(await client.get("/api/agent-outreach/programs", params(v.organization_id, { afterId: v.after_id, limit: v.limit })), "1.0.0"));
66
93
  register("get_outreach_program_context", "Read one program's rules, authorization revision and permitted sender identities. Cannot authorize, resume, raise caps, grant rights or change senders.", z.object(scope).strict(), async (v) => requireOutreachVersion(await client.get(programPath(v.program_id), params(v.organization_id)), "1.0.0"));
67
- register("query_outreach_prospects", "Select canonical people server-side before pagination. Recipes: followup_due = seven days without pending/unknown/reply; channel_gap = LinkedIn messages >=2 and Gmail=0; replies_to_handle. For 72 hours set filters.last_confirmed_outbound_before.before to an explicit ISO timestamp. Signal filters support detection dates, levels and person/company scope. Keep cursor, filters and limit identical on continuation; selections expire after ten minutes. An incomplete history never proves no previous contact.", querySchema, async (v) => requireOutreachVersion(await client.post(postPath(`${programPath(v.program_id)}/prospects/query`, v.organization_id), queryBody(v)), "1.0.0"));
94
+ register("query_outreach_prospects", "Select canonical people server-side before pagination. Recipes: followup_due = seven days without pending/unknown/reply; channel_gap = LinkedIn messages >=2 and Gmail=0; replies_to_handle. For 72 hours set filters.last_confirmed_outbound_before.before to an explicit ISO timestamp. Signal filters support detection dates, levels and person/company scope. filters.qualified:true keeps the people whose qualification is finished; filters.qualification_levels (hot, warm, cold; 1 to 3 values) filters the temperature. Keep cursor, filters and limit identical on continuation; selections expire after ten minutes. An incomplete history never proves no previous contact.", querySchema, async (v) => requireOutreachVersion(await client.post(postPath(`${programPath(v.program_id)}/prospects/query`, v.organization_id), queryBody(v)), "1.0.0"));
68
95
  const personSchema = z.object({ ...scope, lead_id: identifier }).strict();
69
96
  register("get_outreach_prospect_summary", "Read a selected person's compact identity, contact counts and selection reasons. This is NOT the writing context: use get_outreach_prospect_context before drafting.", personSchema, v => client.get(`${programPath(v.program_id)}/prospects/${encoded(v.lead_id)}`, params(v.organization_id)));
70
97
  register("get_outreach_contact_history", "Read confirmed contact evidence for one person across accessible accounts, including pending, unknown and manual activity. Coverage limits remain explicit.", personSchema, v => client.get(`${programPath(v.program_id)}/contacts/${encoded(v.lead_id)}`, params(v.organization_id)));
71
- register("get_outreach_prospect_context", "Read fresh writing context, full-thread readiness, identity, qualification, signals, exclusion, authorizations and Context Workspace. Draft only when readiness.ready=true; WAIT requires resolving the stated reasons. Copy all versions, factsVersion, contextVersion and readAt into the current decision. Never starts qualification. A human takeover can only be resumed by a human in Leadify.", personSchema, async (v) => requireOutreachVersion(await client.get(`${programPath(v.program_id, true)}/people/${encoded(v.lead_id)}/context`, params(v.organization_id)), "agent-writing-context.v1"));
98
+ register("get_outreach_prospect_context", "LEGACY whole writing context, about 90 KB: runtimes that set aside tool results above 50,000 characters never see it. Agents must NOT call it: read get_outreach_context_summary, then the get_outreach_context_<module> tools. Kept for clients that can read very large results. Draft only when readiness.ready=true; WAIT requires resolving the stated reasons. Copy all versions, factsVersion, contextVersion and readAt into the current decision. Never starts qualification. A human takeover can only be resumed by a human in Leadify.", personSchema, async (v) => requireOutreachVersion(await client.get(`${programPath(v.program_id, true)}/people/${encoded(v.lead_id)}/context`, params(v.organization_id)), "agent-writing-context.v1"));
99
+ // PRD-2632 : the same context in pieces. Summary first, then one tool per module.
100
+ const contextPath = (v, tail) => `${programPath(v.program_id, true)}/people/${encoded(v.lead_id)}/context/${tail}`;
101
+ const expectKind = (data, kind, module) => {
102
+ const read = requireOutreachVersion(data, "agent-writing-context.v1");
103
+ if (object(read).responseKind !== kind || (module !== undefined && object(read).module !== module))
104
+ throw new LeadifyApiError(409, { code: "OUTREACH_CONTRACT_INCOMPATIBLE",
105
+ error: "Le serveur n'a pas rendu la lecture de contexte attendue. Vérifiez sa version avant de continuer.", expected: { responseKind: kind, module: module ?? null },
106
+ received: { responseKind: object(read).responseKind ?? null, module: object(read).module ?? null } });
107
+ return read;
108
+ };
109
+ register("get_outreach_context_summary", "START HERE to write for one person. Light read (about 7 KB): ids, readiness, the eight versions, contextVersion, factsVersion, the 13 modules in reading order (readOrder) with characters, pages and fingerprint, warnings, and decisionContext, the block to copy into the context of each deposited decision (modules included). Replaces get_outreach_prospect_context, whose 90 KB result is set aside by agent runtimes. Draft only when readiness.ready=true; otherwise WAIT with the stated reasons. Then read the modules, in readOrder, with get_outreach_context_<module>; each module answer carries its own version, which must equal modules[].version here, else the context moved: restart from this summary. Never starts qualification.", personSchema, async (v) => expectKind(await client.get(contextPath(v, "summary"), params(v.organization_id)), "summary"), false, true);
110
+ const pagedModules = new Set(OUTREACH_CONTEXT_PAGED_MODULES);
111
+ for (const module of OUTREACH_CONTEXT_MODULES) {
112
+ const paged = pagedModules.has(module);
113
+ const schema = paged ? z.object({ ...scope, lead_id: identifier, cursor: z.string().min(1).max(2000).optional().describe("page.nextCursor from the previous page, unchanged. Omit for the first page.") }).strict() : personSchema;
114
+ register(`get_outreach_context_${module}`, `Writing context, module ${module}: ${CONTEXT_MODULE_DESCRIPTION[module]} Read get_outreach_context_summary first. Answer: {module, version, readAt, data, page}; compact JSON, kept under about 25,000 characters per page. Compare version with the summary's modules[].version: if it differs, the context moved, restart from the summary.${paged ? " Pass page.nextCursor unchanged as cursor until it is null; the header comes with the first page only." : ""} Never starts qualification.`, schema, async (v) => expectKind(await client.get(contextPath(v, `modules/${module}`), params(v.organization_id, { cursor: v.cursor })), "module", module), false, true);
115
+ }
72
116
  register("get_outreach_thread", "Read one exact person's account/thread with complete bodies or explicit unavailable coverage. Pass nextCursor unchanged as cursor. An excerpt is not a complete conversation.", z.object({ ...scope, lead_id: identifier, account_key: z.string().min(1).max(1000), thread_id: identifier, cursor: z.string().min(1).max(8000).optional(), limit: z.number().int().min(1).max(100).default(50) }).strict(), v => client.get(`${programPath(v.program_id, true)}/people/${encoded(v.lead_id)}/thread`, params(v.organization_id, { accountKey: v.account_key, threadId: v.thread_id, cursor: v.cursor, limit: v.limit })));
73
117
  register("submit_outreach_messages", "Deposit 1–20 fresh decisions to Leadify for now, at most one message per channel per person/decision, never a sequence or scheduled steps. Preserve authored text exactly. A reply requires thread_id and expected_inbound_id. Use the SAME request_key and identical payload after interruption; a changed payload needs a new decision after rereading context. Inspect EVERY receipt: a successful call may contain ACCEPTED, WAIT and REFUSED decisions." + receiptNotice, submitSchema, async (v) => requireOutreachVersion(await client.post(postPath(`${programPath(v.program_id)}/messages/batch`, v.organization_id), { decisions: v.decisions.map(decisionBody) }), "agent-message-receipt.v1"), true);
74
118
  register("list_outreach_messages", "List this key's deposited messages and decision receipts, including after sender grant revocation. Pagination uses nextCursor as after_id." + receiptNotice, z.object({ ...scope, after_id: identifier.optional(), limit: z.number().int().min(1).max(50).default(25) }).strict(), async (v) => {
@@ -99,6 +99,8 @@ export declare const filters: z.ZodObject<{
99
99
  unknown: z.ZodOptional<z.ZodBoolean>;
100
100
  reply: z.ZodOptional<z.ZodEnum<["TO_HANDLE", "WAITING", "NONE"]>>;
101
101
  excluded: z.ZodOptional<z.ZodBoolean>;
102
+ qualified: z.ZodOptional<z.ZodBoolean>;
103
+ qualification_levels: z.ZodOptional<z.ZodArray<z.ZodEnum<["hot", "warm", "cold"]>, "many">>;
102
104
  }, "strict", z.ZodTypeAny, {
103
105
  group_id?: string | undefined;
104
106
  unknown?: boolean | undefined;
@@ -125,6 +127,8 @@ export declare const filters: z.ZodObject<{
125
127
  pending?: boolean | undefined;
126
128
  reply?: "TO_HANDLE" | "WAITING" | "NONE" | undefined;
127
129
  excluded?: boolean | undefined;
130
+ qualified?: boolean | undefined;
131
+ qualification_levels?: ("hot" | "warm" | "cold")[] | undefined;
128
132
  }, {
129
133
  group_id?: string | undefined;
130
134
  unknown?: boolean | undefined;
@@ -151,6 +155,51 @@ export declare const filters: z.ZodObject<{
151
155
  pending?: boolean | undefined;
152
156
  reply?: "TO_HANDLE" | "WAITING" | "NONE" | undefined;
153
157
  excluded?: boolean | undefined;
158
+ qualified?: boolean | undefined;
159
+ qualification_levels?: ("hot" | "warm" | "cold")[] | undefined;
160
+ }>;
161
+ export declare const contextModules: z.ZodObject<{
162
+ prospect: z.ZodString;
163
+ company: z.ZodString;
164
+ workspace: z.ZodString;
165
+ company_brain: z.ZodString;
166
+ vertical: z.ZodString;
167
+ offers: z.ZodString;
168
+ persona: z.ZodString;
169
+ playbook: z.ZodString;
170
+ qualification: z.ZodString;
171
+ signals: z.ZodString;
172
+ history: z.ZodString;
173
+ crm: z.ZodString;
174
+ authorization: z.ZodString;
175
+ }, "strict", z.ZodTypeAny, {
176
+ prospect: string;
177
+ company: string;
178
+ workspace: string;
179
+ company_brain: string;
180
+ vertical: string;
181
+ offers: string;
182
+ persona: string;
183
+ playbook: string;
184
+ qualification: string;
185
+ signals: string;
186
+ history: string;
187
+ crm: string;
188
+ authorization: string;
189
+ }, {
190
+ prospect: string;
191
+ company: string;
192
+ workspace: string;
193
+ company_brain: string;
194
+ vertical: string;
195
+ offers: string;
196
+ persona: string;
197
+ playbook: string;
198
+ qualification: string;
199
+ signals: string;
200
+ history: string;
201
+ crm: string;
202
+ authorization: string;
154
203
  }>;
155
204
  export declare const context: z.ZodObject<{
156
205
  contract_version: z.ZodLiteral<"agent-writing-context.v1">;
@@ -167,54 +216,127 @@ export declare const context: z.ZodObject<{
167
216
  authorization: z.ZodString;
168
217
  workspace: z.ZodString;
169
218
  }, "strict", z.ZodTypeAny, {
170
- identity: string;
219
+ workspace: string;
171
220
  qualification: string;
172
221
  signals: string;
222
+ authorization: string;
223
+ identity: string;
173
224
  conversation: string;
174
225
  contactState: string;
175
226
  exclusion: string;
176
- authorization: string;
177
- workspace: string;
178
227
  }, {
179
- identity: string;
228
+ workspace: string;
180
229
  qualification: string;
181
230
  signals: string;
231
+ authorization: string;
232
+ identity: string;
182
233
  conversation: string;
183
234
  contactState: string;
184
235
  exclusion: string;
236
+ }>;
237
+ modules: z.ZodOptional<z.ZodObject<{
238
+ prospect: z.ZodString;
239
+ company: z.ZodString;
240
+ workspace: z.ZodString;
241
+ company_brain: z.ZodString;
242
+ vertical: z.ZodString;
243
+ offers: z.ZodString;
244
+ persona: z.ZodString;
245
+ playbook: z.ZodString;
246
+ qualification: z.ZodString;
247
+ signals: z.ZodString;
248
+ history: z.ZodString;
249
+ crm: z.ZodString;
250
+ authorization: z.ZodString;
251
+ }, "strict", z.ZodTypeAny, {
252
+ prospect: string;
253
+ company: string;
254
+ workspace: string;
255
+ company_brain: string;
256
+ vertical: string;
257
+ offers: string;
258
+ persona: string;
259
+ playbook: string;
260
+ qualification: string;
261
+ signals: string;
262
+ history: string;
263
+ crm: string;
185
264
  authorization: string;
265
+ }, {
266
+ prospect: string;
267
+ company: string;
186
268
  workspace: string;
187
- }>;
269
+ company_brain: string;
270
+ vertical: string;
271
+ offers: string;
272
+ persona: string;
273
+ playbook: string;
274
+ qualification: string;
275
+ signals: string;
276
+ history: string;
277
+ crm: string;
278
+ authorization: string;
279
+ }>>;
188
280
  }, "strict", z.ZodTypeAny, {
189
281
  contract_version: "agent-writing-context.v1";
190
282
  context_version: string;
191
283
  facts_version: string;
192
284
  read_at: string;
193
285
  versions: {
194
- identity: string;
286
+ workspace: string;
195
287
  qualification: string;
196
288
  signals: string;
289
+ authorization: string;
290
+ identity: string;
197
291
  conversation: string;
198
292
  contactState: string;
199
293
  exclusion: string;
200
- authorization: string;
201
- workspace: string;
202
294
  };
295
+ modules?: {
296
+ prospect: string;
297
+ company: string;
298
+ workspace: string;
299
+ company_brain: string;
300
+ vertical: string;
301
+ offers: string;
302
+ persona: string;
303
+ playbook: string;
304
+ qualification: string;
305
+ signals: string;
306
+ history: string;
307
+ crm: string;
308
+ authorization: string;
309
+ } | undefined;
203
310
  }, {
204
311
  contract_version: "agent-writing-context.v1";
205
312
  context_version: string;
206
313
  facts_version: string;
207
314
  read_at: string;
208
315
  versions: {
209
- identity: string;
316
+ workspace: string;
210
317
  qualification: string;
211
318
  signals: string;
319
+ authorization: string;
320
+ identity: string;
212
321
  conversation: string;
213
322
  contactState: string;
214
323
  exclusion: string;
215
- authorization: string;
216
- workspace: string;
217
324
  };
325
+ modules?: {
326
+ prospect: string;
327
+ company: string;
328
+ workspace: string;
329
+ company_brain: string;
330
+ vertical: string;
331
+ offers: string;
332
+ persona: string;
333
+ playbook: string;
334
+ qualification: string;
335
+ signals: string;
336
+ history: string;
337
+ crm: string;
338
+ authorization: string;
339
+ } | undefined;
218
340
  }>;
219
341
  export declare const message: z.ZodEffects<z.ZodObject<{
220
342
  channel: z.ZodEnum<["GMAIL", "LINKEDIN"]>;
@@ -325,54 +447,127 @@ export declare const decision: z.ZodEffects<z.ZodObject<{
325
447
  authorization: z.ZodString;
326
448
  workspace: z.ZodString;
327
449
  }, "strict", z.ZodTypeAny, {
328
- identity: string;
450
+ workspace: string;
329
451
  qualification: string;
330
452
  signals: string;
453
+ authorization: string;
454
+ identity: string;
331
455
  conversation: string;
332
456
  contactState: string;
333
457
  exclusion: string;
334
- authorization: string;
335
- workspace: string;
336
458
  }, {
337
- identity: string;
459
+ workspace: string;
338
460
  qualification: string;
339
461
  signals: string;
462
+ authorization: string;
463
+ identity: string;
340
464
  conversation: string;
341
465
  contactState: string;
342
466
  exclusion: string;
467
+ }>;
468
+ modules: z.ZodOptional<z.ZodObject<{
469
+ prospect: z.ZodString;
470
+ company: z.ZodString;
471
+ workspace: z.ZodString;
472
+ company_brain: z.ZodString;
473
+ vertical: z.ZodString;
474
+ offers: z.ZodString;
475
+ persona: z.ZodString;
476
+ playbook: z.ZodString;
477
+ qualification: z.ZodString;
478
+ signals: z.ZodString;
479
+ history: z.ZodString;
480
+ crm: z.ZodString;
481
+ authorization: z.ZodString;
482
+ }, "strict", z.ZodTypeAny, {
483
+ prospect: string;
484
+ company: string;
485
+ workspace: string;
486
+ company_brain: string;
487
+ vertical: string;
488
+ offers: string;
489
+ persona: string;
490
+ playbook: string;
491
+ qualification: string;
492
+ signals: string;
493
+ history: string;
494
+ crm: string;
343
495
  authorization: string;
496
+ }, {
497
+ prospect: string;
498
+ company: string;
344
499
  workspace: string;
345
- }>;
500
+ company_brain: string;
501
+ vertical: string;
502
+ offers: string;
503
+ persona: string;
504
+ playbook: string;
505
+ qualification: string;
506
+ signals: string;
507
+ history: string;
508
+ crm: string;
509
+ authorization: string;
510
+ }>>;
346
511
  }, "strict", z.ZodTypeAny, {
347
512
  contract_version: "agent-writing-context.v1";
348
513
  context_version: string;
349
514
  facts_version: string;
350
515
  read_at: string;
351
516
  versions: {
352
- identity: string;
517
+ workspace: string;
353
518
  qualification: string;
354
519
  signals: string;
520
+ authorization: string;
521
+ identity: string;
355
522
  conversation: string;
356
523
  contactState: string;
357
524
  exclusion: string;
358
- authorization: string;
359
- workspace: string;
360
525
  };
526
+ modules?: {
527
+ prospect: string;
528
+ company: string;
529
+ workspace: string;
530
+ company_brain: string;
531
+ vertical: string;
532
+ offers: string;
533
+ persona: string;
534
+ playbook: string;
535
+ qualification: string;
536
+ signals: string;
537
+ history: string;
538
+ crm: string;
539
+ authorization: string;
540
+ } | undefined;
361
541
  }, {
362
542
  contract_version: "agent-writing-context.v1";
363
543
  context_version: string;
364
544
  facts_version: string;
365
545
  read_at: string;
366
546
  versions: {
367
- identity: string;
547
+ workspace: string;
368
548
  qualification: string;
369
549
  signals: string;
550
+ authorization: string;
551
+ identity: string;
370
552
  conversation: string;
371
553
  contactState: string;
372
554
  exclusion: string;
373
- authorization: string;
374
- workspace: string;
375
555
  };
556
+ modules?: {
557
+ prospect: string;
558
+ company: string;
559
+ workspace: string;
560
+ company_brain: string;
561
+ vertical: string;
562
+ offers: string;
563
+ persona: string;
564
+ playbook: string;
565
+ qualification: string;
566
+ signals: string;
567
+ history: string;
568
+ crm: string;
569
+ authorization: string;
570
+ } | undefined;
376
571
  }>;
377
572
  authorization_revision: z.ZodNumber;
378
573
  messages: z.ZodArray<z.ZodEffects<z.ZodObject<{
@@ -468,15 +663,30 @@ export declare const decision: z.ZodEffects<z.ZodObject<{
468
663
  facts_version: string;
469
664
  read_at: string;
470
665
  versions: {
471
- identity: string;
666
+ workspace: string;
472
667
  qualification: string;
473
668
  signals: string;
669
+ authorization: string;
670
+ identity: string;
474
671
  conversation: string;
475
672
  contactState: string;
476
673
  exclusion: string;
477
- authorization: string;
478
- workspace: string;
479
674
  };
675
+ modules?: {
676
+ prospect: string;
677
+ company: string;
678
+ workspace: string;
679
+ company_brain: string;
680
+ vertical: string;
681
+ offers: string;
682
+ persona: string;
683
+ playbook: string;
684
+ qualification: string;
685
+ signals: string;
686
+ history: string;
687
+ crm: string;
688
+ authorization: string;
689
+ } | undefined;
480
690
  };
481
691
  authorization_revision: number;
482
692
  messages: {
@@ -511,15 +721,30 @@ export declare const decision: z.ZodEffects<z.ZodObject<{
511
721
  facts_version: string;
512
722
  read_at: string;
513
723
  versions: {
514
- identity: string;
724
+ workspace: string;
515
725
  qualification: string;
516
726
  signals: string;
727
+ authorization: string;
728
+ identity: string;
517
729
  conversation: string;
518
730
  contactState: string;
519
731
  exclusion: string;
520
- authorization: string;
521
- workspace: string;
522
732
  };
733
+ modules?: {
734
+ prospect: string;
735
+ company: string;
736
+ workspace: string;
737
+ company_brain: string;
738
+ vertical: string;
739
+ offers: string;
740
+ persona: string;
741
+ playbook: string;
742
+ qualification: string;
743
+ signals: string;
744
+ history: string;
745
+ crm: string;
746
+ authorization: string;
747
+ } | undefined;
523
748
  };
524
749
  authorization_revision: number;
525
750
  messages: {
@@ -554,15 +779,30 @@ export declare const decision: z.ZodEffects<z.ZodObject<{
554
779
  facts_version: string;
555
780
  read_at: string;
556
781
  versions: {
557
- identity: string;
782
+ workspace: string;
558
783
  qualification: string;
559
784
  signals: string;
785
+ authorization: string;
786
+ identity: string;
560
787
  conversation: string;
561
788
  contactState: string;
562
789
  exclusion: string;
563
- authorization: string;
564
- workspace: string;
565
790
  };
791
+ modules?: {
792
+ prospect: string;
793
+ company: string;
794
+ workspace: string;
795
+ company_brain: string;
796
+ vertical: string;
797
+ offers: string;
798
+ persona: string;
799
+ playbook: string;
800
+ qualification: string;
801
+ signals: string;
802
+ history: string;
803
+ crm: string;
804
+ authorization: string;
805
+ } | undefined;
566
806
  };
567
807
  authorization_revision: number;
568
808
  messages: {
@@ -597,15 +837,30 @@ export declare const decision: z.ZodEffects<z.ZodObject<{
597
837
  facts_version: string;
598
838
  read_at: string;
599
839
  versions: {
600
- identity: string;
840
+ workspace: string;
601
841
  qualification: string;
602
842
  signals: string;
843
+ authorization: string;
844
+ identity: string;
603
845
  conversation: string;
604
846
  contactState: string;
605
847
  exclusion: string;
606
- authorization: string;
607
- workspace: string;
608
848
  };
849
+ modules?: {
850
+ prospect: string;
851
+ company: string;
852
+ workspace: string;
853
+ company_brain: string;
854
+ vertical: string;
855
+ offers: string;
856
+ persona: string;
857
+ playbook: string;
858
+ qualification: string;
859
+ signals: string;
860
+ history: string;
861
+ crm: string;
862
+ authorization: string;
863
+ } | undefined;
609
864
  };
610
865
  authorization_revision: number;
611
866
  messages: {
@@ -721,6 +976,8 @@ export declare const querySchema: z.ZodObject<{
721
976
  unknown: z.ZodOptional<z.ZodBoolean>;
722
977
  reply: z.ZodOptional<z.ZodEnum<["TO_HANDLE", "WAITING", "NONE"]>>;
723
978
  excluded: z.ZodOptional<z.ZodBoolean>;
979
+ qualified: z.ZodOptional<z.ZodBoolean>;
980
+ qualification_levels: z.ZodOptional<z.ZodArray<z.ZodEnum<["hot", "warm", "cold"]>, "many">>;
724
981
  }, "strict", z.ZodTypeAny, {
725
982
  group_id?: string | undefined;
726
983
  unknown?: boolean | undefined;
@@ -747,6 +1004,8 @@ export declare const querySchema: z.ZodObject<{
747
1004
  pending?: boolean | undefined;
748
1005
  reply?: "TO_HANDLE" | "WAITING" | "NONE" | undefined;
749
1006
  excluded?: boolean | undefined;
1007
+ qualified?: boolean | undefined;
1008
+ qualification_levels?: ("hot" | "warm" | "cold")[] | undefined;
750
1009
  }, {
751
1010
  group_id?: string | undefined;
752
1011
  unknown?: boolean | undefined;
@@ -773,6 +1032,8 @@ export declare const querySchema: z.ZodObject<{
773
1032
  pending?: boolean | undefined;
774
1033
  reply?: "TO_HANDLE" | "WAITING" | "NONE" | undefined;
775
1034
  excluded?: boolean | undefined;
1035
+ qualified?: boolean | undefined;
1036
+ qualification_levels?: ("hot" | "warm" | "cold")[] | undefined;
776
1037
  }>>;
777
1038
  limit: z.ZodDefault<z.ZodNumber>;
778
1039
  cursor: z.ZodOptional<z.ZodString>;
@@ -805,6 +1066,8 @@ export declare const querySchema: z.ZodObject<{
805
1066
  pending?: boolean | undefined;
806
1067
  reply?: "TO_HANDLE" | "WAITING" | "NONE" | undefined;
807
1068
  excluded?: boolean | undefined;
1069
+ qualified?: boolean | undefined;
1070
+ qualification_levels?: ("hot" | "warm" | "cold")[] | undefined;
808
1071
  };
809
1072
  limit: number;
810
1073
  organization_id: string;
@@ -841,6 +1104,8 @@ export declare const querySchema: z.ZodObject<{
841
1104
  pending?: boolean | undefined;
842
1105
  reply?: "TO_HANDLE" | "WAITING" | "NONE" | undefined;
843
1106
  excluded?: boolean | undefined;
1107
+ qualified?: boolean | undefined;
1108
+ qualification_levels?: ("hot" | "warm" | "cold")[] | undefined;
844
1109
  } | undefined;
845
1110
  limit?: number | undefined;
846
1111
  cursor?: string | undefined;
@@ -878,54 +1143,127 @@ export declare const submitSchema: z.ZodObject<{
878
1143
  authorization: z.ZodString;
879
1144
  workspace: z.ZodString;
880
1145
  }, "strict", z.ZodTypeAny, {
881
- identity: string;
1146
+ workspace: string;
882
1147
  qualification: string;
883
1148
  signals: string;
1149
+ authorization: string;
1150
+ identity: string;
884
1151
  conversation: string;
885
1152
  contactState: string;
886
1153
  exclusion: string;
887
- authorization: string;
888
- workspace: string;
889
1154
  }, {
890
- identity: string;
1155
+ workspace: string;
891
1156
  qualification: string;
892
1157
  signals: string;
1158
+ authorization: string;
1159
+ identity: string;
893
1160
  conversation: string;
894
1161
  contactState: string;
895
1162
  exclusion: string;
1163
+ }>;
1164
+ modules: z.ZodOptional<z.ZodObject<{
1165
+ prospect: z.ZodString;
1166
+ company: z.ZodString;
1167
+ workspace: z.ZodString;
1168
+ company_brain: z.ZodString;
1169
+ vertical: z.ZodString;
1170
+ offers: z.ZodString;
1171
+ persona: z.ZodString;
1172
+ playbook: z.ZodString;
1173
+ qualification: z.ZodString;
1174
+ signals: z.ZodString;
1175
+ history: z.ZodString;
1176
+ crm: z.ZodString;
1177
+ authorization: z.ZodString;
1178
+ }, "strict", z.ZodTypeAny, {
1179
+ prospect: string;
1180
+ company: string;
1181
+ workspace: string;
1182
+ company_brain: string;
1183
+ vertical: string;
1184
+ offers: string;
1185
+ persona: string;
1186
+ playbook: string;
1187
+ qualification: string;
1188
+ signals: string;
1189
+ history: string;
1190
+ crm: string;
896
1191
  authorization: string;
1192
+ }, {
1193
+ prospect: string;
1194
+ company: string;
897
1195
  workspace: string;
898
- }>;
1196
+ company_brain: string;
1197
+ vertical: string;
1198
+ offers: string;
1199
+ persona: string;
1200
+ playbook: string;
1201
+ qualification: string;
1202
+ signals: string;
1203
+ history: string;
1204
+ crm: string;
1205
+ authorization: string;
1206
+ }>>;
899
1207
  }, "strict", z.ZodTypeAny, {
900
1208
  contract_version: "agent-writing-context.v1";
901
1209
  context_version: string;
902
1210
  facts_version: string;
903
1211
  read_at: string;
904
1212
  versions: {
905
- identity: string;
1213
+ workspace: string;
906
1214
  qualification: string;
907
1215
  signals: string;
1216
+ authorization: string;
1217
+ identity: string;
908
1218
  conversation: string;
909
1219
  contactState: string;
910
1220
  exclusion: string;
911
- authorization: string;
912
- workspace: string;
913
1221
  };
1222
+ modules?: {
1223
+ prospect: string;
1224
+ company: string;
1225
+ workspace: string;
1226
+ company_brain: string;
1227
+ vertical: string;
1228
+ offers: string;
1229
+ persona: string;
1230
+ playbook: string;
1231
+ qualification: string;
1232
+ signals: string;
1233
+ history: string;
1234
+ crm: string;
1235
+ authorization: string;
1236
+ } | undefined;
914
1237
  }, {
915
1238
  contract_version: "agent-writing-context.v1";
916
1239
  context_version: string;
917
1240
  facts_version: string;
918
1241
  read_at: string;
919
1242
  versions: {
920
- identity: string;
1243
+ workspace: string;
921
1244
  qualification: string;
922
1245
  signals: string;
1246
+ authorization: string;
1247
+ identity: string;
923
1248
  conversation: string;
924
1249
  contactState: string;
925
1250
  exclusion: string;
926
- authorization: string;
927
- workspace: string;
928
1251
  };
1252
+ modules?: {
1253
+ prospect: string;
1254
+ company: string;
1255
+ workspace: string;
1256
+ company_brain: string;
1257
+ vertical: string;
1258
+ offers: string;
1259
+ persona: string;
1260
+ playbook: string;
1261
+ qualification: string;
1262
+ signals: string;
1263
+ history: string;
1264
+ crm: string;
1265
+ authorization: string;
1266
+ } | undefined;
929
1267
  }>;
930
1268
  authorization_revision: z.ZodNumber;
931
1269
  messages: z.ZodArray<z.ZodEffects<z.ZodObject<{
@@ -1021,15 +1359,30 @@ export declare const submitSchema: z.ZodObject<{
1021
1359
  facts_version: string;
1022
1360
  read_at: string;
1023
1361
  versions: {
1024
- identity: string;
1362
+ workspace: string;
1025
1363
  qualification: string;
1026
1364
  signals: string;
1365
+ authorization: string;
1366
+ identity: string;
1027
1367
  conversation: string;
1028
1368
  contactState: string;
1029
1369
  exclusion: string;
1030
- authorization: string;
1031
- workspace: string;
1032
1370
  };
1371
+ modules?: {
1372
+ prospect: string;
1373
+ company: string;
1374
+ workspace: string;
1375
+ company_brain: string;
1376
+ vertical: string;
1377
+ offers: string;
1378
+ persona: string;
1379
+ playbook: string;
1380
+ qualification: string;
1381
+ signals: string;
1382
+ history: string;
1383
+ crm: string;
1384
+ authorization: string;
1385
+ } | undefined;
1033
1386
  };
1034
1387
  authorization_revision: number;
1035
1388
  messages: {
@@ -1064,15 +1417,30 @@ export declare const submitSchema: z.ZodObject<{
1064
1417
  facts_version: string;
1065
1418
  read_at: string;
1066
1419
  versions: {
1067
- identity: string;
1420
+ workspace: string;
1068
1421
  qualification: string;
1069
1422
  signals: string;
1423
+ authorization: string;
1424
+ identity: string;
1070
1425
  conversation: string;
1071
1426
  contactState: string;
1072
1427
  exclusion: string;
1073
- authorization: string;
1074
- workspace: string;
1075
1428
  };
1429
+ modules?: {
1430
+ prospect: string;
1431
+ company: string;
1432
+ workspace: string;
1433
+ company_brain: string;
1434
+ vertical: string;
1435
+ offers: string;
1436
+ persona: string;
1437
+ playbook: string;
1438
+ qualification: string;
1439
+ signals: string;
1440
+ history: string;
1441
+ crm: string;
1442
+ authorization: string;
1443
+ } | undefined;
1076
1444
  };
1077
1445
  authorization_revision: number;
1078
1446
  messages: {
@@ -1107,15 +1475,30 @@ export declare const submitSchema: z.ZodObject<{
1107
1475
  facts_version: string;
1108
1476
  read_at: string;
1109
1477
  versions: {
1110
- identity: string;
1478
+ workspace: string;
1111
1479
  qualification: string;
1112
1480
  signals: string;
1481
+ authorization: string;
1482
+ identity: string;
1113
1483
  conversation: string;
1114
1484
  contactState: string;
1115
1485
  exclusion: string;
1116
- authorization: string;
1117
- workspace: string;
1118
1486
  };
1487
+ modules?: {
1488
+ prospect: string;
1489
+ company: string;
1490
+ workspace: string;
1491
+ company_brain: string;
1492
+ vertical: string;
1493
+ offers: string;
1494
+ persona: string;
1495
+ playbook: string;
1496
+ qualification: string;
1497
+ signals: string;
1498
+ history: string;
1499
+ crm: string;
1500
+ authorization: string;
1501
+ } | undefined;
1119
1502
  };
1120
1503
  authorization_revision: number;
1121
1504
  messages: {
@@ -1150,15 +1533,30 @@ export declare const submitSchema: z.ZodObject<{
1150
1533
  facts_version: string;
1151
1534
  read_at: string;
1152
1535
  versions: {
1153
- identity: string;
1536
+ workspace: string;
1154
1537
  qualification: string;
1155
1538
  signals: string;
1539
+ authorization: string;
1540
+ identity: string;
1156
1541
  conversation: string;
1157
1542
  contactState: string;
1158
1543
  exclusion: string;
1159
- authorization: string;
1160
- workspace: string;
1161
1544
  };
1545
+ modules?: {
1546
+ prospect: string;
1547
+ company: string;
1548
+ workspace: string;
1549
+ company_brain: string;
1550
+ vertical: string;
1551
+ offers: string;
1552
+ persona: string;
1553
+ playbook: string;
1554
+ qualification: string;
1555
+ signals: string;
1556
+ history: string;
1557
+ crm: string;
1558
+ authorization: string;
1559
+ } | undefined;
1162
1560
  };
1163
1561
  authorization_revision: number;
1164
1562
  messages: {
@@ -1199,15 +1597,30 @@ export declare const submitSchema: z.ZodObject<{
1199
1597
  facts_version: string;
1200
1598
  read_at: string;
1201
1599
  versions: {
1202
- identity: string;
1600
+ workspace: string;
1203
1601
  qualification: string;
1204
1602
  signals: string;
1603
+ authorization: string;
1604
+ identity: string;
1205
1605
  conversation: string;
1206
1606
  contactState: string;
1207
1607
  exclusion: string;
1208
- authorization: string;
1209
- workspace: string;
1210
1608
  };
1609
+ modules?: {
1610
+ prospect: string;
1611
+ company: string;
1612
+ workspace: string;
1613
+ company_brain: string;
1614
+ vertical: string;
1615
+ offers: string;
1616
+ persona: string;
1617
+ playbook: string;
1618
+ qualification: string;
1619
+ signals: string;
1620
+ history: string;
1621
+ crm: string;
1622
+ authorization: string;
1623
+ } | undefined;
1211
1624
  };
1212
1625
  authorization_revision: number;
1213
1626
  messages: {
@@ -1246,15 +1659,30 @@ export declare const submitSchema: z.ZodObject<{
1246
1659
  facts_version: string;
1247
1660
  read_at: string;
1248
1661
  versions: {
1249
- identity: string;
1662
+ workspace: string;
1250
1663
  qualification: string;
1251
1664
  signals: string;
1665
+ authorization: string;
1666
+ identity: string;
1252
1667
  conversation: string;
1253
1668
  contactState: string;
1254
1669
  exclusion: string;
1255
- authorization: string;
1256
- workspace: string;
1257
1670
  };
1671
+ modules?: {
1672
+ prospect: string;
1673
+ company: string;
1674
+ workspace: string;
1675
+ company_brain: string;
1676
+ vertical: string;
1677
+ offers: string;
1678
+ persona: string;
1679
+ playbook: string;
1680
+ qualification: string;
1681
+ signals: string;
1682
+ history: string;
1683
+ crm: string;
1684
+ authorization: string;
1685
+ } | undefined;
1258
1686
  };
1259
1687
  authorization_revision: number;
1260
1688
  messages: {
@@ -1349,6 +1777,8 @@ export declare function queryBody(v: z.infer<typeof querySchema>): {
1349
1777
  unknown: boolean | undefined;
1350
1778
  reply: "TO_HANDLE" | "WAITING" | "NONE" | undefined;
1351
1779
  excluded: boolean | undefined;
1780
+ qualified: boolean | undefined;
1781
+ qualificationLevels: ("hot" | "warm" | "cold")[] | undefined;
1352
1782
  };
1353
1783
  };
1354
1784
  export declare function decisionBody(d: z.infer<typeof decision>): {
@@ -1362,19 +1792,34 @@ export declare function decisionBody(d: z.infer<typeof decision>): {
1362
1792
  url: string;
1363
1793
  }[];
1364
1794
  context: {
1795
+ modules?: {
1796
+ prospect: string;
1797
+ company: string;
1798
+ workspace: string;
1799
+ company_brain: string;
1800
+ vertical: string;
1801
+ offers: string;
1802
+ persona: string;
1803
+ playbook: string;
1804
+ qualification: string;
1805
+ signals: string;
1806
+ history: string;
1807
+ crm: string;
1808
+ authorization: string;
1809
+ } | undefined;
1365
1810
  contractVersion: "agent-writing-context.v1";
1366
1811
  contextVersion: string;
1367
1812
  factsVersion: string;
1368
1813
  readAt: string;
1369
1814
  versions: {
1370
- identity: string;
1815
+ workspace: string;
1371
1816
  qualification: string;
1372
1817
  signals: string;
1818
+ authorization: string;
1819
+ identity: string;
1373
1820
  conversation: string;
1374
1821
  contactState: string;
1375
1822
  exclusion: string;
1376
- authorization: string;
1377
- workspace: string;
1378
1823
  };
1379
1824
  };
1380
1825
  authorizationRevision: number;
@@ -21,12 +21,19 @@ export const filters = z.object({
21
21
  last_confirmed_outbound_before: z.object({ channel: z.enum(["any", "GMAIL", "LINKEDIN"]), before: date }).strict().optional(),
22
22
  counts: z.array(count).max(6).optional(), never_on: z.array(target).max(3).optional(),
23
23
  pending: z.boolean().optional(), unknown: z.boolean().optional(), reply: z.enum(["TO_HANDLE", "WAITING", "NONE"]).optional(), excluded: z.boolean().optional(),
24
+ // PRD-2650 (server: PRD-2649): qualification finished, and its temperature.
25
+ qualified: z.boolean().optional(), qualification_levels: z.array(z.enum(["hot", "warm", "cold"])).min(1).max(3).optional(),
24
26
  }).strict();
27
+ // PRD-2632 : one fingerprint per module, copied from get_outreach_context_summary.decisionContext.modules.
28
+ export const contextModules = z.object({ prospect: version, company: version, workspace: version, company_brain: version, vertical: version, offers: version,
29
+ persona: version, playbook: version, qualification: version, signals: version, history: version, crm: version, authorization: version }).strict();
25
30
  export const context = z.object({
26
31
  contract_version: z.literal("agent-writing-context.v1"), context_version: version, facts_version: version, read_at: date,
27
32
  versions: z.object({ identity: version, qualification: version, signals: version, conversation: version,
28
33
  contactState: version, exclusion: version, authorization: version, workspace: version }).strict()
29
- .describe("Copy the versions object from get_outreach_prospect_context unchanged, including contactState."),
34
+ .describe("Copy the versions object from get_outreach_context_summary (or get_outreach_prospect_context) unchanged, including contactState."),
35
+ modules: contextModules.optional()
36
+ .describe("Copy decisionContext.modules from get_outreach_context_summary unchanged, all 13 fingerprints. Always send it when you wrote from modules: Leadify then refuses the decision, naming the modules, if one changed after you read it."),
30
37
  }).strict();
31
38
  export const message = z.object({
32
39
  channel, action: z.enum(["MESSAGE", "INVITATION"]), sender_id: identifier, account_key: z.string().min(1).max(1000),
@@ -84,12 +91,13 @@ export function queryBody(v) {
84
91
  groupId: f.group_id, signalFilter: f.signal_filter && { detectedSince: f.signal_filter.detected_since, detectedBefore: f.signal_filter.detected_before, levels: f.signal_filter.levels, scope: f.signal_filter.scope },
85
92
  lastConfirmedOutboundBefore: f.last_confirmed_outbound_before, counts: f.counts, neverOn: f.never_on,
86
93
  pending: f.pending, unknown: f.unknown, reply: f.reply, excluded: f.excluded,
94
+ qualified: f.qualified, qualificationLevels: f.qualification_levels,
87
95
  } };
88
96
  }
89
97
  export function decisionBody(d) {
90
98
  return { ...(d.agent_cycle_id !== undefined ? { agentCycleId: d.agent_cycle_id } : {}), requestKey: d.request_key, leadId: d.lead_id, personId: d.person_id, purpose: d.purpose, reason: d.reason, sources: d.sources,
91
99
  context: { contractVersion: d.context.contract_version, contextVersion: d.context.context_version, factsVersion: d.context.facts_version,
92
- readAt: d.context.read_at, versions: d.context.versions }, authorizationRevision: d.authorization_revision,
100
+ readAt: d.context.read_at, versions: d.context.versions, ...(d.context.modules ? { modules: d.context.modules } : {}) }, authorizationRevision: d.authorization_revision,
93
101
  messages: d.messages.map(m => ({ channel: m.channel, action: m.action, senderId: m.sender_id, accountKey: m.account_key,
94
102
  recipient: m.recipient, subject: m.subject, body: m.body, threadId: m.thread_id, expectedInboundId: m.expected_inbound_id, technicalParts: m.technical_parts })) };
95
103
  }
@@ -1,4 +1,4 @@
1
- import { OUTREACH_MCP_CONTRACT, OUTREACH_SERVER_CONTRACTS, OUTREACH_TOOL_NAMES, requireOutreachVersion, outreachError } from "./agent_outreach.js";
1
+ import { OUTREACH_MCP_CONTRACT, OUTREACH_SERVER_CONTRACTS, OUTREACH_TOOL_NAMES, OUTREACH_CONTEXT_MODULES, requireOutreachVersion, outreachError } from "./agent_outreach.js";
2
2
  import { getClient } from "../client.js";
3
3
  import { toolResult, handleToolError } from "../types.js";
4
4
  import { z } from "zod";
@@ -13,7 +13,7 @@ export function projectMcpRuntimeInfo(data, organizationId) {
13
13
  version: MCP_VERSION,
14
14
  organization: organization ? { id: organization.id, name: organization.name ?? null, slug: organization.slug ?? null } : null,
15
15
  organizationAccessible: Boolean(organization),
16
- outreach: { contract: OUTREACH_MCP_CONTRACT, tools: OUTREACH_TOOL_NAMES, expectedServerContracts: OUTREACH_SERVER_CONTRACTS, serverCompatibility: "NOT_CHECKED", administrativeAuthority: false },
16
+ outreach: { contract: OUTREACH_MCP_CONTRACT, tools: OUTREACH_TOOL_NAMES, contextModules: OUTREACH_CONTEXT_MODULES, expectedServerContracts: OUTREACH_SERVER_CONTRACTS, serverCompatibility: "NOT_CHECKED", administrativeAuthority: false },
17
17
  readOnly: true,
18
18
  writes: 0,
19
19
  sends: 0,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agifyai/leadify-mcp",
3
- "version": "9.7.2",
3
+ "version": "9.9.0",
4
4
  "description": "MCP server for Leadify lead management API",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",