Skip to content

feat: add Amazon Bedrock AgentCore Web Search as a native search provider - #34098

Closed
CrypticDriver wants to merge 5 commits into
BerriAI:litellm_oss_daily_2026_07_20from
CrypticDriver:agentcore-search-provider
Closed

feat: add Amazon Bedrock AgentCore Web Search as a native search provider#34098
CrypticDriver wants to merge 5 commits into
BerriAI:litellm_oss_daily_2026_07_20from
CrypticDriver:agentcore-search-provider

Conversation

@CrypticDriver

@CrypticDriver CrypticDriver commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Relevant issues

Fixes #31819

Enables Anthropic-native web_search (and the Claude Code WebSearch tutorial flow) for Bedrock users with an all-AWS search backend — related to the provider matrix in docs/my-website/docs/search/index.md and docs/my-website/docs/tutorials/claude_code_websearch.md.

Pre-Submission checklist

Please complete all items before asking a LiteLLM maintainer to review your PR

  • I have added meaningful tests
  • My PR passes all CI/CD checks (e.g., lint, format, unit tests)
  • My PR's scope is as isolated as possible; it only solves 1 specific problem
  • I have received a Greptile Confidence Score of at least 4/5 before requesting a maintainer review (Greptile reviews automatically once the PR is opened; only comment @greptileai to re-request a review after pushing changes)

Screenshots / Proof of Fix

All proofs are fully e2e against a real AgentCore Gateway (websearchgateway-*.gateway.bedrock-agentcore.us-east-1.amazonaws.com/mcp with a web-search connector target) and real Bedrock Claude calls. Captured at commit 6fef231f.

1. Direct litellm.search() (real gateway, SigV4):

$ python -c "import litellm; resp = litellm.search(query='python 3.13 release date', search_provider='agentcore', max_results=3); ..."
- What's New In Python 3.13 — documentación de Python | https://docs.python.org/es/3.15/whatsnew/3.13.html
- Python Release Python 3.13.3 | https://python.org/downloads/release/python-3133/
- wikipedia.org | https://wikipedia.org

2. Claude Code request shape through the proxy (web_search_20250305 + forced tool_choice, websearch_interception + this provider, Bedrock Claude Sonnet):

$ curl http://localhost:4000/v1/messages ... -d '{"model": "claude-sonnet", "tools": [{"type": "web_search_20250305", "name": "web_search", "max_uses": 8}], "tool_choice": {"type": "tool", "name": "web_search"}, ...}'
content block types: ['web_search_tool_result', 'tool_use']
- What's New In Python 3.13 — documentación de Python | https://docs.python.org/es/3.15/whatsnew/3.13.html
- Python Release Python 3.13.3 | https://python.org/downloads/release/python-3133/
- Python Release Python 3.13.1 | https://www.python.org/downloads/release/python-3131/

3. Real Claude Code CLI end-to-end (ANTHROPIC_BASE_URL → proxy → Bedrock, WebSearch executed by this provider; zero client-side config):

