From 72a8e4e5db85479bbc24f3bc1005d1ff63e9f976 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Thu, 23 Apr 2026 20:09:46 -0700 Subject: [PATCH] docs(codex): clarify hook layering Clarify Codex hook layering in the harness docs. --- docs/concepts/agent-loop.md | 6 ++++- docs/plugins/codex-harness.md | 47 ++++++++++++++++++++++++++++++----- 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/docs/concepts/agent-loop.md b/docs/concepts/agent-loop.md index ca1c1e8014b..ba4458e4290 100644 --- a/docs/concepts/agent-loop.md +++ b/docs/concepts/agent-loop.md @@ -98,7 +98,7 @@ These run inside the agent loop or gateway pipeline: - **`before_compaction` / `after_compaction`**: observe or annotate compaction cycles. - **`before_tool_call` / `after_tool_call`**: intercept tool params/results. - **`before_install`**: inspect built-in scan findings and optionally block skill or plugin installs. -- **`tool_result_persist`**: synchronously transform tool results before they are written to the session transcript. +- **`tool_result_persist`**: synchronously transform tool results before they are written to an OpenClaw-owned session transcript. - **`message_received` / `message_sending` / `message_sent`**: inbound + outbound message hooks. - **`session_start` / `session_end`**: session lifecycle boundaries. - **`gateway_start` / `gateway_stop`**: gateway lifecycle events. @@ -114,6 +114,10 @@ Hook decision rules for outbound/tool guards: See [Plugin hooks](/plugins/architecture-internals#provider-runtime-hooks) for the hook API and registration details. +Harnesses may adapt these hooks differently. The Codex app-server harness keeps +OpenClaw plugin hooks as the compatibility contract for documented mirrored +surfaces, while Codex native hooks remain a separate lower-level Codex mechanism. + ## Streaming + partial replies - Assistant deltas are streamed from pi-agent-core and emitted as `assistant` events. diff --git a/docs/plugins/codex-harness.md b/docs/plugins/codex-harness.md index 03e9b35ecba..0e6cb642af7 100644 --- a/docs/plugins/codex-harness.md +++ b/docs/plugins/codex-harness.md @@ -15,19 +15,21 @@ discovery, native thread resume, native compaction, and app-server execution. OpenClaw still owns chat channels, session files, model selection, tools, approvals, media delivery, and the visible transcript mirror. -Native Codex turns also respect the shared plugin hooks so prompt shims, -compaction-aware automation, tool middleware, and lifecycle observers stay -aligned with the PI harness: +Native Codex turns keep OpenClaw plugin hooks as the public compatibility layer. +These are in-process OpenClaw hooks, not Codex `hooks.json` command hooks: - `before_prompt_build` - `before_compaction`, `after_compaction` - `llm_input`, `llm_output` -- `tool_result`, `after_tool_call` -- `before_message_write` +- `after_tool_call` +- `before_message_write` for mirrored transcript records - `agent_end` Bundled plugins can also register a Codex app-server extension factory to add -async `tool_result` middleware. +async `tool_result` middleware. That middleware runs for OpenClaw dynamic tools +after OpenClaw executes the tool and before the result is returned to Codex. It +is separate from the public `tool_result_persist` plugin hook, which transforms +OpenClaw-owned transcript tool-result writes. The harness is off by default. New configs should keep OpenAI model refs canonical as `openai/gpt-*` and explicitly force @@ -505,6 +507,35 @@ The command surface requires Codex app-server `0.118.0` or newer. Individual control methods are reported as `unsupported by this Codex app-server` if a future or custom app-server does not expose that JSON-RPC method. +## Hook boundaries + +The Codex harness has three hook layers: + +| Layer | Owner | Purpose | +| ------------------------------------- | ------------------------ | ------------------------------------------------------------------- | +| OpenClaw plugin hooks | OpenClaw | Product/plugin compatibility across PI and Codex harnesses. | +| Codex app-server extension middleware | OpenClaw bundled plugins | Per-turn adapter behavior around OpenClaw dynamic tools. | +| Codex native hooks | Codex | Low-level Codex lifecycle and native tool policy from Codex config. | + +OpenClaw does not use project or global Codex `hooks.json` files to route +OpenClaw plugin behavior. Codex native hooks are useful for Codex-owned +operations such as shell policy, native tool result review, stop handling, and +native compaction/model lifecycle, but they are not the OpenClaw plugin API. + +For OpenClaw dynamic tools, OpenClaw executes the tool after Codex asks for the +call, so OpenClaw fires the plugin and middleware behavior it owns in the +harness adapter. For Codex-native tools, Codex owns the canonical tool record. +OpenClaw can mirror selected events, but it cannot rewrite the native Codex +thread unless Codex exposes that operation through app-server or native hook +callbacks. + +When newer Codex app-server builds expose native compaction and model lifecycle +hook events, OpenClaw should version-gate that protocol support and map the +events into the existing OpenClaw hook contract where the semantics are honest. +Until then, OpenClaw's `before_compaction`, `after_compaction`, `llm_input`, and +`llm_output` events are adapter-level observations, not byte-for-byte captures +of Codex's internal request or compaction payloads. + ## Tools, media, and compaction The Codex harness changes the low-level embedded agent executor only. @@ -527,6 +558,10 @@ records native compaction start and completion signals. It does not yet expose a human-readable compaction summary or an auditable list of which entries Codex kept after compaction. +Because Codex owns the canonical native thread, `tool_result_persist` does not +currently rewrite Codex-native tool result records. It only applies when +OpenClaw is writing an OpenClaw-owned session transcript tool result. + Media generation does not require PI. Image, video, music, PDF, TTS, and media understanding continue to use the matching provider/model settings such as `agents.defaults.imageGenerationModel`, `videoGenerationModel`, `pdfModel`, and