Architekturdiagramm eines Privacy Routers: Datenfluss aufgeteilt in lokalen und Cloud-Pfad

    Privacy Router mit OpenClaw bauen: Ein Praxis-Guide mit Code

    Till FreitagTill Freitag17. März 20266 min read
    Till Freitag

    TL;DR: „Ein Privacy Router braucht drei Dinge: eine Policy-Engine, die Sensitivität klassifiziert, einen lokalen Modell-Pfad und einen Cloud-Pfad. Hier ist, wie man das mit OpenClaw baut."

    — Till Freitag

    In 30 Sekunden

    Der Privacy Router ist ein Konzept – NVIDIA hat es auf der GTC vorgestellt, aber die Implementierungsdetails fehlen noch. Dieser Guide zeigt, wie man das Konzept mit OpenClaw selbst umsetzt: eine Policy-Engine, die Anfragen klassifiziert, und ein Router, der sensible Daten lokal hält und alles andere in die Cloud schickt.

    Was wir bauen

    Ein Privacy Router mit drei Komponenten:

    User Query
      └── Policy Engine (klassifiziert Sensitivität)
           ├── SENSITIVE → lokales Modell (Nemotron / Llama / Qwen)
           └── NON_SENSITIVE → Cloud-Frontier (Claude / GPT / Gemini)

    Voraussetzungen:

    • OpenClaw installiert und konfiguriert
    • Ein lokales Modell (via Ollama, vLLM oder ähnlich)
    • Ein Cloud-API-Key (OpenRouter, Anthropic, OpenAI o.ä.)

    Schritt 1: Die Policy-Engine

    Die Policy-Engine ist das Herzstück. Sie entscheidet, ob eine Anfrage sensible Daten enthält – bevor sie an ein Modell geht. Kritisch: Diese Entscheidung trifft die Policy, nicht der Agent.

    Regelbasierter Ansatz

    Für den Anfang reicht ein regelbasierter Klassifikator. Kein ML, kein Overhead – nur Pattern Matching:

    from dataclasses import dataclass
    from enum import Enum
    import re
    
    class Sensitivity(Enum):
        SENSITIVE = "sensitive"
        NON_SENSITIVE = "non_sensitive"
    
    @dataclass
    class PolicyRule:
        name: str
        patterns: list[str]
        sensitivity: Sensitivity
    
    class PolicyEngine:
        def __init__(self, rules: list[PolicyRule]):
            self.rules = rules
            self._compiled = [
                (rule, [re.compile(p, re.IGNORECASE) for p in rule.patterns])
                for rule in rules
            ]
        
        def classify(self, text: str) -> Sensitivity:
            for rule, patterns in self._compiled:
                for pattern in patterns:
                    if pattern.search(text):
                        return rule.sensitivity
            return Sensitivity.NON_SENSITIVE  # Default: nicht-sensibel

    Policies definieren

    Policies sind deklarativ – keine Logik, nur Daten:

    GDPR_POLICIES = [
        PolicyRule(
            name="personal_data",
            patterns=[
                r"\b[A-Z][a-z]+ [A-Z][a-z]+\b",  # Vor- und Nachname
                r"\b\d{2}\.\d{2}\.\d{4}\b",        # Geburtsdatum (DE Format)
                r"\b[A-Z]{2}\d{2}\s?\w{4,}\b",     # IBAN-Muster
            ],
            sensitivity=Sensitivity.SENSITIVE,
        ),
        PolicyRule(
            name="health_data",
            patterns=[
                r"\b(diagnose|patient|krankenhaus|medikament)\b",
                r"\b(blutdruck|allergie|therapie|befund)\b",
            ],
            sensitivity=Sensitivity.SENSITIVE,
        ),
        PolicyRule(
            name="employee_data",
            patterns=[
                r"\b(gehalt|personalnummer|sozialversicherung)\b",
                r"\b(kündig|abmahnung|arbeitszeugnis)\b",
            ],
            sensitivity=Sensitivity.SENSITIVE,
        ),
    ]
    
    engine = PolicyEngine(GDPR_POLICIES)

    Warum regelbasiert und nicht ML?

    Ein ML-Klassifikator für Sensitivität klingt eleganter – aber er hat Nachteile:

    Regelbasiert ML-basiert
    Erklärbarkeit Jede Entscheidung nachvollziehbar Black Box
    DSGVO-Compliance Auditierbar Schwer nachweisbar
    False Negatives Bekannt und kontrollierbar Unvorhersehbar
    Latenz ~0ms ~10–50ms
    Wartung Regeln manuell pflegen Trainingsdaten + Modell pflegen

    Für die meisten Fälle ist regelbasiert der bessere Start. ML kann später als zweite Schicht ergänzt werden.

    Schritt 2: Der Router

    Der Router nimmt die Entscheidung der Policy-Engine und leitet die Anfrage an das richtige Modell weiter:

    from openclaw import Agent, ModelConfig
    
    class PrivacyRouter:
        def __init__(
            self,
            policy_engine: PolicyEngine,
            local_model: ModelConfig,
            cloud_model: ModelConfig,
        ):
            self.policy = policy_engine
            self.local_model = local_model
            self.cloud_model = cloud_model
            self._log: list[dict] = []
        
        def route(self, query: str) -> ModelConfig:
            sensitivity = self.policy.classify(query)
            
            selected = (
                self.local_model
                if sensitivity == Sensitivity.SENSITIVE
                else self.cloud_model
            )
            
            self._log.append({
                "query_hash": hash(query),  # Kein Klartext loggen!
                "sensitivity": sensitivity.value,
                "model": selected.name,
            })
            
            return selected
        
        def get_audit_log(self) -> list[dict]:
            return self._log.copy()

    Modelle konfigurieren

    local = ModelConfig(
        name="nemotron-nano",
        endpoint="http://localhost:11434/v1",  # Ollama
        model_id="nemotron:3b",
        max_tokens=4096,
    )
    
    cloud = ModelConfig(
        name="claude-sonnet",
        endpoint="https://api.anthropic.com/v1",
        model_id="claude-sonnet-4-20250514",
        api_key="${ANTHROPIC_API_KEY}",  # Aus Umgebungsvariable
        max_tokens=8192,
    )
    
    router = PrivacyRouter(
        policy_engine=engine,
        local_model=local,
        cloud_model=cloud,
    )

    Schritt 3: Integration in den Agent

    Der Router wird als Middleware in den OpenClaw-Agent eingebaut. Der Agent merkt nicht, welches Modell er nutzt – das ist Absicht:

    from openclaw import Agent, Tool
    
    class PrivacyAwareAgent(Agent):
        def __init__(self, router: PrivacyRouter, tools: list[Tool]):
            self.router = router
            super().__init__(tools=tools)
        
        async def process(self, user_input: str) -> str:
            # 1. Policy entscheidet über Routing
            model = self.router.route(user_input)
            
            # 2. Agent läuft mit dem gewählten Modell
            response = await self.run(
                input=user_input,
                model=model,
            )
            
            return response.content
    
    # Verwendung
    agent = PrivacyAwareAgent(
        router=router,
        tools=[search_tool, calculator_tool, crm_tool],
    )
    
    # Sensible Anfrage → lokal
    result = await agent.process(
        "Was ist das aktuelle Gehalt von Max Mustermann?"
    )
    
    # Allgemeine Anfrage → Cloud
    result = await agent.process(
        "Fasse die Top-3 Trends im Projektmanagement zusammen"
    )

    Schritt 4: Audit-Trail für Compliance

    Für DSGVO-Compliance braucht man einen nachweisbaren Audit-Trail. Wann wurde was wohin geroutet – und warum:

    import json
    from datetime import datetime
    
    class AuditLogger:
        def __init__(self, storage_path: str):
            self.path = storage_path
        
        def log_routing_decision(
            self,
            query_hash: str,
            sensitivity: str,
            model_used: str,
            policy_rule_matched: str | None,
            timestamp: datetime | None = None,
        ):
            entry = {
                "timestamp": (timestamp or datetime.utcnow()).isoformat(),
                "query_hash": query_hash,  # Nie den Klartext loggen
                "sensitivity": sensitivity,
                "model": model_used,
                "policy_rule": policy_rule_matched,
                "routing_decision": (
                    "local" if sensitivity == "sensitive" else "cloud"
                ),
            }
            
            with open(self.path, "a") as f:
                f.write(json.dumps(entry) + "\n")

    Wichtig: Den Klartext der Anfrage nie loggen – nur einen Hash. Sonst wird der Audit-Trail selbst zum Datenschutzproblem.

    Schritt 5: Sandboxing für den lokalen Pfad

    Der lokale Pfad verarbeitet sensible Daten – er braucht stärkere Isolation als der Cloud-Pfad:

    from openclaw.sandbox import ContainerSandbox
    
    # Tool-Calls im lokalen Pfad laufen in Containern
    local_sandbox = ContainerSandbox(
        image="openclaw/tool-runner:latest",
        memory_limit="512m",
        cpu_limit=1.0,
        network="none",       # Kein Netzwerkzugriff
        read_only_fs=True,    # Nur-Lese-Dateisystem
        timeout_seconds=30,
    )
    
    # Cloud-Pfad braucht weniger Isolation
    cloud_sandbox = ContainerSandbox(
        image="openclaw/tool-runner:latest",
        memory_limit="1g",
        cpu_limit=2.0,
        network="restricted",  # Nur ausgehend, nur HTTPS
        timeout_seconds=60,
    )

    Vollständiges Setup

    Alles zusammen:

    from openclaw import Agent, ModelConfig, Tool
    from openclaw.sandbox import ContainerSandbox
    
    # 1. Policy Engine
    engine = PolicyEngine(GDPR_POLICIES)
    
    # 2. Modelle
    local = ModelConfig(name="nemotron-nano", ...)
    cloud = ModelConfig(name="claude-sonnet", ...)
    
    # 3. Router
    router = PrivacyRouter(engine, local, cloud)
    
    # 4. Sandboxes
    local_sandbox = ContainerSandbox(network="none", ...)
    cloud_sandbox = ContainerSandbox(network="restricted", ...)
    
    # 5. Agent
    agent = PrivacyAwareAgent(
        router=router,
        tools=[
            Tool("crm_lookup", sandbox=local_sandbox),
            Tool("web_search", sandbox=cloud_sandbox),
            Tool("calculator", sandbox=cloud_sandbox),
        ],
    )
    
    # 6. Audit
    audit = AuditLogger("./audit/routing.jsonl")

    Erweiterte Patterns

    Multi-Level-Routing

    Nicht nur binär (sensibel/nicht-sensibel), sondern mit Abstufungen:

    class Sensitivity(Enum):
        CRITICAL = "critical"      # Lokal + Container + Kernel
        SENSITIVE = "sensitive"    # Lokal + Container
        INTERNAL = "internal"      # Lokal, ohne Extra-Isolation
        PUBLIC = "public"          # Cloud erlaubt
    
    class MultiLevelRouter(PrivacyRouter):
        def __init__(self, policy_engine, models: dict[Sensitivity, ModelConfig]):
            self.policy = policy_engine
            self.models = models
        
        def route(self, query: str) -> ModelConfig:
            level = self.policy.classify(query)
            return self.models[level]

    Fallback-Ketten

    Was passiert, wenn das lokale Modell nicht verfügbar ist?

    class ResilientRouter(PrivacyRouter):
        async def route_with_fallback(self, query: str) -> ModelConfig:
            sensitivity = self.policy.classify(query)
            
            if sensitivity == Sensitivity.SENSITIVE:
                if await self._is_healthy(self.local_model):
                    return self.local_model
                else:
                    # NICHT auf Cloud fallen! Lieber fehlschlagen.
                    raise RuntimeError(
                        "Local model unavailable – "
                        "refusing to route sensitive data to cloud"
                    )
            
            return self.cloud_model

    Kritisch: Ein Privacy Router darf bei sensiblen Daten nie auf die Cloud zurückfallen. Lieber fehlschlagen als Datenschutz brechen.

    Häufige Fehler

    Fehler Warum problematisch Lösung
    Agent entscheidet Sensitivität Agent kann manipuliert werden (Prompt Injection) Policy entscheidet, nicht der Agent
    Cloud als Fallback für sensible Daten Datenschutz-Verletzung Fail statt Fallback
    Klartext im Audit-Log Log wird selbst zum Datenschutzproblem Nur Hashes loggen
    Nur Regex-Patterns Fehlende Abdeckung Regeln regelmäßig reviewen + ML als 2. Schicht
    Kein Sandboxing lokal Sensible Daten ohne Isolation Container + Kernel-Härtung

    Fazit

    Ein Privacy Router ist kein Hexenwerk – die Grundversion ist in 200 Zeilen Code gebaut. Das Schwierige ist nicht die Technik, sondern die Policies: Welche Daten sind sensibel? Wie granular muss die Klassifikation sein? Wie oft müssen Regeln aktualisiert werden?

    Drei Takeaways:

    1. Start regelbasiert – ML-Klassifikation kann später ergänzt werden, aber Regeln sind auditierbar
    2. Policy first, Code second – Definiere zuerst die Regeln, dann die Implementierung
    3. Nie auf Cloud fallen bei sensiblen Daten – Fail > Fallback

    NemoClaw: Privacy Router erklärtAgent Sandboxing: Container vs. WASM vs. KernelDie 5 Bausteine eines KI-AgentenKontakt aufnehmen

    TeilenLinkedInWhatsAppE-Mail

    Related Articles

    Diagramm eines Privacy Routers: lokale Modelle für sensible Daten, Cloud-Modelle für alles andere
    March 17, 20263 min

    NemoClaw: NVIDIAs Privacy Router und was er für die Agent-Architektur bedeutet

    NVIDIA steigt mit NemoClaw in die Claw-Welt ein – und bringt ein Konzept mit, das die Agent-Architektur verändern könnte…

    Read more
    Drei Isolationsebenen für KI-Agenten: Container, WASM und Kernel
    March 17, 20265 min

    Agent Sandboxing: Container vs. WASM vs. Kernel – drei Wege, Agenten einzusperren

    KI-Agenten brauchen Isolation. Aber welche? Container, WASM oder Kernel-Level – drei Ansätze im Vergleich, mit konkreten…

    Read more
    Dashboard zur Überwachung autonomer KI-Agenten mit Audit-Trail und Kill-Switch
    March 18, 20267 min

    AI Agent Ops: Agenten in Produktion überwachen, auditieren und kontrollieren

    Governance ist die Strategie – Agent Ops ist die Umsetzung. Wie man autonome KI-Agenten in Produktion überwacht, auditie…

    Read more
    Hunter Alpha: Das größte kostenlose KI-Modell der Welt – und steckt DeepSeek V4 dahinter?
    March 13, 20264 min

    Hunter Alpha: Das größte kostenlose KI-Modell der Welt – und steckt DeepSeek V4 dahinter?

    1 Billion Parameter, 1 Million Token Kontext, komplett kostenlos – Hunter Alpha ist das größte je veröffentlichte KI-Mod…

    Read more
    Architektur-Diagramm der 5 Bausteine eines KI-Agenten: Runtime, Channels, Memory, Tools und Self-Scheduling
    March 10, 20265 min

    Die 5 Bausteine eines KI-Agenten – Was wirklich unter der Haube steckt

    Anthropic, AWS und Google haben ihre Agent-Frameworks veröffentlicht. Aber was braucht ein KI-Agent wirklich? 5 Baustein…

    Read more
    Claude Code ist kein Dev-Tool mehr – es ist ein GTM-Layer
    March 5, 20263 min

    Claude Code ist kein Dev-Tool mehr – es ist ein GTM-Layer

    Mit Opus 4.6 hat sich Claude Code fundamental verändert: Vom Entwickler-Werkzeug zum autonomen Go-To-Market-Layer. Was w…

    Read more
    Lokale LLMs mit OpenClaw: Ollama, Llama 3.3, Qwen 3.5 & MiniMax M2.5 im Praxistest
    February 28, 20265 min

    Lokale LLMs mit OpenClaw: Ollama, Llama 3.3, Qwen 3.5 & MiniMax M2.5 im Praxistest

    Llama 3.3, Qwen 3.5 und MiniMax M2.5 lokal mit OpenClaw und Ollama betreiben – Performance-Benchmarks, Kosten-Vergleich …

    Read more
    OpenFang Agent Operating System Architektur mit 7 autonomen Hands und Rust-Kern
    March 14, 20265 min

    OpenFang Deep Dive – Das erste Agent Operating System im Detail

    OpenFang ist kein Agent-Framework – es ist ein Agent Operating System. 7 autonome Hands, 38 Tools, 40 Messaging-Kanäle. …

    Read more
    ZeroClaw KI-Agent in Rust – minimaler Footprint, maximale Performance
    March 14, 20265 min

    ZeroClaw Deep Dive – NullClaws Nachfolger in Rust im Detail

    ZeroClaw ist der Rust-Nachfolger von NullClaw – mit 26.800+ GitHub Stars, Single-Binary-Deployment und 99% kleinerem Foo…

    Read more