@elevasis/core 0.7.1 → 0.8.2

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 (476) hide show
  1. package/dist/test-utils/index.d.ts +3122 -0
  2. package/dist/test-utils/index.js +386 -0
  3. package/package.json +6 -1
  4. package/src/README.md +39 -36
  5. package/src/__tests__/publish.test.ts +18 -13
  6. package/src/__tests__/{template-foundations-compatibility.test.ts → template-core-compatibility.test.ts} +99 -99
  7. package/src/_gen/__tests__/__snapshots__/contracts.md.snap +1135 -1131
  8. package/src/_gen/__tests__/scaffold-contracts.test.ts +47 -36
  9. package/src/_gen/scaffold-contracts.ts +45 -45
  10. package/src/auth/multi-tenancy/credentials/README.md +38 -38
  11. package/src/auth/multi-tenancy/credentials/index.ts +6 -6
  12. package/src/auth/multi-tenancy/credentials/server/encryption.ts +39 -39
  13. package/src/auth/multi-tenancy/credentials/server/service.ts +60 -60
  14. package/src/auth/multi-tenancy/index.ts +17 -17
  15. package/src/auth/multi-tenancy/invitations/api-schemas.ts +107 -107
  16. package/src/auth/multi-tenancy/invitations/index.ts +37 -37
  17. package/src/auth/multi-tenancy/invitations/invitation.ts +86 -86
  18. package/src/auth/multi-tenancy/invitations/server/index.ts +25 -25
  19. package/src/auth/multi-tenancy/invitations/server/transforms.ts +24 -24
  20. package/src/auth/multi-tenancy/invitations/server/workos.ts +24 -24
  21. package/src/auth/multi-tenancy/invitations/supabase.ts +50 -50
  22. package/src/auth/multi-tenancy/memberships/api-schemas.ts +126 -126
  23. package/src/auth/multi-tenancy/memberships/index.ts +21 -21
  24. package/src/auth/multi-tenancy/memberships/membership.ts +138 -138
  25. package/src/auth/multi-tenancy/memberships/server/index.ts +15 -15
  26. package/src/auth/multi-tenancy/memberships/server/transforms.ts +32 -32
  27. package/src/auth/multi-tenancy/memberships/server/workos.ts +21 -21
  28. package/src/auth/multi-tenancy/memberships/supabase.ts +46 -46
  29. package/src/auth/multi-tenancy/organizations/api-schemas.ts +128 -128
  30. package/src/auth/multi-tenancy/organizations/index.ts +23 -23
  31. package/src/auth/multi-tenancy/organizations/organization.ts +24 -24
  32. package/src/auth/multi-tenancy/organizations/server/index.ts +10 -10
  33. package/src/auth/multi-tenancy/organizations/server/transforms.ts +35 -35
  34. package/src/auth/multi-tenancy/organizations/server/workos.ts +20 -20
  35. package/src/auth/multi-tenancy/types.ts +83 -83
  36. package/src/auth/multi-tenancy/users/api-schemas.ts +194 -194
  37. package/src/auth/multi-tenancy/users/index.ts +27 -27
  38. package/src/auth/multi-tenancy/users/server/index.ts +19 -19
  39. package/src/auth/multi-tenancy/users/server/transforms.ts +21 -21
  40. package/src/auth/multi-tenancy/users/server/workos.ts +16 -16
  41. package/src/auth/multi-tenancy/users/user.ts +65 -65
  42. package/src/business/README.md +52 -52
  43. package/src/business/__tests__/entities-published.test.ts +33 -33
  44. package/src/business/acquisition/api-schemas.ts +759 -759
  45. package/src/business/acquisition/index.ts +109 -109
  46. package/src/business/acquisition/types.ts +402 -402
  47. package/src/business/base-entities.test.ts +481 -481
  48. package/src/business/base-entities.ts +241 -241
  49. package/src/business/entities-published.ts +24 -24
  50. package/src/business/index.ts +15 -15
  51. package/src/business/pdf/browser/pdfmake-browser.ts +229 -229
  52. package/src/business/pdf/index.ts +10 -10
  53. package/src/business/pdf/server/index.ts +21 -21
  54. package/src/business/pdf/server/themes/default.ts +8 -8
  55. package/src/business/pdf/server/themes/index.ts +9 -9
  56. package/src/business/pdf/server/themes/types.ts +8 -8
  57. package/src/business/pdf/types.ts +272 -272
  58. package/src/business/projects/index.ts +2 -2
  59. package/src/business/projects/sse-events.ts +21 -21
  60. package/src/business/projects/types.ts +89 -89
  61. package/src/business/sales/api-schemas.ts +75 -75
  62. package/src/business/seo/__tests__/linking.test.ts +549 -549
  63. package/src/business/seo/__tests__/types.test.ts +404 -404
  64. package/src/business/seo/index.ts +2 -2
  65. package/src/business/seo/linking.ts +281 -281
  66. package/src/business/seo/types.ts +199 -199
  67. package/src/commands/queue/index.ts +3 -3
  68. package/src/commands/queue/schemas.test.ts +593 -593
  69. package/src/commands/queue/schemas.ts +125 -125
  70. package/src/commands/queue/sse-events.ts +61 -61
  71. package/src/commands/queue/types/action.ts +52 -52
  72. package/src/commands/queue/types/checkpoint.ts +44 -44
  73. package/src/commands/queue/types/index.ts +7 -7
  74. package/src/commands/queue/types/task.ts +116 -116
  75. package/src/commands/queue/types.ts +14 -14
  76. package/src/content/distribution-metadata.ts +61 -61
  77. package/src/content/index.ts +10 -10
  78. package/src/deployments/index.ts +22 -22
  79. package/src/execution/core/__tests__/archived-logs.test.ts +72 -72
  80. package/src/execution/core/index.ts +11 -11
  81. package/src/execution/core/runner-types.ts +80 -80
  82. package/src/execution/core/server/environment.ts +31 -31
  83. package/src/execution/core/sse-executions.ts +119 -119
  84. package/src/execution/core/types.ts +29 -29
  85. package/src/execution/engine/__tests__/fixtures/test-agents.ts +4 -4
  86. package/src/execution/engine/__tests__/timeout.test.ts +565 -565
  87. package/src/execution/engine/agent/__tests__/errors.test.ts +508 -508
  88. package/src/execution/engine/agent/actions/__tests__/processor.test.ts +531 -531
  89. package/src/execution/engine/agent/actions/executor.ts +205 -205
  90. package/src/execution/engine/agent/actions/navigate-knowledge-executor.ts +230 -230
  91. package/src/execution/engine/agent/actions/processor.ts +116 -116
  92. package/src/execution/engine/agent/actions/types.ts +70 -70
  93. package/src/execution/engine/agent/core/agent.ts +810 -810
  94. package/src/execution/engine/agent/core/types.ts +155 -155
  95. package/src/execution/engine/agent/errors.ts +251 -251
  96. package/src/execution/engine/agent/index.ts +78 -78
  97. package/src/execution/engine/agent/knowledge-map/types.ts +106 -106
  98. package/src/execution/engine/agent/knowledge-map/utils.ts +101 -101
  99. package/src/execution/engine/agent/memory/__tests__/manager.test.ts +754 -754
  100. package/src/execution/engine/agent/memory/domains.ts +99 -99
  101. package/src/execution/engine/agent/memory/manager.ts +365 -365
  102. package/src/execution/engine/agent/memory/processor.ts +66 -66
  103. package/src/execution/engine/agent/memory/types.ts +90 -90
  104. package/src/execution/engine/agent/memory/utils.ts +134 -134
  105. package/src/execution/engine/agent/observability/logging.ts +467 -467
  106. package/src/execution/engine/agent/observability/types.ts +64 -64
  107. package/src/execution/engine/agent/reasoning/adapters/agent-adapter-helpers.ts +349 -349
  108. package/src/execution/engine/agent/reasoning/processor.ts +92 -92
  109. package/src/execution/engine/agent/reasoning/prompt-sections/base-actions.ts +134 -134
  110. package/src/execution/engine/agent/reasoning/prompt-sections/completion.ts +49 -49
  111. package/src/execution/engine/agent/reasoning/prompt-sections/knowledge-map.ts +93 -93
  112. package/src/execution/engine/agent/reasoning/prompt-sections/memory.ts +65 -65
  113. package/src/execution/engine/agent/reasoning/prompt-sections/tools.ts +44 -44
  114. package/src/execution/engine/agent/reasoning/request-builder.ts +169 -169
  115. package/src/execution/engine/agent/reasoning/types.ts +18 -18
  116. package/src/execution/engine/base/errors.ts +118 -118
  117. package/src/execution/engine/base/index.ts +2 -2
  118. package/src/execution/engine/base/logging.ts +31 -31
  119. package/src/execution/engine/base/serialization.ts +324 -324
  120. package/src/execution/engine/base/types.ts +126 -126
  121. package/src/execution/engine/base/utils.ts +41 -41
  122. package/src/execution/engine/index.ts +434 -434
  123. package/src/execution/engine/interface/index.ts +1 -1
  124. package/src/execution/engine/interface/types.ts +62 -62
  125. package/src/execution/engine/llm/__tests__/model-info.test.ts +50 -50
  126. package/src/execution/engine/llm/__tests__/model-validation.test.ts +321 -321
  127. package/src/execution/engine/llm/__tests__/response-schema-validator.test.ts +115 -115
  128. package/src/execution/engine/llm/adapters/__tests__/adapter-factory.test.ts +375 -375
  129. package/src/execution/engine/llm/adapters/__tests__/anthropic-adapter.test.ts +463 -463
  130. package/src/execution/engine/llm/adapters/__tests__/anthropic.integration.test.ts +177 -177
  131. package/src/execution/engine/llm/adapters/__tests__/google-adapter.test.ts +722 -722
  132. package/src/execution/engine/llm/adapters/__tests__/google.integration.test.ts +376 -376
  133. package/src/execution/engine/llm/adapters/__tests__/openai-adapter.test.ts +551 -551
  134. package/src/execution/engine/llm/adapters/__tests__/openrouter-adapter.test.ts +563 -563
  135. package/src/execution/engine/llm/adapters/__tests__/openrouter.integration.test.ts +105 -105
  136. package/src/execution/engine/llm/adapters/__tests__/universal-adapter.test.ts +537 -537
  137. package/src/execution/engine/llm/adapters/circuit-breaker.ts +147 -147
  138. package/src/execution/engine/llm/adapters/index.ts +17 -17
  139. package/src/execution/engine/llm/adapters/mock-adapter.ts +116 -116
  140. package/src/execution/engine/llm/adapters/server/adapter-factory.ts +130 -130
  141. package/src/execution/engine/llm/adapters/server/anthropic.ts +137 -137
  142. package/src/execution/engine/llm/adapters/server/google.ts +283 -283
  143. package/src/execution/engine/llm/adapters/server/index.ts +12 -12
  144. package/src/execution/engine/llm/adapters/server/openai.ts +206 -206
  145. package/src/execution/engine/llm/adapters/server/openrouter.ts +235 -235
  146. package/src/execution/engine/llm/adapters/universal-adapter.ts +230 -230
  147. package/src/execution/engine/llm/errors.ts +186 -186
  148. package/src/execution/engine/llm/model-info.ts +332 -332
  149. package/src/execution/engine/llm/response-schema-validator.ts +113 -113
  150. package/src/execution/engine/llm/types.ts +86 -86
  151. package/src/execution/engine/test-utils/index.ts +6 -6
  152. package/src/execution/engine/test-utils/mocks.ts +56 -56
  153. package/src/execution/engine/tools/integration/base-integration-adapter.ts +50 -50
  154. package/src/execution/engine/tools/integration/index.ts +53 -53
  155. package/src/execution/engine/tools/integration/server/adapters/anymailfinder/anymailfinder-adapter.ts +73 -73
  156. package/src/execution/engine/tools/integration/server/adapters/anymailfinder/anymailfinder-tools.ts +209 -209
  157. package/src/execution/engine/tools/integration/server/adapters/anymailfinder/fetch/find-company-email/index.ts +82 -82
  158. package/src/execution/engine/tools/integration/server/adapters/anymailfinder/fetch/find-decision-maker-email/index.ts +122 -122
  159. package/src/execution/engine/tools/integration/server/adapters/anymailfinder/fetch/find-person-email/index.ts +89 -89
  160. package/src/execution/engine/tools/integration/server/adapters/anymailfinder/fetch/verify-email/index.ts +84 -84
  161. package/src/execution/engine/tools/integration/server/adapters/anymailfinder/index.ts +16 -16
  162. package/src/execution/engine/tools/integration/server/adapters/apify/__tests__/apify-run-actor.integration.test.ts +293 -293
  163. package/src/execution/engine/tools/integration/server/adapters/apify/apify-adapter.ts +100 -100
  164. package/src/execution/engine/tools/integration/server/adapters/apify/apify-tools.ts +217 -217
  165. package/src/execution/engine/tools/integration/server/adapters/apify/fetch/get-dataset-items/index.ts +92 -92
  166. package/src/execution/engine/tools/integration/server/adapters/apify/fetch/run-actor/index.ts +218 -218
  167. package/src/execution/engine/tools/integration/server/adapters/apify/fetch/start-actor/index.ts +87 -87
  168. package/src/execution/engine/tools/integration/server/adapters/apify/index.ts +11 -11
  169. package/src/execution/engine/tools/integration/server/adapters/attio/__tests__/attio-crud.integration.test.ts +361 -361
  170. package/src/execution/engine/tools/integration/server/adapters/attio/attio-adapter.ts +162 -162
  171. package/src/execution/engine/tools/integration/server/adapters/attio/attio-tools.ts +594 -594
  172. package/src/execution/engine/tools/integration/server/adapters/attio/fetch/create-attribute/index.ts +214 -214
  173. package/src/execution/engine/tools/integration/server/adapters/attio/fetch/create-note/index.ts +152 -152
  174. package/src/execution/engine/tools/integration/server/adapters/attio/fetch/create-record/index.ts +141 -141
  175. package/src/execution/engine/tools/integration/server/adapters/attio/fetch/delete-note/index.ts +86 -86
  176. package/src/execution/engine/tools/integration/server/adapters/attio/fetch/delete-record/index.ts +105 -105
  177. package/src/execution/engine/tools/integration/server/adapters/attio/fetch/get-record/index.ts +118 -118
  178. package/src/execution/engine/tools/integration/server/adapters/attio/fetch/list-attributes/index.ts +165 -165
  179. package/src/execution/engine/tools/integration/server/adapters/attio/fetch/list-notes/index.ts +96 -96
  180. package/src/execution/engine/tools/integration/server/adapters/attio/fetch/list-objects/index.ts +104 -104
  181. package/src/execution/engine/tools/integration/server/adapters/attio/fetch/list-records/index.ts +156 -156
  182. package/src/execution/engine/tools/integration/server/adapters/attio/fetch/update-attribute/index.ts +220 -220
  183. package/src/execution/engine/tools/integration/server/adapters/attio/fetch/update-record/index.ts +140 -140
  184. package/src/execution/engine/tools/integration/server/adapters/attio/fetch/utils/types.ts +146 -146
  185. package/src/execution/engine/tools/integration/server/adapters/attio/index.ts +31 -31
  186. package/src/execution/engine/tools/integration/server/adapters/gmail/gmail-adapter.ts +210 -210
  187. package/src/execution/engine/tools/integration/server/adapters/gmail/gmail-tools.ts +104 -104
  188. package/src/execution/engine/tools/integration/server/adapters/google-sheets/__tests__/google-sheets.integration.test.ts +261 -261
  189. package/src/execution/engine/tools/integration/server/adapters/google-sheets/google-sheets-adapter.ts +1189 -1189
  190. package/src/execution/engine/tools/integration/server/adapters/google-sheets/google-sheets-tools.ts +641 -641
  191. package/src/execution/engine/tools/integration/server/adapters/google-sheets/index.ts +18 -18
  192. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/activate-campaign/index.ts +86 -86
  193. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/add-to-campaign/__tests__/index.test.ts +289 -289
  194. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/add-to-campaign/index.ts +154 -154
  195. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/bulk-add-leads/__tests__/index.test.ts +325 -325
  196. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/bulk-add-leads/index.ts +153 -153
  197. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/bulk-delete-leads/index.ts +84 -84
  198. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/create-campaign/index.ts +125 -125
  199. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/create-inbox-test/index.ts +107 -107
  200. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/delete-campaign/index.ts +85 -85
  201. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/get-account-health/index.ts +91 -91
  202. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/get-campaign/index.ts +92 -92
  203. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/get-campaign-analytics/__tests__/index.test.ts +195 -195
  204. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/get-campaign-analytics/index.ts +113 -113
  205. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/get-daily-campaign-analytics/index.ts +104 -104
  206. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/get-emails/index.ts +155 -155
  207. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/get-step-analytics/__tests__/index.test.ts +196 -196
  208. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/get-step-analytics/index.ts +102 -102
  209. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/list-campaigns/__tests__/index.test.ts +189 -189
  210. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/list-campaigns/index.ts +87 -87
  211. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/list-leads/index.ts +112 -112
  212. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/patch-lead/index.ts +76 -76
  213. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/pause-campaign/index.ts +86 -86
  214. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/remove-from-subsequence/index.ts +98 -98
  215. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/send-reply/index.ts +126 -126
  216. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/update-campaign/__tests__/index.test.ts +193 -193
  217. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/update-campaign/index.ts +99 -99
  218. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/update-interest-status/__tests__/index.test.ts +621 -621
  219. package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/update-interest-status/index.ts +125 -125
  220. package/src/execution/engine/tools/integration/server/adapters/instantly/index.ts +29 -29
  221. package/src/execution/engine/tools/integration/server/adapters/instantly/instantly-adapter.ts +178 -178
  222. package/src/execution/engine/tools/integration/server/adapters/instantly/instantly-tools.ts +1473 -1473
  223. package/src/execution/engine/tools/integration/server/adapters/millionverifier/fetch/check-credits/index.ts +59 -59
  224. package/src/execution/engine/tools/integration/server/adapters/millionverifier/fetch/verify-email/index.ts +102 -102
  225. package/src/execution/engine/tools/integration/server/adapters/millionverifier/index.ts +17 -17
  226. package/src/execution/engine/tools/integration/server/adapters/millionverifier/millionverifier-adapter.ts +80 -80
  227. package/src/execution/engine/tools/integration/server/adapters/millionverifier/millionverifier-tools.ts +102 -102
  228. package/src/execution/engine/tools/integration/server/adapters/resend/fetch/get-email/index.ts +102 -102
  229. package/src/execution/engine/tools/integration/server/adapters/resend/fetch/send-email/index.ts +134 -134
  230. package/src/execution/engine/tools/integration/server/adapters/resend/fetch/utils/types.ts +75 -75
  231. package/src/execution/engine/tools/integration/server/adapters/resend/index.ts +27 -27
  232. package/src/execution/engine/tools/integration/server/adapters/resend/resend-adapter.ts +108 -108
  233. package/src/execution/engine/tools/integration/server/adapters/resend/resend-tools.ts +132 -132
  234. package/src/execution/engine/tools/integration/server/adapters/signature-api/fetch/create-envelope/index.ts +274 -274
  235. package/src/execution/engine/tools/integration/server/adapters/signature-api/fetch/download-document/index.ts +230 -230
  236. package/src/execution/engine/tools/integration/server/adapters/signature-api/fetch/get-envelope/index.ts +133 -133
  237. package/src/execution/engine/tools/integration/server/adapters/signature-api/fetch/void-envelope/index.ts +90 -90
  238. package/src/execution/engine/tools/integration/server/adapters/stripe/fetch/utils/types.ts +210 -210
  239. package/src/execution/engine/tools/integration/server/adapters/stripe/stripe-adapter.ts +517 -517
  240. package/src/execution/engine/tools/integration/server/adapters/stripe/stripe-tools.ts +309 -309
  241. package/src/execution/engine/tools/integration/server/adapters/tomba/fetch/domain-search/index.ts +133 -133
  242. package/src/execution/engine/tools/integration/server/adapters/tomba/fetch/email-finder/index.ts +122 -122
  243. package/src/execution/engine/tools/integration/server/adapters/tomba/fetch/email-verifier/index.ts +111 -111
  244. package/src/execution/engine/tools/integration/server/adapters/tomba/index.ts +11 -11
  245. package/src/execution/engine/tools/integration/server/adapters/tomba/tomba-adapter.ts +78 -78
  246. package/src/execution/engine/tools/integration/server/adapters/tomba/tomba-tools.ts +222 -222
  247. package/src/execution/engine/tools/integration/server/index.ts +61 -61
  248. package/src/execution/engine/tools/integration/service.ts +161 -161
  249. package/src/execution/engine/tools/integration/tool.ts +253 -253
  250. package/src/execution/engine/tools/integration/types/anymailfinder.ts +74 -74
  251. package/src/execution/engine/tools/integration/types/apify.ts +92 -92
  252. package/src/execution/engine/tools/integration/types/index.ts +19 -19
  253. package/src/execution/engine/tools/integration/types/instantly.ts +557 -557
  254. package/src/execution/engine/tools/integration/types/millionverifier.ts +56 -56
  255. package/src/execution/engine/tools/integration/types/stripe.ts +162 -162
  256. package/src/execution/engine/tools/integration/types/tomba.ts +94 -94
  257. package/src/execution/engine/tools/lead-service-types.ts +884 -884
  258. package/src/execution/engine/tools/llm/index.ts +11 -11
  259. package/src/execution/engine/tools/llm/server/index.ts +8 -8
  260. package/src/execution/engine/tools/llm/server/llm-call-tool.ts +118 -118
  261. package/src/execution/engine/tools/platform/__tests__/pdf.test.ts +441 -441
  262. package/src/execution/engine/tools/platform/acquisition/company-tools.ts +248 -248
  263. package/src/execution/engine/tools/platform/acquisition/contact-tools.ts +319 -319
  264. package/src/execution/engine/tools/platform/acquisition/index.ts +43 -43
  265. package/src/execution/engine/tools/platform/acquisition/list-tools.ts +148 -148
  266. package/src/execution/engine/tools/platform/acquisition/types.ts +260 -260
  267. package/src/execution/engine/tools/platform/email/index.ts +122 -122
  268. package/src/execution/engine/tools/platform/email/types.ts +96 -96
  269. package/src/execution/engine/tools/platform/index.ts +157 -157
  270. package/src/execution/engine/tools/platform/notification.ts +81 -81
  271. package/src/execution/engine/tools/platform/pdf/index.ts +110 -110
  272. package/src/execution/engine/tools/platform/pdf/types.ts +77 -77
  273. package/src/execution/engine/tools/platform/scheduler.ts +87 -87
  274. package/src/execution/engine/tools/platform/storage/index.ts +370 -370
  275. package/src/execution/engine/tools/platform/types.ts +148 -148
  276. package/src/execution/engine/tools/registry.ts +700 -700
  277. package/src/execution/engine/tools/tool-maps.ts +786 -786
  278. package/src/execution/engine/tools/types.ts +233 -233
  279. package/src/execution/engine/workflow/__tests__/errors.test.ts +139 -139
  280. package/src/execution/engine/workflow/errors.ts +63 -63
  281. package/src/execution/engine/workflow/helpers/index.ts +11 -11
  282. package/src/execution/engine/workflow/helpers/server/index.ts +8 -8
  283. package/src/execution/engine/workflow/helpers/server/llm-call.ts +93 -93
  284. package/src/execution/engine/workflow/index.ts +19 -19
  285. package/src/execution/engine/workflow/log-truncate.ts +26 -26
  286. package/src/execution/engine/workflow/logging.ts +191 -191
  287. package/src/execution/engine/workflow/types.ts +182 -182
  288. package/src/execution/engine/workflow/utils.ts +280 -280
  289. package/src/execution/engine/workflow/workflow.ts +168 -168
  290. package/src/execution/index.ts +3 -3
  291. package/src/execution/scheduler/__tests__/api-schemas.test.ts +733 -733
  292. package/src/execution/scheduler/__tests__/utils.test.ts +1009 -1009
  293. package/src/execution/scheduler/api-schemas.ts +296 -296
  294. package/src/execution/scheduler/index.ts +50 -50
  295. package/src/execution/scheduler/schemas.ts +264 -264
  296. package/src/execution/scheduler/types.ts +111 -111
  297. package/src/execution/scheduler/utils.ts +364 -364
  298. package/src/forms/index.ts +7 -7
  299. package/src/forms/schemas.ts +69 -69
  300. package/src/forms/types.ts +70 -70
  301. package/src/index.ts +71 -60
  302. package/src/integrations/credentials/__tests__/schemas.test.ts +82 -82
  303. package/src/integrations/credentials/__tests__/utils.test.ts +144 -144
  304. package/src/integrations/credentials/api-schemas.ts +143 -143
  305. package/src/integrations/credentials/index.ts +32 -32
  306. package/src/integrations/credentials/schemas.ts +164 -164
  307. package/src/integrations/credentials/utils.ts +59 -59
  308. package/src/integrations/oauth/__tests__/provider-registry.test.ts +59 -59
  309. package/src/integrations/oauth/api-schemas.ts +92 -92
  310. package/src/integrations/oauth/index.ts +19 -19
  311. package/src/integrations/oauth/provider-registry.ts +61 -61
  312. package/src/integrations/oauth/server/__tests__/refresh-concurrent.test.ts +183 -183
  313. package/src/integrations/oauth/server/__tests__/refresh.test.ts +577 -577
  314. package/src/integrations/oauth/server/credentials.ts +39 -39
  315. package/src/integrations/oauth/server/refresh.ts +214 -214
  316. package/src/integrations/oauth/types.ts +34 -34
  317. package/src/integrations/webhook-endpoints/__tests__/api-schemas.test.ts +318 -318
  318. package/src/integrations/webhook-endpoints/api-schemas.ts +102 -102
  319. package/src/integrations/webhook-endpoints/index.ts +28 -28
  320. package/src/integrations/webhook-endpoints/types.ts +51 -51
  321. package/src/operations/activities/api-schemas.ts +79 -79
  322. package/src/operations/activities/index.ts +9 -9
  323. package/src/operations/activities/sse-events.ts +30 -30
  324. package/src/operations/activities/types.ts +63 -63
  325. package/src/operations/debug-logs/client.ts +60 -60
  326. package/src/operations/debug-logs/debug-logger.ts +83 -83
  327. package/src/operations/debug-logs/index.ts +8 -8
  328. package/src/operations/debug-logs/server.ts +19 -19
  329. package/src/operations/debug-logs/types.ts +33 -33
  330. package/src/operations/index.ts +50 -50
  331. package/src/operations/notifications/api-schemas.ts +91 -91
  332. package/src/operations/notifications/index.ts +3 -3
  333. package/src/operations/notifications/sse-events.ts +21 -21
  334. package/src/operations/notifications/types.ts +47 -47
  335. package/src/operations/observability/__tests__/openrouter-cost-flow.test.ts +297 -297
  336. package/src/operations/observability/__tests__/utils.test.ts +54 -54
  337. package/src/operations/observability/ai-usage-collector.ts +64 -64
  338. package/src/operations/observability/index.ts +13 -13
  339. package/src/operations/observability/metrics-collector.ts +49 -49
  340. package/src/operations/observability/schemas.ts +39 -39
  341. package/src/operations/observability/types.ts +463 -463
  342. package/src/operations/observability/utils.ts +77 -77
  343. package/src/operations/sessions/__tests__/manager.test.ts +821 -821
  344. package/src/operations/sessions/index.ts +26 -26
  345. package/src/operations/sessions/server/manager.ts +90 -90
  346. package/src/operations/sessions/server/session.ts +180 -180
  347. package/src/operations/sessions/types.ts +98 -98
  348. package/src/operations/triggers/index.ts +12 -12
  349. package/src/operations/triggers/webhook/definitions/instantly-account-error.ts +44 -44
  350. package/src/operations/triggers/webhook/definitions/instantly-auto-reply-received.ts +51 -51
  351. package/src/operations/triggers/webhook/definitions/instantly-campaign-completed.ts +45 -45
  352. package/src/operations/triggers/webhook/definitions/instantly-email-bounced.ts +49 -49
  353. package/src/operations/triggers/webhook/definitions/instantly-lead-unsubscribed.ts +45 -45
  354. package/src/operations/triggers/webhook/definitions/instantly-reply-received.ts +54 -54
  355. package/src/operations/triggers/webhook/index.ts +35 -35
  356. package/src/operations/triggers/webhook/types.ts +74 -74
  357. package/src/organization-model/README.md +97 -97
  358. package/src/organization-model/__tests__/defaults.test.ts +175 -175
  359. package/src/organization-model/__tests__/domains/customers.test.ts +295 -295
  360. package/src/organization-model/__tests__/domains/goals.test.ts +479 -479
  361. package/src/organization-model/__tests__/domains/identity.test.ts +279 -279
  362. package/src/organization-model/__tests__/domains/navigation.test.ts +212 -212
  363. package/src/organization-model/__tests__/domains/offerings.test.ts +419 -419
  364. package/src/organization-model/__tests__/domains/operations.test.ts +203 -203
  365. package/src/organization-model/__tests__/domains/resource-mappings.test.ts +362 -362
  366. package/src/organization-model/__tests__/domains/roles.test.ts +347 -347
  367. package/src/organization-model/__tests__/domains/statuses.test.ts +243 -243
  368. package/src/organization-model/__tests__/foundation.test.ts +105 -105
  369. package/src/organization-model/__tests__/graph.test.ts +894 -894
  370. package/src/organization-model/__tests__/resolve.test.ts +690 -690
  371. package/src/organization-model/__tests__/schema.test.ts +407 -407
  372. package/src/organization-model/contracts.ts +14 -14
  373. package/src/organization-model/defaults.ts +148 -148
  374. package/src/organization-model/domains/branding.ts +22 -22
  375. package/src/organization-model/domains/customers.ts +75 -75
  376. package/src/organization-model/domains/features.ts +22 -22
  377. package/src/organization-model/domains/goals.ts +80 -80
  378. package/src/organization-model/domains/identity.ts +94 -94
  379. package/src/organization-model/domains/navigation.ts +391 -391
  380. package/src/organization-model/domains/offerings.ts +66 -66
  381. package/src/organization-model/domains/operations.ts +85 -85
  382. package/src/organization-model/domains/projects.ts +48 -48
  383. package/src/organization-model/domains/prospecting.ts +33 -33
  384. package/src/organization-model/domains/roles.ts +55 -55
  385. package/src/organization-model/domains/sales.ts +94 -94
  386. package/src/organization-model/domains/shared.ts +62 -62
  387. package/src/organization-model/domains/statuses.ts +130 -130
  388. package/src/organization-model/foundation.ts +97 -97
  389. package/src/organization-model/graph/build.ts +399 -399
  390. package/src/organization-model/graph/index.ts +4 -4
  391. package/src/organization-model/graph/schema.ts +48 -48
  392. package/src/organization-model/graph/types.ts +40 -40
  393. package/src/organization-model/index.ts +13 -13
  394. package/src/organization-model/organization-graph.mdx +272 -272
  395. package/src/organization-model/organization-model.mdx +320 -320
  396. package/src/organization-model/published.ts +85 -85
  397. package/src/organization-model/resolve.ts +66 -66
  398. package/src/organization-model/schema.ts +287 -287
  399. package/src/organization-model/types.ts +46 -46
  400. package/src/platform/api/index.ts +1 -1
  401. package/src/platform/api/types.ts +35 -35
  402. package/src/platform/constants/http.ts +37 -37
  403. package/src/platform/constants/index.ts +5 -5
  404. package/src/platform/constants/limits.ts +32 -32
  405. package/src/platform/constants/resilience.ts +51 -51
  406. package/src/platform/constants/timeouts.ts +20 -20
  407. package/src/platform/constants/versions.ts +3 -3
  408. package/src/platform/registry/__tests__/resource-registry-static.test.ts +347 -347
  409. package/src/platform/registry/__tests__/resource-registry.integration.test.ts +1028 -1028
  410. package/src/platform/registry/__tests__/resource-registry.list-executable.test.ts +393 -393
  411. package/src/platform/registry/__tests__/resource-registry.test.ts +2005 -2005
  412. package/src/platform/registry/__tests__/serialization.test.ts +1127 -1127
  413. package/src/platform/registry/command-view.ts +180 -180
  414. package/src/platform/registry/domains.ts +165 -165
  415. package/src/platform/registry/index.ts +93 -93
  416. package/src/platform/registry/reserved.ts +24 -24
  417. package/src/platform/registry/resource-metadata.ts +59 -59
  418. package/src/platform/registry/resource-registry.command-queue-groups.test.ts +129 -129
  419. package/src/platform/registry/resource-registry.ts +876 -876
  420. package/src/platform/registry/serialization.ts +273 -273
  421. package/src/platform/registry/serialized-types.ts +231 -231
  422. package/src/platform/registry/stats-types.ts +66 -66
  423. package/src/platform/registry/types.ts +404 -404
  424. package/src/platform/registry/validation.ts +513 -513
  425. package/src/platform/resilience/__tests__/rate-limiter.test.ts +471 -471
  426. package/src/platform/resilience/circuit-breaker.ts +164 -164
  427. package/src/platform/resilience/errors.ts +68 -68
  428. package/src/platform/resilience/http-error-mapper.ts +129 -129
  429. package/src/platform/resilience/index.ts +93 -93
  430. package/src/platform/resilience/rate-limiter-types.ts +46 -46
  431. package/src/platform/resilience/rate-limiter.ts +140 -140
  432. package/src/platform/resilience/retry.ts +89 -89
  433. package/src/platform/resilience/timeout.ts +63 -63
  434. package/src/platform/sse/events.ts +37 -37
  435. package/src/platform/sse/index.ts +7 -7
  436. package/src/platform/utils/__tests__/validation.test.ts +1083 -1083
  437. package/src/platform/utils/currency.ts +96 -96
  438. package/src/platform/utils/debounce.ts +52 -52
  439. package/src/platform/utils/error.ts +41 -41
  440. package/src/platform/utils/hmac.test.ts +97 -97
  441. package/src/platform/utils/index.ts +32 -32
  442. package/src/platform/utils/server/betterstack-logger.ts +210 -210
  443. package/src/platform/utils/server/hmac.ts +44 -44
  444. package/src/platform/utils/server/unsubscribe.ts +111 -111
  445. package/src/platform/utils/token-counter.ts +96 -96
  446. package/src/platform/utils/validation.ts +425 -425
  447. package/src/projects/api-schemas.ts +268 -268
  448. package/src/published.ts +1 -1
  449. package/src/reference/_generated/contracts.md +607 -607
  450. package/src/reference/glossary.md +105 -105
  451. package/src/requests/__tests__/api-schemas.test.ts +277 -277
  452. package/src/requests/api-schemas.ts +83 -83
  453. package/src/requests/index.ts +1 -1
  454. package/src/scaffold-registry/__tests__/index.test.ts +17 -0
  455. package/src/scaffold-registry/__tests__/schema.test.ts +329 -230
  456. package/src/scaffold-registry/index.ts +205 -189
  457. package/src/scaffold-registry/schema.ts +196 -128
  458. package/src/server.ts +272 -272
  459. package/src/supabase/database.types.ts +2719 -2719
  460. package/src/supabase/helpers.ts +20 -20
  461. package/src/supabase/index.ts +52 -52
  462. package/src/supabase/server/client.ts +58 -58
  463. package/src/test-utils/README.md +30 -138
  464. package/src/test-utils/browser-mocks.ts +54 -54
  465. package/src/test-utils/fixtures/api-keys.ts +52 -52
  466. package/src/test-utils/fixtures/index.ts +4 -4
  467. package/src/test-utils/fixtures/memberships.ts +80 -80
  468. package/src/test-utils/fixtures/organizations.ts +69 -69
  469. package/src/test-utils/fixtures/users.ts +79 -79
  470. package/src/test-utils/index.ts +7 -8
  471. package/src/test-utils/mocks/index.ts +2 -2
  472. package/src/test-utils/mocks/supabase.ts +142 -142
  473. package/src/test-utils/mocks/workos.ts +108 -108
  474. package/src/test-utils/published.ts +4 -0
  475. package/src/test-utils/rls/RLSTestContext.ts +554 -554
  476. 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
+ }