mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +00:00
Add SubagentStop hook (#22873)
# What <img width="1792" height="1024" alt="image" src="https://github.com/user-attachments/assets/8f81d232-5813-4994-a61d-e42a05a93a3e" /> `SubagentStop` runs when a thread-spawned subagent turn is about to finish. Thread-spawned subagents use `SubagentStop` instead of the normal root-agent `Stop` hook. Configured handlers match on `agent_type`. Hook input includes the normal stop fields plus: - `agent_id`: the child thread id. - `agent_type`: the resolved subagent type. - `agent_transcript_path`: the child subagent transcript path. - `transcript_path`: the parent thread transcript path. - `last_assistant_message`: the final assistant message from the child turn, when available. - `stop_hook_active`: `true` when the child is already continuing because an earlier stop-like hook blocked completion. `SubagentStop` shares the same completion-control semantics as `Stop`, scoped to the child turn: - No decision allows the child turn to finish. - `decision: "block"` with a non-empty `reason` records that reason as hook feedback and continues the child with that prompt. - `continue: false` stops the child turn. If `stopReason` is present, Codex surfaces it as the stop reason. # Lifecycle Scope Only thread-spawned subagents run `SubagentStop`. Internal/system subagents such as Review, Compact, MemoryConsolidation, and Other do not run normal `Stop` hooks and do not run `SubagentStop`. This avoids exposing synthetic matcher labels for internal implementation paths. # Stack 1. #22782: add `SubagentStart`. 2. This PR: add `SubagentStop`. 3. #22882: add subagent identity to normal hook inputs.
This commit is contained in:
1 parent
40ad7be2b5
commit
eee3e60db3
43 files changed
+813
-77
No files matched your search
@@ -15,7 +15,7 @@ pub use declarations::PluginHookDeclaration;
|
||||
pub use declarations::plugin_hook_declarations;
|
||||
pub use engine::HookListEntry;
|
||||
/// Hook event names as they appear in hooks JSON and config files.
|
||||
pub const HOOK_EVENT_NAMES: [&str; 9] = [
|
||||
pub const HOOK_EVENT_NAMES: [&str; 10] = [
|
||||
"PreToolUse",
|
||||
"PermissionRequest",
|
||||
"PostToolUse",
|
||||
@@ -24,6 +24,7 @@ pub const HOOK_EVENT_NAMES: [&str; 9] = [
|
||||
"SessionStart",
|
||||
"UserPromptSubmit",
|
||||
"SubagentStart",
|
||||
"SubagentStop",
|
||||
"Stop",
|
||||
];
|
||||
|
||||
@@ -32,7 +33,7 @@ pub const HOOK_EVENT_NAMES: [&str; 9] = [
|
||||
/// Other events can appear in hooks JSON, but Codex ignores their matcher
|
||||
/// fields because those events do not dispatch against a tool, compaction
|
||||
/// trigger, or session-start source.
|
||||
pub const HOOK_EVENT_NAMES_WITH_MATCHERS: [&str; 7] = [
|
||||
pub const HOOK_EVENT_NAMES_WITH_MATCHERS: [&str; 8] = [
|
||||
"PreToolUse",
|
||||
"PermissionRequest",
|
||||
"PostToolUse",
|
||||
@@ -40,6 +41,7 @@ pub const HOOK_EVENT_NAMES_WITH_MATCHERS: [&str; 7] = [
|
||||
"PostCompact",
|
||||
"SessionStart",
|
||||
"SubagentStart",
|
||||
"SubagentStop",
|
||||
];
|
||||
|
||||
pub use events::compact::PostCompactRequest;
|
||||
@@ -57,6 +59,7 @@ pub use events::session_start::SessionStartOutcome;
|
||||
pub use events::session_start::SessionStartRequest;
|
||||
pub use events::session_start::SessionStartSource;
|
||||
pub use events::session_start::StartHookTarget;
|
||||
pub use events::stop::StopHookTarget;
|
||||
pub use events::stop::StopOutcome;
|
||||
pub use events::stop::StopRequest;
|
||||
pub use events::user_prompt_submit::UserPromptSubmitOutcome;
|
||||
@@ -87,6 +90,7 @@ pub fn hook_event_key_label(event_name: HookEventName) -> &'static str {
|
||||
HookEventName::SessionStart => "session_start",
|
||||
HookEventName::UserPromptSubmit => "user_prompt_submit",
|
||||
HookEventName::SubagentStart => "subagent_start",
|
||||
HookEventName::SubagentStop => "subagent_stop",
|
||||
HookEventName::Stop => "stop",
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user