Skip to main content

Composition

Agent tools, interaction/service capabilities, and bundled skills

A package can contain three kinds of things, aimed at three different consumers:

Agent tools

Functions the model can call. Two hard rules by design.

Rule one: keep the number of tools as small as possible. Every registered tool gets injected into the model's context on every turn — more tools means more tokens and a higher chance the model picks the wrong one.

Rule two: merge related operations into a single tool with an action parameter.

ctx.tools.register({
  name: 'pjblog_post',
  title: 'PJBlog Post',
  description: `Manage blog posts.
action:
  list    — list all posts
  create  — create a new draft
  update  — update an existing post
  publish — publish a draft`,
  inputSchema: {
    type: 'object',
    properties: {
      action: { type: 'string', enum: ['list', 'create', 'update', 'publish'] },
      slug: { type: 'string' },
      title: { type: 'string' },
    },
    required: ['action'],
  },
  risk: 'medium',
  async execute(input, exec) { /* switch (input.action) */ },
});

description must enumerate every action — it's the model's only manual for how to use the tool.

Tool names are fixed lowercase snake_case, in the form <mini_tool_name>_<function_name>. Avoid generic short names like init or status.

If you genuinely need more than 10 tools, switch to a local MCP server for on-demand loading — see MCP integration.

Long-running task progress: exec.progress.report({ message }) shows an indeterminate progress indicator; add percent for a determinate one. Progress isn't the result — the tool still must return a final ToolResult.

Interaction & service capabilities

The parts not aimed at the model, triggered by the user or the system instead: Composer buttons, dialogs, forms, session containers, OAuth login, MCP bridging, background polling. This is the mini tool's "service surface" — see Standardized UI, Accounts, settings & OAuth login, Session containers, and Session Loop.

Bundled skills

A package can bundle skills, active while enabled and gone once disabled:

my-mini-tool/
└── skills/
    └── my-workflow/
        └── SKILL.md

Declare contributes.skills: true in the manifest — no need to do anything else. They are never copied into the global skills directory.