@botpress/adk 1.17.0 → 1.18.0-beta.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.
- 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/generators/tests.d.ts.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +704 -468
- 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 +7 -15
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# {{projectName}}
|
|
2
|
+
|
|
3
|
+
A RAG-powered knowledge assistant built with Botpress ADK. This agent answers questions using your documents, with source citations for every response.
|
|
4
|
+
|
|
5
|
+
## How It Works
|
|
6
|
+
|
|
7
|
+
1. **Knowledge Base**: Documents in `src/knowledge/` are indexed for semantic search
|
|
8
|
+
2. **Conversations**: When a user asks a question, the AI searches the knowledge base for relevant passages
|
|
9
|
+
3. **Citations**: Responses include references to the source documents used
|
|
10
|
+
|
|
11
|
+
## Getting Started
|
|
12
|
+
|
|
13
|
+
1. Install dependencies:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
{{packageManager}} install
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
2. Add your documents to `src/knowledge/` (markdown, PDF, or text files)
|
|
20
|
+
|
|
21
|
+
3. Start development server:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
adk dev
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
4. Deploy your agent:
|
|
28
|
+
```bash
|
|
29
|
+
adk deploy
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Adding Documents
|
|
33
|
+
|
|
34
|
+
Place your documents in `src/knowledge/`. Supported formats:
|
|
35
|
+
|
|
36
|
+
- Markdown (`.md`)
|
|
37
|
+
- PDF (`.pdf`)
|
|
38
|
+
- Text (`.txt`)
|
|
39
|
+
|
|
40
|
+
The knowledge base automatically indexes all supported files. After adding new documents, run `adk kb sync` or restart `adk dev` to re-index.
|
|
41
|
+
|
|
42
|
+
## Project Structure
|
|
43
|
+
|
|
44
|
+
- `src/knowledge/docs.ts` - Knowledge base definition
|
|
45
|
+
- `src/knowledge/*.md` - Your source documents
|
|
46
|
+
- `src/conversations/index.ts` - Conversation handler with RAG execution
|
|
47
|
+
- `src/actions/` - Add custom actions (e.g. programmatic KB search for API access)
|
|
48
|
+
- `src/tables/` - Data storage (extend as needed)
|
|
49
|
+
- `src/triggers/` - Event subscriptions (extend as needed)
|
|
50
|
+
- `src/workflows/` - Long-running processes (extend as needed)
|
|
51
|
+
|
|
52
|
+
## How Citations Work
|
|
53
|
+
|
|
54
|
+
The conversation handler passes the knowledge base to `execute()`. The AI automatically searches relevant documents when answering questions and cites its sources. This is handled by the Botpress runtime -- no manual citation logic is required.
|
|
55
|
+
|
|
56
|
+
## Customization
|
|
57
|
+
|
|
58
|
+
- **Model**: Change `defaultModels` in `agent.config.ts` to use a different LLM
|
|
59
|
+
- **Instructions**: Edit the `instructions` in `src/conversations/index.ts` to change the agent's personality
|
|
60
|
+
- **Knowledge sources**: Add website crawling or table-based sources in `src/knowledge/docs.ts`
|
|
61
|
+
- **Tools**: Convert the search action to a tool with `.asTool()` for more control
|
|
62
|
+
|
|
63
|
+
## Learn More
|
|
64
|
+
|
|
65
|
+
- [ADK Documentation](https://botpress.com/docs/adk)
|
|
66
|
+
- [Botpress Platform](https://botpress.com)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { z, defineConfig } from '@botpress/runtime'
|
|
2
|
+
|
|
3
|
+
export default defineConfig({
|
|
4
|
+
name: '{{projectName}}',
|
|
5
|
+
description: 'A RAG-powered knowledge assistant that answers questions using your documents',
|
|
6
|
+
|
|
7
|
+
defaultModels: {
|
|
8
|
+
autonomous: 'openai:gpt-4.1-mini-2025-04-14',
|
|
9
|
+
zai: 'openai:gpt-4.1-2025-04-14',
|
|
10
|
+
},
|
|
11
|
+
|
|
12
|
+
// Per-bot persistent state
|
|
13
|
+
bot: {
|
|
14
|
+
state: z.object({}),
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
// Per-user persistent state
|
|
18
|
+
user: {
|
|
19
|
+
state: z.object({}),
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
// Integrations extend your agent with actions, channels, and events.
|
|
23
|
+
dependencies: {
|
|
24
|
+
integrations: {},
|
|
25
|
+
},
|
|
26
|
+
})
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{projectName}}",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A RAG-powered knowledge assistant built with Botpress 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,50 @@
|
|
|
1
|
+
import { Action, z, context } from '@botpress/runtime'
|
|
2
|
+
import { DocsKB } from '../knowledge/docs'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Search the knowledge base programmatically.
|
|
6
|
+
*
|
|
7
|
+
* This action provides API-level access to the documentation search,
|
|
8
|
+
* useful for integrations, workflows, or external systems that need
|
|
9
|
+
* to query the knowledge base outside of a conversation.
|
|
10
|
+
*/
|
|
11
|
+
export const searchDocs = new Action({
|
|
12
|
+
name: 'searchDocs',
|
|
13
|
+
description: 'Search the documentation knowledge base',
|
|
14
|
+
|
|
15
|
+
input: z.object({
|
|
16
|
+
query: z.string().describe('The search query'),
|
|
17
|
+
limit: z.number().min(1).max(20).default(5).describe('Maximum number of results to return'),
|
|
18
|
+
}),
|
|
19
|
+
|
|
20
|
+
output: z.object({
|
|
21
|
+
results: z.array(
|
|
22
|
+
z.object({
|
|
23
|
+
content: z.string().describe('The matched passage content'),
|
|
24
|
+
source: z.string().describe('The source file path'),
|
|
25
|
+
score: z.number().describe('Relevance score'),
|
|
26
|
+
})
|
|
27
|
+
),
|
|
28
|
+
}),
|
|
29
|
+
|
|
30
|
+
async handler({ input }) {
|
|
31
|
+
const client = context.get('client')
|
|
32
|
+
|
|
33
|
+
const { passages } = await client.searchFiles({
|
|
34
|
+
query: input.query,
|
|
35
|
+
tags: {
|
|
36
|
+
source: 'knowledge-base',
|
|
37
|
+
kbName: [DocsKB.name],
|
|
38
|
+
},
|
|
39
|
+
limit: input.limit,
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
results: passages.map((p) => ({
|
|
44
|
+
content: p.content,
|
|
45
|
+
source: p.file.key,
|
|
46
|
+
score: p.score,
|
|
47
|
+
})),
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
})
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Conversation } from '@botpress/runtime'
|
|
2
|
+
import { DocsKB } from '../knowledge/docs'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Main conversation handler for the knowledge assistant.
|
|
6
|
+
*
|
|
7
|
+
* Uses execute() with the DocsKB knowledge base. The AI automatically
|
|
8
|
+
* gets a search tool for the KB — no custom action needed.
|
|
9
|
+
*
|
|
10
|
+
* Handles all channels (chat, webchat, etc.) via the wildcard channel.
|
|
11
|
+
*/
|
|
12
|
+
export default new Conversation({
|
|
13
|
+
channel: '*',
|
|
14
|
+
|
|
15
|
+
async handler({ execute }) {
|
|
16
|
+
await execute({
|
|
17
|
+
instructions: `You are a company knowledge assistant. You answer employee questions using the company documentation.
|
|
18
|
+
|
|
19
|
+
Lead with example questions, to assist the user in asking good questions. For example:
|
|
20
|
+
- "What is the company's remote work policy?"
|
|
21
|
+
- "How do I request time off?"
|
|
22
|
+
- "What are the steps to set up my email on a new device?"
|
|
23
|
+
Rules:
|
|
24
|
+
- Search the knowledge base for every question. Do not guess or use general knowledge.
|
|
25
|
+
- If the answer is in the docs, quote the relevant policy or section.
|
|
26
|
+
- If the docs don't cover it, say "I don't have information about that in our docs" and suggest who to ask (HR, manager, IT, etc).
|
|
27
|
+
- Be direct. Lead with the answer, then provide context.
|
|
28
|
+
- Use short paragraphs. Bullet points for lists.`,
|
|
29
|
+
|
|
30
|
+
knowledge: [DocsKB],
|
|
31
|
+
})
|
|
32
|
+
},
|
|
33
|
+
})
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Knowledge, DataSource } from '@botpress/runtime'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Knowledge base that indexes all markdown files in the src/knowledge/ directory.
|
|
5
|
+
*
|
|
6
|
+
* Add your documents (markdown, PDF, text) to this folder and they will be
|
|
7
|
+
* automatically indexed for semantic search. The AI uses this knowledge base
|
|
8
|
+
* to answer questions with accurate, source-cited responses.
|
|
9
|
+
*
|
|
10
|
+
* Sync your knowledge base:
|
|
11
|
+
* adk kb sync (manual sync)
|
|
12
|
+
* adk dev (auto-syncs on startup and file changes)
|
|
13
|
+
*/
|
|
14
|
+
const docsSource = DataSource.Directory.fromPath('src/knowledge', {
|
|
15
|
+
id: 'docs',
|
|
16
|
+
filter: (filePath) => filePath.endsWith('.md') || filePath.endsWith('.pdf') || filePath.endsWith('.txt'),
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
export const DocsKB = new Knowledge({
|
|
20
|
+
name: 'docsKB',
|
|
21
|
+
description: 'Documentation and reference materials for answering user questions',
|
|
22
|
+
sources: [docsSource],
|
|
23
|
+
})
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Company Handbook
|
|
2
|
+
|
|
3
|
+
Welcome to Acme Corp! This document covers our policies, benefits, and day-to-day operations.
|
|
4
|
+
|
|
5
|
+
> **Note:** This is sample content. Replace it with your actual company docs, product documentation, or any knowledge you want your assistant to answer questions about.
|
|
6
|
+
|
|
7
|
+
## Working Hours
|
|
8
|
+
|
|
9
|
+
Our standard working hours are 9 AM to 5 PM in your local timezone. We offer flexible scheduling — as long as you're available for core hours (11 AM to 3 PM) and attend your team's standups, you can adjust your start and end times.
|
|
10
|
+
|
|
11
|
+
## Time Off Policy
|
|
12
|
+
|
|
13
|
+
- **PTO:** 20 days per year, accruing monthly
|
|
14
|
+
- **Sick leave:** Unlimited, no questions asked for the first 3 days. Beyond that, a doctor's note is appreciated but not required.
|
|
15
|
+
- **Holidays:** We follow the US federal holiday calendar. If you're outside the US, you can swap US holidays for your local ones.
|
|
16
|
+
- **Parental leave:** 16 weeks paid for all parents, regardless of gender.
|
|
17
|
+
|
|
18
|
+
## Expense Policy
|
|
19
|
+
|
|
20
|
+
- **Software and tools:** Pre-approved up to $100/month. Anything over needs manager approval.
|
|
21
|
+
- **Books and courses:** Fully covered, no cap. Submit receipts through Expensify.
|
|
22
|
+
- **Travel:** Book economy for flights under 5 hours, business class for longer. Hotels up to $250/night.
|
|
23
|
+
- **Meals:** $30/day when traveling. Team dinners covered fully with VP approval.
|
|
24
|
+
|
|
25
|
+
## Engineering Practices
|
|
26
|
+
|
|
27
|
+
### Code Review
|
|
28
|
+
|
|
29
|
+
Every PR needs at least one approval before merging. For changes touching auth, payments, or data deletion, two approvals are required. Reviewers should respond within 24 hours.
|
|
30
|
+
|
|
31
|
+
### Incident Response
|
|
32
|
+
|
|
33
|
+
1. **Severity 1 (service down):** Page the on-call engineer via PagerDuty. All hands until resolved.
|
|
34
|
+
2. **Severity 2 (degraded):** Notify #incidents in Slack. On-call investigates, escalates if not resolved in 1 hour.
|
|
35
|
+
3. **Severity 3 (minor bug):** File a ticket, fix in next sprint.
|
|
36
|
+
|
|
37
|
+
Post-incident reviews happen within 48 hours. No blame, just learnings.
|
|
38
|
+
|
|
39
|
+
### Deployment
|
|
40
|
+
|
|
41
|
+
We deploy to production twice daily (11 AM and 4 PM UTC). Feature flags are required for anything user-facing. Rollbacks are one-click via the deploy dashboard.
|
|
42
|
+
|
|
43
|
+
## Benefits
|
|
44
|
+
|
|
45
|
+
- **Health insurance:** 100% covered for employees, 80% for dependents
|
|
46
|
+
- **401k:** 4% match, vests immediately
|
|
47
|
+
- **Home office:** $1,500 one-time setup budget for new hires
|
|
48
|
+
- **Wellness:** $100/month for gym, therapy, or wellness apps
|
|
49
|
+
- **Learning:** Conference budget of $2,000/year plus 3 days off to attend
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// import { Table, z } from '@botpress/runtime'
|
|
2
|
+
//
|
|
3
|
+
// /**
|
|
4
|
+
// * Example: Track search queries and feedback to improve the knowledge base over time.
|
|
5
|
+
// *
|
|
6
|
+
// * Table names must end with "Table" (e.g. QueriesTable, FeedbackTable).
|
|
7
|
+
// * Mark string columns as `{ searchable: true, schema: z.string() }` to enable semantic search.
|
|
8
|
+
// * @reserved id, createdAt, updatedAt — auto-managed by the system, do not define them.
|
|
9
|
+
// */
|
|
10
|
+
// export const QueriesTable = new Table({
|
|
11
|
+
// name: 'queriesTable',
|
|
12
|
+
// description: 'Tracks user search queries and their feedback',
|
|
13
|
+
// columns: {
|
|
14
|
+
// query: {
|
|
15
|
+
// searchable: true,
|
|
16
|
+
// schema: z.string().describe('The user search query'),
|
|
17
|
+
// },
|
|
18
|
+
// resultCount: z.number().describe('Number of results returned'),
|
|
19
|
+
// helpful: z.boolean().optional().describe('Whether the user found the answer helpful'),
|
|
20
|
+
// },
|
|
21
|
+
// })
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// import { Trigger } from '@botpress/runtime'
|
|
2
|
+
//
|
|
3
|
+
// /**
|
|
4
|
+
// * Example: Track when users start conversations to monitor KB assistant usage.
|
|
5
|
+
// *
|
|
6
|
+
// * Bot events: 'register', 'message.created', 'conversation.started', 'conversation.ended',
|
|
7
|
+
// * 'user.created', 'workflow.started', 'workflow.completed', 'workflow.failed'
|
|
8
|
+
// * Run `adk info <integration>` to see all events for an integration.
|
|
9
|
+
// */
|
|
10
|
+
// export default new Trigger({
|
|
11
|
+
// name: 'onConversationStarted',
|
|
12
|
+
// description: 'Logs when a new knowledge assistant conversation begins',
|
|
13
|
+
// events: ['conversation.started'],
|
|
14
|
+
// handler: async ({ event }) => {
|
|
15
|
+
// console.log(`New conversation started: ${event.payload.conversationId}`)
|
|
16
|
+
// },
|
|
17
|
+
// })
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// import { Workflow, z } from '@botpress/runtime'
|
|
2
|
+
// import { DocsKB } from '../knowledge/docs'
|
|
3
|
+
//
|
|
4
|
+
// /**
|
|
5
|
+
// * Example: A research workflow that searches the knowledge base and produces a summary.
|
|
6
|
+
// *
|
|
7
|
+
// * Each `step()` call is checkpointed — safe to retry on failure.
|
|
8
|
+
// * Start from a trigger or conversation via `ResearchWorkflow.start({ input })`.
|
|
9
|
+
// */
|
|
10
|
+
// export const ResearchWorkflow = new Workflow({
|
|
11
|
+
// name: 'research',
|
|
12
|
+
// input: z.object({
|
|
13
|
+
// topic: z.string().describe('The topic to research'),
|
|
14
|
+
// }),
|
|
15
|
+
// output: z.object({
|
|
16
|
+
// summary: z.string().describe('A summary of findings from the knowledge base'),
|
|
17
|
+
// }),
|
|
18
|
+
// handler: async ({ input, step, execute }) => {
|
|
19
|
+
// const summary = await step('research', async () => {
|
|
20
|
+
// const result = await execute({
|
|
21
|
+
// instructions: `Research the following topic using the knowledge base and provide a concise summary: ${input.topic}`,
|
|
22
|
+
// knowledge: [DocsKB],
|
|
23
|
+
// })
|
|
24
|
+
// return result
|
|
25
|
+
// })
|
|
26
|
+
// return { summary }
|
|
27
|
+
// },
|
|
28
|
+
// })
|
|
@@ -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,74 @@
|
|
|
1
|
+
# {{projectName}}
|
|
2
|
+
|
|
3
|
+
A Slack triage bot built with the Botpress ADK. It monitors channels for help requests, classifies them using AI, and routes them to the right person or channel based on configurable routing rules.
|
|
4
|
+
|
|
5
|
+
## How It Works
|
|
6
|
+
|
|
7
|
+
1. **Trigger**: A new message arrives in a monitored Slack channel
|
|
8
|
+
2. **Classify**: The `classify-request` action uses Zai to categorize the request (bug, feature_request, question, ops_issue)
|
|
9
|
+
3. **Route**: The `triage-flow` workflow looks up routing rules from the `RoutingRulesTable` and posts a summary to the appropriate channel or person
|
|
10
|
+
4. **Respond**: The Slack DM conversation handler answers follow-up questions about triage status
|
|
11
|
+
|
|
12
|
+
## Getting Started
|
|
13
|
+
|
|
14
|
+
1. Install dependencies:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
{{packageManager}} install
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
2. Configure Slack:
|
|
21
|
+
- Create a Slack app at https://api.slack.com/apps
|
|
22
|
+
- Add the bot to your workspace
|
|
23
|
+
- Run `adk dev` and configure the Slack integration in the Botpress dashboard
|
|
24
|
+
|
|
25
|
+
3. Seed routing rules:
|
|
26
|
+
After your first `adk dev`, add rows to the `RoutingRulesTable` via the Botpress dashboard or a script:
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
| category | assignee | slackChannel | priority |
|
|
30
|
+
|-----------------|----------------|-------------------|----------|
|
|
31
|
+
| bug | @oncall-eng | #bugs | high |
|
|
32
|
+
| feature_request | @product-team | #feature_requests | medium |
|
|
33
|
+
| question | @support-team | #help-desk | low |
|
|
34
|
+
| ops_issue | @devops | #ops-alerts | high |
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
4. Start development server:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
adk dev
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
5. Deploy your agent:
|
|
44
|
+
```bash
|
|
45
|
+
adk deploy
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Project Structure
|
|
49
|
+
|
|
50
|
+
- `src/actions/classify-request.ts` - AI-powered request classification
|
|
51
|
+
- `src/workflows/triage-flow.ts` - Multi-step triage workflow (classify, lookup, route)
|
|
52
|
+
- `src/conversations/slack-dm.ts` - Handles Slack channel messages with AI
|
|
53
|
+
- `src/tables/routing-rules.ts` - Configurable routing rules
|
|
54
|
+
- `src/triggers/new-message.ts` - Fires on new Slack messages
|
|
55
|
+
- `src/knowledge/team-directory.md` - Team directory for AI context
|
|
56
|
+
|
|
57
|
+
## Customization
|
|
58
|
+
|
|
59
|
+
### Adding Categories
|
|
60
|
+
|
|
61
|
+
Edit `src/actions/classify-request.ts` to add new categories to the `category` enum and update the Zai label definitions.
|
|
62
|
+
|
|
63
|
+
### Changing Routing Logic
|
|
64
|
+
|
|
65
|
+
Edit `src/workflows/triage-flow.ts` to customize how requests are routed. You can add steps for priority escalation, duplicate detection, or SLA tracking.
|
|
66
|
+
|
|
67
|
+
### Adding Channels
|
|
68
|
+
|
|
69
|
+
Create new conversation handlers in `src/conversations/` for other Slack channels or platforms (e.g., `slack-channel.ts` for public channel responses).
|
|
70
|
+
|
|
71
|
+
## Learn More
|
|
72
|
+
|
|
73
|
+
- [ADK Documentation](https://botpress.com/docs/adk)
|
|
74
|
+
- [Botpress Platform](https://botpress.com)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { z, defineConfig } from '@botpress/runtime'
|
|
2
|
+
|
|
3
|
+
export default defineConfig({
|
|
4
|
+
name: '{{projectName}}',
|
|
5
|
+
description: 'Slack triage bot - monitors channels, classifies help requests, and routes them to the right person',
|
|
6
|
+
|
|
7
|
+
defaultModels: {
|
|
8
|
+
autonomous: 'openai:gpt-4.1-mini-2025-04-14', // Model used by execute() in conversations/workflows
|
|
9
|
+
zai: 'openai:gpt-4.1-2025-04-14', // Model used by Zai (extract, check, label, etc.)
|
|
10
|
+
},
|
|
11
|
+
|
|
12
|
+
// Per-bot persistent state - tracks triage statistics across all conversations.
|
|
13
|
+
bot: {
|
|
14
|
+
state: z.object({
|
|
15
|
+
totalTriaged: z.number().default(0).describe('Total requests triaged'),
|
|
16
|
+
lastTriagedAt: z.string().optional().describe('ISO timestamp of last triage'),
|
|
17
|
+
}),
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
// Per-user persistent state - remembers routing preferences per user.
|
|
21
|
+
user: {
|
|
22
|
+
state: z.object({
|
|
23
|
+
preferredCategory: z.string().optional().describe('Category this user most often submits'),
|
|
24
|
+
requestCount: z.number().default(0).describe('Number of requests from this user'),
|
|
25
|
+
}),
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
// Integrations extend your agent with actions, channels, and events.
|
|
29
|
+
// Browse available integrations: adk search <name> | adk list --available
|
|
30
|
+
// Install one: adk add <integration> (e.g. adk add browser)
|
|
31
|
+
// See actions/events/channels: adk info <integration>
|
|
32
|
+
dependencies: {
|
|
33
|
+
integrations: {},
|
|
34
|
+
},
|
|
35
|
+
})
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Eval: triage-basic
|
|
3
|
+
*
|
|
4
|
+
* Verifies that the triage bot correctly classifies common request types.
|
|
5
|
+
*
|
|
6
|
+
* Evals use the Eval class from @botpress/adk. Each eval defines a simulated
|
|
7
|
+
* conversation with assertions on the bot's responses and tool usage.
|
|
8
|
+
*
|
|
9
|
+
* Run evals with: adk eval
|
|
10
|
+
* Run a specific eval: adk eval --name triage-basic
|
|
11
|
+
*/
|
|
12
|
+
import { Eval } from '@botpress/adk'
|
|
13
|
+
|
|
14
|
+
export default new Eval({
|
|
15
|
+
name: 'triage-basic',
|
|
16
|
+
description: 'Verify the bot classifies bug reports, feature requests, and questions correctly',
|
|
17
|
+
tags: ['triage', 'classification'],
|
|
18
|
+
type: 'regression',
|
|
19
|
+
|
|
20
|
+
conversation: [
|
|
21
|
+
{
|
|
22
|
+
user: 'The login page is showing a 500 error whenever I try to sign in with Google SSO',
|
|
23
|
+
assert: {
|
|
24
|
+
response: [
|
|
25
|
+
{
|
|
26
|
+
llm_judge:
|
|
27
|
+
'Response acknowledges this is a bug or error report and indicates it will be triaged or routed to the appropriate team',
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
user: 'It would be great if we could export dashboard data to CSV',
|
|
34
|
+
assert: {
|
|
35
|
+
response: [
|
|
36
|
+
{
|
|
37
|
+
llm_judge:
|
|
38
|
+
'Response recognizes this as a feature request and indicates it will be forwarded to the product team or logged appropriately',
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
user: 'How do I reset my password?',
|
|
45
|
+
assert: {
|
|
46
|
+
response: [
|
|
47
|
+
{
|
|
48
|
+
llm_judge:
|
|
49
|
+
'Response treats this as a general question and either answers it directly or indicates it will be routed to support',
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
})
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{projectName}}",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A Slack triage bot built with the ADK - classifies help requests and routes them",
|
|
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,65 @@
|
|
|
1
|
+
import { Action, z, adk } from '@botpress/runtime'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Classifies an incoming help request into a category using Zai.
|
|
5
|
+
*
|
|
6
|
+
* Supported categories:
|
|
7
|
+
* - bug: Something is broken or not working as expected
|
|
8
|
+
* - feature_request: A request for new functionality
|
|
9
|
+
* - question: A general question or "how do I..." inquiry
|
|
10
|
+
* - ops_issue: Infrastructure, deployment, or operational problem
|
|
11
|
+
*
|
|
12
|
+
* Customize: Add new categories by extending the enum and the label definitions below.
|
|
13
|
+
*/
|
|
14
|
+
export const classifyRequest = new Action({
|
|
15
|
+
name: 'classifyRequest',
|
|
16
|
+
description: 'Classify a help request into a category using AI',
|
|
17
|
+
|
|
18
|
+
input: z.object({
|
|
19
|
+
message: z.string().describe('The raw help request message text'),
|
|
20
|
+
}),
|
|
21
|
+
|
|
22
|
+
output: z.object({
|
|
23
|
+
category: z.enum(['bug', 'feature_request', 'question', 'ops_issue']).describe('The classified category'),
|
|
24
|
+
confidence: z.string().describe('How confident the classification is: high, medium, or low'),
|
|
25
|
+
summary: z.string().describe('A one-sentence summary of the request'),
|
|
26
|
+
}),
|
|
27
|
+
|
|
28
|
+
handler: async ({ input }) => {
|
|
29
|
+
// Use Zai label() with .result() to get confidence scores per category.
|
|
30
|
+
// Each label is evaluated independently with a 5-tier confidence scale.
|
|
31
|
+
const { output: labels } = await adk.zai
|
|
32
|
+
.label(input.message, {
|
|
33
|
+
bug: 'reports a bug, error, crash, or something not working as expected',
|
|
34
|
+
feature_request: 'requests a new feature, enhancement, or improvement to existing functionality',
|
|
35
|
+
question: 'asks a general question, seeks guidance, or wants to know how to do something',
|
|
36
|
+
ops_issue: 'reports an infrastructure, deployment, uptime, or operational problem',
|
|
37
|
+
})
|
|
38
|
+
.result()
|
|
39
|
+
|
|
40
|
+
// Pick the category with the highest confidence that matched (value: true).
|
|
41
|
+
type Category = 'bug' | 'feature_request' | 'question' | 'ops_issue'
|
|
42
|
+
const categories: Category[] = ['bug', 'feature_request', 'question', 'ops_issue']
|
|
43
|
+
|
|
44
|
+
const best = categories
|
|
45
|
+
.filter((c) => labels[c].value)
|
|
46
|
+
.sort((a, b) => labels[b].confidence - labels[a].confidence)[0]
|
|
47
|
+
|
|
48
|
+
const category: Category = best ?? 'question'
|
|
49
|
+
const confidence = best ? (labels[best].confidence >= 0.8 ? 'high' : 'medium') : 'low'
|
|
50
|
+
|
|
51
|
+
// Use Zai extract() to generate a concise summary of the request.
|
|
52
|
+
const extracted = await adk.zai.extract(
|
|
53
|
+
input.message,
|
|
54
|
+
z.object({
|
|
55
|
+
summary: z.string().describe('A single concise sentence summarizing the help request'),
|
|
56
|
+
})
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
category,
|
|
61
|
+
confidence,
|
|
62
|
+
summary: extracted.summary,
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
})
|