Skip to content

feat(tools): add AgentCore Web Search as a Strands Agents tool - #673

Open
sundargthb wants to merge 4 commits into
mainfrom
tools/strands-web-search
Open

sundargthb wants to merge 4 commits into
mainfrom
tools/strands-web-search

Conversation

@sundargthb

@sundargthb sundargthb commented Sep 22, 2026

Copy link
Copy Markdown
Member

Description

Adds AgentCoreWebSearch, exposing the AgentCore Web Search tool as a Strands Agents tool. Placement follows memory/integrations/strands, payments/integrations/strands and gateway/integrations/strands: a subpackage behind the existing strands-agents extra, reached only by explicit import. No pyproject.toml change, and a base install is unaffected.

from strands import Agent

from bedrock_agentcore.tools.integrations.strands import AgentCoreWebSearch

with AgentCoreWebSearch(region="us-east-1", gateway_id="my-gateway-abc123") as search:
    agent = Agent(tools=[search.web_search])
    agent("What changed in the most recent boto3 release?")

Notes

region is defaulted only when no region and no gateway ARN were given. WebSearchClient does region = region or arn_region, so filling a default in here unconditionally would silently send a eu-west-1 gateway's traffic to us-east-1.

A failed search raises rather than returning the message as a result. The Strands executor converts the exception to a status: "error" tool result, so the agent keeps running and the model can react. Returning "Web search failed: ..." as a successful result is indistinguishable to the model from a search that found nothing.

Both are pinned down by tests that drive a real Agent, with a scripted model standing in for the model's
choice and WebSearchClient stubbed, so the agent, the tool registry, the spec generation and the tool
executor are the real ones. I checked those tests bite by mutating the source: dropping include_domains
from the forwarded arguments, and returning the failure as text instead of raising, each turned two tests
red and nothing else.

One forward-compatibility note: which transport is used stays inside WebSearchClient. Every gateway argument here is optional and only the ones supplied are forwarded, so the direct web search API will work through the same call without a signature change in this module.

Testing

$ uv run pytest tests/bedrock_agentcore/tools/integrations -q --cov=src/bedrock_agentcore/tools/integrations --cov-report=term-missing
27 passed
src/bedrock_agentcore/tools/integrations/strands/web_search.py   69   0   24   0   100%

$ uv run pytest tests/ -q
3572 passed, 10 skipped, 4 xpassed

$ uv run ruff check src tests tests_integ
All checks passed!

$ uv run ruff format --check src tests tests_integ
341 files already formatted

$ uv run mypy src/bedrock_agentcore/tools/integrations/
Success: no issues found in 3 source files

Also run against a live gateway, on an account entitled to the web search connector, with a web search connector target in us-east-1:

$ WEB_SEARCH_GATEWAY_ID=<gateway-id> BEDROCK_TEST_REGION=us-east-1 \
    uv run pytest tests_integ/tools/integrations/strands/test_web_search_integration.py -v
6 passed, 2 warnings in 14.34s

That covers cited results coming back, max_results being honoured, an include_domains filter, tool-name discovery through tools/list when no target_name is given, one backend and one connection pool being reused across searches, and the end to end path where a real Claude model on Bedrock decides to call the tool and a URL reaches the tool result in the agent's messages.

Two assertions in that file were wrong on their first live run and are fixed in this branch, both the test's fault rather than the tool's. max_results is honoured exactly, but asserting "3. " is absent searches the result extracts too, and web prose contains a digit followed by a period often enough that it was never going to hold, so the numbered blocks are counted instead. And Mcp-Session-Id is optional in MCP and this connector does not send one, so the backend's session id stays None however many searches run through it; the reuse test asserts the backend and its connection pool are the same objects instead.

Related

Exposes the web search tool as a single Strands tool, alongside the existing
memory, payments and gateway Strands integrations, behind the same
strands-agents extra. Attributed with integration_source="strands".

Which transport is used stays inside WebSearchClient. Every gateway argument
here is optional and only the ones supplied are forwarded, so the direct web
search API will work through the same call without a signature change.

Two behaviours the tests pin down:

- region is defaulted only when no region and no gateway ARN were given. The
  client prefers an explicit region over the ARN's, so defaulting it
  unconditionally sends a eu-west-1 gateway's traffic to us-east-1.
- a failed search raises rather than returning the message as a result. The
  Strands executor turns that into a status=error tool result, which a model can
  react to; a successful result reading "search failed" is indistinguishable to
  it from a search that found nothing.

Unit tests cover the module to 100% branch coverage. The integration tests need
a gateway with a web search target and have not been run.
@github-actions

Copy link
Copy Markdown
Contributor

✅ No Breaking Changes Detected

No public API breaking changes found in this PR.

@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation agentcore-devx-automation Bot removed the claude-security-reviewing Claude Code /security-review in progress label Sep 22, 2026
The AgentCoreWebSearch box's content lines were one column wider than its
border, which skewed every box to its right. All five lines are now the same
width with the edges in the same columns.
@github-actions github-actions Bot removed the size/l PR size: L label Sep 22, 2026
@github-actions github-actions Bot added the size/l PR size: L label Sep 22, 2026
@agentcore-devx-automation agentcore-devx-automation Bot added the claude-security-reviewing Claude Code /security-review in progress label Sep 22, 2026
@agentcore-devx-automation agentcore-devx-automation Bot added the claude-security-reviewing Claude Code /security-review in progress label Sep 22, 2026
@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation agentcore-devx-automation Bot removed the claude-security-reviewing Claude Code /security-review in progress label Sep 22, 2026
@github-actions github-actions Bot added size/l PR size: L and removed size/l PR size: L labels Sep 22, 2026
Both failed on their first live run against a gateway, and both were the
test's fault rather than the tool's.

max_results is honoured exactly, 1 gives 1 and 2 gives 2, but asserting
"3. " is absent searches the result extracts too, and web prose contains a
digit followed by a period often enough that this was never going to hold.
Count the lines that open a numbered block instead.

Mcp-Session-Id is optional in MCP and this connector does not send one, so
the backend's session id stays None however many searches run through it.
Assert what the test is named for by checking the backend and its
connection pool are the same objects across two searches.
@github-actions github-actions Bot added size/l PR size: L and removed size/l PR size: L labels Sep 22, 2026
@agentcore-devx-automation agentcore-devx-automation Bot added the claude-security-reviewing Claude Code /security-review in progress label Sep 22, 2026
@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation agentcore-devx-automation Bot removed the claude-security-reviewing Claude Code /security-review in progress label Sep 22, 2026
@sundargthb
sundargthb marked this pull request as ready for review September 22, 2026 02:06
@sundargthb
sundargthb requested a review from a team September 22, 2026 02:06
@github-actions github-actions Bot added size/l PR size: L and removed size/l PR size: L labels Sep 22, 2026

This branch was successfully deployed

1 active deployment
auto-approve a094cc2f Deployed Sep 22, 2026 by sundargthb via Test (runtime) #1591
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/l PR size: L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant