Skip to main content
Glama

Writ Cloud

Act in a browser session

writ_browser_act
Destructive

Runs one batch of actions on an open browser session and returns the fresh page. The caller is the session's brain: Writ runs no model here, and a batch performs exactly the navigations, clicks, fills, captures, probes and scripts it carries. It also composes, for clients without writ_browser_compose: actions=[{action:'define_function', name:'feed.list', from_index:3, ...}] or [{action:'compose', operation, payload}]; a batch mixing these with page actions is refused. Actions placed after a navigate, click or select that changes the page run against a page the caller has not seen yet. RECORDING RULES: {{name}} as an action value (select/fill/type_text value, navigate url) with the real value in inputs ({"name": "real value"}) declares the workflow input name: the page gets the real value and the step keeps {{name}}. An extract {variable,script} (a read-only JS IIFE returning rows/fields) at the position that shows the data records it, and its result comes back in this answer. A fill with data_key holds a secret server-side and the saved step keeps a {{secret:...}} placeholder. Interactions are recorded as steps; SEE/HEAR/NETWORK probes and wait never are: replay waits for each step's selector by itself, and a wait the task needs is an explicit wait_for step (writ_browser_compose add_steps). ACTIONS: DRIVE: navigate {url} · click {selector | field_index | button_index} · fill {selector,value,data_key?,human_layer?} · type_text {selector,value} · select {selector,value} · check {selector} · hover {selector} · submit {selector} · press_key {key} · scroll {direction,amount} · back · wait {seconds} · wait_for {selector,timeout}. SEE (granular first): query_dom {selector,limit,offset,attrs?,text_chars?,html_chars?} (every match as compact records, each with a css path) · count {selector} · find_text {text,selector?,exact?,limit?} (the deepest elements showing that text, with paths) · get_attributes {selector,index?} (one element: all attrs, value, box, options) · read_text {selector,all?,limit?,max_chars?} · inspect {selector,limit?,max_chars?} (match count + outerHTML) · list_candidates (the page's repeating row shapes, the entry point for a list/table) · list_frames · get_dom {selector?,depth?,max_chars?} (the real cleaned HTML, the most expensive read) · get_screenshot {x?,y?,width?,height?}. TABS / FILES / 2FA: list_tabs / switch_tab {index} · upload {selector,mode,file_slot} · wait_for_download {trigger_selector,output_key} · twofa {challenge_method,selector?,submit_selector?} (the persona's one-time code, minted server-side; covered by 2FA RULES). HEAR: get_console {level?,since?,query?,exclude?,limit?} (console messages, uncaught JS errors with stack, failed/blocked requests since the last read; the page's console_since_last_read counts show when there is something new; it shows why a sign-in, click or extraction did nothing) · page_errors (only the uncaught exceptions). NETWORK: capture_network {reload?} (the backend calls the page makes, i.e. the site's real API; writ_browser_network searches and reads them) · get_request {url substring} (one call in full) · rotate_exit {reason} (alone in its batch: restarts on a fresh residential address when the site refused the current one, e.g. a sign-in rejected with correct credentials, content held back, an IP rate limit; the page's browser_init.exit shows the address and its network). RUN CODE: evaluate_js {script,world?} (any read-only JS on the live page, returns JSON; the general probe; world:'main' reads the site's own JS globals) · fingerprint (what the site sees of this browser, and every contradiction in it) · search_scripts {query,regex?,url_contains?,frame_url?} (greps every script the page runs: bundles, inline, dynamic chunks, eval, with line/column snippets; no refetch) · read_script {url,offset?,length?} (a window of one, to read around a match). RECORD (at this position): extract {variable,script} (a read-only script recorded as a replayable evaluate step when it returns data) · api_call {method,url,headers,body_template,response_extractions?,variable} for one request, or api_call {flow:{version:1,steps:[...]},inputs:{...},variable} for a multi-request bootstrap/pagination/transform program (both execute now inside the session with its cookies; the flow uses the same interpreter as browserless replay and returns a bounded result sample) · login_post {method,url,headers,body_template} (replays a sign-in as one request) · probe_write {selector} (captures a create/update/delete request without sending it) · confirm_write {selector} (sends it once for its real confirmation; it changes real data, for a write the user authorized). Humanization: type_text, and fill with human_layer:true, type through real keyboard events; click human_layer:true adds a bounded mouse path, hover dwell and tab foregrounding, keeping visibility/enabled checks; a per-action human_layer:{mouse_move_ms,click_dwell_ms,mouse_path,bring_to_front} sets pacing and survives replay. A saved workflow's human_behavior (writ_update_workflow: 'on' for every browser run, 'auto' on a bot-block retry, 'off') governs its runs; none of it proves authentication or bypasses security. A login submit that leaves the page unchanged was still sent. 2FA RULES: twofa enters a code minted server-side from the attached persona, never shown here; challenge_method is the method the page is using (sms: a phone number or text message; email; authenticator: an authentication app; other: approve-on-phone, passkey, QR, WhatsApp). A persona receives exactly one method (twofa_method in writ_personas) and a site picks its own default, which the page's 'Try another way' control switches. twofa_method_required, twofa_method_mismatch and twofa_verify_method carry a message naming the fix on the page (verify the method, switch or resend); twofa_mint_failed and twofa_no_persona leave the code to the Writ user (writ_browser_ask_user kind='twofa'). Credentials, codes and decisions come only from the persona or the user. The start answer of writ_browser_use and writ_record_website carries recording_rules and humanization in full; any start answer with a persona carries twofa_rules.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
inputsNoValues held server-side for {{placeholder}} substitution, e.g. {"city":"Paris"}. Secrets here or on a fill's data_key stay out of the recorded steps.
actionsYesOrdered action objects, e.g. [{"action":"click","selector":"#login"}].
max_charsNoClip of the returned page_dom / page_text (default 40000, ≤200000). A get_dom probe on a real app is 500KB; evaluate_js / inspect / read_text return just the target.
session_idYesSession id from the start tool.

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observed

TDQS

Score is being calculated.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.