Skip to content

think: add a fetch tool with whitelisted domains #1344

Description

@threepointone

Parent roadmap: #1439

Summary

Think should include an optional, conservative fetch tool for agents that need to read HTTP resources without enabling arbitrary browser automation or unrestricted network access.

This should be a small capability in the execution ladder: more powerful than plain model knowledge, less powerful than Browser Run, and safer than letting generated code call any URL.

Problem

A lot of agent tasks need simple network reads:

  • fetch public docs pages or API references
  • retrieve JSON from a known service endpoint
  • inspect a changelog, release note, RSS feed, or status page
  • call a first-party internal endpoint that the app owner explicitly allows

Today, Think has workspace tools and codemode execution, and browser tools exist for full CDP/browser workflows. But there is no clear built-in path for “read this allowlisted URL safely”. Users either need to write their own tool, use browser automation for a simple fetch, or expose broader network access than intended.

Goals

  • Provide a simple Think tool for HTTP reads against an explicit allowlist.
  • Make the safe path obvious for common docs/API lookup use cases.
  • Keep the tool deterministic and bounded: limits, redirects, content types, and output size should be explicit.
  • Avoid creating a general-purpose SSRF primitive.

Non-goals

  • Do not add unrestricted outbound network access.
  • Do not replace Browser Run for rendered pages, screenshots, auth flows, or CDP/browser automation.
  • Do not make this a generic HTTP client for mutating APIs in v1.
  • Do not persist fetched content automatically as memory unless the caller explicitly does that through existing tools.

Proposed API shape

Names are illustrative:

createFetchTool({
  allowlist: [
    "https://developers.cloudflare.com/**",
    "https://api.github.com/repos/cloudflare/agents/**"
  ],
  methods: ["GET"],
  maxBytes: 512_000,
  timeoutMs: 10_000,
  followRedirects: "same-origin",
  response: "text" // or "json" / "auto"
})

Possible Think usage:

getTools() {
  return {
    ...createWorkspaceTools(this.workspace),
    ...createFetchTool({
      allowlist: this.getAllowedFetchOrigins()
    })
  };
}

The AI-facing tool could be one tool:

  • fetch_url({ url, headers? })

or two tools:

  • fetch_text({ url })
  • fetch_json({ url })

Prefer the smallest surface that keeps output predictable.

Security / design questions

  • What allowlist syntax should we support? Exact URLs, origins, glob paths, URLPattern, or caller-provided predicate?
  • Should redirects be disabled by default, same-origin only, or allowlisted destination only?
  • Should private IPs, localhost, .internal, link-local, and metadata-service ranges be blocked even if a caller misconfigures the allowlist?
  • Should request headers be fully blocked, fixed by the app, or allowlisted by header name?
  • Should only GET be supported in v1? If POST is supported later, it likely belongs in a separate explicit API/action tool with approval.
  • How should content be normalized? Raw text, Markdown extraction, JSON parsing, or content-type aware auto mode?
  • How should large responses be handled? Hard byte cap, truncation with metadata, or write-to-workspace option?
  • Should robots.txt/cache semantics be documented or enforced?
  • How should errors be represented so models can distinguish disallowed URL, timeout, non-2xx, unsupported content type, and truncation?

Suggested v1 behavior

  • Only GET and HEAD.
  • Require explicit allowlist.
  • Deny private-network targets by default.
  • Follow redirects only when the final URL is also allowlisted.
  • Cap response bytes and tool-output tokens.
  • Return structured metadata: final URL, status, content type, byte length, truncated flag.
  • Support text, json, and maybe arrayBuffer only if the caller opts into writing binaries to Workspace.
  • Do not include credentials unless the app supplies fixed server-side headers for a specific allowlisted origin.

Acceptance criteria

  • @cloudflare/think exposes a documented fetch tool factory or clearly documented example pattern.
  • The tool cannot fetch URLs outside the configured allowlist.
  • Redirects cannot escape the allowlist.
  • Private-network / localhost SSRF cases are blocked or explicitly addressed.
  • Response size, timeout, and content-type handling are tested.
  • Error messages are actionable for users and models.
  • Docs compare this with Browser Run and codemode so developers know when to use each.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requeston the roadmapFeature accepted and planned for implementation

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions