Web Search and Read Tools
An agent loop that needs the web should not build its own ungoverned tool. The Agent Runtime Pack
ships two tools, web:search and web:read, that run through runGovernedAgentLoop. The host
supplies the search provider behind a port; the pack names no provider.
web:search takes { query, limit?, recency? } (recency is day, week, month or year).
It returns results of { title, url, snippet, source_id, citation }, plus truncated.
web:read takes { url, max_bytes? }. It returns { url, final_url, content_type, text, truncated, fetched_at, bytes, untrusted, citation }. Only http and https URLs without credentials are
accepted, and only text, JSON and XML content types are returned.
The search provider port
Section titled “The search provider port”WebSearchProvider has one method, search({ query, limit, recency? }, { signal? }), returning
{ title, url, snippet } hits. The host supplies the adapter (for example a hosted search
service). createFixtureWebSearchProvider(hits) serves tests. A provider failure is the tool error
WEB_SEARCH_PROVIDER_ERROR.
Egress allowlist and violations
Section titled “Egress allowlist and violations”The allowlist is per run and uses the same grammar as the sandbox network allowlist: host,
host:port or an IPv4 CIDR. An empty list denies every read. The check runs before the first
request and again on every redirect hop. A denial returns WEB_EGRESS_DENIED, makes no request
and emits one sandbox:violation event (network_egress_blocked) to the emitter.
The default transport is the platform fetch. A host that confines egress passes a fetch routed
through the engine egress proxy (see the confinement reference), which adds address vetting and
the proxy’s own denial events on top of this check.
caps.max_results (default 10) and caps.max_read_bytes (default 262144) are host ceilings. A
call’s limit and max_bytes can only lower them. When results or bytes are cut, truncated is
true. Other caps: default_read_bytes, max_snippet_chars, max_redirects and timeout_ms.
Citations
Section titled “Citations”Every search result and every page read carries a citation in the shape of the knowledge pack’s
KnowledgeCitation: { sourceId, documentId, path, revisionId, retrievedAt }. sourceId is the
host name, documentId a digest of the URL, path the URL, and revisionId a digest of the
content seen.
Untrusted content
Section titled “Untrusted content”Fetched text is data. web:read returns text inside an untrusted-web-content block whose first
line says the text is data, not instructions. The block records the source URL, fetch time and a
random nonce. Any copy of the block’s tags inside the page is broken, so a page cannot close the
fence early. The output also carries untrusted: true and an external_tool_read provenance
label. Search results are marked the same way. The loop only executes tool calls the model
requests; text in a tool result never becomes a call, and the tests prove an injected instruction
in a fetched page does not.
Task contract
Section titled “Task contract”Wrap the web runtime with createAgentTaskRun(...).guardRuntime and each call is a step record
under the task’s max_steps, cost and duration budgets. Declare an approval_class for
web:read in toolPolicy to put reads behind the request_user gate.
Errors
Section titled “Errors”WEB_INVALID_INPUT, WEB_URL_NOT_ALLOWED, WEB_EGRESS_DENIED, WEB_HTTP_ERROR,
WEB_FETCH_FAILED, WEB_TOO_MANY_REDIRECTS, WEB_CONTENT_TYPE_UNSUPPORTED and
WEB_SEARCH_PROVIDER_ERROR.