@agifyai/leadify-mcp 9.7.1 → 9.8.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 |
@@ -587,10 +590,55 @@ droits est refusé ; aucun redémarrage caché n'a lieu. Programmes, messages et
587
590
  conversations utilisent `after_id` pour leur page suivante. Les événements et les
588
591
  fils utilisent `cursor`. Les curseurs sont opaques et ne doivent pas être inventés.
589
592
 
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.
593
+ `get_outreach_prospect_summary` est un résumé de la sélection, pas le contexte de
594
+ rédaction. Avant d'écrire, lire `get_outreach_context_summary`, vérifier
595
+ `readiness.ready`, puis chaque module dans l'ordre de `readOrder`, puis les fils
596
+ exacts nécessaires avec `get_outreach_thread`. Un corps indisponible ou un simple
597
+ extrait ne vaut pas une conversation complète. Le contexte n'effectue aucune
598
+ qualification.
599
+
600
+ #### Contexte de rédaction par modules (PRD-2632)
601
+
602
+ La lecture entière `get_outreach_prospect_context` pèse près de 90 Ko. Un agent dont
603
+ l'exécution écarte tout résultat d'outil de plus de 50 000 caractères (Hermès) ne la
604
+ voit jamais. Elle est conservée mais déconseillée : lire le sommaire, puis un module
605
+ à la fois. Toutes ces réponses sont en JSON compact, sur une seule ligne.
606
+
607
+ `get_outreach_context_summary` rend, en quelques Ko : les identifiants, `readiness`,
608
+ les huit `versions`, `contextVersion`, `factsVersion`, `readAt`, `readOrder`, la liste
609
+ des treize modules (`module`, `version` = empreinte, `characters`, `pages`, `purpose`),
610
+ les `warnings` (module trop grand, historique incomplet) et `decisionContext`, le bloc
611
+ à recopier dans le `context` de chaque décision déposée.
612
+
613
+ Les treize outils `get_outreach_context_<module>`, dans l'ordre de lecture utile :
614
+
615
+ | Module | Contenu | Pages |
616
+ |---|---|---|
617
+ | `prospect` | identité, coordonnées, langue, poste | 1 |
618
+ | `company` | employeur et fiches entreprise qualifiées | 1 |
619
+ | `workspace` | choix du groupe : persona, verticale, offre, expéditeur, appel à l'action | 1 |
620
+ | `company_brain` | Company Brain de l'organisation qui prospecte | 1 |
621
+ | `vertical` | verticale du persona | 1 |
622
+ | `offers` | offre retenue (trois au plus) | 1 |
623
+ | `persona` | persona et son contrat de rédaction | 1 |
624
+ | `playbook` | playbook commercial publié | 1 |
625
+ | `qualification` | fiche de qualification de la personne | 1 |
626
+ | `signals` | signaux récents, le plus récent d'abord | curseur |
627
+ | `history` | messages échangés avec leur texte, fils connus | curseur |
628
+ | `crm` | statut CRM, exclusion, réception, prise en main humaine | 1 |
629
+ | `authorization` | état du programme, plafonds, expéditeurs, droits | 1 |
630
+
631
+ Chaque réponse contient `module`, `version` (l'empreinte du module), `readAt`, `data`
632
+ et `page` (null, ou `nextCursor` à repasser tel quel dans `cursor`). Un module paginé
633
+ rend son en-tête avec la première page seulement ; une page tient sous environ
634
+ 25 000 caractères. Si `version` diffère de celle du sommaire, le contexte a changé
635
+ entre deux lectures : repartir du sommaire. Un curseur lié à une empreinte périmée est
636
+ refusé (`VERSION_CONFLICT`).
637
+
638
+ Au dépôt, `context.modules` reprend `decisionContext.modules` à l'identique (les treize
639
+ empreintes). Il est facultatif pour les anciens clients et strict quand il est présent.
640
+ Les huit `versions` restent obligatoires. Si une empreinte a bougé depuis la lecture,
641
+ Leadify refuse avec `CONTEXT_STALE` et nomme les modules (`CONTEXT_MODULE_CHANGED:<module>`).
594
642
 
595
643
  ### Dépôt et reprise
596
644
 
@@ -601,7 +649,9 @@ et `messages` (1 à 2, un par canal).
601
649
 
602
650
  Le contexte transmis comporte `contract_version: "agent-writing-context.v1"`,
