tx claim
Claim a task with a lease to prevent parallel collisions
Purpose
tx claim marks a task as being actively worked on by a specific worker. This prevents multiple agents from picking the same task and duplicating work. Claims use a lease-based model with automatic expiry.
At A Glance
Lease Lifecycle
Collision Block
Claim a Task
tx claim <task-id> <worker-id> [options]Arguments
| Argument | Required | Description |
|---|---|---|
<task-id> | Yes | Task ID (e.g., tx-a1b2c3d4) |
<worker-id> | Yes | Worker ID (e.g., worker-abc12345) |
Options
| Option | Description |
|---|---|
--lease <m> | Lease duration in minutes (default: 30) |
--json | Output as JSON |
--help | Show help |
Examples
# Claim with default 30-minute lease
tx claim tx-abc123 worker-def456
# Claim with 60-minute lease
tx claim tx-abc123 worker-def456 --lease 60
# JSON output
tx claim tx-abc123 worker-def456 --jsonimport { TxClient } from '@jamesaphoenix/tx-agent-sdk'
const tx = new TxClient({ apiUrl: 'http://localhost:3456' })
// Claim a task with a 60-minute lease
const claim = await tx.claims.claim('tx-abc123', 'worker-1', 60)
// Returns: { id, taskId, workerId, claimedAt, leaseExpiresAt, renewedCount, status }
console.log(`Claimed until ${claim.leaseExpiresAt}`){
"tool": "tx_claim",
"arguments": {
"taskId": "tx-abc123",
"workerId": "worker-1",
"leaseDurationMinutes": 60
}
}# Claim a task with a 60-minute lease
curl -X POST http://localhost:3456/api/tasks/tx-abc123/claim \
-H "Content-Type: application/json" \
-d '{"workerId": "worker-1", "leaseDurationMinutes": 60}'
# Claim with default lease duration
curl -X POST http://localhost:3456/api/tasks/tx-abc123/claim \
-H "Content-Type: application/json" \
-d '{"workerId": "worker-1"}'
# Get the active claim for a task
curl http://localhost:3456/api/tasks/tx-abc123/claimRelease a Claim
Release a worker's claim on a task, allowing other workers to claim it.
tx claim release <task-id> <worker-id> [options]Arguments
| Argument | Required | Description |
|---|---|---|
<task-id> | Yes | Task ID |
<worker-id> | Yes | Worker ID that holds the claim |
Options
| Option | Description |
|---|---|
--json | Output as JSON |
--help | Show help |
Examples
tx claim release tx-abc123 worker-def456import { TxClient } from '@jamesaphoenix/tx-agent-sdk'
const tx = new TxClient({ apiUrl: 'http://localhost:3456' })
await tx.claims.release('tx-abc123', 'worker-1'){
"tool": "tx_claim_release",
"arguments": {
"taskId": "tx-abc123",
"workerId": "worker-1"
}
}# Release a claim
curl -X DELETE http://localhost:3456/api/tasks/tx-abc123/claim \
-H "Content-Type: application/json" \
-d '{"workerId": "worker-1"}'Renew a Claim
Extend the lease on an existing claim. Use this for long-running tasks to prevent the claim from expiring.
tx claim renew <task-id> <worker-id> [options]Arguments
| Argument | Required | Description |
|---|---|---|
<task-id> | Yes | Task ID |
<worker-id> | Yes | Worker ID that holds the claim |
Options
| Option | Description |
|---|---|
--json | Output as JSON |
--help | Show help |
Limits
- Maximum 10 renewals per claim
- Fails if the lease has already expired
- Fails if no active claim exists for this task and worker
Examples
tx claim renew tx-abc123 worker-def456import { TxClient } from '@jamesaphoenix/tx-agent-sdk'
const tx = new TxClient({ apiUrl: 'http://localhost:3456' })
const renewed = await tx.claims.renew('tx-abc123', 'worker-1')
console.log(`New expiry: ${renewed.leaseExpiresAt}`)
console.log(`Renewals: ${renewed.renewedCount}/10`){
"tool": "tx_claim_renew",
"arguments": {
"taskId": "tx-abc123",
"workerId": "worker-1"
}
}# Renew a claim's lease
curl -X POST http://localhost:3456/api/tasks/tx-abc123/claim/renew \
-H "Content-Type: application/json" \
-d '{"workerId": "worker-1"}'Atomic Ready + Claim
For parallel workers, use tx ready --claim to atomically fetch and claim a task in one step. This eliminates the race window between separate tx ready and tx claim calls.
# One command: find the best ready task AND claim it
tx ready --json --limit 1 --claim worker-1 --lease 30This is the recommended approach for multi-worker setups. See tx ready for full details.
Use Case: Parallel Agent Execution
Without claims, parallel agents might pick the same task:
# Problem: Both agents pick the same task
Agent1: tx ready --limit 1 → tx-abc123
Agent2: tx ready --limit 1 → tx-abc123 # Same task!With claims:
# Solution: Claims prevent collision
Agent1: tx claim tx-abc123 worker-1 # Success
Agent2: tx claim tx-abc123 worker-2 # Fails - already claimedParallel Agent Loop (Recommended)
#!/bin/bash
# Use atomic ready+claim to avoid race conditions
WORKER_ID="worker-$$"
while true; do
RESULT=$(tx ready --json --limit 1 --claim "$WORKER_ID" --lease 30)
TASK=$(echo "$RESULT" | jq -r '.task.id // empty')
[ -z "$TASK" ] && break
claude "Your task is $TASK. Run 'tx show $TASK' for details."
tx done "$TASK"
doneTwo-Step Pattern (Legacy)
#!/bin/bash
WORKER_ID="worker-$$"
while true; do
TASK=$(tx ready --json --limit 1 | jq -r '.[0].id // empty')
[ -z "$TASK" ] && break
# Try to claim - skip if another worker got it
tx claim "$TASK" "$WORKER_ID" || continue
# Work on the task
claude "Your task is $TASK. Run 'tx show $TASK' for details."
# Complete and release
tx done "$TASK"
doneBehavior
- Claiming creates a lease with an expiry time
- Expired leases allow other workers to claim the task
- Completing a task (
tx done) does not require releasing the claim first - Long tasks should periodically renew with
tx claim renew