Zum Inhalt springen
Zurück zu Tutorials

Eine agentische AI-App absichern: Guardrails, Tool-Berechtigungen und Audit-Logs

Experte · 1 hour 15 minutes · 7 Min. Lesezeit · Byte Smith ·

Bevor du beginnst

  • Eine grundlegende Web-App- oder API-Architektur
  • Zugriff auf einen LLM-Provider oder Model-Gateway
  • Ein Tool-Calling- oder Action-Framework in Ihrer App
  • Ein Logging-Stack wie Pino, OpenTelemetry oder eine SIEM-kompatible Log-Pipeline
  • Grundlegende TypeScript- oder Node.js-Kenntnisse

Was du lernen wirst

  • Die echten Faehigkeiten und den Explosionsradius einer agentischen App kartieren
  • Vertrauensgrenzen zwischen Benutzereingabe, Speicher, Tools und externen Systemen definieren
  • Pro-Tool-Berechtigungen, Nur-Lese- versus Schreib-Scopes und Genehmigungsgates implementieren
  • Einen sicheren Ausfuehrungsfluss aufbauen, der Absicht validiert und jede wichtige Aktion protokolliert
  • Audit-Logs hinzufuegen, die Tool-Nutzung mit Benutzern, Sessions und Policy-Entscheidungen verknuepfen
  • Ihren eigenen Agenten vor dem Produktions-Rollout Red-Teamen
1
2
3
4
5
6
7
8
9
10
Auf dieser Seite

Agentische Apps sind riskanter als normale Chat-Apps, weil sie mehr tun als Text generieren. Eine normale Chat-App beantwortet einen Prompt. Eine agentische App kann Speicher lesen, Tools aufrufen, interne Systeme abfragen, Nachrichten senden, Datensaetze aktualisieren und Aktionen ausfuehren, die Menschen oder Geld betreffen. Das aendert das Bedrohungsmodell von “schlechtem Output” zu “schlechten Entscheidungen, schlechten Aktionen oder schlechten Aktionsketten.”

Dieses Tutorial zeigt, wie man eine agentische AI-App von Anfang an absichert, mit einer praktischen TypeScript-Referenzimplementierung. Sie werden eine Tool-Registry aufbauen, Vertrauensgrenzen taggen, Berechtigungen durchsetzen, menschliche Genehmigung fuer riskante Aktionen verlangen, jede wichtige Entscheidung protokollieren und Red-Team-Tests hinzufuegen. Am Ende haben Sie eine Sicherheits-Basislinie, die Sie anwenden koennen, egal ob Ihr Agent mit MCP-Tools, internen APIs oder provider-nativer Function-Calling spricht.

Verwenden Sie dies als Architekturmuster, nicht als Anbieter-Lock-in-Rezept. Der Modell-Provider kann sich aendern. Der sichere Ausfuehrungsfluss sollte es nicht.

Bevor Sie beginnen, erstellen Sie ein kleines Node.js-Projekt und installieren Sie die in den Beispielen verwendeten Abhaengigkeiten:

mkdir secure-agent-app
cd secure-agent-app
npm init -y
npm install express zod pino pino-http express-rate-limit
npm install -D typescript tsx vitest @types/node @types/express
npx tsc --init

Schritt 1: Die echten Kraaefte Ihres Agenten kartieren

Der groesste fruehe Fehler bei der Sicherheit agentischer Apps ist, vorzugeben, der Agent “ruft nur ein paar APIs auf.” Das tut er nicht. Er uebt Krafte aus. Wenn Sie diese Kraaefte nicht explizit inventarisieren, koennen Sie nicht ueber Explosionsradius, Genehmigungsanforderungen oder Audit-Erwartungen nachdenken.

Beginnen Sie damit, jedes Tool zu definieren, das der Agent verwenden kann, und klassifizieren Sie es nach Aktionstyp, Berechtigung, Umgebung und menschlicher Auswirkung.

Eine Tool-Registry erstellen

File: src/security/tool-registry.ts

import { z } from "zod";

export type ToolMode = "read" | "write";
export type Environment = "development" | "staging" | "production";

