Hadrian is experimental alpha software. Do not use in production.
Hadrian
ConfigurationFeatures

Web Tools

Configure server-side web search and URL fetching tools

The [features.web_search] and [features.web_fetch] sections configure server-side web tools used by the chat UI. Web search requires an external provider API key; web fetch works out of the box.

Configuration Reference

[features.web_search]
provider = "tavily"
api_key = "${TAVILY_API_KEY}"
max_results = 10
timeout_secs = 30
cost_microcents_per_request = 10000
KeyTypeDefaultDescription
providerstringSearch provider: "tavily" or "exa" (required)
api_keystringProvider API key, supports ${ENV_VAR} (required)
max_resultsinteger10Maximum results per search (also caps per-request limit)
timeout_secsinteger30Request timeout in seconds
cost_microcents_per_requestinteger10000Cost per request in microcents ($0.01 default)

Omit the [features.web_search] section entirely to disable web search. There is no separate enabled flag — the presence of the section enables the feature.

Provider Setup

Tavily

  1. Sign up at tavily.com and obtain an API key
  2. Set the environment variable or inline the key:
[features.web_search]
provider = "tavily"
api_key = "${TAVILY_API_KEY}"

Exa

  1. Sign up at exa.ai and obtain an API key
  2. Configure with the exa provider:
[features.web_search]
provider = "exa"
api_key = "${EXA_API_KEY}"

Exa returns full-text content for each result rather than snippets.

Cost Tracking

Each search request is logged with the configured cost_microcents_per_request. The default of 10000 represents $0.01 per search. Adjust to match your provider's actual pricing.

Web Fetch

Configuration Reference

[features.web_fetch]
enabled = true
max_response_bytes = 1048576
timeout_secs = 30
allowed_content_types = ["text/html", "text/plain", "application/json", "application/xml", "text/xml", "text/csv", "text/markdown"]
cost_microcents_per_request = 0
KeyTypeDefaultDescription
enabledbooleantrueEnable/disable the web fetch tool
max_response_bytesinteger1048576 (1 MB)Maximum response body size in bytes
timeout_secsinteger30Request timeout in seconds
allowed_content_typesstring[]See aboveContent types to accept (prefix match)
cost_microcents_per_requestinteger0Cost per request in microcents (free by default)

Omit the [features.web_fetch] section entirely to disable web fetch. When present, set enabled = false to temporarily disable without removing the configuration.

Security

Web fetch includes multiple layers of SSRF protection:

ProtectionDescription
URL validationBlocks private/loopback IPs by default
DNS pinningResolves DNS once and pins the connection to prevent rebinding
Redirect blockingRejects HTTP redirects to prevent SSRF via redirect chains
Content filteringOnly fetches allowed content types
Size limitsTruncates responses at max_response_bytes

To allow fetching from private/loopback addresses (development only):

[server]
allow_loopback_urls = true
allow_private_urls = true

Content Type Filtering

The allowed_content_types list uses prefix matching. For example, "text/html" matches "text/html; charset=utf-8". An empty list allows all content types (not recommended).

Complete Examples

Development

[features.web_search]
provider = "tavily"
api_key = "${TAVILY_API_KEY}"
max_results = 5
timeout_secs = 10

[features.web_fetch]
max_response_bytes = 524288
timeout_secs = 15

Production

[features.web_search]
provider = "tavily"
api_key = "${TAVILY_API_KEY}"
max_results = 10
timeout_secs = 30
cost_microcents_per_request = 10000

[features.web_fetch]
max_response_bytes = 1048576
timeout_secs = 30
cost_microcents_per_request = 0
allowed_content_types = ["text/html", "text/plain", "application/json"]

Web Fetch Only

# No [features.web_search] — web search disabled

[features.web_fetch]
max_response_bytes = 2097152
timeout_secs = 60

Next Steps

On this page