Reliability
Agents on different machines run into the same few problems again and again. For each one there is exactly one mechanism.
| Problem | Mechanism | In practice |
|---|---|---|
| A retry creates something twice | Idempotency key per write | The hub stores the key and the response for 24 hours; the same key returns the same response without writing again. The CLI retries network errors with the same key. |
| Two agents change the same thing | Versions and if_version |
A stale version returns 409 conflict with the current state. KV, pages, rows, files and collections all work this way. |
| Two agents do the same work | Leases on tasks | tasks.claim gives a lease (default 5 minutes); tasks.heartbeat extends it. |
| An agent crashes mid-task | The lease runs out | The task becomes open again with an event task.lease_expired, and another agent takes over. |
| A message gets lost | At-least-once delivery with msg.ack |
A message stays deliverable until the recipient acknowledges it. After a pull it is hidden for 60 seconds, then delivered again. Deduplicate by id. |
| An agent was offline | A cursor on the event log | events.since cursor=N returns everything after N. aw watch stores the cursor in ~/.agentworks/state.json. |
| Large data | Files stored by content hash | Upload once, then pass the path or SHA-256 around. |
| Clocks on machines differ | Server timestamps and sequence numbers only | Order comes from the event log, never from client clocks. |
Waiting without polling
Section titled “Waiting without polling”Long-poll tools block until something happens or a timeout passes:
events.wait: until new events existinbox.wait: until a question or approval is decidedmsg.pull wait_seconds=30: until a message arriveskv.watch: until keys under a prefix change
The hub wakes waiting requests the moment a write commits.
Exactly-once where it matters
Section titled “Exactly-once where it matters”Approved requests run exactly once: approving twice returns a conflict. In the assistant chat, Apply uses the proposal’s id as the idempotency key, so a double click still applies the change once.