feat(gateway): wire coding tools into /tools/invoke HTTP surface#63919
feat(gateway): wire coding tools into /tools/invoke HTTP surface#63919simonusa wants to merge 2 commits intoopenclaw:mainfrom
Conversation
Greptile SummaryThis PR completes the wiring of Confidence Score: 5/5Safe to merge — previous review concerns are addressed and no new P0/P1 issues remain. Both prior concerns (MCP loopback exposure and duplicate agentId resolution) are fixed. The surface === 'http' guard is correct, dedup logic is sound, and all 24 tests pass. All remaining considerations are P2 or lower. No files require special attention.
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b73a50ce84
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
b73a50c to
7cdd9b1
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7cdd9b1ad8
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
7cdd9b1 to
ffed1db
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ffed1dbccd
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
check-additional failure is pre-existing upstream lint debt unrelated to this PR: lint:tmp:no-random-messaging — os.tmpdir() usage in extensions/active-memory, browser, memory-core, etc. (being addressed by #63902) |
|
Codex review: needs maintainer review before merge. Summary Reproducibility: yes. Source inspection on current main shows the Gateway resolver only materializes createOpenClawTools, so a direct invoke request for a coding primitive such as read has no core coding tool to resolve. Next step before merge Security Review detailsBest possible solution: Land this after maintainer sign-off and a green targeted Gateway/Testbox changed gate, with explicit confirmation that the shared HTTP/RPC direct-invoke behavior and docs scope are intended. Do we have a high-confidence way to reproduce the issue? Yes. Source inspection on current main shows the Gateway resolver only materializes createOpenClawTools, so a direct invoke request for a coding primitive such as read has no core coding tool to resolve. Is this the best way to solve the issue? Yes for the code shape, subject to maintainer approval. The patch reuses the existing resolver, policy, hook, owner, and deny-list pipeline; gates coding-tool construction away from loopback; and avoids plugin/provider-gated tool re-entry in the raw factory. Acceptance criteria:
What I checked:
Likely related people:
Remaining risk / open question:
Codex review notes: model gpt-5.5, reasoning high; reviewed against a3f6f24b79a5. |
ffed1db to
2239686
Compare
|
Pivoted to Option A per the clawsweeper review — coding tools are now constructed via a new Rationale: Implementation (~170 lines, 4 files):
Tests cover the bot's specific concerns:
Local test results: 90/90 pass on Force-pushed |
214f5b5 to
1520271
Compare
|
Addressed all 3 clawsweeper review findings (force-pushed). [P1] Canonical mutating tools added to default HTTP deny list [P2] Coding-tool construction gated to [P2] Unwrap path replaced with explicit skip flag New regression tests:
Test results: 156/156 pass across Net diff: 5 files, +202 / -16 lines. Re-review progress:
|
|
Friendly ping — this PR has been ready for review for a few days now:
@steipete — flagging you since you've recently maintained the gateway tool-resolution and tools-invoke surfaces (e.g. Happy to address any further feedback. Thanks! |
1520271 to
2ae9e0f
Compare
2ae9e0f to
ccbe3cb
Compare
ccbe3cb to
91fbb47
Compare
|
Addressed all clawsweeper review findings; current head is [P2] Plugin suppression — Added [P2] Provider-gated tools — Added [P3] Docs + changelog — Updated Local tests on the private fork: 99/99 in |
91fbb47 to
cb8229d
Compare
… raw coding factory Address bot review on PR openclaw#63919: [P2] Plugin suppression bypass — `createOpenClawCodingToolsRaw()` previously delegated to the full coding factory which unconditionally appended `createOpenClawTools(...)` and `listChannelAgentTools(...)`. The resolver explicitly requests core-only resolution for known core tool requests (`disablePluginTools: true`), but that intent was lost — a "core-only" HTTP request could still re-enter plugin resolution via the coding factory. Added `disablePluginTools` flag to `createOpenClawCodingTools` options that skips both plugin spreads. Raw factory always sets it. Independent of the existing `includeCoreTools` flag — keeps core coding tools materialized, only suppresses plugin loading. [P2] Provider-gated tools without context — `apply_patch` is provider-gated to OpenAI-family models. The /tools/invoke HTTP surface has no session-bound model context, so allowlisting `apply_patch` would silently produce nothing (resolver reports tool unavailable). Added `excludeProviderGatedTools` flag that drops provider-gated tools at construction time. Raw factory always sets it. Documented in tools-invoke HTTP API docs that `apply_patch` is no longer materializable via this surface even if allowlisted. [P3] Docs + changelog — updated `docs/gateway/tools-invoke-http-api.md` to reflect the new default deny entries (`process`, `write`, `edit`) and added a "Coding tools available via HTTP" section. Added Unreleased changelog entry describing the new feature and contract. Local tests: 99/99 in tools-invoke-http suites pass on private fork (legacy fork has pre-existing typebox dep issue unrelated to this change).
cb8229d to
d5393cf
Compare
…tory Coding tools (exec, edit, read, browser, apply_patch) were never wired into resolveGatewayScopedTools, so /tools/invoke could not reach them even when gateway.tools.allow named them. The DEFAULT_GATEWAY_HTTP_TOOL_DENY list already anticipated these tool names — the resolver just had nothing to gate. This wires them in via a new createOpenClawCodingToolsRaw factory that returns the same tool set as createOpenClawCodingTools but WITHOUT wrapToolWithBeforeToolCallHook applied. handleToolsInvokeHttpRequest already calls runBeforeToolCallHook itself before dispatch; routing hook-wrapped tools through that path would double-fire the hook and leak adjusted-params state (the wrapper stashes adjusted params keyed by toolCallId; only the agent subscribe path drains them via consumeAdjustedParamsForToolCall). Implementation: - pi-tools.before-tool-call.ts: new BEFORE_TOOL_CALL_ORIGINAL_TOOL symbol stored on wrapped tools + unwrapToolBeforeToolCallHook() helper. - pi-tools.ts: new createOpenClawCodingToolsRaw() — calls existing factory, unwraps each tool. ~5 lines, no logic duplication. - tool-resolution.ts: import the raw factory, build coding tools alongside gateway tools, dedup with gateway tools taking precedence on name clash. surface === "http" loopback guard preserved. - tools-invoke-http.test.ts: 5 new regression tests — coding tool reachable when allowlisted, single before_tool_call fire, no adjusted-params leak, deny-list still blocks, loopback non-expansion preserved. Tests: 90/90 pass (85 pre-existing + 5 new). Typecheck: clean (errors in unrelated UI/optional-dep files only). Lint: clean (errors in unrelated Discord/Slack files only). Addresses openclaw#37131 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… raw coding factory Address bot review on PR openclaw#63919: [P2] Plugin suppression bypass — `createOpenClawCodingToolsRaw()` previously delegated to the full coding factory which unconditionally appended `createOpenClawTools(...)` and `listChannelAgentTools(...)`. The resolver explicitly requests core-only resolution for known core tool requests (`disablePluginTools: true`), but that intent was lost — a "core-only" HTTP request could still re-enter plugin resolution via the coding factory. Added `disablePluginTools` flag to `createOpenClawCodingTools` options that skips both plugin spreads. Raw factory always sets it. Independent of the existing `includeCoreTools` flag — keeps core coding tools materialized, only suppresses plugin loading. [P2] Provider-gated tools without context — `apply_patch` is provider-gated to OpenAI-family models. The /tools/invoke HTTP surface has no session-bound model context, so allowlisting `apply_patch` would silently produce nothing (resolver reports tool unavailable). Added `excludeProviderGatedTools` flag that drops provider-gated tools at construction time. Raw factory always sets it. Documented in tools-invoke HTTP API docs that `apply_patch` is no longer materializable via this surface even if allowlisted. [P3] Docs + changelog — updated `docs/gateway/tools-invoke-http-api.md` to reflect the new default deny entries (`process`, `write`, `edit`) and added a "Coding tools available via HTTP" section. Added Unreleased changelog entry describing the new feature and contract. Local tests: 99/99 in tools-invoke-http suites pass on private fork (legacy fork has pre-existing typebox dep issue unrelated to this change).
d5393cf to
427c102
Compare
|
Rebased onto current @steipete — bot lists you as primary reviewer; the only remaining gate per its summary is maintainer approval for exposing core coding primitives over authenticated HTTP. Concrete question: is the proposed surface acceptable in principle?
The PR is complete as-is and ready to merge if the answer is yes. If |
Summary
resolveGatewayScopedToolsonly includedcreateOpenClawTools(gateway management tools);createOpenClawCodingTools(exec, edit, read, browser, etc.) was never wired inexecas blocked by the HTTP deny list by default — implying the intent was always for coding tools to be available on this surface, gated bygateway.tools.allowPOST /tools/invoke, subject to the existing deny list and policy pipelineRoot Cause
The deny list in
DEFAULT_GATEWAY_HTTP_TOOL_DENYalready includedexec,spawn,apply_patch, etc. — designed to gate exactly these tools on the HTTP surface. ButcreateOpenClawCodingToolswas never passed toresolveGatewayScopedTools, so the deny list had nothing to gate: coding tools simply weren't present at all. The docs described the intended behavior; the implementation was incomplete.What did NOT change
execand other high-risk tools remain onDEFAULT_GATEWAY_HTTP_TOOL_DENY— blocked by default, require explicitgateway.tools.allowto enableapplyToolPolicyPipeline+ deny-list as all other toolsRegression Test Plan
createOpenClawCodingToolsstub to thevi.mock("../agents/pi-tools.js")block intools-invoke-http.test.ts— without this, all 22 existing tests failed with 500s (undefined function crash)exposes coding tools via /tools/invoke when agent policy allows them— verifies a coding tool passes through policy + deny-list filtering and is callable via the HTTP surfaceEvidence
Production motivation: a LangGraph orchestrator running ruff/bandit/tsc/npm via
/tools/invokein an OpenClaw container — eliminates ~240s LLM agent startup overhead per deterministic command call where no model reasoning is needed.Human Verification
npx vitest run src/gateway/tools-invoke-http.test.ts— 24/24 pass on a clean branch based onupstream/mainRelationship to existing PRs
fix(gateway): deny nodes over HTTP tools invoke) — orthogonal: restricts the surface; this PR expands it. Both coexist.fix(gateway): enforce owner-only tools in invoke API) — orthogonal: enforces owner-only policy. Our change passessenderIsOwner: truefor HTTP bearer auth, consistent with that direction.Risks and Mitigations
execviagateway.tools.allowwithout understanding the RCE surfaceMitigation:
execis onDEFAULT_GATEWAY_HTTP_TOOL_DENY— explicit opt-in required; no behavior change for default installsMitigation: gateway and coding tool names are disjoint in practice; merge order is documented in the code comment
Addresses #37131