export type ToolDefinition<TArgs = unknown> = {
  name: string;
  description: string;
  mode: ToolMode;
  requiredPermission: string;
  allowedEnvironments: Environment[];
  requiresConfirmation: boolean;
  humanImpacting: boolean;
  argsSchema: z.ZodType<TArgs>;
};

const SearchKnowledgeBaseArgs = z.object({
  query: z.string().min(3).max(500),
});

const GetCustomerProfileArgs = z.object({
  customerId: z.string().uuid(),
});

const UpdateCustomerPlanArgs = z.object({
  customerId: z.string().uuid(),
  newPlan: z.enum(["basic", "pro", "enterprise"]),
  reason: z.string().min(5).max(500),
});

const SendTransactionalEmailArgs = z.object({
  customerId: z.string().uuid(),
  template: z.enum(["plan-change", "billing-notice"]),
  variables: z.record(z.string(), z.string().max(500)),
});

const IssueRefundArgs = z.object({
  customerId: z.string().uuid(),
  amountCents: z.number().int().positive().max(500000),
  reason: z.string().min(5).max(500),
});

export const toolRegistry = {
  searchKnowledgeBase: {
    name: "searchKnowledgeBase",
    description: "Read-only search over internal help and policy content.",
    mode: "read",
    requiredPermission: "kb:read",
    allowedEnvironments: ["development", "staging", "production"],
    requiresConfirmation: false,
    humanImpacting: false,
    argsSchema: SearchKnowledgeBaseArgs,
  },
  getCustomerProfile: {
    name: "getCustomerProfile",
    description: "Retrieve customer profile data needed for support tasks.",
    mode: "read",
    requiredPermission: "customer:read",
    allowedEnvironments: ["development", "staging", "production"],
    requiresConfirmation: false,
    humanImpacting: false,
    argsSchema: GetCustomerProfileArgs,
  },
  updateCustomerPlan: {
    name: "updateCustomerPlan",
    description: "Change a customer subscription plan.",
    mode: "write",
    requiredPermission: "customer:write",
    allowedEnvironments: ["staging", "production"],
    requiresConfirmation: true,
    humanImpacting: true,
    argsSchema: UpdateCustomerPlanArgs,
  },
  sendTransactionalEmail: {
    name: "sendTransactionalEmail",
    description: "Send a pre-approved customer email template.",
    mode: "write",
    requiredPermission: "email:send",
    allowedEnvironments: ["staging", "production"],
    requiresConfirmation: true,
    humanImpacting: true,
    argsSchema: SendTransactionalEmailArgs,
  },
  issueRefund: {
    name: "issueRefund",
    description: "Issue a billing refund to a customer.",
    mode: "write",
    requiredPermission: "refund:write",
    allowedEnvironments: ["staging", "production"],
    requiresConfirmation: true,
    humanImpacting: true,
    argsSchema: IssueRefundArgs,
  },
} as const;

export type ToolName = keyof typeof toolRegistry;

export type ToolRequest = {
  toolName: ToolName;
  args: unknown;
  userConfirmed?: boolean;
  approvalId?: string;
};

Diese Registry wird zur Wahrheitsquelle. Das Modell entscheidet nicht, welche Kraaefte existieren. Ihr Code tut das.

Warnung

Lassen Sie “Tool Calling” nicht die geschaeftliche Auswirkung verstecken. Ein sendTransactionalEmail-Aufruf ist nicht nur ein Tool. Es ist eine kundenorientierte Aktion mit rechtlichen, Vertrauens- und operationellen Konsequenzen.

Sie sollten nun eine Registry haben, die jede echte Aktion auflistet, die Ihr Agent ausfuehren kann, und einen schnellen Weg, seinen Explosionsradius zu ueberpruefen, bevor Sie irgendetwas ausliefern.

Schritt 2: Vertrauensgrenzen definieren

Die meisten Agenten-Fehler beginnen an einer Vertrauensgrenze. Die App behandelt abgerufene Inhalte wie Policy, Speicher wie Wahrheit oder Tool-Output wie validierte Daten. Ihr Agent muss wissen, woher Informationen kamen, wie viel er ihnen vertrauen kann und ob sie Entscheidungen oder Aktionen beeinflussen koennen.

