@elevasis/core 0.7.1 → 0.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.
Files changed (473) hide show
  1. package/package.json +1 -1
  2. package/src/README.md +41 -41
  3. package/src/__tests__/publish.test.ts +18 -18
  4. package/src/__tests__/{template-foundations-compatibility.test.ts → template-core-compatibility.test.ts} +99 -99
  5. package/src/_gen/__tests__/__snapshots__/contracts.md.snap +1135 -1131
  6. package/src/_gen/__tests__/scaffold-contracts.test.ts +53 -53
  7. package/src/_gen/scaffold-contracts.ts +45 -45
  8. package/src/auth/multi-tenancy/credentials/README.md +38 -38
  9. package/src/auth/multi-tenancy/credentials/index.ts +6 -6
  10. package/src/auth/multi-tenancy/credentials/server/encryption.ts +39 -39
  11. package/src/auth/multi-tenancy/credentials/server/service.ts +60 -60
  12. package/src/auth/multi-tenancy/index.ts +17 -17
  13. package/src/auth/multi-tenancy/invitations/api-schemas.ts +107 -107
  14. package/src/auth/multi-tenancy/invitations/index.ts +37 -37
  15. package/src/auth/multi-tenancy/invitations/invitation.ts +86 -86
  16. package/src/auth/multi-tenancy/invitations/server/index.ts +25 -25
  17. package/src/auth/multi-tenancy/invitations/server/transforms.ts +24 -24
  18. package/src/auth/multi-tenancy/invitations/server/workos.ts +24 -24
  19. package/src/auth/multi-tenancy/invitations/supabase.ts +50 -50
  20. package/src/auth/multi-tenancy/memberships/api-schemas.ts +126 -126
  21. package/src/auth/multi-tenancy/memberships/index.ts +21 -21
  22. package/src/auth/multi-tenancy/memberships/membership.ts +138 -138
  23. package/src/auth/multi-tenancy/memberships/server/index.ts +15 -15
  24. package/src/auth/multi-tenancy/memberships/server/transforms.ts +32 -32
  25. package/src/auth/multi-tenancy/memberships/server/workos.ts +21 -21
  26. package/src/auth/multi-tenancy/memberships/supabase.ts +46 -46
  27. package/src/auth/multi-tenancy/organizations/api-schemas.ts +128 -128
  28. package/src/auth/multi-tenancy/organizations/index.ts +23 -23
  29. package/src/auth/multi-tenancy/organizations/organization.ts +24 -24
  30. package/src/auth/multi-tenancy/organizations/server/index.ts +10 -10
  31. package/src/auth/multi-tenancy/organizations/server/transforms.ts +35 -35
  32. package/src/auth/multi-tenancy/organizations/server/workos.ts +20 -20
  33. package/src/auth/multi-tenancy/types.ts +83 -83
  34. package/src/auth/multi-tenancy/users/api-schemas.ts +194 -194
  35. package/src/auth/multi-tenancy/users/index.ts +27 -27
  36. package/src/auth/multi-tenancy/users/server/index.ts +19 -19
  37. package/src/auth/multi-tenancy/users/server/transforms.ts +21 -21
  38. package/src/auth/multi-tenancy/users/server/workos.ts +16 -16
  39. package/src/auth/multi-tenancy/users/user.ts +65 -65
  40. package/src/business/README.md +52 -52
  41. package/src/business/__tests__/entities-published.test.ts +33 -33
  42. package/src/business/acquisition/api-schemas.ts +759 -759
  43. package/src/business/acquisition/index.ts +109 -109
  44. package/src/business/acquisition/types.ts +402 -402
  45. package/src/business/base-entities.test.ts +481 -481
  46. package/src/business/base-entities.ts +241 -241
  47. package/src/business/entities-published.ts +24 -24
  48. package/src/business/index.ts +15 -15
  49. package/src/business/pdf/browser/pdfmake-browser.ts +229 -229
  50. package/src/business/pdf/index.ts +10 -10
  51. package/src/business/pdf/server/index.ts +21 -21
  52. package/src/business/pdf/server/themes/default.ts +8 -8
  53. package/src/business/pdf/server/themes/index.ts +9 -9
  54. package/src/business/pdf/server/themes/types.ts +8 -8
  55. package/src/business/pdf/types.ts +272 -272
  56. package/src/business/projects/index.ts +2 -2
  57. package/src/business/projects/sse-events.ts +21 -21
  58. package/src/business/projects/types.ts +89 -89
  59. package/src/business/sales/api-schemas.ts +75 -75
  60. package/src/business/seo/__tests__/linking.test.ts +549 -549
  61. package/src/business/seo/__tests__/types.test.ts +404 -404
  62. package/src/business/seo/index.ts +2 -2
  63. package/src/business/seo/linking.ts +281 -281
  64. package/src/business/seo/types.ts +199 -199
  65. package/src/commands/queue/index.ts +3 -3
  66. package/src/commands/queue/schemas.test.ts +593 -593
  67. package/src/commands/queue/schemas.ts +125 -125
  68. package/src/commands/queue/sse-events.ts +61 -61
  69. package/src/commands/queue/types/action.ts +52 -52
  70. package/src/commands/queue/types/checkpoint.ts +44 -44
  71. package/src/commands/queue/types/index.ts +7 -7
  72. package/src/commands/queue/types/task.ts +116 -116
  73. package/src/commands/queue/types.ts +14 -14
  74. package/src/content/distribution-metadata.ts +61 -61
  75. package/src/content/index.ts +10 -10
  76. package/src/deployments/index.ts +22 -22
  77. package/src/execution/core/__tests__/archived-logs.test.ts +72 -72
  78. package/src/execution/core/index.ts +11 -11
  79. package/src/execution/core/runner-types.ts +80 -80
  80. package/src/execution/core/server/environment.ts +31 -31
  81. package/src/execution/core/sse-executions.ts +119 -119
  82. package/src/execution/core/types.ts +29 -29
  83. package/src/execution/engine/__tests__/fixtures/test-agents.ts +4 -4
  84. package/src/execution/engine/__tests__/timeout.test.ts +565 -565
  85. package/src/execution/engine/agent/__tests__/errors.test.ts +508 -508
  86. package/src/execution/engine/agent/actions/__tests__/processor.test.ts +531 -531
  87. package/src/execution/engine/agent/actions/executor.ts +205 -205
  88. package/src/execution/engine/agent/actions/navigate-knowledge-executor.ts +230 -230
  89. package/src/execution/engine/agent/actions/processor.ts +116 -116
  90. package/src/execution/engine/agent/actions/types.ts +70 -70
  91. package/src/execution/engine/agent/core/agent.ts +810 -810
  92. package/src/execution/engine/agent/core/types.ts +155 -155
  93. package/src/execution/engine/agent/errors.ts +251 -251
  94. package/src/execution/engine/agent/index.ts +78 -78
  95. package/src/execution/engine/agent/knowledge-map/types.ts +106 -106
  96. package/src/execution/engine/agent/knowledge-map/utils.ts +101 -101
  97. package/src/execution/engine/agent/memory/__tests__/manager.test.ts +754 -754
  98. package/src/execution/engine/agent/memory/domains.ts +99 -99
  99. package/src/execution/engine/agent/memory/manager.ts +365 -365
  100. package/src/execution/engine/agent/memory/processor.ts +66 -66
  101. package/src/execution/engine/agent/memory/types.ts +90 -90
  102. package/src/execution/engine/agent/memory/utils.ts +134 -134
  103. package/src/execution/engine/agent/observability/logging.ts +467 -467
  104. package/src/execution/engine/agent/observability/types.ts +64 -64
  105. package/src/execution/engine/agent/reasoning/adapters/agent-adapter-helpers.ts +349 -349
  106. package/src/execution/engine/agent/reasoning/processor.ts +92 -92
  107. package/src/execution/engine/agent/reasoning/prompt-sections/base-actions.ts +134 -134
  108. package/src/execution/engine/agent/reasoning/prompt-sections/completion.ts +49 -49
  109. package/src/execution/engine/agent/reasoning/prompt-sections/knowledge-map.ts +93 -93
  110. package/src/execution/engine/agent/reasoning/prompt-sections/memory.ts +65 -65
  111. package/src/execution/engine/agent/reasoning/prompt-sections/tools.ts +44 -44
  112. package/src/execution/engine/agent/reasoning/request-builder.ts +169 -169
  113. package/src/execution/engine/agent/reasoning/types.ts +18 -18
  114. package/src/execution/engine/base/errors.ts +118 -118
  115. package/src/execution/engine/base/index.ts +2 -2
  116. package/src/execution/engine/base/logging.ts +31 -31
  117. package/src/execution/engine/base/serialization.ts +324 -324
  118. package/src/execution/engine/base/types.ts +126 -126
  119. package/src/execution/engine/base/utils.ts +41 -41
  120. package/src/execution/engine/index.ts +434 -434
  121. package/src/execution/engine/interface/index.ts +1 -1
  122. package/src/execution/engine/interface/types.ts +62 -62
  123. package/src/execution/engine/llm/__tests__/model-info.test.ts +50 -50
  124. package/src/execution/engine/llm/__tests__/model-validation.test.ts +321 -321
  125. package/src/execution/engine/llm/__tests__/response-schema-validator.test.ts +115 -115
  126. package/src/execution/engine/llm/adapters/__tests__/adapter-factory.test.ts +375 -375
  127. package/src/execution/engine/llm/adapters/__tests__/anthropic-adapter.test.ts +463 -463
  128. package/src/execution/engine/llm/adapters/__tests__/anthropic.integration.test.ts +177 -177
  129. package/src/execution/engine/llm/adapters/__tests__/google-adapter.test.ts +722 -722
  130. package/src/execution/engine/llm/adapters/__tests__/google.integration.test.ts +376 -376
  131. package/src/execution/engine/llm/adapters/__tests__/openai-adapter.test.ts +551 -551
  132. package/src/execution/engine/llm/adapters/__tests__/openrouter-adapter.test.ts +563 -563
  133. package/src/execution/engine/llm/adapters/__tests__/openrouter.integration.test.ts +105 -105
  134. package/src/execution/engine/llm/adapters/__tests__/universal-adapter.test.ts +537 -537
  135. package/src/execution/engine/llm/adapters/circuit-breaker.ts +147 -147
  136. package/src/execution/engine/llm/adapters/index.ts +17 -17
  137. package/src/execution/engine/llm/adapters/mock-adapter.ts +116 -116
  138. package/src/execution/engine/llm/adapters/server/adapter-factory.ts +130 -130
  139. package/src/execution/engine/llm/adapters/server/anthropic.ts +137 -137
  140. package/src/execution/engine/llm/adapters/server/google.ts +283 -283
  141. package/src/execution/engine/llm/adapters/server/index.ts +12 -12
  142. package/src/execution/engine/llm/adapters/server/openai.ts +206 -206
  143. package/src/execution/engine/llm/adapters/server/openrouter.ts +235 -235
  144. package/src/execution/engine/llm/adapters/universal-adapter.ts +230 -230
  145. package/src/execution/engine/llm/errors.ts +186 -186
  146. package/src/execution/engine/llm/model-info.ts +332 -332
  147. package/src/execution/engine/llm/response-schema-validator.ts +113 -113
  148. package/src/execution/engine/llm/types.ts +86 -86
  149. package/src/execution/engine/test-utils/index.ts +6 -6
  150. package/src/execution/engine/test-utils/mocks.ts +56 -56
  151. package/src/execution/engine/tools/integration/base-integration-adapter.ts +50 -50
  152. package/src/execution/engine/tools/integration/index.ts +53 -53
  153. package/src/execution/engine/tools/integration/server/adapters/anymailfinder/anymailfinder-adapter.ts +73 -73
  154. package/src/execution/engine/tools/integration/server/adapters/anymailfinder/anymailfinder-tools.ts +209 -209
  155. package/src/execution/engine/tools/integration/server/adapters/anymailfinder/fetch/find-company-email/index.ts +82 -82
  156. package/src/execution/engine/tools/integration/server/adapters/anymailfinder/fetch/find-decision-maker-email/index.ts +122 -122
  157. package/src/execution/engine/tools/integration/server/adapters/anymailfinder/fetch/find-person-email/index.ts +89 -89
  158. package/src/execution/engine/tools/integration/server/adapters/anymailfinder/fetch/verify-email/index.ts +84 -84
  159. package/src/execution/engine/tools/integration/server/adapters/anymailfinder/index.ts +16 -16
  160. package/src/execution/engine/tools/integration/server/adapters/apify/__tests__/apify-run-actor.integration.test.ts +293 -293
  161. package/src/execution/engine/tools/integration/server/adapters/apify/apify-adapter.ts +100 -100
  162. package/src/execution/engine/tools/integration/server/adapters/apify/apify-tools.ts +217 -217
  163. package/src/execution/engine/tools/integration/server/adapters/apify/fetch/get-dataset-items/index.ts +92 -92
  164. package/src/execution/engine/tools/integration/server/adapters/apify/fetch/run-actor/index.ts +218 -218
  165. package/src/execution/engine/tools/integration/server/adapters/apify/fetch/start-actor/index.ts +87 -87
  166. package/src/execution/engine/tools/integration/server/adapters/apify/index.ts +11 -11
  167. package/src/execution/engine/tools/integration/server/adapters/attio/__tests__/attio-crud.integration.test.ts +361 -361
  168. package/src/execution/engine/tools/integration/server/adapters/attio/attio-adapter.ts +162 -162
  169. package/src/execution/engine/tools/integration/server/adapters/attio/attio-tools.ts +594 -594
  170. package/src/execution/engine/tools/integration/server/adapters/attio/fetch/create-attribute/index.ts +214 -214
  171. package/src/execution/engine/tools/integration/server/adapters/attio/fetch/create-note/index.ts +152 -152
  172. package/src/execution/engine/tools/integration/server/adapters/attio/fetch/create-record/index.ts +141 -141
  173. package/src/execution/engine/tools/integration/server/adapters/attio/fetch/delete-note/index.ts +86 -86
  174. package/src/execution/engine/tools/integration/server/adapters/attio/fetch/delete-record/index.ts +105 -105
  175. package/src/execution/engine/tools/integration/server/adapters/attio/fetch/get-record/index.ts +118 -118
  176. package/src/execution/engine/tools/integration/server/adapters/attio/fetch/list-attributes/index.ts +165 -165
  177. package/src/execution/engine/tools/integration/server/adapters/attio/fetch/list-notes/index.ts +96 -96
  178. package/src/execution/engine/tools/integration/server/adapters/attio/fetch/list-objects/index.ts +104 -104
  179. package/src/execution/engine/tools/integration/server/adapters/attio/fetch/list-records/index.ts +156 -156
  180. package/src/execution/engine/tools/integration/server/adapters/attio/fetch/update-attribute/index.ts +220 -220
  181. package/src/execution/engine/tools/integration/server/adapters/attio/fetch/update-record/index.ts +140 -140
  182. package/src/execution/engine/tools/integration/server/adapters/attio/fetch/utils/types.ts +146 -146
  183. package/src/execution/engine/tools/integration/server/adapters/attio/index.ts +31 -31
  184. package/src/execution/engine/tools/integration/server/adapters/gmail/gmail-adapter.ts +210 -210
  185. package/src/execution/engine/tools/integration/server/adapters/gmail/gmail-tools.ts +104 -104
  186. package/src/execution/engine/tools/integration/server/adapters/google-sheets/__tests__/google-sheets.integration.test.ts +261 -261
  187. package/src/execution/engine/tools/integration/server/adapters/google-sheets/google-sheets-adapter.ts +1189 -1189
  188. package/src/execution/engine/tools/integration/server/adapters/google-sheets/google-sheets-tools.ts +641 -641
  189. package/src/execution/engine/tools/integration/server/adapters/google-sheets/index.ts +18 -18
  190. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/activate-campaign/index.ts +86 -86
  191. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/add-to-campaign/__tests__/index.test.ts +289 -289
  192. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/add-to-campaign/index.ts +154 -154
  193. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/bulk-add-leads/__tests__/index.test.ts +325 -325
  194. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/bulk-add-leads/index.ts +153 -153
  195. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/bulk-delete-leads/index.ts +84 -84
  196. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/create-campaign/index.ts +125 -125
  197. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/create-inbox-test/index.ts +107 -107
  198. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/delete-campaign/index.ts +85 -85
  199. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/get-account-health/index.ts +91 -91
  200. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/get-campaign/index.ts +92 -92
  201. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/get-campaign-analytics/__tests__/index.test.ts +195 -195
  202. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/get-campaign-analytics/index.ts +113 -113
  203. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/get-daily-campaign-analytics/index.ts +104 -104
  204. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/get-emails/index.ts +155 -155
  205. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/get-step-analytics/__tests__/index.test.ts +196 -196
  206. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/get-step-analytics/index.ts +102 -102
  207. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/list-campaigns/__tests__/index.test.ts +189 -189
  208. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/list-campaigns/index.ts +87 -87
  209. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/list-leads/index.ts +112 -112
  210. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/patch-lead/index.ts +76 -76
  211. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/pause-campaign/index.ts +86 -86
  212. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/remove-from-subsequence/index.ts +98 -98
  213. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/send-reply/index.ts +126 -126
  214. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/update-campaign/__tests__/index.test.ts +193 -193
  215. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/update-campaign/index.ts +99 -99
  216. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/update-interest-status/__tests__/index.test.ts +621 -621
  217. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/update-interest-status/index.ts +125 -125
  218. package/src/execution/engine/tools/integration/server/adapters/instantly/index.ts +29 -29
  219. package/src/execution/engine/tools/integration/server/adapters/instantly/instantly-adapter.ts +178 -178
  220. package/src/execution/engine/tools/integration/server/adapters/instantly/instantly-tools.ts +1473 -1473
  221. package/src/execution/engine/tools/integration/server/adapters/millionverifier/fetch/check-credits/index.ts +59 -59
  222. package/src/execution/engine/tools/integration/server/adapters/millionverifier/fetch/verify-email/index.ts +102 -102
  223. package/src/execution/engine/tools/integration/server/adapters/millionverifier/index.ts +17 -17
  224. package/src/execution/engine/tools/integration/server/adapters/millionverifier/millionverifier-adapter.ts +80 -80
  225. package/src/execution/engine/tools/integration/server/adapters/millionverifier/millionverifier-tools.ts +102 -102
  226. package/src/execution/engine/tools/integration/server/adapters/resend/fetch/get-email/index.ts +102 -102
  227. package/src/execution/engine/tools/integration/server/adapters/resend/fetch/send-email/index.ts +134 -134
  228. package/src/execution/engine/tools/integration/server/adapters/resend/fetch/utils/types.ts +75 -75
  229. package/src/execution/engine/tools/integration/server/adapters/resend/index.ts +27 -27
  230. package/src/execution/engine/tools/integration/server/adapters/resend/resend-adapter.ts +108 -108
  231. package/src/execution/engine/tools/integration/server/adapters/resend/resend-tools.ts +132 -132
  232. package/src/execution/engine/tools/integration/server/adapters/signature-api/fetch/create-envelope/index.ts +274 -274
  233. package/src/execution/engine/tools/integration/server/adapters/signature-api/fetch/download-document/index.ts +230 -230
  234. package/src/execution/engine/tools/integration/server/adapters/signature-api/fetch/get-envelope/index.ts +133 -133
  235. package/src/execution/engine/tools/integration/server/adapters/signature-api/fetch/void-envelope/index.ts +90 -90
  236. package/src/execution/engine/tools/integration/server/adapters/stripe/fetch/utils/types.ts +210 -210
  237. package/src/execution/engine/tools/integration/server/adapters/stripe/stripe-adapter.ts +517 -517
  238. package/src/execution/engine/tools/integration/server/adapters/stripe/stripe-tools.ts +309 -309
  239. package/src/execution/engine/tools/integration/server/adapters/tomba/fetch/domain-search/index.ts +133 -133
  240. package/src/execution/engine/tools/integration/server/adapters/tomba/fetch/email-finder/index.ts +122 -122
  241. package/src/execution/engine/tools/integration/server/adapters/tomba/fetch/email-verifier/index.ts +111 -111
  242. package/src/execution/engine/tools/integration/server/adapters/tomba/index.ts +11 -11
  243. package/src/execution/engine/tools/integration/server/adapters/tomba/tomba-adapter.ts +78 -78
  244. package/src/execution/engine/tools/integration/server/adapters/tomba/tomba-tools.ts +222 -222
  245. package/src/execution/engine/tools/integration/server/index.ts +61 -61
  246. package/src/execution/engine/tools/integration/service.ts +161 -161
  247. package/src/execution/engine/tools/integration/tool.ts +253 -253
  248. package/src/execution/engine/tools/integration/types/anymailfinder.ts +74 -74
  249. package/src/execution/engine/tools/integration/types/apify.ts +92 -92
  250. package/src/execution/engine/tools/integration/types/index.ts +19 -19
  251. package/src/execution/engine/tools/integration/types/instantly.ts +557 -557
  252. package/src/execution/engine/tools/integration/types/millionverifier.ts +56 -56
  253. package/src/execution/engine/tools/integration/types/stripe.ts +162 -162
  254. package/src/execution/engine/tools/integration/types/tomba.ts +94 -94
  255. package/src/execution/engine/tools/lead-service-types.ts +884 -884
  256. package/src/execution/engine/tools/llm/index.ts +11 -11
  257. package/src/execution/engine/tools/llm/server/index.ts +8 -8
  258. package/src/execution/engine/tools/llm/server/llm-call-tool.ts +118 -118
  259. package/src/execution/engine/tools/platform/__tests__/pdf.test.ts +441 -441
  260. package/src/execution/engine/tools/platform/acquisition/company-tools.ts +248 -248
  261. package/src/execution/engine/tools/platform/acquisition/contact-tools.ts +319 -319
  262. package/src/execution/engine/tools/platform/acquisition/index.ts +43 -43
  263. package/src/execution/engine/tools/platform/acquisition/list-tools.ts +148 -148
  264. package/src/execution/engine/tools/platform/acquisition/types.ts +260 -260
  265. package/src/execution/engine/tools/platform/email/index.ts +122 -122
  266. package/src/execution/engine/tools/platform/email/types.ts +96 -96
  267. package/src/execution/engine/tools/platform/index.ts +157 -157
  268. package/src/execution/engine/tools/platform/notification.ts +81 -81
  269. package/src/execution/engine/tools/platform/pdf/index.ts +110 -110
  270. package/src/execution/engine/tools/platform/pdf/types.ts +77 -77
  271. package/src/execution/engine/tools/platform/scheduler.ts +87 -87
  272. package/src/execution/engine/tools/platform/storage/index.ts +370 -370
  273. package/src/execution/engine/tools/platform/types.ts +148 -148
  274. package/src/execution/engine/tools/registry.ts +700 -700
  275. package/src/execution/engine/tools/tool-maps.ts +786 -786
  276. package/src/execution/engine/tools/types.ts +233 -233
  277. package/src/execution/engine/workflow/__tests__/errors.test.ts +139 -139
  278. package/src/execution/engine/workflow/errors.ts +63 -63
  279. package/src/execution/engine/workflow/helpers/index.ts +11 -11
  280. package/src/execution/engine/workflow/helpers/server/index.ts +8 -8
  281. package/src/execution/engine/workflow/helpers/server/llm-call.ts +93 -93
  282. package/src/execution/engine/workflow/index.ts +19 -19
  283. package/src/execution/engine/workflow/log-truncate.ts +26 -26
  284. package/src/execution/engine/workflow/logging.ts +191 -191
  285. package/src/execution/engine/workflow/types.ts +182 -182
  286. package/src/execution/engine/workflow/utils.ts +280 -280
  287. package/src/execution/engine/workflow/workflow.ts +168 -168
  288. package/src/execution/index.ts +3 -3
  289. package/src/execution/scheduler/__tests__/api-schemas.test.ts +733 -733
  290. package/src/execution/scheduler/__tests__/utils.test.ts +1009 -1009
  291. package/src/execution/scheduler/api-schemas.ts +296 -296
  292. package/src/execution/scheduler/index.ts +50 -50
  293. package/src/execution/scheduler/schemas.ts +264 -264
  294. package/src/execution/scheduler/types.ts +111 -111
  295. package/src/execution/scheduler/utils.ts +364 -364
  296. package/src/forms/index.ts +7 -7
  297. package/src/forms/schemas.ts +69 -69
  298. package/src/forms/types.ts +70 -70
  299. package/src/index.ts +71 -60
  300. package/src/integrations/credentials/__tests__/schemas.test.ts +82 -82
  301. package/src/integrations/credentials/__tests__/utils.test.ts +144 -144
  302. package/src/integrations/credentials/api-schemas.ts +143 -143
  303. package/src/integrations/credentials/index.ts +32 -32
  304. package/src/integrations/credentials/schemas.ts +164 -164
  305. package/src/integrations/credentials/utils.ts +59 -59
  306. package/src/integrations/oauth/__tests__/provider-registry.test.ts +59 -59
  307. package/src/integrations/oauth/api-schemas.ts +92 -92
  308. package/src/integrations/oauth/index.ts +19 -19
  309. package/src/integrations/oauth/provider-registry.ts +61 -61
  310. package/src/integrations/oauth/server/__tests__/refresh-concurrent.test.ts +183 -183
  311. package/src/integrations/oauth/server/__tests__/refresh.test.ts +577 -577
  312. package/src/integrations/oauth/server/credentials.ts +39 -39
  313. package/src/integrations/oauth/server/refresh.ts +214 -214
  314. package/src/integrations/oauth/types.ts +34 -34
  315. package/src/integrations/webhook-endpoints/__tests__/api-schemas.test.ts +318 -318
  316. package/src/integrations/webhook-endpoints/api-schemas.ts +102 -102
  317. package/src/integrations/webhook-endpoints/index.ts +28 -28
  318. package/src/integrations/webhook-endpoints/types.ts +51 -51
  319. package/src/operations/activities/api-schemas.ts +79 -79
  320. package/src/operations/activities/index.ts +9 -9
  321. package/src/operations/activities/sse-events.ts +30 -30
  322. package/src/operations/activities/types.ts +63 -63
  323. package/src/operations/debug-logs/client.ts +60 -60
  324. package/src/operations/debug-logs/debug-logger.ts +83 -83
  325. package/src/operations/debug-logs/index.ts +8 -8
  326. package/src/operations/debug-logs/server.ts +19 -19
  327. package/src/operations/debug-logs/types.ts +33 -33
  328. package/src/operations/index.ts +50 -50
  329. package/src/operations/notifications/api-schemas.ts +91 -91
  330. package/src/operations/notifications/index.ts +3 -3
  331. package/src/operations/notifications/sse-events.ts +21 -21
  332. package/src/operations/notifications/types.ts +47 -47
  333. package/src/operations/observability/__tests__/openrouter-cost-flow.test.ts +297 -297
  334. package/src/operations/observability/__tests__/utils.test.ts +54 -54
  335. package/src/operations/observability/ai-usage-collector.ts +64 -64
  336. package/src/operations/observability/index.ts +13 -13
  337. package/src/operations/observability/metrics-collector.ts +49 -49
  338. package/src/operations/observability/schemas.ts +39 -39
  339. package/src/operations/observability/types.ts +463 -463
  340. package/src/operations/observability/utils.ts +77 -77
  341. package/src/operations/sessions/__tests__/manager.test.ts +821 -821
  342. package/src/operations/sessions/index.ts +26 -26
  343. package/src/operations/sessions/server/manager.ts +90 -90
  344. package/src/operations/sessions/server/session.ts +180 -180
  345. package/src/operations/sessions/types.ts +98 -98
  346. package/src/operations/triggers/index.ts +12 -12
  347. package/src/operations/triggers/webhook/definitions/instantly-account-error.ts +44 -44
  348. package/src/operations/triggers/webhook/definitions/instantly-auto-reply-received.ts +51 -51
  349. package/src/operations/triggers/webhook/definitions/instantly-campaign-completed.ts +45 -45
  350. package/src/operations/triggers/webhook/definitions/instantly-email-bounced.ts +49 -49
  351. package/src/operations/triggers/webhook/definitions/instantly-lead-unsubscribed.ts +45 -45
  352. package/src/operations/triggers/webhook/definitions/instantly-reply-received.ts +54 -54
  353. package/src/operations/triggers/webhook/index.ts +35 -35
  354. package/src/operations/triggers/webhook/types.ts +74 -74
  355. package/src/organization-model/README.md +97 -97
  356. package/src/organization-model/__tests__/defaults.test.ts +175 -175
  357. package/src/organization-model/__tests__/domains/customers.test.ts +295 -295
  358. package/src/organization-model/__tests__/domains/goals.test.ts +479 -479
  359. package/src/organization-model/__tests__/domains/identity.test.ts +279 -279
  360. package/src/organization-model/__tests__/domains/navigation.test.ts +212 -212
  361. package/src/organization-model/__tests__/domains/offerings.test.ts +419 -419
  362. package/src/organization-model/__tests__/domains/operations.test.ts +203 -203
  363. package/src/organization-model/__tests__/domains/resource-mappings.test.ts +362 -362
  364. package/src/organization-model/__tests__/domains/roles.test.ts +347 -347
  365. package/src/organization-model/__tests__/domains/statuses.test.ts +243 -243
  366. package/src/organization-model/__tests__/foundation.test.ts +105 -105
  367. package/src/organization-model/__tests__/graph.test.ts +894 -894
  368. package/src/organization-model/__tests__/resolve.test.ts +690 -690
  369. package/src/organization-model/__tests__/schema.test.ts +407 -407
  370. package/src/organization-model/contracts.ts +14 -14
  371. package/src/organization-model/defaults.ts +148 -148
  372. package/src/organization-model/domains/branding.ts +22 -22
  373. package/src/organization-model/domains/customers.ts +75 -75
  374. package/src/organization-model/domains/features.ts +22 -22
  375. package/src/organization-model/domains/goals.ts +80 -80
  376. package/src/organization-model/domains/identity.ts +94 -94
  377. package/src/organization-model/domains/navigation.ts +391 -391
  378. package/src/organization-model/domains/offerings.ts +66 -66
  379. package/src/organization-model/domains/operations.ts +85 -85
  380. package/src/organization-model/domains/projects.ts +48 -48
  381. package/src/organization-model/domains/prospecting.ts +33 -33
  382. package/src/organization-model/domains/roles.ts +55 -55
  383. package/src/organization-model/domains/sales.ts +94 -94
  384. package/src/organization-model/domains/shared.ts +62 -62
  385. package/src/organization-model/domains/statuses.ts +130 -130
  386. package/src/organization-model/foundation.ts +97 -97
  387. package/src/organization-model/graph/build.ts +399 -399
  388. package/src/organization-model/graph/index.ts +4 -4
  389. package/src/organization-model/graph/schema.ts +48 -48
  390. package/src/organization-model/graph/types.ts +40 -40
  391. package/src/organization-model/index.ts +13 -13
  392. package/src/organization-model/organization-graph.mdx +272 -272
  393. package/src/organization-model/organization-model.mdx +320 -320
  394. package/src/organization-model/published.ts +85 -85
  395. package/src/organization-model/resolve.ts +66 -66
  396. package/src/organization-model/schema.ts +287 -287
  397. package/src/organization-model/types.ts +46 -46
  398. package/src/platform/api/index.ts +1 -1
  399. package/src/platform/api/types.ts +35 -35
  400. package/src/platform/constants/http.ts +37 -37
  401. package/src/platform/constants/index.ts +5 -5
  402. package/src/platform/constants/limits.ts +32 -32
  403. package/src/platform/constants/resilience.ts +51 -51
  404. package/src/platform/constants/timeouts.ts +20 -20
  405. package/src/platform/constants/versions.ts +3 -3
  406. package/src/platform/registry/__tests__/resource-registry-static.test.ts +347 -347
  407. package/src/platform/registry/__tests__/resource-registry.integration.test.ts +1028 -1028
  408. package/src/platform/registry/__tests__/resource-registry.list-executable.test.ts +393 -393
  409. package/src/platform/registry/__tests__/resource-registry.test.ts +2005 -2005
  410. package/src/platform/registry/__tests__/serialization.test.ts +1127 -1127
  411. package/src/platform/registry/command-view.ts +180 -180
  412. package/src/platform/registry/domains.ts +165 -165
  413. package/src/platform/registry/index.ts +93 -93
  414. package/src/platform/registry/reserved.ts +24 -24
  415. package/src/platform/registry/resource-metadata.ts +59 -59
  416. package/src/platform/registry/resource-registry.command-queue-groups.test.ts +129 -129
  417. package/src/platform/registry/resource-registry.ts +876 -876
  418. package/src/platform/registry/serialization.ts +273 -273
  419. package/src/platform/registry/serialized-types.ts +231 -231
  420. package/src/platform/registry/stats-types.ts +66 -66
  421. package/src/platform/registry/types.ts +404 -404
  422. package/src/platform/registry/validation.ts +513 -513
  423. package/src/platform/resilience/__tests__/rate-limiter.test.ts +471 -471
  424. package/src/platform/resilience/circuit-breaker.ts +164 -164
  425. package/src/platform/resilience/errors.ts +68 -68
  426. package/src/platform/resilience/http-error-mapper.ts +129 -129
  427. package/src/platform/resilience/index.ts +93 -93
  428. package/src/platform/resilience/rate-limiter-types.ts +46 -46
  429. package/src/platform/resilience/rate-limiter.ts +140 -140
  430. package/src/platform/resilience/retry.ts +89 -89
  431. package/src/platform/resilience/timeout.ts +63 -63
  432. package/src/platform/sse/events.ts +37 -37
  433. package/src/platform/sse/index.ts +7 -7
  434. package/src/platform/utils/__tests__/validation.test.ts +1083 -1083
  435. package/src/platform/utils/currency.ts +96 -96
  436. package/src/platform/utils/debounce.ts +52 -52
  437. package/src/platform/utils/error.ts +41 -41
  438. package/src/platform/utils/hmac.test.ts +97 -97
  439. package/src/platform/utils/index.ts +32 -32
  440. package/src/platform/utils/server/betterstack-logger.ts +210 -210
  441. package/src/platform/utils/server/hmac.ts +44 -44
  442. package/src/platform/utils/server/unsubscribe.ts +111 -111
  443. package/src/platform/utils/token-counter.ts +96 -96
  444. package/src/platform/utils/validation.ts +425 -425
  445. package/src/projects/api-schemas.ts +268 -268
  446. package/src/published.ts +1 -1
  447. package/src/reference/_generated/contracts.md +607 -607
  448. package/src/reference/glossary.md +105 -105
  449. package/src/requests/__tests__/api-schemas.test.ts +277 -277
  450. package/src/requests/api-schemas.ts +83 -83
  451. package/src/requests/index.ts +1 -1
  452. package/src/scaffold-registry/__tests__/index.test.ts +17 -0
  453. package/src/scaffold-registry/__tests__/schema.test.ts +329 -230
  454. package/src/scaffold-registry/index.ts +205 -189
  455. package/src/scaffold-registry/schema.ts +196 -128
  456. package/src/server.ts +272 -272
  457. package/src/supabase/database.types.ts +2719 -2719
  458. package/src/supabase/helpers.ts +20 -20
  459. package/src/supabase/index.ts +52 -52
  460. package/src/supabase/server/client.ts +58 -58
  461. package/src/test-utils/README.md +38 -38
  462. package/src/test-utils/browser-mocks.ts +54 -54
  463. package/src/test-utils/fixtures/api-keys.ts +52 -52
  464. package/src/test-utils/fixtures/index.ts +4 -4
  465. package/src/test-utils/fixtures/memberships.ts +80 -80
  466. package/src/test-utils/fixtures/organizations.ts +69 -69
  467. package/src/test-utils/fixtures/users.ts +79 -79
  468. package/src/test-utils/index.ts +11 -11
  469. package/src/test-utils/mocks/index.ts +2 -2
  470. package/src/test-utils/mocks/supabase.ts +142 -142
  471. package/src/test-utils/mocks/workos.ts +108 -108
  472. package/src/test-utils/rls/RLSTestContext.ts +556 -556
  473. package/src/test-utils/rls/index.ts +1 -1
