`browse_web` agent tool with S3-backed domain allowlist; AgentCore Browser removed

dropthejase adds a `browse_web` tool to the main agent that fetches legal and regulatory websites using `fetch()` and strips HTML. The domain allowlist lives in S3 so it can be updated without redeploying. AgentCore's managed browser is removed in the same cluster - tried, then abandoned.

integrationsecurity

The tool (9196cbc) is a straightforward fetch() + HTML-stripping implementation using the Strands tool() factory. It returns stripped visible text (up to 40,000 characters) plus up to 50 extracted links. A 20-second fetch timeout handles slow government websites.

The allowlist design is the reusable idea. On first invocation, the tool reads browse-allowlist.json from process.env.ADMIN_BUCKET_NAME in S3 and caches the result as a Set<string> for the container's lifetime. If the S3 load fails, it falls back to a hardcoded list of eight domains (curia.europa.eu, eur-lex.europa.eu, bailii.org, ICO, FCA, Companies House). Any URL whose hostname is not in the set gets rejected with an error string rather than a silent failure. Admin can update the allowlist by uploading a new JSON file - takes effect on next cold start.

The AgentCore Browser infrastructure removal (f6da49c) is telling. A CfnBrowserCustom resource with Chrome Enterprise policy, an IAM BrowserExecutionRole, and a chrome-policy.json config were all in place. All of it gets deleted. The AgentStack is simplified to just an admin S3 bucket with seed config files. The implication is that AgentCore's managed browser didn't fit the constraint surface - the allowlist was baked into Chrome policy rather than hot-editable, and the full browser overhead wasn't justified for what amounts to HTML fetching from a known set of static government sites.

So what Worth a look for the S3-backed hot-editable allowlist pattern specifically - it applies to any per-tool configuration that ops needs to change without a redeploy. The fetch-and-strip approach is adequate for static legal/regulatory pages that don't require JavaScript rendering. Skip if you need a full browser with JS execution or session handling - dropthejase tried that path and removed it.

View this fork on GitHub →

Spotted something wrong? Or know the PR text has fresher detail than the writeup above?

Commits in this thread

4 commits from dropthejase/louis, oldest first. Source extracted verbatim from the harvested git log.

SHA Subject Author Date
9196cbc5 feat(browse-web): add web browsing tool with S3-backed domain allowlist Jason Lee 2026-05-15 ↗ GitHub
commit body
Adds browse_web tool to the main agent using fetch() + HTML stripping.
Domain allowlist loaded from admin S3 bucket (browse-allowlist.json) at
container startup, with hardcoded fallback if S3 unavailable.

Introduces AgentStack (shared admin config bucket + AgentCore Browser
resource) and wires ADMIN_BUCKET_NAME through ApiStack props, agentCoreRole
IAM policy, and deploy-agent.sh env vars.
5a568f43 feat: merge feature/web-search - browse_web tool with S3-backed domain allowlist Jason Lee 2026-05-15 ↗ GitHub
80ff0272 docs(readme): add Web Search to Additional Features Jason Lee 2026-05-15 ↗ GitHub
f6da49c2 feat(infra): remove AgentCore Browser infrastructure Jason Lee 2026-05-15 ↗ GitHub
CfnBrowserCustom, BrowserExecutionRole, BROWSER_ARN env var, and
AgentCoreBrowser IAM policy removed. browse_web tool (plain HTTP fetch
with S3-backed allowlist) is unaffected.

Capture this thread into my fork

Download a single Markdown prompt that tells Claude how to port every commit above into your working tree — adapting paths and structure to match your repo. Run it via claude -p < capture-thread-349.md from inside the repo you want the changes in.

⬇ Download capture-thread-349.md