feat(claude): opt-in ENABLE_TOOL_SEARCH injection for launched Claude Code sessions - #5029
Conversation
… Code sessions Claude Code turns MCP tool deferral off whenever ANTHROPIC_BASE_URL names a non-first-party host, keyed on the host rather than the model, so every ocx claude session inlines all MCP tool schemas. Add claudeCode.toolSearch, injected as ENABLE_TOOL_SEARCH by the three launch surfaces that already carry the other Claude Code levers, with user-wins semantics throughout. Default off. Deferral is a server-side optimisation, not a smaller request: deferred tools still carry input_schema on the wire, and Anthropic's API is what keeps their schemas out of the model context and answers the tool_search server tool. A translated route never reaches that machinery, so enabling it there leaves the provider holding every schema while Claude Code stops accounting for them. Closes #4838
|
Warning Review limit reachedNext included review available in 7 seconds. View limit detailsLimit details: You’ve used all 10 included reviews currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Advanced Run ID: 📒 Files selected for processing (14)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
✅ Deterministic PR hygiene checks passed. |
리뷰 · 우선순위 76 / 80지금 그런데 이슈가 원한 “기본 ON / 무조건 주입”은 지금 구현은 세 주입면이 같은 헬퍼를 쓴다. 라인 - 이게 무슨 문제다 tests/claude-integration/claude-cli.test.ts (toolSearch: "auto:25") - PR 본문·영문 가이드·헬퍼 주석은 Claude Code 파서가 N을 최소 100으로 거부한다고 적혀 있다. 와이어에 그대로 넣는 동작 검증이라면 통과하지만, 픽스처 값이 문서의 유효 어휘와 어긋나서 “opencodex가 auto:25를 정상으로 취급한다”처럼 읽힐 수 있다. docs-site 번역 가이드(표 행만 추가) - 영문만 “번역 경로에선 켜면 스키마는 그대로·compact만 멈춘다 / enforce면 400” 경고가 있다. 비영문 사용자는 표만 보고 src/server/management/agent-settings-routes.ts - 본문 타입에 src/claude/context-windows.ts gui/ · Dashboard - 메인테이너의 판단이 필요한 지점
너의 추천 이 댓글은 grok-bot이 작성했습니다 |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6d810da8a7
ℹ️ 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".
| * inject nothing — they do not force the variable off, because a value the | ||
| * operator exported themselves always wins. | ||
| */ | ||
| toolSearch?: boolean | string; |
There was a problem hiding this comment.
Update the structure owners for the new config lever
This adds a persisted claudeCode setting and changes the Claude CLI and server environment-injection contracts, but the commit updates none of the applicable documents mapped by structure/INDEX.md (including runtime.md, config.md, and the client-integration owners). Update the owned structure documentation in the same change so the maintainer-facing source of truth describes toolSearch and its three injection surfaces.
AGENTS.md reference: src/AGENTS.md:L10-L11
Useful? React with 👍 / 👎.
| const toolSearch = claudeToolSearchEnv(config.claudeCode?.toolSearch); | ||
| if (toolSearch !== undefined) injectLever("ENABLE_TOOL_SEARCH", toolSearch); |
There was a problem hiding this comment.
Reconcile owned launchctl values when toolSearch changes
On macOS with claudeCode.systemEnv enabled, once opencodex has injected and tracked ENABLE_TOOL_SEARCH, a later injectSystemEnv call sees the existing launchctl value and injectLever treats it as user-owned. Consequently changing toolSearch from true to "auto:N", false, or unset leaves the old value active indefinitely; this also occurs when a tracking record survives a crash/reapply. Recognize tracked keys as opencodex-owned, update or unset this key according to the new config, remove it from injectedKeys when disabled, and cover the transition in tests/server/system-env.test.ts rather than only testing buildClaudeEnv.
AGENTS.md reference: AGENTS.md:L376-L379
Useful? React with 👍 / 👎.
|
Approving the judgement call, and recording why, because this PR does not do what its issue asked for and that is the right outcome. The issue asked for That is a failure mode worse than the reported one, and it would have been indistinguishable from a proxy bug to the person who asked for it. Two details in the investigation are worth keeping. Establishing the gate from the installed Claude Code binary rather than from documentation is what produced the accepted value set ( Keeping the lever out of |
|
Merging with macOS legs outstanding, and recording why rather than leaving it implicit. At this exact head the full Linux suite (test 1/4 through 4/4), This change is platform-neutral, so waiting on a queue that is both saturated and known-unreliable would delay the work without adding information. The evidence that governs the release is not per-PR macOS legs; it is the full-platform Stating the boundary plainly: this is merged on Linux, gates and cross-platform smoke evidence at its exact head, with macOS coverage deferred to the candidate run rather than claimed here. |
Summary
ocx claudenow supportsclaudeCode.toolSearch, injected asENABLE_TOOL_SEARCHinto the launched Claude Code environment. It is opt-in and off by default, which is a deliberate departure from the issue's request — the evidence below is why.The reported problem is real and the named variable is the right lever. Claude Code 2.1.273 disables MCP tool deferral on a non-first-party
ANTHROPIC_BASE_URL, keyed on the host rather than the model, so it hits everyocx claudesession. Its own diagnostic states both the gate and the precondition for lifting it:and its settings documentation:
We do not forward those blocks on a translated route, so injecting it unconditionally would not do what it appears to do. Deferral is a server-side context optimisation, not a smaller request. Claude Code's own deferred-tool predicate requires
input_schemato still be present alongsidedefer_loading: true, so every schema stays on the wire and it is Anthropic's API that keeps them out of the model's context and answers thetool_searchserver tool withtool_referenceblocks. On the translated path:src/claude/inbound-content-options.tstoolsToResponsesconverts any tool carryinginput_schemainto a full Responses function tool and ignoresdefer_loadingentirely; thetool_search_tool_*server tool falls through to the drop branch.src/claude/compatibility.tsliststool_search,tool_referenceanddeferred_toolsin the table whosetrueentries mean unsupported —compatibleis computed as!FEATURE_CODES.some(code => detected.has(code) && FEATURES[code]). The issue reads that table as declaring support; it declares the opposite.So on a routed non-Anthropic model the provider would still receive all 292 schemas, while Claude Code would believe its context was nearly empty and stop compacting — trading a session that compacts often for one that overruns the provider window. An operator who has set
claudeCode.compatibility: "enforce"gets a hard 400 on every request instead. On the native Anthropic passthrough route the body reaches Anthropic untouched and the feature works exactly as reported.Shipping it as a documented, upgrade-safe switch gives the reporter their shell alias as first-class configuration today, and keeps the default honest until translated deferral is actually implemented.
Behaviour:
claudeCode.toolSearch: trueinjects"true"; a string is passed through verbatim so Claude Code's own vocabulary (auto,auto:N,force) stays reachable.false, absent and blank inject nothing rather than injecting"false", which would be the one path that could disagree with an operator's own export.ENABLE_TOOL_SEARCHalways wins:setDefaultinocx claude,injectLeverin the launchd system env, and a conditional export in the shell env file.ENABLE_TOOL_SEARCHis deliberately not added toNATIVE_STRIPPED_LEVERS, and the list now carries a comment saying why: it is the only one of those levers whose value is meaningful to a native session, where the base URL is first-party and the variable is the user's own tuning knob.Out of scope, deliberately: no Dashboard control (
gui/src/pages/claude-manual-env.tsuntouched, so this PR changes nogui/file), and no management-API field.PUT /api/claude-codebuilds its next block with{ ...(config.claudeCode ?? {}) }, so a hand-written key survives a Dashboard save.Verification
ocxbinary, because an earlier local run deleted a real~/.opencodexdirectory. Hosted CI on Linux, Windows and macOS is the verification path for this change.src/claude/context-windows.tsnext toresolveAutoContext, which all three call sites already import, so no server-to-cli import edge is introduced.deleteUntrustedAnthropicSlotsonly touchesANTHROPIC_PARENT_ENV_SLOTS, so an inheritedENABLE_TOOL_SEARCHreachessetDefaultintact.auto/auto:N/forceparser, the deferred-tool predicate requiringinput_schema, and thetool-search-tool-2025-10-19beta value were all read out of it.tests/claude-integration/claude-cli.test.ts> "ocx claude tool-search deferral (ocx claudeshould setENABLE_TOOL_SEARCH=true: Claude Code disables MCP tool deferral behind a non-Anthropic base URL, so every tool schema ships in full #4838)": default-off, the three accepted value forms, the false/blank/absent cases, the operator-export-wins case, and the native-fallback case asserting this lever survives whileCLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERYis shed. That file is 803 lines and carries notests/fixtures/file-size-baseline.jsonentry, so the ratchet is not involved.Closes #4838
Checklist