Skip to content

feat(codex): support remote app-server plugins#94203

Merged
kevinlin-openai merged 7 commits into
openclaw:mainfrom
kevinslin:dev/kevinlin/codex-remote-app-server-plugin-topology
Jun 17, 2026
Merged

feat(codex): support remote app-server plugins#94203
kevinlin-openai merged 7 commits into
openclaw:mainfrom
kevinslin:dev/kevinlin/codex-remote-app-server-plugin-topology

Conversation

@kevinslin

@kevinslin kevinslin commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds remote Codex app-server support for native Codex plugin turns in OpenClaw.

This PR:

  • classifies Codex app-server connections as local-loopback or remote;
  • requires bearer-style auth for remote WebSocket app-servers;
  • captures Codex initialize runtime identity and uses it in app inventory cache keys and thread binding fingerprints;
  • rotates stale remote thread bindings when the remote runtime fingerprint changes;
  • supports optional appServer.remoteWorkspaceRoot projection so OpenClaw infers the local workspace root, preserves the current cwd suffix, and sends Codex only the final app-server cwd;
  • always installs or refreshes configured native Codex plugins through the connected app-server before exposing plugin-owned apps;
  • skips the initial app inventory wait when a configured plugin must first be installed;
  • refreshes app inventory by plugin-owned app IDs so remote app catalog pagination can stop once required plugin apps are found;
  • forces direct dynamic tool loading for remote app-server turns to avoid namespace wrapper schemas rejected by the current remote Codex app-server; and
  • updates focused tests and docs for config, activation, app cache keys, thread lifecycle, dynamic tools, startup, targeted app inventory refresh, and the remote app-server config surface.

Compatibility note

This PR intentionally treats non-loopback Codex app-server WebSocket URLs as remote:

  • remote WebSocket app-servers require identity-bearing auth through appServer.authToken or an Authorization header;
  • configured native Codex plugins are always activated with install-and-refresh behavior on the connected app-server;
  • operators should only point OpenClaw at remote app-servers trusted to accept OpenClaw-managed plugin installs and app inventory refreshes;
  • remoteWorkspaceRoot names only the remote app-server workspace root; OpenClaw derives the gateway-side root from the resolved OpenClaw workspace and fails closed if the effective cwd is outside that workspace.

The old appServer.remoteWorkspace.localRoot / remoteRoot object and the configurable appServer.remoteMutationPolicy key were removed from the current config shape. There is no backwards-compat shim in this PR.

Real behavior proof

  • Behavior addressed: Remote OpenClaw gateway profiles can query Google Calendar through a native Codex plugin when the Codex app-server is running on another machine. The live proof covered a remote app-server where Google Calendar started uninstalled and OpenClaw installed it through the install-and-refresh path.
  • Real environment tested: Local OpenClaw gateway profile devbox connected to remote Codex app-server wss://kbox8-oai-kevinlin-openclaw-codex.devbox-1.gateway.internal.api.openai.org.
  • Exact setup shape after the current config cleanup:
scripts/setup-gateway.py --apply --plugins google-calendar --ws-token-file /tmp/codex-ws-auth-token.txt --remote-workspace-root /home/oai/openclaw-workspaces
OPENCLAW_DISABLE_BONJOUR=1 OPENCLAW_SKIP_CHANNELS=1 ./openclaw.mjs --profile devbox gateway run --auth none --port 18789 --bind loopback --ws-log compact
./openclaw.mjs --profile devbox agent --session-key agent:codex:remote-gcal-install-refresh-20260618-proof-v3 --message "Use the Google Calendar plugin through the configured remote Codex app-server. What is my Google Calendar schedule tomorrow? For this run, tomorrow is Thursday, June 18, 2026 in America/Los_Angeles. Return the events with times, and say if there are no events." --timeout 900 --json
  • Evidence from the earlier live install-and-refresh proof:
baseline plugin/read: google-calendar@openai-curated installed=false enabled=false
runId: 502dc4b4-7eb1-42ec-84c5-4b38babe8ed4
status: ok
tool calls: codex_apps.google_calendar.search_events
tool failures: 0
post-run plugin/read: google-calendar@openai-curated installed=true enabled=true
date: 2026-06-18
timezone: America/Los_Angeles

Proof artifact:

