Skip to content

Commit 34fb966

Browse files
Support MCP hooks in the Codex harness (#71707)
* codex harness mcp hook parity * tighten codex hook parity floor * prove security-style mcp hook blocking * bound native hook relay key handling * clarify permission relay defers to provider * harden native hook relay approvals * fix(agents): bound native hook relay JSON work budget --------- Co-authored-by: Peter Steinberger <steipete@gmail.com>
1 parent e2fd3dc commit 34fb966

19 files changed

Lines changed: 717 additions & 86 deletions

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ Docs: https://docs.openclaw.ai
5656
- Providers/Local CLI TTS: add a bundled local command speech provider with file/stdout input, voice-note Opus conversion, and telephony PCM output. (#56239) Thanks @solar2ain.
5757
- Android/Talk Mode: expose Talk Mode in the Voice tab with runtime-owned voice capture modes and microphone foreground-service escalation. Thanks @alex-latitude.
5858
- Providers/LiteLLM: register `litellm` as an image-generation provider so `image_generate model=litellm/...` calls and `agents.defaults.imageGenerationModel.fallbacks` entries resolve through the LiteLLM proxy. Thanks @zqchris.
59+
- Codex harness: require Codex app-server `0.125.0` or newer and cover native MCP `PreToolUse`, `PostToolUse`, and `PermissionRequest` payloads through the OpenClaw hook relay.
5960

6061
### Fixes
6162

docs/plugins/codex-harness.md

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,8 @@ Codex after changing config.
103103
## Requirements
104104

105105
- OpenClaw with the bundled `codex` plugin available.
106-
- Codex app-server `0.118.0` or newer.
106+
- Codex app-server `0.125.0` or newer. Native MCP hook payloads landed in Codex
107+
`0.124.0`; OpenClaw uses `0.125.0` as the tested support floor.
107108
- Codex auth available to the app-server process.
108109

109110
The plugin blocks older or unversioned app-server handshakes. That keeps
@@ -551,7 +552,7 @@ normal turns. On the next message, OpenClaw resumes that Codex thread, passes th
551552
currently selected OpenClaw model into app-server, and keeps extended history
552553
enabled.
553554

554-
The command surface requires Codex app-server `0.118.0` or newer. Individual
555+
The command surface requires Codex app-server `0.125.0` or newer. Individual
555556
control methods are reported as `unsupported by this Codex app-server` if a
556557
future or custom app-server does not expose that JSON-RPC method.
557558

@@ -597,31 +598,30 @@ around that boundary.
597598

598599
Supported in Codex runtime v1:
599600

600-
| Surface | Support | Why |
601-
| --------------------------------------- | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
602-
| OpenAI model loop through Codex | Supported | Codex app-server owns the OpenAI turn, native thread resume, and native tool continuation. |
603-
| OpenClaw channel routing and delivery | Supported | Telegram, Discord, Slack, WhatsApp, iMessage, and other channels stay outside the model runtime. |
604-
| OpenClaw dynamic tools | Supported | Codex asks OpenClaw to execute these tools, so OpenClaw stays in the execution path. |
605-
| Prompt and context plugins | Supported | OpenClaw builds prompt overlays and projects context into the Codex turn before starting or resuming the thread. |
606-
| Context engine lifecycle | Supported | Assemble, ingest or after-turn maintenance, and context-engine compaction coordination run for Codex turns. |
607-
| Dynamic tool hooks | Supported | `before_tool_call`, `after_tool_call`, and tool-result middleware run around OpenClaw-owned dynamic tools. |
608-
| Lifecycle hooks | Supported as adapter observations | `llm_input`, `llm_output`, `agent_end`, `before_compaction`, and `after_compaction` fire with honest Codex-mode payloads. |
609-
| Native shell and patch block or observe | Supported through the native hook relay | Codex `PreToolUse` and `PostToolUse` are relayed for the committed native tool surfaces. Blocking is supported; argument rewriting is not. |
610-
| Native permission policy | Supported through the native hook relay | Codex `PermissionRequest` can be routed through OpenClaw policy where the runtime exposes it. |
611-
| App-server trajectory capture | Supported | OpenClaw records the request it sent to app-server and the app-server notifications it receives. |
601+
| Surface | Support | Why |
602+
| --------------------------------------------- | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
603+
| OpenAI model loop through Codex | Supported | Codex app-server owns the OpenAI turn, native thread resume, and native tool continuation. |
604+
| OpenClaw channel routing and delivery | Supported | Telegram, Discord, Slack, WhatsApp, iMessage, and other channels stay outside the model runtime. |
605+
| OpenClaw dynamic tools | Supported | Codex asks OpenClaw to execute these tools, so OpenClaw stays in the execution path. |
606+
| Prompt and context plugins | Supported | OpenClaw builds prompt overlays and projects context into the Codex turn before starting or resuming the thread. |
607+
| Context engine lifecycle | Supported | Assemble, ingest or after-turn maintenance, and context-engine compaction coordination run for Codex turns. |
608+
| Dynamic tool hooks | Supported | `before_tool_call`, `after_tool_call`, and tool-result middleware run around OpenClaw-owned dynamic tools. |
609+
| Lifecycle hooks | Supported as adapter observations | `llm_input`, `llm_output`, `agent_end`, `before_compaction`, and `after_compaction` fire with honest Codex-mode payloads. |
610+
| Native shell, patch, and MCP block or observe | Supported through the native hook relay | Codex `PreToolUse` and `PostToolUse` are relayed for committed native tool surfaces, including MCP payloads on Codex app-server `0.125.0` or newer. Blocking is supported; argument rewriting is not. |
611+
| Native permission policy | Supported through the native hook relay | Codex `PermissionRequest` can be routed through OpenClaw policy where the runtime exposes it. If OpenClaw returns no decision, Codex continues through its normal guardian or user approval path. |
612+
| App-server trajectory capture | Supported | OpenClaw records the request it sent to app-server and the app-server notifications it receives. |
612613

613614
Not supported in Codex runtime v1:
614615

615-
| Surface | V1 boundary | Future path |
616-
| --------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
617-
| Native tool argument mutation | Codex native pre-tool hooks can block, but OpenClaw does not rewrite Codex-native tool arguments. | Requires Codex hook/schema support for replacement tool input. |
618-
| Editable Codex-native transcript history | Codex owns canonical native thread history. OpenClaw owns a mirror and can project future context, but should not mutate unsupported internals. | Add explicit Codex app-server APIs if native thread surgery is needed. |
619-
| `tool_result_persist` for Codex-native tool records | That hook transforms OpenClaw-owned transcript writes, not Codex-native tool records. | Could mirror transformed records, but canonical rewrite needs Codex support. |
620-
| Rich native compaction metadata | OpenClaw observes compaction start and completion, but does not receive a stable kept/dropped list, token delta, or summary payload. | Needs richer Codex compaction events. |
621-
| Compaction intervention | Current OpenClaw compaction hooks are notification-level in Codex mode. | Add Codex pre/post compaction hooks if plugins need to veto or rewrite native compaction. |
622-
| Stop or final-answer gating | Codex has native stop hooks, but OpenClaw does not expose final-answer gating as a v1 plugin contract. | Future opt-in primitive with loop and timeout safeguards. |
623-
| Native MCP hook parity as a committed v1 surface | The relay is generic, but OpenClaw has not version-gated and tested native MCP pre/post hook behavior end to end. | Add OpenClaw MCP relay tests and docs once the supported app-server protocol floor covers those payloads. |
624-
| Byte-for-byte model API request capture | OpenClaw can capture app-server requests and notifications, but Codex core builds the final OpenAI API request internally. | Needs a Codex model-request tracing event or debug API. |
616+
| Surface | V1 boundary | Future path |
617+
| --------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
618+
| Native tool argument mutation | Codex native pre-tool hooks can block, but OpenClaw does not rewrite Codex-native tool arguments. | Requires Codex hook/schema support for replacement tool input. |
619+
| Editable Codex-native transcript history | Codex owns canonical native thread history. OpenClaw owns a mirror and can project future context, but should not mutate unsupported internals. | Add explicit Codex app-server APIs if native thread surgery is needed. |
620+
| `tool_result_persist` for Codex-native tool records | That hook transforms OpenClaw-owned transcript writes, not Codex-native tool records. | Could mirror transformed records, but canonical rewrite needs Codex support. |
621+
| Rich native compaction metadata | OpenClaw observes compaction start and completion, but does not receive a stable kept/dropped list, token delta, or summary payload. | Needs richer Codex compaction events. |
622+
| Compaction intervention | Current OpenClaw compaction hooks are notification-level in Codex mode. | Add Codex pre/post compaction hooks if plugins need to veto or rewrite native compaction. |
623+
| Stop or final-answer gating | Codex has native stop hooks, but OpenClaw does not expose final-answer gating as a v1 plugin contract. | Future opt-in primitive with loop and timeout safeguards. |
624+
| Byte-for-byte model API request capture | OpenClaw can capture app-server requests and notifications, but Codex core builds the final OpenAI API request internally. | Needs a Codex model-request tracing event or debug API. |
625625

626626
## Tools, media, and compaction
627627

@@ -632,9 +632,15 @@ harness. Text, images, video, music, TTS, approvals, and messaging-tool output
632632
continue through the normal OpenClaw delivery path.
633633

634634
The native hook relay is intentionally generic, but the v1 support contract is
635-
limited to the Codex-native tool and permission paths that OpenClaw tests. Do not
636-
assume every future Codex hook event is an OpenClaw plugin surface until the
637-
runtime contract names it.
635+
limited to the Codex-native tool and permission paths that OpenClaw tests. In
636+
the Codex runtime, that includes shell, patch, and MCP `PreToolUse`,
637+
`PostToolUse`, and `PermissionRequest` payloads. Do not assume every future
638+
Codex hook event is an OpenClaw plugin surface until the runtime contract names
639+
it.
640+
641+
For `PermissionRequest`, OpenClaw only returns explicit allow or deny decisions
642+
when policy decides. A no-decision result is not an allow. Codex treats it as no
643+
hook decision and falls through to its own guardian or user approval path.
638644

639645
Codex MCP tool approval elicitations are routed through OpenClaw's plugin
640646
approval flow when Codex marks `_meta.codex_approval_kind` as
@@ -677,7 +683,9 @@ explicitly set `embeddedHarness.fallback: "pi"`. Once Codex app-server is
677683
selected, its failures surface directly without extra fallback config.
678684

679685
**The app-server is rejected:** upgrade Codex so the app-server handshake
680-
reports version `0.118.0` or newer.
686+
reports version `0.125.0` or newer. Same-version prereleases or build-suffixed
687+
versions such as `0.125.0-alpha.2` or `0.125.0+custom` are rejected because the
688+
stable `0.125.0` protocol floor is what OpenClaw tests.
681689

682690
**Model discovery is slow:** lower `plugins.entries.codex.config.discovery.timeoutMs`
683691
or disable discovery.

docs/plugins/sdk-agent-harness.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,9 +142,11 @@ Codex provider and harness for compatibility.
142142
For operator setup, model prefix examples, and Codex-only configs, see
143143
[Codex Harness](/plugins/codex-harness).
144144

145-
OpenClaw requires Codex app-server `0.118.0` or newer. The Codex plugin checks
145+
OpenClaw requires Codex app-server `0.125.0` or newer. The Codex plugin checks
146146
the app-server initialize handshake and blocks older or unversioned servers so
147-
OpenClaw only runs against the protocol surface it has been tested with.
147+
OpenClaw only runs against the protocol surface it has been tested with. The
148+
`0.125.0` floor includes the native MCP hook payload support that landed in
149+
Codex `0.124.0`, while pinning OpenClaw to the newer tested stable line.
148150

149151
### Tool-result middleware
150152

extensions/codex/media-understanding-provider.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ function threadStartResult() {
3535
status: { type: "idle" },
3636
path: null,
3737
cwd: "/tmp/openclaw-agent",
38-
cliVersion: "0.118.0",
38+
cliVersion: "0.125.0",
3939
source: "unknown",
4040
agentNickname: null,
4141
agentRole: null,

extensions/codex/src/app-server/auth-profile-runtime-contract.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ function threadStartResult(threadId = "thread-auth-contract") {
4343
status: { type: "idle" },
4444
path: null,
4545
cwd: "",
46-
cliVersion: "0.118.0",
46+
cliVersion: "0.125.0",
4747
source: "unknown",
4848
agentNickname: null,
4949
agentRole: null,

0 commit comments

Comments
 (0)