$ ANTHROPIC_BASE_URL=http://localhost:4000 claude -p "Use the WebSearch tool to find the release date of Python 3.13..." --allowedTools WebSearch
Sources:
- [Python 3.13.0 (final) released](https://blog.python.org/2024/10/python-3130-final-released)
- [PEP 719 – Python 3.13 Release Schedule](https://peps.python.org/pep-0719/)

Bearer-token mode was additionally verified against a real CUSTOM_JWT gateway (Cognito client_credentials token) with AWS ambient credentials deliberately removed, including a full Claude Code CLI round-trip.

Unit tests:

$ pytest tests/search_tests/test_agentcore_search.py -q
13 passed
$ pytest tests/search_tests/test_tavily_search.py test_brave_search.py test_searxng_search.py -q   # regression for shared handler change
20 passed, 3 skipped

Type

🆕 New Feature

Changes

Adds Amazon Bedrock AgentCore Web Search (search_provider: agentcore) as a native search provider. Web Search on AgentCore is an AWS-managed web index (GA June 2026) exposed as an MCP tool on an AgentCore Gateway — no third-party search API or key, and queries never leave AWS.

Combined with websearch_interception, this gives Bedrock users a pure-YAML way to make Claude Code / Anthropic-native web_search_20250305 work:

search_tools:
  - search_tool_name: agentcore-search
    litellm_params:
      search_provider: agentcore
      api_base: https://<gateway-id>.gateway.bedrock-agentcore.us-east-1.amazonaws.com/mcp
      # MCP tool name is "<target-name>___WebSearch". Defaults to
      # "web-search-tool___WebSearch" (the target name used in the AWS docs'
      # boto3/CLI examples). Set this when your gateway target has a different
      # name, e.g. created via the agentcore CLI:
      # tool_name: MyWebSearchTarget___WebSearch
      # AWS_IAM gateway: explicit keys, or omit to use the default credential chain
      aws_access_key_id: os.environ/AWS_ACCESS_KEY_ID
      aws_secret_access_key: os.environ/AWS_SECRET_ACCESS_KEY
      # CUSTOM_JWT gateway alternative: api_key: os.environ/AGENTCORE_GATEWAY_TOKEN

litellm_settings:
  callbacks: ["websearch_interception"]
  websearch_interception_params:
    enabled_providers: ["bedrock"]
    search_tool_name: agentcore-search
  • AgentCoreSearchConfig (litellm/llms/bedrock/search/transformation.py): BaseSearchConfig + BaseAWSLLM. Transforms the unified search request into an MCP tools/call, parses plain-JSON and SSE-framed MCP responses into SearchResponse, propagates MCP errors, truncates queries to the 200-char gateway limit. Auth follows the gateway's inbound authorizer: SigV4 (bedrock-agentcore service; signing region auto-derived from the gateway URL) or OAuth2 bearer token (api_key / AGENTCORE_GATEWAY_TOKEN).
  • BaseSearchConfig.sign_request() (new optional hook, no-op by default): mirrors the existing sign_request pattern in anthropic_messages/chat. The search HTTP handler (sync + async) sends a signed body verbatim when present — re-serializing would invalidate the signature. No behavior change for the 17 existing search providers (regression suite passing above).
  • Registers SearchProviders.AGENTCORE + config-map entry.
  • 13 unit tests in tests/search_tests/test_agentcore_search.py.

Notes / known limitations

  • tool_name: the gateway exposes the connector as <target-name>___WebSearch, where <target-name> is chosen by the user at target creation. The default (web-search-tool___WebSearch) matches the AWS documentation's boto3/CLI setup examples; targets created with other names need tool_name set explicitly (misconfiguration surfaces as a propagated MCP "tool not found" error, not a silent failure). Auto-discovery via tools/list was considered and deliberately left out: a gateway can legitimately host multiple *___WebSearch targets (e.g. with different domain-filter policies), and silently picking one would be worse than an explicit config error.
  • Admin UI: the search-tool create form currently has no api_base field, so UI-driven setup requires the AGENTCORE_GATEWAY_URL env var on the proxy; config.yaml setup (above) is unaffected. Adding the field to the form is a UI-side follow-up that would also benefit other self-hosted providers (e.g. searxng).

@CLAassistant

CLAassistant commented Jul 21, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@greptile-apps

greptile-apps Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds Amazon Bedrock AgentCore as a native web search provider. The main changes are:

  • MCP request and response transformation for AgentCore Web Search
  • SigV4 and bearer-token authentication with gateway host checks
  • A shared search-request signing hook for sync and async HTTP calls
  • Provider registration, example proxy configuration, and focused tests

Confidence Score: 5/5

This looks safe to merge.

  • The updated authentication path keeps server credentials on the configured gateway host.
  • SigV4 signing no longer falls back to a Bedrock Runtime token.
  • Custom gateway hosts use explicit or shared AWS region configuration.
  • SSE responses handle multiline data and progress events before the final result.
  • No blocking issue remains in the changed code.

Important Files Changed

Filename Overview
litellm/llms/bedrock/search/transformation.py Adds AgentCore MCP transformation, authentication, signing-region resolution, and JSON or SSE response parsing.
litellm/llms/base_llm/search/transformation.py Adds an optional no-op request-signing contract for search providers.
litellm/llms/custom_httpx/llm_http_handler.py Calls the provider signing hook and preserves signed request bodies in sync and async search paths.
litellm/types/utils.py Adds the AgentCore search provider enum value.
litellm/utils.py Registers AgentCore with the existing search provider configuration manager.
tests/search_tests/test_agentcore_search.py Covers request transformation, authentication boundaries, signing regions, signed transport, and MCP response parsing.

Reviews (3): Last reviewed commit: "fix: honor AWS shared-config region for ..." | Re-trigger Greptile

Comment thread litellm/llms/bedrock/search/transformation.py
Comment thread litellm/llms/bedrock/search/transformation.py Outdated
Comment thread litellm/llms/bedrock/search/transformation.py
Comment thread litellm/llms/bedrock/search/transformation.py Outdated
Comment thread litellm/llms/bedrock/search/transformation.py Outdated
@veria-ai

veria-ai Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

PR overview

All previously flagged issues have been addressed. No open security concerns remain on this pull request.

Security review

No open security issues remain on this pull request.

Fixed/addressed: 2 · PR risk: 0/10

@codecov

codecov Bot commented Jul 21, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.26087% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
litellm/llms/bedrock/search/transformation.py 99.01% 1 Missing ⚠️
litellm/llms/custom_httpx/llm_http_handler.py 83.33% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!


import httpx

from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj
import httpx

from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj
from litellm.llms.base_llm.chat.transformation import BaseLLMException
Comment on lines +42 to +46
from litellm.llms.base_llm.search.transformation import (
BaseSearchConfig,
SearchResponse,
SearchResult,
)
SearchResponse,
SearchResult,
)
from litellm.llms.bedrock.base_aws_llm import BaseAWSLLM
SearchResult,
)
from litellm.llms.bedrock.base_aws_llm import BaseAWSLLM
from litellm.llms.bedrock.common_utils import BedrockError
)
from litellm.llms.bedrock.base_aws_llm import BaseAWSLLM
from litellm.llms.bedrock.common_utils import BedrockError
from litellm.secret_managers.main import get_secret_str
Comment thread litellm/utils.py
from litellm.llms.apiserpent.search.transformation import (
APISerpentSearchConfig,
)
from litellm.llms.bedrock.search.transformation import AgentCoreSearchConfig
@codspeed-hq

codspeed-hq Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 31 untouched benchmarks


Comparing CrypticDriver:agentcore-search-provider (789e2ba) with main (5d4c4d0)1

Open in CodSpeed

Footnotes

  1. No successful run was found on litellm_oss_daily_2026_07_20 (5d4c4d0) during the generation of this report, so main (5d4c4d0) was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@CrypticDriver
CrypticDriver force-pushed the agentcore-search-provider branch from 6fef231 to 789e2ba Compare July 21, 2026 11:59
@CrypticDriver
CrypticDriver changed the base branch from main to litellm_oss_daily_2026_07_20 July 21, 2026 11:59
@CrypticDriver
CrypticDriver force-pushed the agentcore-search-provider branch 2 times, most recently from c5616c7 to bf7e2c2 Compare July 21, 2026 12:11
Comment thread litellm/llms/bedrock/search/transformation.py
@CrypticDriver
CrypticDriver force-pushed the agentcore-search-provider branch 4 times, most recently from df3e1b0 to 563b392 Compare July 21, 2026 15:29
…ider

Adds 'agentcore' to SearchProviders, backed by an AgentCore Gateway
web-search connector target (MCP tools/call over Streamable HTTP).

Web Search on Amazon Bedrock AgentCore is an AWS-managed web index
(GA June 2026). Exposing it as a native search provider lets Bedrock
users enable Claude Code / Anthropic-native WebSearch through
websearch_interception with a pure-YAML config and AWS-native auth,
keeping the whole search path inside AWS.

