@botpress/adk 1.16.7 → 1.18.0-beta.1

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 (156) hide show
  1. package/dist/agent-init/agent-project-generator.d.ts +32 -8
  2. package/dist/agent-init/agent-project-generator.d.ts.map +1 -1
  3. package/dist/agent-init/index.d.ts +1 -0
  4. package/dist/agent-init/index.d.ts.map +1 -1
  5. package/dist/agent-project/agent-project.d.ts +13 -1
  6. package/dist/agent-project/agent-project.d.ts.map +1 -1
  7. package/dist/agent-project/agent-resolver.d.ts +4 -3
  8. package/dist/agent-project/agent-resolver.d.ts.map +1 -1
  9. package/dist/agent-project/config-writer.d.ts +33 -0
  10. package/dist/agent-project/config-writer.d.ts.map +1 -1
  11. package/dist/agent-project/dependencies-parser.d.ts.map +1 -1
  12. package/dist/agent-project/index.d.ts +1 -1
  13. package/dist/agent-project/index.d.ts.map +1 -1
  14. package/dist/agent-project/types.d.ts +48 -22
  15. package/dist/agent-project/types.d.ts.map +1 -1
  16. package/dist/agent-project/validation-errors.d.ts.map +1 -1
  17. package/dist/auth/credentials.d.ts +15 -1
  18. package/dist/auth/credentials.d.ts.map +1 -1
  19. package/dist/auth/index.d.ts +2 -0
  20. package/dist/auth/index.d.ts.map +1 -1
  21. package/dist/bot-generator/dev-id-manager.d.ts.map +1 -1
  22. package/dist/bot-generator/generator.d.ts.map +1 -1
  23. package/dist/commands/base-command.d.ts.map +1 -1
  24. package/dist/commands/bp-add-command.d.ts.map +1 -1
  25. package/dist/commands/bp-build-command.d.ts.map +1 -1
  26. package/dist/commands/bp-chat-command.d.ts.map +1 -1
  27. package/dist/commands/bp-deploy-command.d.ts.map +1 -1
  28. package/dist/commands/bp-dev-command.d.ts +2 -2
  29. package/dist/commands/bp-dev-command.d.ts.map +1 -1
  30. package/dist/commands/opencode-command.d.ts +2 -2
  31. package/dist/commands/opencode-command.d.ts.map +1 -1
  32. package/dist/commands/opencode-config.d.ts +1 -1
  33. package/dist/commands/opencode-config.d.ts.map +1 -1
  34. package/dist/config/coerce-config-value.d.ts.map +1 -1
  35. package/dist/config/manager.d.ts +5 -5
  36. package/dist/config/manager.d.ts.map +1 -1
  37. package/dist/eval/client.d.ts +8 -0
  38. package/dist/eval/client.d.ts.map +1 -1
  39. package/dist/eval/graders/index.d.ts +1 -0
  40. package/dist/eval/graders/index.d.ts.map +1 -1
  41. package/dist/eval/graders/llm.d.ts +6 -2
  42. package/dist/eval/graders/llm.d.ts.map +1 -1
  43. package/dist/eval/graders/response.d.ts +1 -0
  44. package/dist/eval/graders/response.d.ts.map +1 -1
  45. package/dist/eval/graders/state.d.ts +1 -1
  46. package/dist/eval/graders/state.d.ts.map +1 -1
  47. package/dist/eval/graders/tables.d.ts.map +1 -1
  48. package/dist/eval/graders/timing.d.ts +7 -0
  49. package/dist/eval/graders/timing.d.ts.map +1 -0
  50. package/dist/eval/graders/workflow.d.ts.map +1 -1
  51. package/dist/eval/index.d.ts +3 -3
  52. package/dist/eval/index.d.ts.map +1 -1
  53. package/dist/eval/loader.d.ts +2 -1
  54. package/dist/eval/loader.d.ts.map +1 -1
  55. package/dist/eval/runner.d.ts +1 -0
  56. package/dist/eval/runner.d.ts.map +1 -1
  57. package/dist/eval/traces.d.ts.map +1 -1
  58. package/dist/eval/types.d.ts +62 -4
  59. package/dist/eval/types.d.ts.map +1 -1
  60. package/dist/file-watcher/watcher.d.ts +9 -0
  61. package/dist/file-watcher/watcher.d.ts.map +1 -1
  62. package/dist/generators/client-wrapper.d.ts.map +1 -1
  63. package/dist/generators/conversation-types.d.ts.map +1 -1
  64. package/dist/generators/integration-types.d.ts.map +1 -1
  65. package/dist/generators/interface-types.d.ts.map +1 -1
  66. package/dist/generators/plugin-types.d.ts.map +1 -1
  67. package/dist/generators/table-types.d.ts.map +1 -1
  68. package/dist/generators/tests.d.ts.map +1 -1
  69. package/dist/generators/workflow-types.d.ts.map +1 -1
  70. package/dist/index.d.ts +6 -5
  71. package/dist/index.d.ts.map +1 -1
  72. package/dist/index.js +1194 -594
  73. package/dist/index.js.map +62 -61
  74. package/dist/integrations/checker.d.ts +2 -2
  75. package/dist/integrations/checker.d.ts.map +1 -1
  76. package/dist/integrations/config-utils.d.ts +4 -3
  77. package/dist/integrations/config-utils.d.ts.map +1 -1
  78. package/dist/integrations/operations.d.ts +19 -6
  79. package/dist/integrations/operations.d.ts.map +1 -1
  80. package/dist/integrations/types.d.ts +1 -1
  81. package/dist/integrations/types.d.ts.map +1 -1
  82. package/dist/interfaces/manager.d.ts.map +1 -1
  83. package/dist/interfaces/types.d.ts +1 -1
  84. package/dist/interfaces/types.d.ts.map +1 -1
  85. package/dist/knowledge/manager.d.ts.map +1 -1
  86. package/dist/plugins/types.d.ts +1 -1
  87. package/dist/plugins/types.d.ts.map +1 -1
  88. package/dist/preflight/agent-config-sync.d.ts +2 -1
  89. package/dist/preflight/agent-config-sync.d.ts.map +1 -1
  90. package/dist/preflight/checker.d.ts.map +1 -1
  91. package/dist/preflight/types.d.ts +8 -8
  92. package/dist/preflight/types.d.ts.map +1 -1
  93. package/dist/runner/index.d.ts +1 -1
  94. package/dist/runner/script-runner.d.ts +1 -1
  95. package/dist/runner/script-runner.d.ts.map +1 -1
  96. package/dist/tables/table-manager.d.ts.map +1 -1
  97. package/dist/tables/types.d.ts +2 -1
  98. package/dist/tables/types.d.ts.map +1 -1
  99. package/dist/templates/README.md +101 -0
  100. package/dist/templates/blank/README.md +36 -0
  101. package/dist/templates/blank/agent.config.ts +49 -0
  102. package/dist/templates/blank/package.json +17 -0
  103. package/dist/templates/blank/src/actions/index.ts +19 -0
  104. package/dist/templates/blank/src/conversations/index.ts +16 -0
  105. package/dist/templates/blank/src/knowledge/index.ts +17 -0
  106. package/dist/templates/blank/src/tables/index.ts +19 -0
  107. package/dist/templates/blank/src/triggers/index.ts +20 -0
  108. package/dist/templates/blank/src/workflows/index.ts +23 -0
  109. package/dist/templates/blank/tsconfig.json +22 -0
  110. package/dist/templates/crm-enrichment/README.md +85 -0
  111. package/dist/templates/crm-enrichment/agent.config.ts +33 -0
  112. package/dist/templates/crm-enrichment/package.json +17 -0
  113. package/dist/templates/crm-enrichment/src/actions/enrich-contact.ts +81 -0
  114. package/dist/templates/crm-enrichment/src/conversations/index.ts +14 -0
  115. package/dist/templates/crm-enrichment/src/knowledge/index.ts +17 -0
  116. package/dist/templates/crm-enrichment/src/tables/contacts.ts +43 -0
  117. package/dist/templates/crm-enrichment/src/triggers/daily-enrichment.ts +30 -0
  118. package/dist/templates/crm-enrichment/src/workflows/enrichment-pipeline.ts +171 -0
  119. package/dist/templates/crm-enrichment/tsconfig.json +22 -0
  120. package/dist/templates/hello-world/README.md +46 -0
  121. package/dist/templates/hello-world/agent.config.ts +48 -0
  122. package/dist/templates/hello-world/package.json +17 -0
  123. package/dist/templates/hello-world/src/actions/index.ts +19 -0
  124. package/dist/templates/hello-world/src/conversations/index.ts +10 -0
  125. package/dist/templates/hello-world/src/knowledge/index.ts +17 -0
  126. package/dist/templates/hello-world/src/tables/index.ts +19 -0
  127. package/dist/templates/hello-world/src/triggers/index.ts +20 -0
  128. package/dist/templates/hello-world/src/workflows/index.ts +23 -0
  129. package/dist/templates/hello-world/tsconfig.json +22 -0
  130. package/dist/templates/knowledge-assistant/README.md +66 -0
  131. package/dist/templates/knowledge-assistant/agent.config.ts +26 -0
  132. package/dist/templates/knowledge-assistant/package.json +17 -0
  133. package/dist/templates/knowledge-assistant/src/actions/index.ts +19 -0
  134. package/dist/templates/knowledge-assistant/src/actions/search-docs.ts +50 -0
  135. package/dist/templates/knowledge-assistant/src/conversations/index.ts +33 -0
  136. package/dist/templates/knowledge-assistant/src/knowledge/docs.ts +23 -0
  137. package/dist/templates/knowledge-assistant/src/knowledge/getting-started.md +49 -0
  138. package/dist/templates/knowledge-assistant/src/tables/index.ts +21 -0
  139. package/dist/templates/knowledge-assistant/src/triggers/index.ts +17 -0
  140. package/dist/templates/knowledge-assistant/src/workflows/index.ts +28 -0
  141. package/dist/templates/knowledge-assistant/tsconfig.json +22 -0
  142. package/dist/templates/slack-triage/README.md +74 -0
  143. package/dist/templates/slack-triage/agent.config.ts +35 -0
  144. package/dist/templates/slack-triage/evals/triage-basic.eval.ts +55 -0
  145. package/dist/templates/slack-triage/package.json +17 -0
  146. package/dist/templates/slack-triage/src/actions/classify-request.ts +65 -0
  147. package/dist/templates/slack-triage/src/conversations/slack-dm.ts +72 -0
  148. package/dist/templates/slack-triage/src/knowledge/team-directory.md +33 -0
  149. package/dist/templates/slack-triage/src/tables/routing-rules.ts +38 -0
  150. package/dist/templates/slack-triage/src/triggers/new-message.ts +44 -0
  151. package/dist/templates/slack-triage/src/workflows/triage-flow.ts +104 -0
  152. package/dist/templates/slack-triage/tsconfig.json +22 -0
  153. package/dist/templates/template.config.json +47 -0
  154. package/dist/utils/json-ordering.d.ts +5 -4
  155. package/dist/utils/json-ordering.d.ts.map +1 -1
  156. package/package.json +31 -38
