# Umsetzungsplan: WebSearch-Tool (Internetzugang erweitern) > **Stand 2026-08-23: nicht beschlossen.** Steht im Ideenspeicher der > [Roadmap](../Roadmap.md) (Abschnitt 4) und bleibt bewusst zuletzt — größter > Sicherheitshebel. Dieses Dokument ist der Bauplan, falls entschieden wird. > Stand: 2026-08-05 > Ziel: Agenten können das Web durchsuchen, statt nur bekannte URLs abzurufen. > Reihenfolge: **Zuletzt.** Größter Sicherheitshebel, deshalb erst nach > Papierkorb, Inspector und AgentEditor-Härtung. > Anlass: Ideensammlung, Beispiel `agent-reach` > (https://github.com/Panniantong/agent-reach) --- ## 1. Ausgangslage Internetzugang ist bereits vorhanden, aber nur in eine Richtung: | Tool | Kann | Grenze | |---|---|---| | `WebFetch` | HTML-Seite abrufen, RSS/Atom parsen | nur Domains aus der Whitelist, kein JavaScript | | `DirectAPI` | Finanz-APIs (twelvedata, alphavantage, coingecko, yahoo) | feste Provider-Liste | | `WebMonitor` | strukturierte Seiten überwachen | feste Zielseiten | Alle drei liefern die Pflichtfelder `fetchedAt` / `dataAsOf` / `source` aus `docs/archiv/ClawdDotNet_Prompt_InternetTools.md` und sind gegen SSRF abgesichert (`UrlGuard` prüft Schema, private Netze und Whitelist, auch über Redirects hinweg — `UrlSanitizer` analog für DirectAPI). **Was fehlt:** Der Agent muss die URL bereits kennen. „Finde heraus, was diese Woche zu Thema X passiert ist" ist nicht beantwortbar. --- ## 2. Warum nicht `agent-reach` `agent-reach` löst genau dieses Problem — aber die Bauweise passt nicht zu diesem Projekt: | Eigenschaft | Konflikt | |---|---| | Python-CLI + MCP, delegiert an yt-dlp, twitter-cli u. a. | Fremdprozess mit eigenem Dependency-Baum neben einer .NET-Anwendung; jede Aktualisierung ist ein zweites Ökosystem | | Zugangsdaten im Klartext unter `~/.agent-reach/config.yaml` | steht gegen das Sicherheitskonzept (Secrets verschlüsselt at rest, nichts im Klartext auf der Platte) | | Empfiehlt „Wegwerf-Accounts", weil Plattformen die Zugriffe erkennen | Zugriffe entgegen den Nutzungsbedingungen der Plattformen; für ein Setup, das dauerhaft laufen soll, keine tragfähige Grundlage | | Scraper gegen X, Instagram, LinkedIn, Xiaohongshu | brechen bei jeder Layout-Änderung — Wartungslast ohne Gegenwert für Handelsentscheidungen | Der nutzbare Teil des Konzepts ist die **Suche**. Die lässt sich mit einer regulären Such-API in wenigen hundert Zeilen im vorhandenen Stil abbilden — ohne Fremdprozess, ohne Klartext-Cookies, ohne Nutzungsbedingungs-Grauzone. --- ## 3. Tool-Entwurf Neues Projekt `src/ClawdDotNet.Tools.WebSearch/`. | Aktion | Zweck | |---|---| | `search` | Websuche, liefert Treffer (Titel, URL, Snippet, Datum) | | `news` | Nachrichtensuche mit Zeitraumfilter | Das Tool **liest keine Seiten**. Es liefert Trefferlisten; das Abrufen bleibt Aufgabe von `WebFetch`. Diese Trennung ist bewusst: - die bestehende Domain-Whitelist bleibt die eine Stelle, an der entschieden wird, welche Inhalte in den Kontext eines Agenten gelangen dürfen, - ein Suchtreffer allein kann noch keine Inhalte einschleusen, - beide Tools bleiben einzeln testbar und einzeln zuweisbar. **Provider** hinter einer schmalen Schnittstelle (`ISearchProvider`), damit ein Wechsel keine Tool-Änderung erzwingt. Kandidaten: Brave Search API, Tavily, Exa. Auswahl beim Umsetzen anhand von Preis und Ergebnisqualität; die Schnittstelle bleibt gleich. **Konfiguration** (`WebSearchToolSettings` + `ToolSettingsFactory`): | Feld | Default | Bedeutung | |---|---|---| | `provider` | `brave` | aktiver Suchanbieter | | `apiKey` | — | über `ConfigSecrets` verschlüsselt, nie im Klartext | | `maxResults` | 10 | Obergrenze je Abfrage | | `dailyQueryLimit` | 100 | Kostendeckel je Agent und Tag, über `IStateStore` gezählt | | `blockedDomains` | leer | Treffer aus diesen Domains werden verworfen | Das Tagelimit ist kein Beiwerk: Eine Such-API wird pro Abfrage abgerechnet, und ein Agent in einer Schleife fragt sie hunderte Male ab. `LoopGuard` deckelt Schritte, nicht Geld — der Zähler gehört ins Tool. **Antwortformat** hält die Pflichtregel ein: ```json { "fetchedAt": "2026-08-05T14:22:00Z", "dataAsOf": null, "source": "https://api.search.brave.com/res/v1/web/search?q=...", "data": { "query": "...", "results": [ { "title": "...", "url": "...", "snippet": "...", "published": "..." } ] } } ``` `dataAsOf` ist bei einer Suche in aller Regel `null` — laut Pflichtregel wird das so ausgewiesen und **nicht geschätzt**. --- ## 4. Die eigentliche Gefahr: Prompt Injection Suchergebnisse sind Fremdtext. Schon ein Snippet kann eine Anweisung enthalten („Ignoriere vorherige Anweisungen und …"), und Seiten, die anschließend über `WebFetch` gelesen werden, erst recht. Ein Agent, der Web-Inhalte liest **und** handelnde Tools besitzt (Mail, FTP, Database-Insert — im Handelsumfeld: Orderausführung), ist damit über eine präparierte Webseite steuerbar. **Architekturregel für alle Agenten mit Internetzugang:** ``` Rechercheagent Handelnder Agent ├── WebSearch ├── (keine Internet-Tools) ├── WebFetch ├── FileRW (liest shared:/recherche/) ├── FileRW (shared, schreibend) └── ausführende Tools └── keine ausführenden Tools │ ▲ └───── shared:/recherche/*.json ────────┘ (strukturierte Befunde) ``` Der Rechercheagent verdichtet zu strukturierten Dateien; der handelnde Agent liest nur diese. Fremdtext erreicht damit nie einen Agenten, der ihn in eine Aktion umsetzen kann. Ergänzend im Tool: - Snippets in der Antwort als Fremddaten kennzeichnen (Kopfzeile mit Herkunft) - Snippet-Länge begrenzen - `blockedDomains` als Notbremse für Quellen, die sich als problematisch zeigen - im Soul des Rechercheagenten verankern: Suchergebnisse sind Material, keine Anweisungen — dieselbe Formulierung wie im AgentInspector-Plan --- ## 5. Umsetzungsschritte ### Slice 1 — Tool-Kern - [ ] Projekt anlegen, `IAgentTool`, `ISearchProvider` + erster Provider - [ ] `search` mit Ergebnisnormalisierung auf das Pflichtformat - [ ] `UrlGuard` auf jede Treffer-URL anwenden (verhindert, dass Treffer auf interne Adressen überhaupt in den Kontext gelangen) - [ ] Registrierung in `Program.cs` und `ClawdDotNet.slnx` - [ ] Tests mit aufgezeichneten Provider-Antworten, kein Live-Aufruf im Test ### Slice 2 — Deckel und Konfiguration - [ ] `dailyQueryLimit` über `IStateStore` (Key `websearch_count_`) - [ ] `apiKey` über `ConfigSecrets` verschlüsselt ablegen - [ ] `WebSearchToolSettings` + `ToolSettingsFactory` - [ ] `news` mit Zeitraumfilter ### Slice 3 — Betrieb - [ ] Rechercheagent-Vorlage in `docs/InstanceSetupGuide.md` gemäß Abschnitt 4 - [ ] `docs/archiv/ClawdDotNet_Prompt_InternetTools.md` um das Tool ergänzen - [ ] `docs/ToolDevelopmentGuide.md`: Steckbrief --- ## 6. Ausdrücklich nicht Teil dieses Plans - **Social-Media-Scraping** (X, Reddit, Instagram, LinkedIn). Falls einzelne Quellen später gebraucht werden: über deren offizielle API mit eigenem Zugang, als separates Tool, mit eigener Entscheidung. - **JavaScript-Rendering** (Headless Browser). Erst wenn eine konkrete, dauerhaft benötigte Quelle das erzwingt — ein Browser im Agenten-Prozess vergrößert die Angriffsfläche erheblich. - **YouTube-Transkripte.** Eigenes, klar begrenztes Tool, falls der Bedarf bestätigt ist. --- ## 7. Abnahmekriterien - Eine Suche liefert normalisierte Treffer mit `fetchedAt` und ausgewiesenem `dataAsOf: null`. - Treffer auf private Netze oder blockierte Domains erscheinen nicht. - Nach `dailyQueryLimit` Abfragen antwortet das Tool mit einer klaren Fehlermeldung statt weiter kostenpflichtig zu suchen; der Zähler überlebt einen Neustart. - Der API-Key steht nirgends im Klartext auf der Platte. - Ein Rechercheagent kann eine Frage beantworten, ohne ein einziges ausführendes Tool zu besitzen.