Skip to content

Codex: inject per-agent context for subagent SessionStart #146

Description

@studykit

Description

Make Codex emit per-agent SubagentStart context when a subagent's SessionStart fires. Today hook_codex.py::_handle_agent_session_start identifies the subagent (via payload markers or transcript session_meta) and calls record_subagent_start, but intentionally skips additional-context emission — the module docstring says "Subagent sessions skip the main-session workflow authoring policy injection." That blanket skip was correct when no per-agent template existed; with issue-planner (#145) merged, Codex subagents now silently miss the <runbook> block and other per-agent context that Claude subagents inherit via SubagentStart.

The shared builder build_subagent_start_context(config, plugin_root, runtime, agent_type) already supports runtime="codex" and renders the codex launcher snippet — the infrastructure is in place. Only the Codex hook adapter declines to call it.

Note: the contract here is not main-session authoring policy. It is the narrower per-agent slice — launcher + authoring resolver + per-agent runbook — that subagents need to operate. The Codex hook should inherit the same scope Claude's SubagentStart inherits today, no more.

Approach

  1. Extend _handle_agent_session_start in plugins/workflow/hooks/scripts/hook_codex.py:
    • After record_subagent_start, call build_subagent_start_context(config, _plugin_root(), runtime="codex", agent_type=<resolved name>).
    • Resolve agent_type from transcript metadata via the existing _agent_name_from_metadata helper.
    • Emit hookSpecificOutput (hookEventName: "SessionStart", additionalContext: <block>) when a non-empty block is produced.
    • Keep the early return when metadata is missing or parent_thread_id cannot be resolved — no metadata, no agent block.
  2. Update the module docstring at the top of hook_codex.py so it no longer claims Codex subagents skip all injection; describe the new contract.
  3. Update plugins/workflow/hooks/AGENTS.md:
    • Rewrite "Subagents inherit env, not policy." — subagents also inherit the per-agent launcher / authoring-resolver / runbook fragments via build_subagent_start_context, but still not the heavier main-session authoring guidance.
    • Keep "Manifest asymmetry is deliberate. Codex registers only SessionStart + UserPromptSubmit." — add a sentence noting that Codex routes the SubagentStart equivalent through SessionStart's subagent branch.
  4. Tests:
    • If existing tests in plugins/workflow/tests/test_workflow_hook.py assert that Codex agent SessionStart emits no additionalContext, flip the assertion: emit when agent_type matches a known per-agent template; stay silent for unknown agents.
    • Add a positive test exercising issue-planner via a synthesized Codex session_meta and verifying the rendered block carries the expected <runbook> tag.
    • Add a negative test: Codex subagent SessionStart with no resolvable agent name still records identity but emits no additional context.

Affected Paths

  • plugins/workflow/hooks/scripts/hook_codex.py
  • plugins/workflow/hooks/AGENTS.md
  • plugins/workflow/tests/test_workflow_hook.py

Unit Test Strategy

  • The existing test helper renders per-agent context via build_subagent_start_context for Claude. Mirror the same shape for Codex with a fixture session_meta that names the agent (agent_name: "issue-planner", or the equivalent slot under source.subagent.thread_spawn). Assert the emitted additionalContext carries the <runbook> block listed in hooks/context/subagent/agents/issue-planner.md.
  • Negative test: a Codex subagent SessionStart with no agent_type resolution records identity but emits no additional context.
  • Regression: main-session Codex SessionStart behavior unchanged — keep existing assertions.

Acceptance Criteria

  • _handle_agent_session_start calls build_subagent_start_context(..., runtime="codex", agent_type=<resolved>) and emits additionalContext via emit_json when the block is non-empty.
  • Agent-name resolution reuses _agent_name_from_metadata — no new metadata-walking code introduced.
  • hooks/AGENTS.md invariant text reflects the new "subagents inherit per-agent context" contract.
  • Existing Codex SessionStart main-session tests still pass unchanged.
  • New positive test for Codex subagent SessionStart against issue-planner asserts the rendered block carries the runbook intents listed in hooks/context/subagent/agents/issue-planner.md.
  • New negative test: missing or unknown agent name yields identity record + no additionalContext emission.
  • pytest plugins/workflow/tests passes.

Out of Scope

  • Adding a true SubagentStart event to Codex's manifest. Codex doesn't expose that event; we route through SessionStart's subagent branch instead.
  • Backporting per-agent emission to historical Codex sessions — only new sessions fire SessionStart.
  • Heavier main-session authoring policy injection for subagents. The contract stays: launcher + authoring resolver + per-agent runbook, nothing more.

Related

Metadata

Metadata

Assignees

Labels

taskWorkflow implementation task

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions