Skip to content
Content
Agent

capabilities

**Navigation**: [Agents package rules](../AGENTS.md) → **Capabilities and tool sources**

From plugin
nodetool
63614 skills14 agents

Claude Code

$ npx -y skills add nodetool-ai/nodetool --agent claude-code

Agent definition

capabilities.md

Capabilities and tool sources

**Navigation**: [Agents package rules](../AGENTS.md) → **Capabilities and tool sources**

Paths are relative to `packages/agents/` unless they name another package.

Capability registry (`src/capabilities/`)

A capability is what replaced the `Tool` class: a **spec** (wire name, description, input schema, and a required `PermissionCategory`), an **impl** `(run, args) => result`, and a **`CapabilityRun`** that carries everything only a run knows — the `ProcessingContext`, the permission gate, the browser router for `ui_*`, the sub-agent runtime, and the injected singletons (`nodeRegistry`, `providers`, `examples`, `exportDsl`, loaders). Per-run state arrives at *call* time, not at construction time, which is what lets one process-level registry serve every host. Design: [docs/tool-class-retirement-design.md](../../../docs/tool-class-retirement-design.md).

[`metadata.ts`](../src/capabilities/metadata.ts) owns the eager `CAPABILITY_SPECS` table and synchronous spec lookups. Each namespace imports its data-only sibling (`workflows.specs.ts`, `media.specs.ts`, …), which holds wire names, descriptions, schemas, categories and message templates without loading implementations. Use `capabilitySpec(name)` and `listCapabilitySpecs()` from this module when only metadata is needed.

[`registry.ts`](../src/capabilities/registry.ts) owns the lazy `CAPABILITY_MODULES` loaders and their process-level cache. Each entry refers to its namespace in `CAPABILITY_SPECS`. TypeScript checks the loader keys against the metadata keys. The registry reexports the metadata lookup APIs. `capabilityForName(name)` returns the shared eager spec and a lazy implementation. Chat and MCP catalogs use specs, with provider declarations built by `capabilityProviderTool(spec)`. Dependencies belong to the host `CapabilityRun`.

`toolFromLazyCapability(spec, run)`, `toolForCapabilityName(name, run)`, and `toolFromCapability(spec, impl, run)` remain compatibility adapters for executors and provider loops that require `Tool[]`. Their calls use the permission and validation machinery in `invoke.ts`. Native capabilities must never pass through `capabilityFromTool`.

A module imports its own specs back and attaches each to an implementation, so one spec *object* stands behind both halves, and `eagerSpecDrift` compares them by identity — a module that copied its spec would pass a field check and still be two things to keep in step. `CapabilitySpec.zodSchema` carries the Zod schema for the capabilities whose identity is one (`view_image`, `list_images`, the `ui_*` document tools, the `settings` and `packs` namespaces). It is checked once, by `validateCapabilityArgs` (`capabilities/args.ts`) at the invocation seam. Compatibility wrappers forward to that same seam. The reserved `_tool_call_id` survives validation, and approval prompts preserve `_message`.

What the registry deliberately does *not* serve is written down where the API it mirrors lives: `packages/websocket/src/trpc/sandbox-coverage.ts` classifies every tRPC procedure as covered by a capability, reachable through a differently-shaped one, withheld with the risk stated, or a recorded gap. `packages/websocket/tests/sandbox-api-coverage.test.ts` walks the live router and fails in both directions, so a new procedure cannot land unclassified and a stale verdict cannot outlive what it judged. The rule the withheld set follows: a run may act on the rows its own user owns, and may not touch credentials, billing, other tenants, host control, the transcript of its own behaviour, or anything that grants a third party access.

`DECLARED_CAPABILITY_MODULES` is derived from `CAPABILITY_MODULES`. The TypeScript key check requires a loader for every metadata namespace and rejects undeclared loader keys. `capabilityModuleDrift()` reports an export missing its name, description, schema, category or implementation (`capabilityModuleIssues`), a spec object rebuilt instead of imported from its `.specs.ts` sibling (`eagerSpecDrift`), and one name owned by multiple modules. [`tests/capabilities-registry.test.ts`](../tests/capabilities-registry.test.ts) also pins a checked-in `name → category` snapshot. [`tests/capabilities-coverage.test.ts`](../tests/capabilities-coverage.test.ts) requires everything `getBuiltinTools()` and `getAllMcpTools({})` assemble to resolve through `findCapability`, or appear in its exception list with a reason.

[`invoke.ts`](../src/capabilities/invoke.ts) holds the permission and validation sequence. Chat, MCP, sandbox imports, and headless evals invoke their owned `CapabilityRun` directly. A child context needs its own run because its memory, workspace, and delegation depth can differ, while sharing the host's gate.

`capabilityRunForTools` ([`legacy-tools.ts`](../src/capabilities/legacy-tools.ts)) builds the belt run. Native compatibility wrappers contribute their original spec and implementation, preserving injected dependencies while taking the belt's gate, signal, and invocation function. Only actual legacy implementations use `capabilityFromTool`. `gateLegacyTools` caches that run per belt and context for consumers that still require `Tool[]`. Sandbox bridges take tool metadata and an invocation function. The Code node supplies its host's gate. The sandbox belt retains its explicit ungated run. Tests in `capabilities-headless-permission.test.ts` cover direct invocation, headless permissions, metadata, validation, and the compatibility boundary.

The guest reaches a namespace by import, never by a global:

import { list_workflows } from "@nodetool-ai/sandbox-nodetool/workflows";
const { workflows } = await list_workflows({ limit: 20 });

Exports carry the wire name — `list_workflows`, not `listWorkflows` — so the prompt, the MCP surface and the belt all say one string. The facade generator and specifier shape live in `@nodetool-ai/protocol` (`sandbox-capability.ts`); the module list stays in the registry here, and the *hos

Read more
@nodetool-ai
Ships withnodetool

Open-source AI film studio · agent + node workflows Direct AI films, shot by shot. Start with one sentence. The agent writes the story, draws a still for every shot, and cuts the clips on a timeline.

6361 skill14 agents
Get the whole plugin

Stars on GitHub

Momentum

stars in total
636
Star history of nodetool-ai/nodetool on GitHub, a chart by star-history.com

Other agents on nodetool.

MUTATION_TESTING

MUTATION_TESTING

Agent

The agent package's pure, deterministic core (the chat permission gate, the control-tool plumbing, JSON extraction, and the…

cli

cli

Agent

**Navigation**: [Agents package rules](../AGENTS.md) → **Running Agents from CLI**

More agents from other plugins.

prompt-manager

prompt-manager

Agent

Agent for managing AI prompts on prompts.chat - search, save, improve, and organize your prompt library.

@gh-f@gh-fInstall Agent
humanize-diagnostician

humanize-diagnostician

Agent

정밀(strict) 모드 1단계 진단 에이전트. 글 전체를 한 번에 보고 "가장 지배적인 AI 티 패턴 3~6개"를 taxonomy ID와 함께 진단한다. 불안정한 span 열거(0↔18개로 요동) 대신 "무엇이 이 글을…

@epoko77-ai@epoko77-aiInstall Agent
blog-cluster-curator
Auto-invoked

blog-cluster-curator

Agent

Topic Clusters curator for the Claude Blog Brain. Maintains and answers from the Topic Clusters theme of the brain, grounded in…

@agricidaniel@agricidanielInstall Agent

Questions about capabilities.

Which coding agents can use capabilities?
capabilities installs in Claude Code and Cursor: each loads subagents from .claude/agents, so copy the file there. Flowy's auto-invocation runs in Claude Code only.