Documentation
Letting an AI agent operate Ward
Ward’s local API was built so a script could open forty profiles. The same surface lets a coding agent build them: create the folders, add the proxies, generate a device for each profile, open one, drive the browser, close it. This page is how to set that up, and what to tell the agent before you do.
Before you hand one a token
An agent holding a Ward token can act on your working machine. A profile is an account you are signed in to. A proxy is a subscription you pay for. A browser it opens makes real requests, from a real address, to a real service. There is no staging copy of any of it.
That is not an argument against doing it. It is an argument for two habits.
- Hand out the smallest scope that does the job. An agent asked to run a morning routine needs Read and launch, not Full control. It cannot then delete a profile or repoint a proxy, however confidently it decides it should.
- Give it its own token, named after it. Revoking is one click, and a token named “Claude on the studio machine” is one you can revoke six months from now without wondering what else stops working.
Two things it cannot do at any scope
It cannot read a proxy password back - no route returns one. And it cannot delete a profile directory: deleting a profile removes the database row and leaves every cookie and signed-in session on disk. Those two are properties of the API, not of the prompt, so they hold whatever the agent decides to try.
Setting it up
- In Ward, open Settings → Scripts and agents → New token. Name it after the agent and pick a scope.
- Put the token where the agent can read it as an environment variable. Do not paste it into a prompt - a prompt is a transcript, and a transcript gets copied.
- Give the agent the base URL, and tell it to read
/v1/agent-guidefirst.
curl -sH "Authorization: Bearer $WARD_TOKEN" http://127.0.0.1:7817/v1/agent-guideThat guide is served by your copy of Ward, not by this website, and is written for a model rather than a person. It carries the scope of the token that asked for it, the full route table, and the three things below - so an agent that reads it starts with correct expectations instead of assuming Ward works like the last tool it saw.
The prompt
Paste this. It is short on purpose: everything else the agent needs, it can fetch from the host, and a prompt that duplicates the specification is a prompt that goes stale.
You can drive Ward, a browser-profile manager running on this machine.
Base URL: http://127.0.0.1:7817
Auth: send "Authorization: Bearer $WARD_TOKEN" on every request.
Before doing anything, fetch GET /v1/agent-guide and read it. It tells you what
your token is allowed to do and three things about this product that will
otherwise surprise you. GET /v1/openapi.json is the full route table.
Rules:
- Never launch a browser yourself. Ask Ward to start a profile and attach to the
browserWSEndpoint it returns. A browser you started has no proxy and no device
identity and will browse from this machine's own address.
- Never send "fingerprint": "none" unless I asked for it.
- Do not reuse one device identity across several profiles.
- If a request answers 403, stop and tell me. Your scope will not change on retry.
- If you are unsure, do nothing and ask. Every write here is on my working
machine and there is no staging copy of it.What it will get wrong
A capable model reasoning from how every other tool in this category behaves will get three things wrong about Ward. All three are in the in-band guide, and they are worth knowing yourself.
“Delete the profile” does not delete the data
DELETE /v1/profiles/{id} removes the row. The profile directory - the cookies, the sessions, the trusted-device tokens - stays exactly where it is, and the response says where. An agent that reports “deleted” without saying that is giving you a half answer, which is why the response carries the sentence and the guide tells it to pass the sentence on.
It cannot check a proxy password
Asked to “verify the proxy credentials”, a model will look for a route that returns them. There is none. The only test is to start a profile through the proxy and see whether Ward’s probe passes, and the honest answer to the question as asked is that Ward will not tell it.
Restore and a device identity cannot both be honoured
A profile set to reopen its previous tabs will not do so while it is masking a device identity. Restored tabs start loading before Ward can tell the browser what device it is, so the sites that profile is signed in to would see your computer first and the profile’s device a moment later - and an account watching a device change mid-session has a stronger signal than a wrong device would ever have given it. An agent debugging “why did my tabs not come back” needs to know this is a decision rather than a fault.
A real task
A task worth handing over, and roughly what the agent does with it. This is the shape the API was widened for: the part that takes an afternoon by hand is the building, not the launching.
Set up ten profiles for the Acme campaign, one per proxy in the list I put in
proxies.csv, all in a folder called Acme, on Ungoogled Chromium. Then open the
first one and tell me what user agent it reports.GET /v1/status -> confirms scope: full
GET /v1/engines -> is ungoogled-chromium installed? if not, say so
POST /v1/folders -> {"name": "Acme"}
POST /v1/proxies x10, one per row
POST /v1/profiles x10, each with its own generated device identity
POST /v1/profiles/{id}/start -> browserWSEndpoint
...attach, read navigator.userAgent...
POST /v1/profiles/{id}/stopIf the engine is missing, the right answer is to say so rather than to fall back to Chrome. The /v1/engines response says what each browser still talks to on its own, which is the fact that makes “just use Chrome instead” the wrong substitution.
Limits worth saying out loud
The API is local. There is no hosted Ward, no remote endpoint, and no way for an agent running somewhere else to reach this one. An agent has to be on the machine.
Ward has to be open. The API is bound by the application; closing the window closes it. There is no service and no headless mode.
The window does not live-update. A profile an agent creates appears in the list when the list is next read. Nothing is lost - the database is the single source - but do not expect a row to animate into place while you watch.
Ward is not undetectable and an agent should not say it is. A browser that is not patched at the source level is detectable through property-descriptor and prototype inspection. What that means in practice is written up here, and the in-band guide tells the agent to answer that question with a no.