Create a skill for generating Tool plugins (best practices, how-to, placement)
### Problem/Motivation The Tool API lets modules expose well-defined, typed actions as `#[Tool]` plugins, and the `tool_ai_connector` submodule automatically surfaces those same tools to AI agents as `AiFunctionCall`s. Authoring a *correct* tool, though, means getting several moving parts right at once: - the `#[Tool]` attribute — `id`, `label`, `description`, the `ToolOperation` enum (`Explain` / `Read` / `Transform` / `Trigger` / `Write`) and the `destructive` flag; - typed `input_definitions` / `output_definitions` (`InputDefinition`, the list/map variants, `constraints`, `default_value`, `required`); - extending `ToolBase` (or `ConditionToolBase`) and implementing `doExecute(): ExecutableResult` plus `checkAccess()`; - the plugin location/namespace (`src/Plugin/tool/Tool/` → `Drupal\<module>\Plugin\tool\Tool\<Name>`), the plugin-ID gotcha (the id must equal the group or be prefixed `group:thing`), and a per-tool permission; - and, critically, *which submodule a new tool belongs in* (`tool_content`, `tool_entity`, `tool_system`, `tool_user`, `tool_content_translation`, …). There is no guided path for contributors — or for AI coding agents — to produce a consistent, correct tool, so tools drift in shape and quality. ### Proposed resolution Create an agent skill (a Claude Code / agent skill, in the same spirit as the existing `create-ai-provider` and `new-document-loader-plugin` skills) that scaffolds a new Tool plugin and encodes the project's conventions. It should cover the three things requested: **1. What should be a tool (best practices)** - A tool is a single, atomic, well-defined action with typed inputs and outputs — not a grab-bag of behaviour. - Choose the correct `ToolOperation` (`Explain` / `Read` / `Transform` / `Trigger` / `Write`) and set `destructive: TRUE` honestly for anything that deletes or irreversibly changes data (it encourages confirmation). - Prefer typed inputs with `constraints` and sensible `default_value`s over free-form strings; mark inputs `required` correctly and declare `output_definitions` so callers (and LLMs) receive structured results. - Always implement `checkAccess()` and ship a matching permission entry. - Reuse existing tools and TypedData adapters instead of duplicating; don't model as a tool what is really static configuration. **2. How to create one** - Generate the plugin class under `src/Plugin/tool/Tool/`, namespace `Drupal\<module>\Plugin\tool\Tool\<Name>`, extending `ToolBase`. - Emit the `#[Tool]` attribute with id/label/description/operation and the input/output definitions. - Stub `doExecute(array $values): ExecutableResult` returning `ExecutableResult::success()` / `ExecutableResult::failure()`, plus `checkAccess()`. - Add the permission to the module's `*.permissions.yml`. - Point at `LogMessage` (`tool_system`) and the `tool_content` entity tools as reference implementations. - Remind the author that, with `tool_ai_connector` enabled, the tool is **automatically exposed to AI agents** — so the label/description must read well to an LLM and every input needs a clear description. **3. Where they belong** - Route the new tool into the right domain submodule (content → `tool_content`, entity/field structure → `tool_entity`, system → `tool_system`, user → `tool_user`, translation → `tool_content_translation`), or scaffold a new submodule when no domain fits. - The skill should ask which domain, default to the closest match, and place the files accordingly. The skill should live in the module repo (e.g. under `.claude/skills/`) so it ships with the project and stays in sync with the API — the way other AI-initiative modules already carry their skills. ### Remaining tasks - Write the skill (`SKILL.md` plus any scaffolding/templates). - Capture the best-practices checklist above as the skill's guidance, with a concrete worked example. - Add a reference/example tool the skill can mirror. - Optional: a short docs page that links to the skill. ### User interface changes None — contributor tooling. ### API changes None.
issue