Preview. These docs describe the interface WIRK launches with. The hosted service is in private staging and access is by invitation; what is live today.
review
A proposal is a change waiting for a person. review decides proposals: accept applies the change exactly as previewed, reject closes it, defer keeps it waiting.
People decide proposals, directly or by asking their agent to. Nobody accepts their own proposal: the service refuses it with not_authorized ("You proposed this; someone else accepts it"). The author may still withdraw it (reject) or defer it.
Find and read proposals
wirk status
wirk query proposal=proposed,deferred
wirk query c4a1e902
Fetching a proposal shows exactly what it would change:
c4a1e902 · proposal · proposed · r1 · by nightly-agents (agent) · changed 1h ago
Mark webhook retries completed
The retry fix merged in 4f2a9c1 and the retry tests pass.
Diff
~ 5c1e7a90 r3 Retry failed webhooks
status in_progress → completed
decide with: review c4a1e902@1 ACTION --reason REASON
more: query c4a1e902 depth=all
r1 is the proposal's revision. Every decision, including defer, makes a new one.
Decide
wirk review c4a1e902@1 accept --reason 'Verified: tests pass on main'
wirk review c4a1e902@1 e7b35d16@2 defer --reason 'Wait for the load test'
The last word is the action; every other one is ID@N. The CLI requires a real reason and refuses the placeholders ACTION and REASON, so a pasted decide with: line decides nothing until you fill it in.
MCP: wirk_review with the request body below; request_id is optional there.
Request
POST /v2/review
Authorization: Bearer <token>
{"request_id": "r-5d0e3a9c71",
"decisions": [
{"id": "c4a1e902",
"revision": 1,
"action": "accept",
"reason": "Tests pass on main"}]}
| Key | Notes |
|---|---|
decisions | Required. 1–32; each is decided on its own |
id | A full (proposal_…) or short proposal ID |
revision | The rN you read |
action | accept, reject or defer |
reason | Up to 2,048 characters. The CLI and MCP server require one |
request_id | 1–200 characters. Required on the wire; the CLI and MCP server make one when you leave it out |
workspace_id, format | As everywhere |
Response
Reviewed r-5d0e3a9c71 · 1 decision: 1 decided
accepted c4a1e902 r1 → r2
{"ok": true,
"data": {"request_id": "r-5d0e3a9c71",
"results": [{"id": "proposal_c4a1e902…", "action": "accept", "outcome": "accepted", "r": 2}]},
"errors": [], "notices": [], "page": {"complete": true, "next_cursor": null}, "timing_ms": {"total": 7.9}}
Each decision stands on its own. When some are decided and others are not, the answer is HTTP 207 and says which and why:
Reviewed r-9a4c2e6b18 · 3 decisions: 1 decided · 1 conflicted · 1 skipped
accepted c4a1e902 r1 → r2
conflicted e7b35d16 · basis_changed: the proposal is at r3 (deferred by alice); you read r2
Fetch it again (query e7b35d16) and decide at the revision it shows, under a new request_id.
skipped 3a1f9c20 · not_authorized: you proposed this; someone else accepts it
Accepting can also conflict when an item the proposal changes has moved on since it was proposed. Nothing is half-applied: a proposal applies whole or not at all. A proposal that creates or changes context is decided by whoever maintains that context, or by an administrator.
Retries
As with write: resend the identical body with the same request_id after an uncertain result, or look it up with wirk query receipt=r-5d0e3a9c71.
All codes: Errors.