Retry-outcome resolution dedup proxy

Retry-outcome resolution dedup proxy — by TextForAgents LLC. A timeout is UNKNOWN, not FAILED — but your agent cannot tell the difference, so it classifies the timeout as a failure, mints a fresh operation identity, and fires the effect again: the double charge, the double email, the double submission. A measured scan of 671 MCP servers found 539 performing real writes and 175 of those (32%) with zero visible idempotency guards; a reproduced incident cost a customer a second $49.99 charge for exactly this reason. This product is a hosted claim-before-execute dedup proxy that sits in the call path: before a side-effecting call fires, it claims a durable slot keyed on semantic identity (tool + the scope fields the tool author declares — never a per-attempt UUID the model mints fresh on retry, never a raw-args hash alone), with a payload fingerprint so a different payload under one identity is refused as a CONFLICT, never silently replayed. A retry of a committed operation returns the original provider receipt without firing. A timeout moves the operation to UNKNOWN and resolves it by status query before any re-fire is permitted; where no status surface exists, the claim is ESCALATED and re-fires are refused until a manual check closes it. Proven in the lab: 16/16 tests + real MCP stdio end-to-end (fresh-UUID retry replayed the original receipt, effect_count=1), status-query verdicts correct in 255/255 fixture cases where a status surface exists, ~$2.8×10⁻⁹/claim, +9.2 ms p99 added latency. Operator $9/mo · Fleet $29/mo · Per-claim API $0.001/claim. First 100 claims free, one time per operator.

Operator $9/mo per operator · Fleet $29/mo per operator · Per-claim API $0.001/claim (x402). First 100 claims free, one time per operator. There is no perpetual free tier.

Honest bounds: "no guard found" in the scan means none visible in public code — the census verifies per-server, never assumes. The product does not guarantee resolution of an UNKNOWN operation against a provider with no status query; escalation is the documented outcome there. The field share of UNKNOWN operations landing on no-status providers is unmeasured — the lab's 15% was fixture-programmed, a mechanism measurement, not a field measurement; production instruments UNKNOWN outcomes by resolution path.

PENDING lease tuning guidance (default 300s)

The resolve-before-takeover PENDING lease defaults to 300 seconds: a PENDING claim older than the lease may be taken over only after a status-query resolution attempt, and takeover is a single-winner stale-guarded update. Tune per tool class: fast calls (payments, emails, submissions completing in seconds) — 60–300s; long-running effects (media generation, provisioning, batch jobs) — set the lease above the longest legitimate tool call (900–3600s); never set it below the tool's own timeout, or a live owner can be taken over mid-fire.

Framework adapters

Shipped, wired integrations (source served at /adapters/): CrewAI — DedupTool, a real crewai BaseTool placed in the agent's tool list, claims via POST /execute before the proxied effect fires; a CrewAI retry re-enters the tool with a fresh attempt_id and consumes the replayed receipt / resolved / ESCALATED verdict instead of re-firing. LangGraph — make_dedup_node / build_retry_graph put the claim inside the side-effecting node under a LangGraph RetryPolicy; checkpoint resumes and policy retries re-enter the same claim because identity excludes attempt ids. Raw MCP: call the dedup_execute MCP tool (POST /mcp) with the same arguments the wrapped tool takes plus its declared scope_fields; dedup_receipt and dedup_resolve expose the stored receipt and the manual ESCALATED-resolution path. Both framework integrations are proven end-to-end against the real frameworks (a claim executed inside a real CrewAI tool-calling loop and a real LangGraph retry path, effect_count stayed 1).

Docs: docs · OpenAPI · Terms · Privacy · Support: support@textforagents.com