Skip to content

Register Codex SessionEnd, SubagentStart and SubagentStop hooks - #294

Merged
Siddhant-K-code merged 1 commit into
mainfrom
siddhant-k-code-codex-session-end-subagent-hooks
Oct 24, 2026
Merged

Siddhant-K-code merged 1 commit into
mainfrom
siddhant-k-code-codex-session-end-subagent-hooks

Conversation

@Siddhant-K-code

Copy link
Copy Markdown
Owner

Summary

agent-strace setup --cli codex used to register five Codex hooks (SessionStart, UserPromptSubmit, PreToolUse, PostToolUse, Stop). This PR adds SessionEnd, SubagentStart and SubagentStop.

  • SessionEnd → agent-strace hook session-end, with "timeout": 3. Codex defaults SessionEnd hooks to 1s and caps them at 3s. Codex traces now get a session_end event, clear their active-session marker and finalize in health.
  • SubagentStart / SubagentStop → subagent-start / subagent-stop. These reuse the feat(copilot): link subagent sessions to their parent via subagentStart/subagentStop #286 handler, so they are recorded as subagent_start / subagent_stop in the parent trace with agent_id and agent_type.
  • No linking for Codex subagents. Codex subagents fire hooks under the parent's session_id and are not separate sessions. Codex is not in _SUBAGENT_SESSION_PROVIDERS, so _link_subagent_session never runs: no child session is invented, the parent is not rewritten and nothing is refused. agent_id is added to the recorded keys only for providers outside that set, so Copilot behavior is unchanged.
  • The setup checklist now says hooks added by a newer agent-strace must be trusted again (codex exec silently skips untrusted hooks).

Observed payloads (codex-cli 0.163.0-alpha.11, field names only)

Hook Fields
SubagentStart agent_id, agent_type, cwd, hook_event_name, model, permission_mode, session_id (the parent's), transcript_path, turn_id (the subagent's turn)
SubagentStop SubagentStart fields + agent_transcript_path, last_assistant_message, stop_hook_active
SessionEnd cwd, hook_event_name, reason (always "other" in every run), session_id, transcript_path. No turn_id or model

Pre/PostToolUse calls made by a subagent also carry agent_id and agent_type. agent_type was default. agent_id is a UUID distinct from the session id.

Order in both live runs:

  1. SessionStart, UserPromptSubmit
  2. spawn_agent Pre/PostToolUse
  3. SubagentStart
  4. wait_agent PreToolUse
  5. Subagent Bash Pre/PostToolUse
  6. SubagentStop
  7. wait_agent PostToolUse
  8. Stop
  9. SessionEnd, last. No hooks fired after it.

The #280 capture had SubagentStart after the wait_agent PreToolUse, so that position is racy. Both orders are now fixture scenarios. The spawn_agent result does not include the agent_id, so a subagent cannot be tied to the tool call that spawned it.

Verification

  • Live end-to-end with the desktop-bundled Codex 0.163.0-alpha.11, an isolated CODEX_HOME, a temp trace dir and no bypass/yolo flags:
    • Ran this branch's setup --cli codex. /hooks showed all 8 hooks as modified (untrusted). After re-trusting, setup --verify reported 8/8.
    • A codex exec -s read-only subagent run recorded:
      • session_start and user_prompt
      • the spawn tool call/result
      • subagent_start, with agent_id, agent_type and turn_id
      • the wait tool call
      • the subagent's Bash call/result
      • subagent_stop
      • the wait result
      • assistant_response
      • session_end
    • No active-session marker remained, and health reported a finalized session.
    • codex exec resume --last appended session_start(resume) followed by session_end to the same trace.
    • replay, replay --tree, --expand-subagents, tree, stats --include-subagents and explain all exited 0.
  • Tests:
    • New TestCodexSessionEndAndSubagentHooks in tests/test_codex_hooks.py:
      • subagent events go to the parent trace
      • no child session and no link
      • SessionEnd finalizes the session
      • hooks arriving after session_end don't break anything
    • Rewrote the Codex fixture tests in tests/test_capture_matrix_fixtures.py.
    • tests/test_setup_verify.py:
      • added a test showing an old 5-hook config now fails --verify
      • updated the event counts from 5 to 8
    • Updated the tests/test_health.py Codex cases. The provider-without-session-end path keeps its coverage through a patched matrix.
    • TMPDIR=/private/tmp PYTHONPATH=src python3 -m unittest discover -s tests: 2385 tests OK (2 skipped).
  • The fixture contains only synthetic values. The diff was leak-scanned for local paths, usernames, real session ids, prompts and credentials.

Upgrade note for existing users

Re-run agent-strace setup --cli codex, then re-trust the hooks in Codex's /hooks. Until you re-trust them, codex exec silently skips the modified hooks. Traces recorded by older installs never cleared their active-session marker, so health now reports them as session_active instead of treating a missing end as a Codex limitation. This is documented in docs/commands.md and docs/capture-matrix.md.

Docs and matrix

  • capture_matrix.json, codex entry:
    • session_end is now captured
    • known gaps rewritten: re-trust is required, SessionEnd reason is always other, subagents are not separate sessions
    • last_verified updated
  • docs/capture-matrix.md: updated the coverage table, the Codex section and the machine-readable row.
  • docs/setup.md: hooks JSON, field notes and an upgrading paragraph.
  • docs/integrations.md: updated the Codex row.
  • docs/commands.md:
    • added subagent-start / subagent-stop rows to the hook table
    • removed the old "Codex has no session end" wording

Deferred

  • SubagentStop's last_assistant_message and agent_transcript_path are not recorded.
  • Subagent tool events don't record agent_id yet.
  • Replay doesn't render agent_id. replay.py is in Refuse sessions with non-object event data instead of printing a traceback #293's scope.
  • SessionEnd was not exercised from the interactive TUI, only from codex exec.
  • Two pre-existing issues seen during the run, unchanged here:
    • an empty .pending-calls file is left after session end
    • agent-strace list ignores AGENT_TRACE_DIR

Related

No version bump, tag or release.

`agent-strace setup --cli codex` now registers SessionEnd, SubagentStart
and SubagentStop alongside the existing five hooks. Codex traces get a
session_end event, and subagent lifecycle is recorded as
subagent_start/subagent_stop in the parent trace with agent_id and
agent_type. Codex subagents share the parent session_id, so no child
session is linked or created.

SessionEnd uses a 3s timeout (Codex's cap; its default is 1s).

Update the capture matrix, the Codex 0.163.0-alpha.11 fixture, tests and
docs. Existing users must re-run setup and re-trust the hooks in /hooks;
codex exec skips untrusted hooks.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@Siddhant-K-code
Siddhant-K-code merged commit f7fc2a8 into main Oct 24, 2026
5 checks passed
@Siddhant-K-code
Siddhant-K-code deleted the siddhant-k-code-codex-session-end-subagent-hooks branch October 24, 2026 17:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant