--- name: agent-author description: > Use when the user wants to create a new agent definition file from scratch ("write an agent for X", "build a subagent that does Y", "create an agent definition for Z"), or improve an existing one. Handles agent definitions at plugin/APM, project, and user scope. Project and user scope always generate a Claude Code (`.md`) + Copilot CLI (`.agent.md`) file pair in one pass; plugin/APM scope generates a single vendor-neutral `.apm/agents/.agent.md` file instead (no per-target Claude Code / Copilot split). Also use when the user provides inline feedback about an agent's behavior and wants it applied, or when a grill session has produced findings the user wants acted on — even if they don't say "improve" explicitly. Do not use for read-only review — examine agent files manually or run a grill session to generate improvement signals. Do not use to author skills — use /skill-author instead. allowed-tools: Bash Read Write Edit metadata: category: factory source_keys: - context7-websites-code-claude - claude-code-plugins-docs - claude-code-subagents-docs - context7-github-en-copilot - github-custom-agents-configuration - github-cli-plugin-reference - github-plugins-creating --- ## Gotchas - At plugin/APM scope, bump the resolved package's `apm.yml` `version` after every change — minor for a new agent, patch for a fix. Consumers compare this version to detect updates; skipping it hides the change. - At plugin/APM scope, `tools` and all Claude-only fields (`isolation`, `maxTurns`, `effort`, `memory`, `permissionMode`, `disallowedTools`, `skills`, `color`, `initialPrompt`, `background`, `hooks`, `mcpServers`) are omitted entirely, not merely restricted (ADR-0016: `apm compile` copies frontmatter verbatim to both harnesses with no per-target integrator, so a harness-specific value is wrong on at least one). Only project/user scope supports these fields. - An `apm.yml` with no top-level `type:` field is a marketplace-only manifest, not a package root — the walk-up skips it and keeps going. - `AskUserQuestion`, `EnterPlanMode`, `ExitPlanMode`, `ScheduleWakeup`, and `WaitForMcpServers` are never available to any subagent regardless of the `tools` field. Exception: `ExitPlanMode` is available when the parent session runs in `permissionMode: plan`. - Duplicate `name` values in the same scope: Claude Code silently discards one without warning. Always verify uniqueness before shipping. - Plugin agents in subdirectories get scoped identifiers (`plugin:folder:name`) — keep agents flat in `agents/` to avoid this. Applies to project/user-scope Claude Code agents only. - Copilot CLI agent files **must** use the `.agent.md` extension — a plain `.md` file isn't picked up. The plugin/APM-scope single file also ends in `.agent.md` by convention, but it's vendor-neutral, not Copilot-only — it compiles to Claude Code too. - Copilot has no `permissionMode`, `maxTurns`, `isolation`, or `memory` fields — do not include them in project/user-scope Copilot files. - `model` resolution order for Claude Code: `CLAUDE_CODE_SUBAGENT_MODEL` env var → per-invocation parameter → frontmatter `model` → main session model. The frontmatter value is a low-priority default, not a guarantee. ## Route If the destination resolves to plugin/APM scope (scope detection in Step 1 finds a `type:`-bearing `apm.yml` at or above the root), read `references/deployment-modes.md`. Determine which flow before touching the filesystem: - **Neither `.md` nor `.agent.md` exist at the target paths** → follow **Creating a new agent** - **At least one file exists + improvement signals present** → follow **Improving an existing agent** - **At least one file exists + no signals** → ask: "No improvement signals found. Did you mean to create a new agent, or do you have feedback to apply?" Signals: grill session output, inline user feedback, session context describing what went wrong. ## Creating a new agent ### Prerequisites Before touching the filesystem, confirm you have: - [ ] Agent name (kebab-case, e.g. `code-reviewer`) - [ ] Root directory (a path inside a package for plugin/APM scope, project root, or `~` for user scope) - [ ] Agent purpose — one sentence describing the task this agent handles - [ ] Trigger condition — when should the runtime delegate to this agent? If any are missing, stop and ask before proceeding. Then capture `git log --oneline -1` before touching the filesystem — Step 5 needs it to verify a real commit landed. Verify `kyberforge:agent-audit` is available — it ships with the kyberforge plugin and is co-installed with this skill. If unavailable, stop and tell the user to install the kyberforge plugin before continuing. ### Step 1 — Scaffold Run the scaffold script with the agent name and root directory: ```bash bash scripts/new-agent.sh ``` Examples: ```bash bash scripts/new-agent.sh code-reviewer packages/my-package/ # plugin/APM scope if packages/my-package/apm.yml has a type: field bash scripts/new-agent.sh deploy-assistant . bash scripts/new-agent.sh security-reviewer ~ ``` **Scope detection (script handles this automatically).** The script walks up from `` for a package boundary — same shape `agent-audit`'s `validate.sh` uses: - Nearest ancestor `apm.yml` with a top-level `type:` field (`instructions`/`skill`/`hybrid`/`prompts`) → **plugin/APM scope** → `/.apm/agents/.agent.md` (single vendor-neutral file). A `type:`-less `apm.yml` is marketplace-only — skipped, walk continues upward. - No such `apm.yml`, `` is a project directory → **project scope** (unchanged) → `/.claude/agents/.md` + `/.github/agents/.agent.md` - `` is exactly `~` (checked directly, no walk-up) → **user scope** (unchanged) → `~/.claude/agents/.md` + `~/.copilot/agents/.agent.md` A bare `plugin.json` with no `apm.yml` no longer signals plugin scope — that path is fully replaced, not dual-mode; it falls through to project scope. The script is file-by-file no-op — it skips any file that already exists. ### Step 2 — Fill in the agent file(s) **At plugin/APM scope**, there is exactly one file: `/.apm/agents/.agent.md`. Frontmatter carries ONLY `name`, `description`, and optionally `model` — never `tools` or the other Claude-only fields listed in Gotchas (ADR-0016). Fill in `name`, `description`, `model`, and the system prompt body per the guidance below; the rest of this step's field-by-field guidance (tools, maxTurns, effort, memory, isolation, disallowedTools, skills, color, initialPrompt, background) is project/user scope only. Skip Step 3 and go to Step 4. **At project/user scope**, continue below to fill in both provider files — this step covers the Claude Code file (`.md`); Step 3 covers the Copilot file. Open the scaffolded Claude Code file. Replace every `FILL IN:` placeholder. **Remove all template documentation comments from the YAML frontmatter after filling in required fields** — these are marked with `` and must be deleted before shipping. **`name`** — lowercase letters and hyphens only. Must be unique within the scope. **`description`** — the most important field for autonomous delegation: - Start with an action verb: "Reviews...", "Analyzes...", "Generates..." - If this agent should trigger without explicit user direction, include "Use proactively" in the description - Specific about the triggering condition and expertise domain - Under 300 characters preferred **`tools`** (project/user scope only — never at plugin/APM scope) — restrict to what the agent actually needs. Omit to inherit all tools. Use `Agent(type1,type2)` to limit which subagent types this agent can spawn; omit `Agent` entirely to prevent spawning. **Optional fields worth considering (project/user scope only — never at plugin/APM scope):** - `model`: set when this agent needs a different capability tier (`haiku` for fast tasks, `opus` for deep reasoning) - `maxTurns`: set a cap to prevent runaway agents on bounded tasks - `effort`: set to `low` for single-lookup tasks, `high` or above for deep reasoning or multi-file analysis — overrides session effort level; omit to inherit - `memory`: `user`, `project`, or `local` — only when cross-session state is genuinely needed - `isolation: worktree` — only when the agent modifies files and needs an isolated copy - `disallowedTools`: space-separated denylist applied before `tools`; supports `mcp__*` glob patterns (e.g. `disallowedTools: mcp__filesystem__*`) - `skills`: list of skill names preloaded at agent startup — different from the `source_keys` metadata field - `color`: UI color for the agent tile (`red`, `blue`, `green`, `yellow`, `purple`, `orange`, `pink`, `cyan`) - `initialPrompt`: auto-submitted as the first turn when this agent activates as the main session thread; only set when this agent is intended for main-thread activation - `background`: set `true` to force background execution **`source_keys`** — top-level list of research source slugs that informed this agent. Add only when research sources were used (i.e. entries with `` `extracted` `` status are in context from a prior `/research` session). Each slug must match an H2 heading in `sources.md` — see Step 4 for where that file lives (plugin/APM scope only). Omit entirely when no research was used. ```yaml source_keys: - my-source-slug ``` **System prompt body** — write as a direct role instruction: - Open with: "You are a [role]. When invoked, [primary action]." - Cover: inputs expected, process steps, output format, error handling - One job per agent ### Step 3 — Fill in the Copilot agent file (project/user scope only) Skip this step entirely at plugin/APM scope — there is no separate Copilot file there. The single `.apm/agents/.agent.md` file from Step 2 already compiles to both Claude Code and Copilot CLI via `apm compile`. **Two distinct Copilot agent formats** exist, with different paths and field sets. Choose one based on the deployment target: **CLI format** (default — what the scaffold creates): - Path: `.github/agents/.agent.md` (project) or `~/.copilot/agents/.agent.md` (user) - Extension: **must be `.agent.md`** - Supported fields: `name` (required), `description` (required), `tools` (optional) - `tools` uses Copilot aliases: `execute` (shell), `read`, `edit`, `search`, `agent`, `web` - Body length limit: **30,000 characters** — content beyond this is silently truncated **Cloud/IDE format** (use when targeting Copilot Chat in VS Code or GitHub.com): - Path: `.github/copilot/agents/.md` (note: plain `.md`, different directory) - Additional fields available: `target` (`vscode`, `github-copilot`, or omit for both), `user-invocable` (set `false` to hide from manual invocation), `disable-model-invocation` (set `true` to require explicit user invocation), `mcp-servers` (MCP server config — processed by cloud runtime, ignored in VS Code) - Body length limit: **30,000 characters** — silently truncated **Do not include Claude Code-only fields in either format**: `maxTurns`, `isolation`, `memory`, `permissionMode`, `effort`, `hooks`, `mcpServers`. **`source_keys`** — add the same top-level list as the CC file when research sources were used. Omit when no research was used. **Remove all template documentation comments from the YAML frontmatter after filling in required fields** — these are marked with `` and must be deleted before shipping. The system prompt body should match the Claude Code version — the agent's task definition is the same across providers. ### Step 4 — Populate or delete `sources.md` (plugin/APM scope only) Skip at project/user scope. The file lives at the package root (alongside `apm.yml`), not inside `.apm/agents/` — otherwise tooling that scans that directory for agent definitions would treat it as an agent needing frontmatter (ADR-0010). If a research `sources.md` is present in the conversation context: 1. Filter to entries with `` `extracted` `` status only. 2. For each entry, identify which agent file it contributed to. 3. Write `sources.md` at the package root using the format below. Paths in `Contributing files:` are relative to the package root. ```markdown # Sources ## slug-name - **URL:** - **Research doc:** - **Description:** - **Contributing files:** .apm/agents/.agent.md - **Status:** `extracted` ``` Each slug must match an H2 heading, and each slug must also appear in the `source_keys` list of the file listed under `Contributing files:`. If no research sources are in context, delete `sources.md`. ### Step 5 — Validate and close Run this checklist before invoking the audit: **Plugin/APM scope — single file (`.agent.md`):** - [ ] `name` field present, kebab-case, unique in scope - [ ] `description` field present and action-first - [ ] Frontmatter contains ONLY `name`, `description`, and optionally `model` (plus `source_keys` if research-sourced) — no `tools`, `isolation`, `maxTurns`, `effort`, `memory`, `permissionMode`, `disallowedTools`, `skills`, `color`, `initialPrompt`, `background`, `hooks`, or `mcpServers` - [ ] System prompt body present and non-empty - [ ] No `FILL IN:` placeholders remain - [ ] No `` template comments remain in frontmatter **Project/user scope — Claude Code file (`.md`):** - [ ] `name` field present, kebab-case, unique in scope - [ ] `description` field present and action-first - [ ] System prompt body present and non-empty - [ ] No `FILL IN:` placeholders remain - [ ] No `` template comments remain in frontmatter **Project/user scope — Copilot CLI file (`.agent.md`):** - [ ] File extension is `.agent.md` (not `.md`) - [ ] `name` field matches the filename stem (e.g. `name: my-agent` in `my-agent.agent.md`) - [ ] `description` field present - [ ] No Claude Code-only fields (`maxTurns`, `isolation`, `memory`, `permissionMode`, `effort`, `hooks`, `mcpServers`) - [ ] System prompt body present and non-empty - [ ] Body does not exceed 30,000 characters - [ ] No `` template comments remain in frontmatter At plugin/APM scope, apply a **minor bump** to the resolved package's `apm.yml` `version` (single manifest, e.g. `1.0.4` → `1.1.0`). Invoke `kyberforge:agent-audit` on the created file(s) before closing — validates the pair at project/user scope, the single file at plugin/APM scope. **Commit verification.** Capture `git log --oneline -1` before Step 1 and keep it. Once the audit is clean, run `git add` and `git commit` for the new agent files — do not stop at staging. Then run `git log --oneline -1` again and confirm the hash changed from the one you captured at the start. A non-empty `git diff --stat` is not sufficient proof of completion: staged-but-uncommitted work isn't part of any commit and can be silently lost if the working tree is cleaned up before a commit lands. Only report the agent as done once the hash has actually changed. ## Improving an existing agent ### Step 1 — Verify inputs Confirm the agent files exist and at least one improvement signal is present in the conversation or a referenced file. If no signals: "This skill applies existing signals to an agent. For a blind review, examine the files manually or run a grill session first." Verify `kyberforge:agent-audit` is available — it ships with the kyberforge plugin and is co-installed with this skill. If unavailable, stop and tell the user to install the kyberforge plugin before continuing. Capture `git log --oneline -1` now, before making any edits — Step 5 needs it to verify a real commit landed. **Partial state (project/user scope only)** — if one provider file exists but not the other, scaffold the missing one (`bash scripts/new-agent.sh `, file-by-file no-op) then continue. Doesn't apply at plugin/APM scope — single file, no partial-pair state. ### Step 2 — Gather and group signals Read the current agent file(s). Collect all signals from the conversation. Group by **root cause**, not symptom. One root cause → one fix. ```text Example: - User feedback: agent keeps trying to push to remote - Session context: no scope boundary in system prompt → Root cause: system prompt lacks git scope constraint → fix: add explicit boundary ``` ### Step 3 — Announce planned changes Before editing, state which root causes were identified, what evidence supports each, and which files will change. Then proceed — edits are reversible via git. ### Step 4 — Apply changes Edit any file the signals point to. Generalize the fix — find the underlying gap, not the specific example that failed. For every sentence you add, ask: "Would the agent get this wrong without it?" A shorter, focused definition consistently outperforms an exhaustive one. For Copilot files, verify no Claude Code-only fields are introduced. For a plugin/APM-scope single file, verify no field beyond `name`, `description`, `model`, and `source_keys` is introduced. If the edit adds or removes research-sourced content, update `source_keys` in the edited file(s) and the corresponding entry in `sources.md` per Create flow's Step 4. ### Step 5 — Validate and close Re-run the validation checklist from the create flow's Step 5 on any edited file. At plugin/APM scope, apply a **patch bump** to the resolved package's `apm.yml` `version` (e.g. `1.0.4` → `1.0.5`). Invoke `kyberforge:agent-audit` on the edited file(s) to confirm no regressions — the pair at project/user scope, the single file at plugin/APM scope. **Commit verification.** Capture `git log --oneline -1` at the start of Step 1 and keep it. Once the audit is clean, run `git add` and `git commit` for the changed files — do not stop at staging. Then run `git log --oneline -1` again and confirm the hash changed from the one you captured at the start. A non-empty `git diff --stat` is not sufficient proof of completion: staged-but-uncommitted work isn't part of any commit and can be silently lost if the working tree is cleaned up before a commit lands. Only report the improvement as done once the hash has actually changed.