Skip to content

fix: normalize LLM tool requests#2142

Merged
yottahmd merged 3 commits into
mainfrom
codex/llm-tool-normalization
May 12, 2026
Merged

fix: normalize LLM tool requests#2142
yottahmd merged 3 commits into
mainfrom
codex/llm-tool-normalization

Conversation

@yottahmd
Copy link
Copy Markdown
Collaborator

@yottahmd yottahmd commented May 12, 2026

Summary

  • add shared LLM request normalization before provider calls
  • deduplicate tool definitions by name and disable provider-native web search when an explicit web_search tool is present
  • cover provider factory, retry, and request-normalization paths with regression tests

Root Cause

  • Agent and chat requests could expose both a configured web_search tool and provider-native web search under the same tool name, and duplicate tool names were not guarded before provider-specific request builders.

Testing

  • go test ./internal/llm/... ./internal/agent ./internal/runtime/builtin/agentstep ./internal/runtime/builtin/chat
  • git diff --check

Summary by CodeRabbit

  • Bug Fixes

    • Chat requests now normalize and deduplicate web-search tools and disable native web-search when an explicit web-search tool is present; normalization is applied before provider calls, retries, and streaming to ensure consistent behavior.
  • Tests

    • Added tests verifying request normalization across provider calls, retry logic, and streaming paths.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 12, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0147301e-0fd2-4c23-bd7d-abfab9f846e4

📥 Commits

Reviewing files that changed from the base of the PR and between 83867ef and b7a34db.

📒 Files selected for processing (2)
  • internal/llm/request.go
  • internal/llm/request_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • internal/llm/request.go
  • internal/llm/request_test.go

📝 Walkthrough

Walkthrough

Chat requests are normalized to prevent tool conflicts when both an explicit "web_search" tool and WebSearch.Enabled are set. Normalization deduplicates tools, deep-copies web search configuration, and disables WebSearch.Enabled upon tool collision. The normalization is applied at the provider factory level via a wrapper type, at retry boundaries, and in streaming executors.

Changes

Chat Request Normalization

Layer / File(s) Summary
Request normalization contract and helper functions
internal/llm/request.go
NormalizeChatRequest clones incoming requests, deduplicates tools by function name, deep-copies WebSearchRequest fields, and disables WebSearch.Enabled when an explicit "web_search" tool is present. Helper functions cloneWebSearchRequest, dedupeTools, and hasToolNamed provide reusable logic for defensive copying and tool inspection.
Provider wrapper and factory integration
internal/llm/request.go, internal/llm/provider.go
normalizedProvider wrapper type intercepts Chat and ChatStream method calls and applies NormalizeChatRequest to each request. NewProvider wraps the factory-created provider in normalizedProvider before returning to callers.
Anthropic provider updates to use canonical constants
internal/llm/providers/anthropic/anthropic.go
Anthropic provider defines anthropicWebSearchToolType constant for the native web search tool type and uses the canonical llm.WebSearchToolName when constructing the web search tool, aligning with provider-independent normalization.
Request normalization at retry and executor call sites
internal/llm/retry.go, internal/runtime/builtin/chat/executor.go
ChatWithRetry and runStreamForModel each call NormalizeChatRequest on the incoming request before proceeding with retry logic or streaming, ensuring normalization occurs at multiple entry points in the call stack.
Request normalization unit tests
internal/llm/request_test.go
TestNormalizeChatRequest validates tool deduplication, WebSearch.Enabled disabling on collision, mutation safety, and preservation of web search when no explicit tool exists. TestNewProviderNormalizesRequests registers a test provider and verifies normalization in both Chat and ChatStream. Test helpers testTool and normalizingTestProvider support test infrastructure.
Retry integration test for request normalization
internal/llm/retry_test.go
New TestChatWithRetry subtest verifies that ChatWithRetry normalizes the request (tool deduplication and WebSearch.Enabled disabled) before passing it to the provider, while confirming the original caller's request is not mutated.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix: normalize LLM tool requests' directly and clearly summarizes the main change: implementing request normalization for LLM tools.
Description check ✅ Passed The pull request description includes a Summary section listing key changes, a Root Cause section explaining the problem, and a Testing section with specific test commands, covering all required template sections.
Docstring Coverage ✅ Passed Docstring coverage is 81.82% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/llm-tool-normalization

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 12, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@yottahmd
Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 12, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@yottahmd yottahmd merged commit 53ed766 into main May 12, 2026
10 checks passed
@yottahmd yottahmd deleted the codex/llm-tool-normalization branch May 12, 2026 09:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant