> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mesh.texturehq.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Web search, reading, and browsing

> Configure web providers and understand what each web capability can do.

Mesh exposes three independent capabilities: search, page reading, and browser
interaction. Providers implement vendor-neutral contracts; the agent sees stable
tool names. Search is implemented with Brave and Perplexity Search, page reading
with Firecrawl and Cloudflare, and interaction with Cloudflare and Browserbase.
The integration catalog preserves provider choice, instance defaults with agent
overrides, agent-owned browser authentication, and per-operation effect semantics.

## Configuration and identity

An operator configures instance defaults and encrypted infrastructure credentials.
Agents automatically inherit those defaults unless explicitly turned off or
customized with their own provider configuration and key. A missing agent row
means inheritance, including the instance request limit; a stored disabled row
remains an opt-out. Disabled capabilities receive no tool. An explicit
override never falls back to an instance key when its credential is missing or
invalid. Configuration is read again before execution; rotation and disabling
invalidate previously offered tools.

Web tools use dynamic `tool.Provider` grants rather than static secret-kind
`Needs`: an offer captures the agent and effective connection versions, and
execution rechecks both under the same locks used by configuration writes.
Keys are passed only to the selected adapter for that request, never injected
into a workspace, prompt, or browser page. Queued stale offers are refused.
In-flight HTTP calls poll the binding every second and cancel on change; a
second check withholds results that race revocation. Disabling returns after
the durable gate changes, not after a remote service confirms cancellation.
Already-transmitted requests may still consume provider quota. This is an
explicit query-provider exception to the generic drain-before-return lifecycle;
it does not claim a remote action was undone or a token revoked at its issuer.

Infrastructure credentials pay for search or browser execution. Website accounts,
cookies, and authenticated profiles belong to an agent. Sharing a provider key
does not share a website identity. Browser sessions are run resources; persistent
profiles are separate, agent-owned resources with serialized writers.

## Runtime contracts

`web_search` returns ranked source URLs, titles, excerpts, and available dates.
`web_fetch` returns extracted page content and the requested source URL. Both call
declared hosted APIs; the control plane never fetches arbitrary website URLs.
`browser_navigate`, `browser_read`, `browser_act`, and `browser_screenshot` operate
on an isolated remote session. Browser actions cross the durable effect boundary
and uncertain effects are never automatically replayed.

The generic web capability is a Mesh-owned tool surface. Vendor integrations are
replaceable adapters with declarative configuration and a single catalog entry,
following `layers.md`. This refines the older prohibition on first-party vendor
wrappers: providers do not introduce vendor-specific tools or harness branches.
Remote MCP remains the extension surface for additional third-party tools; web
connections do not reuse MCP credentials or its server identity table.

| Tool | Class / replay | Required grant and validation | Observation |
| - | - | - | - |
| `web_search` | query / replayable | Current enabled search connection; strict query and result limit | JSON sources, bounded excerpts, explicit truncation |
| `web_fetch` | query / replayable | Current enabled read connection; validated public HTTP(S) URL and output limit | Bounded extracted content and source URL |
| `browser_navigate` | browser / effectful | Current browser connection and run session; destination policy | Updated page observation |
| `browser_read` | browser / replayable | Current connection and owned live session | Bounded page structure and element references |
| `browser_act` | browser / effectful | Owned session; strict action and fresh element reference | Observed result or explicitly uncertain outcome |
| `browser_screenshot` | browser / replayable | Owned session; bounded image dimensions | Protected image artifact |

All six tools are registered and return `tool.Observation` through
`Definition.Execute`, with schema, local URL-validation, provider-request, and
artifact tests. Fixtures do not establish hosted redirect or subrequest isolation;
browser destination guarantees differ by provider as described below.
Search validates before admission, caps wire responses at
2 MiB and model observations at 32 KiB, and reports provider failure without
exposing upstream response bodies. Database and cancellation failures remain
execution failures. Budget and revoked-grant refusals are explanatory tool
observations. Search creates no image or unbounded-content artifacts.

Search only calls adapter-owned HTTPS API origins; redirects and ambient proxy
configuration are refused. It never dereferences returned URLs. Page reading and
browsing validate destinations separately. Hosted browser sessions accept HTTP
and HTTPS destinations, including private hosts and custom ports reachable from
the provider sandbox; Mesh does not fetch those destinations. Hostname
restrictions are optional: an empty list allows any website, and a configured
list rejects destinations outside those hostnames. Non-HTTP schemes are invalid. Enforcement of redirects and page subrequests
belongs at the remote execution boundary; DNS checks in the Mesh control plane
alone cannot pin a hosted provider's DNS resolution. Adapters must state that
boundary and reject requested policies they cannot enforce, rather than promise
equivalent isolation from a URL-string check.