@@ -0,0 +1,20 @@
1
+ // import { Trigger } from '@botpress/runtime'
2
+ //
3
+ // /**
4
+ // * An event subscription that fires automatically when the specified events occur.
5
+ // * Bot events: 'register', 'message.created', 'conversation.started', 'conversation.ended',
6
+ // * 'user.created', 'workflow.started', 'workflow.completed', 'workflow.failed'
7
+ // * Webchat: 'webchat:conversationStarted', 'webchat:trigger'
8
+ // * Slack: 'slack:reactionAdded', 'slack:memberJoinedChannel'
9
+ // * Linear: 'linear:issueCreated', 'linear:issueUpdated'
10
+ // * GitHub: 'github:issueOpened', 'github:pullRequestMerged'
11
+ // * Run `adk info <integration>` to see all events for an integration.
12
+ // */
13
+ // export default new Trigger({
14
+ // name: 'onRegister',
15
+ // description: 'Runs on bot startup to initialize state',
16
+ // events: ['register'],
17
+ // handler: async () => {
18
+ // console.log('Bot started!')
19
+ // },
20
+ // })
@@ -0,0 +1,23 @@
1
+ // import { Workflow, z } from '@botpress/runtime'
2
+ //
3
+ // /**
4
+ // * A multi-step, resumable process that persists state across executions.
5
+ // * Each `step()` call is checkpointed — safe to retry on failure.
6
+ // * Use `step.sleep()`, `step.request()`, or `step.listen()` to pause execution.
7
+ // * Start from a trigger or conversation via `MyWorkflow.start({ input })`.
8
+ // */
9
+ // export const MyWorkflow = new Workflow({
10
+ // name: 'myWorkflow',
11
+ // input: z.object({
12
+ // data: z.string().describe('Input data to process'),
13
+ // }),
14
+ // output: z.object({
15
+ // result: z.string().describe('The processed result'),
16
+ // }),
17
+ // handler: async ({ input, step }) => {
18
+ // const result = await step('process', async () => {
19
+ // return `Processed: ${input.data}`
20
+ // })
21
+ // return { result }
22
+ // },
23
+ // })
@@ -0,0 +1,22 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ES2022",
5
+ "moduleResolution": "Bundler",
6
+ "lib": ["ES2022", "DOM"],
7
+ "outDir": "./dist",
8
+ "rootDir": ".",
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "allowSyntheticDefaultImports": true,
12
+ "skipLibCheck": true,
13
+ "forceConsistentCasingInFileNames": true,
14
+ "moduleDetection": "force",
15
+ "resolveJsonModule": true,
16
+ "paths": {
17
+ "@botpress/runtime/_types/*": ["./.adk/*-types"]
18
+ }
19
+ },
20
+ "include": ["src/**/*", ".adk/**/*"],
21
+ "exclude": ["node_modules", "dist"]
22
+ }
@@ -0,0 +1,85 @@
1
+ # {{projectName}}
2
+
3
+ A backend CRM enrichment agent built with the Botpress ADK. This agent runs scheduled workflows to classify, score, and enrich contacts in a table using AI -- no chat interface required.
4
+
5
+ ## How It Works
6
+
7
+ 1. **Contacts table** (`src/tables/contacts.ts`) stores raw and enriched contact data.
8
+ 2. **Enrich action** (`src/actions/enrich-contact.ts`) uses Zai to classify a single contact's use case, industry, and lead score.
9
+ 3. **Enrichment pipeline** (`src/workflows/enrichment-pipeline.ts`) fetches unenriched contacts, enriches each one, and writes results back.
10
+ 4. **Daily trigger** (`src/triggers/daily-enrichment.ts`) kicks off the pipeline on a schedule and on initial bot registration.
11
+
12
+ ## Getting Started
13
+
14
+ 1. Install dependencies:
15
+
16
+ ```bash
17
+ {{packageManager}} install
18
+ ```
19
+
20
+ 2. Start development server:
21
+
22
+ ```bash
23
+ adk dev
24
+ ```
25
+
26
+ 3. Add some contacts to the `ContactsTable` (via `adk run` script or the dev UI), then watch the enrichment pipeline process them.
27
+
28
+ 4. Deploy your agent:
29
+ ```bash
30
+ adk deploy
31
+ ```
32
+
33
+ ## Customizing the Enrichment Logic
34
+
35
+ The core AI classification lives in `src/actions/enrich-contact.ts`. You can customize:
36
+
37
+ - **Use case categories** -- edit the `useCase` enum in the Zai extract schema to match your business.
38
+ - **Industry list** -- expand or narrow the `industry` enum.
39
+ - **Scoring criteria** -- change the `score` enum and the `instructions` string to reflect your ideal customer profile.
40
+ - **Additional fields** -- add more columns to the table and more fields to the extract schema.
41
+
42
+ ## Scheduling
43
+
44
+ The workflow runs on a cron schedule defined in `src/workflows/enrichment-pipeline.ts`:
45
+
46
+ ```typescript
47
+ schedule: '0 9 * * *' // Every day at 9:00 AM UTC
48
+ ```
49
+
50
+ Common alternatives:
51
+
52
+ - `"0 */6 * * *"` -- every 6 hours
53
+ - `"0 9 * * 1-5"` -- weekday mornings only
54
+ - `"*/30 * * * *"` -- every 30 minutes
55
+
56
+ The trigger in `src/triggers/daily-enrichment.ts` also fires on `register` (bot startup) so the pipeline runs once immediately during development.
57
+
58
+ ## Adding Integrations
59
+
60
+ This template starts with no integrations. To extend it:
61
+
62
+ ```bash
63
+ # Send enrichment reports to Slack
64
+ adk add slack@latest
65
+
66
+ # Sync contacts from a CRM
67
+ adk add salesforce@latest
68
+
69
+ # Send email summaries
70
+ adk add sendgrid@latest
71
+ ```
72
+
73
+ ## Project Structure
74
+
75
+ - `src/tables/` -- ContactsTable schema
76
+ - `src/actions/` -- AI enrichment action
77
+ - `src/workflows/` -- Enrichment pipeline workflow
78
+ - `src/triggers/` -- Scheduled trigger
79
+ - `src/conversations/` -- Unused (backend agent)
80
+ - `src/knowledge/` -- Unused (no RAG needed)
81
+
82
+ ## Learn More
83
+
84
+ - [ADK Documentation](https://botpress.com/docs/adk)
85
+ - [Botpress Platform](https://botpress.com)
@@ -0,0 +1,33 @@
1
+ import { z, defineConfig } from '@botpress/runtime'
2
+
3
+ export default defineConfig({
4
+ name: '{{projectName}}',
5
+ description:
6
+ 'A backend agent that enriches CRM contacts with AI-driven classification, scoring, and industry detection',
7
+
8
+ defaultModels: {
9
+ autonomous: 'openai:gpt-4.1-mini-2025-04-14',
10
+ zai: 'openai:gpt-4.1-2025-04-14',
11
+ },
12
+
13
+ // Bot-level persistent state — tracks enrichment run metadata across executions.
14
+ bot: {
15
+ state: z.object({
16
+ lastEnrichmentRunAt: z.string().optional().describe('ISO timestamp of the last completed enrichment run'),
17
+ totalContactsEnriched: z.number().default(0).describe('Cumulative count of contacts enriched across all runs'),
18
+ }),
19
+ },
20
+
21
+ // Per-user state is unused in this backend-only agent.
22
+ user: {
23
+ state: z.object({}),
24
+ },
25
+
26
+ // No integration dependencies — this is a pure backend workflow agent.
27
+ // If you want to send enrichment reports to Slack or email, add integrations here:
28
+ // adk add slack@latest
29
+ // adk add sendgrid@latest
30
+ dependencies: {
31
+ integrations: {},
32
+ },
33
+ })
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "{{projectName}}",
3
+ "version": "1.0.0",
4
+ "description": "A CRM enrichment agent built with the ADK — scheduled workflows that classify and score contacts using AI",
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "adk dev",
8
+ "build": "adk build",
9
+ "deploy": "adk deploy"
10
+ },
11
+ "dependencies": {
12
+ "@botpress/runtime": "^{{runtimeVersion}}"
13
+ },
14
+ "devDependencies": {
15
+ "typescript": "^5.9.3"
16
+ }
17
+ }
@@ -0,0 +1,81 @@
1
+ import { Action, z, adk } from '@botpress/runtime'
2
+
3
+ /**
4
+ * Enriches a single contact using AI classification.
5
+ *
6
+ * Given a contact's name, email, and company, this action uses Zai to extract:
7
+ * - industry: what sector the company operates in
8
+ * - useCase: what they would most likely use the product for
9
+ * - score: a lead quality rating (high / medium / low)
10
+ *
11
+ * Customization points:
12
+ * - Change the enum values to match your business categories.
13
+ * - Edit the `instructions` to reflect your ideal customer profile.
14
+ * - Add more extracted fields (e.g. companySize, region, buyerPersona).
15
+ */
16
+ export const enrichContact = new Action({
17
+ name: 'enrichContact',
18
+ description: 'Classify a CRM contact using AI to determine industry, use case, and lead score',
19
+
20
+ input: z.object({
21
+ name: z.string().describe('Full name of the contact'),
22
+ email: z.string().describe('Contact email address'),
23
+ company: z.string().describe('Company or organization name'),
24
+ }),
25
+
26
+ output: z.object({
27
+ industry: z.string().describe('Classified industry'),
28
+ useCase: z.string().describe('Classified use case'),
29
+ score: z.enum(['high', 'medium', 'low']).describe('Lead quality score'),
30
+ }),
31
+
32
+ async handler({ input }) {
33
+ // Build a text summary for the AI to classify.
34
+ const contactSummary = [`Name: ${input.name}`, `Email: ${input.email}`, `Company: ${input.company}`].join('\n')
35
+
36
+ // Use Zai extract to pull structured classification from the contact info.
37
+ // The AI infers industry, use case, and score from the name, email domain, and company.
38
+ const enriched = await adk.zai.extract(
39
+ contactSummary,
40
+ z.object({
41
+ industry: z
42
+ .enum([
43
+ 'Technology',
44
+ 'Healthcare',
45
+ 'Finance',
46
+ 'Retail',
47
+ 'Education',
48
+ 'Manufacturing',
49
+ 'Media',
50
+ 'Government',
51
+ 'Other',
52
+ ])
53
+ .describe('The primary industry the company operates in'),
54
+
55
+ useCase: z
56
+ .enum([
57
+ 'Customer Support',
58
+ 'Sales Automation',
59
+ 'Internal Helpdesk',
60
+ 'Lead Generation',
61
+ 'Knowledge Management',
62
+ 'Other',
63
+ ])
64
+ .describe('The most likely use case for a conversational AI product'),
65
+
66
+ score: z.enum(['high', 'medium', 'low']).describe('Lead quality score based on company fit and likely intent'),
67
+ }),
68
+ {
69
+ instructions: [
70
+ 'Classify this CRM contact based on their name, email domain, and company.',
71
+ 'For industry: infer from the company name and email domain.',
72
+ 'For useCase: estimate the most likely reason they would adopt a conversational AI platform.',
73
+ "For score: rate as 'high' if the company is mid-market or enterprise in a strong vertical,",
74
+ "'medium' for smaller companies or less obvious fit, 'low' for generic or unclear profiles.",
75
+ ].join(' '),
76
+ }
77
+ )
78
+
79
+ return enriched
80
+ },
81
+ })
@@ -0,0 +1,14 @@
1
+ // This template is a backend-only agent — no conversation handler is needed.
2
+ // If you want to add a chat interface (e.g. to let users query enriched contacts),
3
+ // uncomment below and install a channel integration: adk add webchat@latest
4
+ //
5
+ // import { Conversation } from '@botpress/runtime'
6
+ //
7
+ // export default new Conversation({
8
+ // channel: '*',
9
+ // handler: async ({ execute }) => {
10
+ // await execute({
11
+ // instructions: 'You are a CRM assistant. Help users look up enriched contacts.',
12
+ // })
13
+ // },
14
+ // })
@@ -0,0 +1,17 @@
1
+ // This template does not use a knowledge base.
2
+ // If you want to ground the enrichment logic with domain-specific documents
3
+ // (e.g. an ICP definition, industry taxonomy, or company database), you can
4
+ // add a knowledge base here and reference it in the enrichment action.
5
+ //
6
+ // import { Knowledge, DataSource } from '@botpress/runtime'
7
+ //
8
+ // const icpDocs = DataSource.Directory.fromPath('src/knowledge', {
9
+ // id: 'icp-docs',
10
+ // filter: (filePath) => filePath.endsWith('.md') || filePath.endsWith('.pdf'),
11
+ // })
12
+ //
13
+ // export const IcpKnowledge = new Knowledge({
14
+ // name: 'icp-knowledge',
15
+ // description: 'Ideal Customer Profile definitions and industry taxonomy',
16
+ // sources: [icpDocs],
17
+ // })
@@ -0,0 +1,43 @@
1
+ import { Table, z } from '@botpress/runtime'
2
+
3
+ /**
4
+ * ContactsTable stores CRM contacts along with their AI-enriched metadata.
5
+ *
6
+ * Columns like `name` and `company` are searchable so you can use semantic search
7
+ * to find contacts by fuzzy name/company queries.
8
+ *
9
+ * The enrichment fields (`useCase`, `industry`, `score`, `enrichedAt`) start empty
10
+ * and are populated by the enrichment pipeline workflow.
11
+ *
12
+ * To customize: add columns for phone, title, source, deal stage, etc.
13
+ */
14
+ export const ContactsTable = new Table({
15
+ name: 'ContactsTable',
16
+ description: 'CRM contacts with AI-enriched classification data',
17
+
18
+ columns: {
19
+ // -- Core contact fields --
20
+
21
+ name: {
22
+ searchable: true,
23
+ schema: z.string().describe('Full name of the contact'),
24
+ },
25
+
26
+ email: z.string().describe('Contact email address'),
27
+
28
+ company: {
29
+ searchable: true,
30
+ schema: z.string().describe('Company or organization name'),
31
+ },
32
+
33
+ // -- AI-enriched fields (populated by the enrichment pipeline) --
34
+
35
+ industry: z.string().optional().describe('AI-classified industry (e.g. Technology, Healthcare, Finance)'),
36
+
37
+ useCase: z.string().optional().describe('AI-classified use case (e.g. Customer Support, Sales Automation)'),
38
+
39
+ score: z.string().optional().describe('AI-assigned lead score: high, medium, or low'),
40
+
41
+ enrichedAt: z.string().optional().describe('ISO timestamp of when this contact was last enriched'),
42
+ },
43
+ })
@@ -0,0 +1,30 @@
1
+ import { Trigger } from '@botpress/runtime'
2
+ import { EnrichmentPipeline } from '../workflows/enrichment-pipeline'
3
+
4
+ /**
5
+ * Fires on bot registration (startup) to kick off an initial enrichment run.
6
+ *
7
+ * The enrichment pipeline also has its own cron schedule ("0 9 * * *"),
8
+ * which handles recurring daily runs automatically. This trigger ensures the
9
+ * pipeline runs once immediately when the bot first starts -- useful during
10
+ * development and after fresh deployments.
11
+ *
12
+ * To add more trigger events:
13
+ * - "user.created" -- enrich new contacts as they arrive
14
+ * - Custom events from integrations (e.g. "salesforce:contactCreated")
15
+ */
16
+ export default new Trigger({
17
+ name: 'dailyEnrichment',
18
+ description: 'Starts the enrichment pipeline on bot registration for an initial run',
19
+ events: ['register'],
20
+
21
+ handler: async () => {
22
+ console.log('Bot registered. Starting initial enrichment pipeline run...')
23
+
24
+ const instance = await EnrichmentPipeline.start({
25
+ batchSize: 50,
26
+ })
27
+
28
+ console.log(`Enrichment pipeline started: ${instance.id}`)
29
+ },
30
+ })
@@ -0,0 +1,171 @@
1
+ import { bot, Workflow, z, actions } from '@botpress/runtime'
2
+ import { ContactsTable } from '../tables/contacts'
3
+
4
+ /**
5
+ * Enrichment pipeline workflow.
6
+ *
7
+ * This scheduled workflow:
8
+ * 1. Fetches contacts that have not been enriched yet.
9
+ * 2. Enriches each contact via the enrichContact action (AI classification).
10
+ * 3. Writes the enrichment results back to the ContactsTable.
11
+ * 4. Updates bot state with run metadata and logs a summary.
12
+ *
13
+ * The workflow uses steps for each phase so progress is checkpointed. If it
14
+ * crashes mid-run, it resumes from the last completed step on restart.
15
+ *
16
+ * Schedule: daily at 9:00 AM UTC (edit the cron expression below).
17
+ * Timeout: 2 hours to handle large contact lists.
18
+ */
19
+ export const EnrichmentPipeline = new Workflow({
20
+ name: 'enrichmentPipeline',
21
+ description: 'Fetches unenriched CRM contacts, classifies them with AI, and writes results back',
22
+
23
+ // Runs every day at 9:00 AM UTC.
24
+ // Change to "*/30 * * * *" for every 30 minutes during development.
25
+ schedule: '0 9 * * *',
26
+
27
+ // Allow up to 2 hours for large batches.
28
+ timeout: '2h',
29
+
30
+ input: z.object({
31
+ batchSize: z.number().default(50).describe('Max number of contacts to enrich per run'),
32
+ }),
33
+
34
+ state: z.object({
35
+ contactsFetched: z.number().default(0),
36
+ contactsEnriched: z.number().default(0),
37
+ errors: z.array(z.string()).default([]),
38
+ }),
39
+
40
+ output: z.object({
41
+ enriched: z.number().describe('Number of contacts enriched this run'),
42
+ errors: z.number().describe('Number of contacts that failed enrichment'),
43
+ summary: z.string().describe('Human-readable run summary'),
44
+ }),
45
+
46
+ async handler({ input, state, step }) {
47
+ // ---------------------------------------------------------------
48
+ // Step 1: Fetch unenriched contacts
49
+ // ---------------------------------------------------------------
50
+ const unenrichedContacts = await step('fetch-unenriched-contacts', async () => {
51
+ const { rows } = await ContactsTable.findRows({
52
+ filter: { enrichedAt: null as unknown as string },
53
+ limit: input.batchSize,
54
+ })
55
+
56
+ return rows
57
+ })
58
+
59
+ state.contactsFetched = unenrichedContacts.length
60
+
61
+ if (unenrichedContacts.length === 0) {
62
+ console.log('No unenriched contacts found. Skipping run.')
63
+ return {
64
+ enriched: 0,
65
+ errors: 0,
66
+ summary: 'No unenriched contacts to process.',
67
+ }
68
+ }
69
+
70
+ console.log(`Found ${unenrichedContacts.length} unenriched contacts. Starting enrichment...`)
71
+
72
+ // ---------------------------------------------------------------
73
+ // Step 2: Enrich each contact via the action
74
+ // ---------------------------------------------------------------
75
+ const enrichmentResults = await step('enrich-contacts', async () => {
76
+ const results: Array<{
77
+ id: number
78
+ industry: string
79
+ useCase: string
80
+ score: string
81
+ success: boolean
82
+ error?: string
83
+ }> = []
84
+
85
+ for (const contact of unenrichedContacts) {
86
+ try {
87
+ const enriched = await actions.enrichContact({
88
+ name: contact.name,
89
+ email: contact.email,
90
+ company: contact.company,
91
+ })
92
+
93
+ results.push({
94
+ id: contact.id,
95
+ industry: enriched.industry,
96
+ useCase: enriched.useCase,
97
+ score: enriched.score,
98
+ success: true,
99
+ })
100
+ } catch (error) {
101
+ const message = error instanceof Error ? error.message : String(error)
102
+ console.error(`Failed to enrich contact ${contact.id} (${contact.name}): ${message}`)
103
+ results.push({
104
+ id: contact.id,
105
+ industry: '',
106
+ useCase: '',
107
+ score: '',
108
+ success: false,
109
+ error: message,
110
+ })
111
+ }
112
+ }
113
+
114
+ return results
115
+ })
116
+
117
+ // ---------------------------------------------------------------
118
+ // Step 3: Write enrichment results back to the table
119
+ // ---------------------------------------------------------------
120
+ await step('update-contacts', async () => {
121
+ const now = new Date().toISOString()
122
+ const successfulResults = enrichmentResults.filter((r) => r.success)
123
+
124
+ if (successfulResults.length === 0) {
125
+ console.log('No successful enrichments to write back.')
126
+ return
127
+ }
128
+
129
+ await ContactsTable.updateRows({
130
+ rows: successfulResults.map((r) => ({
131
+ id: r.id,
132
+ industry: r.industry,
133
+ useCase: r.useCase,
134
+ score: r.score,
135
+ enrichedAt: now,
136
+ })),
137
+ })
138
+
139
+ console.log(`Updated ${successfulResults.length} contacts in the table.`)
140
+ })
141
+
142
+ // ---------------------------------------------------------------
143
+ // Step 4: Update bot state and log summary
144
+ // ---------------------------------------------------------------
145
+ const successCount = enrichmentResults.filter((r) => r.success).length
146
+ const errorCount = enrichmentResults.filter((r) => !r.success).length
147
+
148
+ state.contactsEnriched = successCount
149
+ state.errors = enrichmentResults.filter((r) => !r.success).map((r) => `Contact ${r.id}: ${r.error}`)
150
+
151
+ // Persist metadata in global bot state for cross-run tracking.
152
+ bot.state.lastEnrichmentRunAt = new Date().toISOString()
153
+ bot.state.totalContactsEnriched = (bot.state.totalContactsEnriched ?? 0) + successCount
154
+
155
+ const summary = [
156
+ `Enrichment run complete.`,
157
+ `Processed: ${unenrichedContacts.length}`,
158
+ `Enriched: ${successCount}`,
159
+ `Errors: ${errorCount}`,
160
+ `Total enriched (all-time): ${bot.state.totalContactsEnriched}`,
161
+ ].join(' | ')
162
+
163
+ console.log(summary)
164
+
165
+ return {
166
+ enriched: successCount,
167
+ errors: errorCount,
168
+ summary,
169
+ }
170
+ },
171
+ })
@@ -0,0 +1,22 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ES2022",
5
+ "moduleResolution": "Bundler",
6
+ "lib": ["ES2022", "DOM"],
7
+ "outDir": "./dist",
8
+ "rootDir": ".",
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "allowSyntheticDefaultImports": true,
12
+ "skipLibCheck": true,
13
+ "forceConsistentCasingInFileNames": true,
14
+ "moduleDetection": "force",
15
+ "resolveJsonModule": true,
16
+ "paths": {
17
+ "@botpress/runtime/_types/*": ["./.adk/*-types"]
18
+ }
19
+ },
20
+ "include": ["src/**/*", ".adk/**/*"],
21
+ "exclude": ["node_modules", "dist"]
22
+ }
@@ -0,0 +1,46 @@
1
+ # {{projectName}}
2
+
3
+ A Botpress Agent built with the ADK, pre-configured with chat and webchat integrations.
4
+
5
+ ## Getting Started
6
+
7
+ 1. Install dependencies:
8
+
9
+ ```bash
10
+ {{packageManager}} install
11
+ ```
12
+
13
+ 2. Start development server:
14
+
15
+ ```bash
16
+ adk dev
17
+ ```
18
+
19
+ 3. Chat with your agent locally:
20
+
21
+ ```bash
22
+ adk chat
23
+ ```
24
+
25
+ 4. Deploy your agent:
26
+ ```bash
27
+ adk deploy
28
+ ```
29
+
30
+ ## Project Structure
31
+
32
+ - `src/actions/` - Define callable functions
33
+ - `src/workflows/` - Define long-running processes
34
+ - `src/conversations/` - Define conversation handlers
35
+ - `src/tables/` - Define data storage schemas
36
+ - `src/triggers/` - Define event subscriptions
37
+ - `src/knowledge/` - Add knowledge base files
38
+
39
+ ## Integrations
40
+
41
+ This agent comes with **chat** and **webchat** integrations enabled, so you can start talking to it right away with `adk chat`.
42
+
43
+ ## Learn More
44
+
45
+ - [ADK Documentation](https://botpress.com/docs/adk)
46
+ - [Botpress Platform](https://botpress.com)