Technology Apr 26, 2026 · 5 min read

I Was Building a Live Trading Bot and a Patented Wagering System. The Bug I Found Is Now Breaking AI Agents Everywhere.

This isn't a library I built to solve a theoretical problem. It's a fix I built because real money was at risk. The trading bot I've been running a live QQQ/TQQQ momentum bot on Alpaca Markets. It reads 1-minute bars, scores market structure using VWAP, SMA8, SMA21, SMA34, and momentum signals, the...

DE
DEV Community
by Anthony Zender
I Was Building a Live Trading Bot and a Patented Wagering System. The Bug I Found Is Now Breaking AI Agents Everywhere.

This isn't a library I built to solve a theoretical problem.
It's a fix I built because real money was at risk.

The trading bot
I've been running a live QQQ/TQQQ momentum bot on Alpaca Markets. It reads 1-minute bars, scores market structure using VWAP, SMA8, SMA21, SMA34, and momentum signals, then enters leveraged positions in TQQQ (bull) or SQQQ (bear) based on that score.
The bot has retry logic built in. It has to — broker ACK timeouts are real. When you submit a market order and the network drops before confirmation comes back, you don't know if it filled or not. So the bot retries.
Here's the problem: if the first order actually filled but the confirmation timed out, the retry fires a second market order. On a 3x leveraged ETF, that's a doubled position you didn't intend. With real dollars on the line.
The bot already had a manual execution lock (EXECUTION_LOCK_SEC=15) and a JSON state machine to handle this. I built it by hand. It worked — mostly. But it was fragile, untested, and not something I'd want to hand to anyone else.

The old pattern — retries up to 3 times

def place_order_with_retry(symbol, qty, side):
last_err = None
for attempt in range(1, EXIT_RETRY_COUNT + 1):
try:
return place_order(symbol, qty, side) # fires twice if first timed out but filled
except Exception as e:
last_err = e
time.sleep(EXIT_RETRY_SLEEP_SEC)
raise last_err:
That place_order call has no memory. If attempt 1 filled and attempt 2 fires, you now own twice the position. The broker doesn't know you didn't mean it.

The wagering system
At the same time I was building the bot, I was designing PeerPlay — a patented P2P wagering exchange for skill-based video game tournaments (USPTO provisional 63/914,036).
PeerPlay has an escrow engine, a verification layer, and a settlement layer. The verification layer uses AI to confirm match results. When a verification agent times out and retries, the settlement layer can receive two confirmation signals for the same match. Two signals → two prize payouts. One tournament result, two winner transfers.
The patent protects the architecture. Nothing in the patent protects you from your own execution layer firing twice.
Same problem. Different domain.

The extraction
I realized the trading bot and PeerPlay had identical failure modes:
Agent/bot decides to act

Network times out

Agent/bot retries

Side effect fires twice
The fix in both cases is the same primitive: before you execute an irreversible action, check whether it already ran. If it did, return the original result. If it didn't, run it and store the result.
That's SafeAgent.
pythonfrom settlement.settlement_requests import SettlementRequestRegistry

registry = SettlementRequestRegistry()

Same request_id on retry → returns original receipt, never re-executes

receipt = registry.execute(
request_id="trade:TQQQ:buy:2026-04-26T09:47:00",
action="order_buy_TQQQ",
payload={"symbol": "TQQQ", "qty": 10, "side": "buy"},
execute_fn=lambda: place_order("TQQQ", 10, "buy"),
)
First call executes the order and stores the receipt. Any retry with the same request_id returns the stored receipt — the broker is never called again.

Why this matters for AI agents specifically
The trading bot and PeerPlay are deterministic systems. They have retry logic because networks are unreliable. AI agents have the same problem but worse — they also have uncertain completion signals.
When Claude or any LLM agent calls a tool, it may:

Get a timeout and retry the same call
Receive an ambiguous response and call again to confirm
Run in a loop and re-trigger the same action
Get restarted mid-execution and replay from the last checkpoint

Every one of these scenarios can produce duplicate side effects. The agent frameworks (LangChain, CrewAI, n8n, OpenAI function calling) handle retries at the transport layer. None of them track whether the side effect already happened.
That gap — between the agent decision and the irreversible action — is where SafeAgent lives.

The state machine
SafeAgent doesn't just deduplicate by request_id. It enforces a finality gate:
OPEN → RESOLVED → IN_RECONCILIATION → FINAL → SETTLED
Execution is only permitted from FINAL. If the agent's signals are ambiguous — conflicting tool responses, partial confirmations, uncertain outcomes — the state stays in IN_RECONCILIATION and the side effect is blocked until the outcome is clear.
This is what I needed for PeerPlay's verification layer. The AI model returns a confidence score. SafeAgent holds the settlement until that score clears a threshold. Below threshold: IN_RECONCILIATION. Above threshold: FINAL. Payout executes exactly once.

Where it fits in the MCP stack
If you're building agents on MCP, SafeAgent sits above your tool layer:
Claude / agent decision
→ SafeAgent finality gate
→ SafeAgent request-id dedup
→ MCP tool executes
→ Receipt stored (SQLite, survives restarts)
It works with any MCP-capable host — Claude, Cursor, Windsurf, custom executors — without modifying the protocol.
As of today (April 26, 2026) SafeAgent is officially listed in the MCP registry:
io.github.azender1/safeagent v0.1.14
registry.modelcontextprotocol.io

Install
bashpip install safeagent-exec-guard
Python 3.10+ · Apache-2.0 · GitHub · Live demo
The trading bot integration example is in the repo at examples/safeagent_trading_integration.py — it shows the before/after pattern with real variable names from the QQQ bot.

The audit
If you're running agents or bots in production and want to know where your system can execute twice, I'm offering a focused duplicate execution risk audit for $499. Written report, every retry path, every side effect boundary, SafeAgent integration recommendations.
DM me or email azender1@yahoo.com.

Built by Anthony Zender, Dayton OH. Payroll tax accountant by day, agent infrastructure builder by night. USPTO provisional 63/914,036 — Zender Gaming Technologies LLC.
Tags: #mcp #ai #python #trading #agents

DE
Source

This article was originally published by DEV Community and written by Anthony Zender.

Read original article on DEV Community
Back to Discover

Reading List