Agents retry. Networks retry. Users mash buttons. If mutating tools are not idempotent, you will double-charge cards or open two Jira tickets for one intent. Day 35 standardizes DynamoDB conditional writes and client tokens across every side-effecting tool.
⚡ TL;DR: Require
idempotencyKeyon mutating tools. Conditional put on(tenant, tool, key). Replay stored results on duplicates. Include the key in EventBridge jobs (Day 34) and approval flows (Day 33).
Schema requirement
{
"name": "create_refund_v1",
"inputSchema": {
"json": {
"type": "object",
"required": ["orderId", "amountCents", "idempotencyKey"],
"properties": {
"orderId": {"type": "string"},
"amountCents": {"type": "integer", "minimum": 1},
"idempotencyKey": {"type": "string", "minLength": 16, "maxLength": 128}
},
"additionalProperties": false
}
}
}
Prefer UI-generated keys so the model cannot wobble between retries. If the model generates keys, instruct: one UUID per user intent, reuse on retry.
Conditional write pattern
def mutate(tenant: str, tool: str, key: str, fn):
pk, sk = f"t#{tenant}", f"tool#{tool}#id#{key}"
try:
table.put_item(
Item={"pk": pk, "sk": sk, "status": "IN_PROGRESS", "ttl": ttl_hours(24)},
ConditionExpression="attribute_not_exists(pk)",
)
except ClientError as e:
if e.response["Error"]["Code"] != "ConditionalCheckFailedException":
raise
item = table.get_item(Key={"pk": pk, "sk": sk})["Item"]
if item["status"] == "DONE":
return item["result"]
raise Conflict("in_progress")
result = fn()
table.update_item(
Key={"pk": pk, "sk": sk},
UpdateExpression="SET #s=:d, result=:r",
ExpressionAttributeNames={"#s": "status"},
ExpressionAttributeValues={":d": "DONE", ":r": result},
)
return result
create_refund(order_id, amount)
Exactly-once delivery is a myth; at-least-once + idempotency is the design.
Production checklist
- [ ] All mutating tools require idempotencyKey
- [ ] Conditional put + stored result replay
- [ ] TTL on idempotency records (24–72h)
- [ ] Metrics for dedupe hits
- [ ] Chaos: replay same call 10× in staging
- [ ] Keys scoped with region if multi-region (Day 38)
Series navigation
Last updated September 11, 2026
Discover more from CheatCoders
Subscribe to get the latest posts sent to your email.
