@botpress/adk 1.17.0 → 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.
- package/dist/agent-init/agent-project-generator.d.ts +32 -8
- package/dist/agent-init/agent-project-generator.d.ts.map +1 -1
- package/dist/agent-init/index.d.ts +1 -0
- package/dist/agent-init/index.d.ts.map +1 -1
- package/dist/agent-project/agent-project.d.ts +5 -1
- package/dist/agent-project/agent-project.d.ts.map +1 -1
- package/dist/agent-project/agent-resolver.d.ts +4 -3
- package/dist/agent-project/agent-resolver.d.ts.map +1 -1
- package/dist/agent-project/config-writer.d.ts +33 -0
- package/dist/agent-project/config-writer.d.ts.map +1 -1
- package/dist/agent-project/dependencies-parser.d.ts.map +1 -1
- package/dist/agent-project/index.d.ts +1 -1
- package/dist/agent-project/index.d.ts.map +1 -1
- package/dist/agent-project/types.d.ts +22 -4
- package/dist/agent-project/types.d.ts.map +1 -1
- package/dist/auth/credentials.d.ts.map +1 -1
- package/dist/bot-generator/dev-id-manager.d.ts.map +1 -1
- package/dist/bot-generator/generator.d.ts.map +1 -1
- package/dist/eval/index.d.ts +1 -1
- package/dist/eval/index.d.ts.map +1 -1
- package/dist/eval/loader.d.ts +2 -1
- package/dist/eval/loader.d.ts.map +1 -1
- package/dist/eval/types.d.ts +15 -2
- package/dist/eval/types.d.ts.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +698 -462
- package/dist/index.js.map +21 -21
- package/dist/integrations/checker.d.ts.map +1 -1
- package/dist/integrations/config-utils.d.ts +1 -0
- package/dist/integrations/config-utils.d.ts.map +1 -1
- package/dist/integrations/operations.d.ts +19 -6
- package/dist/integrations/operations.d.ts.map +1 -1
- package/dist/knowledge/manager.d.ts.map +1 -1
- package/dist/preflight/checker.d.ts.map +1 -1
- package/dist/templates/README.md +101 -0
- package/dist/templates/blank/README.md +36 -0
- package/dist/templates/blank/agent.config.ts +49 -0
- package/dist/templates/blank/package.json +17 -0
- package/dist/templates/blank/src/actions/index.ts +19 -0
- package/dist/templates/blank/src/conversations/index.ts +16 -0
- package/dist/templates/blank/src/knowledge/index.ts +17 -0
- package/dist/templates/blank/src/tables/index.ts +19 -0
- package/dist/templates/blank/src/triggers/index.ts +20 -0
- package/dist/templates/blank/src/workflows/index.ts +23 -0
- package/dist/templates/blank/tsconfig.json +22 -0
- package/dist/templates/crm-enrichment/README.md +85 -0
- package/dist/templates/crm-enrichment/agent.config.ts +33 -0
- package/dist/templates/crm-enrichment/package.json +17 -0
- package/dist/templates/crm-enrichment/src/actions/enrich-contact.ts +81 -0
- package/dist/templates/crm-enrichment/src/conversations/index.ts +14 -0
- package/dist/templates/crm-enrichment/src/knowledge/index.ts +17 -0
- package/dist/templates/crm-enrichment/src/tables/contacts.ts +43 -0
- package/dist/templates/crm-enrichment/src/triggers/daily-enrichment.ts +30 -0
- package/dist/templates/crm-enrichment/src/workflows/enrichment-pipeline.ts +171 -0
- package/dist/templates/crm-enrichment/tsconfig.json +22 -0
- package/dist/templates/hello-world/README.md +46 -0
- package/dist/templates/hello-world/agent.config.ts +48 -0
- package/dist/templates/hello-world/package.json +17 -0
- package/dist/templates/hello-world/src/actions/index.ts +19 -0
- package/dist/templates/hello-world/src/conversations/index.ts +10 -0
- package/dist/templates/hello-world/src/knowledge/index.ts +17 -0
- package/dist/templates/hello-world/src/tables/index.ts +19 -0
- package/dist/templates/hello-world/src/triggers/index.ts +20 -0
- package/dist/templates/hello-world/src/workflows/index.ts +23 -0
- package/dist/templates/hello-world/tsconfig.json +22 -0
- package/dist/templates/knowledge-assistant/README.md +66 -0
- package/dist/templates/knowledge-assistant/agent.config.ts +26 -0
- package/dist/templates/knowledge-assistant/package.json +17 -0
- package/dist/templates/knowledge-assistant/src/actions/index.ts +19 -0
- package/dist/templates/knowledge-assistant/src/actions/search-docs.ts +50 -0
- package/dist/templates/knowledge-assistant/src/conversations/index.ts +33 -0
- package/dist/templates/knowledge-assistant/src/knowledge/docs.ts +23 -0
- package/dist/templates/knowledge-assistant/src/knowledge/getting-started.md +49 -0
- package/dist/templates/knowledge-assistant/src/tables/index.ts +21 -0
- package/dist/templates/knowledge-assistant/src/triggers/index.ts +17 -0
- package/dist/templates/knowledge-assistant/src/workflows/index.ts +28 -0
- package/dist/templates/knowledge-assistant/tsconfig.json +22 -0
- package/dist/templates/slack-triage/README.md +74 -0
- package/dist/templates/slack-triage/agent.config.ts +35 -0
- package/dist/templates/slack-triage/evals/triage-basic.eval.ts +55 -0
- package/dist/templates/slack-triage/package.json +17 -0
- package/dist/templates/slack-triage/src/actions/classify-request.ts +65 -0
- package/dist/templates/slack-triage/src/conversations/slack-dm.ts +72 -0
- package/dist/templates/slack-triage/src/knowledge/team-directory.md +33 -0
- package/dist/templates/slack-triage/src/tables/routing-rules.ts +38 -0
- package/dist/templates/slack-triage/src/triggers/new-message.ts +44 -0
- package/dist/templates/slack-triage/src/workflows/triage-flow.ts +104 -0
- package/dist/templates/slack-triage/tsconfig.json +22 -0
- package/dist/templates/template.config.json +47 -0
- package/dist/utils/json-ordering.d.ts +1 -1
- package/dist/utils/json-ordering.d.ts.map +1 -1
- package/package.json +2 -10
|
@@ -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)
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { z, defineConfig } from '@botpress/runtime'
|
|
2
|
+
|
|
3
|
+
export default defineConfig({
|
|
4
|
+
name: '{{projectName}}',
|
|
5
|
+
description: 'An AI agent built with Botpress ADK',
|
|
6
|
+
|
|
7
|
+
defaultModels: {
|
|
8
|
+
autonomous: 'cerebras:gpt-oss-120b',
|
|
9
|
+
zai: 'cerebras:gpt-oss-120b',
|
|
10
|
+
},
|
|
11
|
+
|
|
12
|
+
// Per-bot persistent state — add fields here to store data across conversations.
|
|
13
|
+
bot: {
|
|
14
|
+
state: z.object({}),
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
// Per-user persistent state — add fields here to remember things about each user.
|
|
18
|
+
user: {
|
|
19
|
+
state: z.object({}),
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
// Static bot-level config — import { configuration } from '@botpress/runtime' to read it anywhere.
|
|
23
|
+
// Great for feature flags, API endpoints, and other deploy-time settings.
|
|
24
|
+
// configuration: {
|
|
25
|
+
// schema: z.object({
|
|
26
|
+
// apiEndpoint: z.string().default("https://api.example.com"),
|
|
27
|
+
// featureFlags: z.object({
|
|
28
|
+
// enableBeta: z.boolean().default(false),
|
|
29
|
+
// }).default({}),
|
|
30
|
+
// }),
|
|
31
|
+
// },
|
|
32
|
+
|
|
33
|
+
// Custom events your agent can emit and subscribe to via triggers.
|
|
34
|
+
// events: {
|
|
35
|
+
// myEvent: {
|
|
36
|
+
// schema: z.object({ userId: z.string(), message: z.string() }),
|
|
37
|
+
// description: 'Emitted when something noteworthy happens',
|
|
38
|
+
// },
|
|
39
|
+
// },
|
|
40
|
+
|
|
41
|
+
// Integrations extend your agent with actions, channels, and events.
|
|
42
|
+
// Browse available integrations: adk search <name> | adk list --available
|
|
43
|
+
// Install one: adk add <integration> (e.g. adk add browser)
|
|
44
|
+
// See actions/events/channels: adk info <integration>
|
|
45
|
+
dependencies: {
|
|
46
|
+
integrations: {},
|
|
47
|
+
},
|
|
48
|
+
})
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{projectName}}",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A Botpress Agent built with the ADK",
|
|
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,19 @@
|
|
|
1
|
+
// import { Action, z } from '@botpress/runtime'
|
|
2
|
+
//
|
|
3
|
+
// /**
|
|
4
|
+
// * A strongly-typed callable function — use `new Action(...)` (it's a class constructor).
|
|
5
|
+
// * Handler always receives `{ input, client }` as props, not the input fields directly.
|
|
6
|
+
// * Can be converted to an AI tool via `.asTool()` and passed to `execute()`.
|
|
7
|
+
// */
|
|
8
|
+
// export default new Action({
|
|
9
|
+
// name: 'myAction',
|
|
10
|
+
// input: z.object({
|
|
11
|
+
// message: z.string().describe('The message to process'),
|
|
12
|
+
// }),
|
|
13
|
+
// output: z.object({
|
|
14
|
+
// result: z.string().describe('The processed result'),
|
|
15
|
+
// }),
|
|
16
|
+
// handler: async ({ input }) => {
|
|
17
|
+
// return { result: `Processed: ${input.message}` }
|
|
18
|
+
// },
|
|
19
|
+
// })
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Conversation } from '@botpress/runtime'
|
|
2
|
+
|
|
3
|
+
export default new Conversation({
|
|
4
|
+
channel: '*',
|
|
5
|
+
handler: async ({ execute }) => {
|
|
6
|
+
await execute({
|
|
7
|
+
instructions: `You are a helpful AI assistant built with Botpress ADK. You can assist users with their questions and tasks.`,
|
|
8
|
+
})
|
|
9
|
+
},
|
|
10
|
+
})
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// import { Knowledge, DataSource } from '@botpress/runtime'
|
|
2
|
+
//
|
|
3
|
+
// /**
|
|
4
|
+
// * A RAG-powered knowledge base for semantic search and AI-grounded responses.
|
|
5
|
+
// * Data sources: Directory (local .md/.pdf), Website (sitemap/URLs), or Table.
|
|
6
|
+
// * Pass to `execute({ knowledge: [MyKB] })` to make the AI use it when answering.
|
|
7
|
+
// */
|
|
8
|
+
// const mySource = DataSource.Directory.fromPath('src/knowledge', {
|
|
9
|
+
// id: 'my-docs',
|
|
10
|
+
// filter: (filePath) => filePath.endsWith('.md') || filePath.endsWith('.pdf'),
|
|
11
|
+
// })
|
|
12
|
+
//
|
|
13
|
+
// export const MyKB = new Knowledge({
|
|
14
|
+
// name: 'my-knowledge',
|
|
15
|
+
// description: 'My knowledge base',
|
|
16
|
+
// sources: [mySource],
|
|
17
|
+
// })
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// import { Table, z } from '@botpress/runtime'
|
|
2
|
+
//
|
|
3
|
+
// /**
|
|
4
|
+
// * Structured data storage with CRUD and optional semantic search.
|
|
5
|
+
// * Table names must end with "Table" (e.g. UsersTable, OrdersTable).
|
|
6
|
+
// * Mark string columns as `{ searchable: true, schema: z.string() }` to enable search.
|
|
7
|
+
// * @reserved id, createdAt, updatedAt — auto-managed by the system, do not define them.
|
|
8
|
+
// */
|
|
9
|
+
// export const MyTable = new Table({
|
|
10
|
+
// name: 'myTable',
|
|
11
|
+
// description: 'Stores my data',
|
|
12
|
+
// columns: {
|
|
13
|
+
// title: {
|
|
14
|
+
// searchable: true,
|
|
15
|
+
// schema: z.string().describe('Title of the entry'),
|
|
16
|
+
// },
|
|
17
|
+
// status: z.string().describe('Current status of the entry'),
|
|
18
|
+
// },
|
|
19
|
+
// })
|
|
@@ -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
|
+
}
|