Skip to main content

Idempotency middleware for LLM agent tool calls — prevent duplicate side effects on retry.

Project description

latch

Idempotency middleware for LLM agent tool calls. Prevents duplicate side effects (double-charged orders, duplicate emails, duplicate records) when an agent retries a tool call after a timeout or transient failure.

The problem

An agent calls a tool. The call times out. The agent doesn't know if the underlying action completed before the timeout — it just knows it didn't get a response. Retrying is the only reasonable move, but if the tool isn't idempotent, retrying can execute the side effect twice.

Install

pip install latch-idempotent

Quickstart

from latch import idempotent

@idempotent()
def create_order(order_id: str, amount: float) -> dict:
    # ... call your payment/order API ...
    return {"order_id": order_id, "status": "created"}

# The agent framework supplies a unique key per logical operation.
result = create_order(order_id="A1", amount=42.0, idempotency_key="run-7-step-3")

# A retry with the same key returns the cached result instead of
# re-executing create_order — no duplicate order.
result_again = create_order(order_id="A1", amount=42.0, idempotency_key="run-7-step-3")
assert result == result_again

Works the same way for async def tool functions.

How it works

  • idempotency_key is a required keyword argument — latch never guesses or auto-generates one. The caller (your agent framework or orchestration code) decides what constitutes "the same logical operation."
  • On first call with a given key, the function executes and the result is cached.
  • On any subsequent call with the same key, within the TTL window (default 24h), the cached result is returned and the function is not re-executed.
  • If the wrapped function raises, nothing is cached — the exception propagates normally so retries can still happen.

Storage backends

Default is an in-memory store (single-process, not persistent across restarts). For multi-process or production deployments, use a distributed store:

from latch import idempotent, InMemoryStore

store = InMemoryStore()

@idempotent(store=store, ttl_seconds=3600)
def send_email(to: str) -> dict:
    ...

Redis backend is planned for v0.2 (pip install latch-idempotent[redis]).

Status

v0.1 — idempotency only. See CLAUDE.md for the roadmap (circuit breaker, budget guardrails, saga/compensation, and framework adapters are planned for later versions).

Prior art

This library exists alongside academic work on agent reliability — see SagaLLM, Robust Agent Compensation, and ReliabilityBench. latch's contribution is a small, adoptable, production-ready implementation of the idempotency pattern specifically — not a claim of inventing it.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

latch_idempotent-0.1.0.tar.gz (9.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

latch_idempotent-0.1.0-py3-none-any.whl (7.1 kB view details)

Uploaded Python 3

File details

Details for the file latch_idempotent-0.1.0.tar.gz.

File metadata

  • Download URL: latch_idempotent-0.1.0.tar.gz
  • Upload date:
  • Size: 9.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.0

File hashes

Hashes for latch_idempotent-0.1.0.tar.gz
Algorithm Hash digest
SHA256 ae04ca9597abe61e800007ba8eede89d6af599864d212590e83a9cd350da6237
MD5 aea80e13c087c69bcdbc3c72820a74f5
BLAKE2b-256 2f91645351c3a70b915cd472f64007846cf73e0eaea1d32e667d0a3b9c353b5e

See more details on using hashes here.

File details

Details for the file latch_idempotent-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for latch_idempotent-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 70239c4f8b606e61698bcef08cafdb2e987c892c3cd1f0640fda617f1c65967f
MD5 46ce533fbcf6ed74333f8760180e8f8f
BLAKE2b-256 10d2f7220652253f6ae74cc1987f36f58d8bbccb55f56cfa1bc07e2ca84decf5

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page