Agent Creator

Caution

Agents with vague descriptions trigger on the wrong requests — or never trigger at all. A bad description means Claude picks the wrong agent, spams irrelevant ones, or silently falls back to the main conversation. Most hand-written agents also leak CLAUDE.md rules into the body (already injected) or forget the Triggers: keyword list that drives auto-selection.

Tip

Describe what you want — the agent handles the rest. It runs parallel analysis of your codebase, drafts the frontmatter and system prompt, validates against Anthropic best practices, then optimizes with brewtools:text-optimize. Improvement and debugging of existing agents follow the same flow.

Quick reference

FieldValue
Triggers”create agent”, “improve agent”, “scaffold agent”
Modelinherit — runs on the session’s model
ToolsRead, Write, Edit, Glob, Grep, Bash, Agent, WebFetch, WebSearch

Scope guard

Agent Creator sizes the task before starting. One bounded unit = one deliverable, roughly 5 files, roughly 10 steps.

SituationWhat the agent does
Brief fits one bounded unitStarts immediately
Brief exceeds ~5 files / ~10 steps, or bundles several independent deliverablesStops before starting, returns a split proposal: 2-N bounded subtasks, each with scope and a suggested owner
Scope grows mid-flightStops at the next clean boundary, reports done / remaining / how to split
Brief is missing GOAL, SCOPE, CONTEXT, CONSUMER or acceptanceStates the assumption explicitly in the report, or asks once — never invents scope

“Create six agents for my team” gets a split proposal — one agent per subtask. The same rule that agent-creator applies to itself is the one it writes into every agent it generates.

Tip

Got a split proposal instead of an agent file? That is the guard working. Pick one agent from the proposal and re-send it, or spawn the subtasks as parallel agents in a single message.

Guardrails in every generated agent

Two blocks land in the body of every agent Agent Creator writes. They are part of the output contract, not advice. One of them is also called Return Contract — a separate thing from Agent Creator’s own return contract described later on this page: this one is what a generated agent hands back, that one is what Agent Creator itself hands back.

GuardrailApplies toWhat it says
Return ContractEvery generated agent, unconditionallyVerdict first, <=30 lines, path:line. !=bodies/output/log/preamble. Unconditional — spend one step on what the MAIN SESSION needs and return only that. Bulk material — long logs, full diffs, dumps, long reports — goes into a file under .claude/reports/<YYYYMMDD-HHMMSS>_<name>/, and only the PATH comes back. Agents that dump everything burn the main session’s context. If the agent-return guard is installed, a return over ~1000 est-tokens (chars/4) is blocked for compression; over <=2500 it must file the detail and answer with path + verdict + <=3 lines.
Scope FitOnly agents whose domain writes code, scripts, SQL, schemas, infra or configBuild for the actual scale and the problems that exist today, not imagined load or speculative abstraction — a 10-user app does not need hardening against DB lock contention. After finishing, one pass: can this be simpler — fewer files, less config, less indirection?

Scope Fit is dropped for research, docs, and review-only agents; Return Contract never is. Both are validation-checklist items, so an agent missing the Return Contract block does not pass. Agent Creator applies Return Contract to itself: its report is agent paths plus a frontmatter / validation verdict, never the full agent bodies.

When to use

  • New agent — you need a specialized subagent (reviewer, code-generator, security-scanner, etc.)
  • Agent not triggering — the agent exists but Claude doesn’t auto-select it reliably
  • Trigger collisions — two agents compete for the same request; need <commentary> disambiguation
  • System prompt quality — existing agent body is vague prose instead of dense tables + checklists
  • Post-update drift — agent worked before but a plugin update changed naming or available tools

Examples

"Create an agent for code review — reads only, outputs severity table"
"My reviewer agent doesn't trigger when I say 'check this PR'"
"Improve the description of my tester agent, it keeps clashing with developer"
# Natural language triggers — all route to agent-creator
"new agent for security scanning"
"agent isn't picking up my requests"
"fix agent description"

