Skip to main content

Command Palette

Search for a command to run...

BDK

Project layout

A Bot Development Kit (BDK) project keeps agent files under bot/. Each file's path determines how BDK loads it.

Existing projects rooted at agent/ remain supported.

Folder structure

For the capabilities below, identity comes from the path.

Path under bot/Resolves to
tools/approve_pr.tstool approve_pr
mcp-connections/linear.tsMCP connection linear (model + host)
host-connections/inventory.tsHost MCP connection inventory (host + mcp oauth only)
skills/pr-review.mdskill pr-review
subagents/reviewer/subagent reviewer
extensions/ci.tsextension mount ci; its contributions become ci__<name>
extensions/notion.tsCursor plugin mount notion (cursorPlugin); its skills, agents, and MCP servers become notion__<name>
channels/drive.tschannel drive, routes under /v1/channels/drive

The root agent takes its name from package.json name, falling back to the directory name. When serving multiple agents, the slug is the directory name and must match [A-Za-z0-9][A-Za-z0-9_-]* (and not the reserved v1, playground, or docs segments).

Project tree

Most projects start with this shape.

my-agent/├── package.json├── bot/│   ├── agent.ts               # model and local harness config│   ├── instructions.md        # always-on system prompt (required)│   ├── tools/│   │   └── approve_pr.ts      # one typed tool per file│   ├── skills/│   │   └── pr-review.md       # on-demand procedures (SKILL.md convention)│   ├── mcp-connections/│   │   └── linear.ts          # tools from external MCP servers│   ├── host-connections/│   │   └── inventory.ts       # host-only MCP tools│   ├── subagents/│   │   └── reviewer/│   │       ├── agent.ts│   │       └── instructions.md│   ├── channels/│   │   └── github.ts          # messages and external events│   └── hooks/│       └── audit.ts           # observe session events└── evals/    └── readiness.eval.ts      # regression cases

Evals stay in evals/ at the project root, as a sibling of bot/, never inside it. See Evals.

Folder reference

Each path maps to a capability and a reference page.

Path under bot/What it isReference
agent.tsdefineAgent({ model?, local? }); the model defaults to grok-4.5 with effort=high, fast=trueAgent config
instructions.mdAlways-on system prompt, required on the root agent (.ts and directory forms exist)Instructions
tools/<name>.tsOne typed tool; filename = tool name. execution: "server" (in-process, default) or "agent" (a script that runs where the agent runs)Tools
skills/*SKILL.md-convention procedures, loaded on demandSkills
mcp-connections/<name>.tsMCP servers, available to the model, to server tools (ctx.host.mcp), and to channel/schedule handlers (args.host.mcp)MCP connections
host-connections/<name>.tsPrivileged MCP servers for ctx.host.mcp and mcp oauth. The model never sees them.MCP connections
subagents/<id>/Child agent directory; description requiredSubagents
extensions/<ns>.ts or extensions/<ns>/A mounted extension or Cursor plugin; its contributions become <ns>__<name>Extensions
channels/*.tsHTTP surfaces beyond the built-in session API; slack.ts and github.ts use the platform packsChannels
hooks/*.tsObserve-only event subscribers, never fatalHooks
artifacts.tsdefineArtifacts kinds, the tag_artifact opt-in, and retentionArtifacts
schedules/*Cron-driven runs (UTC, 5-field; never auto-fire under --dev)Schedules
reminders/*.tsNamed reminder handlers that stay armed across restartsSchedules
sandbox/workspace/**Seed files copied into each local session workspaceSessions
lib/Import-only shared code, never discoveredNone

Discovery rejects a bot/result.ts file. To act on a turn's decision, have the model record it with an authored tool, then act on it from a turn.completed hook.

Evals use project-root paths:

Project-root pathWhat it isReference
evals/evals.config.tsShared eval settings (e.g. maxConcurrency); required when evals existEvals
evals/**/*.eval.tsFilesystem evals; case id = path under evals/Evals

Use bot/lib/ for shared imports. A .ts file in one of the listed discovery folders loads as a definition; unrecognized directories produce a validation warning.

Inspect discovery

Run bdk validate --dir . and bdk info --dir .. validate prints diagnostics, and serve refuses to start on error-severity ones. Warnings print but don't block. info lists the discovered surface, so a missing tool or channel shows up immediately. From there, check the folder reference: the file is usually in the wrong directory or has the wrong extension.

bdk validate --dir .    # diagnostics; non-zero exit on errorsbdk info --dir .        # human-readable surfacebdk info --dir . --json # machine-readable project info (same shape as GET /v1/info)
  • Agent config: the config at the project root
  • Tools: add typed actions under tools/
  • CLI: commands that discover this tree