Files
holocron/plugins/kyberforge/skills/agent-audit/references/description-quality.md
Defame1297 0f2bb242ad chore(plugins): sync generated content mirrors
Regenerates `plugins/*/skills`, `plugins/*/agents`, both per-plugin `plugin.json` manifests and the
two marketplace mirrors from `.apm/` per ADR-0017, via `scripts/sync-plugin-content.sh --all`.

The manifests matter beyond tidiness here: `plugin.json` carries the plugin version and wins over
the marketplace entry at install time (calculatePluginVersion precedence). Until this ran, the patch
bumps in the preceding commit were inert for anyone installing these plugins.

ADR: 0017
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EeH8SCbcrCAQrtymkNuhKP
2026-09-09 05:15:53 +00:00

97 lines
5.1 KiB
Markdown

---
source_keys:
- context7-websites-code-claude
- claude-code-subagents-docs
- context7-github-en-copilot
- github-custom-agents-configuration
---
# Agent Description Quality Reference
Upstream source: Claude Code subagent reference, GitHub Copilot custom-agents configuration.
House contract: ADR-0020, the context budget. The house contract is narrower than either
platform's schema rather than a reinterpretation of it: where both speak, both must be satisfied.
## Why the description is the expensive part
At startup an agent loads only the `name` and `description` of every installed skill and agent.
The body is never seen until the agent is invoked. The description therefore carries the entire
triggering burden **and** is paid for in every session, whether the agent fires or not.
A second cost is less obvious and is a correctness hazard rather than a token cost: a description
that summarises the workflow is a shortcut the caller takes *instead of* reading the body. A
measured failure upstream — a description saying "code review between tasks" — produced one review
where the body's flowchart specified two.
## Step 0 — establish which contract applies
Read the frontmatter before judging a single word.
- **`disable-model-invocation: true`** — the agent is hand-invoked. Its description is never
matched against user intent, so it is not a routing string. It carries **one plain human-facing
sentence** stating what the agent does. Audit it for that and nothing else. Reporting a missing
trigger clause, a missing boundary clause or absent indirect triggers on a hand-invoked agent is a
wrong finding, not a strict one. The field is Copilot-only and not on the vendor-neutral APM
allowlist, so this case arises in a Copilot `.agent.md` at project/user scope and nowhere else.
Its Claude Code counterpart has no equivalent field and stays model-invoked, so the two halves of
the pair carrying differently shaped descriptions is expected there rather than a
pair-consistency finding.
`user-invocable: false` does not belong in this bullet. The two are separate fields with opposite
defaults — `disable-model-invocation` (default `false`) governs runtime auto-selection,
`user-invocable` (default `true`) governs manual invocation, and the retired `infer` field was
replaced by the pair rather than by either one. So `user-invocable: false` says nothing about
whether the agent is model-routed: judge that from `disable-model-invocation` alone, and where
that is absent the three-part shape below still applies. `user-invocable` carries no
description-quality contract of its own and is out of this file's scope entirely.
- **No such flag** — the agent is model-invoked and the rest of this file applies.
## The three-part shape
A model-invoked description carries exactly three things:
1. **Trigger clause.** When to invoke, phrased imperatively: `Use when ...`. Not `This agent ...` —
the caller is deciding whether to act, not reading a catalogue entry.
2. **At most one capability clause.** What it does, in one clause. Never an enumeration.
3. **Boundary clause.** Compressed form: `Not <thing> -> <skill-name>.` The target must resolve to
a real skill directory or agent file in the authoring source.
Everything else belongs in the body or in the plugin's `README.md`.
## Indirect triggers — conditional, never blanket
Add "even if the user doesn't say X" **only where the user's natural phrasing genuinely omits the
domain word.** True for the `gitea-*` family: people say "create an issue", not "create a Gitea
issue". False for `git-commits`: nobody asks for a commit without saying commit. A blanket
indirect-trigger clause on an agent whose domain word is unavoidable is padding charged to every
session.
## Near-miss exclusions
Add a boundary clause only where a sibling skill or agent could plausibly steal the activation. Use
strong near-misses — queries that share keywords but need something different — not weak ones. One
boundary clause per genuine near-miss; a list of four is enumeration wearing a boundary's clothes.
## Before / after
```yaml
# FAIL — a noun-phrase opener rather than a trigger, capability enumeration in
# place of one capability clause, and no boundary clause at all, preloaded into
# every session forever. (The live git-orchestrate description, 254 chars.)
description: Orchestrates git workflow operations for other agents. Invoke when a
caller needs a multi-step or destructive git operation (rebase, force-push, branch
deletion) coordinated across domain skills with safety gates, session context, and
structured results.
# PASS — trigger, one capability clause, boundary. The operation list and the
# safety-gate mechanics are the body's job; the router cannot act on them.
description: >
Use when an agent caller needs a multi-step or destructive git operation
dispatched and safety-gated. Not conversational git help -> git-workflow.
```
## Where the criteria live
Every FAIL and SUGGESTION criterion for this dimension is in `references/finding-criteria.md`,
which Step 3 reads on every run. This file is the reasoning behind them, loaded only when that file
puts the description dimension in play.