Notes
AI agent idempotency: how to stop one approved action becoming two writes
For engineers and operations teams whose agents already write to production systems, and who have to answer what a timeout, a restart or a re-plan does to a refund, a payment or a disabled account.
GembaOS is a zero-trust governance runtime for enterprise AI agents: policy-decided access, single-use clearance tokens bound to exact parameters, and accountable human approvals, running on-premises or in a private VPC. This note is about the least glamorous way an agent causes real damage: doing the right thing twice.
What is idempotency, and why do agents need it?
An operation is idempotent when performing it repeatedly leaves the same result as performing it once. Agents need it because retries are ordinary, not exceptional. The call times out and the client resends. A rate limit rejects the attempt and something retries it. The process restarts after the write left but before the response came back. The model gets an ambiguous tool result and plans the step again.
None of those is misbehaviour, and none of them is caught by a permission check. The agent is allowed to issue that call; it is issuing it twice.
| Trigger | What the agent sees | What the business sees without a key |
|---|---|---|
| Timeout | No response | Two refunds |
| Restart mid-write | The step never finished | A duplicate record, or an account disabled twice |
| Rate limit then retry | An error, then success | One charge, or two |
| The model re-plans | The previous result was unclear | A second ticket, a second email |
Where should the idempotency key come from?
From the authorization, not from the attempt. This is the whole design decision, and the common mistake is a key generated inside the call, for example from a UUID or a timestamp: the retry generates a different one, the target system sees a new request, and the duplicate is written. The key must be the same on both attempts, which means it has to be derived from something that existed before either of them.
| Key derived from | Same on a retry? | Chosen by |
|---|---|---|
| A UUID made at call time | No | The agent |
| The arguments alone | Yes, but two legitimate identical refunds collide | The agent |
| The approval and the work item | Yes | GembaOS Governance Kernel |
GembaOS takes the third. The key is built deterministically by the GembaOS kernel from the approval request and the work item, so the agent neither chooses it nor can vary it, and two genuinely separate approvals for the same amount stay separate because their approvals differ.
What does a governed execution actually guarantee?
Three mechanisms sit behind the one sentence one approval, at most one write, and they cover different layers. Inside GembaOS, the clearance is single-use: executing the approved action consumes it, and a second attempt under the same clearance is refused and recorded. Inside the target system, the idempotency key makes the repeat land as the same write. And where the system offers neither, the adapter declares how its write is guarded — a version, a conditional write, or a lease held on the record while the action runs.

The report line on the record names both: the clearance the write ran under, and the execution key derived from the approval and the work item. An auditor reading this later does not have to trust that a retry was handled; the key that made it safe is on the record.
What about a batch?
A batch is where duplicates get expensive, because a re-run after a partial failure is the obvious human reaction. In GembaOS one approval can cover a list, but each row stays its own work item with its own record under that approval.

Three rows succeeded, one failed because the target system answered that the account did not exist, and the failure states plainly that nothing was executed for that row. The tally, the per-row state and the shared approval are all on the record, so the question “which rows actually happened?” has an answer that does not depend on reading logs.
Summary
Idempotency is not a detail of the HTTP client. For an agent that writes to a production system it is part of the authorization: a decision that a person signed once should become a write that happens once, whatever the network does in between. The practical test for any agent platform is short — ask where the idempotency key comes from. If the answer is “the agent generates it”, the platform has not solved this; it has moved it.
Questions this note answers
What is idempotency for an AI agent?
An operation is idempotent when running it more than once leaves the same result as running it once. For an agent this matters at the write: a refund, a payment, a ticket or a disabled account should land once even if the call that created it was sent twice.
Why can't the agent generate the idempotency key?
Because the second attempt is a second generation. A key made inside the attempt differs on the retry, so the target system sees a new request and writes a second record. The key has to come from something stable that both attempts share, which is the approval, not the attempt.
What if the target system has no idempotency support?
Then the guard has to be a pre-write check against the record itself: a conditional write, a version, or a lease held on the record while the action runs. Each adapter declares which of these it uses, so the runtime knows what a write is protected by before it allows one.
What happens to a batch where one row fails?
Each row is its own work item under the one approval and is recorded separately, so a failure on one row is visible as a failure on that row. Re-running the batch does not re-apply the rows that already succeeded.
Sources
As of September 2026 GembaOS holds no certification; the control mappings on this site are self-assessed, not audited. GembaOS is in its design partner stage. Read about the design partner program.
Last updated: · GembaOS v0.2