.mem/main/proofs/demo-38-devbox-remote-google-calendar-install-refresh/proof.md
  • Observed result after fix: The gateway installed/enabled the remote Google Calendar plugin, completed the Calendar query, and returned the user's Thursday, June 18, 2026 schedule with no Google Calendar tool failures.
  • What was not tested: Full local PR gates were not run; focused tests/type/build and the live remote proof were run. The latest commits removed the remote mutation policy and old local-root workspace object after that live proof, so the proof command shown above reflects the cleaned current setup shape.
  • Proof limitations or environment constraints: The setup helper used for the live profile lives in the local OpenAI spec workspace, not this OpenClaw repository PR. The proof artifacts are local under .mem/main/proofs/... and are summarized in this PR body.
  • Before evidence: Before this follow-up, the install-and-refresh path could block before plugin/install because it waited for initial app inventory, then could block on later remote app/list pages even after the Google Calendar app appeared.

Earlier remote proof with preinstalled Google Calendar:

runId: 10e57e73-790a-4532-8ff2-98709941e732
status: ok
tool calls: memory_search, codex_apps.google_calendar.get_profile, codex_apps.google_calendar.search_events, codex_apps.google_calendar.batch_read_event
tool failures: 0
event count: 9
date: 2026-06-17
timezone: America/Los_Angeles
proof artifact: .mem/main/proofs/demo-37-devbox-remote-google-calendar/proof.md

Validation

Latest validation on e0b476d9ec9a6cb9e6cc5ae50752bf4caa664674:

node scripts/run-vitest.mjs run --config test/vitest/vitest.extension-codex.config.ts extensions/codex/src/app-server/config.test.ts extensions/codex/src/app-server/dynamic-tool-build.test.ts extensions/codex/src/app-server/plugin-app-cache-key.test.ts extensions/codex/src/app-server/thread-lifecycle.test.ts

Passed: 4 files, 220 tests.

node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.extensions.test.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/extensions-test.tsbuildinfo

Passed.

OPENCLAW_BUILD_ALL_NO_PNPM=1 node scripts/build-all.mjs cliStartup

Passed.

git diff --check

Passed in both the OpenClaw checkout and the local OpenAI spec workspace.

PYTHONPYCACHEPREFIX=/tmp/openclaw-spec-pycache python3 -m py_compile scripts/setup-gateway.py

Passed in the local OpenAI spec workspace for the setup helper.

pnpm docs:list

Blocked by internal npm registry auth while pnpm tried to fetch @opentelemetry/exporter-metrics-otlp-proto-0.219.0.tgz from socket-firewall-registry.gateway.unified-30.internal.api.openai.org: ERR_PNPM_FETCH_403, No authorization header was set for the request.

Earlier validation on this PR:

node scripts/run-vitest.mjs run --config test/vitest/vitest.extension-codex.config.ts extensions/codex/src/app-server/config.test.ts extensions/codex/src/app-server/plugin-activation.test.ts extensions/codex/src/app-server/plugin-thread-config.test.ts extensions/codex/src/app-server/plugin-app-cache-key.test.ts

Passed: 4 files, 129 tests.

node scripts/run-vitest.mjs run --config test/vitest/vitest.extension-codex.config.ts extensions/codex/src/app-server/attempt-diagnostics.test.ts

Passed: 1 file, 1 test.

node scripts/run-vitest.mjs run --config test/vitest/vitest.extension-codex.config.ts extensions/codex/src/app-server/schema-normalization-runtime-contract.test.ts

Passed: 1 file, 3 tests.

node scripts/run-vitest.mjs run --config test/vitest/vitest.extension-codex.config.ts extensions/codex/src/app-server/thread-lifecycle.binding.test.ts

Passed: 1 file, 41 tests.

uvx showboat verify /Users/kevinlin/code/openclaw/.mem/main/proofs/demo-37-devbox-remote-google-calendar/raw/showboat-summary.md

Passed.

@clawsweeper

clawsweeper Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Codex review: found issues before merge. Reviewed June 17, 2026, 3:36 PM ET / 19:36 UTC.

Summary
The PR adds remote Codex app-server plugin support, including remote connection classification, runtime identity cache/thread fingerprints, remote cwd projection, install-and-refresh plugin activation, targeted app inventory refresh, direct dynamic-tool loading for remote runtimes, focused tests, and docs.

PR surface: Source +330, Tests +375, Docs +15. Total +720 across 28 files.

Reproducibility: not applicable. this is a feature/config PR, not a bug report needing a current-main failing reproduction. The PR body includes after-fix live terminal proof for a remote Codex app-server Google Calendar run plus focused tests for the changed paths.

Review metrics: 2 noteworthy metrics.

  • Config/default surfaces: 1 appServer field added; non-loopback WebSocket auth tightened. The PR changes operator-visible Codex app-server setup and can affect existing remote WebSocket profiles during upgrade.
  • Release-owned changelog: 2 entries added. CHANGELOG.md is release-generated, so normal PR entries need removal before merge.

Stored data model
Persistent data-model change detected: persistent cache schema: extensions/codex/src/app-server/app-inventory-cache.test.ts, persistent cache schema: extensions/codex/src/app-server/attempt-startup.ts, persistent cache schema: extensions/codex/src/app-server/plugin-app-cache-key.test.ts, serialized state: extensions/codex/src/app-server/plugin-app-cache-key.ts, serialized state: extensions/codex/src/app-server/plugin-thread-config.test.ts, serialized state: extensions/codex/src/app-server/session-binding.ts. Confirm migration or upgrade compatibility proof before merge.

Merge readiness
Overall: 🦐 gold shrimp
Proof: 🦞 diamond lobster
Patch quality: 🦐 gold shrimp
Result: needs maintainer review before merge.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • Remove the two CHANGELOG.md entries from the PR branch.
  • Have a maintainer explicitly accept or revise the remote WebSocket auth and remote plugin install/refresh compatibility behavior.

Risk before merge

  • [P1] Merging changes existing non-loopback WebSocket app-server behavior by requiring identity-bearing auth and treating those runtimes as remote, so maintainers should explicitly accept the upgrade impact.
  • [P1] Configured native Codex plugins will install or refresh on the connected app-server; that operator-facing remote mutation behavior should be accepted as intentional before merge.

Maintainer options:

  1. Remove Changelog And Record Compatibility Acceptance (recommended)
    Remove the release-owned CHANGELOG.md edits and have a maintainer explicitly accept the remote auth, plugin install/refresh, and cwd projection behavior before merge.
  2. Preserve Existing WebSocket Upgrade Behavior
    If unauthenticated non-loopback WebSocket setups are considered supported, revise the branch to keep the old behavior by default and gate strict remote requirements behind an explicit migration or option.
  3. Pause Remote App-Server Mutation Direction
    If OpenClaw should not install or refresh plugins on remote Codex app-servers by default, pause this PR for a narrower product direction before landing.

Next step before merge

  • [P2] The remaining work combines one mechanical PR fix with maintainer compatibility/product acceptance, so it should stay in human review rather than an automated repair lane.

Security
Cleared: No new dependency, workflow, lockfile, package, or secret-handling surface was added; the remote auth and plugin-install behavior is a compatibility/product risk rather than a concrete security regression.

Review findings

  • [P2] Remove the unreleased changelog entries — CHANGELOG.md:18-19
Review details

Best possible solution:

Remove the normal-PR CHANGELOG.md edits, keep the release-note context in the PR/squash metadata, and merge only after maintainers accept the remote WebSocket auth and remote plugin install/refresh compatibility behavior.

Do we have a high-confidence way to reproduce the issue?

Not applicable: this is a feature/config PR, not a bug report needing a current-main failing reproduction. The PR body includes after-fix live terminal proof for a remote Codex app-server Google Calendar run plus focused tests for the changed paths.

Is this the best way to solve the issue?

No, not as submitted: the Codex plugin-owned implementation is a plausible maintainable path and matches inspected upstream Codex contracts, but normal PRs should not edit CHANGELOG.md and the remote compatibility behavior still needs maintainer acceptance.

Full review comments:

  • [P2] Remove the unreleased changelog entries — CHANGELOG.md:18-19
    CHANGELOG.md is release-owned in this repo, and normal PRs should keep release-note context in the PR body or squash message. Adding these NOT_IN_SPEC entries under the current release section would put unreleased PR-specific notes into the generated release surface and conflict with the release-generation flow.
    Confidence: 0.93

Overall correctness: patch is incorrect
Overall confidence: 0.88

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 3be74caeaec8.

Label changes

Label justifications:

  • P2: This is a normal-priority Codex remote-runtime feature with limited blast radius but real operator compatibility impact.
  • merge-risk: 🚨 compatibility: Existing non-loopback WebSocket app-server setups can fail closed without auth, and remote plugin install/refresh behavior changes operator expectations.
  • rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🦞 diamond lobster and patch quality is 🦐 gold shrimp.
  • status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Sufficient (terminal): The PR body includes after-fix terminal/live-output proof for a real remote Codex app-server Google Calendar run, including install-and-refresh from an initially uninstalled plugin and zero tool failures.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes after-fix terminal/live-output proof for a real remote Codex app-server Google Calendar run, including install-and-refresh from an initially uninstalled plugin and zero tool failures.
Evidence reviewed

PR surface:

Source +330, Tests +375, Docs +15. Total +720 across 28 files.

