Native hook relay drops mid-agent-turn after long model-thinking gaps
Filed against: OpenClaw 2026.5.28 (commit e932160)
Reporter date: 2026-05-27
Retest / submission update: 2026-06-01
Severity: Medium — recoverable per-turn but disrupts long agent runs; affects all Codex (GPT-5) sessions that include >~90s thinking gaps mid-turn.
Environment
- OpenClaw
2026.5.28 (commit e932160), installed via npm at /opt/homebrew/lib/node_modules/openclaw/; CLI and Gateway both verified on 2026.5.28 after gateway restart on 2026-06-01
- macOS 26.5 arm64, node 25.5.0
- Codex (GPT-5) agent running via
ai.openclaw.gateway LaunchAgent
- Gateway was freshly
bootout+bootstrap-restarted at 2026-05-27 15:22 PT before the captured reproducer (rules out stale-process drift across the boundary)
Symptom
The Codex exec_command tool returns the literal string:
Command blocked by PreToolUse hook: Native hook relay unavailable.
mid-way through an agent turn that had previously executed successful tool calls on the same gateway PID. The same shell-style call (sed -n, rg, pwd) succeeds before the gap and fails after, with no intervening user action.
Reproducer
Rollout file:
/Users/synthiacipher/.openclaw/agents/main/agent/codex-home/sessions/2026/05/27/rollout-2026-05-27T16-31-43-019e6bc7-9987-74d0-97a9-0a7459da7a9f.jsonl
Timeline (UTC, single agent turn, gateway PID 41808 throughout):
| Time (UTC) |
Δ |
Tool calls |
Result |
| 23:32:08–23:32:17 |
— |
8 reads (sed -n, rg) |
All exited with code 0 ✓ |
| 23:33:57 |
+100s (model thinking) |
4 reads (sed -n) |
All Native hook relay unavailable ✗ |
| 23:35:46 |
+107s |
1 read (pwd) |
Native hook relay unavailable ✗ |
The 100-second model-thinking gap is the inflection point — every tool call after the gap fails until the agent yields, and the failure persists across additional thinking gaps inside the same turn.
Contradiction with documented constants
Per the shipped bundle at /opt/homebrew/lib/node_modules/openclaw/dist/:
CODEX_NATIVE_HOOK_RELAY_MIN_TTL_MS = 30 * 6e4 → 30 minutes minimum TTL
CODEX_NATIVE_HOOK_RELAY_RENEW_INTERVAL_MS = 6e4 → 60s renewal interval
MAX_NATIVE_HOOK_RELAY_INVOCATIONS = 200 → 200-call cap per bridge
A 100-second model-thinking gap should not exhaust any of these on its own. Hypothesis: the renewal pings are driven by the Codex app-server tool-call cadence and stop while the model is in long thinking, with no server-side keepalive timer. By the time the next tool call arrives, the bridge has either been GC'd or its state is stale, and the app-server surfaces the resulting "unavailable" verbatim to the model.
Other observations
openclaw hooks check reports Ready: 5 / Not ready: 0 both before and after the failure window, so that diagnostic doesn't detect this case — it tests registry, not in-flight bridges.
- The bridge directory
~/.openclaw/tmp/openclaw-native-hook-relays-501/ is empty at idle, which appears to be normal lazy-init behavior; not the cause.
- 12 distinct rollouts on 2026-05-27 alone contain this error or the agent's narrativized form of it ("the hook relay seems to have failed…"). This is not a one-off.
- Gateway log (
~/Library/Logs/openclaw/gateway.log) has no [hook]/[relay]/[bridge] entries around the failure window. The failure path is either logged only at DEBUG, or it lives in the Codex sidecar stream rather than the gateway's main log. Either way, the user-visible surface is the literal verbatim error inside the model's tool-call output, with no breadcrumb anywhere in the standard logs.
Reproduction status on 2026.5.28
Retested on 2026-06-01 after upgrading the CLI to OpenClaw 2026.5.28 (commit e932160). The running Gateway initially remained on 2026.5.27, which caused immediate agent-turn failures with:
GatewayClientRequestError: Error: Unable to resolve bundled plugin public surface speech-core/runtime-api.js
Restarting the Gateway aligned CLI and Gateway on 2026.5.28; the synthetic relay test was then run again.
Test protocol:
- Prompt A (baseline, no injected keepalive):
Think very carefully for at least 90 seconds about the tradeoffs between event-driven and timer-driven keepalive mechanisms in client/server bridges. Then run pwd.
- Prompt B (keepalive injected):
First run pwd. Then think very carefully for at least 90 seconds about the tradeoffs between event-driven and timer-driven keepalive mechanisms in client/server bridges. Then run pwd again.
- Each prompt was run 3 times with a unique fresh session key,
--thinking high, and --timeout 420.
Results:
| Prompt |
Runs |
Result |
Durations |
| A baseline |
3 |
3/3 final pwd succeeded; no Native hook relay unavailable string |
91s, 47s, 65s |
| B keepalive |
3 |
3/3 final pwd succeeded; no Native hook relay unavailable string |
56s, 91s, 77s |
Interpretation: the synthetic prompt did not reproduce the mid-turn relay failure on 2026.5.28. It also did not demonstrate that the no-op keepalive helps, because baseline did not fail. Only two of the six runs reached the requested ~90s duration, so this is best treated as inconclusive rather than proof of a fix.
Full raw experiment log:
~/.openclaw/logs/relay-keepalive-experiment-2026-06-01.md
Additional post-upgrade observation: each valid run included an earlier failed/timed-out internal attempt with:
Package subpath './plugin-sdk/codex-native-task-runtime' is not defined by "exports" in /Users/synthiacipher/.openclaw/npm/node_modules/@openclaw/codex/node_modules/openclaw/package.json imported from /Users/synthiacipher/.openclaw/npm/node_modules/@openclaw/codex/dist/run-attempt-BqRPAaHk.js
OpenClaw retried and produced a successful final answer, so this appears separate from the native-hook-relay failure but may indicate a package export mismatch in the bundled Codex runtime.
Related
Suggested fix area
The likely fix area is a server-side keepalive timer independent of tool-call cadence. The relay should be renewed every CODEX_NATIVE_HOOK_RELAY_RENEW_INTERVAL_MS / NATIVE_HOOK_RELAY_RENEW_INTERVAL_MS by wall clock while the turn is active, regardless of whether the model is currently issuing tool calls. That would prevent long model-thinking gaps from starving relay renewal and would keep the app-server from surfacing a low-level bridge availability error as a tool result.
Suggested fixes (for upstream to consider)
- Server-side keepalive timer. Renew the relay bridge independently of app-server tool-call cadence, so model-thinking gaps don't starve the renewal loop.
- Granular INFO logging on relay failure. When the relay returns "unavailable," log which specific condition tripped —
bridge expired vs bridge not found vs unreadable result vs renewal-window missed — at INFO so users can self-diagnose without grepping dist/.
- App-server side: re-spawn the bridge before surfacing failure. On
Native hook relay unavailable, have the Codex app-server transparently re-spawn the bridge and retry once, since the model has no useful recovery action and currently confabulates an explanation instead.
- (Optional) Surface relay state in
openclaw hooks check. Extend the diagnostic to inspect in-flight bridge state and TTL, not just registry readiness, so the check matches what users assume it covers.
How I'd reproduce
- Start a fresh gateway:
launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/ai.openclaw.gateway.plist && launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/ai.openclaw.gateway.plist
- Open a Codex session and issue a prompt that forces the model into a long chain-of-thought between tool calls — e.g. "Read the following 8 files quickly, then think for two minutes about how they interact, then read 4 more."
- Observe: the first burst (pre-thinking) succeeds; the second burst (post-thinking) returns
Native hook relay unavailable for every call until the turn ends.
- Cross-check
openclaw hooks check immediately after — it will report all hooks Ready, confirming the diagnostic gap.
- Grep
~/.openclaw/agents/main/agent/codex-home/sessions/**/rollout-*.jsonl for "Native hook relay unavailable" to count occurrences across the day.
Rollout-file evidence is from the 2026.5.26 install at commit 10ad3aa; the reproduction status section above records retest results after upgrading to 2026.5.28 (e932160).
Native hook relay drops mid-agent-turn after long model-thinking gaps
Filed against: OpenClaw
2026.5.28(commite932160)Reporter date: 2026-05-27
Retest / submission update: 2026-06-01
Severity: Medium — recoverable per-turn but disrupts long agent runs; affects all Codex (GPT-5) sessions that include >~90s thinking gaps mid-turn.
Environment
2026.5.28(commite932160), installed via npm at/opt/homebrew/lib/node_modules/openclaw/; CLI and Gateway both verified on2026.5.28after gateway restart on 2026-06-01ai.openclaw.gatewayLaunchAgentbootout+bootstrap-restarted at 2026-05-27 15:22 PT before the captured reproducer (rules out stale-process drift across the boundary)Symptom
The Codex
exec_commandtool returns the literal string:mid-way through an agent turn that had previously executed successful tool calls on the same gateway PID. The same shell-style call (
sed -n,rg,pwd) succeeds before the gap and fails after, with no intervening user action.Reproducer
Rollout file:
Timeline (UTC, single agent turn, gateway PID 41808 throughout):
sed -n,rg)exited with code 0✓sed -n)Native hook relay unavailable✗pwd)Native hook relay unavailable✗The 100-second model-thinking gap is the inflection point — every tool call after the gap fails until the agent yields, and the failure persists across additional thinking gaps inside the same turn.
Contradiction with documented constants
Per the shipped bundle at
/opt/homebrew/lib/node_modules/openclaw/dist/:CODEX_NATIVE_HOOK_RELAY_MIN_TTL_MS = 30 * 6e4→ 30 minutes minimum TTLCODEX_NATIVE_HOOK_RELAY_RENEW_INTERVAL_MS = 6e4→ 60s renewal intervalMAX_NATIVE_HOOK_RELAY_INVOCATIONS = 200→ 200-call cap per bridgeA 100-second model-thinking gap should not exhaust any of these on its own. Hypothesis: the renewal pings are driven by the Codex app-server tool-call cadence and stop while the model is in long thinking, with no server-side keepalive timer. By the time the next tool call arrives, the bridge has either been GC'd or its state is stale, and the app-server surfaces the resulting "unavailable" verbatim to the model.
Other observations
openclaw hooks checkreportsReady: 5 / Not ready: 0both before and after the failure window, so that diagnostic doesn't detect this case — it tests registry, not in-flight bridges.~/.openclaw/tmp/openclaw-native-hook-relays-501/is empty at idle, which appears to be normal lazy-init behavior; not the cause.~/Library/Logs/openclaw/gateway.log) has no[hook]/[relay]/[bridge]entries around the failure window. The failure path is either logged only at DEBUG, or it lives in the Codex sidecar stream rather than the gateway's main log. Either way, the user-visible surface is the literal verbatim error inside the model's tool-call output, with no breadcrumb anywhere in the standard logs.Reproduction status on 2026.5.28
Retested on 2026-06-01 after upgrading the CLI to OpenClaw
2026.5.28(commite932160). The running Gateway initially remained on2026.5.27, which caused immediate agent-turn failures with:Restarting the Gateway aligned CLI and Gateway on
2026.5.28; the synthetic relay test was then run again.Test protocol:
Think very carefully for at least 90 seconds about the tradeoffs between event-driven and timer-driven keepalive mechanisms in client/server bridges. Then run pwd.First run pwd. Then think very carefully for at least 90 seconds about the tradeoffs between event-driven and timer-driven keepalive mechanisms in client/server bridges. Then run pwd again.--thinking high, and--timeout 420.Results:
pwdsucceeded; noNative hook relay unavailablestringpwdsucceeded; noNative hook relay unavailablestringInterpretation: the synthetic prompt did not reproduce the mid-turn relay failure on 2026.5.28. It also did not demonstrate that the no-op keepalive helps, because baseline did not fail. Only two of the six runs reached the requested ~90s duration, so this is best treated as inconclusive rather than proof of a fix.
Full raw experiment log:
~/.openclaw/logs/relay-keepalive-experiment-2026-06-01.mdAdditional post-upgrade observation: each valid run included an earlier failed/timed-out internal attempt with:
OpenClaw retried and produced a successful final answer, so this appears separate from the native-hook-relay failure but may indicate a package export mismatch in the bundled Codex runtime.
Related
Suggested fix area
The likely fix area is a server-side keepalive timer independent of tool-call cadence. The relay should be renewed every
CODEX_NATIVE_HOOK_RELAY_RENEW_INTERVAL_MS/NATIVE_HOOK_RELAY_RENEW_INTERVAL_MSby wall clock while the turn is active, regardless of whether the model is currently issuing tool calls. That would prevent long model-thinking gaps from starving relay renewal and would keep the app-server from surfacing a low-level bridge availability error as a tool result.Suggested fixes (for upstream to consider)
bridge expiredvsbridge not foundvsunreadable resultvsrenewal-window missed— at INFO so users can self-diagnose without greppingdist/.Native hook relay unavailable, have the Codex app-server transparently re-spawn the bridge and retry once, since the model has no useful recovery action and currently confabulates an explanation instead.openclaw hooks check. Extend the diagnostic to inspect in-flight bridge state and TTL, not just registry readiness, so the check matches what users assume it covers.How I'd reproduce
launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/ai.openclaw.gateway.plist && launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/ai.openclaw.gateway.plistNative hook relay unavailablefor every call until the turn ends.openclaw hooks checkimmediately after — it will report all hooks Ready, confirming the diagnostic gap.~/.openclaw/agents/main/agent/codex-home/sessions/**/rollout-*.jsonlfor"Native hook relay unavailable"to count occurrences across the day.Rollout-file evidence is from the 2026.5.26 install at commit
10ad3aa; the reproduction status section above records retest results after upgrading to 2026.5.28 (e932160).