Writ Cloud
Read, crawl and act on websites, signed in as the user, and turn any site into an API.
¿Debería usar esto?
Calidad y seguridad
Hallazgos (8)
- HIGH
- LOWen writ_browser_ask_user
- LOWen writ_browser_context
- LOWen writ_browser_network
- LOWen writ_browser_cancel
- LOWen writ_browser_sessions
- LOWen writ_diagnose_http_workflow
- LOWen writ_list_webhooks
Basado en el análisis automatizado de las definiciones de herramientas y el cumplimiento del protocolo.
Costo de contexto
Este es el número aproximado de tokens que se consumen cada vez que las herramientas del servidor se cargan en el contexto de un modelo. Los recuentos más altos reducen la atención disponible para otras tareas.
Instalar
Instalación con un clic
Agrega esto a tu archivo `claude_desktop_config.json`:
{
"mcpServers": {
"writ-cloud": {
"command": "npx",
"args": [
"writ-mcp"
]
}
}
}Paquetes ejecutables
1.2.0stdioPuntos de conexión remotos
https://api.usewrit.app/mcpstreamable-httpQué puede hacer
Inventario de herramientas
Herramientas (40)
🔴writ_browser_use(url, persona_id, goal, use_residential, execution_target)
A REAL CLOUD BROWSER FOR A TASK ON A SITE: the user's signed-in account (a persona_id from writ_personas: the password stays sealed in Writ, and sessions never ask for a password), a click, form, submit or search inside an app, or a page a plain fetch cannot open (login wall, 403, CAPTCHA). Opens the browser and returns the first page; writ_browser_act drives it (Writ runs no model here). Recording is always on: writ_browser_save turns the session into a workflow that replays without a browser, writ_browser_cancel closes it (an open browser bills). The start answer carries the action vocabulary, the recording rules and, with a persona, the 2FA rules. NOT FOR: reading pages (writ_scrape) or building an API (writ_website_to_api).
Esquema de entrada
{
"type": "object",
"properties": {
"url": {
"type": "string"
},
"persona_id": {
"type": [
"integer",
"string"
]
},
"goal": {
"type": "string"
},
"use_residential": {
"type": "boolean",
"description": "Open on the residential network (bot walls, CAPTCHAs)."
},
"execution_target": {
"type": "string",
"description": "cloud | auto | local (the user's own desktop app)."
}
},
"required": [
"url"
]
}🔴writ_record_website(goal, url, persona_id, use_residential)
Records a repeatable task on a site as a workflow (goal + start url): the same session as writ_browser_use, labelled with its goal, driven with writ_browser_act and saved with writ_browser_save. A goal that asks for an API goes to writ_website_to_api's build instead.
Esquema de entrada
{
"type": "object",
"properties": {
"goal": {
"type": "string"
},
"url": {
"type": "string"
},
"persona_id": {
"type": [
"integer",
"string"
]
},
"use_residential": {
"type": "boolean",
"description": "Residential network (bot walls)."
}
},
"required": [
"goal",
"url"
]
}🔴writ_website_to_api(url, goal, save_as, persona_id, mode, ...)
TURNS A WEBSITE INTO A CALLABLE API (named functions with inputs, returning JSON) for a service with no practical official API. 3 calls: (1) this tool with url = the page that already shows the rows (a search-results or listing URL, not the home page) and goal = the inputs and fields wanted; (2) writ_discovery_status(build_id, wait=true); (3) on success, its run_example (writ_run_workflow with function_name). Writ builds it itself (an AI fast path in a real browser, each function live-tested) and first proposes the user's matching saved workflows and marketplace APIs (skip_existing / skip_marketplace build fresh). A sign-in wall answers persona_needed. NOT FOR: reading content (writ_scrape) or a one-off task (writ_browser_use). Modes and the guided build: writ_help('writ_website_to_api').
Esquema de entrada
{
"type": "object",
"properties": {
"url": {
"type": "string"
},
"goal": {
"type": "string"
},
"save_as": {
"type": "string"
},
"persona_id": {
"type": "integer"
},
"mode": {
"type": "string",
"enum": [
"intelligent",
"guided",
"auto",
"fast",
"crawl",
"browser",
"regular",
"deep"
],
"description": "intelligent (default, Writ builds it) | guided (the caller drives) | auto | fast | crawl | browser."
},
"build_id": {
"type": "integer"
},
"skip_existing": {
"type": "boolean",
"description": "Skip the proposal of the user's own matching workflows."
},
"skip_marketplace": {
"type": "boolean",
"description": "Skip the marketplace proposals."
}
}
}🟢writ_discovery_status(build_id, wait, timeout_seconds)
Status of a writ_website_to_api build. wait=true is one held call (up to 75 s) that follows the build to its newest rung and returns when it is done or parked. Answers: succeeded (workflow_id, functions, run_example), failed, cancelled, or needs_guidance (the build is the caller's to finish with writ_website_to_api mode=guided build_id=<id>; its map comes with it).
Esquema de entrada
{
"type": "object",
"properties": {
"build_id": {
"type": "integer"
},
"wait": {
"type": "boolean",
"description": "One held call until done or parked."
},
"timeout_seconds": {
"type": "integer",
"description": "Ceiling for wait=true (up to 75)."
}
},
"required": [
"build_id"
]
}🔴writ_browser_act(session_id, actions, inputs, max_chars)
Runs one batch of actions on an open session and returns the fresh page. Each action is an object, e.g. {"action":"click","selector":"#go"}. DRIVE: navigate, click, fill, type_text, select, check, hover, submit, press_key, scroll, back, wait, wait_for. SEE: query_dom, find_text, read_text, count, get_attributes, inspect, list_candidates, get_dom, get_screenshot. NETWORK: capture_network, get_request, rotate_exit. CODE: evaluate_js, search_scripts, read_script. RECORD: extract {variable,script}, api_call, login_post, probe_write, confirm_write. 2FA: twofa {challenge_method}. A value written {{name}} with its real value in `inputs` becomes a workflow input. Each action's arguments: the session's start answer, or writ_help('writ_browser_act').
Esquema de entrada
{
"type": "object",
"properties": {
"session_id": {
"type": "string"
},
"actions": {
"type": "array",
"items": {
"type": "object"
},
"description": "Ordered action objects, e.g. [{\"action\":\"click\",\"selector\":\"#login\"}]."
},
"inputs": {
"type": "object"
},
"max_chars": {
"type": "integer",
"description": "Clip of the returned page (default 40000)."
}
},
"required": [
"session_id",
"actions"
]
}🟢writ_browser_context(session_id, section)
Re-reads an open session: section=page (url, fields, buttons, cleaned DOM), lists (the page's repeating rows with a live-tested define_function payload for writ_browser_compose), map (the evidence of the build the session is bound to).
Esquema de entrada
{
"type": "object",
"properties": {
"session_id": {
"type": "string"
},
"section": {
"type": "string",
"enum": [
"page",
"lists",
"map",
"explorer",
"concierge_api"
],
"description": "page (default) | lists | map | explorer | concierge_api."
}
},
"required": [
"session_id"
]
}🟢writ_browser_network(session_id, operation, query, method, index)
Searches (operation=search, query, method) or reads in full (operation=detail, index) the backend requests the page made after capture_network: the site's real API. An index feeds writ_browser_compose define_function from_index.
Esquema de entrada
{
"type": "object",
"properties": {
"session_id": {
"type": "string"
},
"operation": {
"type": "string",
"enum": [
"search",
"detail"
],
"description": "search (default) | detail."
},
"query": {
"type": "string",
"description": "Substring filter."
},
"method": {
"type": "string",
"description": "HTTP method filter."
},
"index": {
"type": "integer",
"minimum": 0,
"description": "detail: which call."
}
},
"required": [
"session_id"
]
}🔴writ_browser_compose(session_id, operation, payload)
Authors the workflow in an open session beyond a recording: named API functions (define_function from a captured call's index or a lists payload, live-tested as defined; compile_function for an authenticated request), set_inputs, add_steps, test_function, remove_function, remove_step, list. Payload shapes: writ_help('writ_browser_compose').
Esquema de entrada
{
"type": "object",
"properties": {
"session_id": {
"type": "string"
},
"operation": {
"type": "string",
"enum": [
"list",
"define_function",
"compile_function",
"test_function",
"remove_function",
"add_steps",
"remove_step",
"set_inputs"
],
"description": "list | define_function | compile_function | test_function | remove_function | add_steps | remove_step | set_inputs."
},
"payload": {
"type": "object",
"description": "The operation's arguments."
}
},
"required": [
"session_id",
"operation"
]
}🔴writ_browser_save(session_id, name, description, allow_no_data)
Saves the open session as a replayable workflow and closes the browser. Composed functions become callable API functions, declared inputs become its parameters. The answer carries the steps, the inputs and a run_example; the workflow runs at zero AI cost through writ_run_workflow. A save that references something no run could resolve is refused with the reasons, and the browser stays open.
Esquema de entrada
{
"type": "object",
"properties": {
"session_id": {
"type": "string"
},
"name": {
"type": "string"
},
"description": {
"type": "string"
},
"allow_no_data": {
"type": "boolean",
"description": "Save a workflow that returns no data, on purpose."
}
},
"required": [
"session_id"
]
}🟢writ_browser_ask_user(session_id, kind, question, wait_seconds)
Hands an open session to the Writ user: kind='captcha' (they complete a security check in the live browser), 'twofa' (they supply the one-time code and Writ types it; the code never reaches this conversation), or 'question' (their text answer). Holds up to 60 s; answers answered, waiting_for_user (the same call again) or expired.
Esquema de entrada
{
"type": "object",
"properties": {
"session_id": {
"type": "string"
},
"kind": {
"type": "string",
"enum": [
"captcha",
"question",
"twofa"
],
"description": "captcha | twofa | question."
},
"question": {
"type": "string",
"description": "kind='question': one short sentence."
},
"wait_seconds": {
"type": "integer",
"description": "Hold up to this long (1-60)."
}
},
"required": [
"session_id"
]
}🔴writ_browser_cancel(session_id, discard)
Closes an open browser session (an open cloud browser bills until it is closed). Unsaved work that did more than visit pages is auto-saved first and the reply names it; discard=true keeps nothing.
Esquema de entrada
{
"type": "object",
"properties": {
"session_id": {
"type": "string"
},
"discard": {
"type": "boolean",
"description": "Throw away unsaved steps instead of auto-saving."
}
},
"required": [
"session_id"
]
}🟢writ_browser_sessions(limit)
Lists the account's open cloud browser sessions (each resumable by its session_id).
Esquema de entrada
{
"type": "object",
"properties": {
"limit": {
"type": "integer"
}
}
}🟡writ_personas(action, domain, link_id, persona_id, why)
The user's own accounts on websites (personas): how Writ signs in as them. No password passes through this tool or the conversation, and its answers never ask for one: credentials are typed only into a Writ window. action='list' domain=<site> shows the personas usable there; with none it answers persona_needed: a tell_user for the user, a create_url (a small Writ window with only the sign-in form, pre-filled for the site) and a link_id. action='wait' link_id=<id> is one held call that answers when the user saves it, with its persona_id. Also get, request (a link for another account), sign_in (refresh the session) and record_login. A persona_id works on writ_scrape, writ_crawl_site, writ_browser_use and writ_run_workflow; a desktop persona ('device:...') signs in on that desktop, from its own vault.
Esquema de entrada
{
"type": "object",
"properties": {
"action": {
"type": "string",
"enum": [
"list",
"get",
"request",
"wait",
"sign_in",
"record_login"
],
"description": "list (default) | get | request | wait | sign_in | record_login."
},
"domain": {
"type": "string",
"description": "list: personas usable on this site. request: the site."
},
"link_id": {
"type": "string",
"description": "wait: the link_id of a persona_needed / request answer."
},
"persona_id": {
"type": "integer"
},
"why": {
"type": "string",
"description": "request: one line the user sees in the window."
}
},
"required": [
"action"
]
}🔴writ_payment(action, site, max_amount, purpose, grant_id, ...)
Pays on a site with one of the user's cards; card numbers never reach this conversation. request (site, max_amount, purpose) returns a tell_user and an open_url where the user approves; wait (grant_id or confirmation_id); checkout pauses at the order button for the user's confirmation, then Writ places the order; fill; list (card handles only). Details: writ_help('writ_payment').
Esquema de entrada
{
"type": "object",
"properties": {
"action": {
"type": "string",
"enum": [
"request",
"wait",
"checkout",
"fill",
"list"
],
"description": "request | wait | checkout | fill | list."
},
"site": {
"type": "string",
"description": "request: the store's domain."
},
"max_amount": {
"type": "number",
"description": "The most it may charge."
},
"purpose": {
"type": "string",
"description": "One line the user reads."
},
"grant_id": {
"type": "string"
},
"confirmation_id": {
"type": "string"
},
"session": {
"type": "string",
"description": "The browser session on the checkout page."
},
"commit_selector": {
"type": "string",
"description": "checkout: the place-order button."
}
},
"required": [
"action"
]
}⚪writ_devices(action, device)
The user's linked Writ desktops: list, use (scope this connection to one: runs, browsers, personas and monitors then target it), clear, monitors, datasets.
Esquema de entrada
{
"type": "object",
"properties": {
"action": {
"type": "string",
"enum": [
"list",
"use",
"clear",
"monitors",
"datasets"
],
"description": "list (default) | use | clear | monitors | datasets."
},
"device": {
"type": "string",
"description": "use: the desktop's agent_id or name."
}
}
}🟢writ_list_workflows(search)
Lists the workflows saved in the Writ account; each runs on demand without live browsing. Returns id, name, declared inputs, schedule, and whether it is pinned as its own run_<name> tool.
Esquema de entrada
{
"type": "object",
"properties": {
"search": {
"type": "string",
"description": "Name/description filter, e.g. a site."
}
}
}🔴writ_run_workflow(workflow_id, workflow, inputs, function_name, persona_id, ...)
Runs a saved workflow by workflow_id or name and returns its extracted data (it waits by default). Inputs go as top-level fields or under `inputs`; function_name runs one function of a multi-function API (with the sign-in it needs). max_age reuses a recent result at no cost. A write function previews with mutation_mode='dry_run'. Runs sign in as the workflow's persona or persona_id; no password is ever passed. Venue, network, files and output shape: writ_help('writ_run_workflow').
Esquema de entrada
{
"type": "object",
"properties": {
"workflow_id": {
"type": [
"integer",
"string"
],
"description": "A number, or 'local:<id>' (a workflow on the user's desktop)."
},
"workflow": {
"type": "string",
"description": "Workflow name (or workflow_id)."
},
"inputs": {
"type": "object",
"description": "Run inputs (top-level fields work too)."
},
"function_name": {
"type": "string",
"description": "One function of a multi-function workflow."
},
"persona_id": {
"type": [
"integer",
"string"
],
"description": "Run as this saved identity."
},
"max_age": {
"type": "integer",
"minimum": 0,
"description": "Reuse a result younger than this many seconds (free). 0 = fresh."
},
"mutation_mode": {
"type": "string",
"enum": [
"live",
"dry_run",
"private_test"
],
"description": "live (default) | dry_run (preview, nothing sent) | private_test."
},
"execution_target": {
"type": "string",
"description": "cloud | auto | local (the user's own desktop app)."
}
}
}🔴writ_update_workflow(workflow_id)
Inspects or edits a saved workflow: an outline, one function's source, targeted function or step edits, a settings patch. Every option: writ_help('writ_update_workflow').
Esquema de entrada
{
"type": "object",
"properties": {
"workflow_id": {
"type": "integer"
}
}
}🔴writ_create_http_extraction(goal, workflow_id, apply)
Drafts or revises a multi-request browserless HTTP extraction (loops, GraphQL, cursor pagination) from captured requests and a plain-language goal. Every option: writ_help('writ_create_http_extraction').
Esquema de entrada
{
"type": "object",
"properties": {
"goal": {
"type": "string"
},
"workflow_id": {
"type": "integer"
},
"apply": {
"type": "boolean",
"description": "false (default) drafts; true writes."
}
},
"required": [
"goal"
]
}🟢writ_diagnose_http_workflow(workflow_id, task_id)
Explains why a saved workflow's run returned nothing or failed: HTTP-lane readiness and, with task_id, the run's requests and responses.
Esquema de entrada
{
"type": "object",
"properties": {
"workflow_id": {
"type": "integer"
},
"task_id": {
"type": "integer"
}
}
}⚪writ_pin_workflow_tool(workflow_id, pinned)
Pins (or unpins) a saved workflow as its own run_<name> tool on this server.
Esquema de entrada
{
"type": "object",
"properties": {
"workflow_id": {
"type": "integer"
},
"pinned": {
"type": "boolean"
}
}
}🟢writ_workflow_data(workflow_id, q, run_id, limit, refs)
Reads a saved workflow's collected data as a table: q filters, run_id picks one run, refs returns full records.
Esquema de entrada
{
"type": "object",
"properties": {
"workflow_id": {
"type": "integer"
},
"q": {
"type": "string"
},
"run_id": {
"type": "integer"
},
"limit": {
"type": "integer"
},
"refs": {
"type": "array",
"items": {
"type": "string"
},
"description": "Full records by '<run_id>:<record_index>'."
}
}
}🟢writ_search_data(q, workflow_id, limit)
Searches everything the account's workflows already collected for a term, without running anything.
Esquema de entrada
{
"type": "object",
"properties": {
"q": {
"type": "string"
},
"workflow_id": {
"type": "integer"
},
"limit": {
"type": "integer"
}
},
"required": [
"q"
]
}🟢writ_export_data(workflow_id, format)
Exports a workflow's full data table as CSV or JSON.
Esquema de entrada
{
"type": "object",
"properties": {
"workflow_id": {
"type": "integer"
},
"format": {
"type": "string",
"description": "csv (default) | json."
}
}
}🟢writ_workflow_runs(workflow_id, status, limit)
Run history (status, timing, errors, venue) of one workflow or all of them.
Esquema de entrada
{
"type": "object",
"properties": {
"workflow_id": {
"type": "integer"
},
"status": {
"type": "string",
"description": "Filter by status."
},
"limit": {
"type": "integer"
}
}
}🔴writ_set_schedule(workflow_id, every_minutes, kind, time, days, ...)
Schedules a saved workflow: every_minutes, or kind='daily'/'weekly' with time (HH:MM) and days. functions + inputs schedule chosen functions of a multi-function API.
Esquema de entrada
{
"type": "object",
"properties": {
"workflow_id": {
"type": "integer"
},
"every_minutes": {
"type": "integer",
"description": "Interval in minutes."
},
"kind": {
"type": "string",
"description": "interval | daily | weekly."
},
"time": {
"type": "string",
"description": "HH:MM (daily/weekly)."
},
"days": {
"type": "array",
"items": {
"type": "integer"
},
"description": "Weekdays 1=Mon..7=Sun (weekly)."
},
"tz": {
"type": "string",
"description": "IANA timezone."
}
}
}🟡writ_expose_workflow_api(workflow_id, label)
Publishes a saved workflow as a REST endpoint (a POST URL that waits and returns its JSON). Repeated calls reuse it.
Esquema de entrada
{
"type": "object",
"properties": {
"workflow_id": {
"type": "integer"
},
"label": {
"type": "string"
}
}
}🔴writ_crawl_site(url, intent, rank_cap, seed_urls, page_budget, ...)
COLLECTS a site or a section into a queryable, change-tracked dataset (one row per page). Scope: intent (a section, in plain words), rank_cap=N (the top N items of a listing), seed_urls (known pages), or the whole site capped by page_budget. Modes: markdown (default, no AI), extract_mode='schema' (uniform records), executor='ai' + extract_prompt (per-page understanding, 5x the page rate). A bounded crawl answers with its rows; an open one returns a crawl_id for writ_crawl_status wait=true. NOT FOR: reading a few pages now (writ_scrape). Every option: writ_help('writ_crawl_site').
Esquema de entrada
{
"type": "object",
"properties": {
"url": {
"type": "string"
},
"intent": {
"type": "string",
"description": "The section wanted, in plain words; the server derives paths and depth."
},
"rank_cap": {
"type": "integer",
"minimum": 1,
"maximum": 50,
"description": "Top N items of a listing (one page per agent, in parallel)."
},
"seed_urls": {
"type": "array",
"items": {
"type": "string"
},
"description": "Exact pages to collect (no discovery)."
},
"page_budget": {
"type": "integer",
"description": "Cap on pages fetched."
},
"extract_mode": {
"type": "string",
"description": "markdown (default) | schema | html."
},
"executor": {
"type": "string",
"description": "regular (default, no AI) | ai (5x the page rate)."
},
"extract_prompt": {
"type": "string",
"description": "With executor=ai: what to extract from each page."
},
"persona_id": {
"type": [
"integer",
"string"
]
},
"save_as": {
"type": "string"
},
"wait": {
"type": "boolean",
"description": "Hold until done and return the rows (default true when bounded)."
}
},
"required": [
"url"
]
}🟢writ_saved_crawls(limit)
Lists the crawls saved for re-running, with their scope.
Esquema de entrada
{
"type": "object",
"properties": {
"limit": {
"type": "integer"
}
}
}🔴writ_update_saved_crawl(crawl, settings)
Inspects or changes a saved crawl's settings in place.
Esquema de entrada
{
"type": "object",
"properties": {
"crawl": {
"type": "string"
},
"settings": {
"type": "object",
"description": "Sparse settings patch."
}
},
"required": [
"crawl"
]
}⚪writ_run_saved_crawl(crawl, max_age, wait)
Runs a saved crawl; max_age returns its recent data at no cost instead of re-crawling.
Esquema de entrada
{
"type": "object",
"properties": {
"crawl": {
"type": "string"
},
"max_age": {
"type": "integer",
"minimum": 0,
"description": "Reuse a run younger than this (seconds)."
},
"wait": {
"type": "boolean",
"description": "Hold until done."
}
},
"required": [
"crawl"
]
}🟢writ_saved_crawl_data(crawl, limit)
Reads the data a saved crawl collected on its last completed run, without crawling.
Esquema de entrada
{
"type": "object",
"properties": {
"crawl": {
"type": "string"
},
"limit": {
"type": "integer"
}
},
"required": [
"crawl"
]
}🟢writ_scrape(url, urls, top_n, format, render_mode, ...)
READ PAGES NOW, no browser session: one page (url), up to 20 pages in parallel (urls), or a listing plus its top N item pages (url + top_n). Returns clean markdown in 2-10 s, including pages a plain fetch cannot read: rendered by JavaScript (render_mode='browser'; a read that only got the page's shell says so and gives the retry), behind a bot wall or 403 (an automatic residential retry), or behind the user's sign-in (persona_id). Discussion threads keep their comments. format='html' returns the raw HTML for selectors. NOT FOR: a site-wide dataset (writ_crawl_site) or clicking and typing (writ_browser_use).
Esquema de entrada
{
"type": "object",
"properties": {
"url": {
"type": "string"
},
"urls": {
"type": "array",
"items": {
"type": "string"
},
"description": "Up to 20 known pages, read in parallel."
},
"top_n": {
"type": "integer",
"minimum": 1,
"maximum": 20,
"description": "With url = a listing: also read its N top-ranked item pages (max 20)."
},
"format": {
"type": "string",
"enum": [
"markdown",
"html",
"both"
],
"description": "markdown (default) | html (raw HTML) | both."
},
"render_mode": {
"type": "string",
"description": "auto (default: HTTP, a browser when the page needs JS) | http | browser."
},
"persona_id": {
"type": [
"integer",
"string"
],
"description": "Read signed in as this saved identity (writ_personas)."
},
"use_residential": {
"type": "boolean",
"description": "Residential network for a bot wall (automatic retry when refused)."
}
}
}🟢writ_crawl_status(crawl_id, wait, limit)
Status of a crawl by crawl_id; wait=true holds up to 75 s and returns the collected rows when it converges.
Esquema de entrada
{
"type": "object",
"properties": {
"crawl_id": {
"type": "integer"
},
"wait": {
"type": "boolean",
"description": "Hold until done and inline the rows."
},
"limit": {
"type": "integer"
}
},
"required": [
"crawl_id"
]
}🟢writ_crawl_files(crawl_id, crawl)
The original files (PDFs, office documents, images, CSVs) a crawl captured, with short-lived download URLs.
Esquema de entrada
{
"type": "object",
"properties": {
"crawl_id": {
"type": "integer"
},
"crawl": {
"type": "string"
}
}
}🟡writ_create_automation(name, when, schedule, on_workflow, target_id, ...)
Creates an automation: on an event (a workflow or crawl completed, a monitor change, a webhook, a schedule) it runs a workflow, sends a notification templated over the event's data, and/or wakes an AI agent. Event, template and webhook options: writ_help('writ_create_automation').
Esquema de entrada
{
"type": "object",
"properties": {
"name": {
"type": "string"
},
"when": {
"type": "string",
"enum": [
"workflow_completed",
"workflow_started",
"crawl_completed",
"crawl_failed",
"ai_session_completed",
"ai_session_started",
"change_detected",
"webhook_received",
"scheduled"
],
"description": "workflow_completed | crawl_completed | change_detected | webhook_received | scheduled | ..."
},
"schedule": {
"type": "object",
"description": "when='scheduled': {kind, interval_minutes | time, days, tz}."
},
"on_workflow": {
"type": "string",
"description": "Source workflow for workflow_* events."
},
"target_id": {
"type": "integer",
"description": "change_detected: the monitor_id."
},
"run_workflow": {
"type": "string",
"description": "Workflow to run."
},
"notify": {
"type": "string",
"description": "Message template, e.g. {{result.extracted_data.0.title}}."
},
"channels": {
"type": "array",
"items": {
"type": "string"
},
"description": "Notification channels."
},
"ai_prompt": {
"type": "string",
"description": "Wake an AI agent with this task."
}
},
"required": [
"name"
]
}🟢writ_list_webhooks(webhook_trigger_id)
The account's inbound webhook URLs and the automations they fire.
Esquema de entrada
{
"type": "object",
"properties": {
"webhook_trigger_id": {
"type": "integer",
"description": "Only this webhook."
}
}
}🟡writ_create_monitor(url, interval, selector, extract, watch, ...)
WATCHES a page for changes: Writ checks it on a schedule and fires change_detected when the page, a CSS selector's text, a value read by `extract`, or a visual zone changes. Returns the monitor_id that writ_wire_monitor connects to an alert, a workflow or an AI task (a price watch takes a threshold there). Without `interval` the answer is needs_input: this plan's options and a tell_user for the user, nothing created. The page is read first: a sign-in answers needs_persona, a bot check offers use_residential.
Esquema de entrada
{
"type": "object",
"properties": {
"url": {
"type": "string"
},
"interval": {
"type": [
"string",
"integer"
],
"description": "How often: an option id from needs_input ('5m', '1h', '24h') or seconds."
},
"selector": {
"type": "string",
"description": "CSS selector whose text is watched (unset = whole page / uptime)."
},
"extract": {
"type": [
"object",
"string"
],
"description": "Browserless read instead of a selector, e.g. {\"from\":\"html_css\",\"selector\":\".price\"}."
},
"watch": {
"type": "string",
"enum": [
"content",
"price"
],
"description": "content (default) | price (the value must hold a number)."
},
"session_id": {
"type": "string"
},
"persona_id": {
"type": [
"integer",
"string"
]
},
"use_residential": {
"type": "boolean",
"description": "Check through a residential exit (bot walls)."
}
},
"required": [
"url"
]
}🟡writ_wire_monitor(monitor_id, action, channels, recipients, threshold, ...)
Connects a monitor's change_detected event to an action: action='notify' (channels and recipients the account has configured), 'workflow' (runs a saved workflow), or 'ai_task' (an AI agent opens the page and works `prompt`). A price watch takes `threshold` (+ threshold_op): the action then runs once, when a check reads a price at or below it. Buying at a price (`buy`): writ_help('writ_wire_monitor').
Esquema de entrada
{
"type": "object",
"properties": {
"monitor_id": {
"type": "integer"
},
"action": {
"type": "string",
"enum": [
"workflow",
"notify",
"ai_task"
],
"description": "notify | workflow | ai_task."
},
"channels": {
"type": "array",
"items": {
"type": "string"
},
"description": "Notification channels, e.g. [\"email\",\"pushover\"]."
},
"recipients": {
"type": "array",
"items": {
"type": "string"
},
"description": "e.g. [\"email:3\"]; omitted = every enabled recipient."
},
"threshold": {
"type": [
"number",
"string"
],
"description": "Price watch: act once when the price reaches this number."
},
"threshold_op": {
"type": "string",
"enum": [
"lt",
"lte",
"gt",
"gte"
],
"description": "lte (default) | lt | gte | gt."
},
"workflow": {
"type": "string"
},
"prompt": {
"type": "string",
"description": "action='ai_task': what the agent does."
},
"buy": {
"type": "object",
"description": "Run the workflow or task as a purchase (saved as a rehearsal until armed)."
}
},
"required": [
"monitor_id",
"action"
]
}🟢writ_help(topic)
The full reference of any Writ tool (every parameter and its rules) and the complete guide. topic = a tool name (e.g. 'writ_browser_compose', a 'run_<workflow>' tool), 'guide' for the manual (recurring digests, HTTP flow building, buying on a price, crawl and build modes), 'actions' / 'recording' / '2fa' for the browser rules, or empty for the list of topics.
Esquema de entrada
{
"type": "object",
"properties": {
"topic": {
"type": "string",
"description": "A tool name, 'guide', 'actions', 'recording', '2fa', or empty."
}
}
}Comunidad
Evidencia