Expand description
§writ-client
Official Rust SDK for the Writ local agent (writ-agentd) — the loopback
HTTP API on 127.0.0.1:8131 (see sdks/DESIGN.md and
sdks/openapi/writ-agent.yaml in the Writ repository).
use writ_client::{WritAgent, RunOptions};
let agent = WritAgent::discover().await?; // env → ~/.writ/runtime.json → probe
let workflows = agent.workflows().list().await?;
let first = &workflows.data[0];
let outcome = agent
.workflows()
.run_and_wait(first.id, &RunOptions::default())
.await?;
println!("{} → {}", first.name, outcome.run.status);§Design notes
- Async-only, built on
reqwest; the library itself has no tokio dependency (any reqwest-compatible runtime works). - Every list method returns a uniform
Page, whatever envelope the daemon used on the wire. - Errors are the three-kind model of DESIGN.md §5:
WritError::Api,WritError::Connection,WritError::Discovery. No automatic retries. - Models type the stable scalar fields and keep everything else in an
extramap, so a newer daemon never breaks deserialization.
Structs§
- Agent
/v1/agent+/v1/health.- Agent
Status GET /v1/agent— lightweight daemon status (server.rs::agent_status).- ApiKey
- A scoped
wlk_API-key record (store/local_api_keys.rs;key_hashis never serialized by the daemon). The plaintextkeyappears only in the create response — capture it immediately. - Automation
- An automation (event→action rule) row, JSON-TEXT columns parsed by the daemon
(
api/v1/automations.rs::automation_response). - Automations
/v1/automations.- Bytes
- A cheaply cloneable and sliceable chunk of contiguous memory.
- Cancel
Outcome - Outcome of a cancel call. A
202answers{run_id, status:"cancel_requested"}; a409answers{status:"not_running", ...}— per DESIGN.md §7 the 409 is a valid result, not an error, so both land here. - Cloud
Client - The async client for the tiered Writ Cloud surface (see the module docs).
- Cloud
Client Builder - Configuration for
CloudClient.build()performs no network I/O; the only side effect is reading/minting~/.writ/client_idon the first keyless call (lazily), never at construction. - Crawl
/v1/crawl— the Dragnet whole-site crawl. One crawl fans a seed URL across a bounded in-process worker pool; extracted pages aggregate under a synthetic per-crawl workflow (CrawlJob::data_workflow_id) read back through the Data API.- Crawl
Cancel POST /v1/crawl/:id/cancel→ the refreshedCrawlJobview pluscancel_requested_now(true iff this call flipped a live crawl tostopping; false when it was already terminal). Never a 409 — always the view.- Crawl
Job - A Dragnet crawl-job status view (
api/v1/crawl.rs::to_viewoverstore/crawl_jobs.rs::CrawlJob). One crawl fans a seed URL across a bounded in-process worker pool; extracted pages aggregate under the syntheticCrawlJob::data_workflow_idworkflow, read back through the Data API. As with monitor rows, the boolean columns arrive as SQLite0/1ints and stay typed asi64(not coerced). - Crawl
List GET /v1/crawl→{crawls: [CrawlJob…]}. Not acrate::Page: this endpoint answers a named object, mirroring the daemon’s other non-envelope list (/v1/data).- Crawl
Start Params - Body for
POST /v1/crawl— start a Dragnet whole-site crawl. Onlyurlis required (empty → the daemon400s); every unset optional field is omitted from the wire body so the daemon fills its documented default. - Data
/v1/data+/v1/workflows/:id/data*— the extracted-data surface. Shapes are query-engine-driven, so responses stay loosely typed.- Dataset
- One row of
GET /v1/datasets— a dataset that has accumulated extracted data, sourced from either a crawl or a workflow. - Dataset
List GET /v1/datasets→{datasets: [Dataset…]}. Not acrate::Page: likeCrawlList, this endpoint answers a named object rather than the list envelope (unwrap itsdatasetsfield).- Dataset
Meta GET /v1/datasets/:id→ one dataset’s metadata + schema.columns/facetsare query-engine-driven, so they stay loosely-typedValues.- Dataset
Ref - The dataset a search hit belongs to — the identifying subset the search endpoints echo back per result.
- Dataset
Search Hit - One hit from
GET /v1/datasets/searchorGET /v1/datasets/:id/search.fields/highlightare query-engine-driven (dynamic columns), so they stay loosely-typedValues. - Dataset
Search Result GET /v1/datasets/searchandGET /v1/datasets/:id/search→ full-text search results across the unified dataset index.- Datasets
/v1/datasets— the unified dataset index over crawl- and workflow-sourced extracted data. Metadata is typed (DatasetList/DatasetMeta); the records/export shapes are query-engine-driven, so those stay loosely typed (as with theDatasurface).- Extractor
- A field extractor under a selector (
store/selector_extractors.rs). - Extractors
/v1/extractors(+/v1/selectors/:sid/extractors).- Files
/v1/files— metadata + byte I/O.- Health
GET /v1/health— deep health probe (server.rs::health).- Keyless
Quota - Remaining keyless allowance echoed back on keyless calls.
- Keys
/v1/keys— scopedwlk_API keys (requires themanage-capablewlt_token).- MapCounts
returned/totalcounts on aMapResult.- MapEntry
- One ranked URL in a
MapResult. - MapOptions
- Options for
CloudClient::map. - MapResult
- A site’s URLs, ranked by an optional
search(CloudClient::map). - Monitor
- A monitor (target) row, enriched with live check state
(
api/v1/monitors.rs::enrichoverstore/targets.rs). - Monitor
History GET /v1/monitors/:id/changes— paginated change + uptime history.- Monitors
/v1/monitors(+/v1/changes/recent).- Page
- One page of list results, normalized across every wire envelope.
- Persona
- A persona in its redacted wire form (
api/v1/personas.rs::shape): secrets collapse tohas_*booleans +linked_secretsnames; no*_encryptedcolumn ever appears. - Personas
/v1/personas.- RunCompleted
- Terminal run document returned by
workflows().run_wait(..)(?wait=true). - RunData
GET /v1/runs/:id/data→{run_id, status, data}(default JSON lane).- RunFeed
Item - Enriched run-feed item (
api/v1/runs.rs::RunFeedItem). - RunOptions
- Options for
POST /v1/workflows/:id/run(andrun_and_wait). - RunOutcome
- Final answer of
crate::resources::Workflows::run_and_wait. - RunResults
GET /v1/runs/:id/results→{run_id, status, result}.- RunStarted
POST /v1/workflows/:id/run→202 {run_id, status:"running"}.- Runs
/v1/runs— read + control. Ids are the numeric row id (RunFeedItem::row_idparses it out of the composite feed id).- Scrape
Result - One clean-markdown page (
CloudClient::scrape). - Secret
Meta - Secret metadata (
api/v1/secrets.rs::meta) — the value is never returned. - Secrets
/v1/secrets— metadata only; secret values never come back over this API.- Selector
- A content selector under a monitor (
store/target_selectors.rs). - Selectors
/v1/monitors/:id/selectors— selectors nested under a monitor.- Stored
File - A stored-file handle in its OpenAI-style wire form
(
api/v1/files.rs::WireStoredFile). - Vault
/v1/vault/*— the app-lock control surface.- Vault
Status GET /v1/vault/status→{enabled, locked, idle_timeout_secs}.- Workflow
- A workflow row as returned by the API (
store/workflows.rs::Workflow, shaped byapi/v1/workflows.rs::redact):credentials_encryptednever appears; the daemon addshas_credentials,credential_keys,placeholders,has_loginand re-hydrates JSON-TEXT columns (steps,functions, …) into real JSON. - Workflows
/v1/workflows.- Writ
Agent - The async client for a local Writ agent (
writ-agentd). - Writ
Agent Builder - Configuration builder.
build()performs no network I/O (and no filesystem discovery); the only I/O it can do is reading the CA file passed toWritAgentBuilder::ca_pem_file.discover()runs the full DESIGN.md §4 algorithm for whichever of base URL / token was not provided. - WsTicket
POST /v1/ws-ticket→{ticket, expires_in_secs}.
Enums§
- Cloud
Tier - Which access tier a
CloudClientresolved to. - Dataset
Format - Output shape for a dataset read (the
?format=query param). - RunEvent
- One frame of the
GET /v1/runs/:id/eventsSSE stream (engine/events.rs::RunEvent, tagged on"event", snake_case). - Writ
Error - Every failure surfaced by this SDK.
Type Aliases§
- Extra
- Catch-all for wire fields this SDK does not type. Keyed by field name.
- Result
- Convenience alias used across the crate.
- RunEvent
Stream - A live stream of
RunEvents; ends after a terminalfinished/errorframe.