web Power
Ready-to-use document reading and local browsing, with configurable Tavily, Exa, and Firecrawl providers
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 Powers → Web. Each capability is configured in place: pick its provider from the dropdown on the capability row in the workspace Sidebar, then edit that capability's parameters in the Mainview.
- 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.
- Advanced: operation timeout, observation character limit, default browser URL, and an optional Chrome path.
API keys can be entered directly in a capability view. 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. A key that is not configured yet shows a 去申请 link that opens the provider's console, so you do not have to search for it. Keys currently live in Downcity's local Power configuration and are not stored in the operating-system keychain.
Global Env remains supported:
TAVILY_API_KEY=...
EXA_API_KEY=...
FIRECRAWL_API_KEY=...Power 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.
Desktop workspace
Web contributes a first-class entry to the Desktop navigation rail with a Sidebar and a Mainview. It declares no separate Config panel: each capability is configured in place.
- Sidebar groups capabilities under 能力, with a 通用 entry at the end. Each capability is a branch with a mode tag on the right (
Auto,Fetch,已关闭, or待配置), expanding to its providers. Each provider row carries a status dot: green when ready, amber when it still needs credentials. - Mainview shows one capability: an enable switch, the resolved provider in the toolbar description, and that capability's own parameters. The browser capability also lists the sessions the provider currently owns. API keys are never returned; only whether a key is configured.
- 通用 holds the parameters shared by all three capabilities (operation timeout, observation character limit) and the config file path with a button to reveal it.
- Advanced holds the parameters that span capabilities: operation timeout, observation character limit, the default browser URL, and an optional Chrome path.
Search, document reading, and browser each have their own on/off switch. Turning a capability off is not the same as choosing a provider, so Off is not listed among the providers.
Web settings are global: one configuration serves every Agent and Workspace, so the workspace asks for no execution scope. Saving is field-scoped: picking a provider submits only its own field, so it never overwrites unsaved input elsewhere on the page.
Creating, observing, and closing browser sessions still happens through Agent actions, so the page never holds a browser on its own.
Defaults
import { WebPower } from "@downcity/powers/web";
const web = new WebPower();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.
WebPower 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.
Browser proxy
Local Chrome applies the network proxy resolved by Desktop: explicit Desktop settings, then
system proxy settings, then Global Env. SDK / CLI usage reads DOWNCITY_PROXY_URL,
HTTPS_PROXY, HTTP_PROXY, and ALL_PROXY in that order, including lowercase forms of
standard variables. With no configured proxy, Chrome follows the system network settings.
Local browsers support HTTP, HTTPS, SOCKS4, and SOCKS5 proxy URLs without usernames or
passwords. Bypass rules come from DOWNCITY_NO_PROXY, NO_PROXY, and no_proxy;
loopback addresses always connect directly.
Existing browser sessions stay open after a proxy change. Find them with
browser_list_sessions and close them with browser_close_session. Creating the next
session restarts an owned browser with the new settings. If a running Web Power browser
has different or unknown proxy settings, close its Chrome window and retry.
Remote CDP proxy settings are managed by the owner of the remote browser.
Fixed SDK configuration
Constructor configuration overrides saved City/Desktop configuration:
const web = new WebPower({
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 WebPower.
Actions
| Action | Purpose |
|---|---|
status | Read the search, document, and browser providers actually active for the current scope |
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 |
browser_list_sessions | List the browser sessions the provider still owns |
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.