跪拜 Guibai
← All articles
AIGC · Backend

Three Design Pitfalls in Agent Skill Systems (and How to Avoid Them)

By AI开发小华 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Agent frameworks are proliferating, and nearly every team building on top of them eventually adds a Skill or plugin system. Getting the metadata contract, invocation path, and lifecycle management right from the start avoids silent token waste, broken tool permissions, and context pollution that are painful to debug later.

Summary

A Skill is a loadable instruction pack centered on a SKILL.md file, but the simplicity of the concept hides several design traps. The header metadata goes well beyond name and description: fields like `allowed-tools`, `disallowed-tools`, `model`, `context`, and `agent` control tool permissions, model routing, and execution isolation. Misunderstanding `disallowed-tools` as a permanent block instead of a single-turn restriction is a common bug that silently breaks subsequent agent actions.

Two invocation patterns dominate: a dedicated `SKILL_TOOL` that returns an activation marker, base directory, and body, or a simpler `ReadFile` approach that reads the markdown directly. The dedicated tool unlocks fine-grained permission scoping and state tracking; the file-read approach works for early prototypes but leaves metadata unused. Regardless of the method, registration must stay lightweight—only name and description enter the system prompt, never the full body.

The third pitfall is skipping deduplication and state tracking. Without an activation marker and an active-skills set, the same Skill body gets injected repeatedly, burning tokens and bloating context. That same set also governs when to apply and revoke tool permissions, making it the linchpin of a clean implementation.

Takeaways
`disallowed-tools` applies only to the turn where the Skill is active; failing to restore those tools in the next turn permanently breaks them for the session.
Skill registration must inject only `name` and `description` into the system prompt—never the full body—or context windows fill with irrelevant content before any Skill is even loaded.
A dedicated `SKILL_TOOL` returns three pieces: an activation marker for deduplication, a base directory for resolving relative paths, and the SKILL.md body.
The `model` field restricts a Skill to specific models, preventing small-model crashes on long-context tasks or routing cheap Skills to cheaper models.
An `active_skills` set serves double duty: it prevents duplicate injections of the same Skill body and tracks which permissions to apply or revoke.
`context: fork` combined with a sub-agent isolates messy multi-step Skills so they don't pollute the main conversation context.
Conclusions

The distinction between `allowed-tools` as pre-approval versus `disallowed-tools` as hard block is subtle but consequential—many implementers treat both as simple filters and miss that one removes the need for human approval while the other requires explicit restoration logic.

Claude Code and Codex already diverge on invocation: Claude Code uses a dedicated tool, while Codex shells out to `cat`. This suggests the ecosystem hasn't converged on a single pattern, and anyone building a Skill system today is making a bet on which approach becomes standard.

The `metadata` field is explicitly not read by the model, which makes it a clean extension point for ops concerns—cost centers, ownership, auditing—without risking prompt pollution. Few plugin systems in the Western ecosystem separate machine-readable metadata from model-readable instructions this cleanly.

Concepts & terms
Skill activation marker
A system-level tag (e.g., `<command-name>code-review</command-name>`) returned when a Skill is loaded, used to detect duplicate invocations and track which Skills are currently active so permissions can be scoped and revoked correctly.
Turn-based tool permission scoping
The practice of applying `allowed-tools` and `disallowed-tools` only for the duration of a single conversation turn. When the turn ends, the tool pool reverts to its previous state; failing to implement this reversion causes tools to remain permanently blocked.
Lightweight Skill registration
A design principle where only a Skill's `name` and `description` are injected into the system prompt during registration. The full body is loaded on demand via a tool call, keeping the base context small and avoiding irrelevant content before a Skill is actually needed.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