The pattern
Use a deterministic, single-segment lock name for the task: for example github-issue-1842 or customer-sync-72. Every agent attempts the same acquire request before it starts. One gets status: "acquired"; the rest get status: "held" and should skip or retry later.
Keep the lock name stable and compact. Put rich details in metadata, not in the path.
Why agents need a lease
Duplicate prevention
Multiple workers may see the same issue, ticket, or queue item. Acquisition makes ownership explicit.
Operator visibility
Metadata can include model, runner, task URL, trace ID, branch, or human escalation context.
Crash recovery
If a worker disappears, renewal stops and the lock expires without a manual cleanup job.
Minimal claim loop
LOCK="github-issue-1842"
TOKEN="YOUR_TOKEN"
claim=$(curl -s -X POST "https://api.octostore.io/locks/$LOCK/acquire" \
-H "Authorization: Bearer ***" \
-H "Content-Type: application/json" \
-d '{"ttl_seconds":120,"metadata":"runner=agent-3 task=https://github.com/acme/app/issues/1842"}')
# If status is acquired, do the work and renew before expiry.
# If status is held, another worker owns it.
Operational guidance
- Choose a TTL long enough for brief pauses, short enough for useful recovery.
- Renew at roughly half the TTL while work continues.
- Release when work completes; if the process dies, rely on expiry.
- Treat downstream writes as idempotent. The lock prevents normal duplication, but retries and external side effects still need care.
- Keep metadata under 1 KB and include only data you are comfortable showing to operators.
Read the deeper write-up
The blog post covers design tradeoffs for hosted agents, including lease duration, metadata, renewal, and stale-worker recovery.
Distributed locking for hosted agents