Custom agent definitions (.claude/agents/) are silently ignored for team agents
Summary
When a custom agent definition (.claude/agents/<name>.md) is used to spawn a team agent (via the Agent tool with team_name parameter), all frontmatter fields and the markdown body (system prompt) are silently ignored. Only model and agent_type (in SubagentStart/SubagentStop hooks) work correctly.
The same custom agent definitions work fully when spawned as pure subagents (without team_name).
Reproduction
- Create
.claude/agents/my-agent.md:
---
name: my-agent
description: Test agent with baked-in identity.
model: opus
hooks:
PreToolUse:
- matcher: ""
hooks:
- type: command
command: echo "hook fired"
skills:
- my-skill
disallowedTools: Write, Edit
---
# You are: My Agent
You have a specific identity and instructions baked in.
- Spawn as pure subagent (works correctly):
Agent(subagent_type="my-agent", prompt="What is your role?")
→ Agent receives the markdown body as system prompt, hooks fire, model is applied.
- Spawn as team agent (broken):
Agent(subagent_type="my-agent", team_name="my-team", name="team-agent" prompt="What is your role?")
→ Agent has NO custom system prompt. Only project-wide rules (.claude/rules/) and CLAUDE.md files are loaded. Agent cannot identify itself.
What is silently ignored for team agents
| Feature | Pure subagent | Team agent |
|---|---|---|
| System prompt (markdown body) | ✅ Works | ✅ Works |
| skills frontmatter | ✅ Works | ❌ Silently ignored (known: #29441 / #24780) |
| disallowedTools frontmatter | ✅ Works | ✅ Works |
| Frontmatter hooks | ✅ Works | ❌ Silently ignored |
| model frontmatter | ✅ Works | ✅ Works |
| agent_type in SubagentStart/Stop | ✅ Works | ✅ Works |
Impact
This makes custom agent definitions nearly useless for team-based workflows. Teams cannot:
- Bake role identity into agents (must use spawn prompt instead)
- Enforce tool restrictions via
disallowedTools - Attach lifecycle hooks to specific agent types
- Preload skills into team agents
The silent failure is particularly problematic — there are no warnings or errors. Users may believe their agent definitions are being applied when they are not.
Environment
- Claude Code version: 2.1.68
- Platform: macOS (Darwin 24.5.0, arm64)
- Agent teams enabled via
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1
Related issues
- #29441 / #24780:
skillsfield silently ignored for team agents (subset of this bug) - #14859: Feature request for agent hierarchy fields in all hook events
12 Comments
Found 2 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
Update: It seems like the system prompt and the disallowed tools work in 2.1.69. skills frontmatter and hooks still are broken.
Regression on v2.1.81 — system prompt still not loaded for team agents
The author's update mentioned system prompt working in v2.1.69, but on v2.1.81 (macOS Darwin 25.4.0, arm64) the system prompt body from custom agent
.mdfiles is still not injected for team agents.Reproduction
1. Plugin agent (plugin
agents/directory):Agent responds with only the generic Claude Code system prompt + CLAUDE.md sections. Zero content from
analyst-maker.mdbody (182 lines with specific etapas, output format, checklist).2. Project-level agent (
~/.claude/agents/):Created
~/.claude/agents/test-identity.md:Spawned as teammate → responded as generic agent, no mention of parrot/bananas/rules.
3. Minimal prompt test:
Even with a minimal prompt (just asking "who are you?"), the agent definition body is not loaded. This rules out the
systemPromptMode: "replace"hypothesis.What works vs what doesn't
| Feature | Status |
|---|---|
|
agentTypein config.json | ✅ Correctly set tocontent-maker:analyst-maker||
modelfrom frontmatter | ✅ Inherited (opusfrom frontmatter appears in config) ||
descriptionfrom frontmatter | ✅ Listed in system-reminder as available agent type || Body content (system prompt) | ❌ Not injected |
Evidence from transcript
The JSONL transcript (
~/.claude/projects/*/subagents/agent-*.jsonl) shows the first user message contains ONLY thepromptfield wrapped in<teammate-message>tags. No system message, no agent definition content. The agent's first response is purely generic.Source code trace
In the minified binary (v2.1.81), the
g4Rfunction (inProcessRunner) has the code path:This suggests the
agentDefinitionis eithernullorgetSystemPrompt()returns falsy when the teammate is spawned.Environment
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1~/.claude/agents/project-level agentsThis is a blocker for any workflow that relies on pre-built agent definitions with Agent Teams.
Generated with Claude Code
UP
I'm also experiencing this issue, which is frustrating...
As of v2.1.97 it's still not fixed.
---
Workaround: SubagentStart hook that injects agent definition into team agents
---
I've been hit by this too (both the system prompt regression and the skills issue). I built a
SubagentStarthook workaround that covers system prompt body and partially skills frontmatter for team agents. Sharing in case it helps others.Note: There's an additional undocumented issue -
additionalContextinjected viaSubagentStarthooks is not persisted across turns for team agents. The agent receives it on the first turn but loses it on subsequent turns. My workaround addresses this by re-injecting on every turn.Note2: In the leaked source files I noticed that for teammates the agent.type is replaced with agent name which may be why proper files are not loaded. This problem is also present in the hook input, which is why I had to resort to reading transcript files.
How it works
SubagentStarthook fires on every teammate turntranscript_pathfrom the hook input and scans the JSONL for the most recentAgenttool_use whereinput.nameorinput.subagent_typematches the hook'sagent_type- and whereinput.team_nameis set (teammates only; regular subagents work fine)input.subagent_typefrom the transcript to locate the correct.mdfile (sinceagent_typein the hook payload contains the agent's display name for teammates, not the qualifiedplugin:agenttype). Should work for plugins (official and custom), local agents, and user agents.skills:list from YAML frontmatter and generates a<LOAD-DEPENDENCY>block instructing the agent to load them<system-reminder>tags, and emits it asadditionalContextWhat it does NOT cover
<LOAD-DEPENDENCY>instruction tells the agent to proactively load its skills, but it's a hint - not a guarantee.hooksfrontmatter: the SubagentStart hook can only inject context, not register new hooks dynamically. Global hooks only.additionalContextis injected as context, not as the actual system prompt. Behavior is close enough for most agents but not identical.Key design decisions
Agenttool_use spawned this teammate. This is necessary becauseagent_typein the hook payload is the agent's display name (e.g.,"pr-opener"), not the qualified type (e.g.,"pull-request:pr-opener") needed to locate the.mdfile.additionalContextis not persisted across teammate turns - without re-injection the agent loses its definition after the first turn. I'm unsure whetherSubagentStartfiring on every teammate turn is intended behavior or a separate bug, but in my case it's actually saving me - without it, the workaround would only work on the first turn.team_nameis absent in the transcript tool_use, since regular subagents receive their definition correctly.Implementation
The hook is a single Python script (stdlib only) installed as a plugin.
hooks/hooks.jsonhooks/inject-agent-def(remeber to do chmod +x)Confirming still reproduces on v2.1.101 (macOS Darwin 24.6,
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1), four versions after @Koriit's v2.1.97 confirmation.Adding one data point to the silently-ignored-frontmatter list:
memory:. Declaringmemory: projectin a teammate's.claude/agents/*.mdhas no effect — the.claude/agent-memory/<agent-name>/MEMORY.mdfile is simply not loaded into the teammate's system prompt. For the same definition spawned as a pure (non-team) subagent on the same machine,memory:loads correctly. Extending the OP's table:| Feature | Pure subagent | Team agent |
|---|---|---|
|
memory:frontmatter | ✅ Works | ❌ Silently ignored (new) |I also want to independently confirm @Koriit's finding that hook-injected
additionalContextdoes not persist across turns for teammates. We hit the same quirk building a SubagentStart-hook workaround for this issue, and independently arrived at the same fix (re-inject on aStophook every turn). That two separate implementations converged on the same workaround is a strong signal it's real behavior, not an implementation artifact — worth surfacing as a first-class documented behavior or fixing.Longer-form context and a production use case is in my comment on the #24316 feature request thread. Happy to provide more reproduction detail if useful.
Closing for now — inactive for too long. Please open a new issue if this is still relevant.
Update from a fresh local POC on Claude Code 2.1.150:
I can no longer reproduce the full original issue. In my test, custom
.claude/agents/*.mddefinitions are now applied to teammate agents:memory: project: works for teammatesskills:frontmatter: works for teammatesmodel:frontmatter: works; my team lead ran Opus while the custom teammate ran SonnetThe remaining thing I can still reproduce is narrower: per-agent
hooks:frontmatter is ignored for teammate agents.Minimal setup:
The agent is asked to run
ReadonREADME.md.Observed behavior:
pure.hook-events.jsonlteam_name/name: teammate runsRead, but no hook event is writtenhooks:frontmatter, not custom-agent loading overallCorrected report from the POC:
So from my current test, #30703 appears mostly fixed in 2.1.150. The remaining actionable issue is that teammate agents silently ignore per-agent
hooks:frontmatter.@olarcher thanks for posting, I wouldn't notice otherwise. I also confirm your findings. 🙌
Cross-linking a related feature request I just filed: #67424 — proposes opt-in
AgentDefinition.projectDir/inheritProjectSettingsso subagent sessions can load the parent project's.claude/settings.jsonhooks. Confirmed unaddressed as of Claude Code v2.1.172 (v2.1.172's pre-warmed-worker settings-leak fix is a different mechanism). Referencing this thread because the May 2026 comment here documents the same per-agenthooks:frontmatter being ignored.Adding a data point on Claude Code 2.1.206 (2026-07-10): the
tools/disallowedToolsfrontmatter fields are still not enforced for teammate agents, even though (per the May update above on 2.1.150) body,memory,skills, andmodelnow apply. Note that the 2.1.150 test above didn't cover tool restrictions — so this may be a never-fixed remainder of the original report rather than a regression.Setup
Custom agent definition at
~/.claude/agents/code-reviewer.md(agent teams enabled viaCLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1):From a fresh session (started after the definition was last modified — ruling out the stale-registry effect where mid-session edits to
agents/*.mddon't reach new spawns), I spawned the same agent type two ways and asked each to (a) enumerate its available tools and (b) attempt exactly oneWriteto a scratch path and report the verbatim tool result.Results
| Spawn path | Tool surface reported by the agent | Write attempt | Restrictions enforced? |
|---|---|---|---|
| Teammate —
Agenttool with aname(team member) |Read, Bash, mcp__linear-server__get_issue, mcp__linear-server__list_comments, Write, Edit, SendMessage, TaskCreate, TaskGet, TaskList, TaskUpdate— i.e. the allowlist plus what looks like a baseline teammate toolset | Succeeded:"File created successfully at: <scratch path>"— file existence and content verified on disk by the parent session | ❌ No || One-shot subagent — same
subagent_type, noname|Read, Bash, mcp__linear-server__get_issue, mcp__linear-server__list_comments— exactly the allowlist | N/A — noWritetool present in its surface to attempt | ✅ Yes |So enforcement diverges by spawn path on the same definition in the same session: one-shot subagents get exactly the allowlist; teammates get the allowlist plus
Write,Edit,SendMessage, and theTask*tools regardless ofdisallowedTools.Why it matters
The agent-teams docs state the teammate "honors that definition's tools allowlist," and the natural use case is read-only roles (e.g. a code reviewer that can inspect but not modify). On the teammate path that read-only posture is currently convention-only — the agent has live
Write/Editcapability and nothing but its system prompt discouraging their use.Happy to provide the full probe transcripts if useful.