How to Restrict Ponytail Rule Injection to Specific Subagent Types Using Regex
Configure the PONYTAIL_SUBAGENT_MATCHER environment variable with a JavaScript-compatible regular expression to filter which sub-agents receive the Ponytail ruleset based on their agent_type field.
Ponytail automatically propagates its ruleset to every sub-agent spawned during task execution, but you often need to limit this behavior to specific agent types. By leveraging the PONYTAIL_SUBAGENT_MATCHER environment variable in the DietrichGebert/ponytail repository, you can restrict Ponytail rule injection to specific subagent types using regex patterns. This selective injection prevents unnecessary overhead and ensures only relevant agents receive the Ponytail instructions.
The Regex Matching Mechanism in hooks/ponytail-subagent.js
The sub-agent filtering logic resides entirely in hooks/ponytail-subagent.js. When a sub-agent initializes, the hook executes a three-phase matching process before deciding whether to inject the ruleset.
Pattern Compilation (Lines 31-39)
The hook first checks for the PONYTAIL_SUBAGENT_MATCHER environment variable. If present, it compiles the value into a case-insensitive RegExp using the 'i' flag. If the pattern is invalid, the catch block treats it as if no matcher were set, preserving the default "inject-everything" behavior.
Agent Type Extraction (Lines 62-64)
The hook reads a JSON payload from stdin containing metadata passed by the parent process. It extracts the agent_type field from this payload, which typically contains identifiers like general, explore, or plugin:name.
Conditional Injection Logic (Lines 66-71)
If a valid matcher exists and the extracted agent_type does not match the regex, the hook exits immediately without injecting the ruleset. If the matcher passes, or if no matcher is configured, the hook calls inject() to write the Ponytail instructions to the sub-agent.
Configuration Examples for Common Filtering Scenarios
The matcher is unanchored and case-insensitive by default. Here are specific patterns for typical filtering needs.
Inject Only into the "general" Subagent
To restrict injection to sub-agents with the exact type general:
export PONYTAIL_SUBAGENT_MATCHER="^general$"
export PONYTAIL_MODE=full
Include Multiple Specific Types
Use the pipe character to match either explore or any plugin-style agent:
export PONYTAIL_SUBAGENT_MATCHER="explore|^plugin:"
export PONYTAIL_MODE=full
This matches explore, plugin:search, and plugin:doc.
Exclude a Specific Noisy Subagent
Use negative lookahead to inject into all agents except those matching a specific type:
export PONYTAIL_SUBAGENT_MATCHER="^(?!search$).*$"
export PONYTAIL_MODE=full
Configuration via_dotenv Files
When using dotenv-style configuration:
PONYTAIL_MODE=full
PONYTAIL_SUBAGENT_MATCHER=explore|general
Key Implementation Details
- Case-insensitive matching: The hook always compiles the pattern with the
iflag, sogeneralmatchesGeneralorGENERAL. - Unanchored patterns: Unless you include
^and$anchors, the regex matches substrings anywhere in theagent_typestring. - Fallback behavior: If
PONYTAIL_SUBAGENT_MATCHERis undefined or contains an invalid regex, the hook defaults to injecting the ruleset into every sub-agent (lines 45-48).
Related Source Files
The injection system spans several files in the repository:
hooks/ponytail-subagent.js: Core hook implementing the regex matcher and injection logic.hooks/ponytail-instructions.js: Generates the instruction set that gets conditionally injected.hooks/ponytail-runtime.js: Handles mode detection (readMode) and hook output coordination.hooks/qoder-hooks.json: Registers the sub-agent hook for the Qoder platform.
Summary
- Set
PONYTAIL_SUBAGENT_MATCHERto a regex string to enable filtering; omit it to inject into all sub-agents. - The regex is compiled case-insensitively in
hooks/ponytail-subagent.js(lines 34-36). - The hook extracts
agent_typefrom the stdin JSON payload (lines 62-64) and exits without injecting if the matcher fails (lines 66-69). - Invalid regex patterns fall back to the default inject-all behavior (lines 31-39).
- Use anchors (
^,$) for exact matches and the pipe operator (|) for multiple allowed types.
Frequently Asked Questions
What happens if my regex pattern is invalid?
If PONYTAIL_SUBAGENT_MATCHER contains an invalid regular expression, the hook catches the SyntaxError and falls back to the default behavior of injecting rules into every sub-agent (lines 31-39).
Is the regex matching case-sensitive?
No. The hook compiles the pattern with the case-insensitive flag (new RegExp(pattern, 'i')), so general matches General, GENERAL, or any other case variation.
Can I exclude specific sub-agent types instead of including them?
Yes. Since the matcher uses standard JavaScript RegExp syntax, you can use negative lookahead patterns like ^(?!search$).*$ to match all agent types except those exactly matching "search".
Where does the sub-agent type value come from?
The agent_type value is passed in the JSON payload from the parent process via stdin and extracted by the hook on lines 62-64 of hooks/ponytail-subagent.js. Common values include general, explore, or plugin identifiers formatted as plugin:name.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →