My Trading Bot Tried to Execute the Same Trade Twice. That Became SafeAgent. On May 21, a live trading bot generated six duplicate execution attempts in a single session, which were all blocked by SafeAgent, an exactly-once execution guard for AI agents and SaaS applications. The tool prevents duplicate payments, emails, trades, and webhook processing when retries fire after a timeout or crash, and now includes a live audit endpoint, SaaS coverage for Stripe and other services, and integration with CrewAI and WisePick. This is a submission for the GitHub Finish-Up-A-Thon Challenge On May 21, my live trading bot generated six duplicate execution attempts in one session. SafeAgent blocked all six. Without the guard: That session changed how I think about AI agents, retries, and execution guarantees. SafeAgent is an exactly-once execution guard for AI agents and SaaS applications. It prevents duplicate payments, emails, trades, and webhook processing when retries fire after a timeout or crash. pip install safeagent-exec-guard Six months ago I was building two things at once: PeerPlay — a patented P2P wagering exchange for skill-based video game tournaments USPTO provisional 63/914,036 — and a live QQQ/TQQQ momentum trading bot running on Alpaca Markets. Both hit the same bug. Contest verification agent times out, retries, settlement fires twice. Bot order fills, confirmation drops, retry fires, doubled position. Same failure mode. Different domain. Different models pushed me toward very different architectures during development. Some were fast but overconfident. The most useful moments came when a model explained why an approach was broken before I implemented it. That's part of why SafeAgent sat unfinished. Not just time — wrong turns that burned momentum. Early versions used a local SQLite guard. It worked until it didn't: Exactly-once semantics require a durable coordination boundary outside the worker itself. That's what the hosted /claim endpoint provides — the claim lives on the server, not in the process. I published the original article in April https://dev.to/azender1/i-was-building-a-live-trading-bot-and-a-patented-wagering-system-the-bug-i-found-is-now-breaking-ai-agents-everywhere after extracting the pattern from both projects. That was the before state: /claim endpoint /audit marked "coming soon" 1. /audit endpoint — now live Was implemented in code, never deployed, never documented. Now it's live: curl "https://safeagent-production.up.railway.app/audit?agent id=bot-1&status=COMMITTED" Full claim history, filterable by agent id , action , status , and timestamp range. Every claim, every SKIP, every duplicate blocked — with timestamps. 2. SaaS coverage — Stripe, webhooks, email The original README read like a trading tool. SafeAgent solves the same problem for any SaaS. Stripe, GitHub, and Twilio all guarantee at-least-once webhook delivery. SafeAgent turns at-least-once into exactly-once: python def handle stripe webhook event : r = requests.post "https://safeagent-production.up.railway.app/claim", json={ "agent id": "saas-webhooks", "action type": "stripe event", "scope": event "id" } if r.json "status" == "SKIP": return {"ok": True} provision subscription event 3. WisePick integration WisePick https://github.com/w2jmoe/WisePick shipped a full adapter, replay demo, and integration docs. The integration splits routing from execution — WisePick answers what and which provider , SafeAgent answers whether this already ran . The decision id is intentionally excluded from the request id derivation so retries that mint a new routing decision still hit the same execution slot and return SKIP. 4. CrewAI hosted backend PR crewAIInc/crewAI 5822 https://github.com/crewAIInc/crewAI/pull/5822 adds pluggable idempotency backends. I shipped a hosted SafeAgentCacheBackend that implements the interface — cross-machine, crash-safe, no local SQLite required. 5. Production proof — May 21 | Time | Event | Blocked | |---|---|---| | 0942 ET | duplicate buy TQQQ qty=6 | $452 | | 0947 ET | duplicate add TQQQ qty=6 | $452 | | 0949 ET | duplicate sell TQQQ qty=12 | $902 | | 1000 ET | duplicate entry TQQQ qty=6 | $454 | | 1014 ET | duplicate sell TQQQ qty=18 | $1,350 | | 1106 ET | duplicate SQQQ add | $43 | The session also surfaced a gap: the exit side has no guard. When a SQQQ exit failed with 422 Unprocessable Entity, the bot logged ENTRY BLOCKED for three hours from a phantom position that didn't exist. That failure mode is now documented and is the next spec item — not buried, in the README. Claude has been in every meaningful step: the two-phase claim architecture, the SaaS integration examples, the WisePick README section, every GitHub PR comment before I posted it. The most useful thing it does isn't writing code — it's telling me when an approach is wrong before I build it. The model that's most confident isn't always the most correct. The one that says "this approach is broken because X" is worth more than the one that says "here's how to build the broken thing faster."