Agenten mit echten Folgen absichern
Problem
Sobald ein Agent nicht nur Text schreibt, sondern Dateien ablegt oder Orders vorbereitet und ausführt, reicht ein guter Prompt nicht. Ich wollte ein Muster, bei dem die Grenzen im Code liegen: was der Agent lesen darf, was schreiben, wer freigibt und wie man alles stoppt. Als Testfeld dienten Marktdaten und Demo-Konten, weil dort jede Aktion eine sichtbare Folge hat, ohne echtes Geld.
Meine Rolle
Ich habe festgelegt, welche Rolle was darf, wie freigegeben und wie gestoppt wird, und die Prüftore abgenommen. Dazu kamen Spezifikation, Review, Tests und die Prüfung, ob die Grenzen im Code wirklich greifen.
Vorgehen
In cctrader startet ein FastAPI-Orchestrator den Coding-Agenten headless per CLI (-p, stream-json). Die Allowlist erlaubt nur die eigenen MCP-Tools, Skills, Subagenten, Read und Grep, also kein Bash und kein Write. Geschrieben wird nur über MCP-Tools, die per Umgebungsvariable an genau eine Analyse-ID gebunden sind. Aus dem Stream speichert der Orchestrator pro Lauf Tokens, Cache-Treffer, Kosten und jeden Tool-Aufruf.
Im Trading-Framework von stratlab hat der MCP-Server drei Stufen: 0 lesen, 1 vorschlagen und Not-Aus, 2 ausführen. Die Stufe kommt aus der Prozessumgebung, der Agent läuft auf 0. Vor jedem Tool außer Journal-Abfrage und Not-Aus prüft ein Guard den Kill-Switch, zurücksetzen kann ihn nur ein Mensch. Vorschläge gehen per Telegram mit APPROVE und REJECT raus und verfallen nach 30 Minuten. Im MT5-Gateway zwingt tool_choice das Modell in ein einziges Werkzeug mit JSON-Schema, submit_trade_intent. Danach prüft eine Policy Symbol, Volumen und Stop-Loss, Standard ist der Dry-Run.
Architektur
Auslöser
API-Aufruf mit Token oder Event-Watcher mit 15 Minuten Entprellung und höchstens 4 Läufen pro Stunde
Headless-Agent
CLI mit -p und stream-json, Allowlist: eigene MCP-Tools und Lesewerkzeuge, kein Bash, kein Write
Eigener MCP-Server
Stufe 0/1/2 aus der Umgebung, Kill-Switch-Guard, Schreib-Tools an eine Analyse-ID gebunden
Deterministische Prüfung
Risk-Engine bzw. Policy: Symbol, Volumen, Stop-Loss, Auto-Execute standardmäßig aus
Mensch gibt frei
Telegram APPROVE oder REJECT, offene Vorschläge verfallen nach 30 Minuten
Ausführung und Protokoll
Erneute Risikoprüfung, nur Demo-Konto oder Fake-Backend, Journal plus Tokens und Kosten pro Lauf
Entscheidung
Rechte gehören in den Prozess, nicht in den Prompt
Ein Prompt wie 'führe nie selbst aus' ist eine Bitte. Deshalb liest der MCP-Server seine Stufe beim Start aus der Umgebung, und die Konfiguration des Agenten setzt sie auf 0. Ausführen kann nur ein anderer Prozess, nachdem ein Mensch freigegeben hat, und auch der prüft das Risiko noch einmal. Kein Tool, das der Agent aufrufen darf, kann die Stufe ändern. Der Preis: mehr bewegliche Teile und eine Freigabe, die nach 30 Minuten verfällt, wenn niemand reagiert.
Code-Auszug
TIER = int(os.environ.get("TRADING_TIER", "0"))
def require_tier(min_tier: int):
def deco(fn):
@functools.wraps(fn)
def wrapper(*a, **kw):
if TIER < min_tier:
return json.dumps({"error": "permission_denied", "required_tier": min_tier, "current_tier": TIER})
return fn(*a, **kw)
return wrapper
return deco
def _killswitch_guard() -> str | None:
if killswitch_is_active():
return json.dumps({"error": "killswitch_active"})
return None
# ...
@mcp.tool()
@require_tier(2)
@_safe
def trade_execute(proposal_id: str) -> str:
guard = _killswitch_guard()
if guard:
return guardErgebnisse
- 25Backend-Tests in cctrader, am 18.10.2026 grün
- 28Tests für Stufen, Kill-Switch und Freigabe, am 18.10.2026 grün
- 0,17 $für einen kompletten Testlauf mit Haiku in 47 s
- 30 minbis ein offener Vorschlag verfällt
- 4
- Bedingungen, bevor das MT5-Gateway wirklich ausführt
Was ich daraus gelernt habe
Nicht jede Grenze war durchgesetzt. In cctrader stehen ein Lauf gleichzeitig und zwölf pro Stunde in der Config, aber kein Code prüft das. Im MT5-Gateway sagt die Doku Policy vor Auth, der Code prüft bei Ausführungen zuerst das Token, und ist keins gesetzt, prüft er gar nicht. Der Telegram-Callback prüft nicht, wer den Knopf gedrückt hat. Heute schreibe ich zu jeder Grenze zuerst einen Test, der sie zu brechen versucht, und fehlende Konfiguration scheitert geschlossen. Offen ist noch der Nachweis gegen ein echtes Demo-Konto, dafür fehlten die Demo-Schlüssel.