Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Agent Artifacts

Skills teach an agent a capability and rules constrain it; an agent artifact defines an agent itself — a named, delegatable assistant with its own system prompt, model, and tool access.

Every major AI client has grown such a definition format: Claude Code subagents, OpenCode agents, and Copilot CLI custom agents. All three read a Markdown file with YAML frontmatter whose body is the system prompt — but each with its own field names, its own directory, and its own quirks. Teams end up copy-pasting near-identical agent files between repositories and editing three variants by hand.

Grimoire treats an agent like any other artifact: author one canonical file, publish it once, and let grim install project it into each client’s native format — the same model that powers vendor-specific metadata for skills and rules.

The canonical format

An agent is a single .md file. Unlike a rule, the frontmatter is required — every client needs at least a description to route work to the agent:

# code-reviewer.md
---
name: code-reviewer
description: Reviews diffs for correctness, security, and style.
model: sonnet
tools: Read,Grep,Bash
metadata:
  summary: Multi-pass diff reviewer
  keywords: review,quality
  claude.memory: project
  opencode.mode: subagent
  opencode.temperature: "0.2"
---
You are a code reviewer. Analyze the diff and report specific,
actionable findings.

The body below the frontmatter is the agent’s system prompt and installs verbatim for every client.

Common fields

FieldRequiredTypeValidation
nameyesstringMust equal the file stem (code-reviewer.mdcode-reviewer); lowercase letters, digits, hyphens
descriptionyesstringFree text — when a client should delegate to this agent
modelnostringPassed through verbatim to each client; no alias translation
toolsnostringComma-separated tool list, projected into each client’s native shape
metadatanostring→string mapCatalog keys (summary, keywords) plus vendor-namespaced keys (<vendor>.<field>)

The name-equals-stem rule exists because OpenCode derives an agent’s identity from its filename; Grimoire enforces the rule for every client so the identity is consistent everywhere.

Everything a single vendor understands — Claude’s permissionMode, OpenCode’s temperature, Copilot’s tool restrictions — is authored as a <vendor>.<field> string key inside metadata. The full key tables live in the vendor metadata reference.

Override precedence

The common model and tools fields are defaults. When a vendor key lifts to the same native field, the vendor key wins for that vendor — silently, because the collision is the documented escape hatch:

model: sonnet
metadata:
  claude.model: opus                       # Claude installs model: opus
  opencode.model: anthropic/claude-sonnet-4-5  # OpenCode gets this instead of "sonnet"

This matters most for model: Claude Code reads aliases like sonnet, while OpenCode expects a provider/model-id string. Grimoire deliberately does not translate between the two — set opencode.model when the common value is not what OpenCode needs.

What each client receives

On install, grim projects the canonical file per client:

Canonical fieldClaude CodeOpenCodeCopilot CLI
namekeptdropped (filename is the identity)kept
descriptionkeptkeptkept
modelkeptkept (see precedence)dropped (no documented field)
toolskept (comma string)dropped (deprecated upstream)emitted as a YAML list
plain metadata / unknown keyskeptdroppeddropped
bodyverbatimverbatimverbatim
provenance commentnoneyesyes

The canonical format is Claude Code’s native subagent format, so a plain agent — one with no <vendor>.<field> metadata keys — installs for Claude byte-identical to the published file (generated: false). The OpenCode and Copilot files are always generated transforms and carry a provenance comment; editing them by hand is detected as drift, exactly like any generated file.

Install locations

Project scope:

ClientPath
Claude Code.claude/agents/<name>.md
OpenCode.opencode/agents/<name>.md
Copilot CLI.github/agents/<name>.md

Global scope (native user-level discovery directories, honoring each client’s directory-override variable — the same resolution as skill discovery):

ClientPathEnv override
Claude Code~/.claude/agents/<name>.md$CLAUDE_CONFIG_DIR/agents/
OpenCode~/.config/opencode/agents/<name>.md (XDG)$OPENCODE_CONFIG_DIR/agents/
Copilot CLI~/.copilot/agents/<name>.md$COPILOT_HOME/agents/

Unlike global rules, Copilot agents have a real user-level home — no inert-install warning applies.

Publishing

grim build and grim release need --kind agent for an agent file:

grim build ./code-reviewer.md --kind agent
grim release ./code-reviewer.md ghcr.io/acme/code-reviewer:1.0.0 --kind agent

The flag is required because a bare .md path is indistinguishable from a rule by shape — and rules accept arbitrary frontmatter, so guessing from content would silently flip kinds. When a file released as a rule carries both name and description, grim warns that it looks like an agent definition.

Publishing runs the same gate as skills and rules: every <vendor>.<field> metadata key is validated against the vendor registries, and an invalid literal (say claude.permission-mode: yolo) fails the release with exit 65 before anything reaches the registry. The artifact publishes with a com.grimoire.kind annotation of agent, so grim add infers the kind with no flag.

Catalog metadata (summary, keywords) is authored in the metadata map, like a skill — see catalog metadata.

Consuming

Agents ride the standard lifecycle. Declarations live in an [agents] table of grimoire.toml; the lock carries [[agent]] entries; and bundles accept agent members alongside skills and rules:

grim add ghcr.io/acme/code-reviewer:1     # kind inferred from com.grimoire.kind
grim install                               # projects into every selected client
grim status                                # shows the agent row
grim uninstall agent code-reviewer         # removes files + declaration

Limitations

  • Object-valued vendor fields cannot be authored: the metadata map is string-valued by the agentskills contract, so Claude’s mcpServers and hooks, OpenCode’s permission, and Copilot’s mcp-servers are not projectable. Add them by editing the installed file (Claude/Copilot) or the client’s own config.
  • No support directory. An agent packs to exactly one <name>.md; a sibling folder sharing the stem is ignored (unlike rules).
  • No model translation. The common model passes through verbatim; use opencode.model when the OpenCode side needs a provider/model-id value.