S’exécute surWrit CloudDesktop
Sur cette page
Quickstart
D’un enregistrement à un endpoint en production.
Writ transforme n’importe quel site web en une API que vos logiciels - et vos agents IA - peuvent appeler. Cette page présente les concepts fondamentaux, puis vous mène de zéro à du JSON structuré sur les deux surfaces : l’agent local gratuit sur votre machine, et l’endpoint publié sur Writ Cloud.
la couche
Ce qu’est Writ.
Writ est la couche API et MCP pour les sites qui n’ont pas d’API. Vous créez un workflow - une séquence d’actions de navigateur enregistrée ou décrite à l’IA - et vous le publiez comme managed REST endpoint sur /v1/{slug}/{path} et comme MCP tool. Dès lors, un seul appel HTTP (ou une invocation de MCP tool) fait le travail et renvoie des données structurées.
Writ s’exécute sur vos propres comptes, avec vos propres identifiants et données, sur les sites que vous êtes autorisé à utiliser.
vocabulaire
Concepts fondamentaux.
| Concept | De quoi il s’agit |
|---|---|
| Workflow | Une séquence d’étapes (navigate, fill, click, extract, actions IA, ...) qui s’exécute dans un vrai navigateur. |
| Session IA | Décrivez un objectif en langage naturel et laissez le cerveau IA piloter le navigateur pour créer ou exécuter un workflow. |
| Moniteur | Surveille une page à la recherche d’un changement aussi souvent que toutes les 10 secondes et peut déclencher un workflow à l’instant où elle change. |
| Persona | Une connexion réutilisable et chiffrée (avec TOTP ou OTP par e-mail) pour que les workflows agissent sur vos propres comptes autorisés. |
| Agent | L’exécuteur du navigateur : votre machine locale/BYO (sans frais de calcul) ou la flotte cloud Writ (facturée au temps d’exécution). |
| Managed endpoint | Votre workflow publié exposé comme REST endpoint et MCP tool sur /v1/{slug}/{path}. |
| portefeuille $ | Un solde prépayé. Le temps d’exécution cloud et les tokens IA y sont prélevés ; les exécutions locales sont sans frais de calcul. |
quickstart
Quatre étapes vers vos premiers appels.
Vous allez créer un compte, créer un workflow, l’exécuter depuis du code sur votre propre machine, puis le publier et l’appeler depuis n’importe où.
1. Créer un compte et installer Writ
Inscrivez-vous sur app.usewrit.app/register, puis installez l’app de bureau. Elle fait tourner le daemon agent local, writ-agentd - la même surface d’API sur http://127.0.0.1:8131 que visent tous les SDKs. Le palier Free s’exécute sur votre propre machine et ne nécessite aucune carte.
2. Enregistrer ou décrire un workflow
Enregistrez un court workflow dans un vrai navigateur, ou décrivez un objectif et laissez une session IA le créer. Dans les deux cas, vous obtenez un workflow exécutable : des entrées, des lignes extraites en sortie.
3. L’exécuter depuis du code - en local
Installez un SDK et exécutez le workflow contre le daemon de votre propre machine. Le client découvre l’agent en cours d’exécution sur 127.0.0.1 - pas d’URL, pas de token à coller :
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); Surface locale. Ce code parle à writ-agentd en loopback, authentifié avec les familles de tokens locales wlt_ / wlk_ / wlo_ - pas votre clé cloud. Votre agent local/BYO fait la navigation, et rien ici n’est facturé.
4. Le publier et l’appeler depuis vos logiciels
Publiez le workflow comme managed endpoint - la publication lui donne un slug et un path sur votre tenant. Dès lors, n’importe quel langage, tâche planifiée ou agent IA peut l’appeler en REST pur :
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(())
} Réponse
{
"run_id": "run_7Qd2",
"status": "succeeded",
"data": { "price": "$129.00", "in_stock": true }
} C’est la réponse canonique d’un endpoint : un run_id, un status et vos data extraites. Un run qui échoue répond status: "failed" - un résultat à lire, pas une erreur HTTP.
Surface cloud. La porte publiée répond sur https://api.usewrit.app/v1/{slug}/{path} avec une clé wt_ comme token Bearer - c’est le seul appel de ce quickstart qui passe par Writ Cloud. Les exécutions cloud sont facturées au temps d’exécution depuis votre portefeuille $ ; routez plutôt l’exécution vers votre propre agent local/BYO et le calcul reste gratuit. La mécanique de la porte : les managed endpoints.
conventions
Deux surfaces, une seule grammaire.
Tout ce que vous venez de faire suivait les mêmes conventions :
| Surface | URL de base | Auth |
|---|---|---|
| Agent local (writ-agentd) | http://127.0.0.1:8131 | Bearer wlt_ · wlk_ · wlo_ |
| Writ Cloud | https://api.usewrit.app | Bearer wt_ · en-tête X-Writ-Client-Id (sans clé) |
- JSON en entrée, JSON en sortie. Requêtes et réponses sont en
application/json. Les erreurs sont{ "error": "…", "code": "…" }avec un code stable - et quelques chemins 4xx répondent en texte brut, tolérez donc le non-JSON en lisant une erreur. - Asynchrone par défaut.
POST /v1/workflows/{id}/runrépond au dispatch ; ajoutez?wait=truepour bloquer jusqu’au résultat (timeout en secondes, borné 1-3600, 120 par défaut). - Un run en échec est un résultat. Vous récupérez l’exécution avec son statut ; réservez les exceptions au transport et à l’auth.
- Parlez à
127.0.0.1, pas àlocalhost. Le daemon vérifie Host et Origin contre le DNS rebinding, et un jumeau HTTPS écoute sur:8132.
La référence endpoint par endpoint - chaque méthode, chemin, code d’erreur et enveloppe de liste sur les deux surfaces - c’est la référence API.
faq
Questions de démarrage, répondues.
Ai-je besoin d’une carte bancaire pour commencer ?
Que signifient les préfixes des clés ?
Que renvoie un endpoint publié ?
Suis-je obligé d’utiliser le cloud ?
et ensuite
Continuez.
- Authentification - clés, portées, sessions, MFA, OAuth, consumer keys.
- Workflows - l’objet, les 30+ types d’étapes et le fonctionnement des exécutions.
- SDKs - les quatre clients publiés : TypeScript, Python, Go, Rust.
- référence API - les deux surfaces, endpoint par endpoint.
- les managed endpoints - publication, mappage des entrées et quotas de la porte REST.
- Facturation & utilisation - comment les exécutions cloud sont facturées et comment ajouter des fonds.