Implementation:
- New AgentCoreSearchConfig (litellm/llms/bedrock/search/) reusing
  BaseAWSLLM credential resolution. Auth follows the gateway's inbound
  authorizer type: AWS_IAM gateways get a SigV4-signed request
  (explicit aws_access_key_id/aws_secret_access_key params or the
  default credential chain); CUSTOM_JWT gateways get an OAuth2 bearer
  token via api_key / AGENTCORE_GATEWAY_TOKEN
- SigV4 signing region is derived from the gateway URL so callers
  don't need aws_region_name to match their default region
- Adds an optional sign_request() hook to BaseSearchConfig (no-op by
  default) and teaches the search HTTP handler to send a signed body
  verbatim, mirroring the existing anthropic_messages/chat pattern
- Handles both plain-JSON and SSE-framed MCP responses, propagates
  MCP errors, truncates queries to the 200-char gateway limit

Tested:
- 13 unit tests: payload/signing, explicit AKSK passthrough, bearer
  token via api_key and env, query truncation, SSE frames, MCP error
  propagation, region derivation
- Verified end-to-end against real AWS_IAM and CUSTOM_JWT gateways,
  including full Claude Code CLI WebSearch round-trips through the
  proxy with websearch_interception
@CrypticDriver
CrypticDriver force-pushed the agentcore-search-provider branch from 563b392 to b61484e Compare July 21, 2026 15:30
- Refuse to send the server-managed AGENTCORE_GATEWAY_TOKEN to a
  caller-supplied api_base (reuses resolve_server_api_key's trusted-host
  guard) — closes the token-exfiltration path via
  /search_tools/test_connection
- Disable BaseAWSLLM's AWS_BEARER_TOKEN_BEDROCK fallback when signing:
  that token is a Bedrock Runtime credential and must not reach an
  AgentCore gateway
- Parse SSE responses per spec: join multi-line data fields, iterate
  events, and return the JSON-RPC response (result/error) instead of the
  first data line — progress notifications no longer shadow the result
- Validate tool_name ends with ___WebSearch so a caller-supplied name
  cannot invoke unrelated tools on the same gateway with the proxy's
  credentials
- Send the documented maxResults default (10) explicitly instead of
  leaving it to the gateway
- Custom gateway hostnames: raise a clear error when no signing region
  can be derived and none is configured, instead of signing for a
  guessed region
- 7 new unit tests covering each fix (20 total)
@CrypticDriver

Copy link
Copy Markdown
Contributor Author

