BrowserWeave can extract bounded content from the active page and send it to a
server-managed OpenAI or OpenAI-compatible model connection. The Core contract
is vendor-neutral: core/ai.Provider.Invoke executes a typed request and core/ai.Resolver
maps a literal connection ID to a provider. Studio supplies the concrete
connection store; workflow YAML never contains an API key.
Open Studio settings → 大模型连接 and create a connection with:
- a stable display name;
- an HTTP(S) Base URL such as
https://api.openai.com/v1; responses(OpenAI Responses API) orchat_completions(compatible Chat Completions API);- a default model ID, optional temperature, maximum output tokens, and timeout;
- an optional bearer API key.
The API key is write-only. List, create, update, capabilities, run, event, and
MCP responses never return it. The local server stores model connections under
.browserweave/secrets/model-connections.json with file mode 0600; production
deployments should additionally protect the data directory with encrypted
storage and authenticated ingress.
Connection endpoints:
| Method | Path | Purpose |
|---|---|---|
GET |
/api/model-connections |
List redacted connections |
POST |
/api/model-connections |
Create a connection |
PUT |
/api/model-connections/{id} |
Update; an empty apiKey keeps the stored key |
DELETE |
/api/model-connections/{id} |
Delete a connection |
POST |
/api/model-connections/{id}/test |
Make a minimal real model request |
page.extract reads the whole document body when locator is absent, or one
located element when it is present.
readPage:
type: page.extract
with:
locator: {engine: js, css: main} # optional
format: text # text | textContent | html
maxChars: 50000 # 1..1000000
normalizeWhitespace: true
sensitive: true # explicit privacy opt-in
saveAs: vars.pageContentOnly saveAs, character count, truncation, and sensitivity metadata enter the
step output. Extraction is visible by default. With explicit
sensitive: true, raw page content remains available to downstream nodes but
is redacted from public run snapshots, SSE, callbacks, and webhooks.
For repeated messages, comments, products, rows, or cards, use extract.list
instead of sending the whole page to a model. It returns a bounded typed array
whose fields are selected relative to each matched item. This makes
extract.list → foreach → model.invoke → condition/switch a deterministic,
AI-authorable chain. See AI inbox and comment automation
and examples/ai-inbox-reply.yaml.
analyze:
type: model.invoke
failure:
timeout: 90s
retry: {maxAttempts: 2, baseDelay: 1s, backoff: exponential}
with:
connection: model-main
operation: evaluate
instructions: Return a concise JSON-compatible answer.
input:
question: "${inputs.question}"
page: "${vars.pageContent}"
constraints: {language: zh-CN, concise: true}
saveAs: vars.answer
sensitive: falseconnection is a literal server-side connection ID and cannot be a runtime
template. operation is one of generate, classify, extract, transform,
evaluate, or custom; it is descriptive metadata and does not add hidden
prompts. input accepts any JSON-compatible value composed from literals and
typed workflow bindings. model, temperature, and maxOutputTokens may
override connection defaults. Encoded input is bounded to 2,000,000 bytes and
instructions to 100,000 characters.
Set sensitive: true when the response itself may contain private data. In
that mode raw text remains usable by downstream flow nodes but is redacted at
all public observability boundaries.
Model connections are a control-plane resource, so discovery marks
model.invoke with executionScopes: [saved]. Publish the workflow and invoke
it through Studio, the saved-workflow HTTP API, or MCP workflow_run_saved.
Ad-hoc MCP execution rejects the node before starting Chrome.
For semantic decisions, configure with.output.type: json and optionally
provide output.name, output.schema, and output.strict. saveAs then
receives a typed JSON value rather than response text. Its fields can be bound
directly into action parameters, loop collections, child-workflow inputs, or a
declarative condition node. Invalid JSON fails model.invoke before any
downstream browser side effect. See VALUE_FLOW.md.
The OpenAI Responses adapter follows the official Create a model response
contract:
it posts model, input, optional instructions, and bounded generation
parameters to /responses. The second adapter targets the widely implemented
/chat/completions compatibility surface.
Structured JSON follows OpenAI's Structured model outputs
contract: Responses receives text.format, while Chat Completions receives
response_format. Providers that do not implement schema enforcement can use
JSON mode; Core still requires one complete valid JSON value before continuing.