# How to Restrict Ponytail Rule Injection to Specific Subagent Types Using Regex

> Learn how to restrict Ponytail rule injection to specific subagent types using regex with the PONYTAIL_SUBAGENT_MATCHER environment variable. Filter subagents efficiently by agent_type.

- Repository: [DietrichGebert/ponytail](https://github.com/DietrichGebert/ponytail)
- Tags: how-to-guide
- Published: 2026-09-03

---

**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`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-subagent.js)

The sub-agent filtering logic resides entirely in [`hooks/ponytail-subagent.js`](https://github.com/DietrichGebert/ponytail/blob/main/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`:

```bash
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:

```bash
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:

```bash
export PONYTAIL_SUBAGENT_MATCHER="^(?!search$).*$"
export PONYTAIL_MODE=full

```

### Configuration via_dotenv Files

When using dotenv-style configuration:

```dotenv
PONYTAIL_MODE=full
PONYTAIL_SUBAGENT_MATCHER=explore|general

```

## Key Implementation Details

- **Case-insensitive matching**: The hook always compiles the pattern with the `i` flag, so `general` matches `General` or `GENERAL`.
- **Unanchored patterns**: Unless you include `^` and `$` anchors, the regex matches substrings anywhere in the `agent_type` string.
- **Fallback behavior**: If `PONYTAIL_SUBAGENT_MATCHER` is 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`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-subagent.js)**: Core hook implementing the regex matcher and injection logic.
- **[`hooks/ponytail-instructions.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-instructions.js)**: Generates the instruction set that gets conditionally injected.
- **[`hooks/ponytail-runtime.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-runtime.js)**: Handles mode detection (`readMode`) and hook output coordination.
- **[`hooks/qoder-hooks.json`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/qoder-hooks.json)**: Registers the sub-agent hook for the Qoder platform.

## Summary

- Set `PONYTAIL_SUBAGENT_MATCHER` to 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`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-subagent.js) (lines 34-36).
- The hook extracts `agent_type` from 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`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-subagent.js). Common values include `general`, `explore`, or plugin identifiers formatted as `plugin:name`.