View PR surface stats
Area Files Added Removed Net
Source 14 370 40 +330
Tests 11 378 3 +375
Docs 3 15 0 +15
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 28 763 43 +720

What I checked:

Likely related people:

  • kevinslin: Introduced the native Codex plugin app support and later auto plugin approval behavior that this remote app-server plugin work extends. (role: feature owner; confidence: high; commits: a1ac559ed7e6, e82d19fb06b5; files: extensions/codex/src/app-server/plugin-thread-config.ts, extensions/codex/src/app-server/plugin-activation.ts, extensions/codex/src/app-server/config.ts)
  • vincentkoc: Recently changed the same Codex app-server config/runtime decision surface, including network proxy profiles and runtime ownership-adjacent behavior. (role: recent area contributor; confidence: high; commits: 5c3469549159, cf7850040e93; files: extensions/codex/src/app-server/config.ts, docs/plugins/codex-harness-reference.md)
  • steipete: Recently documented Codex plugin app configuration, which is the public docs surface this PR updates. (role: adjacent docs contributor; confidence: medium; commits: d99268ae514a; files: docs/plugins/codex-harness-reference.md, extensions/codex/src/app-server/plugin-thread-config.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@kevinslin
kevinslin marked this pull request as ready for review June 17, 2026 16:06

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 84b51c14bb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +1003 to +1008
const host = parsed.hostname.toLowerCase();
return (
host === "localhost" ||
host === "127.0.0.1" ||
host === "::1" ||
host.startsWith("127.")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Recognize IPv6 loopback WebSocket URLs

When a local app-server is configured as ws://[::1]:..., Node's URL.hostname is [::1], not ::1, so this check classifies IPv6 localhost as remote. The new remote-auth assertion then rejects an unauthenticated local loopback app-server or applies remote defaults to it, which breaks valid IPv6 localhost setups.

Useful? React with 👍 / 👎.

Comment on lines +612 to +616
const prefix = `${localRoot}/`;
if (!value.startsWith(prefix)) {
return value;
}
return `${remoteRoot}/${value.slice(prefix.length)}`;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Normalize Windows separators before remote workspace mapping

On a Windows gateway, child paths under localRoot use backslashes, but the remote workspace mapper only tests for a / suffix prefix. In that environment only the exact root maps; a cwd such as C:\repo\pkg falls through unchanged and is sent to the remote Codex app-server, which cannot resolve that local Windows path.

Useful? React with 👍 / 👎.

Comment thread extensions/codex/openclaw.plugin.json Outdated
Comment on lines +179 to +182
"properties": {
"localRoot": { "type": "string" },
"remoteRoot": { "type": "string" }
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Require both remote workspace roots in the manifest

The runtime schema requires both remoteWorkspace.localRoot and remoteWorkspace.remoteRoot, and readCodexPluginConfig drops the whole Codex plugin config when the zod parse fails. Because this manifest schema allows { remoteWorkspace: {} } or only one side, manifest-driven validation/setup can accept a config that the runtime silently ignores instead of reporting the missing paired root.

Useful? React with 👍 / 👎.

@kevinslin
kevinslin force-pushed the dev/kevinlin/codex-remote-app-server-plugin-topology branch from 84b51c1 to f94e771 Compare June 17, 2026 16:41
@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. labels Jun 17, 2026
@openclaw-barnacle openclaw-barnacle Bot added the docs Improvements or additions to documentation label Jun 17, 2026
@kevinlin-openai

Copy link
Copy Markdown
Contributor

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@kevinslin
kevinslin force-pushed the dev/kevinlin/codex-remote-app-server-plugin-topology branch from 95fef08 to b09894b Compare June 17, 2026 20:23
@kevinlin-openai
kevinlin-openai merged commit bc5081c into openclaw:main Jun 17, 2026
159 checks passed
crh-code pushed a commit to crh-code/openclaw that referenced this pull request Jun 18, 2026
* feat(codex): support remote app-server plugins

* fix(codex): refresh remote plugin apps after install

* fix(codex): infer remote app-server topology

* docs(codex): document remote app-server plugin config

* fix(codex): remove remote mutation policy

* fix(codex): simplify remote workspace root

* docs(codex): fix remote app-server PR docs
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jun 18, 2026
* feat(codex): support remote app-server plugins

* fix(codex): refresh remote plugin apps after install

* fix(codex): infer remote app-server topology

* docs(codex): document remote app-server plugin config

* fix(codex): remove remote mutation policy

* fix(codex): simplify remote workspace root

* docs(codex): fix remote app-server PR docs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Improvements or additions to documentation extensions: codex maintainer Maintainer-authored PR merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. size: L status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants