#89's grilling session surfaced a real upstream gap: APM's agent primitive has no per-target compile integrator, so tools: and every Claude-only field (isolation, maxTurns, effort, memory, permissionMode) would verbatim-copy into Copilot's file with an incompatible or unrecognized shape. Omitting them entirely is the only option that never ships a wrong value to a real harness. Scoped to plugin-scope agent-author only — project/user scope keep today's Claude+Copilot pair model unchanged. Partially supersedes ADR-0005 and ADR-0008's plugin-scope clauses (addenda appended to both); ADR-0009's field-inventory.md mechanism is unaffected, only its plugin-scope content shape changes. Refs: #89
3.2 KiB
agent-author generates both provider files from a single root input
agent-author is the skill that creates Claude Code and GitHub Copilot CLI agent
definition files. Both providers are always targeted: Claude Code produces a .md
file; Copilot CLI produces a .agent.md file. The scaffold script new-agent.sh
accepts a single root directory and derives both destination paths by convention
rather than requiring the caller to supply two explicit paths. Scope is detected
from the root: a directory containing plugin.json is plugin scope (both files
land in <root>/agents/); a directory with .git but no plugin.json is project
scope (.claude/agents/<name>.md + .github/agents/<name>.agent.md); ~ is user
scope (~/.claude/agents/<name>.md + ~/.copilot/agents/<name>.agent.md).
Considered options
Two explicit destination paths (rejected) — new-agent.sh <name> <claude-dest> <copilot-dest> accepts a separate path per provider. Rejected because it breaks
the minimal-input principle that guides the entire skill: the caller must now know
and supply two provider-specific paths, which is exactly the convention knowledge
the script is meant to encapsulate. Every invocation becomes more error-prone and
harder to drive from a skill body without user interaction.
Plugin-only dual generation (rejected) — generate both files only at plugin scope; at project/user scope generate a single file with the provider inferred from the destination path. Rejected because it is an artificial asymmetry: the reason to author for both providers does not disappear outside a plugin context. It would force users to run the skill twice per agent at project/user scope or build a separate single-provider skill, adding complexity with no benefit.
Consequences
.github/agents/is the locked-in Copilot CLI convention at project scope. Non-standard paths (e.g..copilot/agents/) are not supported without an explicit override flag — deferred to a follow-on issue.- The script interface
new-agent.sh <name> <root>is a stable public contract. Changing to a two-destination form is a breaking change to any caller. - At plugin scope, both files share a single
agents/sources.mdfor provenance. At project/user scope, no sources file is generated — ad-hoc authoring outside a research-driven workflow has no provenance chain to record. - The file-by-file no-op in the script (skip existing files rather than overwriting) means partial state — one provider file exists, the other does not — is handled by routing in the skill body, not in the script.
Update (ADR-0010): the agents/sources.md path above is superseded. The provenance
file now lives at <plugin-root>/sources.md, outside the agents/ directory, because
claude plugin validate --strict auto-discovers every .md under agents/ as an agent
requiring frontmatter. See ADR-0010 for the empirical finding and rationale.
Update (ADR-0016): the plugin-scope clause above is superseded. Plugin scope is no longer
detected via plugin.json, and no longer produces a Claude+Copilot file pair — a directory
containing apm.yml now gets a single vendor-neutral .apm/agents/<name>.agent.md file with
no provider-specific fields. Project scope and user scope are unaffected. See ADR-0016.