603
651
  `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
652
+ serveur. Les clés de cet objet restent inchangées, dont `contactState`. Quand la
653
+ rédaction vient du contexte par modules, `modules` (les treize empreintes de
654
+ `decisionContext.modules`) l'accompagne. Un message
605
655
  contient `channel`, `action`, `sender_id`, `account_key`, `recipient`, `subject`,
606
656
  `body`, `thread_id`, `expected_inbound_id`, `technical_parts` (signature et
607
657
  unsubscribe). Les champs nullables doivent être présents. Une réponse désigne
@@ -643,3 +693,14 @@ avec l'application, ses écritures enregistrées et sa vérification visuelle.
643
693
  La publication suit `publish.yml` après fusion : registre npm, archive de version
644
694
  explicite et découverte dans un processus neuf doivent être vérifiés séparément.
645
695
  Une conversation Louise déjà ouverte peut conserver un ancien catalogue.
696
+
697
+ La décision accepte aussi `agent_cycle_id`, facultatif : transmettre uniquement
698
+ l’identifiant réel du cycle courant (1 à 200 caractères, sans espaces ni caractères
699
+ de contrôle). Il devient `agentCycleId` côté serveur ; absent, il reste absent.
700
+ Les lectures des messages conservent `decision.agentCycleId` et, dans chaque
701
+ tentative, `triggerRunId`, `reconciliationRunId` et `reconciliationErrorCode`.
702
+ Une valeur absente ou nulle ne prouve aucune exécution ; ces références ne
703
+ changent pas l’état du message et n’exposent pas l’enveloppe fournisseur brute.
704
+
705
+ Pour un signal daté, `signal_upsert.date_evidence` fournit le passage source qui
706
+ établit `date`. Le serveur conserve cette preuve ; une date sans preuve est refusée.
@@ -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" };
@@ -40,10 +49,10 @@ export function projectOutreachMessage(data) {
40
49
  const m = object(data);
41
50
  const result = pick(m, ["id", "organizationId", "programId", "decisionId", "senderId", "conversationId", "channel", "action", "recipient", "subject", "body", "expectedInboundId", "providerThreadId", "accountKey", "technicalParts", "state", "revision", "reasonCode", "expiresAt", "notBefore", "sentAt", "providerMessageId", "createdAt", "updatedAt"]);
42
51
  if (m.decision)
43
- result.decision = pick(m.decision, ["id", "personId", "leadId", "requestKey", "purpose", "reason", "sources", "contextVersion", "authorizationRevision", "contextReadAt", "receipt", "createdAt"]);
52
+ result.decision = pick(m.decision, ["id", "agentCycleId", "personId", "leadId", "requestKey", "purpose", "reason", "sources", "contextVersion", "authorizationRevision", "contextReadAt", "receipt", "createdAt"]);
44
53
  if (Array.isArray(m.attempts))
45
54
  result.attempts = m.attempts.map(a => {
46
- const attempt = pick(a, ["id", "ordinal", "startedAt", "providerBarrierAt", "finishedAt", "outcome", "providerMessageId", "errorCode", "lastReconciledAt", "reconciliationResult"]);
55
+ const attempt = pick(a, ["id", "ordinal", "startedAt", "providerBarrierAt", "finishedAt", "outcome", "providerMessageId", "errorCode", "lastReconciledAt", "reconciliationResult", "triggerRunId", "reconciliationRunId", "reconciliationErrorCode"]);
47
56
  const receipt = object(object(object(a).providerRequest).receipt);
48
57
  const safeReceipt = Object.fromEntries([["providerMessageId", receipt.id], ["providerThreadId", receipt.threadId]].filter(([, value]) => typeof value === "string"));
49
58
  if (Object.keys(safeReceipt).length)
@@ -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);
@@ -68,7 +95,24 @@ export function registerAgentOutreachTools(server, client = getClient()) {
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) => {
@@ -152,6 +152,49 @@ export declare const filters: z.ZodObject<{
152
152
  reply?: "TO_HANDLE" | "WAITING" | "NONE" | undefined;
153
153
  excluded?: boolean | undefined;
154
154
  }>;
155
+ export declare const contextModules: z.ZodObject<{
156
+ prospect: z.ZodString;
157
+ company: z.ZodString;
158
+ workspace: z.ZodString;
159
+ company_brain: z.ZodString;
160
+ vertical: z.ZodString;
161
+ offers: z.ZodString;
162
+ persona: z.ZodString;
163
+ playbook: z.ZodString;
164
+ qualification: z.ZodString;
165
+ signals: z.ZodString;
166
+ history: z.ZodString;
167
+ crm: z.ZodString;
168
+ authorization: z.ZodString;
169
+ }, "strict", z.ZodTypeAny, {
170
+ prospect: string;
171
+ company: string;
172
+ workspace: string;
173
+ company_brain: string;
174
+ vertical: string;
175
+ offers: string;
176
+ persona: string;
177
+ playbook: string;
178
+ qualification: string;
179
+ signals: string;
180
+ history: string;
181
+ crm: string;
182
+ authorization: string;
183
+ }, {
184
+ prospect: string;
185
+ company: string;
186
+ workspace: string;
187
+ company_brain: string;
188
+ vertical: string;
189
+ offers: string;
190
+ persona: string;
191
+ playbook: string;
192
+ qualification: string;
193
+ signals: string;
194
+ history: string;
195
+ crm: string;
196
+ authorization: string;
197
+ }>;
155
198
  export declare const context: z.ZodObject<{
156
199
  contract_version: z.ZodLiteral<"agent-writing-context.v1">;
157
200
  context_version: z.ZodString;
@@ -167,54 +210,127 @@ export declare const context: z.ZodObject<{
167
210
  authorization: z.ZodString;
168
211
  workspace: z.ZodString;
169
212
  }, "strict", z.ZodTypeAny, {
170
- identity: string;
213
+ workspace: string;
171
214
  qualification: string;
172
215
  signals: string;
216
+ authorization: string;
217
+ identity: string;
173
218
  conversation: string;
174
219
  contactState: string;
175
220
  exclusion: string;
176
- authorization: string;
177
- workspace: string;
178
221
  }, {
179
- identity: string;
222
+ workspace: string;
180
223
  qualification: string;
181
224
  signals: string;
225
+ authorization: string;
226
+ identity: string;
182
227
  conversation: string;
183
228
  contactState: string;
184
229
  exclusion: string;
230
+ }>;
231
+ modules: z.ZodOptional<z.ZodObject<{
232
+ prospect: z.ZodString;
233
+ company: z.ZodString;
234
+ workspace: z.ZodString;
235
+ company_brain: z.ZodString;
236
+ vertical: z.ZodString;
237
+ offers: z.ZodString;
238
+ persona: z.ZodString;
239
+ playbook: z.ZodString;
240
+ qualification: z.ZodString;
241
+ signals: z.ZodString;
242
+ history: z.ZodString;
243
+ crm: z.ZodString;
244
+ authorization: z.ZodString;
245
+ }, "strict", z.ZodTypeAny, {
246
+ prospect: string;
247
+ company: string;
248
+ workspace: string;
249
+ company_brain: string;
250
+ vertical: string;
251
+ offers: string;
252
+ persona: string;
253
+ playbook: string;
254
+ qualification: string;
255
+ signals: string;
256
+ history: string;
257
+ crm: string;
185
258
  authorization: string;
259
+ }, {
260
+ prospect: string;
261
+ company: string;
186
262
  workspace: string;
187
- }>;
263
+ company_brain: string;
264
+ vertical: string;
265
+ offers: string;
266
+ persona: string;
267
+ playbook: string;
268
+ qualification: string;
269
+ signals: string;
270
+ history: string;
271
+ crm: string;
272
+ authorization: string;
273
+ }>>;
188
274
  }, "strict", z.ZodTypeAny, {
189
275
  contract_version: "agent-writing-context.v1";
190
276
  context_version: string;
191
277
  facts_version: string;
192
278
  read_at: string;
193
279
  versions: {
194
- identity: string;
280
+ workspace: string;
195
281
  qualification: string;
196
282
  signals: string;
283
+ authorization: string;
284
+ identity: string;
197
285
  conversation: string;
198
286
  contactState: string;
199
287
  exclusion: string;
200
- authorization: string;
201
- workspace: string;
202
288
  };
289
+ modules?: {
290
+ prospect: string;
291
+ company: string;
292
+ workspace: string;
293
+ company_brain: string;
294
+ vertical: string;
295
+ offers: string;
296
+ persona: string;
297
+ playbook: string;
298
+ qualification: string;
299
+ signals: string;
300
+ history: string;
301
+ crm: string;
302
+ authorization: string;
303
+ } | undefined;
203
304
  }, {
204
305
  contract_version: "agent-writing-context.v1";
205
306
  context_version: string;
206
307
  facts_version: string;
207
308
  read_at: string;
208
309
  versions: {
209
- identity: string;
310
+ workspace: string;
210
311
  qualification: string;
211
312
  signals: string;
313
+ authorization: string;
314
+ identity: string;
212
315
  conversation: string;
213
316
  contactState: string;
214
317
  exclusion: string;
215
- authorization: string;
216
- workspace: string;
217
318
  };
319
+ modules?: {
320
+ prospect: string;
321
+ company: string;
322
+ workspace: string;
323
+ company_brain: string;
324
+ vertical: string;
325
+ offers: string;
326
+ persona: string;
327
+ playbook: string;
328
+ qualification: string;
329
+ signals: string;
330
+ history: string;
331
+ crm: string;
332
+ authorization: string;
333
+ } | undefined;
218
334
  }>;
219
335
  export declare const message: z.ZodEffects<z.ZodObject<{
220
336
  channel: z.ZodEnum<["GMAIL", "LINKEDIN"]>;
@@ -294,6 +410,7 @@ export declare const message: z.ZodEffects<z.ZodObject<{
294
410
  };
295
411
  }>;
296
412
  export declare const decision: z.ZodEffects<z.ZodObject<{
413
+ agent_cycle_id: z.ZodOptional<z.ZodString>;
297
414
  request_key: z.ZodString;
298
415
  lead_id: z.ZodString;
299
416
  person_id: z.ZodString;
@@ -324,54 +441,127 @@ export declare const decision: z.ZodEffects<z.ZodObject<{
324
441
  authorization: z.ZodString;
325
442
  workspace: z.ZodString;
326
443
  }, "strict", z.ZodTypeAny, {
327
- identity: string;
444
+ workspace: string;
328
445
  qualification: string;
329
446
  signals: string;
447
+ authorization: string;
448
+ identity: string;
330
449
  conversation: string;
331
450
  contactState: string;
332
451
  exclusion: string;
333
- authorization: string;
334
- workspace: string;
335
452
  }, {
336
- identity: string;
453
+ workspace: string;
337
454
  qualification: string;
338
455
  signals: string;
456
+ authorization: string;
457
+ identity: string;
339
458
  conversation: string;
340
459
  contactState: string;
341
460
  exclusion: string;
461
+ }>;
462
+ modules: z.ZodOptional<z.ZodObject<{
463
+ prospect: z.ZodString;
464
+ company: z.ZodString;
465
+ workspace: z.ZodString;
466
+ company_brain: z.ZodString;
467
+ vertical: z.ZodString;
468
+ offers: z.ZodString;
469
+ persona: z.ZodString;
470
+ playbook: z.ZodString;
471
+ qualification: z.ZodString;
472
+ signals: z.ZodString;
473
+ history: z.ZodString;
474
+ crm: z.ZodString;
475
+ authorization: z.ZodString;
476
+ }, "strict", z.ZodTypeAny, {
477
+ prospect: string;
478
+ company: string;
479
+ workspace: string;
480
+ company_brain: string;
481
+ vertical: string;
482
+ offers: string;
483
+ persona: string;
484
+ playbook: string;
485
+ qualification: string;
486
+ signals: string;
487
+ history: string;
488
+ crm: string;
342
489
  authorization: string;
490
+ }, {
491
+ prospect: string;
492
+ company: string;
343
493
  workspace: string;
344
- }>;
494
+ company_brain: string;
495
+ vertical: string;
496
+ offers: string;
497
+ persona: string;
498
+ playbook: string;
499
+ qualification: string;
500
+ signals: string;
501
+ history: string;
502
+ crm: string;
503
+ authorization: string;
504
+ }>>;
345
505
  }, "strict", z.ZodTypeAny, {
346
506
  contract_version: "agent-writing-context.v1";
347
507
  context_version: string;
348
508
  facts_version: string;
349
509
  read_at: string;
350
510
  versions: {
351
- identity: string;
511
+ workspace: string;
352
512
  qualification: string;
353
513
  signals: string;
514
+ authorization: string;
515
+ identity: string;
354
516
  conversation: string;
355
517
  contactState: string;
356
518
  exclusion: string;
357
- authorization: string;
358
- workspace: string;
359
519
  };
520
+ modules?: {
521
+ prospect: string;
522
+ company: string;
523
+ workspace: string;
524
+ company_brain: string;
525
+ vertical: string;
526
+ offers: string;
527
+ persona: string;
528
+ playbook: string;
529
+ qualification: string;
530
+ signals: string;
531
+ history: string;
532
+ crm: string;
533
+ authorization: string;
534
+ } | undefined;
360
535
  }, {
361
536
  contract_version: "agent-writing-context.v1";
362
537
  context_version: string;
363
538
  facts_version: string;
364
539
  read_at: string;
365
540
  versions: {
366
- identity: string;
541
+ workspace: string;
367
542
  qualification: string;
368
543
  signals: string;
544
+ authorization: string;
545
+ identity: string;
369
546
  conversation: string;
370
547
  contactState: string;
371
548
  exclusion: string;
372
- authorization: string;
373
- workspace: string;
374
549
  };
550
+ modules?: {
551
+ prospect: string;
552
+ company: string;
553
+ workspace: string;
554
+ company_brain: string;
555
+ vertical: string;
556
+ offers: string;
557
+ persona: string;
558
+ playbook: string;
559
+ qualification: string;
560
+ signals: string;
561
+ history: string;
562
+ crm: string;
563
+ authorization: string;
564
+ } | undefined;
375
565
  }>;
376
566
  authorization_revision: z.ZodNumber;
377
567
  messages: z.ZodArray<z.ZodEffects<z.ZodObject<{
@@ -467,15 +657,30 @@ export declare const decision: z.ZodEffects<z.ZodObject<{
467
657
  facts_version: string;
468
658
  read_at: string;
469
659
  versions: {
470
- identity: string;
660
+ workspace: string;
471
661
  qualification: string;
472
662
  signals: string;
663
+ authorization: string;
664
+ identity: string;
473
665
  conversation: string;
474
666
  contactState: string;
475
667
  exclusion: string;
476
- authorization: string;
477
- workspace: string;
478
668
  };
669
+ modules?: {
670
+ prospect: string;
671
+ company: string;
672
+ workspace: string;
673
+ company_brain: string;
674
+ vertical: string;
675
+ offers: string;
676
+ persona: string;
677
+ playbook: string;
678
+ qualification: string;
679
+ signals: string;
680
+ history: string;
681
+ crm: string;
682
+ authorization: string;
683
+ } | undefined;
479
684
  };
480
685
  authorization_revision: number;
481
686
  messages: {
@@ -493,6 +698,7 @@ export declare const decision: z.ZodEffects<z.ZodObject<{
493
698
  unsubscribe: string;
494
699
  };
495
700
  }[];
701
+ agent_cycle_id?: string | undefined;
496
702
  }, {
497
703
  request_key: string;
498
704
  lead_id: string;
@@ -509,15 +715,30 @@ export declare const decision: z.ZodEffects<z.ZodObject<{
509
715
  facts_version: string;
510
716
  read_at: string;
511
717
  versions: {
512
- identity: string;
718
+ workspace: string;
513
719
  qualification: string;
514
720
  signals: string;
721
+ authorization: string;
722
+ identity: string;
515
723
  conversation: string;
516
724
  contactState: string;
517
725
  exclusion: string;
518
- authorization: string;
519
- workspace: string;
520
726
  };
727
+ modules?: {
728
+ prospect: string;
729
+ company: string;
730
+ workspace: string;
731
+ company_brain: string;
732
+ vertical: string;
733
+ offers: string;
734
+ persona: string;
735
+ playbook: string;
736
+ qualification: string;
737
+ signals: string;
738
+ history: string;
739
+ crm: string;
740
+ authorization: string;
741
+ } | undefined;
521
742
  };
522
743
  authorization_revision: number;
523
744
  messages: {
@@ -535,6 +756,7 @@ export declare const decision: z.ZodEffects<z.ZodObject<{
535
756
  unsubscribe: string;
536
757
  };
537
758
  }[];
759
+ agent_cycle_id?: string | undefined;
538
760
  }>, {
539
761
  request_key: string;
540
762
  lead_id: string;
@@ -551,15 +773,30 @@ export declare const decision: z.ZodEffects<z.ZodObject<{
551
773
  facts_version: string;
552
774
  read_at: string;
553
775
  versions: {
554
- identity: string;
776
+ workspace: string;
555
777
  qualification: string;
556
778
  signals: string;
779
+ authorization: string;
780
+ identity: string;
557
781
  conversation: string;
558
782
  contactState: string;
559
783
  exclusion: string;
560
- authorization: string;
561
- workspace: string;
562
784
  };
785
+ modules?: {
786
+ prospect: string;
787
+ company: string;
788
+ workspace: string;
789
+ company_brain: string;
790
+ vertical: string;
791
+ offers: string;
792
+ persona: string;
793
+ playbook: string;
794
+ qualification: string;
795
+ signals: string;
796
+ history: string;
797
+ crm: string;
798
+ authorization: string;
799
+ } | undefined;
563
800
  };
564
801
  authorization_revision: number;
565
802
  messages: {
@@ -577,6 +814,7 @@ export declare const decision: z.ZodEffects<z.ZodObject<{
577
814
  unsubscribe: string;
578
815
  };
579
816
  }[];
817
+ agent_cycle_id?: string | undefined;
580
818
  }, {
581
819
  request_key: string;
582
820
  lead_id: string;
@@ -593,15 +831,30 @@ export declare const decision: z.ZodEffects<z.ZodObject<{
593
831
  facts_version: string;
594
832
  read_at: string;
595
833
  versions: {
596
- identity: string;
834
+ workspace: string;
597
835
  qualification: string;
598
836
  signals: string;
837
+ authorization: string;
838
+ identity: string;
599
839
  conversation: string;
600
840
  contactState: string;
601
841
  exclusion: string;
602
- authorization: string;
603
- workspace: string;
604
842
  };
843
+ modules?: {
844
+ prospect: string;
845
+ company: string;
846
+ workspace: string;
847
+ company_brain: string;
848
+ vertical: string;
849
+ offers: string;
850
+ persona: string;
851
+ playbook: string;
852
+ qualification: string;
853
+ signals: string;
854
+ history: string;
855
+ crm: string;
856
+ authorization: string;
857
+ } | undefined;
605
858
  };
606
859
  authorization_revision: number;
607
860
  messages: {
@@ -619,6 +872,7 @@ export declare const decision: z.ZodEffects<z.ZodObject<{
619
872
  unsubscribe: string;
620
873
  };
621
874
  }[];
875
+ agent_cycle_id?: string | undefined;
622
876
  }>;
623
877
  export declare const querySchema: z.ZodObject<{
624
878
  recipe: z.ZodOptional<z.ZodEnum<["never_contacted", "followup_due", "channel_gap", "replies_to_handle"]>>;
@@ -842,6 +1096,7 @@ export declare const querySchema: z.ZodObject<{
842
1096
  }>;
843
1097
  export declare const submitSchema: z.ZodObject<{
844
1098
  decisions: z.ZodArray<z.ZodEffects<z.ZodObject<{
1099
+ agent_cycle_id: z.ZodOptional<z.ZodString>;
845
1100
  request_key: z.ZodString;
846
1101
  lead_id: z.ZodString;
847
1102
  person_id: z.ZodString;
@@ -872,54 +1127,127 @@ export declare const submitSchema: z.ZodObject<{
872
1127
  authorization: z.ZodString;
873
1128
  workspace: z.ZodString;
874
1129
  }, "strict", z.ZodTypeAny, {
875
- identity: string;
1130
+ workspace: string;
876
1131
  qualification: string;
877
1132
  signals: string;
1133
+ authorization: string;
1134
+ identity: string;
878
1135
  conversation: string;
879
1136
  contactState: string;
880
1137
  exclusion: string;
881
- authorization: string;
882
- workspace: string;
883
1138
  }, {
884
- identity: string;
1139
+ workspace: string;
885
1140
  qualification: string;
886
1141
  signals: string;
1142
+ authorization: string;
1143
+ identity: string;
887
1144
  conversation: string;
888
1145
  contactState: string;
889
1146
  exclusion: string;
1147
+ }>;
1148
+ modules: z.ZodOptional<z.ZodObject<{
1149
+ prospect: z.ZodString;
1150
+ company: z.ZodString;
1151
+ workspace: z.ZodString;
1152
+ company_brain: z.ZodString;
1153
+ vertical: z.ZodString;
1154
+ offers: z.ZodString;
1155
+ persona: z.ZodString;
1156
+ playbook: z.ZodString;
1157
+ qualification: z.ZodString;
1158
+ signals: z.ZodString;
1159
+ history: z.ZodString;
1160
+ crm: z.ZodString;
1161
+ authorization: z.ZodString;
1162
+ }, "strict", z.ZodTypeAny, {
1163
+ prospect: string;
1164
+ company: string;
1165
+ workspace: string;
1166
+ company_brain: string;
1167
+ vertical: string;
1168
+ offers: string;
1169
+ persona: string;
1170
+ playbook: string;
1171
+ qualification: string;
1172
+ signals: string;
1173
+ history: string;
1174
+ crm: string;
890
1175
  authorization: string;
1176
+ }, {
1177
+ prospect: string;
1178
+ company: string;
891
1179
  workspace: string;
892
- }>;
1180
+ company_brain: string;
1181
+ vertical: string;
1182
+ offers: string;
1183
+ persona: string;
1184
+ playbook: string;
1185
+ qualification: string;
1186
+ signals: string;
1187
+ history: string;
1188
+ crm: string;
1189
+ authorization: string;
1190
+ }>>;
893
1191
  }, "strict", z.ZodTypeAny, {
894
1192
  contract_version: "agent-writing-context.v1";
895
1193
  context_version: string;
896
1194
  facts_version: string;
897
1195
  read_at: string;
898
1196
  versions: {
899
- identity: string;
1197
+ workspace: string;
900
1198
  qualification: string;
901
1199
  signals: string;
1200
+ authorization: string;
1201
+ identity: string;
902
1202
  conversation: string;
903
1203
  contactState: string;
904
1204
  exclusion: string;
905
- authorization: string;
906
- workspace: string;
907
1205
  };
1206
+ modules?: {
1207
+ prospect: string;
1208
+ company: string;
1209
+ workspace: string;
1210
+ company_brain: string;
1211
+ vertical: string;
1212
+ offers: string;
1213
+ persona: string;
1214
+ playbook: string;
1215
+ qualification: string;
1216
+ signals: string;
1217
+ history: string;
1218
+ crm: string;
1219
+ authorization: string;
1220
+ } | undefined;
908
1221
  }, {
909
1222
  contract_version: "agent-writing-context.v1";
910
1223
  context_version: string;
911
1224
  facts_version: string;
912
1225
  read_at: string;
913
1226
  versions: {
914
- identity: string;
1227
+ workspace: string;
915
1228
  qualification: string;
916
1229
  signals: string;
1230
+ authorization: string;
1231
+ identity: string;
917
1232
  conversation: string;
918
1233
  contactState: string;
919
1234
  exclusion: string;
920
- authorization: string;
921
- workspace: string;
922
1235
  };
1236
+ modules?: {
1237
+ prospect: string;
1238
+ company: string;
1239
+ workspace: string;
1240
+ company_brain: string;
1241
+ vertical: string;
1242
+ offers: string;
1243
+ persona: string;
1244
+ playbook: string;
1245
+ qualification: string;
1246
+ signals: string;
1247
+ history: string;
1248
+ crm: string;
1249
+ authorization: string;
1250
+ } | undefined;
923
1251
  }>;
924
1252
  authorization_revision: z.ZodNumber;
925
1253
  messages: z.ZodArray<z.ZodEffects<z.ZodObject<{
@@ -1015,15 +1343,30 @@ export declare const submitSchema: z.ZodObject<{
1015
1343
  facts_version: string;
1016
1344
  read_at: string;
1017
1345
  versions: {
1018
- identity: string;
1346
+ workspace: string;
1019
1347
  qualification: string;
1020
1348
  signals: string;
1349
+ authorization: string;
1350
+ identity: string;
1021
1351
  conversation: string;
1022
1352
  contactState: string;
1023
1353
  exclusion: string;
1024
- authorization: string;
1025
- workspace: string;
1026
1354
  };
1355
+ modules?: {
1356
+ prospect: string;
1357
+ company: string;
1358
+ workspace: string;
1359
+ company_brain: string;
1360
+ vertical: string;
1361
+ offers: string;
1362
+ persona: string;
1363
+ playbook: string;
1364
+ qualification: string;
1365
+ signals: string;
1366
+ history: string;
1367
+ crm: string;
1368
+ authorization: string;
1369
+ } | undefined;
1027
1370
  };
1028
1371
  authorization_revision: number;
1029
1372
  messages: {
@@ -1041,6 +1384,7 @@ export declare const submitSchema: z.ZodObject<{
1041
1384
  unsubscribe: string;
1042
1385
  };
1043
1386
  }[];
1387
+ agent_cycle_id?: string | undefined;
1044
1388
  }, {
1045
1389
  request_key: string;
1046
1390
  lead_id: string;
@@ -1057,15 +1401,30 @@ export declare const submitSchema: z.ZodObject<{
1057
1401
  facts_version: string;
1058
1402
  read_at: string;
1059
1403
  versions: {
1060
- identity: string;
1404
+ workspace: string;
1061
1405
  qualification: string;
1062
1406
  signals: string;
1407
+ authorization: string;
1408
+ identity: string;
1063
1409
  conversation: string;
1064
1410
  contactState: string;
1065
1411
  exclusion: string;
1066
- authorization: string;
1067
- workspace: string;
1068
1412
  };
1413
+ modules?: {
1414
+ prospect: string;
1415
+ company: string;
1416
+ workspace: string;
1417
+ company_brain: string;
1418
+ vertical: string;
1419
+ offers: string;
1420
+ persona: string;
1421
+ playbook: string;
1422
+ qualification: string;
1423
+ signals: string;
1424
+ history: string;
1425
+ crm: string;
1426
+ authorization: string;
1427
+ } | undefined;
1069
1428
  };
1070
1429
  authorization_revision: number;
1071
1430
  messages: {
@@ -1083,6 +1442,7 @@ export declare const submitSchema: z.ZodObject<{
1083
1442
  unsubscribe: string;
1084
1443
  };
1085
1444
  }[];
1445
+ agent_cycle_id?: string | undefined;
1086
1446
  }>, {
1087
1447
  request_key: string;
1088
1448
  lead_id: string;
@@ -1099,15 +1459,30 @@ export declare const submitSchema: z.ZodObject<{
1099
1459
  facts_version: string;
1100
1460
  read_at: string;
1101
1461
  versions: {
1102
- identity: string;
1462
+ workspace: string;
1103
1463
  qualification: string;
1104
1464
  signals: string;
1465
+ authorization: string;
1466
+ identity: string;
1105
1467
  conversation: string;
1106
1468
  contactState: string;
1107
1469
  exclusion: string;
1108
- authorization: string;
1109
- workspace: string;
1110
1470
  };
1471
+ modules?: {
1472
+ prospect: string;
1473
+ company: string;
1474
+ workspace: string;
1475
+ company_brain: string;
1476
+ vertical: string;
1477
+ offers: string;
1478
+ persona: string;
1479
+ playbook: string;
1480
+ qualification: string;
1481
+ signals: string;
1482
+ history: string;
1483
+ crm: string;
1484
+ authorization: string;
1485
+ } | undefined;
1111
1486
  };
1112
1487
  authorization_revision: number;
1113
1488
  messages: {
@@ -1125,6 +1500,7 @@ export declare const submitSchema: z.ZodObject<{
1125
1500
  unsubscribe: string;
1126
1501
  };
1127
1502
  }[];
1503
+ agent_cycle_id?: string | undefined;
1128
1504
  }, {
1129
1505
  request_key: string;
1130
1506
  lead_id: string;
@@ -1141,15 +1517,30 @@ export declare const submitSchema: z.ZodObject<{
1141
1517
  facts_version: string;
1142
1518
  read_at: string;
1143
1519
  versions: {
1144
- identity: string;
1520
+ workspace: string;
1145
1521
  qualification: string;
1146
1522
  signals: string;
1523
+ authorization: string;
1524
+ identity: string;
1147
1525
  conversation: string;
1148
1526
  contactState: string;
1149
1527
  exclusion: string;
1150
- authorization: string;
1151
- workspace: string;
1152
1528
  };
1529
+ modules?: {
1530
+ prospect: string;
1531
+ company: string;
1532
+ workspace: string;
1533
+ company_brain: string;
1534
+ vertical: string;
1535
+ offers: string;
1536
+ persona: string;
1537
+ playbook: string;
1538
+ qualification: string;
1539
+ signals: string;
1540
+ history: string;
1541
+ crm: string;
1542
+ authorization: string;
1543
+ } | undefined;
1153
1544
  };
1154
1545
  authorization_revision: number;
1155
1546
  messages: {
@@ -1167,6 +1558,7 @@ export declare const submitSchema: z.ZodObject<{
1167
1558
  unsubscribe: string;
1168
1559
  };
1169
1560
  }[];
1561
+ agent_cycle_id?: string | undefined;
1170
1562
  }>, "many">;
1171
1563
  organization_id: z.ZodString;
1172
1564
  program_id: z.ZodString;
@@ -1189,15 +1581,30 @@ export declare const submitSchema: z.ZodObject<{
1189
1581
  facts_version: string;
1190
1582
  read_at: string;
1191
1583
  versions: {
1192
- identity: string;
1584
+ workspace: string;
1193
1585
  qualification: string;
1194
1586
  signals: string;
1587
+ authorization: string;
1588
+ identity: string;
1195
1589
  conversation: string;
1196
1590
  contactState: string;
1197
1591
  exclusion: string;
1198
- authorization: string;
1199
- workspace: string;
1200
1592
  };
1593
+ modules?: {
1594
+ prospect: string;
1595
+ company: string;
1596
+ workspace: string;
1597
+ company_brain: string;
1598
+ vertical: string;
1599
+ offers: string;
1600
+ persona: string;
1601
+ playbook: string;
1602
+ qualification: string;
1603
+ signals: string;
1604
+ history: string;
1605
+ crm: string;
1606
+ authorization: string;
1607
+ } | undefined;
1201
1608
  };
1202
1609
  authorization_revision: number;
1203
1610
  messages: {
@@ -1215,6 +1622,7 @@ export declare const submitSchema: z.ZodObject<{
1215
1622
  unsubscribe: string;
1216
1623
  };
1217
1624
  }[];
1625
+ agent_cycle_id?: string | undefined;
1218
1626
  }[];
1219
1627
  }, {
1220
1628
  organization_id: string;
@@ -1235,15 +1643,30 @@ export declare const submitSchema: z.ZodObject<{
1235
1643
  facts_version: string;
1236
1644
  read_at: string;
1237
1645
  versions: {
1238
- identity: string;
1646
+ workspace: string;
1239
1647
  qualification: string;
1240
1648
  signals: string;
1649
+ authorization: string;
1650
+ identity: string;
1241
1651
  conversation: string;
1242
1652
  contactState: string;
1243
1653
  exclusion: string;
1244
- authorization: string;
1245
- workspace: string;
1246
1654
  };
1655
+ modules?: {
1656
+ prospect: string;
1657
+ company: string;
1658
+ workspace: string;
1659
+ company_brain: string;
1660
+ vertical: string;
1661
+ offers: string;
1662
+ persona: string;
1663
+ playbook: string;
1664
+ qualification: string;
1665
+ signals: string;
1666
+ history: string;
1667
+ crm: string;
1668
+ authorization: string;
1669
+ } | undefined;
1247
1670
  };
1248
1671
  authorization_revision: number;
1249
1672
  messages: {
@@ -1261,11 +1684,12 @@ export declare const submitSchema: z.ZodObject<{
1261
1684
  unsubscribe: string;
1262
1685
  };
1263
1686
  }[];
1687
+ agent_cycle_id?: string | undefined;
1264
1688
  }[];
1265
1689
  }>;
1266
- export declare const acknowledgeSchema: z.ZodEffects<z.ZodObject<{
1690
+ export declare const acknowledgeSchema: z.ZodObject<{
1267
1691
  cursor: z.ZodString;
1268
- receipts: z.ZodArray<z.ZodObject<{
1692
+ receipts: z.ZodEffects<z.ZodArray<z.ZodObject<{
1269
1693
  change_id: z.ZodEffects<z.ZodString, string, string>;
1270
1694
  status: z.ZodEnum<["PROCESSED", "DISMISSED"]>;
1271
1695
  reason: z.ZodString;
@@ -1277,28 +1701,18 @@ export declare const acknowledgeSchema: z.ZodEffects<z.ZodObject<{
1277
1701
  status: "PROCESSED" | "DISMISSED";
1278
1702
  reason: string;
1279
1703
  change_id: string;
1280
- }>, "many">;
1281
- organization_id: z.ZodString;
1282
- program_id: z.ZodString;
1283
- }, "strict", z.ZodTypeAny, {
1284
- cursor: string;
1285
- organization_id: string;
1286
- program_id: string;
1287
- receipts: {
1704
+ }>, "many">, {
1288
1705
  status: "PROCESSED" | "DISMISSED";
1289
1706
  reason: string;
1290
1707
  change_id: string;
1291
- }[];
1292
- }, {
1293
- cursor: string;
1294
- organization_id: string;
1295
- program_id: string;
1296
- receipts: {
1708
+ }[], {
1297
1709
  status: "PROCESSED" | "DISMISSED";
1298
1710
  reason: string;
1299
1711
  change_id: string;
1300
- }[];
1301
- }>, {
1712
+ }[]>;
1713
+ organization_id: z.ZodString;
1714
+ program_id: z.ZodString;
1715
+ }, "strict", z.ZodTypeAny, {
1302
1716
  cursor: string;
1303
1717
  organization_id: string;
1304
1718
  program_id: string;
@@ -1360,19 +1774,34 @@ export declare function decisionBody(d: z.infer<typeof decision>): {
1360
1774
  url: string;
1361
1775
  }[];
1362
1776
  context: {
1777
+ modules?: {
1778
+ prospect: string;
1779
+ company: string;
1780
+ workspace: string;
1781
+ company_brain: string;
1782
+ vertical: string;
1783
+ offers: string;
1784
+ persona: string;
1785
+ playbook: string;
1786
+ qualification: string;
1787
+ signals: string;
1788
+ history: string;
1789
+ crm: string;
1790
+ authorization: string;
1791
+ } | undefined;
1363
1792
  contractVersion: "agent-writing-context.v1";
1364
1793
  contextVersion: string;
1365
1794
  factsVersion: string;
1366
1795
  readAt: string;
1367
1796
  versions: {
1368
- identity: string;
1797
+ workspace: string;
1369
1798
  qualification: string;
1370
1799
  signals: string;
1800
+ authorization: string;
1801
+ identity: string;
1371
1802
  conversation: string;
1372
1803
  contactState: string;
1373
1804
  exclusion: string;
1374
- authorization: string;
1375
- workspace: string;
1376
1805
  };
1377
1806
  };
1378
1807
  authorizationRevision: number;
@@ -1391,4 +1820,5 @@ export declare function decisionBody(d: z.infer<typeof decision>): {
1391
1820
  unsubscribe: string;
1392
1821
  };
1393
1822
  }[];
1823
+ agentCycleId?: string | undefined;
1394
1824
  };
@@ -22,11 +22,16 @@ export const filters = z.object({
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
24
  }).strict();
25
+ // PRD-2632 : one fingerprint per module, copied from get_outreach_context_summary.decisionContext.modules.
26
+ export const contextModules = z.object({ prospect: version, company: version, workspace: version, company_brain: version, vertical: version, offers: version,
27
+ persona: version, playbook: version, qualification: version, signals: version, history: version, crm: version, authorization: version }).strict();
25
28
  export const context = z.object({
26
29
  contract_version: z.literal("agent-writing-context.v1"), context_version: version, facts_version: version, read_at: date,
27
30
  versions: z.object({ identity: version, qualification: version, signals: version, conversation: version,
28
31
  contactState: version, exclusion: version, authorization: version, workspace: version }).strict()
29
- .describe("Copy the versions object from get_outreach_prospect_context unchanged, including contactState."),
32
+ .describe("Copy the versions object from get_outreach_context_summary (or get_outreach_prospect_context) unchanged, including contactState."),
33
+ modules: contextModules.optional()
34
+ .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
35
  }).strict();
31
36
  export const message = z.object({
32
37
  channel, action: z.enum(["MESSAGE", "INVITATION"]), sender_id: identifier, account_key: z.string().min(1).max(1000),
@@ -52,6 +57,7 @@ export const message = z.object({
52
57
  issue(["body"], "Renseignez le texte du message.");
53
58
  });
54
59
  export const decision = z.object({
60
+ agent_cycle_id: z.string().min(1).max(200).regex(/^[^\s\u0000-\u001f\u007f]+$/).optional().describe("Exact existing agent cycle identifier; omit when unavailable, never invent one."),
55
61
  request_key: z.string().min(1).max(200), lead_id: identifier, person_id: identifier,
56
62
  purpose: z.enum(["FIRST_CONTACT", "FOLLOW_UP", "REPLY"]), reason: z.string().min(1).max(2000),
57
63
  sources: z.array(z.object({ label: exactText.min(1), url: z.string().url().max(20000) }).strict()).max(20),
@@ -75,8 +81,8 @@ export const querySchema = z.object({ ...scope, recipe: z.enum(["never_contacted
75
81
  export const submitSchema = z.object({ ...scope, decisions: z.array(decision).min(1).max(20) }).strict();
76
82
  export const acknowledgeSchema = z.object({ ...scope, cursor: z.string().min(1).max(2000),
77
83
  receipts: z.array(z.object({ change_id: z.string().regex(/^[1-9]\d{0,18}$/).refine(v => /^[1-9]\d{0,18}$/.test(v) && BigInt(v) <= 9223372036854775807n),
78
- status: z.enum(["PROCESSED", "DISMISSED"]), reason: z.string().trim().min(1).max(2000) }).strict()).min(1).max(100),
79
- }).strict().refine(v => new Set(v.receipts.map(r => r.change_id)).size === v.receipts.length, "Chaque changement doit être indiqué une seule fois.");
84
+ status: z.enum(["PROCESSED", "DISMISSED"]), reason: z.string().trim().min(1).max(2000) }).strict()).min(1).max(100).refine(receipts => new Set(receipts.map(r => r.change_id)).size === receipts.length, "Chaque changement doit être indiqué une seule fois."),
85
+ }).strict();
80
86
  export function queryBody(v) {
81
87
  const f = v.filters;
82
88
  return { recipe: v.recipe, limit: v.limit, cursor: v.cursor, filters: {
@@ -86,9 +92,9 @@ export function queryBody(v) {
86
92
  } };
87
93
  }
88
94
  export function decisionBody(d) {
89
- return { requestKey: d.request_key, leadId: d.lead_id, personId: d.person_id, purpose: d.purpose, reason: d.reason, sources: d.sources,
95
+ 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,
90
96
  context: { contractVersion: d.context.contract_version, contextVersion: d.context.context_version, factsVersion: d.context.facts_version,
91
- readAt: d.context.read_at, versions: d.context.versions }, authorizationRevision: d.authorization_revision,
97
+ readAt: d.context.read_at, versions: d.context.versions, ...(d.context.modules ? { modules: d.context.modules } : {}) }, authorizationRevision: d.authorization_revision,
92
98
  messages: d.messages.map(m => ({ channel: m.channel, action: m.action, senderId: m.sender_id, accountKey: m.account_key,
93
99
  recipient: m.recipient, subject: m.subject, body: m.body, threadId: m.thread_id, expectedInboundId: m.expected_inbound_id, technicalParts: m.technical_parts })) };
94
100
  }
@@ -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,
@@ -87,7 +87,8 @@ export function registerSignalTools(server) {
87
87
  .optional()
88
88
  .describe("Date the business event actually occurred (≠ insertion date). Partial or full " +
89
89
  "ISO 8601: 'YYYY' / 'YYYY-MM' / 'YYYY-MM-DD' / datetime. Use the finest " +
90
- "precision you can reliably determine."),
90
+ "precision you can reliably determine. When provided, date_evidence is required."),
91
+ date_evidence: z.string().optional().describe("Source passage or factual evidence establishing the event date. Required and non-empty when date is provided; never infer a date from insertion time."),
91
92
  source: z
92
93
  .string()
93
94
  .optional()
@@ -101,7 +102,7 @@ export function registerSignalTools(server) {
101
102
  reason: reasonParam,
102
103
  },
103
104
  annotations: { idempotentHint: true },
104
- }, async ({ id, lead_id, level, title, content, ai_summary, date, source, agent_source, source_url, reason, }) => {
105
+ }, async ({ id, lead_id, level, title, content, ai_summary, date, date_evidence, source, agent_source, source_url, reason, }) => {
105
106
  const capError = capExceeded();
106
107
  if (capError)
107
108
  return capError;
@@ -121,6 +122,8 @@ export function registerSignalTools(server) {
121
122
  body.aiSummary = ai_summary;
122
123
  if (date !== undefined)
123
124
  body.date = date;
125
+ if (date_evidence !== undefined)
126
+ body.dateEvidence = date_evidence;
124
127
  if (source !== undefined)
125
128
  body.source = source;
126
129
  if (agent_source !== undefined)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agifyai/leadify-mcp",
3
- "version": "9.7.1",
3
+ "version": "9.8.0",
4
4
  "description": "MCP server for Leadify lead management API",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",