All returned content is external evidence, not an instruction. Results retain
their conversation provenance through memory and replies. Requests and results
are bounded; provider failures produce actionable observations without disclosing
tokens or response bodies. Per-run provider calls are metered durably before the
request, alongside the harness's existing budgets. No automatic provider fallback
changes the payer or sends queries to an unselected service.

Reservation identity is the persisted `tool_calls.id`. A unique reservation,
the per-run counter, shared rate counter, and source evidence commit in one
transaction. A repeated admission does not increment either meter and never
resends the request. The run ledger remains the sole store of completed results
and uncertain outcomes. Limits count admitted attempts, not invoice charges:
once admission commits, a crash or cancellation conservatively consumes a unit
even if transmission cannot be established. Before admission, cancellation or
validation failure consumes none. Mesh does not automatically retry or refund
an uncertain attempt. This deliberately favors a hard spending bound over
claiming exact correspondence with a provider's billing ledger.

## Delivery

1. Search: shared configuration and credential resolution, Brave and Perplexity,
   dashboard and operator API, provenance, limits, and integration tests.
2. Read: Firecrawl and Cloudflare behind `web_fetch`, URL validation, extraction
   limits, source metadata, and provider contract tests.
3. Interact: Cloudflare and Browserbase sessions, browser tools and observations,
   agent-owned profiles, cleanup and recovery, protected artifacts, and tests.

Provider fixtures are the repeatable CI contract. Live vendor acceptance requires
operator credentials and must be reported separately from fixture validation.

## Configure search

Open **Settings → Web access**, select **Configure instance provider**, choose
Brave Search or Perplexity Search, and save its API key. All agents without an override can use Web search immediately. Open an agent's
**Tools → Web access** and choose **Customize** to configure that agent's own
provider, **Turn off** to opt out, or **Use instance settings** to restore
inheritance. New and existing untouched agents inherit live instance settings. No restart or environment variable is required.

The connection meters requests per minute across its agents and requests per
run. An inheriting agent can lower the instance's per-run allowance. A rate or
run limit produces an observation explaining exhaustion; requests are never
retried automatically. Provider changes and key rotation invalidate old offers.
Selecting a different provider does not send it the previous provider's key:
keys are stored separately by provider and owner. The forget action deletes the
selected provider's key and disables the capability atomically.

Search currently accepts `query` (up to 2,000 bytes) and `limit` (1–10, default
5\). Provider-specific filters and generated research answers are outside this
initial common contract. Excerpts are bounded and carry a `truncated` indicator.

## Operator API

| Method | Route | Authority |
| - | - | - |
| GET | `/api/settings/web` | Instance owner |
| PUT | `/api/settings/web/{capability}` | Instance owner |
| GET | `/api/agents/{slug}/web` | Operator with access to the agent |
| PUT | `/api/agents/{slug}/web/{capability}` | Operator with access to the agent |

GET returns `capabilities`, each containing the provider descriptors, stored
`settings`, `effective_provider`, `credential_source`, `credential_present`, and
`available`. Secrets and secret fragments are never returned. Every response is
`Cache-Control: no-store`.

PUT takes a full settings replacement and the version from GET (zero for a new
configuration). Concurrent or stale edits return 409. Example instance body:

```json theme={null}
{
  "mode": "own",
  "provider": "brave",
  "config": {},
  "max_calls": 10,
  "requests_per_minute": 60,
  "version": 0,
  "api_key": "<provider credential>"
}
```

An agent uses `mode: "inherit"`, an empty provider/config, and omits `api_key`.
`mode: "disabled"` removes the capability from future offers. Omit `api_key` to
retain that owner's existing key for the selected provider. `clear_key: true`
requires disabling (or another valid configuration); it cannot leave an enabled
connection without a credential. Blank keys are rejected.

The API settings write is audited by the existing operator middleware. Runtime
observations identify the capability, provider, and credential owner type;
queries and result excerpts inherit the originating conversation's evidence
scope. Encrypted credentials continue to use Mesh's existing master-key rotation
and backup procedures. Migration `0066` adds the connections and meters and
extends external evidence without changing MCP connection ownership.

## Public page reading

