Skip to content

SubagentStart always sends the full SKILL.md — reuse the shipped condensed fallback for subagent workers #597

Description

@HetCreep

Request

Have SubagentStart send the plugin's own condensed instruction set (getFallbackInstructions) instead of the full mode-filtered SKILL.md (getPonytailInstructions's primary path), for whichever subagent types end up receiving the injection at all.

Why

hooks/ponytail-subagent.js:25 calls getPonytailInstructions(mode) unconditionally. That function (hooks/ponytail-instructions.js:86-90) reads the full skills/ponytail/SKILL.md, mode-filters it, and returns it — 5,229 characters (~1,300 tokens) for the default full mode, verified against current main (14a0d79). It only drops to the shorter getFallbackInstructions (hooks/ponytail-instructions.js:43-76, 2,680 characters / ~670 tokens) when the file read throws — an install error, never a deliberate choice.

That fallback already carries the operative rails — the ladder, the rules, the output format, the "when not to be lazy" boundaries — just without the intensity table and the worked examples, which mainly help a human/persistent-session reader compare lite vs. full vs. ultra. A subagent spawned via the Agent tool gets one task and no memory of the alternatives; it needs the rails, not the comparison. (#592 already keeps canonical vs. fallback content in sync, so this isn't proposing a stale text.)

Measured impact: a heavy Task/Agent-tool session (Claude Code, many subagents) commonly spawns 37–240 subagents; at the current per-spawn size that's roughly 48k–312k tokens of repeated, identical text, and a single 50-spawn swarm alone pays ~65k tokens. Switching matched subagents to the condensed set is close to a 49% cut on that — same rules, about half the tokens. (Reproduction: count SubagentStart fires × the injected payload length in any session with many Task/Agent spawns.)

This is separate from #506/#507/#522 (already shipped): PONYTAIL_SUBAGENT_MATCHER controls which agent types get the injection at all. This is about how much text the ones that do get it receive — complementary, not overlapping. See also #502.

Proposed options (any one solves it)

  1. Make getFallbackInstructions(mode) the default SubagentStart payload — hooks/ponytail-subagent.js:25 calls the already-exported getFallbackInstructions(mode) instead of getPonytailInstructions(mode). One line.
  2. Make it configurable, e.g. PONYTAIL_SUBAGENT_INSTRUCTIONS=full|condensed, for anyone who wants the full text in matched subagents.
  3. Combine with the existing matcher: matched agent types get the condensed set, unmatched get nothing — same opt-in shape as SubagentStart hook has no matcher — allow scoping the persona injection to specific agent types #506.

Context

Filed from a heavy Task/Agent-tool workflow where this showed up in a per-call overhead check — same shape of report as #506. Happy to send a PR for option 1 if that's the preferred direction.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions