Give bots skills: runbooks they load when a job matches

A skill is a runbook: a name, a unique slug, a one-line description of when
it applies, and the markdown body. A run only ever sees the slug and
description (one load_skill tool carries them), and reads the whole body
only when it calls the tool, so a long runbook costs nothing until needed.

Skills are the third extension kind beside MCP servers and custom tools, on
the same botExtensionsSql path, so per-bot, per-workspace and all-bots
grants work the same way, and attachDefaultExtensions hands an every-bot
skill to new bots. load_skill is a reserved tool name, so a custom tool
cannot shadow it, and a built-in wins a clash.

Managed on Settings > Skills; ExtensionRow links each kind to its own page
and a skill never reports a failure, since nothing connects or runs.
This commit is contained in:
2026-10-22 12:31:42 +01:00
parent 379ef35e08
commit 08d02e6033
62 changed files with 1438 additions and 79 deletions
+29 -3
View File
@@ -598,6 +598,27 @@ export type CustomToolRecord = {
| { kind: "prompt"; config: CustomToolPromptConfig }
);
/**
* A `skills` row: a runbook a bot loads when it applies.
*/
export type SkillRecord = {
id: number;
name: string;
slug: string;
description: string;
body: string;
all_bots: boolean;
enabled: boolean;
};
/**
* A skill as the Skills settings page shows it: nothing secret in one, so
* it's the row with who gets it instead of `all_bots`.
*/
export type PublicSkill = Omit<SkillRecord, "all_bots"> & {
access: ExtensionAccess;
};
/**
* An MCP server as the MCPs settings page shows it. Only super admins get
* how it's reached (`url`, `headers`, `command`, `setup_command`, `env`).
@@ -650,7 +671,7 @@ export type ExtensionTargets = {
* composer show it.
*/
export type BotExtension = {
kind: "mcp" | "tool";
kind: "mcp" | "tool" | "skill";
id: number;
name: string;
description: string;
@@ -668,12 +689,12 @@ export type BotExtension = {
};
/**
* A bot's MCP servers and tools, and what can be added. Only super admins
* A bot's MCP servers, tools and skills, and what can be added. Only super admins
* and admins (the super admin alone for the coordinator) manage them.
*/
export type BotExtensionsPayload = {
attached: BotExtension[];
addable: { kind: "mcp" | "tool"; id: number; name: string }[];
addable: { kind: "mcp" | "tool" | "skill"; id: number; name: string }[];
can_manage: boolean;
};
@@ -681,6 +702,10 @@ export type McpServersOverviewPayload = ExtensionTargets & {
servers: PublicMcpServer[];
};
export type SkillsOverviewPayload = ExtensionTargets & {
skills: PublicSkill[];
};
export type CustomToolsOverviewPayload = ExtensionTargets & {
tools: PublicCustomTool[];
};
@@ -1016,6 +1041,7 @@ export type PagePropsType = {
push_overview?: PushOverview | null;
mcps_overview?: McpServersOverviewPayload | null;
tools_overview?: CustomToolsOverviewPayload | null;
skills_overview?: SkillsOverviewPayload | null;
bot_extensions?: BotExtensionsPayload | null;
/**
* The files browser's folders (a user's own crew and media, and what a