web Plugin
Ready-to-use document reading and local browsing, with configurable Tavily, Exa, and Firecrawl providers
web Plugin
web owns its search, document, and browser providers. It does not depend on
context.agent.web. In Desktop, static document reading and a managed local Chrome browser work
without manual CDP setup. Search becomes available after an API key is configured.
Desktop configuration
Open Plugins → Web. The page has three capability sections:
- Search:
Auto,Tavily,Exa, or disabled. Auto prefers Tavily and then Exa. - Documents: built-in Fetch by default, or Firecrawl for harder pages.
- Browser: managed Local Chrome by default, Remote CDP, or disabled.
API keys can be entered directly on the Web configuration page. Saved values are never returned to the renderer; the page only shows whether a key is configured. An empty field preserves the existing value, while the explicit Clear action removes it. Keys currently live in Downcity's local Plugin configuration and are not stored in the operating-system keychain.
Global Env remains supported:
TAVILY_API_KEY=...
EXA_API_KEY=...
FIRECRAWL_API_KEY=...Plugin configuration takes precedence over Global Env. Each capability section includes a test button that saves the draft and performs one minimal call through a real Agent and Workspace.
Defaults
import { WebPlugin } from "@downcity/plugins/web";
const web = new WebPlugin();openuses the built-in Fetch provider and never executes page scripts.- Browser actions discover Google Chrome, Chromium, or Microsoft Edge and use a private persistent profile.
searchselects Tavily or Exa when a key is available; missing search credentials do not disable other capabilities.
WebPlugin closes browser processes and pages it owns. The persistent profile keeps login state. For a cloud browser, select Remote CDP and enter its HTTP or WebSocket endpoint.
Fixed SDK configuration
Constructor configuration overrides saved City/Desktop configuration:
const web = new WebPlugin({
config: {
search_provider: "tavily",
tavily_api_key: process.env.TAVILY_API_KEY,
document_provider: "firecrawl",
firecrawl_api_key: process.env.FIRECRAWL_API_KEY,
browser_provider: "cdp",
cdp_url: "https://browser.example.com/cdp",
},
});Hosts may still inject search_provider, document_provider, or browser_provider_factory.
Ownership of injected providers transfers to WebPlugin.
Actions
| Action | Purpose |
|---|---|
search | Search through Tavily, Exa, or an injected provider |
open | Read through safe Fetch, Firecrawl, or an injected provider |
browser_create_session | Create a browser session |
browser_observe | Read URL, title, accessibility snapshot, visible text, refs, and an optional screenshot |
browser_act | Perform a deterministic action with an observation generation and ref |
browser_semantic_act | Use an optional semantic adapter |
browser_extract | Extract text from a selector or the body |
browser_semantic_extract | Extract through an optional semantic adapter |
browser_close_session | Close a session and release its page |
Observe first, then act with a ref from that exact generation:
const observed = await web.actions.browser_observe.execute({
context,
input: { session_id },
});
await web.actions.browser_act.execute({
context,
input: {
session_id,
action: {
type: "click",
ref: observed.data.elements[0].ref,
observation_generation: observed.data.observation_generation,
},
},
});Element refs are valid only for the observation generation that produced them. Use new refs after every action. CSS selectors remain available only for explicit deterministic automation.
Network and safety boundaries
- Fetch only permits public HTTP(S) targets and revalidates every redirect against SSRF rules.
- Requests have timeout, redirect-count, and response-size limits.
- Provider errors do not expose API keys, authentication headers, or full error response bodies.
- Consequential actions such as submit, send, purchase, upload, and delete still require host approval.
- Page content is always untrusted input and cannot override Agent or host instructions.