Skill SDK Reference
Build a Botonom agent skill: a small MCP microservice that gives your agents new tools. Use @botonom/skill-sdk, or register an existing MCP server with no code.
This guide begins with Overview, continues through Quick start (Path A), The contract, Permissions, and finishes with Path B - register an existing MCP server.
Overview
A skill is a capability you give a Botonom agent. At runtime it is a set of MCP tools (Model Context Protocol) the agent may call during a conversation, plus optional inbound events it reacts to. A skill is a small, self-contained network service: you declare the tools, permissions and handlers; Botonom handles routing, authentication, tenant/role context and delivery.
Two ways to build one:
- Path A - build on the SDK. You own the logic. Write the tool handlers (wrap a database, a third-party API, your own product) and ship the skill as its own service.
@botonom/skill-sdkgives you everything except the handlers. - Path B - register an existing MCP server. A standards-compliant MCP server already exists; point Botonom at its URL. No SDK, no code.
Quick start (Path A)
mkdir botonom-skill-warehouse && cd botonom-skill-warehouse
npm init -y
npm install @botonom/skill-sdk
Create skill.js:
import { defineSkill, startSkill, z } from "@botonom/skill-sdk";
const skill = defineSkill({
code: "warehouse",
version: "1.0.0",
tools: {
location: {
description: "Find where a stock item is stored.",
input: { sku: z.string() },
handler: async ({ sku }, ctx) => ({ sku, location: "A-12-3" }),
},
},
});
startSkill(skill, { port: 3620 });
The service now serves POST /mcp, GET /manifest, POST /events and GET /health. Register it in Botonom, install it on an agent, grant the capability, and the agent can call warehouse__location in a real chat.
The contract
The manifest is the contract. Any service that serves the same GET /manifest and POST /mcp shape is a valid Botonom skill, in any language - the Node SDK is just the reference implementation.
- Each skill is its own service: one process, one port, one bearer. The provider reaches it over HTTP and speaks MCP (
POST /mcp). - A tool
actioninside skillcodeis exposed to the model ascode__action. - The provider passes a trusted per-call context (
ctx) to your handler: tenant ids, user id and roles. Trust onlyctx.
Permissions
Permissions are enforced inside the skill, at the data layer, never in the prompt. The source of truth is the capability, not a role name - so your skill never hardcodes a tenant's roles.
Botonom's built-in roles are owner, admin, member (and public for anonymous visitors). Everything else is a role the company defines in its dashboard, with names of its choosing.
- Each tool has a capability,
code.action(e.g.warehouse.location). In Company > Roles & Access each company grants that capability to whichever of its own roles it wants. Different companies with different role names all work, because the match is on the capability. - At call time the control plane resolves the caller's roles to their allowed capabilities and hands those to your skill; the SDK checks the capability (deny-by-default). A tool stays invisible until its capability is granted.
- You may optionally add
roles: [...]to a tool as a standalone fallback (used only when a skill runs on its own, before grants propagate). In production the panel's capability grants override it, so most skills omit it. - For a public-facing agent (embedded widget) grant only the safe capabilities to the anonymous
publicrole.
Path B - register an existing MCP server
If you already run a standards-compliant MCP server you do not need the SDK at all. Point Botonom at its URL; Botonom reads its manifest, registers the tools, and enforces permissions the same way. This is the fastest path when a capability already exists as an MCP service.
