Add SubagentStart hook (#22782)

# What

`SubagentStart` runs once when Codex creates a thread-spawned subagent,
before that child sends its first model request. Thread-spawned
subagents use `SubagentStart` instead of the normal root-agent
`SessionStart` hook.

Configured handlers match on the subagent `agent_type`, using the same
value passed to `spawn_agent`. When no agent type is specified, Codex
uses the default agent type.

Hook input includes the normal session-start fields plus:

- `agent_id`: the child thread id.
- `agent_type`: the resolved subagent type.

`SubagentStart` may return `hookSpecificOutput.additionalContext`. That
context is added to the child conversation before the first model
request.

# Lifecycle Scope

Only thread-spawned subagents run `SubagentStart`.

Internal/system subagents such as Review, Compact, MemoryConsolidation,
and Other do not run normal `SessionStart` hooks and do not run
`SubagentStart`. This avoids exposing synthetic matcher labels for
internal implementation paths.

Also the `SessionStart` hook no longer fires for subagents, this matches
behavior with other coding agents' implementation

# Stack

1. This PR: add `SubagentStart`.
2. #22873: add `SubagentStop`.
3. #22882: add subagent identity to normal hook inputs.
This commit is contained in:
Abhinav
2026-05-19 12:45:08 -07:00
committed by GitHub
parent d269aa2af9
commit d661ab70ed
43 changed files with 716 additions and 44 deletions
@@ -1740,6 +1740,7 @@
"postCompact",
"sessionStart",
"userPromptSubmit",
"subagentStart",
"stop"
],
"type": "string"
@@ -9624,6 +9624,7 @@
"postCompact",
"sessionStart",
"userPromptSubmit",
"subagentStart",
"stop"
],
"type": "string"
@@ -10514,6 +10515,12 @@
},
"type": "array"
},
"SubagentStart": {
"items": {
"$ref": "#/definitions/v2/ConfiguredHookMatcherGroup"
},
"type": "array"
},
"UserPromptSubmit": {
"items": {
"$ref": "#/definitions/v2/ConfiguredHookMatcherGroup"
@@ -10541,6 +10548,7 @@
"PreToolUse",
"SessionStart",
"Stop",
"SubagentStart",
"UserPromptSubmit"
],
"type": "object"
@@ -6124,6 +6124,7 @@
"postCompact",
"sessionStart",
"userPromptSubmit",
"subagentStart",
"stop"
],
"type": "string"
@@ -7063,6 +7064,12 @@
},
"type": "array"
},
"SubagentStart": {
"items": {
"$ref": "#/definitions/ConfiguredHookMatcherGroup"
},
"type": "array"
},
"UserPromptSubmit": {
"items": {
"$ref": "#/definitions/ConfiguredHookMatcherGroup"
@@ -7090,6 +7097,7 @@
"PreToolUse",
"SessionStart",
"Stop",
"SubagentStart",
"UserPromptSubmit"
],
"type": "object"
@@ -261,6 +261,12 @@
},
"type": "array"
},
"SubagentStart": {
"items": {
"$ref": "#/definitions/ConfiguredHookMatcherGroup"
},
"type": "array"
},
"UserPromptSubmit": {
"items": {
"$ref": "#/definitions/ConfiguredHookMatcherGroup"
@@ -288,6 +294,7 @@
"PreToolUse",
"SessionStart",
"Stop",
"SubagentStart",
"UserPromptSubmit"
],
"type": "object"
@@ -14,6 +14,7 @@
"postCompact",
"sessionStart",
"userPromptSubmit",
"subagentStart",
"stop"
],
"type": "string"
@@ -14,6 +14,7 @@
"postCompact",
"sessionStart",
"userPromptSubmit",
"subagentStart",
"stop"
],
"type": "string"
@@ -29,6 +29,7 @@
"postCompact",
"sessionStart",
"userPromptSubmit",
"subagentStart",
"stop"
],
"type": "string"
@@ -46,6 +46,7 @@
"postCompact",
"sessionStart",
"userPromptSubmit",
"subagentStart",
"stop"
],
"type": "string"
@@ -2,4 +2,4 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type HookEventName = "preToolUse" | "permissionRequest" | "postToolUse" | "preCompact" | "postCompact" | "sessionStart" | "userPromptSubmit" | "stop";
export type HookEventName = "preToolUse" | "permissionRequest" | "postToolUse" | "preCompact" | "postCompact" | "sessionStart" | "userPromptSubmit" | "subagentStart" | "stop";
@@ -3,4 +3,4 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { ConfiguredHookMatcherGroup } from "./ConfiguredHookMatcherGroup";
export type ManagedHooksRequirements = { managedDir: string | null, windowsManagedDir: string | null, PreToolUse: Array<ConfiguredHookMatcherGroup>, PermissionRequest: Array<ConfiguredHookMatcherGroup>, PostToolUse: Array<ConfiguredHookMatcherGroup>, PreCompact: Array<ConfiguredHookMatcherGroup>, PostCompact: Array<ConfiguredHookMatcherGroup>, SessionStart: Array<ConfiguredHookMatcherGroup>, UserPromptSubmit: Array<ConfiguredHookMatcherGroup>, Stop: Array<ConfiguredHookMatcherGroup>, };
export type ManagedHooksRequirements = { managedDir: string | null, windowsManagedDir: string | null, PreToolUse: Array<ConfiguredHookMatcherGroup>, PermissionRequest: Array<ConfiguredHookMatcherGroup>, PostToolUse: Array<ConfiguredHookMatcherGroup>, PreCompact: Array<ConfiguredHookMatcherGroup>, PostCompact: Array<ConfiguredHookMatcherGroup>, SessionStart: Array<ConfiguredHookMatcherGroup>, UserPromptSubmit: Array<ConfiguredHookMatcherGroup>, SubagentStart: Array<ConfiguredHookMatcherGroup>, Stop: Array<ConfiguredHookMatcherGroup>, };
@@ -423,6 +423,9 @@ pub struct ManagedHooksRequirements {
#[serde(rename = "UserPromptSubmit")]
#[ts(rename = "UserPromptSubmit")]
pub user_prompt_submit: Vec<ConfiguredHookMatcherGroup>,
#[serde(rename = "SubagentStart")]
#[ts(rename = "SubagentStart")]
pub subagent_start: Vec<ConfiguredHookMatcherGroup>,
#[serde(rename = "Stop")]
#[ts(rename = "Stop")]
pub stop: Vec<ConfiguredHookMatcherGroup>,
@@ -17,7 +17,7 @@ use ts_rs::TS;
v2_enum_from_core!(
pub enum HookEventName from CoreHookEventName {
PreToolUse, PermissionRequest, PostToolUse, PreCompact, PostCompact, SessionStart, UserPromptSubmit, Stop
PreToolUse, PermissionRequest, PostToolUse, PreCompact, PostCompact, SessionStart, UserPromptSubmit, SubagentStart, Stop
}
);