Skip to content

Connecting Agents

Writ edited this page Jul 28, 2026 · 3 revisions

Connecting agents

The coordinator runs no browsers. It holds your data, serves the UI and decides what should run; agents do the actual browsing. Until one agent is connected, nothing executes — workflows queue, monitors never check.

Agents dial out over WebSocket. They need no inbound ports and work behind NAT. Run as many as you like, anywhere; the coordinator spreads work across whichever have capacity.

The one-line install

Fleet → Connect a new agent gives you a command with a pairing code:

curl -fsSL https://writ.example.com/agent.sh | sh -s -- WRIT-4K2P-9XQ

Run it on the machine that should do the browsing. It detects the platform, downloads the matching release, redeems the code, and starts the agent. It appears in Fleet within a few seconds.

The code is single-use and expires in 15 minutes. It is exchanged once for a real fleet token plus the coordinator URL and document-extractor settings, so none of that has to travel in the command. A code taken from a shell history or a proxy log is already spent.

Codes are case- and dash-insensitive: writ4k2p9xq works as well as WRIT-4K2P-9XQ. The alphabet omits I, L, O and U so a code survives being read aloud.

Manual install

The same modal has Binary and Docker tabs carrying a raw fleet token, for air-gapped hosts or scripted enrolment where a single-use interactive code is the wrong shape.

The fleet worker is writ-agent-fleet and is configured entirely by environment — it has no config file and no config subcommand (that belongs to the separate desktop writ-agent binary):

WRIT_SERVICE_TOKEN=<token> \
WRIT_COORDINATOR_URL=https://writ.example.com \
DOC_EXTRACT_URL=https://docs.writ.example.com \
DOC_EXTRACT_SECRET=<secret> \
writ-agent-fleet
Variable Required What it does
WRIT_SERVICE_TOKEN yes The fleet token. Its presence is what selects infrastructure mode.
WRIT_COORDINATOR_URL yes HTTP(S) base of the coordinator. SAAS_URL is accepted as an alias.
WRIT_HOME no Data directory, default ~/.writ. One worker per directory — a lock enforces it.
WRIT_FLEET_ALLOW_INSECURE no 1 to permit a plaintext http:// coordinator on a non-loopback host.
WRIT_FLEET_STATUS_PORT no Serve a loopback GET /healthz on this port.
WRIT_RETENTION_DAYS no Local retention window, default 90. 0 keeps everything.
DOC_EXTRACT_URL / DOC_EXTRACT_SECRET no Document extraction. Unset means non-HTML content is silently skipped.

Where to get the binary: writ-agent Releases, the ghcr.io/usewrit/writ-agent:latest image, or build it:

cargo build --release --no-default-features --features local,fleet,openai --bin writ-agent-fleet

Running an agent on the coordinator's own host

If you installed with run-local.sh rather than Docker, Fleet → run an agent on this host does the download, configure and launch for you.

It is unavailable on a Docker install, and the button will say so. A container has no host process table and no browser runtime, so it genuinely cannot start an agent on your machine — that is what the one-line installer is for.

Agents on other machines

Two things must be reachable from wherever the agent runs:

  1. WRIT_PUBLIC_URL — the agent discovers the WebSocket gateway from it. If it points at localhost while the agent is elsewhere, the agent retries forever with Connection refused and nothing says why.
  2. DOC_EXTRACT_URL — defaults to a loopback address a remote agent cannot reach. Set it to something routable in .env and every generated connect command picks it up.

Checking the connection

curl -s https://writ.example.com/api/fleet/agents -H "Authorization: Bearer <token>"

Or watch the agent's own log — ~/.writ/agent.log by default. A healthy start ends with:

FleetBridge connected to coordinator agent_id=agent-…

Removing an agent

Fleet → ⋯ → Remove revokes its token and evicts the live connection. Stale offline entries can be cleared with Prune.

Troubleshooting

See Troubleshooting for connection failures, capacity problems and the "agent is online but nothing runs" case.

Clone this wiki locally