Se ejecuta enWrit CloudDesktop
En esta página
Quickstart
De una grabación a un endpoint en marcha.
Writ convierte cualquier sitio web en una API que tu software - y tus agentes de IA - pueden llamar. Esta página cubre los conceptos fundamentales y luego te lleva de cero a JSON estructurado en las dos superficies: el agente local gratuito en tu máquina, y el endpoint publicado en Writ Cloud.
la capa
Qué es Writ.
Writ es la capa de API y MCP para sitios que no tienen API. Creas un workflow - una secuencia de acciones de navegador grabada o descrita a la IA - y lo publicas como managed REST endpoint en /v1/{slug}/{path} y como MCP tool. A partir de ahí, una sola llamada HTTP (o una invocación de MCP tool) hace el trabajo y devuelve datos estructurados.
Writ se ejecuta en tus propias cuentas, con tus propias credenciales y datos, en los sitios que estás autorizado a usar.
vocabulario
Conceptos fundamentales.
| Concepto | Qué es |
|---|---|
| Workflow | Una secuencia de pasos (navigate, fill, click, extract, acciones de IA, ...) que se ejecuta en un navegador real. |
| AI session | Describe un objetivo en lenguaje natural y deja que el cerebro de IA conduzca el navegador para crear o ejecutar un workflow. |
| Monitor | Vigila una página en busca de cambios tan rápido como cada 10 segundos y puede disparar un workflow en el instante en que cambia. |
| Persona | Un inicio de sesión reutilizable y cifrado (con TOTP u OTP por correo) para que los workflows actúen en tus propias cuentas autorizadas. |
| Agent | El ejecutor del navegador: tu máquina local/BYO (sin cargo de cómputo) o la flota cloud de Writ (facturada por tiempo de ejecución). |
| Managed endpoint | Tu workflow publicado expuesto como REST endpoint y MCP tool en /v1/{slug}/{path}. |
| $ wallet | Un saldo prepago. El tiempo de ejecución cloud y los tokens de IA se descuentan de él; las ejecuciones locales no tienen cargo de cómputo. |
quickstart
Cuatro pasos hasta tus primeras llamadas.
Crearás una cuenta, crearás un workflow, lo ejecutarás desde código en tu propia máquina y luego lo publicarás y lo llamarás desde cualquier parte.
1. Crear una cuenta e instalar Writ
Regístrate en app.usewrit.app/register e instala la app de escritorio. Mantiene en marcha el daemon agente local, writ-agentd - la misma superficie de API en http://127.0.0.1:8131 a la que apuntan todos los SDKs. El plan Free se ejecuta en tu propia máquina y no necesita tarjeta.
2. Grabar o describir un workflow
Graba un workflow corto en un navegador real, o describe un objetivo y deja que una sesión de IA lo cree. En ambos casos terminas con un workflow ejecutable: entradas dentro, filas extraídas fuera.
3. Ejecutarlo desde código - en local
Instala un SDK y ejecuta el workflow contra el daemon de tu propia máquina. El cliente descubre el agente en marcha en 127.0.0.1 - sin URL, sin token que pegar:
run.ts
import { WritAgent, runRowId } from "@usewrit/agent-sdk";
const client = new WritAgent(); // discovers the running agent + token
const { data: workflows } = await client.workflows.list();
const run = await client.workflows.runAndWait(workflows[0].id, {
inputs: { city: "Paris" },
});
const { data: rows } = await client.runs.data(runRowId(run));
console.log(run.status, rows); run.py
from writ_agent import WritAgent, run_row_id
with WritAgent() as client: # discovers the local daemon
run = client.workflows.run_and_wait(3, inputs={"city": "Paris"})
print(run["status"], run["rows_extracted"])
print(client.runs.data(run_row_id(run))["data"]) # extracted rows run.go
client, err := writ.Discover(ctx) // find the running agent
page, _ := client.Workflows.List(ctx, nil)
item, _ := client.Workflows.RunAndWait(ctx, page.Data[0].ID, nil)
rowID, _ := item.RowID()
csv, _ := client.Runs.DataCSV(ctx, rowID) // extracted rows as CSV
fmt.Println(item.Status, "
", csv) run.rs
use writ_client::{RunOptions, WritAgent};
let agent = WritAgent::discover().await?; // find the running daemon
let workflows = agent.workflows().list().await?;
let wf = &workflows.data[0];
let outcome = agent.workflows().run_and_wait(wf.id, &RunOptions::default()).await?;
let rows = agent.runs().data(outcome.run.row_id().unwrap()).await?;
println!("{} → {}: {}", wf.name, outcome.run.status, rows.data); Superficie local. Este código habla con writ-agentd por loopback, autenticado con las familias de tokens locales wlt_ / wlk_ / wlo_ - no con tu clave cloud. Tu agent local/BYO hace la navegación, y nada aquí se factura.
4. Publicarlo y llamarlo desde tu software
Publica el workflow como managed endpoint - la publicación le da un slug y un path en tu tenant. Desde entonces, cualquier lenguaje, tarea programada o agente de IA puede llamarlo como REST puro:
call.sh
curl -X POST https://api.usewrit.app/v1/acme/price-check \
-H "Authorization: Bearer $WRIT_CONSUMER_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com/product/42"}' call.py
import os, requests
res = requests.post(
"https://api.usewrit.app/v1/acme/price-check",
headers={"Authorization": f"Bearer {os.environ['WRIT_CONSUMER_KEY']}"}, # csk_...
json={"url": "https://example.com/product/42"},
timeout=120,
)
res.raise_for_status()
payload = res.json()
print(payload["run_id"], payload["data"]) call.ts
const res = await fetch("https://api.usewrit.app/v1/acme/price-check", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.WRIT_CONSUMER_KEY}`, // csk_...
"Content-Type": "application/json",
},
body: JSON.stringify({ url: "https://example.com/product/42" }),
});
if (!res.ok) throw new Error(`Writ call failed: ${res.status}`);
const { run_id, data } = await res.json();
console.log(run_id, data); call.go
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
)
func main() {
body, _ := json.Marshal(map[string]string{"url": "https://example.com/product/42"})
req, _ := http.NewRequest("POST", "https://api.usewrit.app/v1/acme/price-check", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("WRIT_CONSUMER_KEY")) // csk_...
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
var out struct {
RunID string `json:"run_id"`
Data json.RawMessage `json:"data"`
}
json.NewDecoder(res.Body).Decode(&out)
fmt.Println(out.RunID, string(out.Data))
} call.rs
use serde_json::{json, Value};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let key = std::env::var("WRIT_CONSUMER_KEY")?; // csk_...
let res: Value = reqwest::Client::new()
.post("https://api.usewrit.app/v1/acme/price-check")
.bearer_auth(key)
.json(&json!({ "url": "https://example.com/product/42" }))
.send()
.await?
.error_for_status()?
.json()
.await?;
println!("{} {}", res["run_id"], res["data"]);
Ok(())
} Respuesta
{
"run_id": "run_7Qd2",
"status": "succeeded",
"data": { "price": "$129.00", "in_stock": true }
} Esa es la respuesta canónica de un endpoint: un run_id, un status y tus data extraídos. Un run que falla responde status: "failed" - un resultado que leer, no un error HTTP.
Superficie cloud. La puerta publicada responde en https://api.usewrit.app/v1/{slug}/{path} con una clave wt_ como token Bearer - es la única llamada de este quickstart que pasa por Writ Cloud. Las ejecuciones cloud se facturan por tiempo de ejecución desde tu $ wallet; enruta la ejecución a tu propio agent local/BYO y el cómputo sigue siendo gratis. La mecánica de la puerta: los managed endpoints.
convenciones
Dos superficies, una sola gramática.
Todo lo que acabas de hacer siguió las mismas convenciones:
| Superficie | URL base | Auth |
|---|---|---|
| Agente local (writ-agentd) | http://127.0.0.1:8131 | Bearer wlt_ · wlk_ · wlo_ |
| Writ Cloud | https://api.usewrit.app | Bearer wt_ · encabezado X-Writ-Client-Id (sin clave) |
- JSON de entrada, JSON de salida. Las solicitudes y respuestas son
application/json. Los errores son{ "error": "…", "code": "…" }con un código estable - y algunas rutas 4xx responden texto plano, así que tolera el no-JSON al leer un error. - Asíncrono por defecto.
POST /v1/workflows/{id}/runresponde al despachar; añade?wait=truepara bloquear hasta el resultado (timeout en segundos, acotado 1-3600, 120 por defecto). - Un run fallido es un resultado. Recibes la ejecución con su estado; reserva las excepciones para transporte y auth.
- Habla con
127.0.0.1, no conlocalhost. El daemon comprueba Host y Origin contra DNS rebinding, y un gemelo HTTPS escucha en:8132.
La referencia endpoint por endpoint - cada método, ruta, código de error y sobre de lista en ambas superficies - es la referencia de la API.
faq
Preguntas de inicio, respondidas.
¿Necesito una tarjeta de crédito para empezar?
¿Qué significan los prefijos de las claves?
¿Qué devuelve un endpoint publicado?
¿Tengo que usar la nube?
qué sigue
Sigue adelante.
- Autenticación - claves, ámbitos, sesiones, MFA, OAuth, consumer keys.
- Workflows - el objeto, los 30+ tipos de pasos y cómo funcionan las ejecuciones.
- SDKs - los cuatro clientes publicados: TypeScript, Python, Go, Rust.
- referencia de la API - las dos superficies, endpoint por endpoint.
- los managed endpoints - publicación, mapeo de entradas y cuotas de la puerta REST.
- Facturación y uso - cómo se facturan las ejecuciones cloud y cómo añadir fondos.