# PONYTAIL_SUBAGENT_MATCHER: Configuring Selective Ruleset Injection in Ponytail

> Learn how to use PONYTAIL_SUBAGENT_MATCHER to control which sub-agents receive Ponytail rulesets via agent type matching. Configure selective injection effectively.

- Repository: [DietrichGebert/ponytail](https://github.com/DietrichGebert/ponytail)
- Tags: configuration-guide
- Published: 2026-09-13

---

**PONYTAIL_SUBAGENT_MATCHER is an environment variable that restricts Ponytail’s ruleset injection to only those sub-agents whose `agent_type` matches a specified regular expression.**

When using the Ponytail framework to orchestrate AI agents, you may need to limit which sub-agents receive the ruleset injection. This configuration option transforms the default universal injection behavior into an opt-in model based on regex pattern matching.

## What is PONYTAIL_SUBAGENT_MATCHER?

`PONYTAIL_SUBAGENT_MATCHER` controls the **scope of ruleset injection** during sub-agent initialization. By default, Ponytail injects its ruleset into every sub-agent launched via the *Agent* tool. Setting this environment variable makes the injection conditional—only sub-agents with an `agent_type` satisfying the regex pattern receive the ruleset.

The implementation resides in [`hooks/ponytail-subagent.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-subagent.js). At lines 34-36, the hook reads `process.env.PONYTAIL_SUBAGENT_MATCHER` and constructs a `RegExp` object. The hook then parses incoming JSON from stdin to extract `agent_type` and tests it against the compiled regex at lines 67-69. If the test passes, injection occurs at line 70; otherwise, the hook exits without modifying the sub-agent.

## Regex Semantics and Matching Behavior

The regex operates under two specific constraints:

- **Unanchored** – The pattern can match anywhere within the `agent_type` string unless you explicitly use `^` (start) and `$` (end) anchors.
- **Case-insensitive** – Matching ignores case differences.

For example, the pattern `"explore|general"` matches any agent type containing either substring, while `"^general$"` requires an exact match. Plugin agents follow the format `plugin:name`, making `"^plugin:"` an effective pattern for targeting all plugin-based sub-agents.

## Configuration Examples

### Target Specific Agent Types Exactly

To inject rules only into agents with the exact type `general`:

```bash
export PONYTAIL_SUBAGENT_MATCHER="^general$"

```

Only sub-agents whose `agent_type` property equals `general` will receive the Ponytail ruleset.

### Match Multiple Agent Patterns

To include both exploration and general-purpose agents while excluding others:

```bash
export PONYTAIL_SUBAGENT_MATCHER="explore|general"

```

This matches any `agent_type` containing either word, such as `general-assistant` or `explore-mode`.

### Target All Plugin Agents

Since plugin agents appear as `plugin:identifier`, target them collectively with:

```bash
export PONYTAIL_SUBAGENT_MATCHER="^plugin:"

```

This pattern matches `plugin:mytool`, `plugin:search`, and any other plugin-prefixed type.

### Restore Default Behavior (Inject All)

To disable scoping and inject into every sub-agent (the default when unset):

```bash
unset PONYTAIL_SUBAGENT_MATCHER

```

Alternatively, simply ensure the variable is not defined in your environment.

## Implementation Details and Error Handling

According to the source code in [`hooks/ponytail-subagent.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-subagent.js), the matching logic follows a **fail-safe** strategy. If you provide an invalid regex or if the sub-agent lacks an `agent_type` field, the hook falls back to injecting the ruleset rather than skipping it. This ensures that configuration errors do not silently disable intended guidance.

The README.md at lines 288-289 documents this option and provides additional context for users configuring their environment. For validation, the test suite in [`tests/hooks.test.js`](https://github.com/DietrichGebert/ponytail/blob/main/tests/hooks.test.js) verifies the matcher behavior using patterns like `'general|plan'` and `'^general$'`, confirming that the regex correctly filters sub-agent types under various scenarios.

## Summary

- **PONYTAIL_SUBAGENT_MATCHER** filters ruleset injection using regex pattern matching against `agent_type`.
- The regex is **unanchored and case-insensitive** by default; use `^` and `$` for exact matches.
- **Default behavior** (variable unset) injects rulesets into all sub-agents.
- **Error handling** defaults to injection rather than skipping if the regex is invalid or `agent_type` is missing.
- Plugin agents use the `plugin:name` format, targetable with patterns like `^plugin:`.

## Frequently Asked Questions

### What happens if PONYTAIL_SUBAGENT_MATCHER is not set?

When the environment variable is unset, Ponytail injects its ruleset into **every** sub-agent unconditionally. This is the default behavior designed for maximum compatibility.

### Is the regex case-sensitive?

No. The regex is **case-insensitive**. A pattern like `"general"` will match `General`, `GENERAL`, or any case variation of the word.

### What happens if I provide an invalid regex?

If the regex is malformed or invalid, the hook **falls back to injecting** the ruleset rather than skipping the sub-agent. This safety mechanism ensures that typos in your pattern do not accidentally disable Ponytail's guidance.

### How do I target only plugin agents?

Use the pattern `"^plugin:"` as the value for `PONYTAIL_SUBAGENT_MATCHER`. Since plugin agents report their type as `plugin:specificname`, this pattern matches all plugins while excluding native agent types.