Pushed ebdad6e addressing the review findings:

  • Bedrock bearer token reaching AgentCore (Greptile P1): fixed — the SigV4 path now passes api_key="" to disable BaseAWSLLM's AWS_BEARER_TOKEN_BEDROCK fallback; that credential never leaves for a gateway.
  • Server token to caller-controlled endpoint (Veria High): fixed — the AGENTCORE_GATEWAY_TOKEN fallback now goes through resolve_server_api_key, which refuses to attach the server-managed token unless the request targets the operator-configured AGENTCORE_GATEWAY_URL host.
  • SSE frames truncated (Greptile P1): fixed — the parser now joins multi-line data: fields per the SSE spec, iterates all events, and returns the JSON-RPC response (result/error), so progress notifications no longer shadow the result.
  • Caller can select another gateway tool (Veria Medium): mitigated — tool_name must end with ___WebSearch; other tools on the gateway can't be invoked through this provider.
  • Documented default not sent (Greptile P2): fixed — maxResults: 10 is now sent explicitly.
  • Custom hostnames lose signing region (Greptile P2): now raises a clear error asking for aws_region_name when the region can't be derived and none is configured, instead of signing for a guessed region.
  • CodeQL cyclic-import notes: these mirror the import pattern shared by all existing provider configs in litellm/llms/* (e.g. tavily/brave search configs import the same modules); no new cycle shape is introduced by this PR.

7 new unit tests cover each fix (20 total in test_agentcore_search.py); SigV4 path re-verified live against a real AgentCore gateway.

@greptileai

Comment thread litellm/llms/bedrock/search/transformation.py Outdated
The previous check only consulted AWS_REGION* env vars before rejecting
custom hostnames, breaking deployments that configure their region via
the AWS shared config (profile). Resolve through boto3's session (env
vars + shared config) and only error when that chain yields nothing —
never sign with a silently guessed region.
@CrypticDriver

Copy link
Copy Markdown
Contributor Author

Pushed 2f342dc addressing the follow-up P1 (Preserve shared-config regions): custom-hostname region resolution now goes through boto3's session (env vars and AWS shared config / profile region) and only errors when that chain yields nothing — a deployment with region = eu-west-1 in its profile works again. Covered by test_sign_request_custom_hostname_uses_shared_config_region.

@greptileai

Coverage collection runs against the sharded tests/test_litellm tree, so
the provider tests living only in tests/search_tests were invisible to
codecov (patch coverage reported ~31% despite the suite). Mirror them as
tests/test_litellm/llms/bedrock/search/test_agentcore_search_transformation.py
and add edge-case tests (malformed MCP content blocks, SSE without a JSON
frame, notification-only streams, list request body, error-class mapping).

transformation.py line coverage: 99% (26 tests x2 trees).
@CrypticDriver

Copy link
Copy Markdown
Contributor Author

Pushed e1629b7 to get CI green: it cherry-picks the 3-line queued status-enum fix from #34318, since the litellm_oss_daily_2026_07_20 base branch predates it and misc / Run tests was failing on test_status_enum_values (the test validates against Google's live Interactions OpenAPI spec, which recently added queued; main already has the fix).

This commit is unrelated to the AgentCore provider itself and its diff will disappear automatically once #34318 lands on the daily branch (or if I rebase onto a newer one — happy to do either). All checks are green now except osv-scan, which flags pre-existing npm vulnerabilities in the dashboard lockfile.

@CrypticDriver

Copy link
Copy Markdown
Contributor Author

@tin-berri Would you mind taking a look when you get a chance? This adds a native search provider following the same pattern as the TinyFish one you merged (#30634) — BaseSearchConfig + provider enum — and it closes #31819 which was tagged enhancement. All bot findings resolved (Greptile two rounds, Veria "no open concerns"), CI green except the pre-existing osv-scan, and it's verified end-to-end with a real Claude Code CLI setup. Happy to address any feedback quickly. Thanks!

@CrypticDriver

Copy link
Copy Markdown
Contributor Author

Docs are up as well: BerriAI/litellm-docs#702 adds the provider page (SDK + proxy usage, IAM/JWT auth, the Claude Code interception setup, tool-name rules and limits) and registers it in the search section.

@CrypticDriver

Copy link
Copy Markdown
Contributor Author

@mateo-berri Could you take a look at this one? It plugs a native AgentCore search provider into the websearch interception flow you own (#33129) — that's what makes Claude Code web search work on Bedrock deployments with zero client-side changes (closes #31819, tagged enhancement + claude code). Everything's ready for review: bot findings all resolved (Greptile two rounds, Veria "no open security concerns"), CI green except the pre-existing osv-scan, patch coverage 98%, verified end-to-end with a real Claude Code CLI setup, and docs are up at BerriAI/litellm-docs#702. Happy to retarget to a newer daily branch whenever one is cut. Thanks!

@yassin-berriai

Copy link
Copy Markdown
Contributor

superceded by #36331

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.

4 participants