Flow

  1. Clarify intent

    Asks 2-3 targeted questions: desired role, allowed tools, model tier (fable / opus / sonnet / haiku). For improvement requests, reads the existing agent file first.

  2. Parallel analysis

    Launches multiple Explore subagents concurrently — codebase conventions, existing agents in scope, CLAUDE.md rules, stack details. Results are merged before writing.

  3. Synthesize

    Extracts project-specific patterns, naming conventions, and anti-patterns. Determines description format: single-line, with Triggers: list, or multi-line with <example> blocks (for ambiguous agents only).

  4. Write

    Produces a complete .md file: frontmatter with all required and relevant optional fields, then a system prompt structured as Role → Context → Patterns → Commands → Checklist. Every generated agent also gets a maxTurns sized to its role plus a checkpointing instruction, so an abort stays recoverable.

  5. Validate

    Checks name format ([a-z0-9-]+), description keyword density, tool minimality (least privilege), no duplicated CLAUDE.md rules in body, unique name in scope, the Return Contract block present, and Scope Fit present exactly when the agent writes code.

  6. Optimize

    Runs brewtools:text-optimize on the output — converts prose to tables, removes filler, trims to dense LLM-readable format (~30% token savings typical).

Frontmatter reference — all fields
---
name: agent-name              # REQ: lowercase-hyphens; no leading `-`, no `:` (reserved for plugin namespacing)
description: "..."            # REQ: action verb + Triggers: keyword list
model: sonnet                 # OPT: fable|opus|sonnet|haiku|inherit  (fable=claude-fable-5, Mythos-class, CC 2.1.170+)
effort: high                  # OPT: low|medium|high|xhigh|max (no auto, no bare integer)
maxTurns: 20                  # OPT: integer, max turns before abort
tools: Read, Glob, Grep       # OPT: omit = inherit all
disallowedTools: Write, Edit  # OPT: explicit deny list
skills: skill1, skill2        # OPT: full content injected into context at startup
color: cyan                   # OPT: 8 valid values -- magenta is NOT one
memory: project               # OPT: user|project|local -- auto-adds Read/Write/Edit
background: true              # OPT: true keeps it backgrounded even when Claude wants the result (DEF unset, no `false` switch)
isolation: worktree           # OPT: FM accepts `worktree` only -- LOW PRIORITY, see below (`remote` is invocation-level, never FM)
permissionMode: default       # OPT: LOCAL-ONLY -- ignored + warn in plugin agents
mcpServers: [server1]         # OPT: LOCAL-ONLY -- ignored + warn in plugin agents
initialPrompt: "..."          # OPT: LOCAL-ONLY -- first prompt sent on start
observer: "reviewer"          # OPT: LOCAL-ONLY -- observing agent
observerMessage: "watch for X"  # OPT: LOCAL-ONLY -- brief for observer
observeSubagents: false       # OPT: LOCAL-ONLY -- `false` disables observation
---

Scope — verified against CC 2.1.233 (two separate parsers: local .claude/agents/ and plugin <plugin>/agents/**.md):

ScopeFields
Local + plugin — both parsers honor itmodel, effort, maxTurns, tools, disallowedTools, skills, color, memory, background, isolation: worktree, initialPrompt
Local only — ignored for plugin agentspermissionMode, hooks, mcpServers (exactly these three)
Absent from the 2.1.233 field table — treat as internal/older, do not emit into a generated agentobserver, observerMessage, observeSubagents

initialPrompt auto-submits as the first user turn only when this exact definition runs as the MAIN session (--agent <name> or the agent setting) — irrelevant on an ordinary subagent spawn, but honored for plugin agents too since origin isn’t the boundary, execution context is. Need permissionMode/hooks/mcpServers? Move the agent to .claude/agents/ — plugin agents ignore these three no matter how the frontmatter is written. isolation: remote is never a valid FM value anywhere — it is invocation-level only, reachable from an Agent(...) tool call.

Caution

isolation is low priority — don’t set it by default. Every spawn with isolation: worktree costs a git worktree setup plus disk, and there’s a known data-loss bug when it’s combined with permissionMode: bypassPermissions (#29110). Use it only when several agents write to the same files concurrently.

Caution

Do not set permissionMode: bypassPermissions by default. This is equivalent to running with --dangerously-skip-permissions — it silently skips all safety prompts. Only use it for fully-sandboxed CI environments where there is no interactive user. For local development, prefer permissionMode: default or permissionMode: acceptEdits. Also note: permissionMode is local-only — plugin agents ignore it entirely.

Description patterns by ambiguity level:

OverlapFormatExample
None — unique domainSingle-line action + Triggers"Implements features, fixes bugs. Triggers: implement, fix bug, add feature"
Some — 1-2 other agentsSingle-line + detailed Triggers"Creates bash scripts. Triggers: create script, bash script, shell script"
High — creator/meta agentsMulti-line + 2-3 <example> blocksSee agent-creator.md source

Subagent spawn note: CC allows nested subagent spawning, but prefer spawning from the main conversation so the orchestrator can integrate each agent’s result directly. Brewcode agents are stateless and resolve plugin paths via ${CLAUDE_PLUGIN_ROOT}.

Known active bugs: #29423 (subagents skip CLAUDE.md), #27736 (skills: in plugin agents), #31392 (global agents not discovered in v2.1.70+).

Subagent resource limits — turns, timeouts, checkpointing

Caution

There is no wall-clock timeout for a subagent. Not in frontmatter, not in settings.json, not as an environment variable. A subagent is bounded by turns, API-call timeouts, and token caps only. An agent stuck inside a single 25-minute Bash call is one turn — maxTurns will not touch it.

A turn = one model inference plus its tool calls; tool results return, then the next turn begins. Parallel tool calls in one assistant message count as ONE turn, so turns are usually fewer than tool calls. Observed in real transcripts from this repo: 12 turns / 19 tool calls, 21 / 33, 40 / 53, 51 / 55.

maxTurns sized by role — every generated agent gets an explicit value:

RolemaxTurns
explorer / quick search40
reviewer / architect / tester60
docs / generator80
developer / orchestrator120

Calibrated against real subagent transcripts (.claude/projects/*/subagents/agent-*.jsonl), not invented. At roughly 10-20 seconds per turn, 120 turns is a 20-30 minute ceiling. Rule of thumb: maxTurns ≈ 2-3x the role’s typical run.

