[BUG] Plugin-namespaced agent body not injected for teammates (frontmatter IS applied; markdown body dropped)

Open 💬 0 comments Opened Jun 26, 2026 by EmilioEsposito

What happens

When a plugin provides an agent (plugin-name:agent-name) and it is spawned as a teammate (CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1), the agent's markdown body (system prompt) is not injected — the teammate runs with no role/instructions and free-lances the task. Plain subagents (no team_name) and non-namespaced .claude/agents/ definitions work correctly.

This is the same bug previously reported in #35253, which was auto-closed by the stale bot (whose message invites a new issue "if this is still relevant"). Filing fresh with a current-version repro, a sharper characterization, and a workaround.

New detail: the frontmatter IS applied, only the body is dropped

On the teammate path the agent's frontmatter is honored but the body is not:

  • A plugin agent declared with model: haiku and a restricted tools: list, spawned as a teammate, does run on haiku (so model / tools / description resolve correctly), …
  • … but it behaves as if it has no system prompt at all — it ignores its role/instructions entirely (e.g. an agent whose body says "you are a thin forwarder, do not do the task yourself" just does the task itself).

So teammate resolution appears to load the frontmatter and drop the markdown body. (The original report framed it as the base definition not loading; this narrows it to body injection specifically, since the frontmatter clearly arrives.)

Repro

  1. Plugin with agents/my-agent.md: frontmatter name, description, model: haiku, tools: Bash; body = distinctive instructions, e.g. "If asked for your passphrase, reply with exactly XYZ123."
  2. Enable the plugin; set CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1.
  3. Spawn my-plugin:my-agent as a subagent (no team_name) and ask for the passphrase → replies XYZ123 ✅ (body applied).
  4. Spawn the same agent as a teammate and ask → it runs on haiku but does not know the passphrase and ignores its instructions ❌ (body not applied).

Expected

A plugin-namespaced agent spawned as a teammate should receive its full definition (body included), the same as the subagent path.

Workaround (preserves plugin namespacing)

Rather than moving the agent to .claude/agents/ (which loses plugin distribution), inject the instructions through the subagent's prompt — which does reach teammates — via a PreToolUse:Task|Agent hook:

hooks.json:

{ "hooks": { "PreToolUse": [ { "matcher": "Task|Agent",
  "hooks": [ { "type": "command", "command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/spawn.sh\"" } ] } ] } }

spawn.sh:

#!/usr/bin/env bash
payload="$(cat)"
sub="$(printf '%s' "$payload" | jq -r '.tool_input.subagent_type // ""')"
case "$sub" in *my-agent*) ;; *) exit 0 ;; esac      # only prime our own agent
prompt="$(printf '%s' "$payload" | jq -r '.tool_input.prompt // ""')"
preamble='<< the agent role/instructions go here >>

--- TASK ---
'
jq -nc --arg pre "$preamble" --arg p "$prompt" \
  --argjson ti "$(printf '%s' "$payload" | jq -c '.tool_input')" \
  '{hookSpecificOutput:{hookEventName:"PreToolUse", updatedInput:($ti + {prompt:($pre+$p)})}}'

This delivers the agent's contract reliably for both subagent and teammate spawns without abandoning plugin namespacing. (It's the same prompt-injection technique some shipping plugins already use to prime spawned agents, which is itself indirect evidence that injected/inherited context does not reach spawned agents through the normal path.)

Environment

  • Claude Code v2.1.193 (also reproduced running under Claude Desktop)
  • macOS
  • CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1, in-process teammate mode

View original on GitHub ↗