1. The Threat Model & The Core Philosophy
An automated trading agent ingests uncontrolled external data — news wires, regulatory filings, and social relays — and controls capital. In this domain, prompt injection is uniquely toxic: a successful attack directly transfers money to the attacker.
Industry standard attempts rely on heuristic detectors ("scan for override keywords"). We reject this on first principles:
- Detectors are an endless arms race against an unbounded adversarial search space (base64, zero-width spaces, Cyrillic homoglyphs, typosquatting).
- A detector's verdict is probabilistic. "We think this text is 94% safe" is unacceptable when standing before a broker execution API.
CLEANROOM’s core bet: Make attacks structurally impossible to monetize, then eliminate reliance on attack detection. A fully compromised reading model can, at worst, return an incorrect JSON field. It can never submit an order because it possesses zero execution capabilities.
2. The Three Planes & The Single Trust Boundary
The architecture enforces a strict physical boundary between unstructured reasoning and capital execution:
[ UNTRUSTED ZONE: Plane 1 (Perception) ] • Untrusted News / Filings • Gemini LLM (0 Tools Bound, Structured Pydantic Output Only) ║ ════════════════════╬══════════════════════════════════════════════ TRUST BOUNDARY ║ (PerceptionOutput Pydantic Contract Only) ════════════════════╬══════════════════════════════════════════════ ▼ [ TRUSTED ZONE: 0 LLM Calls · 100% Deterministic Code ] • Plane 2: AIRLOCK (Normalizes text, tags provenance, flags anomalies) • Plane 3: Strategy (Maps sentiment to trade side; sizing = market arithmetic) • Plane 3: Execution Controller (Fail-closed BLOCK invariants, code-level VETO) │ ▼ [ Alpaca Broker API ] (PASS → Paper Order | VETO → Discarded)
Architectural Guarantees:
- Zero Tools in Perception:
perception.pyconstructs LLM requests with strict schema constraints and notools=argument. It can describe data, but possesses no mechanism to act. - Separation of Privileges: Static source code tests (
bench.py) inspect AST tokens and fail the build ifsubmit_order,TradingClient, or broker API primitives are referenced within untrusted modules. - Deterministic VETO: The VETO decision is not a generated LLM response. It is a boolean logic evaluation in Python code over explicit risk checks (
MAX_DAILY_NOTIONAL_USD,SYMBOL_WHITELIST, stop-loss distance).
3. Ablation Benchmark Results
We evaluated the architecture against a naive baseline (an identical model provided with direct broker order tools) using an adversarial corpus of 15 realistic injection vectors (sizing bombs, Cyrillic homoglyph attacks, typosquats, and override payloads):
| Benchmark Dimension | Unhardened Naive Agent | Hardened (CLEANROOM) |
|---|---|---|
| Attack Success Rate (ASR) | 5 / 15 (33%) | 0 / 15 (0%) |
| Benign False Positive Rate (FPR) | — | 0 / 4 (0%) |
PERCEPTION_TOOL_ZERO_TRUST | FAILED | PASS (Structural) |
EXECUTION_PRIVILEGE_SEPARATION | FAILED | PASS (Structural) |
Verified empirically and structurally at commit b8dd751 with 53 passing automated pytest specifications.
4. Mission Control UI & Dual-Stream Sandbox
The system includes an operator console built with FastAPI and Next.js:
- Live Adversarial Arena: Operators and evaluators can submit arbitrary text payloads. The API dispatches the text simultaneously to both the naive agent and the hardened CLEANROOM pipeline.
- Server-Sent Events (SSE): Streams real-time pipeline transitions (`Raw Text → Perc