#8022: feat: implement before_model_select plugin hook
stale
Cluster:
Plugin and Hook Enhancements
## Summary
Implements the `before_model_select` plugin hook that allows plugins to intercept and modify model selection before it's finalized. This enables intelligent routing based on prompt content (e.g., local Ollama classification for model routing).
## Changes
- **Types** (`src/plugins/types.ts`):
- Added `PluginHookBeforeModelSelectEvent` type with `provider`, `model`, `sessionKey`, `allowedModelKeys`, `prompt`
- Added `PluginHookBeforeModelSelectResult` type with optional `provider` and `model`
- Added `"before_model_select"` to `PluginHookName` union
- Added handler signature to `PluginHookHandlerMap`
- **Hook Runner** (`src/plugins/hooks.ts`):
- Added `runBeforeModelSelect()` function using `runModifyingHook` pattern
- Merges results from multiple handlers (last non-undefined wins for each field)
- Re-exports new types for consumers
- **Integration** (`src/auto-reply/reply/model-selection.ts`):
- Added `prompt?: string` parameter to `createModelSelectionState`
- Hook is called after stored override resolution
- Hook results are validated against allowlist (strict enforcement)
- Backward compatible - no change when no plugins registered
## Test Coverage
- 8 tests for hook runner (`src/plugins/hooks.before-model-select.test.ts`)
- 8 tests for integration (`src/auto-reply/reply/model-selection.before-model-select.test.ts`)
## Hook Behavior
- **Type**: Modifying (sequential execution, result merging)
- **Event Data**: `{ provider, model, sessionKey?, allowedModelKeys, prompt? }`
- **Result**: `{ provider?, model? }` - partial results allowed
- **Allowlist**: Strict - hook results validated against `allowedModelKeys`
- **Priority**: Higher priority handlers execute first
## Use Case
Enables plugins to implement intelligent model routing:
```typescript
hooks: [{
hookName: "before_model_select",
handler: async (event, ctx) => {
// Classify prompt with local Ollama
const category = await classifyPrompt(event.prompt);
// Route to appropriate model
return category === "code"
? { provider: "anthropic", model: "claude-sonnet-4-20250514" }
: { provider: "openai", model: "gpt-4o-mini" };
}
}]
```
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
Adds a new plugin lifecycle hook, `before_model_select`, allowing plugins to intercept and modify the resolved provider/model before it’s finalized. This includes:
- New hook event/result types and registration signature in `src/plugins/types.ts`.
- Hook runner support via `createHookRunner().runBeforeModelSelect()` in `src/plugins/hooks.ts`, using the existing sequential “modifying hook” pattern.
- Integration into model selection (`src/auto-reply/reply/model-selection.ts`), passing `{ provider, model, sessionKey, allowedModelKeys, prompt? }` and enforcing that hook-provided selections must be allowlisted.
- Focused unit tests for both the hook runner and the model-selection integration.
<h3>Confidence Score: 4/5</h3>
- This PR looks safe to merge; changes are localized and well-tested, with only minor semantic clarifications recommended.
- The new hook is implemented using existing hook-runner patterns and is covered by targeted tests. Main concerns are around potentially confusing precedence semantics (priority vs last-wins) and provider-only hook results being silently ignored in some cases, which are correctness/UX for plugin authors rather than core runtime stability issues.
- src/auto-reply/reply/model-selection.ts; src/plugins/hooks.ts
<!-- greptile_other_comments_section -->
<sub>(4/5) You can add custom instructions or style guidelines for the agent [here](https://app.greptile.com/review/github)!</sub>
**Context used:**
- Context from `dashboard` - CLAUDE.md ([source](https://app.greptile.com/review/custom-context?memory=fd949e91-5c3a-4ab5-90a1-cbe184fd6ce8))
- Context from `dashboard` - AGENTS.md ([source](https://app.greptile.com/review/custom-context?memory=0d0c8278-ef8e-4d6c-ab21-f5527e322f13))
<!-- /greptile_comment -->
Most Similar PRs
#14647: feat(plugins): allow before_agent_start hook to override model (#14...
by lailoo · 2026-02-12
86.2%
#17614: feat: allow before_agent_start hook to override model selection
by plc · 2026-02-16
85.6%
#22624: feat(plugins): add before_context_send hook and model routing via b...
by davidrudduck · 2026-02-21
83.3%
#11155: feat(hooks): before_agent_start model/provider override (run-scoped...
by alanranger · 2026-02-07
83.1%
#14873: [Feature]: Extend before_agent_start hook context with Model, Tools...
by akv2011 · 2026-02-12
82.4%
#23559: feat(plugins): add before_context_send hook and model routing via b...
by davidrudduck · 2026-02-22
81.4%
#8178: feat: allow before_agent_start to override the prompt
by richardfogaca · 2026-02-03
81.3%
#6017: feat(hooks): add systemPrompt and tools to before_agent_start event
by yajatns · 2026-02-01
78.7%
#11124: feat(plugins): add before_llm_request hook for custom LLM headers
by johnlanni · 2026-02-07
78.2%
#14544: feat: add before_context_send plugin hook
by Windelly · 2026-02-12
78.2%