@@ -1,1473 +1,1473 @@
1
- import { z } from 'zod'
2
- import { createIntegrationTool } from '../../../tool'
3
- import type { Tool } from '../../../../types'
4
-
5
- /**
6
- * Create Instantly send reply tool
7
- *
8
- * Sends a reply to an email thread maintaining proper threading.
9
- *
10
- * @param credentialName - Name of credential in credentials table
11
- * @returns Tool that sends email replies via Instantly
12
- *
13
- * @example
14
- * const sendReply = createInstantlySendReplyTool('instantly-elevasis')
15
- */
16
- export function createInstantlySendReplyTool(credentialName: string): Tool {
17
- return createIntegrationTool({
18
- name: 'instantly_send_reply',
19
- description: `Send a reply to an email thread via Instantly.ai
20
-
21
- USE CASES:
22
- - Send a personalized reply to a prospect who responded to your outreach campaign
23
- - Maintain email threading for organized conversations
24
- - Schedule replies for future delivery
25
-
26
- REQUIRED PARAMETERS:
27
- - eaccount: Email account that will send the reply (must be connected to workspace)
28
- - reply_to_uuid: UUID of the email you are replying to (from webhook payload)
29
- - subject: Subject line of the reply (typically "Re: Original Subject")
30
- - body: Email body (must provide either text or html)
31
-
32
- OPTIONAL PARAMETERS:
33
- - timestamp: ISO timestamp to schedule reply for future
34
-
35
- EXAMPLE:
36
- {
37
- "eaccount": "alex@elevasis.com",
38
- "reply_to_uuid": "123e4567-e89b-12d3-a456-426614174000",
39
- "subject": "Re: Automate your client acquisition",
40
- "body": {
41
- "text": "Thanks for your interest! Here's my calendar: https://calendly.com/..."
42
- }
43
- }
44
-
45
- OUTPUT:
46
- {
47
- "success": true,
48
- "email_id": "email-abc123",
49
- "thread_id": "thread-xyz789",
50
- "sent_at": "2025-12-22T14:30:00Z"
51
- }`,
52
-
53
- inputSchema: z.object({
54
- eaccount: z.string().describe('Email account that will send the reply (must be connected to workspace)'),
55
- reply_to_uuid: z.string().describe('UUID of the email you are replying to (from webhook payload)'),
56
- subject: z.string().describe('Subject line of the reply (typically "Re: Original Subject")'),
57
- body: z
58
- .object({
59
- text: z.string().optional().describe('Plain text email body'),
60
- html: z.string().optional().describe('HTML email body')
61
- })
62
- .refine((data) => data.text || data.html, {
63
- message: 'Must provide either text or html body'
64
- }),
65
- timestamp: z.string().optional().describe('ISO timestamp to schedule reply for future (optional)')
66
- }),
67
-
68
- outputSchema: z.object({
69
- success: z.boolean().describe('Whether reply was sent successfully'),
70
- email_id: z.string().describe('ID of the sent email'),
71
- thread_id: z.string().describe('Thread ID for conversation tracking'),
72
- sent_at: z.string().describe('Timestamp when email was sent')
73
- }),
74
-
75
- integration: 'instantly' as const,
76
- method: 'sendReply' as const,
77
- credentialName
78
- })
79
- }
80
-
81
- /**
82
- * Create Instantly remove from subsequence tool
83
- *
84
- * Removes a lead from a campaign sequence to stop further outreach.
85
- *
86
- * @param credentialName - Name of credential in credentials table
87
- * @returns Tool that removes leads from campaigns
88
- *
89
- * @example
90
- * const removeFromCampaign = createInstantlyRemoveFromSubsequenceTool('instantly-elevasis')
91
- */
92
- export function createInstantlyRemoveFromSubsequenceTool(credentialName: string): Tool {
93
- return createIntegrationTool({
94
- name: 'instantly_remove_from_subsequence',
95
- description: `Remove a lead from an Instantly campaign subsequence
96
-
97
- USE CASES:
98
- - Stop a lead from receiving further emails in a campaign
99
- - Use after positive reply, hard-no, or disqualification
100
- - Prevent over-emailing engaged prospects
101
-
102
- REQUIRED PARAMETERS:
103
- - lead_email: Email address of the lead to remove
104
- - campaign_id: Campaign ID to remove lead from
105
-
106
- EXAMPLE:
107
- {
108
- "lead_email": "prospect@agency.com",
109
- "campaign_id": "campaign-123"
110
- }
111
-
112
- OUTPUT:
113
- {
114
- "success": true,
115
- "lead_email": "prospect@agency.com",
116
- "campaign_id": "campaign-123"
117
- }`,
118
-
119
- inputSchema: z.object({
120
- lead_email: z.string().email().describe('Email address of the lead to remove'),
121
- campaign_id: z.string().describe('Campaign ID to remove lead from')
122
- }),
123
-
124
- outputSchema: z.object({
125
- success: z.boolean().describe('Whether removal was successful'),
126
- lead_email: z.string().describe('Email of the removed lead'),
127
- campaign_id: z.string().describe('Campaign ID lead was removed from')
128
- }),
129
-
130
- integration: 'instantly' as const,
131
- method: 'removeFromSubsequence' as const,
132
- credentialName
133
- })
134
- }
135
-
136
- /**
137
- * Create Instantly get emails tool
138
- *
139
- * Fetches email data from Instantly workspace with optional filtering and pagination.
140
- *
141
- * @param credentialName - Name of credential in credentials table
142
- * @returns Tool that retrieves email data
143
- */
144
- export function createInstantlyGetEmailsTool(credentialName: string): Tool {
145
- return createIntegrationTool({
146
- name: 'instantly_get_emails',
147
- description: `Get emails from Instantly workspace
148
-
149
- USE CASES:
150
- - Fetch a specific email by ID for reply processing
151
- - Retrieve full email threads by thread ID
152
- - Filter emails by campaign, lead, or type
153
- - List recent emails with cursor pagination
154
-
155
- OPTIONAL PARAMETERS:
156
- - email_id: Specific email ID to fetch (returns single email)
157
- - search: Email address OR "thread:{thread_id}" for thread retrieval
158
- - campaign_id: Filter by campaign UUID
159
- - lead: Filter by lead email address
160
- - email_type: Filter by type (received, sent, manual)
161
- - eaccount: Filter by sending account (comma-separated)
162
- - sort_order: Sort by creation date (asc, desc; default: desc)
163
- - preview_only: Return preview only (lighter response)
164
- - is_unread: Filter by unread status
165
- - limit: Items per page (1-100)
166
- - starting_after: Cursor for pagination (from next_starting_after in previous response)
167
-
168
- EXAMPLE (Single Email):
169
- {
170
- "email_id": "email-abc123"
171
- }
172
-
173
- EXAMPLE (Thread Retrieval):
174
- {
175
- "search": "thread:019a449c-f57a-73b2-91b5-75537ca85008",
176
- "sort_order": "asc",
177
- "limit": 50
178
- }
179
-
180
- EXAMPLE (Lead Emails in Campaign):
181
- {
182
- "lead": "jondoe@example.com",
183
- "campaign_id": "019a449c-f57a-73b2-91b5-754f1fca9f44",
184
- "sort_order": "asc"
185
- }
186
-
187
- OUTPUT:
188
- {
189
- "emails": [...email data...],
190
- "total_count": 3,
191
- "next_starting_after": "cursor-token-or-undefined"
192
- }`,
193
-
194
- inputSchema: z.object({
195
- email_id: z.string().optional().describe('Specific email ID to fetch'),
196
- search: z
197
- .string()
198
- .optional()
199
- .describe('Search query: email address or "thread:{thread_id}" for thread retrieval'),
200
- campaign_id: z.string().optional().describe('Filter by campaign UUID'),
201
- lead: z.string().optional().describe('Filter by lead email address'),
202
- email_type: z.enum(['received', 'sent', 'manual']).optional().describe('Filter by email type'),
203
- eaccount: z.string().optional().describe('Filter by sending account (comma-separated)'),
204
- sort_order: z.enum(['asc', 'desc']).optional().describe('Sort order by creation date (default: desc)'),
205
- preview_only: z.boolean().optional().describe('Return preview only (lighter response)'),
206
- is_unread: z.boolean().optional().describe('Filter by unread status'),
207
- limit: z.number().min(1).max(100).optional().describe('Items per page (1-100)'),
208
- starting_after: z.string().optional().describe('Cursor for pagination (from next_starting_after)')
209
- }),
210
-
211
- outputSchema: z.object({
212
- emails: z.array(z.unknown()).describe('Array of email data'),
213
- total_count: z.number().describe('Count of emails returned'),
214
- next_starting_after: z.string().optional().describe('Cursor for next page (undefined = no more)')
215
- }),
216
-
217
- integration: 'instantly' as const,
218
- method: 'getEmails' as const,
219
- credentialName
220
- })
221
- }
222
-
223
- /**
224
- * Create Instantly update interest status tool
225
- *
226
- * Updates the interest status of a lead, which can stop email sequences,
227
- * mark leads as interested, or reset to default status.
228
- *
229
- * @param credentialName - Name of credential in credentials table
230
- * @returns Tool that updates lead interest status
231
- *
232
- * @example
233
- * const updateStatus = createInstantlyUpdateInterestStatusTool('instantly-elevasis')
234
- */
235
- export function createInstantlyUpdateInterestStatusTool(credentialName: string): Tool {
236
- return createIntegrationTool({
237
- name: 'instantly_update_interest_status',
238
- description: `Update interest status of a lead in Instantly
239
-
240
- USE CASES:
241
- - Stop email sequence for leads who reply with "unsubscribe" or "not interested" (set interest_value: -1)
242
- - Mark engaged leads as interested for prioritization (set interest_value: 1)
243
- - Reset lead status back to default (set interest_value: 0)
244
- - Comply with opt-out requests to protect sender reputation
245
-
246
- INTEREST VALUES:
247
- - 1: Interested - Marks lead as interested
248
- - 0: Lead (default) - Resets to default status
249
- - -1: Not Interested - STOPS sequence (no more emails sent)
250
-
251
- REQUIRED PARAMETERS:
252
- - lead_email: Email address of the lead
253
- - interest_value: Status value (1, 0, or -1)
254
-
255
- OPTIONAL PARAMETERS:
256
- - campaign_id: Limit status update to specific campaign (UUID)
257
- - disable_auto_interest: Disable AI auto-tagging for this lead
258
-
259
- EXAMPLE (Stop Sequence):
260
- {
261
- "lead_email": "prospect@agency.com",
262
- "interest_value": -1
263
- }
264
-
265
- EXAMPLE (Mark Interested in Specific Campaign):
266
- {
267
- "lead_email": "prospect@agency.com",
268
- "interest_value": 1,
269
- "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43"
270
- }
271
-
272
- OUTPUT:
273
- {
274
- "success": true,
275
- "lead_email": "prospect@agency.com"
276
- }`,
277
-
278
- inputSchema: z.object({
279
- lead_email: z.string().email().describe('Email address of the lead'),
280
- interest_value: z
281
- .number()
282
- .int()
283
- .min(-1)
284
- .max(1)
285
- .describe('Interest status: 1 (interested), 0 (default), -1 (not interested - stops sequence)'),
286
- campaign_id: z.string().optional().describe('Campaign ID to limit status update to (UUID)'),
287
- disable_auto_interest: z.boolean().optional().describe('Disable AI auto-tagging for this lead')
288
- }),
289
-
290
- outputSchema: z.object({
291
- success: z.boolean().describe('Whether status update was successful'),
292
- lead_email: z.string().describe('Email of the updated lead')
293
- }),
294
-
295
- integration: 'instantly' as const,
296
- method: 'updateInterestStatus' as const,
297
- credentialName
298
- })
299
- }
300
-
301
- /**
302
- * Create Instantly add to campaign tool
303
- *
304
- * Adds leads to an Instantly campaign to begin the email sequence.
305
- *
306
- * @param credentialName - Name of credential in credentials table
307
- * @returns Tool that adds leads to a campaign
308
- *
309
- * @example
310
- * const addToCampaign = createInstantlyAddToCampaignTool('instantly-elevasis')
311
- */
312
- export function createInstantlyAddToCampaignTool(credentialName: string): Tool {
313
- return createIntegrationTool({
314
- name: 'instantly_add_to_campaign',
315
- description: `Add leads to an Instantly campaign
316
-
317
- USE CASES:
318
- - Add interested leads to a follow-up campaign after initial outreach
319
- - Start a drip sequence for leads who requested more information
320
- - Enroll new leads into automated nurture campaigns
321
-
322
- REQUIRED PARAMETERS:
323
- - campaign_id: UUID of the Instantly campaign to add leads to
324
- - leads: Array of lead objects (at least one required)
325
-
326
- LEAD OBJECT FIELDS:
327
- - email: (required) Email address of the lead
328
- - first_name: (optional) First name for personalization
329
- - last_name: (optional) Last name for personalization
330
- - company_name: (optional) Company name for personalization
331
-
332
- IMPORTANT: When leads are added, they begin receiving the campaign sequence immediately.
333
- "Day 0" starts at the moment of addition.
334
-
335
- EXAMPLE:
336
- {
337
- "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43",
338
- "leads": [
339
- {
340
- "email": "prospect@agency.com",
341
- "first_name": "John",
342
- "last_name": "Smith",
343
- "company_name": "Acme Agency"
344
- }
345
- ]
346
- }
347
-
348
- OUTPUT:
349
- {
350
- "success": true,
351
- "added_count": 1,
352
- "errors": null
353
- }`,
354
-
355
- inputSchema: z.object({
356
- campaign_id: z.string().describe('UUID of the Instantly campaign to add leads to'),
357
- leads: z
358
- .array(
359
- z.object({
360
- email: z.string().email().describe('Email address of the lead'),
361
- first_name: z.string().optional().describe('First name for personalization'),
362
- last_name: z.string().optional().describe('Last name for personalization'),
363
- company_name: z.string().optional().describe('Company name for personalization')
364
- })
365
- )
366
- .min(1)
367
- .describe('Array of leads to add (at least one required)')
368
- }),
369
-
370
- outputSchema: z.object({
371
- success: z.boolean().describe('Whether leads were added successfully'),
372
- added_count: z.number().describe('Number of leads successfully added'),
373
- errors: z.array(z.string()).optional().describe('Array of error messages if any failures occurred')
374
- }),
375
-
376
- integration: 'instantly' as const,
377
- method: 'addToCampaign' as const,
378
- credentialName
379
- })
380
- }
381
-
382
- /**
383
- * Create Instantly list campaigns tool
384
- *
385
- * Lists all campaigns in the workspace with optional filtering and pagination.
386
- *
387
- * @param credentialName - Name of credential in credentials table
388
- * @returns Tool that lists Instantly campaigns
389
- *
390
- * @example
391
- * const listCampaigns = createInstantlyListCampaignsTool('instantly-elevasis')
392
- */
393
- export function createInstantlyListCampaignsTool(credentialName: string): Tool {
394
- return createIntegrationTool({
395
- name: 'instantly_list_campaigns',
396
- description: `List all campaigns in the Instantly workspace
397
-
398
- USE CASES:
399
- - Discover available campaigns before adding leads or fetching analytics
400
- - Filter campaigns by status to find active or paused campaigns
401
- - Search campaigns by name to locate a specific campaign ID
402
- - Paginate through large campaign lists using cursor-based pagination
403
-
404
- OPTIONAL PARAMETERS:
405
- - limit: Number of campaigns to return per page (default: 10)
406
- - starting_after: Cursor from previous response for pagination
407
- - status: Filter by campaign status (e.g. "active", "paused", "completed")
408
- - search: Search term to filter campaigns by name
409
-
410
- EXAMPLE (List Active Campaigns):
411
- {
412
- "status": "active",
413
- "limit": 20
414
- }
415
-
416
- EXAMPLE (Search by Name):
417
- {
418
- "search": "cold outreach Q1"
419
- }
420
-
421
- OUTPUT:
422
- {
423
- "campaigns": [
424
- {
425
- "id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43",
426
- "name": "Cold Outreach Q1",
427
- "status": "active",
428
- "created_at": "2025-01-15T09:00:00Z"
429
- }
430
- ],
431
- "next_starting_after": "cursor-token"
432
- }`,
433
-
434
- inputSchema: z.object({
435
- limit: z.number().min(1).max(100).optional().describe('Number of campaigns per page (default: 10)'),
436
- starting_after: z
437
- .string()
438
- .optional()
439
- .describe('Cursor for pagination (from next_starting_after in previous response)'),
440
- status: z.string().optional().describe('Filter by campaign status (e.g. "active", "paused", "completed")'),
441
- search: z.string().optional().describe('Search term to filter campaigns by name')
442
- }),
443
-
444
- outputSchema: z.object({
445
- campaigns: z
446
- .array(
447
- z.object({
448
- id: z.string().describe('Campaign UUID'),
449
- name: z.string().describe('Campaign name'),
450
- status: z.string().describe('Campaign status'),
451
- created_at: z.string().describe('Campaign creation timestamp')
452
- })
453
- )
454
- .describe('Array of campaigns'),
455
- next_starting_after: z.string().optional().describe('Cursor for next page (undefined = no more pages)')
456
- }),
457
-
458
- integration: 'instantly' as const,
459
- method: 'listCampaigns' as const,
460
- credentialName
461
- })
462
- }
463
-
464
- /**
465
- * Create Instantly get campaign tool
466
- *
467
- * Fetches full details for a single campaign including sequences and configuration.
468
- *
469
- * @param credentialName - Name of credential in credentials table
470
- * @returns Tool that retrieves a single Instantly campaign
471
- *
472
- * @example
473
- * const getCampaign = createInstantlyGetCampaignTool('instantly-elevasis')
474
- */
475
- export function createInstantlyGetCampaignTool(credentialName: string): Tool {
476
- return createIntegrationTool({
477
- name: 'instantly_get_campaign',
478
- description: `Get full details of a specific Instantly campaign
479
-
480
- USE CASES:
481
- - Inspect campaign sequences and step configurations before modifying
482
- - Verify campaign status before activating or pausing
483
- - Retrieve sending settings such as daily limits and reply handling
484
- - Confirm the campaign name and metadata before referencing in reports
485
-
486
- REQUIRED PARAMETERS:
487
- - campaign_id: UUID of the campaign to retrieve
488
-
489
- EXAMPLE:
490
- {
491
- "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43"
492
- }
493
-
494
- OUTPUT:
495
- {
496
- "id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43",
497
- "name": "Cold Outreach Q1",
498
- "status": "active",
499
- "sequences": [...],
500
- "created_at": "2025-01-15T09:00:00Z"
501
- }`,
502
-
503
- inputSchema: z.object({
504
- campaign_id: z.string().describe('UUID of the campaign to retrieve')
505
- }),
506
-
507
- outputSchema: z.object({
508
- id: z.string().describe('Campaign UUID'),
509
- name: z.string().describe('Campaign name'),
510
- status: z.string().describe('Campaign status'),
511
- sequences: z.array(z.unknown()).describe('Campaign sequence steps'),
512
- created_at: z.string().describe('Campaign creation timestamp')
513
- }),
514
-
515
- integration: 'instantly' as const,
516
- method: 'getCampaign' as const,
517
- credentialName
518
- })
519
- }
520
-
521
- /**
522
- * Create Instantly update campaign tool
523
- *
524
- * Partially updates a campaign's fields such as name, sequences, or sending limits.
525
- *
526
- * @param credentialName - Name of credential in credentials table
527
- * @returns Tool that updates an Instantly campaign
528
- *
529
- * @example
530
- * const updateCampaign = createInstantlyUpdateCampaignTool('instantly-elevasis')
531
- */
532
- export function createInstantlyUpdateCampaignTool(credentialName: string): Tool {
533
- return createIntegrationTool({
534
- name: 'instantly_update_campaign',
535
- description: `Update fields on an existing Instantly campaign
536
-
537
- USE CASES:
538
- - Rename a campaign to reflect updated targeting or messaging
539
- - Adjust the daily sending limit to control volume
540
- - Replace or edit campaign sequences and email steps
541
- - Toggle stop-on-reply to pause the sequence when a lead responds
542
-
543
- REQUIRED PARAMETERS:
544
- - campaign_id: UUID of the campaign to update
545
-
546
- OPTIONAL PARAMETERS (at least one must be provided):
547
- - name: New campaign name
548
- - sequences: Full replacement of campaign sequences (array of step objects)
549
- - daily_limit: Maximum emails to send per day
550
- - stop_on_reply: Whether to stop sending when a lead replies (true/false)
551
-
552
- EXAMPLE (Rename and Adjust Limit):
553
- {
554
- "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43",
555
- "name": "Cold Outreach Q2",
556
- "daily_limit": 50
557
- }
558
-
559
- OUTPUT:
560
- {
561
- "success": true,
562
- "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43"
563
- }`,
564
-
565
- inputSchema: z.object({
566
- campaign_id: z.string().describe('UUID of the campaign to update'),
567
- name: z.string().optional().describe('New campaign name'),
568
- sequences: z.array(z.unknown()).optional().describe('Replacement campaign sequences (array of step objects)'),
569
- daily_limit: z.number().int().min(1).optional().describe('Maximum emails to send per day'),
570
- stop_on_reply: z.boolean().optional().describe('Whether to stop the sequence when a lead replies')
571
- }),
572
-
573
- outputSchema: z.object({
574
- success: z.boolean().describe('Whether the update was successful'),
575
- campaign_id: z.string().describe('UUID of the updated campaign')
576
- }),
577
-
578
- integration: 'instantly' as const,
579
- method: 'updateCampaign' as const,
580
- credentialName
581
- })
582
- }
583
-
584
- /**
585
- * Create Instantly pause campaign tool
586
- *
587
- * Pauses an active campaign to stop email sends until reactivated.
588
- *
589
- * @param credentialName - Name of credential in credentials table
590
- * @returns Tool that pauses an Instantly campaign
591
- *
592
- * @example
593
- * const pauseCampaign = createInstantlyPauseCampaignTool('instantly-elevasis')
594
- */
595
- export function createInstantlyPauseCampaignTool(credentialName: string): Tool {
596
- return createIntegrationTool({
597
- name: 'instantly_pause_campaign',
598
- description: `Pause an active Instantly campaign
599
-
600
- USE CASES:
601
- - Temporarily halt outreach while reviewing campaign performance
602
- - Pause before making sequence edits to avoid sending stale content
603
- - Stop sends during public holidays or blackout periods
604
- - Hold sends when a domain reputation issue is detected
605
-
606
- REQUIRED PARAMETERS:
607
- - campaign_id: UUID of the campaign to pause
608
-
609
- EXAMPLE:
610
- {
611
- "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43"
612
- }
613
-
614
- OUTPUT:
615
- {
616
- "success": true,
617
- "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43"
618
- }`,
619
-
620
- inputSchema: z.object({
621
- campaign_id: z.string().describe('UUID of the campaign to pause')
622
- }),
623
-
624
- outputSchema: z.object({
625
- success: z.boolean().describe('Whether the campaign was paused successfully'),
626
- campaign_id: z.string().describe('UUID of the paused campaign')
627
- }),
628
-
629
- integration: 'instantly' as const,
630
- method: 'pauseCampaign' as const,
631
- credentialName
632
- })
633
- }
634
-
635
- /**
636
- * Create Instantly delete campaign tool
637
- *
638
- * Permanently deletes a campaign and all associated data.
639
- *
640
- * @param credentialName - Name of credential in credentials table
641
- * @returns Tool that deletes an Instantly campaign
642
- *
643
- * @example
644
- * const deleteCampaign = createInstantlyDeleteCampaignTool('instantly-elevasis')
645
- */
646
- export function createInstantlyDeleteCampaignTool(credentialName: string): Tool {
647
- return createIntegrationTool({
648
- name: 'instantly_delete_campaign',
649
- description: `Permanently delete an Instantly campaign
650
-
651
- USE CASES:
652
- - Clean up test or draft campaigns after diagnostic runs
653
- - Remove campaigns that are no longer needed
654
- - Delete accidentally created campaigns
655
-
656
- REQUIRED PARAMETERS:
657
- - campaign_id: UUID of the campaign to delete
658
-
659
- EXAMPLE:
660
- {
661
- "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43"
662
- }
663
-
664
- OUTPUT:
665
- {
666
- "success": true,
667
- "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43"
668
- }`,
669
-
670
- inputSchema: z.object({
671
- campaign_id: z.string().describe('UUID of the campaign to delete')
672
- }),
673
-
674
- outputSchema: z.object({
675
- success: z.boolean().describe('Whether the campaign was deleted successfully'),
676
- campaign_id: z.string().describe('UUID of the deleted campaign')
677
- }),
678
-
679
- integration: 'instantly' as const,
680
- method: 'deleteCampaign' as const,
681
- credentialName
682
- })
683
- }
684
-
685
- /**
686
- * Create Instantly activate campaign tool
687
- *
688
- * Activates or resumes a paused or draft campaign to begin sending.
689
- *
690
- * @param credentialName - Name of credential in credentials table
691
- * @returns Tool that activates an Instantly campaign
692
- *
693
- * @example
694
- * const activateCampaign = createInstantlyActivateCampaignTool('instantly-elevasis')
695
- */
696
- export function createInstantlyActivateCampaignTool(credentialName: string): Tool {
697
- return createIntegrationTool({
698
- name: 'instantly_activate_campaign',
699
- description: `Activate or resume an Instantly campaign
700
-
701
- USE CASES:
702
- - Launch a newly created campaign to begin sending to enrolled leads
703
- - Resume a paused campaign after completing edits or reviews
704
- - Re-activate a campaign after resolving domain reputation issues
705
- - Start scheduled outreach at the beginning of a new period
706
-
707
- REQUIRED PARAMETERS:
708
- - campaign_id: UUID of the campaign to activate
709
-
710
- EXAMPLE:
711
- {
712
- "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43"
713
- }
714
-
715
- OUTPUT:
716
- {
717
- "success": true,
718
- "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43"
719
- }`,
720
-
721
- inputSchema: z.object({
722
- campaign_id: z.string().describe('UUID of the campaign to activate')
723
- }),
724
-
725
- outputSchema: z.object({
726
- success: z.boolean().describe('Whether the campaign was activated successfully'),
727
- campaign_id: z.string().describe('UUID of the activated campaign')
728
- }),
729
-
730
- integration: 'instantly' as const,
731
- method: 'activateCampaign' as const,
732
- credentialName
733
- })
734
- }
735
-
736
- /**
737
- * Create Instantly get campaign analytics tool
738
- *
739
- * Retrieves aggregate engagement statistics for a campaign.
740
- *
741
- * @param credentialName - Name of credential in credentials table
742
- * @returns Tool that fetches campaign-level analytics
743
- *
744
- * @example
745
- * const getAnalytics = createInstantlyGetCampaignAnalyticsTool('instantly-elevasis')
746
- */
747
- export function createInstantlyGetCampaignAnalyticsTool(credentialName: string): Tool {
748
- return createIntegrationTool({
749
- name: 'instantly_get_campaign_analytics',
750
- description: `Get aggregate analytics for an Instantly campaign
751
-
752
- USE CASES:
753
- - Review overall campaign performance including open rate, reply rate, and bounce rate
754
- - Compare send volume against replies to evaluate outreach effectiveness
755
- - Monitor unsubscribes to maintain sender reputation
756
- - Scope analytics to a date range for period-specific reporting
757
-
758
- REQUIRED PARAMETERS:
759
- - campaign_id: UUID of the campaign
760
-
761
- OPTIONAL PARAMETERS:
762
- - start_date: ISO date string to filter analytics from (e.g. "2025-01-01")
763
- - end_date: ISO date string to filter analytics to (e.g. "2025-03-31")
764
-
765
- EXAMPLE:
766
- {
767
- "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43",
768
- "start_date": "2025-01-01",
769
- "end_date": "2025-03-31"
770
- }
771
-
772
- OUTPUT:
773
- {
774
- "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43",
775
- "sent": 450,
776
- "opened": 180,
777
- "unique_opened": 160,
778
- "replied": 35,
779
- "unique_replied": 30,
780
- "bounced": 5,
781
- "unsubscribed": 2
782
- }`,
783
-
784
- inputSchema: z.object({
785
- campaign_id: z.string().describe('UUID of the campaign to fetch analytics for'),
786
- start_date: z.string().optional().describe('Start date for analytics range (ISO date string, e.g. "2025-01-01")'),
787
- end_date: z.string().optional().describe('End date for analytics range (ISO date string, e.g. "2025-03-31")')
788
- }),
789
-
790
- outputSchema: z.object({
791
- campaign_id: z.string().describe('Campaign UUID'),
792
- sent: z.number().describe('Total emails sent'),
793
- opened: z.number().describe('Total open events'),
794
- unique_opened: z.number().describe('Unique leads who opened'),
795
- replied: z.number().describe('Total reply events'),
796
- unique_replied: z.number().describe('Unique leads who replied'),
797
- bounced: z.number().describe('Total bounced emails'),
798
- unsubscribed: z.number().describe('Total unsubscribes')
799
- }),
800
-
801
- integration: 'instantly' as const,
802
- method: 'getCampaignAnalytics' as const,
803
- credentialName
804
- })
805
- }
806
-
807
- /**
808
- * Create Instantly get step analytics tool
809
- *
810
- * Retrieves per-step and per-variant analytics for a campaign sequence.
811
- *
812
- * @param credentialName - Name of credential in credentials table
813
- * @returns Tool that fetches step-level analytics
814
- *
815
- * @example
816
- * const getStepAnalytics = createInstantlyGetStepAnalyticsTool('instantly-elevasis')
817
- */
818
- export function createInstantlyGetStepAnalyticsTool(credentialName: string): Tool {
819
- return createIntegrationTool({
820
- name: 'instantly_get_step_analytics',
821
- description: `Get per-step and per-variant analytics for an Instantly campaign
822
-
823
- USE CASES:
824
- - Identify which sequence step has the highest reply rate
825
- - Compare A/B subject line variants to determine the winning version
826
- - Diagnose a drop-off point where prospects stop engaging
827
- - Optimize multi-step sequences based on step-level performance data
828
-
829
- REQUIRED PARAMETERS:
830
- - campaign_id: UUID of the campaign
831
-
832
- EXAMPLE:
833
- {
834
- "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43"
835
- }
836
-
837
- OUTPUT:
838
- {
839
- "steps": [
840
- {
841
- "step": "1",
842
- "variant": "A",
843
- "sent": 200,
844
- "opened": 90,
845
- "unique_opened": 80,
846
- "replies": 20,
847
- "unique_replies": 18
848
- },
849
- {
850
- "step": "2",
851
- "variant": "A",
852
- "sent": 160,
853
- "opened": 55,
854
- "unique_opened": 50,
855
- "replies": 10,
856
- "unique_replies": 9
857
- }
858
- ]
859
- }`,
860
-
861
- inputSchema: z.object({
862
- campaign_id: z.string().describe('UUID of the campaign to fetch step analytics for')
863
- }),
864
-
865
- outputSchema: z.object({
866
- steps: z
867
- .array(
868
- z.object({
869
- step: z.string().describe('Step number in the sequence'),
870
- variant: z.string().describe('Variant label (e.g. "A", "B")'),
871
- sent: z.number().describe('Emails sent for this step/variant'),
872
- opened: z.number().describe('Total open events'),
873
- unique_opened: z.number().describe('Unique leads who opened'),
874
- replies: z.number().describe('Total reply events'),
875
- unique_replies: z.number().describe('Unique leads who replied')
876
- })
877
- )
878
- .describe('Per-step, per-variant analytics entries')
879
- }),
880
-
881
- integration: 'instantly' as const,
882
- method: 'getStepAnalytics' as const,
883
- credentialName
884
- })
885
- }
886
-
887
- /**
888
- * Create Instantly bulk add leads tool
889
- *
890
- * Adds up to 1000 leads to a campaign in a single request.
891
- *
892
- * @param credentialName - Name of credential in credentials table
893
- * @returns Tool that bulk-uploads leads to an Instantly campaign
894
- *
895
- * @example
896
- * const bulkAddLeads = createInstantlyBulkAddLeadsTool('instantly-elevasis')
897
- */
898
- export function createInstantlyBulkAddLeadsTool(credentialName: string): Tool {
899
- return createIntegrationTool({
900
- name: 'instantly_bulk_add_leads',
901
- description: `Bulk upload up to 1000 leads to an Instantly campaign
902
-
903
- USE CASES:
904
- - Import a large list of qualified prospects into a campaign at once
905
- - Enroll leads exported from a CRM or enrichment tool into outreach
906
- - Upload leads with custom variables for deep personalization
907
- - Add leads with website and company data for context-aware sequences
908
-
909
- REQUIRED PARAMETERS:
910
- - campaign_id: UUID of the campaign to add leads to
911
- - leads: Array of lead objects (1–1000 leads)
912
-
913
- LEAD OBJECT FIELDS:
914
- - email: (required) Email address of the lead
915
- - first_name: (optional) First name for personalization
916
- - last_name: (optional) Last name for personalization
917
- - company_name: (optional) Company name for personalization
918
- - website: (optional) Company website URL
919
- - custom_variables: (optional) Key-value map of custom merge fields
920
-
921
- EXAMPLE:
922
- {
923
- "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43",
924
- "leads": [
925
- {
926
- "email": "ceo@agency.com",
927
- "first_name": "Sarah",
928
- "last_name": "Chen",
929
- "company_name": "Growth Agency",
930
- "website": "https://growthagency.com",
931
- "custom_variables": { "pain_point": "manual lead gen" }
932
- }
933
- ]
934
- }
935
-
936
- OUTPUT:
937
- {
938
- "success": true,
939
- "added_count": 1,
940
- "failed_count": 0
941
- }`,
942
-
943
- inputSchema: z.object({
944
- campaign_id: z.string().describe('UUID of the campaign to add leads to'),
945
- leads: z
946
- .array(
947
- z.object({
948
- email: z.string().email().describe('Email address of the lead'),
949
- first_name: z.string().optional().describe('First name for personalization'),
950
- last_name: z.string().optional().describe('Last name for personalization'),
951
- company_name: z.string().optional().describe('Company name for personalization'),
952
- website: z.string().optional().describe('Company website URL'),
953
- custom_variables: z
954
- .record(z.string(), z.string())
955
- .optional()
956
- .describe('Key-value map of custom merge field values')
957
- })
958
- )
959
- .min(1)
960
- .max(1000)
961
- .describe('Array of leads to upload (1–1000)')
962
- }),
963
-
964
- outputSchema: z.object({
965
- success: z.boolean().describe('True if all leads were added without errors'),
966
- added_count: z.number().describe('Number of leads successfully added'),
967
- failed_count: z.number().describe('Number of leads that failed to add'),
968
- errors: z
969
- .array(
970
- z.object({
971
- email: z.string().describe('Email of the lead that failed'),
972
- error: z.string().describe('Error message for this lead')
973
- })
974
- )
975
- .optional()
976
- .describe('Per-lead error details when failures occurred')
977
- }),
978
-
979
- integration: 'instantly' as const,
980
- method: 'bulkAddLeads' as const,
981
- credentialName
982
- })
983
- }
984
-
985
- /**
986
- * Create Instantly get account health tool
987
- *
988
- * Lists email sending accounts with warmup status and health scores.
989
- *
990
- * @param credentialName - Name of credential in credentials table
991
- * @returns Tool that retrieves account health data
992
- *
993
- * @example
994
- * const getAccountHealth = createInstantlyGetAccountHealthTool('instantly-elevasis')
995
- */
996
- export function createInstantlyGetAccountHealthTool(credentialName: string): Tool {
997
- return createIntegrationTool({
998
- name: 'instantly_get_account_health',
999
- description: `List email accounts with health status and warmup information
1000
-
1001
- USE CASES:
1002
- - Audit all connected sending accounts before launching a campaign
1003
- - Identify accounts with low health scores that may cause deliverability issues
1004
- - Verify warmup status to ensure accounts are ready for full sending volume
1005
- - Monitor account portfolio health as part of regular sender hygiene checks
1006
-
1007
- OPTIONAL PARAMETERS:
1008
- - limit: Number of accounts to return per page
1009
- - starting_after: Cursor from previous response for pagination
1010
-
1011
- EXAMPLE:
1012
- {
1013
- "limit": 20
1014
- }
1015
-
1016
- OUTPUT:
1017
- {
1018
- "accounts": [
1019
- {
1020
- "id": "acct-abc123",
1021
- "email": "alex@elevasis.com",
1022
- "status": "active",
1023
- "warmup_enabled": true,
1024
- "health_score": 92
1025
- }
1026
- ],
1027
- "next_starting_after": "cursor-token"
1028
- }`,
1029
-
1030
- inputSchema: z.object({
1031
- limit: z.number().min(1).max(100).optional().describe('Number of accounts per page'),
1032
- starting_after: z
1033
- .string()
1034
- .optional()
1035
- .describe('Cursor for pagination (from next_starting_after in previous response)')
1036
- }),
1037
-
1038
- outputSchema: z.object({
1039
- accounts: z
1040
- .array(
1041
- z.object({
1042
- id: z.string().describe('Account ID'),
1043
- email: z.string().describe('Sending email address'),
1044
- status: z.string().describe('Account status'),
1045
- warmup_enabled: z.boolean().describe('Whether warmup is active for this account'),
1046
- health_score: z.number().optional().describe('Health score (0–100)')
1047
- })
1048
- )
1049
- .describe('Array of sending accounts with health data'),
1050
- next_starting_after: z.string().optional().describe('Cursor for next page (undefined = no more pages)')
1051
- }),
1052
-
1053
- integration: 'instantly' as const,
1054
- method: 'getAccountHealth' as const,
1055
- credentialName
1056
- })
1057
- }
1058
-
1059
- /**
1060
- * Create Instantly create campaign tool
1061
- *
1062
- * Creates a new campaign in Instantly with optional sequences and sending configuration.
1063
- *
1064
- * @param credentialName - Name of credential in credentials table
1065
- * @returns Tool that creates a new Instantly campaign
1066
- *
1067
- * @example
1068
- * const createCampaign = createInstantlyCreateCampaignTool('instantly-elevasis')
1069
- */
1070
- export function createInstantlyCreateCampaignTool(credentialName: string): Tool {
1071
- return createIntegrationTool({
1072
- name: 'instantly_create_campaign',
1073
- description: `Create a new Instantly campaign
1074
-
1075
- USE CASES:
1076
- - Set up a new cold outreach campaign with custom sequences
1077
- - Create a campaign with predefined email steps and A/B variants
1078
- - Configure sending limits and reply handling at creation time
1079
- - Prepare a campaign shell to be populated with leads and activated later
1080
-
1081
- REQUIRED PARAMETERS:
1082
- - name: Display name of the new campaign
1083
-
1084
- OPTIONAL PARAMETERS:
1085
- - sequences: Array of sequence objects with email steps and optional A/B variants
1086
- - email_list: Array of sending account emails to use for the campaign
1087
- - daily_limit: Maximum emails to send per day
1088
- - stop_on_reply: Whether to stop the sequence when a lead replies
1089
- - stop_on_auto_reply: Whether to stop on auto-replies
1090
- - track_opens: Whether to track email opens
1091
- - track_clicks: Whether to track link clicks
1092
- - text_only: Whether to send text-only emails (no HTML)
1093
-
1094
- EXAMPLE (Simple Campaign):
1095
- {
1096
- "name": "Cold Outreach Q2 2025",
1097
- "daily_limit": 50,
1098
- "stop_on_reply": true
1099
- }
1100
-
1101
- EXAMPLE (Campaign with Sequence):
1102
- {
1103
- "name": "Agency Outreach",
1104
- "sequences": [
1105
- {
1106
- "steps": [
1107
- {
1108
- "subject": "Quick question about {{company_name}}",
1109
- "body": "Hi {{first_name}}, I noticed..."
1110
- },
1111
- {
1112
- "subject": "Following up",
1113
- "body": "Hi {{first_name}}, just wanted to circle back..."
1114
- }
1115
- ]
1116
- }
1117
- ],
1118
- "daily_limit": 30,
1119
- "stop_on_reply": true
1120
- }
1121
-
1122
- OUTPUT:
1123
- {
1124
- "success": true,
1125
- "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43",
1126
- "name": "Cold Outreach Q2 2025"
1127
- }`,
1128
-
1129
- inputSchema: z.object({
1130
- name: z.string().describe('Display name of the new campaign'),
1131
- sequences: z
1132
- .array(
1133
- z.object({
1134
- steps: z.array(
1135
- z.object({
1136
- subject: z.string().describe('Email subject line for this step'),
1137
- body: z.string().describe('Email body for this step'),
1138
- variants: z
1139
- .array(
1140
- z.object({
1141
- subject: z.string().describe('A/B variant subject line'),
1142
- body: z.string().describe('A/B variant body')
1143
- })
1144
- )
1145
- .optional()
1146
- .describe('A/B test variants for this step')
1147
- })
1148
- )
1149
- })
1150
- )
1151
- .optional()
1152
- .describe('Campaign sequences with email steps'),
1153
- email_list: z.array(z.string()).optional().describe('Sending account emails to use for the campaign'),
1154
- daily_limit: z.number().int().min(1).optional().describe('Maximum emails to send per day'),
1155
- stop_on_reply: z.boolean().optional().describe('Whether to stop the sequence when a lead replies'),
1156
- stop_on_auto_reply: z.boolean().optional().describe('Whether to stop the sequence on auto-replies'),
1157
- track_opens: z.boolean().optional().describe('Whether to track email opens'),
1158
- track_clicks: z.boolean().optional().describe('Whether to track link clicks'),
1159
- text_only: z.boolean().optional().describe('Whether to send text-only emails (no HTML)')
1160
- }),
1161
-
1162
- outputSchema: z.object({
1163
- success: z.boolean().describe('Whether the campaign was created successfully'),
1164
- campaign_id: z.string().describe('UUID of the newly created campaign'),
1165
- name: z.string().describe('Name of the created campaign')
1166
- }),
1167
-
1168
- integration: 'instantly' as const,
1169
- method: 'createCampaign' as const,
1170
- credentialName
1171
- })
1172
- }
1173
-
1174
- /**
1175
- * Create Instantly create inbox test tool
1176
- *
1177
- * Initiates an inbox placement test to diagnose deliverability for a sending account.
1178
- *
1179
- * @param credentialName - Name of credential in credentials table
1180
- * @returns Tool that creates an Instantly inbox placement test
1181
- *
1182
- * @example
1183
- * const createInboxTest = createInstantlyCreateInboxTestTool('instantly-elevasis')
1184
- */
1185
- export function createInstantlyCreateInboxTestTool(credentialName: string): Tool {
1186
- return createIntegrationTool({
1187
- name: 'instantly_create_inbox_test',
1188
- description: `Create an inbox placement test for an Instantly sending account
1189
-
1190
- USE CASES:
1191
- - Verify deliverability before launching a high-volume campaign
1192
- - Diagnose spam filtering issues on a specific sending account
1193
- - Test whether custom subject lines land in inbox or spam
1194
- - Monitor placement across Gmail, Outlook, and other major providers
1195
-
1196
- REQUIRED PARAMETERS:
1197
- - email_account: The sending account to test (must be connected to workspace)
1198
-
1199
- OPTIONAL PARAMETERS:
1200
- - subject: Custom subject line to use in the test email
1201
- - body: Custom body text to use in the test email
1202
-
1203
- EXAMPLE:
1204
- {
1205
- "email_account": "alex@elevasis.com",
1206
- "subject": "Quick question about your agency",
1207
- "body": "Hi, I wanted to reach out about..."
1208
- }
1209
-
1210
- OUTPUT:
1211
- {
1212
- "success": true,
1213
- "test_id": "test-abc123",
1214
- "status": "pending"
1215
- }`,
1216
-
1217
- inputSchema: z.object({
1218
- email_account: z.string().describe('Sending account email address to test (must be connected to workspace)'),
1219
- subject: z.string().optional().describe('Custom subject line for the test email'),
1220
- body: z.string().optional().describe('Custom body text for the test email')
1221
- }),
1222
-
1223
- outputSchema: z.object({
1224
- success: z.boolean().describe('Whether the test was created successfully'),
1225
- test_id: z.string().describe('Unique ID of the inbox placement test'),
1226
- status: z.string().describe('Initial test status (e.g. "pending")')
1227
- }),
1228
-
1229
- integration: 'instantly' as const,
1230
- method: 'createInboxTest' as const,
1231
- credentialName
1232
- })
1233
- }
1234
-
1235
- /**
1236
- * Create Instantly get daily campaign analytics tool
1237
- *
1238
- * Retrieves day-by-day engagement breakdown for campaigns.
1239
- *
1240
- * @param credentialName - Name of credential in credentials table
1241
- * @returns Tool that fetches daily campaign analytics
1242
- *
1243
- * @example
1244
- * const getDailyAnalytics = createInstantlyGetDailyCampaignAnalyticsTool('instantly-elevasis')
1245
- */
1246
- export function createInstantlyGetDailyCampaignAnalyticsTool(credentialName: string): Tool {
1247
- return createIntegrationTool({
1248
- name: 'instantly_get_daily_campaign_analytics',
1249
- description: `Get day-by-day analytics breakdown for Instantly campaigns
1250
-
1251
- USE CASES:
1252
- - Analyze send and open trends over a date range to identify patterns
1253
- - Spot peak engagement days to optimize future send scheduling
1254
- - Compare daily click and reply volumes across a campaign period
1255
- - Get cross-campaign aggregate metrics when no campaign_id is specified
1256
-
1257
- OPTIONAL PARAMETERS:
1258
- - campaign_id: Filter analytics to a specific campaign UUID (omit for all campaigns)
1259
- - start_date: Start of date range (ISO date, e.g. "2025-01-01")
1260
- - end_date: End of date range (ISO date, e.g. "2025-03-31")
1261
-
1262
- EXAMPLE (Single Campaign):
1263
- {
1264
- "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43",
1265
- "start_date": "2025-01-01",
1266
- "end_date": "2025-01-31"
1267
- }
1268
-
1269
- EXAMPLE (All Campaigns):
1270
- {
1271
- "start_date": "2025-01-01",
1272
- "end_date": "2025-01-31"
1273
- }
1274
-
1275
- OUTPUT:
1276
- {
1277
- "data": [
1278
- {
1279
- "date": "2025-01-15",
1280
- "sent": 120,
1281
- "opened": 48,
1282
- "unique_opened": 42,
1283
- "replied": 8,
1284
- "unique_replied": 7,
1285
- "bounced": 1,
1286
- "clicks": 12,
1287
- "unique_clicks": 10
1288
- }
1289
- ]
1290
- }`,
1291
-
1292
- inputSchema: z.object({
1293
- campaign_id: z.string().optional().describe('Campaign UUID to filter analytics (omit to get all campaigns)'),
1294
- start_date: z.string().optional().describe('Start of date range (ISO date, e.g. "2025-01-01")'),
1295
- end_date: z.string().optional().describe('End of date range (ISO date, e.g. "2025-03-31")')
1296
- }),
1297
-
1298
- outputSchema: z.object({
1299
- data: z
1300
- .array(
1301
- z.object({
1302
- date: z.string().describe('Date (YYYY-MM-DD)'),
1303
- sent: z.number().describe('Emails sent on this date'),
1304
- opened: z.number().describe('Total open events'),
1305
- unique_opened: z.number().describe('Unique leads who opened'),
1306
- replied: z.number().describe('Total reply events'),
1307
- unique_replied: z.number().describe('Unique leads who replied'),
1308
- bounced: z.number().describe('Emails bounced'),
1309
- clicks: z.number().describe('Total link click events'),
1310
- unique_clicks: z.number().describe('Unique leads who clicked')
1311
- })
1312
- )
1313
- .describe('Array of daily analytics entries')
1314
- }),
1315
-
1316
- integration: 'instantly' as const,
1317
- method: 'getDailyCampaignAnalytics' as const,
1318
- credentialName
1319
- })
1320
- }
1321
-
1322
- /**
1323
- * Create Instantly list leads tool
1324
- *
1325
- * Lists leads with optional filtering by campaign or email and cursor pagination.
1326
- *
1327
- * @param credentialName - Name of credential in credentials table
1328
- * @returns Tool that lists Instantly leads
1329
- *
1330
- * @example
1331
- * const listLeads = createInstantlyListLeadsTool('instantly-elevasis')
1332
- */
1333
- export function createInstantlyListLeadsTool(credentialName: string): Tool {
1334
- return createIntegrationTool({
1335
- name: 'instantly_list_leads',
1336
- description: `List leads in Instantly with optional filtering and pagination
1337
-
1338
- USE CASES:
1339
- - Retrieve all leads enrolled in a specific campaign for auditing
1340
- - Look up a specific lead by email address to check their status
1341
- - Paginate through a large lead list using cursor-based pagination
1342
- - Review lead metadata including status, timestamps, and campaign assignment
1343
-
1344
- OPTIONAL PARAMETERS:
1345
- - campaign_id: Filter leads by campaign UUID
1346
- - email: Filter by specific lead email address
1347
- - limit: Number of leads per page
1348
- - starting_after: Cursor from previous response for pagination
1349
-
1350
- NOTE: This uses a POST endpoint per Instantly API design (complex filter arguments).
1351
-
1352
- EXAMPLE (Campaign Leads):
1353
- {
1354
- "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43",
1355
- "limit": 50
1356
- }
1357
-
1358
- EXAMPLE (Single Lead Lookup):
1359
- {
1360
- "email": "prospect@agency.com"
1361
- }
1362
-
1363
- OUTPUT:
1364
- {
1365
- "items": [
1366
- {
1367
- "id": "lead-abc123",
1368
- "email": "prospect@agency.com",
1369
- "first_name": "John",
1370
- "last_name": "Smith",
1371
- "company_name": "Acme Agency",
1372
- "status": "active",
1373
- "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43",
1374
- "timestamp_created": "2025-01-15T09:00:00Z"
1375
- }
1376
- ],
1377
- "next_starting_after": "cursor-token"
1378
- }`,
1379
-
1380
- inputSchema: z.object({
1381
- campaign_id: z.string().optional().describe('Filter leads by campaign UUID'),
1382
- email: z.string().optional().describe('Filter by specific lead email address'),
1383
- limit: z.number().min(1).max(100).optional().describe('Number of leads per page'),
1384
- starting_after: z
1385
- .string()
1386
- .optional()
1387
- .describe('Cursor for pagination (from next_starting_after in previous response)')
1388
- }),
1389
-
1390
- outputSchema: z.object({
1391
- items: z
1392
- .array(
1393
- z.object({
1394
- id: z.string().describe('Lead ID'),
1395
- email: z.string().describe('Lead email address'),
1396
- first_name: z.string().optional().describe('Lead first name'),
1397
- last_name: z.string().optional().describe('Lead last name'),
1398
- company_name: z.string().optional().describe('Lead company name'),
1399
- status: z.string().describe('Lead status in campaign'),
1400
- campaign_id: z.string().optional().describe('Campaign this lead belongs to'),
1401
- timestamp_created: z.string().optional().describe('Lead creation timestamp')
1402
- })
1403
- )
1404
- .describe('Array of leads'),
1405
- next_starting_after: z.string().optional().describe('Cursor for next page (undefined = no more pages)')
1406
- }),
1407
-
1408
- integration: 'instantly' as const,
1409
- method: 'listLeads' as const,
1410
- credentialName
1411
- })
1412
- }
1413
-
1414
- /**
1415
- * Create Instantly bulk delete leads tool
1416
- *
1417
- * Deletes leads in bulk by IDs, campaign, or list with an optional limit.
1418
- *
1419
- * @param credentialName - Name of credential in credentials table
1420
- * @returns Tool that bulk-deletes Instantly leads
1421
- *
1422
- * @example
1423
- * const bulkDeleteLeads = createInstantlyBulkDeleteLeadsTool('instantly-elevasis')
1424
- */
1425
- export function createInstantlyBulkDeleteLeadsTool(credentialName: string): Tool {
1426
- return createIntegrationTool({
1427
- name: 'instantly_bulk_delete_leads',
1428
- description: `Bulk delete leads from Instantly by IDs, campaign, or list
1429
-
1430
- USE CASES:
1431
- - Remove a batch of disqualified leads from a campaign at once
1432
- - Clean up leads from a completed campaign before archiving
1433
- - Delete leads from a specific list to maintain database hygiene
1434
- - Remove a set of specific leads by their IDs after a data audit
1435
-
1436
- OPTIONAL PARAMETERS (at least one filter recommended):
1437
- - ids: Array of specific lead IDs to delete
1438
- - campaign_id: Delete all leads from this campaign
1439
- - list_id: Delete all leads from this list
1440
- - limit: Maximum number of leads to delete in this operation (1-10000)
1441
-
1442
- EXAMPLE (Delete by IDs):
1443
- {
1444
- "ids": ["lead-abc123", "lead-def456"]
1445
- }
1446
-
1447
- EXAMPLE (Delete from Campaign):
1448
- {
1449
- "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43",
1450
- "limit": 100
1451
- }
1452
-
1453
- OUTPUT:
1454
- {
1455
- "deleted_count": 42
1456
- }`,
1457
-
1458
- inputSchema: z.object({
1459
- ids: z.array(z.string()).optional().describe('Specific lead IDs to delete'),
1460
- campaign_id: z.string().optional().describe('Delete leads from this campaign'),
1461
- list_id: z.string().optional().describe('Delete leads from this list'),
1462
- limit: z.number().int().min(1).optional().describe('Maximum number of leads to delete')
1463
- }),
1464
-
1465
- outputSchema: z.object({
1466
- deleted_count: z.number().describe('Number of leads deleted')
1467
- }),
1468
-
1469
- integration: 'instantly' as const,
1470
- method: 'bulkDeleteLeads' as const,
1471
- credentialName
1472
- })
1473
- }
1
+ import { z } from 'zod'
2
+ import { createIntegrationTool } from '../../../tool'
3
+ import type { Tool } from '../../../../types'
4
+
5
+ /**
6
+ * Create Instantly send reply tool
7
+ *
8
+ * Sends a reply to an email thread maintaining proper threading.
9
+ *
10
+ * @param credentialName - Name of credential in credentials table
11
+ * @returns Tool that sends email replies via Instantly
12
+ *
13
+ * @example
14
+ * const sendReply = createInstantlySendReplyTool('instantly-elevasis')
15
+ */
16
+ export function createInstantlySendReplyTool(credentialName: string): Tool {
17
+ return createIntegrationTool({
18
+ name: 'instantly_send_reply',
19
+ description: `Send a reply to an email thread via Instantly.ai
20
+
21
+ USE CASES:
22
+ - Send a personalized reply to a prospect who responded to your outreach campaign
23
+ - Maintain email threading for organized conversations
24
+ - Schedule replies for future delivery
25
+
26
+ REQUIRED PARAMETERS:
27
+ - eaccount: Email account that will send the reply (must be connected to workspace)
28
+ - reply_to_uuid: UUID of the email you are replying to (from webhook payload)
29
+ - subject: Subject line of the reply (typically "Re: Original Subject")
30
+ - body: Email body (must provide either text or html)
31
+
32
+ OPTIONAL PARAMETERS:
33
+ - timestamp: ISO timestamp to schedule reply for future
34
+
35
+ EXAMPLE:
36
+ {
37
+ "eaccount": "alex@elevasis.com",
38
+ "reply_to_uuid": "123e4567-e89b-12d3-a456-426614174000",
39
+ "subject": "Re: Automate your client acquisition",
40
+ "body": {
41
+ "text": "Thanks for your interest! Here's my calendar: https://calendly.com/..."
42
+ }
43
+ }
44
+
45
+ OUTPUT:
46
+ {
47
+ "success": true,
48
+ "email_id": "email-abc123",
49
+ "thread_id": "thread-xyz789",
50
+ "sent_at": "2025-12-22T14:30:00Z"
51
+ }`,
52
+
53
+ inputSchema: z.object({
54
+ eaccount: z.string().describe('Email account that will send the reply (must be connected to workspace)'),
55
+ reply_to_uuid: z.string().describe('UUID of the email you are replying to (from webhook payload)'),
56
+ subject: z.string().describe('Subject line of the reply (typically "Re: Original Subject")'),
57
+ body: z
58
+ .object({
59
+ text: z.string().optional().describe('Plain text email body'),
60
+ html: z.string().optional().describe('HTML email body')
61
+ })
62
+ .refine((data) => data.text || data.html, {
63
+ message: 'Must provide either text or html body'
64
+ }),
65
+ timestamp: z.string().optional().describe('ISO timestamp to schedule reply for future (optional)')
66
+ }),
67
+
68
+ outputSchema: z.object({
69
+ success: z.boolean().describe('Whether reply was sent successfully'),
70
+ email_id: z.string().describe('ID of the sent email'),
71
+ thread_id: z.string().describe('Thread ID for conversation tracking'),
72
+ sent_at: z.string().describe('Timestamp when email was sent')
73
+ }),
74
+
75
+ integration: 'instantly' as const,
76
+ method: 'sendReply' as const,
77
+ credentialName
78
+ })
79
+ }
80
+
81
+ /**
82
+ * Create Instantly remove from subsequence tool
83
+ *
84
+ * Removes a lead from a campaign sequence to stop further outreach.
85
+ *
86
+ * @param credentialName - Name of credential in credentials table
87
+ * @returns Tool that removes leads from campaigns
88
+ *
89
+ * @example
90
+ * const removeFromCampaign = createInstantlyRemoveFromSubsequenceTool('instantly-elevasis')
91
+ */
92
+ export function createInstantlyRemoveFromSubsequenceTool(credentialName: string): Tool {
93
+ return createIntegrationTool({
94
+ name: 'instantly_remove_from_subsequence',
95
+ description: `Remove a lead from an Instantly campaign subsequence
96
+
97
+ USE CASES:
98
+ - Stop a lead from receiving further emails in a campaign
99
+ - Use after positive reply, hard-no, or disqualification
100
+ - Prevent over-emailing engaged prospects
101
+
102
+ REQUIRED PARAMETERS:
103
+ - lead_email: Email address of the lead to remove
104
+ - campaign_id: Campaign ID to remove lead from
105
+
106
+ EXAMPLE:
107
+ {
108
+ "lead_email": "prospect@agency.com",
109
+ "campaign_id": "campaign-123"
110
+ }
111
+
112
+ OUTPUT:
113
+ {
114
+ "success": true,
115
+ "lead_email": "prospect@agency.com",
116
+ "campaign_id": "campaign-123"
117
+ }`,
118
+
119
+ inputSchema: z.object({
120
+ lead_email: z.string().email().describe('Email address of the lead to remove'),
121
+ campaign_id: z.string().describe('Campaign ID to remove lead from')
122
+ }),
123
+
124
+ outputSchema: z.object({
125
+ success: z.boolean().describe('Whether removal was successful'),
126
+ lead_email: z.string().describe('Email of the removed lead'),
127
+ campaign_id: z.string().describe('Campaign ID lead was removed from')
128
+ }),
129
+
130
+ integration: 'instantly' as const,
131
+ method: 'removeFromSubsequence' as const,
132
+ credentialName
133
+ })
134
+ }
135
+
136
+ /**
137
+ * Create Instantly get emails tool
138
+ *
139
+ * Fetches email data from Instantly workspace with optional filtering and pagination.
140
+ *
141
+ * @param credentialName - Name of credential in credentials table
142
+ * @returns Tool that retrieves email data
143
+ */
144
+ export function createInstantlyGetEmailsTool(credentialName: string): Tool {
145
+ return createIntegrationTool({
146
+ name: 'instantly_get_emails',
147
+ description: `Get emails from Instantly workspace
148
+
149
+ USE CASES:
150
+ - Fetch a specific email by ID for reply processing
151
+ - Retrieve full email threads by thread ID
152
+ - Filter emails by campaign, lead, or type
153
+ - List recent emails with cursor pagination
154
+
155
+ OPTIONAL PARAMETERS:
156
+ - email_id: Specific email ID to fetch (returns single email)
157
+ - search: Email address OR "thread:{thread_id}" for thread retrieval
158
+ - campaign_id: Filter by campaign UUID
159
+ - lead: Filter by lead email address
160
+ - email_type: Filter by type (received, sent, manual)
161
+ - eaccount: Filter by sending account (comma-separated)
162
+ - sort_order: Sort by creation date (asc, desc; default: desc)
163
+ - preview_only: Return preview only (lighter response)
164
+ - is_unread: Filter by unread status
165
+ - limit: Items per page (1-100)
166
+ - starting_after: Cursor for pagination (from next_starting_after in previous response)
167
+
168
+ EXAMPLE (Single Email):
169
+ {
170
+ "email_id": "email-abc123"
171
+ }
172
+
173
+ EXAMPLE (Thread Retrieval):
174
+ {
175
+ "search": "thread:019a449c-f57a-73b2-91b5-75537ca85008",
176
+ "sort_order": "asc",
177
+ "limit": 50
178
+ }
179
+
180
+ EXAMPLE (Lead Emails in Campaign):
181
+ {
182
+ "lead": "jondoe@example.com",
183
+ "campaign_id": "019a449c-f57a-73b2-91b5-754f1fca9f44",
184
+ "sort_order": "asc"
185
+ }
186
+
187
+ OUTPUT:
188
+ {
189
+ "emails": [...email data...],
190
+ "total_count": 3,
191
+ "next_starting_after": "cursor-token-or-undefined"
192
+ }`,
193
+
194
+ inputSchema: z.object({
195
+ email_id: z.string().optional().describe('Specific email ID to fetch'),
196
+ search: z
197
+ .string()
198
+ .optional()
199
+ .describe('Search query: email address or "thread:{thread_id}" for thread retrieval'),
200
+ campaign_id: z.string().optional().describe('Filter by campaign UUID'),
201
+ lead: z.string().optional().describe('Filter by lead email address'),
202
+ email_type: z.enum(['received', 'sent', 'manual']).optional().describe('Filter by email type'),
203
+ eaccount: z.string().optional().describe('Filter by sending account (comma-separated)'),
204
+ sort_order: z.enum(['asc', 'desc']).optional().describe('Sort order by creation date (default: desc)'),
205
+ preview_only: z.boolean().optional().describe('Return preview only (lighter response)'),
206
+ is_unread: z.boolean().optional().describe('Filter by unread status'),
207
+ limit: z.number().min(1).max(100).optional().describe('Items per page (1-100)'),
208
+ starting_after: z.string().optional().describe('Cursor for pagination (from next_starting_after)')
209
+ }),
210
+
211
+ outputSchema: z.object({
212
+ emails: z.array(z.unknown()).describe('Array of email data'),
213
+ total_count: z.number().describe('Count of emails returned'),
214
+ next_starting_after: z.string().optional().describe('Cursor for next page (undefined = no more)')
215
+ }),
216
+
217
+ integration: 'instantly' as const,
218
+ method: 'getEmails' as const,
219
+ credentialName
220
+ })
221
+ }
222
+
223
+ /**
224
+ * Create Instantly update interest status tool
225
+ *
226
+ * Updates the interest status of a lead, which can stop email sequences,
227
+ * mark leads as interested, or reset to default status.
228
+ *
229
+ * @param credentialName - Name of credential in credentials table
230
+ * @returns Tool that updates lead interest status
231
+ *
232
+ * @example
233
+ * const updateStatus = createInstantlyUpdateInterestStatusTool('instantly-elevasis')
234
+ */
235
+ export function createInstantlyUpdateInterestStatusTool(credentialName: string): Tool {
236
+ return createIntegrationTool({
237
+ name: 'instantly_update_interest_status',
238
+ description: `Update interest status of a lead in Instantly
239
+
240
+ USE CASES:
241
+ - Stop email sequence for leads who reply with "unsubscribe" or "not interested" (set interest_value: -1)
242
+ - Mark engaged leads as interested for prioritization (set interest_value: 1)
243
+ - Reset lead status back to default (set interest_value: 0)
244
+ - Comply with opt-out requests to protect sender reputation
245
+
246
+ INTEREST VALUES:
247
+ - 1: Interested - Marks lead as interested
248
+ - 0: Lead (default) - Resets to default status
249
+ - -1: Not Interested - STOPS sequence (no more emails sent)
250
+
251
+ REQUIRED PARAMETERS:
252
+ - lead_email: Email address of the lead
253
+ - interest_value: Status value (1, 0, or -1)
254
+
255
+ OPTIONAL PARAMETERS:
256
+ - campaign_id: Limit status update to specific campaign (UUID)
257
+ - disable_auto_interest: Disable AI auto-tagging for this lead
258
+
259
+ EXAMPLE (Stop Sequence):
260
+ {
261
+ "lead_email": "prospect@agency.com",
262
+ "interest_value": -1
263
+ }
264
+
265
+ EXAMPLE (Mark Interested in Specific Campaign):
266
+ {
267
+ "lead_email": "prospect@agency.com",
268
+ "interest_value": 1,
269
+ "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43"
270
+ }
271
+
272
+ OUTPUT:
273
+ {
274
+ "success": true,
275
+ "lead_email": "prospect@agency.com"
276
+ }`,
277
+
278
+ inputSchema: z.object({
279
+ lead_email: z.string().email().describe('Email address of the lead'),
280
+ interest_value: z
281
+ .number()
282
+ .int()
283
+ .min(-1)
284
+ .max(1)
285
+ .describe('Interest status: 1 (interested), 0 (default), -1 (not interested - stops sequence)'),
286
+ campaign_id: z.string().optional().describe('Campaign ID to limit status update to (UUID)'),
287
+ disable_auto_interest: z.boolean().optional().describe('Disable AI auto-tagging for this lead')
288
+ }),
289
+
290
+ outputSchema: z.object({
291
+ success: z.boolean().describe('Whether status update was successful'),
292
+ lead_email: z.string().describe('Email of the updated lead')
293
+ }),
294
+
295
+ integration: 'instantly' as const,
296
+ method: 'updateInterestStatus' as const,
297
+ credentialName
298
+ })
299
+ }
300
+
301
+ /**
302
+ * Create Instantly add to campaign tool
303
+ *
304
+ * Adds leads to an Instantly campaign to begin the email sequence.
305
+ *
306
+ * @param credentialName - Name of credential in credentials table
307
+ * @returns Tool that adds leads to a campaign
308
+ *
309
+ * @example
310
+ * const addToCampaign = createInstantlyAddToCampaignTool('instantly-elevasis')
311
+ */
312
+ export function createInstantlyAddToCampaignTool(credentialName: string): Tool {
313
+ return createIntegrationTool({
314
+ name: 'instantly_add_to_campaign',
315
+ description: `Add leads to an Instantly campaign
316
+
317
+ USE CASES:
318
+ - Add interested leads to a follow-up campaign after initial outreach
319
+ - Start a drip sequence for leads who requested more information
320
+ - Enroll new leads into automated nurture campaigns
321
+
322
+ REQUIRED PARAMETERS:
323
+ - campaign_id: UUID of the Instantly campaign to add leads to
324
+ - leads: Array of lead objects (at least one required)
325
+
326
+ LEAD OBJECT FIELDS:
327
+ - email: (required) Email address of the lead
328
+ - first_name: (optional) First name for personalization
329
+ - last_name: (optional) Last name for personalization
330
+ - company_name: (optional) Company name for personalization
331
+
332
+ IMPORTANT: When leads are added, they begin receiving the campaign sequence immediately.
333
+ "Day 0" starts at the moment of addition.
334
+
335
+ EXAMPLE:
336
+ {
337
+ "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43",
338
+ "leads": [
339
+ {
340
+ "email": "prospect@agency.com",
341
+ "first_name": "John",
342
+ "last_name": "Smith",
343
+ "company_name": "Acme Agency"
344
+ }
345
+ ]
346
+ }
347
+
348
+ OUTPUT:
349
+ {
350
+ "success": true,
351
+ "added_count": 1,
352
+ "errors": null
353
+ }`,
354
+
355
+ inputSchema: z.object({
356
+ campaign_id: z.string().describe('UUID of the Instantly campaign to add leads to'),
357
+ leads: z
358
+ .array(
359
+ z.object({
360
+ email: z.string().email().describe('Email address of the lead'),
361
+ first_name: z.string().optional().describe('First name for personalization'),
362
+ last_name: z.string().optional().describe('Last name for personalization'),
363
+ company_name: z.string().optional().describe('Company name for personalization')
364
+ })
365
+ )
366
+ .min(1)
367
+ .describe('Array of leads to add (at least one required)')
368
+ }),
369
+
370
+ outputSchema: z.object({
371
+ success: z.boolean().describe('Whether leads were added successfully'),
372
+ added_count: z.number().describe('Number of leads successfully added'),
373
+ errors: z.array(z.string()).optional().describe('Array of error messages if any failures occurred')
374
+ }),
375
+
376
+ integration: 'instantly' as const,
377
+ method: 'addToCampaign' as const,
378
+ credentialName
379
+ })
380
+ }
381
+
382
+ /**
383
+ * Create Instantly list campaigns tool
384
+ *
385
+ * Lists all campaigns in the workspace with optional filtering and pagination.
386
+ *
387
+ * @param credentialName - Name of credential in credentials table
388
+ * @returns Tool that lists Instantly campaigns
389
+ *
390
+ * @example
391
+ * const listCampaigns = createInstantlyListCampaignsTool('instantly-elevasis')
392
+ */
393
+ export function createInstantlyListCampaignsTool(credentialName: string): Tool {
394
+ return createIntegrationTool({
395
+ name: 'instantly_list_campaigns',
396
+ description: `List all campaigns in the Instantly workspace
397
+
398
+ USE CASES:
399
+ - Discover available campaigns before adding leads or fetching analytics
400
+ - Filter campaigns by status to find active or paused campaigns
401
+ - Search campaigns by name to locate a specific campaign ID
402
+ - Paginate through large campaign lists using cursor-based pagination
403
+
404
+ OPTIONAL PARAMETERS:
405
+ - limit: Number of campaigns to return per page (default: 10)
406
+ - starting_after: Cursor from previous response for pagination
407
+ - status: Filter by campaign status (e.g. "active", "paused", "completed")
408
+ - search: Search term to filter campaigns by name
409
+
410
+ EXAMPLE (List Active Campaigns):
411
+ {
412
+ "status": "active",
413
+ "limit": 20
414
+ }
415
+
416
+ EXAMPLE (Search by Name):
417
+ {
418
+ "search": "cold outreach Q1"
419
+ }
420
+
421
+ OUTPUT:
422
+ {
423
+ "campaigns": [
424
+ {
425
+ "id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43",
426
+ "name": "Cold Outreach Q1",
427
+ "status": "active",
428
+ "created_at": "2025-01-15T09:00:00Z"
429
+ }
430
+ ],
431
+ "next_starting_after": "cursor-token"
432
+ }`,
433
+
434
+ inputSchema: z.object({
435
+ limit: z.number().min(1).max(100).optional().describe('Number of campaigns per page (default: 10)'),
436
+ starting_after: z
437
+ .string()
438
+ .optional()
439
+ .describe('Cursor for pagination (from next_starting_after in previous response)'),
440
+ status: z.string().optional().describe('Filter by campaign status (e.g. "active", "paused", "completed")'),
441
+ search: z.string().optional().describe('Search term to filter campaigns by name')
442
+ }),
443
+
444
+ outputSchema: z.object({
445
+ campaigns: z
446
+ .array(
447
+ z.object({
448
+ id: z.string().describe('Campaign UUID'),
449
+ name: z.string().describe('Campaign name'),
450
+ status: z.string().describe('Campaign status'),
451
+ created_at: z.string().describe('Campaign creation timestamp')
452
+ })
453
+ )
454
+ .describe('Array of campaigns'),
455
+ next_starting_after: z.string().optional().describe('Cursor for next page (undefined = no more pages)')
456
+ }),
457
+
458
+ integration: 'instantly' as const,
459
+ method: 'listCampaigns' as const,
460
+ credentialName
461
+ })
462
+ }
463
+
464
+ /**
465
+ * Create Instantly get campaign tool
466
+ *
467
+ * Fetches full details for a single campaign including sequences and configuration.
468
+ *
469
+ * @param credentialName - Name of credential in credentials table
470
+ * @returns Tool that retrieves a single Instantly campaign
471
+ *
472
+ * @example
473
+ * const getCampaign = createInstantlyGetCampaignTool('instantly-elevasis')
474
+ */
475
+ export function createInstantlyGetCampaignTool(credentialName: string): Tool {
476
+ return createIntegrationTool({
477
+ name: 'instantly_get_campaign',
478
+ description: `Get full details of a specific Instantly campaign
479
+
480
+ USE CASES:
481
+ - Inspect campaign sequences and step configurations before modifying
482
+ - Verify campaign status before activating or pausing
483
+ - Retrieve sending settings such as daily limits and reply handling
484
+ - Confirm the campaign name and metadata before referencing in reports
485
+
486
+ REQUIRED PARAMETERS:
487
+ - campaign_id: UUID of the campaign to retrieve
488
+
489
+ EXAMPLE:
490
+ {
491
+ "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43"
492
+ }
493
+
494
+ OUTPUT:
495
+ {
496
+ "id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43",
497
+ "name": "Cold Outreach Q1",
498
+ "status": "active",
499
+ "sequences": [...],
500
+ "created_at": "2025-01-15T09:00:00Z"
501
+ }`,
502
+
503
+ inputSchema: z.object({
504
+ campaign_id: z.string().describe('UUID of the campaign to retrieve')
505
+ }),
506
+
507
+ outputSchema: z.object({
508
+ id: z.string().describe('Campaign UUID'),
509
+ name: z.string().describe('Campaign name'),
510
+ status: z.string().describe('Campaign status'),
511
+ sequences: z.array(z.unknown()).describe('Campaign sequence steps'),
512
+ created_at: z.string().describe('Campaign creation timestamp')
513
+ }),
514
+
515
+ integration: 'instantly' as const,
516
+ method: 'getCampaign' as const,
517
+ credentialName
518
+ })
519
+ }
520
+
521
+ /**
522
+ * Create Instantly update campaign tool
523
+ *
524
+ * Partially updates a campaign's fields such as name, sequences, or sending limits.
525
+ *
526
+ * @param credentialName - Name of credential in credentials table
527
+ * @returns Tool that updates an Instantly campaign
528
+ *
529
+ * @example
530
+ * const updateCampaign = createInstantlyUpdateCampaignTool('instantly-elevasis')
531
+ */
532
+ export function createInstantlyUpdateCampaignTool(credentialName: string): Tool {
533
+ return createIntegrationTool({
534
+ name: 'instantly_update_campaign',
535
+ description: `Update fields on an existing Instantly campaign
536
+
537
+ USE CASES:
538
+ - Rename a campaign to reflect updated targeting or messaging
539
+ - Adjust the daily sending limit to control volume
540
+ - Replace or edit campaign sequences and email steps
541
+ - Toggle stop-on-reply to pause the sequence when a lead responds
542
+
543
+ REQUIRED PARAMETERS:
544
+ - campaign_id: UUID of the campaign to update
545
+
546
+ OPTIONAL PARAMETERS (at least one must be provided):
547
+ - name: New campaign name
548
+ - sequences: Full replacement of campaign sequences (array of step objects)
549
+ - daily_limit: Maximum emails to send per day
550
+ - stop_on_reply: Whether to stop sending when a lead replies (true/false)
551
+
552
+ EXAMPLE (Rename and Adjust Limit):
553
+ {
554
+ "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43",
555
+ "name": "Cold Outreach Q2",
556
+ "daily_limit": 50
557
+ }
558
+
559
+ OUTPUT:
560
+ {
561
+ "success": true,
562
+ "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43"
563
+ }`,
564
+
565
+ inputSchema: z.object({
566
+ campaign_id: z.string().describe('UUID of the campaign to update'),
567
+ name: z.string().optional().describe('New campaign name'),
568
+ sequences: z.array(z.unknown()).optional().describe('Replacement campaign sequences (array of step objects)'),
569
+ daily_limit: z.number().int().min(1).optional().describe('Maximum emails to send per day'),
570
+ stop_on_reply: z.boolean().optional().describe('Whether to stop the sequence when a lead replies')
571
+ }),
572
+
573
+ outputSchema: z.object({
574
+ success: z.boolean().describe('Whether the update was successful'),
575
+ campaign_id: z.string().describe('UUID of the updated campaign')
576
+ }),
577
+
578
+ integration: 'instantly' as const,
579
+ method: 'updateCampaign' as const,
580
+ credentialName
581
+ })
582
+ }
583
+
584
+ /**
585
+ * Create Instantly pause campaign tool
586
+ *
587
+ * Pauses an active campaign to stop email sends until reactivated.
588
+ *
589
+ * @param credentialName - Name of credential in credentials table
590
+ * @returns Tool that pauses an Instantly campaign
591
+ *
592
+ * @example
593
+ * const pauseCampaign = createInstantlyPauseCampaignTool('instantly-elevasis')
594
+ */
595
+ export function createInstantlyPauseCampaignTool(credentialName: string): Tool {
596
+ return createIntegrationTool({
597
+ name: 'instantly_pause_campaign',
598
+ description: `Pause an active Instantly campaign
599
+
600
+ USE CASES:
601
+ - Temporarily halt outreach while reviewing campaign performance
602
+ - Pause before making sequence edits to avoid sending stale content
603
+ - Stop sends during public holidays or blackout periods
604
+ - Hold sends when a domain reputation issue is detected
605
+
606
+ REQUIRED PARAMETERS:
607
+ - campaign_id: UUID of the campaign to pause
608
+
609
+ EXAMPLE:
610
+ {
611
+ "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43"
612
+ }
613
+
614
+ OUTPUT:
615
+ {
616
+ "success": true,
617
+ "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43"
618
+ }`,
619
+
620
+ inputSchema: z.object({
621
+ campaign_id: z.string().describe('UUID of the campaign to pause')
622
+ }),
623
+
624
+ outputSchema: z.object({
625
+ success: z.boolean().describe('Whether the campaign was paused successfully'),
626
+ campaign_id: z.string().describe('UUID of the paused campaign')
627
+ }),
628
+
629
+ integration: 'instantly' as const,
630
+ method: 'pauseCampaign' as const,
631
+ credentialName
632
+ })
633
+ }
634
+
635
+ /**
636
+ * Create Instantly delete campaign tool
637
+ *
638
+ * Permanently deletes a campaign and all associated data.
639
+ *
640
+ * @param credentialName - Name of credential in credentials table
641
+ * @returns Tool that deletes an Instantly campaign
642
+ *
643
+ * @example
644
+ * const deleteCampaign = createInstantlyDeleteCampaignTool('instantly-elevasis')
645
+ */
646
+ export function createInstantlyDeleteCampaignTool(credentialName: string): Tool {
647
+ return createIntegrationTool({
648
+ name: 'instantly_delete_campaign',
649
+ description: `Permanently delete an Instantly campaign
650
+
651
+ USE CASES:
652
+ - Clean up test or draft campaigns after diagnostic runs
653
+ - Remove campaigns that are no longer needed
654
+ - Delete accidentally created campaigns
655
+
656
+ REQUIRED PARAMETERS:
657
+ - campaign_id: UUID of the campaign to delete
658
+
659
+ EXAMPLE:
660
+ {
661
+ "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43"
662
+ }
663
+
664
+ OUTPUT:
665
+ {
666
+ "success": true,
667
+ "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43"
668
+ }`,
669
+
670
+ inputSchema: z.object({
671
+ campaign_id: z.string().describe('UUID of the campaign to delete')
672
+ }),
673
+
674
+ outputSchema: z.object({
675
+ success: z.boolean().describe('Whether the campaign was deleted successfully'),
676
+ campaign_id: z.string().describe('UUID of the deleted campaign')
677
+ }),
678
+
679
+ integration: 'instantly' as const,
680
+ method: 'deleteCampaign' as const,
681
+ credentialName
682
+ })
683
+ }
684
+
685
+ /**
686
+ * Create Instantly activate campaign tool
687
+ *
688
+ * Activates or resumes a paused or draft campaign to begin sending.
689
+ *
690
+ * @param credentialName - Name of credential in credentials table
691
+ * @returns Tool that activates an Instantly campaign
692
+ *
693
+ * @example
694
+ * const activateCampaign = createInstantlyActivateCampaignTool('instantly-elevasis')
695
+ */
696
+ export function createInstantlyActivateCampaignTool(credentialName: string): Tool {
697
+ return createIntegrationTool({
698
+ name: 'instantly_activate_campaign',
699
+ description: `Activate or resume an Instantly campaign
700
+
701
+ USE CASES:
702
+ - Launch a newly created campaign to begin sending to enrolled leads
703
+ - Resume a paused campaign after completing edits or reviews
704
+ - Re-activate a campaign after resolving domain reputation issues
705
+ - Start scheduled outreach at the beginning of a new period
706
+
707
+ REQUIRED PARAMETERS:
708
+ - campaign_id: UUID of the campaign to activate
709
+
710
+ EXAMPLE:
711
+ {
712
+ "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43"
713
+ }
714
+
715
+ OUTPUT:
716
+ {
717
+ "success": true,
718
+ "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43"
719
+ }`,
720
+
721
+ inputSchema: z.object({
722
+ campaign_id: z.string().describe('UUID of the campaign to activate')
723
+ }),
724
+
725
+ outputSchema: z.object({
726
+ success: z.boolean().describe('Whether the campaign was activated successfully'),
727
+ campaign_id: z.string().describe('UUID of the activated campaign')
728
+ }),
729
+
730
+ integration: 'instantly' as const,
731
+ method: 'activateCampaign' as const,
732
+ credentialName
733
+ })
734
+ }
735
+
736
+ /**
737
+ * Create Instantly get campaign analytics tool
738
+ *
739
+ * Retrieves aggregate engagement statistics for a campaign.
740
+ *
741
+ * @param credentialName - Name of credential in credentials table
742
+ * @returns Tool that fetches campaign-level analytics
743
+ *
744
+ * @example
745
+ * const getAnalytics = createInstantlyGetCampaignAnalyticsTool('instantly-elevasis')
746
+ */
747
+ export function createInstantlyGetCampaignAnalyticsTool(credentialName: string): Tool {
748
+ return createIntegrationTool({
749
+ name: 'instantly_get_campaign_analytics',
750
+ description: `Get aggregate analytics for an Instantly campaign
751
+
752
+ USE CASES:
753
+ - Review overall campaign performance including open rate, reply rate, and bounce rate
754
+ - Compare send volume against replies to evaluate outreach effectiveness
755
+ - Monitor unsubscribes to maintain sender reputation
756
+ - Scope analytics to a date range for period-specific reporting
757
+
758
+ REQUIRED PARAMETERS:
759
+ - campaign_id: UUID of the campaign
760
+
761
+ OPTIONAL PARAMETERS:
762
+ - start_date: ISO date string to filter analytics from (e.g. "2025-01-01")
763
+ - end_date: ISO date string to filter analytics to (e.g. "2025-03-31")
764
+
765
+ EXAMPLE:
766
+ {
767
+ "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43",
768
+ "start_date": "2025-01-01",
769
+ "end_date": "2025-03-31"
770
+ }
771
+
772
+ OUTPUT:
773
+ {
774
+ "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43",
775
+ "sent": 450,
776
+ "opened": 180,
777
+ "unique_opened": 160,
778
+ "replied": 35,
779
+ "unique_replied": 30,
780
+ "bounced": 5,
781
+ "unsubscribed": 2
782
+ }`,
783
+
784
+ inputSchema: z.object({
785
+ campaign_id: z.string().describe('UUID of the campaign to fetch analytics for'),
786
+ start_date: z.string().optional().describe('Start date for analytics range (ISO date string, e.g. "2025-01-01")'),
787
+ end_date: z.string().optional().describe('End date for analytics range (ISO date string, e.g. "2025-03-31")')
788
+ }),
789
+
790
+ outputSchema: z.object({
791
+ campaign_id: z.string().describe('Campaign UUID'),
792
+ sent: z.number().describe('Total emails sent'),
793
+ opened: z.number().describe('Total open events'),
794
+ unique_opened: z.number().describe('Unique leads who opened'),
795
+ replied: z.number().describe('Total reply events'),
796
+ unique_replied: z.number().describe('Unique leads who replied'),
797
+ bounced: z.number().describe('Total bounced emails'),
798
+ unsubscribed: z.number().describe('Total unsubscribes')
799
+ }),
800
+
801
+ integration: 'instantly' as const,
802
+ method: 'getCampaignAnalytics' as const,
803
+ credentialName
804
+ })
805
+ }
806
+
807
+ /**
808
+ * Create Instantly get step analytics tool
809
+ *
810
+ * Retrieves per-step and per-variant analytics for a campaign sequence.
811
+ *
812
+ * @param credentialName - Name of credential in credentials table
813
+ * @returns Tool that fetches step-level analytics
814
+ *
815
+ * @example
816
+ * const getStepAnalytics = createInstantlyGetStepAnalyticsTool('instantly-elevasis')
817
+ */
818
+ export function createInstantlyGetStepAnalyticsTool(credentialName: string): Tool {
819
+ return createIntegrationTool({
820
+ name: 'instantly_get_step_analytics',
821
+ description: `Get per-step and per-variant analytics for an Instantly campaign
822
+
823
+ USE CASES:
824
+ - Identify which sequence step has the highest reply rate
825
+ - Compare A/B subject line variants to determine the winning version
826
+ - Diagnose a drop-off point where prospects stop engaging
827
+ - Optimize multi-step sequences based on step-level performance data
828
+
829
+ REQUIRED PARAMETERS:
830
+ - campaign_id: UUID of the campaign
831
+
832
+ EXAMPLE:
833
+ {
834
+ "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43"
835
+ }
836
+
837
+ OUTPUT:
838
+ {
839
+ "steps": [
840
+ {
841
+ "step": "1",
842
+ "variant": "A",
843
+ "sent": 200,
844
+ "opened": 90,
845
+ "unique_opened": 80,
846
+ "replies": 20,
847
+ "unique_replies": 18
848
+ },
849
+ {
850
+ "step": "2",
851
+ "variant": "A",
852
+ "sent": 160,
853
+ "opened": 55,
854
+ "unique_opened": 50,
855
+ "replies": 10,
856
+ "unique_replies": 9
857
+ }
858
+ ]
859
+ }`,
860
+
861
+ inputSchema: z.object({
862
+ campaign_id: z.string().describe('UUID of the campaign to fetch step analytics for')
863
+ }),
864
+
865
+ outputSchema: z.object({
866
+ steps: z
867
+ .array(
868
+ z.object({
869
+ step: z.string().describe('Step number in the sequence'),
870
+ variant: z.string().describe('Variant label (e.g. "A", "B")'),
871
+ sent: z.number().describe('Emails sent for this step/variant'),
872
+ opened: z.number().describe('Total open events'),
873
+ unique_opened: z.number().describe('Unique leads who opened'),
874
+ replies: z.number().describe('Total reply events'),
875
+ unique_replies: z.number().describe('Unique leads who replied')
876
+ })
877
+ )
878
+ .describe('Per-step, per-variant analytics entries')
879
+ }),
880
+
881
+ integration: 'instantly' as const,
882
+ method: 'getStepAnalytics' as const,
883
+ credentialName
884
+ })
885
+ }
886
+
887
+ /**
888
+ * Create Instantly bulk add leads tool
889
+ *
890
+ * Adds up to 1000 leads to a campaign in a single request.
891
+ *
892
+ * @param credentialName - Name of credential in credentials table
893
+ * @returns Tool that bulk-uploads leads to an Instantly campaign
894
+ *
895
+ * @example
896
+ * const bulkAddLeads = createInstantlyBulkAddLeadsTool('instantly-elevasis')
897
+ */
898
+ export function createInstantlyBulkAddLeadsTool(credentialName: string): Tool {
899
+ return createIntegrationTool({
900
+ name: 'instantly_bulk_add_leads',
901
+ description: `Bulk upload up to 1000 leads to an Instantly campaign
902
+
903
+ USE CASES:
904
+ - Import a large list of qualified prospects into a campaign at once
905
+ - Enroll leads exported from a CRM or enrichment tool into outreach
906
+ - Upload leads with custom variables for deep personalization
907
+ - Add leads with website and company data for context-aware sequences
908
+
909
+ REQUIRED PARAMETERS:
910
+ - campaign_id: UUID of the campaign to add leads to
911
+ - leads: Array of lead objects (1–1000 leads)
912
+
913
+ LEAD OBJECT FIELDS:
914
+ - email: (required) Email address of the lead
915
+ - first_name: (optional) First name for personalization
916
+ - last_name: (optional) Last name for personalization
917
+ - company_name: (optional) Company name for personalization
918
+ - website: (optional) Company website URL
919
+ - custom_variables: (optional) Key-value map of custom merge fields
920
+
921
+ EXAMPLE:
922
+ {
923
+ "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43",
924
+ "leads": [
925
+ {
926
+ "email": "ceo@agency.com",
927
+ "first_name": "Sarah",
928
+ "last_name": "Chen",
929
+ "company_name": "Growth Agency",
930
+ "website": "https://growthagency.com",
931
+ "custom_variables": { "pain_point": "manual lead gen" }
932
+ }
933
+ ]
934
+ }
935
+
936
+ OUTPUT:
937
+ {
938
+ "success": true,
939
+ "added_count": 1,
940
+ "failed_count": 0
941
+ }`,
942
+
943
+ inputSchema: z.object({
944
+ campaign_id: z.string().describe('UUID of the campaign to add leads to'),
945
+ leads: z
946
+ .array(
947
+ z.object({
948
+ email: z.string().email().describe('Email address of the lead'),
949
+ first_name: z.string().optional().describe('First name for personalization'),
950
+ last_name: z.string().optional().describe('Last name for personalization'),
951
+ company_name: z.string().optional().describe('Company name for personalization'),
952
+ website: z.string().optional().describe('Company website URL'),
953
+ custom_variables: z
954
+ .record(z.string(), z.string())
955
+ .optional()
956
+ .describe('Key-value map of custom merge field values')
957
+ })
958
+ )
959
+ .min(1)
960
+ .max(1000)
961
+ .describe('Array of leads to upload (1–1000)')
962
+ }),
963
+
964
+ outputSchema: z.object({
965
+ success: z.boolean().describe('True if all leads were added without errors'),
966
+ added_count: z.number().describe('Number of leads successfully added'),
967
+ failed_count: z.number().describe('Number of leads that failed to add'),
968
+ errors: z
969
+ .array(
970
+ z.object({
971
+ email: z.string().describe('Email of the lead that failed'),
972
+ error: z.string().describe('Error message for this lead')
973
+ })
974
+ )
975
+ .optional()
976
+ .describe('Per-lead error details when failures occurred')
977
+ }),
978
+
979
+ integration: 'instantly' as const,
980
+ method: 'bulkAddLeads' as const,
981
+ credentialName
982
+ })
983
+ }
984
+
985
+ /**
986
+ * Create Instantly get account health tool
987
+ *
988
+ * Lists email sending accounts with warmup status and health scores.
989
+ *
990
+ * @param credentialName - Name of credential in credentials table
991
+ * @returns Tool that retrieves account health data
992
+ *
993
+ * @example
994
+ * const getAccountHealth = createInstantlyGetAccountHealthTool('instantly-elevasis')
995
+ */
996
+ export function createInstantlyGetAccountHealthTool(credentialName: string): Tool {
997
+ return createIntegrationTool({
998
+ name: 'instantly_get_account_health',
999
+ description: `List email accounts with health status and warmup information
1000
+
1001
+ USE CASES:
1002
+ - Audit all connected sending accounts before launching a campaign
1003
+ - Identify accounts with low health scores that may cause deliverability issues
1004
+ - Verify warmup status to ensure accounts are ready for full sending volume
1005
+ - Monitor account portfolio health as part of regular sender hygiene checks
1006
+
1007
+ OPTIONAL PARAMETERS:
1008
+ - limit: Number of accounts to return per page
1009
+ - starting_after: Cursor from previous response for pagination
1010
+
1011
+ EXAMPLE:
1012
+ {
1013
+ "limit": 20
1014
+ }
1015
+
1016
+ OUTPUT:
1017
+ {
1018
+ "accounts": [
1019
+ {
1020
+ "id": "acct-abc123",
1021
+ "email": "alex@elevasis.com",
1022
+ "status": "active",
1023
+ "warmup_enabled": true,
1024
+ "health_score": 92
1025
+ }
1026
+ ],
1027
+ "next_starting_after": "cursor-token"
1028
+ }`,
1029
+
1030
+ inputSchema: z.object({
1031
+ limit: z.number().min(1).max(100).optional().describe('Number of accounts per page'),
1032
+ starting_after: z
1033
+ .string()
1034
+ .optional()
1035
+ .describe('Cursor for pagination (from next_starting_after in previous response)')
1036
+ }),
1037
+
1038
+ outputSchema: z.object({
1039
+ accounts: z
1040
+ .array(
1041
+ z.object({
1042
+ id: z.string().describe('Account ID'),
1043
+ email: z.string().describe('Sending email address'),
1044
+ status: z.string().describe('Account status'),
1045
+ warmup_enabled: z.boolean().describe('Whether warmup is active for this account'),
1046
+ health_score: z.number().optional().describe('Health score (0–100)')
1047
+ })
1048
+ )
1049
+ .describe('Array of sending accounts with health data'),
1050
+ next_starting_after: z.string().optional().describe('Cursor for next page (undefined = no more pages)')
1051
+ }),
1052
+
1053
+ integration: 'instantly' as const,
1054
+ method: 'getAccountHealth' as const,
1055
+ credentialName
1056
+ })
1057
+ }
1058
+
1059
+ /**
1060
+ * Create Instantly create campaign tool
1061
+ *
1062
+ * Creates a new campaign in Instantly with optional sequences and sending configuration.
1063
+ *
1064
+ * @param credentialName - Name of credential in credentials table
1065
+ * @returns Tool that creates a new Instantly campaign
1066
+ *
1067
+ * @example
1068
+ * const createCampaign = createInstantlyCreateCampaignTool('instantly-elevasis')
1069
+ */
1070
+ export function createInstantlyCreateCampaignTool(credentialName: string): Tool {
1071
+ return createIntegrationTool({
1072
+ name: 'instantly_create_campaign',
1073
+ description: `Create a new Instantly campaign
1074
+
1075
+ USE CASES:
1076
+ - Set up a new cold outreach campaign with custom sequences
1077
+ - Create a campaign with predefined email steps and A/B variants
1078
+ - Configure sending limits and reply handling at creation time
1079
+ - Prepare a campaign shell to be populated with leads and activated later
1080
+
1081
+ REQUIRED PARAMETERS:
1082
+ - name: Display name of the new campaign
1083
+
1084
+ OPTIONAL PARAMETERS:
1085
+ - sequences: Array of sequence objects with email steps and optional A/B variants
1086
+ - email_list: Array of sending account emails to use for the campaign
1087
+ - daily_limit: Maximum emails to send per day
1088
+ - stop_on_reply: Whether to stop the sequence when a lead replies
1089
+ - stop_on_auto_reply: Whether to stop on auto-replies
1090
+ - track_opens: Whether to track email opens
1091
+ - track_clicks: Whether to track link clicks
1092
+ - text_only: Whether to send text-only emails (no HTML)
1093
+
1094
+ EXAMPLE (Simple Campaign):
1095
+ {
1096
+ "name": "Cold Outreach Q2 2025",
1097
+ "daily_limit": 50,
1098
+ "stop_on_reply": true
1099
+ }
1100
+
1101
+ EXAMPLE (Campaign with Sequence):
1102
+ {
1103
+ "name": "Agency Outreach",
1104
+ "sequences": [
1105
+ {
1106
+ "steps": [
1107
+ {
1108
+ "subject": "Quick question about {{company_name}}",
1109
+ "body": "Hi {{first_name}}, I noticed..."
1110
+ },
1111
+ {
1112
+ "subject": "Following up",
1113
+ "body": "Hi {{first_name}}, just wanted to circle back..."
1114
+ }
1115
+ ]
1116
+ }
1117
+ ],
1118
+ "daily_limit": 30,
1119
+ "stop_on_reply": true
1120
+ }
1121
+
1122
+ OUTPUT:
1123
+ {
1124
+ "success": true,
1125
+ "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43",
1126
+ "name": "Cold Outreach Q2 2025"
1127
+ }`,
1128
+
1129
+ inputSchema: z.object({
1130
+ name: z.string().describe('Display name of the new campaign'),
1131
+ sequences: z
1132
+ .array(
1133
+ z.object({
1134
+ steps: z.array(
1135
+ z.object({
1136
+ subject: z.string().describe('Email subject line for this step'),
1137
+ body: z.string().describe('Email body for this step'),
1138
+ variants: z
1139
+ .array(
1140
+ z.object({
1141
+ subject: z.string().describe('A/B variant subject line'),
1142
+ body: z.string().describe('A/B variant body')
1143
+ })
1144
+ )
1145
+ .optional()
1146
+ .describe('A/B test variants for this step')
1147
+ })
1148
+ )
1149
+ })
1150
+ )
1151
+ .optional()
1152
+ .describe('Campaign sequences with email steps'),
1153
+ email_list: z.array(z.string()).optional().describe('Sending account emails to use for the campaign'),
1154
+ daily_limit: z.number().int().min(1).optional().describe('Maximum emails to send per day'),
1155
+ stop_on_reply: z.boolean().optional().describe('Whether to stop the sequence when a lead replies'),
1156
+ stop_on_auto_reply: z.boolean().optional().describe('Whether to stop the sequence on auto-replies'),
1157
+ track_opens: z.boolean().optional().describe('Whether to track email opens'),
1158
+ track_clicks: z.boolean().optional().describe('Whether to track link clicks'),
1159
+ text_only: z.boolean().optional().describe('Whether to send text-only emails (no HTML)')
1160
+ }),
1161
+
1162
+ outputSchema: z.object({
1163
+ success: z.boolean().describe('Whether the campaign was created successfully'),
1164
+ campaign_id: z.string().describe('UUID of the newly created campaign'),
1165
+ name: z.string().describe('Name of the created campaign')
1166
+ }),
1167
+
1168
+ integration: 'instantly' as const,
1169
+ method: 'createCampaign' as const,
1170
+ credentialName
1171
+ })
1172
+ }
1173
+
1174
+ /**
1175
+ * Create Instantly create inbox test tool
1176
+ *
1177
+ * Initiates an inbox placement test to diagnose deliverability for a sending account.
1178
+ *
1179
+ * @param credentialName - Name of credential in credentials table
1180
+ * @returns Tool that creates an Instantly inbox placement test
1181
+ *
1182
+ * @example
1183
+ * const createInboxTest = createInstantlyCreateInboxTestTool('instantly-elevasis')
1184
+ */
1185
+ export function createInstantlyCreateInboxTestTool(credentialName: string): Tool {
1186
+ return createIntegrationTool({
1187
+ name: 'instantly_create_inbox_test',
1188
+ description: `Create an inbox placement test for an Instantly sending account
1189
+
1190
+ USE CASES:
1191
+ - Verify deliverability before launching a high-volume campaign
1192
+ - Diagnose spam filtering issues on a specific sending account
1193
+ - Test whether custom subject lines land in inbox or spam
1194
+ - Monitor placement across Gmail, Outlook, and other major providers
1195
+
1196
+ REQUIRED PARAMETERS:
1197
+ - email_account: The sending account to test (must be connected to workspace)
1198
+
1199
+ OPTIONAL PARAMETERS:
1200
+ - subject: Custom subject line to use in the test email
1201
+ - body: Custom body text to use in the test email
1202
+
1203
+ EXAMPLE:
1204
+ {
1205
+ "email_account": "alex@elevasis.com",
1206
+ "subject": "Quick question about your agency",
1207
+ "body": "Hi, I wanted to reach out about..."
1208
+ }
1209
+
1210
+ OUTPUT:
1211
+ {
1212
+ "success": true,
1213
+ "test_id": "test-abc123",
1214
+ "status": "pending"
1215
+ }`,
1216
+
1217
+ inputSchema: z.object({
1218
+ email_account: z.string().describe('Sending account email address to test (must be connected to workspace)'),
1219
+ subject: z.string().optional().describe('Custom subject line for the test email'),
1220
+ body: z.string().optional().describe('Custom body text for the test email')
1221
+ }),
1222
+
1223
+ outputSchema: z.object({
1224
+ success: z.boolean().describe('Whether the test was created successfully'),
1225
+ test_id: z.string().describe('Unique ID of the inbox placement test'),
1226
+ status: z.string().describe('Initial test status (e.g. "pending")')
1227
+ }),
1228
+
1229
+ integration: 'instantly' as const,
1230
+ method: 'createInboxTest' as const,
1231
+ credentialName
1232
+ })
1233
+ }
1234
+
1235
+ /**
1236
+ * Create Instantly get daily campaign analytics tool
1237
+ *
1238
+ * Retrieves day-by-day engagement breakdown for campaigns.
1239
+ *
1240
+ * @param credentialName - Name of credential in credentials table
1241
+ * @returns Tool that fetches daily campaign analytics
1242
+ *
1243
+ * @example
1244
+ * const getDailyAnalytics = createInstantlyGetDailyCampaignAnalyticsTool('instantly-elevasis')
1245
+ */
1246
+ export function createInstantlyGetDailyCampaignAnalyticsTool(credentialName: string): Tool {
1247
+ return createIntegrationTool({
1248
+ name: 'instantly_get_daily_campaign_analytics',
1249
+ description: `Get day-by-day analytics breakdown for Instantly campaigns
1250
+
1251
+ USE CASES:
1252
+ - Analyze send and open trends over a date range to identify patterns
1253
+ - Spot peak engagement days to optimize future send scheduling
1254
+ - Compare daily click and reply volumes across a campaign period
1255
+ - Get cross-campaign aggregate metrics when no campaign_id is specified
1256
+
1257
+ OPTIONAL PARAMETERS:
1258
+ - campaign_id: Filter analytics to a specific campaign UUID (omit for all campaigns)
1259
+ - start_date: Start of date range (ISO date, e.g. "2025-01-01")
1260
+ - end_date: End of date range (ISO date, e.g. "2025-03-31")
1261
+
1262
+ EXAMPLE (Single Campaign):
1263
+ {
1264
+ "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43",
1265
+ "start_date": "2025-01-01",
1266
+ "end_date": "2025-01-31"
1267
+ }
1268
+
1269
+ EXAMPLE (All Campaigns):
1270
+ {
1271
+ "start_date": "2025-01-01",
1272
+ "end_date": "2025-01-31"
1273
+ }
1274
+
1275
+ OUTPUT:
1276
+ {
1277
+ "data": [
1278
+ {
1279
+ "date": "2025-01-15",
1280
+ "sent": 120,
1281
+ "opened": 48,
1282
+ "unique_opened": 42,
1283
+ "replied": 8,
1284
+ "unique_replied": 7,
1285
+ "bounced": 1,
1286
+ "clicks": 12,
1287
+ "unique_clicks": 10
1288
+ }
1289
+ ]
1290
+ }`,
1291
+
1292
+ inputSchema: z.object({
1293
+ campaign_id: z.string().optional().describe('Campaign UUID to filter analytics (omit to get all campaigns)'),
1294
+ start_date: z.string().optional().describe('Start of date range (ISO date, e.g. "2025-01-01")'),
1295
+ end_date: z.string().optional().describe('End of date range (ISO date, e.g. "2025-03-31")')
1296
+ }),
1297
+
1298
+ outputSchema: z.object({
1299
+ data: z
1300
+ .array(
1301
+ z.object({
1302
+ date: z.string().describe('Date (YYYY-MM-DD)'),
1303
+ sent: z.number().describe('Emails sent on this date'),
1304
+ opened: z.number().describe('Total open events'),
1305
+ unique_opened: z.number().describe('Unique leads who opened'),
1306
+ replied: z.number().describe('Total reply events'),
1307
+ unique_replied: z.number().describe('Unique leads who replied'),
1308
+ bounced: z.number().describe('Emails bounced'),
1309
+ clicks: z.number().describe('Total link click events'),
1310
+ unique_clicks: z.number().describe('Unique leads who clicked')
1311
+ })
1312
+ )
1313
+ .describe('Array of daily analytics entries')
1314
+ }),
1315
+
1316
+ integration: 'instantly' as const,
1317
+ method: 'getDailyCampaignAnalytics' as const,
1318
+ credentialName
1319
+ })
1320
+ }
1321
+
1322
+ /**
1323
+ * Create Instantly list leads tool
1324
+ *
1325
+ * Lists leads with optional filtering by campaign or email and cursor pagination.
1326
+ *
1327
+ * @param credentialName - Name of credential in credentials table
1328
+ * @returns Tool that lists Instantly leads
1329
+ *
1330
+ * @example
1331
+ * const listLeads = createInstantlyListLeadsTool('instantly-elevasis')
1332
+ */
1333
+ export function createInstantlyListLeadsTool(credentialName: string): Tool {
1334
+ return createIntegrationTool({
1335
+ name: 'instantly_list_leads',
1336
+ description: `List leads in Instantly with optional filtering and pagination
1337
+
1338
+ USE CASES:
1339
+ - Retrieve all leads enrolled in a specific campaign for auditing
1340
+ - Look up a specific lead by email address to check their status
1341
+ - Paginate through a large lead list using cursor-based pagination
1342
+ - Review lead metadata including status, timestamps, and campaign assignment
1343
+
1344
+ OPTIONAL PARAMETERS:
1345
+ - campaign_id: Filter leads by campaign UUID
1346
+ - email: Filter by specific lead email address
1347
+ - limit: Number of leads per page
1348
+ - starting_after: Cursor from previous response for pagination
1349
+
1350
+ NOTE: This uses a POST endpoint per Instantly API design (complex filter arguments).
1351
+
1352
+ EXAMPLE (Campaign Leads):
1353
+ {
1354
+ "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43",
1355
+ "limit": 50
1356
+ }
1357
+
1358
+ EXAMPLE (Single Lead Lookup):
1359
+ {
1360
+ "email": "prospect@agency.com"
1361
+ }
1362
+
1363
+ OUTPUT:
1364
+ {
1365
+ "items": [
1366
+ {
1367
+ "id": "lead-abc123",
1368
+ "email": "prospect@agency.com",
1369
+ "first_name": "John",
1370
+ "last_name": "Smith",
1371
+ "company_name": "Acme Agency",
1372
+ "status": "active",
1373
+ "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43",
1374
+ "timestamp_created": "2025-01-15T09:00:00Z"
1375
+ }
1376
+ ],
1377
+ "next_starting_after": "cursor-token"
1378
+ }`,
1379
+
1380
+ inputSchema: z.object({
1381
+ campaign_id: z.string().optional().describe('Filter leads by campaign UUID'),
1382
+ email: z.string().optional().describe('Filter by specific lead email address'),
1383
+ limit: z.number().min(1).max(100).optional().describe('Number of leads per page'),
1384
+ starting_after: z
1385
+ .string()
1386
+ .optional()
1387
+ .describe('Cursor for pagination (from next_starting_after in previous response)')
1388
+ }),
1389
+
1390
+ outputSchema: z.object({
1391
+ items: z
1392
+ .array(
1393
+ z.object({
1394
+ id: z.string().describe('Lead ID'),
1395
+ email: z.string().describe('Lead email address'),
1396
+ first_name: z.string().optional().describe('Lead first name'),
1397
+ last_name: z.string().optional().describe('Lead last name'),
1398
+ company_name: z.string().optional().describe('Lead company name'),
1399
+ status: z.string().describe('Lead status in campaign'),
1400
+ campaign_id: z.string().optional().describe('Campaign this lead belongs to'),
1401
+ timestamp_created: z.string().optional().describe('Lead creation timestamp')
1402
+ })
1403
+ )
1404
+ .describe('Array of leads'),
1405
+ next_starting_after: z.string().optional().describe('Cursor for next page (undefined = no more pages)')
1406
+ }),
1407
+
1408
+ integration: 'instantly' as const,
1409
+ method: 'listLeads' as const,
1410
+ credentialName
1411
+ })
1412
+ }
1413
+
1414
+ /**
1415
+ * Create Instantly bulk delete leads tool
1416
+ *
1417
+ * Deletes leads in bulk by IDs, campaign, or list with an optional limit.
1418
+ *
1419
+ * @param credentialName - Name of credential in credentials table
1420
+ * @returns Tool that bulk-deletes Instantly leads
1421
+ *
1422
+ * @example
1423
+ * const bulkDeleteLeads = createInstantlyBulkDeleteLeadsTool('instantly-elevasis')
1424
+ */
1425
+ export function createInstantlyBulkDeleteLeadsTool(credentialName: string): Tool {
1426
+ return createIntegrationTool({
1427
+ name: 'instantly_bulk_delete_leads',
1428
+ description: `Bulk delete leads from Instantly by IDs, campaign, or list
1429
+
1430
+ USE CASES:
1431
+ - Remove a batch of disqualified leads from a campaign at once
1432
+ - Clean up leads from a completed campaign before archiving
1433
+ - Delete leads from a specific list to maintain database hygiene
1434
+ - Remove a set of specific leads by their IDs after a data audit
1435
+
1436
+ OPTIONAL PARAMETERS (at least one filter recommended):
1437
+ - ids: Array of specific lead IDs to delete
1438
+ - campaign_id: Delete all leads from this campaign
1439
+ - list_id: Delete all leads from this list
1440
+ - limit: Maximum number of leads to delete in this operation (1-10000)
1441
+
1442
+ EXAMPLE (Delete by IDs):
1443
+ {
1444
+ "ids": ["lead-abc123", "lead-def456"]
1445
+ }
1446
+
1447
+ EXAMPLE (Delete from Campaign):
1448
+ {
1449
+ "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43",
1450
+ "limit": 100
1451
+ }
1452
+
1453
+ OUTPUT:
1454
+ {
1455
+ "deleted_count": 42
1456
+ }`,
1457
+
1458
+ inputSchema: z.object({
1459
+ ids: z.array(z.string()).optional().describe('Specific lead IDs to delete'),
1460
+ campaign_id: z.string().optional().describe('Delete leads from this campaign'),
1461
+ list_id: z.string().optional().describe('Delete leads from this list'),
1462
+ limit: z.number().int().min(1).optional().describe('Maximum number of leads to delete')
1463
+ }),
1464
+
1465
+ outputSchema: z.object({
1466
+ deleted_count: z.number().describe('Number of leads deleted')
1467
+ }),
1468
+
1469
+ integration: 'instantly' as const,
1470
+ method: 'bulkDeleteLeads' as const,
1471
+ credentialName
1472
+ })
1473
+ }