Jede Kontextquelle taggen

Erstellen Sie einen Kontext-Builder, der jede Eingabequelle mit einem Trust-Level taggt und Policy von Daten trennt. Benutzertext ist untrusted. Abgerufene Inhalte sind untrusted. Speicher ist restricted. Policy ist trusted und wird durch Code kontrolliert.

Tipp

Ein sicherer Agent “vertraut dem Prompt” nicht. Er taggt jede Eingabequelle und haelt Policy, Speicher, Benutzereingabe und abgerufene Inhalte den gesamten Ausfuehrungspfad hindurch getrennt.

Schritt 3: Berechtigungsgrenzen hinzufuegen

Jetzt erzwingen Sie Least Privilege im Code. Hier scheitern viele Teams, weil sie sich auf Modellanweisungen wie “mach nur sichere Dinge” verlassen. Das ist kein Berechtigungssystem.

Die Autorisierungsschicht empfaengt user.permissions und environment. Das Modell kann diese Werte nicht hochstufen.

Warnung

Verwenden Sie nie dieselben Tool-Credentials in Staging und Produktion, wenn die Aktion Kunden- oder finanzielle Auswirkungen hat. Umgebungstrennung ist fuer agentische Apps nicht optional.

Schritt 4: Gegen haeufige Agenten-Risiken verteidigen

An diesem Punkt hat Ihr Agent Struktur. Jetzt brauchen Sie Verteidigungen gegen die haeufigsten agentenspezifischen Fehlermodi: Zielentfuehrung, Tool-Missbrauch, Privilegienmissbrauch, Datenleck und Tool-Chain- oder Abhaengigkeits-Exposition.

Wenn Ihr Agent beliebige URLs aufrufen kann, haben Sie bereits ein Problem. Setzen Sie ausgehenden Zugriff hinter eine Allowlist.

Hinweis

Supply-Chain-Risiko in agentischen Systemen ist nicht nur Ihr Modell-SDK. Es umfasst auch Tool-Server, Paketmanager, Plugin-Systeme, Shell-Wrapper, Browser-Automatisierungs-Treiber und jeden Helfer, der externe Systeme erreichen kann.

Schritt 5: Einen sicheren Ausfuehrungsfluss aufbauen

Kombinieren Sie nun die Teile zu einem echten Ausfuehrungspfad. Eine sichere Agentenschleife sollte Absicht validieren, vertrauenswuerdigen Kontext aufbauen, das Modell nach einem Plan fragen, jede Tool-Anfrage durch Policy laufen lassen, Genehmigung bei Bedarf verlangen und jede Entscheidung protokollieren.

Tipp

Der sicherste Ort, um einen schlechten Agenten zu stoppen, ist vor dem Tool-Aufruf, nicht danach. Policy-Entscheidungen sollten jedes Mal vor der Ausfuehrung stattfinden.

Schritt 6: Auditierbarkeit hinzufuegen

Wenn Ihr Agent eine E-Mail sendet, einen Plan aendert oder eine Erstattung ausstellt, muessen Sie spaeter grundlegende Fragen beantworten koennen: Wer hat gefragt, welcher Kontext wurde verwendet, was hat das Modell vorgeschlagen, was hat die Policy entschieden, welches Tool lief, und was passierte danach.

Warnung

Audit-Logs sind Teil Ihrer Datenexpositions-Oberflaeche. Wenn Sie wahllos alles loggen, koennen Sie ein zweites Sicherheitsproblem erzeugen, waehrend Sie versuchen, das erste zu loesen.

Schritt 7: Ihren eigenen Agenten Red-Teamen

Warten Sie nicht auf Produktionstraffic, um herauszufinden, ob Ihr Agent der Policy gehorcht. Schreiben Sie Tests, die haeufige Missbrauchspfade simulieren: Prompt-Injection, versteckte Exfiltration, Privilegieneskalation und Schreibanfragen ohne Genehmigung.

Hinweis

Red-Teaming einer agentischen App betrifft nicht nur den Modell-Prompt. Es betrifft die gesamte Kette: Kontextzusammenstellung, Risikoklassifizierung, Autorisierung, Ausfuehrung und Logging.

Schritt 8: Produktions-Rollout-Checkliste

Sie sind fast bereit auszuliefern, aber die Produktions-Basislinie braucht noch operationelle Kontrollen. Hier wird ein sicheres Design zu einem sicheren Dienst.

Fuer LLM-spezifisches Rate-Limiting auf der Proxy-Schicht, einschliesslich Pro-Key-Token-Budgets und Kosten-Dashboards, siehe LLM-API-Rate-Limiting und Kostenkontrollen implementieren.

Tipp

Fuer den Launch bedeutet “sicher genug” normalerweise, dass die App fail-closed sein kann: kein Modell-Response, keine Tool-Ausfuehrung und ein klarer Audit-Trail, der zeigt, warum.

Haeufige Einrichtungsprobleme

Alles erfordert Genehmigung, also fuehlt sich der Agent nutzlos an

Das bedeutet normalerweise, dass Sie zu viele Leseaktionen als menschlich-auswirkende Schreibvorgaenge klassifiziert haben. Halten Sie Genehmigungen bei Aktionen, die den Geschaeftszustand aendern, extern kommunizieren, Zugriff aendern oder Geld bewegen.

Ihre Logs sind voller sensibler Daten

Das passiert, wenn rohe Prompts, Tool-Argumente oder Tool-Ergebnisse direkt in Logs geschrieben werden. Redaktieren Sie Secrets, fassen Sie Ergebnisse zusammen und trennen Sie Audit-Records von Debugging-Logs.

Tool-Berechtigungen leben nur in Prompts

Wenn der System-Prompt “erstatte Kunden nicht, es sei denn genehmigt” sagt, der Code aber trotzdem issueRefund ohne Pruefungen exponiert, ist der Prompt dekorativ. Verschieben Sie alle Autorisierung in Code.

Speicher wurde zu einem Cross-User-Leak

Wenn die Notizen oder Zusammenfassungsdaten eines Benutzers in der Session eines anderen Benutzers erscheinen koennen, ist Ihre Speicherschicht jetzt ein Datenexpositionsproblem. Namespacen Sie Speicher nach Tenant, Benutzer und Session, und filtern Sie, was das Modell erreicht.

Ihr Agent kann immer noch ueber ein “sicheres” Tool exfiltrieren

Teams schuetzen oft HTTP, vergessen aber E-Mail, Tickets, Slack oder Dateiexport-Tools. Exfiltration kann ueber jeden Schreibkanal passieren.

Zusammenfassung

Sie haben nun eine minimale sichere Basislinie fuer eine agentische AI-App: eine Tool-Registry, explizite Vertrauensgrenzen, code-erzwungene Berechtigungen, Genehmigungsgates fuer riskante Aktionen, strukturierte Audit-Logs, Missbrauchspfad-Tests und eine Produktions-Checkliste, die der App hilft, sicher zu versagen, statt ruecksichtslos zu handeln.

Nach v1 sind die naechsten Verbesserungen normalerweise bessere Risikobewertung, staerkere Tenant-Isolation, Genehmigungs-UX, reichere Audit-Dashboards und engeres Sandboxing um Tools oder MCP-Server. Wenn Ihre App in Multi-Agenten-Workflows, Browser-Automatisierung oder mehr externe Tools waechst, ueberpruefen Sie dieselben Grundlagen: Least Privilege, Vertrauensgrenzen, menschliche Genehmigung wo es darauf ankommt, und Logs, die Ihnen erlauben, zu rekonstruieren, was passiert ist.

Die wichtigste Designentscheidung ist einfach: Behandeln Sie das Modell als Planer, nicht als Superuser. Sobald Ihre Architektur das widerspiegelt, wird der Rest der Sicherheitsgeschichte viel einfacher.

Wenn Ihre agentische AI-App Code in CI/CD-Pipelines generiert, siehe auch AI-Coding-Agent-Pipelines absichern, das behandelt, wie man AI-generierte PRs erkennt, Policy-as-Code durchsetzt, Sicherheitsscans ausfuehrt, Tests in einer Sandbox ausfuehrt und Merges nach Risikostufe gated.