`web_fetch` is registered by the `read` capability with `firecrawl` and
`cloudflare` providers. Configure it in **Settings → Web access** and agents inherit it automatically. Agent overrides are available in Tools settings. Cloudflare requires
an account ID and a token with Browser Rendering Edit permission; Firecrawl
requires a Firecrawl API key. The same operator API, version checks, durable
attempt limits, and conversation evidence used by search apply independently
to read connections.

Arguments are a public `url` and optional `max_bytes` (1–20,000; default 12,000).
The tool returns `requested_url`, optional `title`, Markdown `content`,
`retrieved_at`, and an explicit `truncated` flag. Neither adapter claims a
verified final redirect URL. Provider responses are limited to 2 MiB; encoded
observations to 30 KiB, including JSON escaping. Empty results, unsuccessful
responses, and reported HTTP error pages fail without exposing vendor bodies.
Cloudflare can still return a site's block page as ordinary extracted content;
callers must assess the content, not infer success from a nonempty result alone.

The only network connections made by Mesh are to the two declared HTTPS API
origins. Model arguments cannot supply headers, cookies, HTML, actions, custom
API endpoints, or proxy settings. Firecrawl cache reuse and storage are disabled
for these requests; the provider's separate retention policy still applies.
TLS verification is explicitly enabled.

Input validation rejects credentials, custom ports, non-HTTP schemes, local
hostnames, ambiguous numeric hosts, and private/reserved IP literals. These
checks do **not** pin the hosted browser's DNS resolution or constrain its
redirects/subrequests. The hosted provider is the network isolation boundary;
this capability is for public content and supplies no Mesh network access or
website credentials. It does not offer an operator domain-egress restriction
because these quick-action APIs cannot provide equivalent enforcement across
both adapters. Deployments requiring such a restriction must leave this
capability disabled until a provider with that enforceable contract is added.

