Control
Side-effecting agent tool not idempotent when the call is retried
A tool an agent or model can call that moves money, sends a message, creates an order or ticket, or otherwise changes an external system accepts an idempotency key derived from the task and call (or deduplicates on a natural key), so a retried or repeated call, whether from a timeout, a framework retry or the model calling the tool again, has its effect once.
Informational data, not legal advice. Summaries and rules have not been reviewed by a lawyer: always verify official law text for decisions. A suggested guard is intended to address each rule; adding it is not a statement of compliance to that law.
Reach
Trust and provenance
How far the rules this guard addresses have been checked. Each rule links to its provision, with its citation, official text and its own panel.
- This control
- Audit-grade: meets all 3 checks of the TwinEthos audit standard that apply to it.
- Lanes
- TwinEthos recommendation (not law) 1
- Data release
- Data release 2026.10.03.4, data as of 3 Oct 2026, schema 0.3.10. This page also reflects corpus changes made after that release; they ship in the next one.
- Legal review
- None of the 1 rule has been reviewed by a lawyer; no TwinEthos rule has been legally reviewed yet. Treat each as research to check against the official text; it is not legal advice.
- Audit standard
- 1 of 1 rule audit-grade. The audit standard is TwinEthos's own quality bar for provenance, dates, applicability, detectors, fixtures, remediation and licences; it is not a legal review.
- Detectors
- 1 detector, all experimental: written from the rule's text and not yet measured for precision on real code, so treat a hit as a lead to verify. Each provision lists its detectors' known limits.
The guard to add
Give every side-effecting tool an idempotency key derived from the tool call, so a retry has its effect once.
In each tool function that changes an external system (payments, refunds, transfers, e-mail, SMS, chat sends, order or ticket creation), derive an idempotency key from the run and the tool-call id (or from the business key, such as order id plus action) and pass it to the downstream API (Stripe idempotency_key=, an Idempotency-Key header, SQS MessageDeduplicationId), or record the key in your own store and return the stored result when it is seen again. Do the same for framework-level retries (LangGraph RetryPolicy, tenacity @retry) around those tools.
Where it goes: 1 application source code, 6 API calls and integrations, 15 agent action surface.
What reviewers look for: idempotency_key= or an Idempotency-Key header on payment, refund, send and create calls inside tool functions, with the key built from the tool-call or task id; or a processed-keys check before the side effect.
Example (Python + Stripe tool), before:
@tool
def refund_order(order_id: str, amount: int) -> str:
stripe.Refund.create(payment_intent=lookup(order_id), amount=amount)
return 'refunded'After:
@tool
def refund_order(order_id: str, amount: int, tool_call_id: str) -> str:
stripe.Refund.create(payment_intent=lookup(order_id), amount=amount,
idempotency_key=f'refund:{order_id}:{tool_call_id}') # a retry refunds once
return 'refunded'Engineering guidance, not legal advice. Each provision below may add its own details (a cadence, a deadline, a required notice element): open it for those.
Every rule this guard addresses
TwinEthos recommendation (not law) (1)
- Everywhere (*)
- Make every side-effecting agent tool idempotent under retry TwinEthos derivation — guardrail.opint-idempotent-side-effecting-tools
Informational data, not legal advice. Summaries are TwinEthos's own words and rules have not been reviewed by a lawyer: check the official text before relying on any of it. A guard addresses an item; adding it is not a statement that your code meets any law.