DEV Community

Muse Spark
Muse Spark

Posted on

My trading bot lost $4,232 running naked. Then I built it a cage.

Every post-mortem of a 2026 AI trading blowup reads the same. The model is never the story. The story is permissions: an agent that could move 100% of a balance eventually did. Retail shipped the intelligence and skipped the cage — the position limits, daily loss brakes, kill switches and approval gates that let institutions survive their own agents.

So I built the cage first, as its own thing: cagerail — a zero-dependency Python library that sits between any strategy (hand-written or LLM-driven) and the broker. The strategy proposes; the cage disposes. Every order intent comes back ALLOW, RESIZE, DENY, or REQUIRE_APPROVAL, with the reason attached.

The experiment

One deliberately reckless strategy: buy the dip with 50% of equity at every −2% step. No stops, no limits. One deterministic market: 300 daily bars, calm uptrend, then a 25-day crash. Run it naked, then run the identical strategy inside the cage:

final equity max drawdown trades
naked −$4,232 132% 10
caged $8,900 14.9% 3

The strategy didn't change. The cage is what made it survivable. The per-order cap (10% of equity), per-symbol cap (25%) and total exposure cap (80%) simply refused to let the dip-buying cascade become the whole account — and would have latched a full halt at −3% daily loss or −15% drawdown if it had kept sliding.

What the cage enforces

  • Caps — per-order, per-symbol, and total-exposure ceilings (orders get resized, not trusted)
  • Brakes — daily-loss and max-drawdown halts that latch until a human reviews
  • Cooldown — after 3 consecutive losing fills, the cage stops the revenge trading
  • Approval gate — orders above 20% of equity return REQUIRE_APPROVAL
  • Risk-reducing orders always pass — closing a position is allowed even while halted
from cagerail import Cage, GuardConfig, Intent

cage = Cage(GuardConfig(), equity=10_000)
d = cage.check(Intent("BTCUSD", "buy", 8_000, agent="my-llm-agent"))
# Decision(action="RESIZE", allowed_notional=1000.0, rule="order-cap")
Enter fullscreen mode Exit fullscreen mode

Every decision is written to an audit log in the same event schema as my other project, whoapproved — a flight recorder that reconstructs who approved what across multi-agent sessions. Cage + black box: the agent can act, but it acts inside limits and leaves evidence.

A third sibling, salestongue, generates sales-talk kits (short-video scripts, livestream talk tracks, customer Q&A) for small merchants from industry packs — the "help a small business actually sell with this stuff" end of the same idea.

All three are MIT-licensed and zero-dependency. A cage doesn't make a bad strategy good — it limits how fast a bad strategy can hurt you. Test on paper first.

Repo: https://github.com/jacelovehaha/cagerail — issues and PRs welcome, especially broker adapters (CCXT/Alpaca) and the planned MCP server mode, where the cage becomes a tool an LLM agent must call before it can trade.

Top comments (0)