Agents

For AI agents

Sessions, registered agents and agent tokens, pathScope, the MCP server and every tool, orientation commands, --json, weave serve, parallel stitching, retries and a recommended workflow.

View as Markdown

Weave treats an AI agent as a first-class author. This page covers everything an agent, or the system that runs agents, needs: identity, tokens, limits, the MCP server, orientation tools, machine-readable output, speed and a recommended workflow.

Quick start for an agent#

bash
export WEAVE_TOKEN=wva_…          # this agent's own token
export WEAVE_AGENT=builder-1      # this agent's session name
weave clone acme/shop && cd shop
weave serve --detach              # keep one fast process for this checkout
weave --json outline --exports-only --budget 2000
weave --json claim 'app/checkout/**' --feature part:checkout --partial
# ... edit files ...
weave --json stitch -i "Checkout page" -w "part checkout of the build plan" --paths app/checkout

Sessions: --agent#

Every command runs as a session: --agent <name> (or WEAVE_AGENT), else you. Each session has its own active workstream, its own private draft (.weave/drafts/<session>/) and its own lock, so several agents can work in one folder without sharing a draft or waiting for each other. --agent-model <model> (or WEAVE_AGENT_MODEL) records the model.

On the hosted service, the agent credited on a stitch comes from the token, never from the client. With an agent token, stitches are recorded as that registered agent (with the model the client sends). With a person's token, the stitch is credited to the person, and --agent only separates drafts and local records.

Register agents and issue agent tokens#

An agent is registered in an organization. It acts for the person who issued its token, under its own id agent:<agentId>, and only ever reaches repositories of its own organization.

In the web UI: organization → Settings → Agents (owners and admins). Under Register an agent enter a Name, a Kind (Worker or Verifier) and optionally Paths it may change, and click Register agent. Then, on the agent's row, choose a Token lifetime (15 minutes, 1 hour, 4 hours or 24 hours) and click Issue token. Give the token to the agent as WEAVE_TOKEN.

Over the API (a personal access token; the caller must be an owner or admin of the organization, with 2FA on):

bash
# register (scope org:admin)
curl -s https://weave.directory/api/v1/orgs/acme/agents \
  -H "Authorization: Bearer $WEAVE_PAT" -H "Content-Type: application/json" \
  -d '{"name": "builder-1", "kind": "worker", "pathScope": ["app/**", "lib/**", ".weave/decisions/**"]}'
json
{ "id": "cm9x2…", "userId": "agent:cm9x2…", "name": "builder-1", "kind": "worker",
  "pathScope": ["app/**", "lib/**", ".weave/decisions/**"], "disabled": false, "disabledAt": null,
  "createdAt": "2026-10-30T12:00:00.000Z", "activeTokens": 0 }
bash
# issue a token (scope tokens:write)
curl -s https://weave.directory/api/v1/agents/cm9x2…/tokens \
  -H "Authorization: Bearer $WEAVE_PAT" -H "Content-Type: application/json" \
  -d '{"ttlMinutes": 1440, "repositoryIds": ["cm3k…"], "scopes": ["repo:read", "repo:write"]}'
json
{ "token": "wva_…", "id": "…", "agentId": "cm9x2…", "expiresAt": "2026-10-31T12:00:00.000Z",
  "scopes": ["repo:read", "repo:write"], "repositoryIds": ["cm3k…"] }
FieldRules
name[A-Za-z0-9][A-Za-z0-9._-]{0,62}, unique in the organization (duplicate → 409 conflict).
kindworker (default) or verifier.
pathScopeOptional glob list (≤ 50). Empty or absent: no path limit for a worker; a verifier gets the default test paths.
ttlMinutesDefault 60, maximum 1440 (24 hours). Renew before it expires.
repositoryIdsOptional; must belong to the agent's organization.
scopesOnly repo:read and repo:write (both by default). Scopes the issuing token lacks are dropped.
  • The plain token is returned once. Agent tokens start with wva_, are stored hashed, and are refused once the agent is disabled.
  • An agent's access = the issuer's access ∩ the token's repositoryIds ∩ its scopes. It never exceeds the issuer's.
  • Agent tokens work on the Weave server and the CLI. They are refused on the platform's /api/v1 (403), except worker agents removing and restoring workstreams.
  • List agents: GET /api/v1/orgs/{slug}/agents. Disable one (revokes all its tokens): DELETE /api/v1/orgs/{slug}/agents/{id}. A disabled agent's new token requests answer 409 agent_disabled.

