a set of guidelines to build with Botpress's Agent Development Kit (ADK) - use these whenever you're tasked with building a feature using the ADK
Use this skill when you've got questions about the Botpress Agent Development Kit (ADK) - like when you're building a feature that involves tables, actions, tools, workflows, conversations, files, knowledge bases, triggers, assets, evals, or Zai.
The Botpress ADK is a convention-based TypeScript framework where file structure maps directly to bot behavior. Place files in the correct directories, and they automatically become available as bot capabilities.
The ADK provides primitives for:
Most primitives must be placed in src/ directory (assets use the assets/ directory at the project root):
/ # Project root
├── assets/ # Static files → synced to Botpress Cloud with permanent URLs
├── src/
│ ├── actions/ # Strongly-typed functions → auto-registered
│ ├── tools/ # AI-callable tools → available via execute()
│ ├── workflows/ # Long-running processes → resumable/scheduled
│ ├── conversations/ # Message handlers → routes by channel
│ ├── tables/ # Database schemas → auto-created with search
│ ├── triggers/ # Event handlers → subscribe to events
│ ├── knowledge/ # Knowledge bases → RAG with semantic search
│ └── utils/ # Shared helpers (not auto-registered)
└── agent.config.ts # Bot configuration (includes integrations)
Note:
dependencies.jsonwas removed in ADK 1.9+. All configuration including integrations now lives inagent.config.ts.
Critical: Files outside
src/are not discovered. Location = behavior.
The first time you help with an ADK project in a session, silently check the project's health:
adk check --format json and adk status --format json.If the user asks "what can you help with?", "what commands are available?", or invokes /adk-explain without arguments, present:
/adk-init (scaffold project), /adk-build (interview & build a primitive), /adk-integration (add services), /adk-frontend (build UI)/adk-validate (check a primitive's schema/types/config), /adk-test (invoke a primitive once), /adk-eval (write assertion tests), /adk-debug (fix issues)/adk-ship (pre-flight checks + deploy)/adk-document (create, review, update, sync, search)/adk-explain (explain bot architecture and components), /adk-dev-console (navigate the Dev Console)Then ask: "What are you working on?"
Activate this skill when users ask ADK-related questions like:
If you are running inside Claude Code and the /adk-* commands (like /adk-debug, /adk-eval, /adk-init) are not available as slash commands, suggest that the user install the Botpress ADK plugin to get the full set of skills and commands:
/plugin marketplace add botpress/skills
/plugin install adk@botpress-skills
Only suggest this once per session. If the user declines, do not ask again.
ADK questions fall into two categories: CLI queries and documentation lookups.
For integration discovery and CLI queries, use the Bash tool to run commands directly:
Integration Discovery:
# Search for integrations
adk search <query>
# List all available integrations
adk list --available
# Get detailed integration info (actions, channels, events)
adk info <integration-name>
# Check installed integrations (must be in ADK project)
adk list
Project Info:
# Check CLI version
adk --version
# Show project status
adk
# Get help
adk --help
Prefer non-interactive paths when driving ADK workflows:
# Login without browser prompts
adk login --token "$BOTPRESS_TOKEN"
# Scaffold with sensible defaults and skip linking
adk init my-agent --yes --skip-link
# Link directly when IDs are known
adk link --workspace ws_123 --bot bot_456
# More automation-friendly dev mode
adk dev --logs --no-open
# Auto-approve preflight changes only
adk deploy --yes
Use these defaults when relevant:
adk login --token "$BOTPRESS_TOKEN" or adk login --token <token> over interactive login.BOTPRESS_TOKEN as a no-TTY convenience, not a guaranteed interactive-terminal shortcut.adk init <name> --yes --skip-link for AI-driven scaffolding, but only after login is already completed.adk link --workspace ... --bot ... as scriptable, but not guaranteed safe in every no-TTY environment.adk dev --logs --no-open as CI-friendly, not fully prompt-free.adk deploy --yes as auto-approving preflight only; config validation can still block automation.When to use CLI commands:
Response pattern:
adk commandadk add slack@3.0.0 to install")For documentation, patterns, and how-to questions, search and reference the documentation files directly:
When to use documentation:
How to answer documentation questions:
Find relevant files - Use Glob to discover documentation:
pattern: **/references/*.md
Search for keywords - Use Grep to find relevant content:
pattern: <keyword from user question>
path: <path to references directory from step 1>
output_mode: files_with_matches
Read the files - Use Read to load relevant documentation
Provide answer with:
For questions about what a bot does, how it's configured, or what it's capable of, combine CLI and file reading:
When to use:
Response pattern:
adk status --format json to get the structured project overviewagent.config.ts for full configuration detailsDocumentation should be located in ./references/ directory relative to this skill. When answering questions, search for these topics:
.bp.tsx files, metadata, usage in conversations)Note: Full integration lifecycle docs (discovery, adding, configuring, and using integrations) are in the separate adk-integrations skill. Install it with
npx skills add botpress/skills --skill adk-integrations. Theadk-integrationsskill coversadk search,adk add,adk info, configuration types, and common integrations. You need it if you are touching integrations.
Note: Frontend integration docs are in the separate adk-frontend skill. Install it with
npx skills add botpress/skills --skill adk-frontend. Theadk-frontendskill covers @botpress/client, calling actions, type generation, and authentication. You need it if you are touching any frontend code.
Note: Detailed eval docs are in the separate adk-evals skill. Install it with
npx skills add botpress/skills --skill adk-evals. Theadk-evalsskill covers writing evals, assertion types, testing workflows, and CLI usage. You usually always need it, for testing and evaluations.
Quick reference for accessing ADK runtime services:
// Always import from @botpress/runtime
import {
Action,
Autonomous,
Workflow,
Conversation,
z,
actions,
adk,
user,
bot,
conversation,
configuration,
context,
} from "@botpress/runtime";
// Bot state (defined in agent.config.ts)
bot.state.maintenanceMode = true;
bot.state.lastDeployedAt = new Date().toISOString();
// User state (defined in agent.config.ts)
user.state.preferredLanguage = "en";
user.state.onboardingComplete = true;
// User tags
user.tags.email; // Access user metadata
// Call bot actions
await actions.fetchUser({ userId: "123" });
await actions.processOrder({ orderId: "456" });
// Call integration actions
await actions.slack.sendMessage({ channel: "...", text: "..." });
await actions.linear.issueList({ teamId: "..." });
// Convert action to tool
tools: [fetchUser.asTool()];
// Get runtime services
const client = context.get("client"); // Botpress client
const cognitive = context.get("cognitive"); // AI model client
const citations = context.get("citations"); // Citation manager
myAction.ts, searchDocs.ts (camelCase)Users.ts, Orders.ts (PascalCase)chat.ts, slack.ts (lowercase)When answering questions, always verify these patterns against the documentation:
# All package managers are supported
bun install # Recommended (fastest)
npm install # Works fine
yarn install # Works fine
pnpm install # Works fine
# ADK auto-detects based on lock files
# - bun.lockb → uses bun
# - package-lock.json → uses npm
# - yarn.lock → uses yarn
# - pnpm-lock.yaml → uses pnpm
// ✅ CORRECT - Always from @botpress/runtime
import { Action, Autonomous, Workflow, z } from "@botpress/runtime";
// ❌ WRONG - Never from zod or @botpress/sdk
import { z } from "zod"; // ❌ Wrong
import { Action } from "@botpress/sdk"; // ❌ Wrong
// ✅ Both patterns work - export const is recommended
export const myAction = new Action({ ... }); // Recommended
export default new Action({ ... }); // Also valid
// Why export const?
// - Enables direct imports: import { myAction } from "./actions/myAction"
// - Can pass to execute(): tools: [myAction.asTool()]
// ✅ CORRECT - Handler receives { input, client }
export const fetchUser = new Action({
name: "fetchUser",
async handler({ input, client }) { // ✅ Destructure from props
const { userId } = input; // ✅ Then destructure fields
return { name: userId };
}
});
// ❌ WRONG - Cannot destructure input fields directly
handler({ userId }) { // ❌ Wrong - must be { input }
return { name: userId };
}
// ✅ CORRECT - Tools CAN destructure directly
export const myTool = new Autonomous.Tool({
handler: async ({ query, maxResults }) => {
// ✅ Direct destructuring OK
return search(query, maxResults);
},
});
// ✅ CORRECT - Use conversation.send() method
await conversation.send({
type: "text",
payload: { text: "Hello!" }
});
// ❌ WRONG - Never use client.createMessage() directly
await client.createMessage({ ... }); // ❌ Wrong
// Handler receives typed context based on the event type:
// type: "message" | "event" | "workflow_request" | "workflow_callback"
async handler({ type, message, event, request, completion, conversation, execute }) {
if (type === "workflow_request") {
// event: WorkflowDataRequestEventType, request: WorkflowRequest
await request.workflow.provide("email", { email: "..." });
}
if (type === "workflow_callback") {
// event: WorkflowCallbackEventType, completion: WorkflowCallback
console.log(completion.status); // "completed" | "failed" | "canceled" | "timed_out"
}
}
// ⚠️ isWorkflowDataRequest() and isWorkflowCallback() are deprecated
// Use type === "workflow_request" / "workflow_callback" instead
Match your response depth to the question depth. Not every question needs a full walkthrough.
One sentence definition + one short code example. That's it.
Knowledge bases add RAG to your bot — place markdown or PDF files in `src/knowledge/` and they become queryable with semantic search.
import { Autonomous } from '@botpress/runtime'
export default new Autonomous.Tool({
handler: async ({ query }) => adk.knowledgeBase.search({ query }),
})
Brief explanation + working code example + one critical pitfall only if it's a common trap.
Read the user's existing files first (src/actions/, src/tools/, src/tables/, agent.config.ts). Generate code that uses their actual names, patterns, and conventions. Only mention pitfalls they're likely to hit given their specific code.
Full structured response: read adk status --format json, agent.config.ts, and relevant source files. Map the data flow and identify the bot's archetype (RAG assistant, support agent, automation, etc.).
Don't answer with documentation. Run adk check --format json and adk logs error --format json, show evidence, and point to the root cause. Follow the debug loop from the adk-debugger skill.
If the answer fits in one sentence and a code snippet, don't add headers, pitfall sections, or related topics. More structure ≠ more helpful.