# How to Restrict Ponytail Injection to Specific Subagent Types

> Learn how to restrict Ponytail injection to specific subagent types using the PONYTAIL_SUBAGENT_MATCHER environment variable and regular expressions. Control your injections effectively.

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

---

**Set the `PONYTAIL_SUBAGENT_MATCHER` environment variable to a case-insensitive regular expression that matches the `agent_type` values you want to target.**

Ponytail automatically injects its ruleset into every subagent process by default. To limit this behavior to specific subagent types, the DietrichGebert/ponytail repository provides a filtering mechanism that inspects the subagent's reported identity before proceeding with injection.

## How Subagent Filtering Works

The injection logic resides in [`hooks/ponytail-subagent.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-subagent.js). This hook intercepts subagent initialization and conditionally injects rules based on the `PONYTAIL_SUBAGENT_MATCHER` environment variable.

### Reading the Matcher Configuration

At startup (lines 8-12 and 34-36), the hook checks for `process.env.PONYTAIL_SUBAGENT_MATCHER`. If present, it compiles the value into a **case-insensitive** regular expression. Invalid regex patterns are safely caught and treated as "no matcher" (lines 31-39), causing the hook to fall back to default behavior and inject into all subagents.

### Extracting agent_type from STDIN

The hook reads a JSON payload from **stdin** (lines 50-67) to extract the `agent_type` field reported by the subagent. The implementation accumulates data chunks from `data` events, parses the JSON, and extracts the type identifier to evaluate against your matcher.

### Conditional Injection Logic

If a matcher is defined and the extracted `agent_type` fails the regex test, the hook exits immediately without injecting the ruleset (line 68). All other scenarios—missing matcher, unparsable payload, or successful match—proceed to injection (lines 46-47, 70-71) by calling the `inject()` function defined at lines 23-30.

## Configuring PONYTAIL_SUBAGENT_MATCHER

Define the environment variable before launching Ponytail to control which subagent types receive the ruleset.

### Match Multiple Agent Types

To inject only into agents whose type contains "general" or "explore":

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

```

The hook will inject the ruleset only when the subagent reports an `agent_type` matching the regex, such as `"General-purpose"` or `"Explore"`.

### Require Exact Matches

To enforce an exact, case-insensitive match for the literal type "general":

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

```

The `^` and `$` anchors ensure only subagents whose `agent_type` is exactly `"general"` receive the injection.

### Restore Default Behavior

To disable filtering and inject into all subagents:

```bash
unset PONYTAIL_SUBAGENT_MATCHER
ponytail

```

When the variable is absent, the hook skips the matcher logic entirely, preserving Ponytail's original behavior of injecting every subagent.

### Programmatic Configuration in Node.js

When spawning subagents programmatically, set the variable in the environment object:

```javascript
const { spawn } = require('child_process');

process.env.PONYTAIL_SUBAGENT_MATCHER = 'assistant|coder';
const sub = spawn('node', ['my-subagent.js'], { env: process.env });

sub.stdout.pipe(process.stdout);
sub.stderr.pipe(process.stderr);

```

The environment variable propagates to the child process, and the hook conditionally injects based on the supplied regex.

## Safety Mechanisms and Error Handling

The implementation includes defensive programming to prevent hook failures from breaking subagent spawning.

### Invalid Regex Handling

If you provide a malformed regular expression in `PONYTAIL_SUBAGENT_MATCHER`, the hook catches the syntax error (lines 31-39) and treats the configuration as undefined. This prevents crashes and ensures subagents still launch, albeit with default injection behavior.

### Timeout Protection

A 1-second timeout (lines 77-78) guarantees the hook never hangs indefinitely while waiting for stdin input or processing the matcher. If the timeout expires, the process exits safely without blocking the subagent initialization.

## Summary

- **`PONYTAIL_SUBAGENT_MATCHER`** controls which subagent types receive Ponytail's ruleset via regex matching against the `agent_type` field.
- The filtering logic is implemented in [`hooks/ponytail-subagent.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-subagent.js) (lines 8-71), which reads the matcher from environment variables and validates subagent payloads from stdin.
- Matching is **case-insensitive** and occurs before the `inject()` function (lines 23-30) writes rules to the hook output.
- Invalid regex patterns trigger a fallback to default behavior (lines 31-39), ensuring subagents always launch even with misconfiguration.
- A 1-second timeout (lines 77-78) prevents the hook from hanging during stdin reads.

## Frequently Asked Questions

### What happens if the regex in PONYTAIL_SUBAGENT_MATCHER is invalid?

The hook wraps the regex compilation in a try-catch block (lines 31-39) according to the DietrichGebert/ponytail source code. Syntax errors are caught and treated as if no matcher was defined, causing the hook to fall back to injecting all subagents rather than crashing.

### Is the agent_type matching case-sensitive?

No. The `PONYTAIL_SUBAGENT_MATCHER` is compiled into a RegExp with the case-insensitive flag (lines 34-36). This means a pattern of `"general"` will match `"General"`, `"GENERAL"`, or `"general"` equally.

### Which subagents receive the injection if I don't set the environment variable?

All subagents receive the injection. When `PONYTAIL_SUBAGENT_MATCHER` is undefined, the hook skips the matcher validation logic (lines 46-47) and proceeds directly to `inject()` (lines 70-71), preserving Ponytail's default behavior of universal ruleset injection.

### Can I use complex regex features like anchors or character classes?

Yes. The hook passes the environment variable directly to the JavaScript `RegExp` constructor (lines 34-36), so any valid JavaScript regular expression syntax is supported. You can use anchors (`^`, `$`), alternation (`|`), character classes (`[a-z]`), and other standard features to define precise matching rules.