Workers and verifiers#

WorkerVerifier
PurposeBuilds featuresWrites and runs tests, reviews
Default pathScopenone (anything)**/tests/**, **/test/**, **/*_test.*, **/*.test.*, **/*.spec.*, **/spec/**, **/specs/**
Remove / restore workstreamsYes (with write access)Never

A pathScope you give replaces the default; it doesn't add to it. To give a verifier decision records too, list the test globs again plus .weave/decisions/**.

pathScope#

A pathScope is a list of globs (* stays within one path segment, ** crosses segments). Every write is checked against it: stitches, web edits and moves, claims, accepting suggestions, change-request resolutions, reverts, promotions, restores and seeding. A write touching a path outside it is refused:

json
{ "type": "error", "code": "path_out_of_scope", "message": "…", "paths": ["lib/db.ts"], "pathScope": ["app/**"] }

Add .weave/decisions/** to every agent's pathScope. Decision records are files stitched with the code (weave stitch -w drafts one), so an agent without it can't stitch a why.

One token per agent#

Give each builder agent its own agent token. Weave tells authors apart by token: user plus verified agent. Agents sharing one person's token look like one author to the server, which means:

  • the clash check can't protect them from each other (one agent can silently take back another's work as "its own undo");
  • claims are shared (stitch --paths releases that person's claims on those files);
  • notices count "my claims" across all of them;
  • batch stitches and credit go to that person.

The MCP server#

weave mcp is an MCP server over stdio. Its instructions explain the workflow to the agent. Run it per agent so tools act as that session:

bash
claude mcp add weave -- weave --agent builder-1 mcp     # Claude Code
weave install-claude                                    # adds a Weave pointer to ./CLAUDE.md

weave init (interactive) can also wire Claude Code, Gemini CLI, Cursor and Codex. WEAVE_MCP_LOG (warn, debug, …) sets its stderr log level.

Every MCP tool#

ToolParameters (? optional)Does
outlinepaths[], exports_only?, budget_tokens? (4000), json?As weave outline: signatures per file, owner, whose draft changed it.
ownerspaths[], fresh?As weave owners --json: owner, part label, lease of files, symbols and JSON keys.
symbol_contexttarget, budget_tokens? (600), json?As weave context: one card about a symbol.
find_symbolsquery, limit? (20), json?As weave find: keyword search over symbols on disk.
search_codequery, limit? (10, max 50), budget_tokens? (800), paths[], json?As weave search: semantic + keyword search.
noticessince?, json?As weave notices for this MCP server's session.
resolutionspoint?, all?Open resolution points (or one, by tag), as JSON.
decisions_forsymbols[] or file, radius? (1), budget_tokens? (800), include_hidden?, format? (summary | constraints)Decisions on symbols and their neighbours; constraints gives KEEP/NEVER lines.
decision_searchquery, near[], budget_tokens? (600), include_hidden?Ranked search over decisions.
decision_getids[]Full decision records.
impactsymbol, depth? (1), budget_tokens? (500)Callers and callees with their decision counts.
decision_proposeanchors[], title, why, alternatives[], constraints[], supersedes?, comment?Record a decision; it joins the draft and is sealed with the next stitch.
decision_reviewstatus_filter? (needs_review), budget_tokens? (600)Decisions whose code changed since they were made.
send_messageto[], body, about_path?, about_symbol?, reply_to?Send a Weave message.
read_messagesunread_only? (true), thread?, limit? (20)Read messages (does not mark them read).
mark_messages_readids[] or all?Mark messages read.
wait_for_messagetimeout_secs? (120, max 600)Block until a message arrives; marks what it returns read.
thread_show, thread_add, thread_add_many, thread_list, thread_search, symbol_list—Short behaviour notes per symbol (threads) and the symbol list.

Message tools need a connected checkout.

Orientation: know the code without reading it all#

These read the files on disk, so they see every agent's in-progress work in the checkout, not only what is weaved.

CommandMCP toolGives
weave outline [paths|globs] [--exports-only] [--budget N]outlinePer file: each symbol's signature, + exported / - local, owner and part label, [changed-in-draft-of <agent>]
weave owners [paths|globs] [--fresh]ownersOwner of files, symbols and JSON keys, part label, lease left (local copy ≤ 15 s old)
weave context <file::symbol> [--budget 600]symbol_contextSignature, doc line, owner, whether it is in someone's draft, callers and callees, decisions, last stitch's intent and why
weave search "<question>" [--limit] [--budget] [--paths a,b]search_codeSemantic search on the head combined with keyword hits on disk (Search)
weave find <words> [--limit]find_symbolsKeyword search over symbol names, signatures and doc lines on disk
weave notices [--since <cursor>]noticesWhat other drafts changed that your code uses; routed clashes; server notices
weave status --symbols—Your draft by symbol, signatures before / after (for fix rounds)
weave drafts --all-sessions—Which session holds which files
weave decision for <targets> --format constraintsdecisions_forKEEP: / NEVER: lines for a starter pack
weave contract declare|check|remove—Planned interfaces between parts, checked against disk
bash
weave outline lib --exports-only --budget 1500
# lib/cart.ts  [owner builder-2 part checkout 8m] [changed-in-draft-of builder-2]
#   + export function addToCart(id: string, qty: number): void
#   + export function cartTotal(items: Item[]): number
weave context lib/cart.ts::addToCart
weave decision for lib/cart.ts::addToCart --format constraints
# KEEP: Prices are integers in cents — floats lost pennies in totals [D-7f3a]
# NEVER: store prices as floats [D-7f3a]

--budget cuts output to about that many tokens (4 characters each), keeping exported symbols first and saying what was cut. Callers, callees and notices resolve references by name, so very common names can over-report.

Contracts between parts#

bash
weave contract declare lib/cart.ts::addToCart \
  --signature "export function addToCart(id: string, qty: number): void" --owner part:commerce
weave contract check --strict          # ok / MISMATCH / MISSING; exit 1 when one is not ok
weave contract remove lib/cart.ts::addToCart

Contracts live in .weave/contracts.toml, local to the checkout (not stitched). They compare normalised signature text (whitespace, export, pub ignored), not types. Write signatures as weave outline prints them.

--json: one document per command#

Add --json (before or after the command) to any command an agent runs. stdout then carries exactly one JSON document; text goes to stderr.

  • Success: the command's fields plus warnings, exit status 0. Hashes are full 64-hex, times RFC 3339, symbols file::Qualified::name.
  • Failure: {"error": {"code", "message", "retryable", "error_id"?, …}, "warnings": […]}, exit status 1.
  • weave contract check --strict exits 1 with its document; weave msg wait exits 2 on timeout ({"messages": [], "timed_out": true}).
  • Commands with nothing to report as JSON (login, config, mcp, watcher, foreground serve, …) refuse --json with unsupported before doing anything.

Error codes#

error.codeMeaningRetry?
unavailableA temporary server storage failure (retryable: true, with error_id)Yes, the same command
unreachableThe server could not be reached; a stitch is queued for weave pushYes
busyAnother weave command holds the lockYes
rejectedThe weave check refused a stitch (reject_code, authors, stitches, symbols)After fixing
claim_conflictA claim target is held (conflicts)Use --partial or ask the owner
needs_dependenciesweave promote without --with-deps (dependencies)With --with-deps
needs_newer_serverThe server doesn't support this requestUpgrade the server
bad_request, unauthenticated, forbidden, not_found, conflict, internalThe server's own error codeNo (internal carries an error_id)
push_failed, not_a_repository, not_running, unsupported, errorLocal failuresNo

Warning codes#

warnings is in every document, maybe empty, as {"code", "message", "paths"}:

CodeMeans
routedA change went to someone as a suggestion because it clashes with their newer work
held_on_diskAn un-added edit was kept on disk because it clashes with the new version
left_out_foreignEdits on disk in another agent's draft were left out of weave add
held_backChanges awaiting their owners were left out of a stitch
resolution_pointYour rejected change was kept beside theirs
adoptedFiles were taken over from another session's draft
draft_keeps_yours, carried_on_disk, carried_forwardYour draft kept your version / was carried onto a newer head
change_requests_opened, clash_change_requestChange requests were opened (the latter in local mode)
decision_recorded, no_decisionA decision record was or wasn't drafted from --why
left_ignored, all_or_nothingPaths ignored by .weaveignore; --partial fell back to all-or-nothing on an older server

weave stitch --json includes result (weaved, suggested, resolved or awaiting), stitch, head, suggestions, routed, held_back and files (written, removed, carried, held). Shapes of every command: CLI reference.

Retrying retryable errors#

A temporary storage failure on the server answers 503:

json
{ "type": "error", "code": "unavailable", "message": "…", "retryable": true, "error_id": "3f9a1c2b7d40" }
  • The CLI already resends the same sealed stitch up to 3 times (backoff 2 s, 4 s) and prints each attempt with the error id. The server recognises a stitch it already weaved (duplicate: true), so a resend never weaves twice. If every attempt fails, your draft is kept.
  • When you call the API yourself: resend reads, submit_stitch / submit_stitches (the same changeset or batch), change-request resolutions with a stitch, blob uploads, claims, releases and lease renewals as they are. Other writes (submit_edit, revert, undo, promote, create workstream, messages) may have been applied: check first, for example the workstream's history.
  • Always log the error_id and quote it when reporting a problem. internal errors carry one too.
  • 429 rate_limited comes with Retry-After: back off.

weave serve: one fast process per checkout#

Agents that run hundreds of commands should start one daemon per checkout:

bash
weave serve --detach         # background; log in .weave/serve.log; stops after 30 idle minutes
weave status                 # now answered by it: same output, exit status and identity
weave serve --status         # pid, version, uptime, commands served and running, connections, files watched
weave serve --stop
  • Later weave commands in the checkout forward their arguments, working directory and environment to it and print what comes back. Each command keeps its own identity (--agent / WEAVE_AGENT, WEAVE_TOKEN, WEAVE_USER, HOME) and takes the same locks; commands run concurrently. One daemon serves every agent and login in the checkout, with one kept server connection per token.
  • It keeps the server connection, loaded states and (with the watcher, on by default on Linux) the walk and stat of files on disk. Use --no-watch when other machines or sandboxes change the files (a network filesystem), --watch to force it elsewhere.
  • If no daemon answers within a second, it is another build of weave, or anything goes wrong before it starts the command, the command runs by itself — never twice. Commands that read stdin, would prompt, run for long or set things up (init, clone, login, msg wait, mcp, …) always run by themselves.
  • --idle-timeout <secs> (default 1800; 0 = never). WEAVE_NO_DAEMON=1 runs one command by itself; WEAVE_DEBUG_SERVE=1 says on stderr why a command didn't use the daemon.
  • In a test with the server 100 ms away, weave add . went from about 540 ms to 220 ms. Unix only (not Windows).

Security model#

  • The socket lives outside the checkout: $XDG_RUNTIME_DIR/weave/<checkout hash>.sock, else ~/.weave/run/<checkout hash>.sock, in a folder only you can open (0700; the socket 0600). Connections from other users are refused by their peer credentials.
  • It only answers clients that present its key (a random secret in a 0600 file in the same folder), so another sandbox that shares the checkout but not your home can't use it.
  • A command whose HOME, USERPROFILE, XDG_RUNTIME_DIR, WEAVE_SERVER_URL, WEAVE_PLATFORM_URL or umask differ from the daemon's — or that runs after the checkout's server configuration changed — runs by itself.
  • The daemon only connects to the server and platform it was started for. A token in a client's WEAVE_TOKEN is used, but never sent anywhere else.
  • --socket .weave/sock (and WEAVE_SOCKET for clients) puts the socket in the checkout instead, as an explicit choice.

Stitching in parallel#

Stitch each part as soon as it passes its own checks. Don't save everything for the end.

bash
# a worker finishing its part: add + stitch + release claims, in one command
weave --agent builder-1 stitch -i "Checkout page" --paths app/checkout lib/cart.ts

# take a sub-agent's drafted changes to those paths along
weave --agent builder-1 stitch -i "Checkout page" --paths app/checkout --also-session builder-1-tests

# seal several sessions' drafts and weave them in one request
weave stitch -i "part {session}" --sessions builder-1,builder-2,builder-3
  • --paths adds those files or folders from disk, stitches only them (the rest of the draft stays drafted) and, once they weaved, releases the claims your identity holds on them. --keep-claims keeps them. Files with parts routed to owners stay claimed.
  • --also-session <session> first takes that session's drafted changes to those paths over, as weave add --adopt, with a decision record naming it.
  • --sessions seals the whole drafts of the named sessions on this device and sends them in one submit_stitches request: woven in order under one workstream lock, one head update, an outcome per stitch. {session} in the intent becomes each session's name. One failing session leaves the others alone (the command then exits non-zero). The server credits every stitch of the batch to the token's identity, so builders that must be credited separately should stitch their own parts with their own tokens (in parallel).
  • Measured with 6 sessions and 60 ms added latency: 0.44 s all at once against 2 s one after another.

Locks#

Each command holds its session's lock (.weave/locks/sessions/<session>.lock) for its whole run, so two commands of one agent run one after the other while other agents run alongside. The checkout-wide .weave/lock is held only while a command reads or writes files on disk (about 20 ms), never while it talks to the server. A command waits up to 30 s for a lock (busy). WEAVE_LOCK_LOG=<file> writes one JSON line per lock released.

Seed a new app from a template#

bash
weave init --server https://api.weave.directory        # in a new, empty repository's folder
weave seed --from acme/starter                         # its main head
weave seed --from acme/starter --workstream dev        # or another workstream's head
weave seed --from acme/starter --state <64-hex>        # or an exact state

The server copies the template's files itself, in one stitch by you — nothing is uploaded. The target workstream must be empty (409 otherwise). You need write on the target and read on the template (a token limited to repositoryIds must include the template). Files a lawful purge removed are left out and listed; the seeded repository's own secret check runs on every file. Seed main first, then create dev and other workstreams so they start from the seeded head. API: POST /api/weave/{repoId}/workstreams/{ws}/seed with {"fromRepo": "<template repo id>"} (plus state or fromWorkstream).

Many agents, one checkout#

A tested setup for a builder running many agents in one sandbox:

  1. Upgrade the server first, then give every agent in the checkout the same CLI version. An older CLI in the same checkout is safe but slow (it holds .weave/lock for whole commands) and can silently take back a clash a 0.4.0 CLI routed.
  2. Register one worker agent per builder and issue each its own wva_ token, with pathScope including .weave/decisions/**.
  3. One checkout: weave clone <org>/<repo>, then weave serve --detach.
  4. Each agent runs with its own WEAVE_AGENT=<name> and WEAVE_TOKEN=<its token> (or --agent), and its own MCP server (weave --agent <name> mcp).
  5. Each agent claims its part with --feature part:<id> (--partial to take what is free) and stitches with --paths as soon as the part passes its checks.
  6. Agents read weave notices (or get them with tool results) and weave msg between turns.
  7. At the end: weave drafts --all-sessions --json, then adopt or stitch orphaned drafts; check weave sync --json for held before recording a head; schedule weave resolve tasks for open resolution points.
  1. Orient with outline, owners, search and context instead of reading whole files. Answer "who has this file?" with owners before asking.
  2. Read constraints: weave decision for <symbols> --format constraints.
  3. Claim your part's scope: weave claim <targets> --feature part:<id> (--partial if others may hold some).
  4. Edit files on disk.
  5. Check your work (build, tests), then weave status --symbols to review your draft by symbol.
  6. Stitch with an intent and a why: weave stitch -i "…" -w "…" --paths <your files>.
  7. Handle the outcome: weaved — done; suggested / routed — not a failure, the owner decides; read the message.
  8. Stay informed: weave notices, weave msg inbox, weave sync.
  9. Follow up open resolution points as their own task: weave resolutions, then weave resolve.

Rules of thumb#

  1. Use --json everywhere and parse it, not text.
  2. Retry on retryable; log every error_id.
  3. A routed clash is not a failure. Never treat a __rp_ copy as permanent code.
  4. One agent token per agent; add .weave/decisions/** to its pathScope.
  5. Stitch each part when it passes its checks; don't batch everything for the end.
  6. Upgrade every agent sharing a checkout together.
  7. Never put secrets in code: the server refuses them (secret_detected).
  8. Repository ids, not org/name, go in /api/weave/{repoId} URLs.