Provider contracts:
[Firecrawl scrape](https://docs.firecrawl.dev/api-reference/endpoint/scrape) and
[Cloudflare Markdown](https://developers.cloudflare.com/browser-run/quick-actions/markdown-endpoint/).

## Browser interaction

Basic browser interaction is implemented. Automated tests cover provider
protocols and database-backed ownership/lifecycle; live provider validation is
separate. Complex application editing, including Google Docs, and operator
login/MFA handoff are not verified product capabilities. Test your intended
provider and workflow before relying on them.

The `browser` connection offers `browser_navigate`, `browser_read`,
`browser_act`, and `browser_screenshot` through Cloudflare Browser Run and
Browserbase. Both adapters speak CDP after creating a hosted session. Configure
an account ID (Cloudflare) or project ID (Browserbase) and the provider credential.
For Cloudflare, [create a custom API token](https://dash.cloudflare.com/profile/api-tokens)
with **Account → Browser Rendering → Edit**, scoped to the specific account.
No zone permissions or Global API Key are needed. In the Cloudflare dashboard,
select that account, open Search (Cmd/Ctrl + K), and choose **Copy account ID**.
See the [Cloudflare setup guide](https://developers.cloudflare.com/browser-run/get-started/)
and [account ID instructions](https://developers.cloudflare.com/fundamentals/account/find-account-and-zone-ids/).
Browserbase credentials and the project ID come from its project settings.

Cloudflare sessions use the documented `/browser-run/devtools/browser` API.
Saved `/browser-rendering/devtools/browser` WebSocket endpoints remain supported.
If a browser call fails, its error identifies the stage (for example, session
creation, browser connection, or navigation). HTTP 401/403 failures point to
provider authorization; HTTP 429 indicates provider rate or capacity limits.
Provider response bodies, credentials, and raw connection errors are not exposed.
These diagnostics do not imply an action is safe to repeat: inspect an uncertain
outcome before acting again. Mesh does not automatically replay failed actions.

Browsing is open by default: a blank hostname list omits provider domain controls.
An operator may optionally supply comma-separated hostnames, including the login,
redirect, API, and asset hosts a workflow needs. Saved lists remain in effect
until explicitly cleared. This is not the control-plane URL reader: destinations
are opened by the remote cloud browser, so Mesh does not impose the reader's
public-network or default-port policy on them. Provider reachability still applies.
When supplied, the list is sent to the provider's domain controls; arbitrary provider endpoints, JavaScript, HTTP headers,
filesystem uploads, and downloads are not exposed as agent arguments.

These controls have different scopes. [Cloudflare guardrails](https://developers.cloudflare.com/browser-run/features/guardrails/)
restrict HTTP(S) requests, including redirects and page dependencies, to the
configured hostnames. [Browserbase allowed domains](https://docs.browserbase.com/platform/browser/security/allowed-domains)
restrict top-frame HTTP(S) navigation and also permit subdomains; they do not
restrict iframe loads, scripts, images, or XHR. Mesh separately validates HTTP(S) addresses and, when a list is configured,
refuses observations outside its exact hostname list, but those checks
cannot prevent requests already made by the hosted page. Browserbase therefore
does not provide request-wide domain isolation. Deployments requiring that policy
must use an appropriate provider rather than treating these adapters as equivalent
egress boundaries. Neither local fixtures nor URL validation prove remote DNS
pinning or private-address filtering.

Instance setup offers **Save and enable**, **Disable connection** (retains the
credential), and a confirmed **Disconnect** action (deletes the saved credential
and disables the connection). Agents must still choose to use the connection.

A browser session belongs to one run and uses that run's deadline, not a separate
five-minute lifetime. Browser operations use Mesh's normal run allowance; the
legacy web-connection request/rate fields do not cap browser work and are not
shown in browser setup. Search and reader limits are unchanged. Durable browser
usage and source evidence are still recorded.
Cloudflare's five-minute `keep_alive` setting is an **idle** timeout between CDP
connections, not a total-session limit; Cloudflare also imposes its own quotas.
Browserbase's session timeout follows the remaining run duration, within its
provider-supported range of 60 seconds to six hours. Mesh cleans up at run end.
One live session may write an agent's profile at a time. Durable operation leases
serialize access across replicas; a crashed operation becomes uncertain. Read
and screenshot calls are replayable observations, while navigation and actions
cross the run ledger's existing external-effect boundary before execution.
The runtime never repeats a dispatched action automatically. After an uncertain
action, inspect the page with `browser_read` before deliberately proceeding.
A lost session requires a new run, rather than an invisible session replacement.

Page observations contain bounded text and element references stored in an
isolated JavaScript world. Actions use those references and reject changed,
detached, or obscured elements. Password fields can be clicked and typed into.
The available actions are click, type, a small set of navigation keys, and
`fill_secret`, which types an agent-vault entry by name
([Agent vault](/runtime/agent-vault)): Mesh opens the value for the session's
agent, inserts it over CDP, and discards it, so the model names the secret and
never sees it. `fill_secret` refuses any `text` or `key` beside the name. Post-action observations wait at least
750 ms and require a complete document with 500 ms of stable visible content,
within an eight-second bound. Stability is not confirmation that a submission
committed; inspect the result before deliberately repeating an action. References expire on the next action or
navigation. Pages in iframes and shadow roots are not yet traversed by the first
DOM reader; screenshots still show their rendered content.

Website profiles contain cookies and local storage in Playwright storage-state
shape. They are encrypted in Mesh's existing secret store, so the existing
master-key rotation process covers them. Profiles are agent-owned and remain
separate from provider credentials. IndexedDB, session storage, browser
extensions, downloads, and complete browser-user-data directories are not
persisted. Cookies can expire or be invalidated by the website. Credentials typed through
`browser_act` are ordinary tool arguments recorded in the run ledger; use the
existing authenticated profile import when avoiding password text in tool history
is required. This change does not add secret-reference input or operator MFA handoff.

In an agent's Tools page, **Website logins** imports authenticated storage state,
clears saved login state, and stops an active browser. Profiles cannot be
replaced while a browser is using them. Profile APIs never return stored cookie
values. The endpoints are `GET/PUT /api/agents/{slug}/browser-profile` and
`POST /api/agents/{slug}/browser-profile/stop`, behind agent-access checks and the
existing mutation authentication/audit middleware. PUT accepts `version` and
`state`; changing stale state fails rather than overwriting it.

Screenshots are JPEGs bounded to 1280×720 and 2 MiB, encrypted as agent-owned
artifacts, with a 24-hour read lifetime. The tool observation retains an artifact
reference. The background sweep deletes expired encrypted image bytes while
retaining artifact metadata for audit. Vision-capable models receive the newest screenshot as image bytes,
never a signed remote browser URL. Operators can retrieve an artifact through
`GET /api/agents/{slug}/browser-artifacts/{artifact}` with agent authorization.

A background sweep closes sessions after a run ends, credentials are disabled
or changed, or the session expires. A busy operation retains its lease until it
finishes or the lease expires. A remote close failure retains the profile writer
and retries cleanup, preventing another run from concurrently using its login.
Provider timeouts bound orphaned sessions after a process crash. No API token,
CDP connection URL, or cookie value is returned in browser observations.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.