maxTurns is an emergency anti-loop stop, not a budget. On exhaustion the binary emits Reached max turns limit (N) and the agent aborts — written files persist, but the final report is lost. That is why agent-creator also writes a checkpointing instruction into every generated agent body: record incremental progress to a report file after each milestone, and on resume read that file first and continue from the last checkpoint.

Relevant environment variables (set under env in settings.json):

VariableBoundsDefault
CLAUDE_CODE_MAX_TURNSTurn cap for ALL agents globallyunset
API_TIMEOUT_MSA single API call10 min
CLAUDE_ASYNC_AGENT_STALL_TIMEOUT_MSBackground-agent stall; resets on streaming10 min
CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTSConcurrent subagents20
CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTHSubagent nesting depth below main; 1 turns nesting off — verify the live cap, don’t hardcode a number3
CLAUDE_CODE_MAX_OUTPUT_TOKENSOutput tokens per responsemodel max
MAX_MCP_OUTPUT_TOKENSMCP result size25k
BASH_DEFAULT_TIMEOUT_MS / BASH_MAX_TIMEOUT_MSBash tool only120s / 600s

Tip

No total-per-session spawn cap exists. CLAUDE_CODE_MAX_SUBAGENTS_PER_SESSION (default 200, added in 2.1.212) was removed in 2.1.224 — concurrency and nesting depth are the only live spawn limits now.

Time-based control is only reachable through PreToolUse, which fires inside the subagent loop and carries agent_id and agent_type: warn at 80% of the budget, deny non-Write tools at 100%. SubagentStart and SubagentStop fire in the MAIN session, not inside the agent. No timer hook exists.

Recovering a partial result:

Path / toolUse
.claude/projects/{project}/{sessionId}/subagents/agent-{agentId}.jsonlFull subagent transcript (retention: cleanupPeriodDays)
run_in_background: true + TaskOutputRead partial output while it runs — from the MAIN session only; TaskOutput is filtered out of every subagent
TaskStopKill a running subagent
SendMessageResume a stopped subagent with context intact

Return Contract

Verdict first, <=30 lines, path:line. No agent bodies, no pasted frontmatter, no analysis transcripts, no preamble. Per generated agent: file path, one-line role, model/maxTurns/tools on one line, validation verdict (pass, or the failing checklist item), text-optimizer run or skipped, and any assumption made about the brief. Longer material — analysis notes, generated bodies, full validation runs — goes to .claude/reports/<YYYYMMDD-HHMMSS>_agent-creator/; only the path comes back.

This is the same discipline Agent Creator bakes into every generated agent — see the Return Contract row in the Guardrails table above, a separate contract from this one. /brewtools:agent-return-setup enforces this at ~1000 / ~2500 est-tokens when installed; the contract itself ships unconditionally.

🧩

Skill Creator

Same design process for skills instead of agents.

Agent Deadline

Installs soft-deadline hooks for subagent runs — the practical continuation of the resource-limits section above.

🔗

GitHub source

Full frontmatter reference, description patterns, and system prompt templates.

🚀

Brewcode overview

All brewcode agents, skills, and hooks in one place.

Updating plugins

Use /brewtools:plugin-update to check and update the brewcode plugin suite in one command. See the FAQ for details.