Short lease with fencing tokens: claim a task for N seconds, renew, release
Lets many agents agree which one works on a task: acquire a named resource for 1-3600 s, renew it while working, release it when done. Every new acquisition returns a strictly larger fencing token; pass it to the downstream store and reject writes carrying a smaller one, so a paused holder whose lease expired cannot clobber its successor. Re-acquiring as the current holder extends the lease with the same token. Scoped to the paying wallet (or tenantId for API-key callers). Not a distributed-systems guarantee beyond that: a lost lease is detected by renew failing.
What you get
Stops two agents buying, sending or deploying the same thing; one $0.005 call per claim.
Call it
Send the JSON body below to https://agents.writerslogic.com/api/v1/lease. An unpaid request answers 402 with the price and how to pay; a request that fails with a 5xx status is not charged.
curl -i -X POST https://agents.writerslogic.com/api/v1/lease \
-H 'content-type: application/json' \
-d '{"op":"acquire","resource":"invoice:INV-1009","holder":"worker-7","ttlSeconds":60,"requestId":"w7-claim-INV-1009"}'
Input
| Field | Type | Required | Description |
|---|---|---|---|
op | string; one of "acquire", "renew", "release", "get" | yes | |
resource | string | yes | Task or resource name, e.g. invoice:INV-1009 or deploy:prod. |
holder | string; length 1..128 | no | Your worker id. Required for acquire, renew and release. |
ttlSeconds | integer; 1..3600 | no | Lease length; default 30. |
token | integer; 1.. | no | Fencing token from acquire; required for renew and release. |
tenantId | string | no | Required for API-key callers (namespaced as key:<tenantId>; keep it unguessable). Ignored when a wallet paid: the payer address is the tenant. |
requestId | string | no | Caller-chosen id for this mutation. A retry with the same id and same input returns the stored response (24 h) instead of applying twice; the same id with different input is rejected. Send one on every mutation you may retry: without it a retry is applied again (fleet-memory record appends a duplicate; a repeated spend-ledger commit or release answers NO_HOLD because the first call already took effect). |
Example request body
{
"op": "acquire",
"resource": "invoice:INV-1009",
"holder": "worker-7",
"ttlSeconds": 60,
"requestId": "w7-claim-INV-1009"
}
Result
The response is { "data": ..., "_provenance": ... }. data carries these fields; _provenance is a signed W3C Verifiable Credential with a C2PA-style manifest, checked free at POST /api/v1/verify-provenance.
| Field | Type | Required | Description |
|---|---|---|---|
status | string; one of "pass", "fail", "unknown", "unsupported" | no | pass: every rule held. fail: a rule was violated (see witnesses). unknown: the input lacks the evidence to decide. unsupported: outside what this engine covers. Missing evidence is never a pass. |
op | string | no | |
granted | boolean | no | acquire/renew: you hold the lease now. release: it is released. get: someone holds it. |
holder | one of | no | Current holder, or null. |
fencingToken | one of | no | Token of the current lease, or null. |
expiresAt | one of | no | ISO time the current lease lapses, or null. |
replayed | boolean | no | True when this response was replayed for a repeated requestId. |
witnesses | array<object> | no | |
versions | object | no | Every semantic dependency of this answer (engine, tables and their as-of dates, tokenizer, calendar, rounding profile). |
limits | array<string> | no | |
deterministic | boolean | no | Always true: pure code, no model. |
Pay and connect
Available through: x402 (USDC on Base), MCP. MCP clients reach it through the agent-coordination-kit package.
Machine-readable
- This agent as JSON (schemas, example, OpenAPI operation)
- Free signed sample response
- OpenAPI 3.1 · Catalog · Index of every agent