cd /news/ai-agents/my-trading-bot-tried-to-execute-the-… Β· home β€Ί topics β€Ί ai-agents β€Ί article
[ARTICLE Β· art-18936] src=dev.to pub= topic=ai-agents verified=true sentiment=Β· neutral

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.

read3 min publishedMay 31, 2026

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 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:

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 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 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."

── more in #ai-agents 4 stories Β· sorted by recency
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain β€” perfect for shipping the agent you just read about.

$git push zahid main
β†’ Live at https://your-agent.zahid.host βœ“
Get free account β†’ Pricing
from €0/mo Β· no card required
LIVE [news/my-trading-bot-tried…] indexed:0 read:3min 2026-05-31 Β· β€”