1. Agenten‑Tool: Was es wirklich ist
In den vorigen Modulen haben Sie Tools bereits von der App‑SDK‑Seite gesehen — als „Backend‑Funktionen“, die ChatGPT über Ihre App aufruft. Jetzt wechseln wir die Perspektive: Wir schauen auf Tools durch die Augen des Agenten im Agents SDK und klären, wie er auswählt, was er aufruft, und was mit Fehlern passiert.
Im klassischen Backend denken Sie in Kategorien wie „Endpoint“, „Controller‑Methode“, „Service‑Funktion“. In der Agentenwelt ist die grundlegende Aktionseinheit das Tool. Agent‑Tools und MCP‑Tools sind verschieden, auch wenn sie sich überschneiden.
Streng genommen ist ein Tool im Kontext des ChatGPT Agents SDK die Beschreibung einer Funktion, die das Modell um Ausführung bitten kann. Das Modell führt keinen Code selbst aus; es generiert eine strukturierte Anfrage (meist JSON), und der Runtime (Ihr Code, ein MCP‑Server oder das Agents SDK) führt die Operation aus und liefert das Ergebnis zurück.
Im Ökosystem des ChatGPT Agents SDK wird ein Tool über eine Konfiguration beschrieben: Es hat name, description und parameters (JSON Schema der Argumente). Der Agent sieht diesen Satz an Tools, hält sie in seinem Kontext und entscheidet im Zuge des Reasonings, welches Tool er mit welchen Argumenten aufruft.
Der Agent (oder ChatGPT als Host) erhält diese Liste, „merkt“ sie sich in seinem Kontext und entscheidet während der Überlegungen (Reasoning): Zu welcher Nutzeranfrage er welches Tool mit welchen Argumenten aufruft. Daher wird in Spezifikationen ständig die Maxime wiederholt „tools are a contract“ — Tools sind ein Vertrag zwischen Modell und Ihrem Code, nicht einfach „eine Funktion in Python/TS“.
Eine Analogie zum klassischen API: Die Route /api/gifts/search ist reine Syntax: URL, Methode, Body‑Format. Ein Tool search_gifts ist Semantik: „Geschenke nach Profil und Budget suchen“. Die Toolbeschreibung ist eine Art Prompt — nur strukturiert und für LLM ausgelegt, nicht für Menschen.
2. Tool‑Typen: Womit sich ein LLM‑Agent konkret befasst
Damit das nicht im Chaos „Funktionen, die alles können“ endet, ist es hilfreich, Tools in ein paar typische Kategorien einzuordnen. Das ist keine formale Typisierung des SDK, sondern architektonisches Denken — sehr hilfreich in der Praxis.
In unserem Backend haben LLM‑Agenten in der Regel drei Quellen für Tools.
- Lokale Business‑Tools. Das ist alles, was in Ihrem Backend lebt: Arbeit mit der DB, Domänenlogik (Filterung, Empfehlungen, Scoring). Für GiftGenius könnten wir z. B. Tools haben, die Produkte aus einer eigenen PostgreSQL‑Tabelle holen oder ein persönliches Scoring berechnen: „Wie gut kommt das Geschenk bei dieser Person an?“
- MCP‑Tools. Hier fungiert der MCP‑Server als Tool‑Provider: Er registriert Funktionen, Ressourcen und Prompts und stellt sie dem Client (ChatGPT, LLM‑Agent) bereit. Über MCP können Tools externe APIs aufrufen, mit Dateien arbeiten oder Prompt‑Templates bereitstellen.
- Integrations‑Tools. Das verbindet Sie mit der Außenwelt: ACP/Commerce (Bestellung anlegen und Checkout), E‑Mails versenden, Webhooks, Einträge ins CRM. Solche Tools sind oft riskanter, weil sie den Zustand externer Systeme ändern; sie benötigen besondere Sorgfalt in Sachen Sicherheit und Idempotenz.
Eine weitere nützliche Einteilung ist die nach der Art der Aktion. In der Forschung zu LLM‑Tools unterscheidet man in der Regel: Datenabruf‑Tools (Suche, RAG, get_*), Tools mit Seiteneffekten (create_order, send_email), reine Rechen‑Tools (calculate_loan) sowie System‑/Steuer‑Tools (handoff_to_human, finish_task).
Zur Veranschaulichung hilft eine kleine Tabelle.
| Kategorie | Beispiel in GiftGenius | Nebeneffekt | Risiko |
|---|---|---|---|
| Data Retrieval | |
Nein | Niedrig |
| Action / Mutating | |
Ja | Hoch |
| Computation | |
Nein | Mittel |
| System / Control | |
Nein | Logisch |
Aus architektonischer Sicht ist am wichtigsten: Read‑only‑Tools sollten zahlreich und günstig sein, mutierende dagegen selten, äußerst sorgfältig umgesetzt, mit Logging, Idempotenz und oft mit Benutzerbestätigung.
Im Folgenden sprechen wir vor allem über Datenabruf‑Tools und Action‑Tools, weil darauf die Logik von GiftGenius basiert.
3. JSON Schema als Vertrag zwischen Modell und Ihrem Code
Schauen wir uns nun an, wie ein Tool beschrieben wird. Im ChatGPT Agents SDK (wie auch im Apps SDK) ist das Standardformat für die Beschreibung der Tool‑Parameter JSON Schema: Sie beschreiben den Typ object, seine properties, Feldtypen, Pflichtfelder, Constraints usw.
Wichtig: JSON Schema dient hier nicht nur der Validierung. Es ist Teil des Prompts für das Modell. In den offiziellen OpenAI‑Guides zum Tool‑Design (tools) wird explizit betont, dass die Qualität der Agentenarbeit stark davon abhängt, wie detailliert und eindeutig Felder, ihre Namen und Beschreibungen ausgearbeitet sind.
Schauen wir auf ein Beispiel für GiftGenius, das wir im Kurs schon erwähnt haben.
{
"name": "search_gifts",
"description": "Findet Geschenke nach Empfängertyp, Interessen und Budget.",
"parameters": {
"type": "object",
"properties": {
"recipient_type": {
"type": "string",
"description": "Wer ist der Geschenkempfänger (z. B. 'Mann', 'Frau', 'Kind')."
},
"interests": {
"type": "array",
"items": { "type": "string" },
"description": "Schlüsselinteressen (Sport, Bücher, Technologie usw.)."
},
"budget": {
"type": "number",
"description": "Maximales Budget in der Währung des Nutzers."
}
},
"required": ["recipient_type", "budget"]
}
}
Hier gibt es mehrere wichtige Punkte.
- Erstens name und description. Für das Modell ist das das wichtigste Signal, wann dieses Tool überhaupt zu verwenden ist. Die Dokumentation zum semantischen Routing betont, dass die Toolbeschreibung faktisch das API für das Modell ist: Wenn Sie es func1 nennen und „macht etwas Nützliches“ schreiben, wird das Modell kaum wissen, wann es das Tool aufrufen soll. Heißt es hingegen search_gifts mit klarer Beschreibung, wird die Wahl wesentlich einfacher.
- Zweitens parameters. Feldnamen und deren Beschreibungen sind extrem wichtig. Für ein LLM ist recipient_type weitaus verständlicher als type. Eine gute Beschreibung wie „Wer ist der Geschenkempfänger …“ signalisiert dem Modell, dass hier der Empfängertyp und nicht z. B. die Verpackungsart einzutragen ist.
- Drittens required. Das ist nicht nur Validierung auf Ihrer Seite, sondern auch ein Hinweis an das Modell: Es wird versuchen, Pflichtfelder zu füllen, und optionale auslassen, wenn der Kontext es nicht hergibt. Das reduziert die Zahl „leerer“ oder fehlerhafter Tool‑Aufrufe.
Die offiziellen Apps‑SDK‑Guides empfehlen ausdrücklich: Bauen Sie Tools schmal, mit einer Verantwortung, klaren Namen und Beschreibungen, und vermeiden Sie „mach‑alles‑für‑Geschenke“-Tools, die verschiedene Aufgaben zusammenwürfeln.
4. Tools für GiftGenius entwerfen: von Schema zu Code
Nehmen wir unser GiftGenius und fügen zwei Schlüsselinstrumente des LLM‑Agenten hinzu, die in fast allen Szenarien benötigt werden:
- suggest_gifts(profile, budget) — liefert eine Kandidatenliste;
- get_gift_details(gift_id) — zeigt Details zu einem konkreten Geschenk.
Unsere suggest_gifts und get_gift_details sind typische lokale Business‑Tools aus der vorigen Klassifikation, überwiegend in der Kategorie Data Retrieval.
Schema für suggest_gifts
Wir beginnen mit einem reinen JSON Schema und zeigen danach, wie das im TypeScript‑Code des Backends/Agent‑Runtimes aussehen kann.
{
"name": "suggest_gifts",
"description": "Stellt eine Geschenkeliste anhand des Empfängerprofils und Budgets zusammen.",
"parameters": {
"type": "object",
"properties": {
"age": {
"type": "integer",
"minimum": 0,
"maximum": 120,
"description": "Alter des Empfängers in Jahren."
},
"relationship": {
"type": "string",
"enum": ["friend", "coworker", "partner", "family"],
"description": "Beziehung zum Empfänger: Freund, Kollege, Partner, Familie."
},
"interests": {
"type": "array",
"items": { "type": "string" },
"description": "Interessen des Empfängers (Sport, Bücher, Technologie usw.)."
},
"budget": {
"type": "number",
"minimum": 1,
"description": "Maximales Budget in der Währung des Nutzers."
}
},
"required": ["budget"]
}
}
Hier verwenden wir enum für relationship, damit das Modell keine beliebigen Strings wie "schlechter Kollege" erfindet und in den Code weiterreicht. Ein sorgfältiges Schema‑Design hilft sowohl dem Modell (es sieht zulässige Varianten) als auch der Entwicklung (weniger Überraschungen im Runtime).
Nehmen wir nun an, wir haben einen MCP‑Server auf Node.js mit einem hypothetischen McpServer. Die Registrierung des Tools könnte so aussehen:
// Vereinfachtes Beispiel für die Registrierung eines Tools im MCP-Server
server.registerTool(
{
name: "suggest_gifts",
description: "Wählt Geschenke nach Profil und Budget aus.",
inputSchema: suggestGiftsSchema
},
async (input, ctx) => {
const gifts = await findGiftsInDb(input, ctx.userLocale);
return { items: gifts }; // JSON, das der Agent anschließend sieht
}
);
Der Code ist stark vereinfacht, aber die Logik ist klar: an einer Stelle — die Vertragsbeschreibung (Name, Beschreibung, Schema), an einer anderen — die Implementierung.
Schema für get_gift_details
Das zweite Tool, das fast in jeder Oberfläche gebraucht wird:
{
"name": "get_gift_details",
"description": "Ruft vollständige Informationen zu einem Geschenk anhand seiner ID ab.",
"parameters": {
"type": "object",
"properties": {
"gift_id": {
"type": "string",
"description": "UUID des Geschenks in der GiftGenius-Datenbank."
}
},
"required": ["gift_id"]
}
}
Und eine ähnliche Registrierung:
server.registerTool(
{
name: "get_gift_details",
description: "Gibt detaillierte Informationen über das Geschenk zurück.",
inputSchema: getGiftDetailsSchema
},
async ({ gift_id }) => {
const gift = await db.gifts.findById(gift_id);
if (!gift) return { notFound: true };
return { gift };
}
);
Beachten Sie: Wir zeigen hier sofort, dass das Tool notFound: true zurückgeben kann. Das sind bereits Ansätze semantischer Fehler (Business‑Fehler), über die wir gleich sprechen. Der Agent kann „Geschenk nicht gefunden“ sehen und entscheiden: z. B. eine andere ID probieren oder dem Nutzer eine Alternative vorschlagen.
5. Wie der Agent auswählt, welches Tool er aufruft
Jetzt wird es spannend: Routing. Im klassischen Web‑App ist Routing strikt: URL → konkreter Controller. In der Welt von ChatGPT Apps und Agenten erfolgt die Tool‑Wahl semantisch und probabilistisch.
Der Zyklus auf hoher Ebene lässt sich so darstellen:
flowchart TD
U[User message] --> M["Modell (Agent)"]
M -->|Anfrageanalyse| C{Tool nötig?}
C -->|nein| T[Textantwort]
C -->|ja| S[Tool-Auswahl]
S --> K[JSON-Argumente erstellen]
K --> R[Tool ausführen]
R --> M2[Modell sieht das Ergebnis]
M2 --> T2[Finale Antwort oder nächster Schritt]
In jedem Schritt sieht der Agent mehrere Dinge:
- Erstens: System‑Instruktionen (Rolle des Agenten, Einschränkungen);
- Zweitens: den Gesprächsverlauf;
- Und schließlich die Liste der Tools mit name, description, inputSchema.
Wenn eine neue Benutzeranfrage ankommt, vergleicht das Modell die Bedeutung der Anfrage mit den Tool‑Beschreibungen (semantisches Matching). Bei „Such ein Geschenk für einen Freund bis 50 Dollar“ klingt die Beschreibung von suggest_gifts deutlich relevanter als get_gift_details — der Agent wird es mit hoher Wahrscheinlichkeit auswählen.
Die offiziellen Guides betonen zwei Punkte, die die Qualität des Routings stark beeinflussen.
- Erstens sollte man semantisch überlappende Tools vermeiden: Wenn Sie search_gifts und find_gifts haben, die beide „Geschenke nach Interessen suchen“, kommt das Modell durcheinander.
- Zweitens empfiehlt sich das Prinzip der Single Responsibility: ein Tool — eine klar umrissene Aufgabe, nicht „Geschenke finden und Bestellung anlegen und E‑Mail senden“.
In verschiedenen LLM‑Agenten gibt es Modi zur Steuerung der Tool‑Auswahl: etwa „auto“ (das Modell entscheidet selbst, ob ein Tool nötig ist), „required“ (Tool‑Aufruf ist obligatorisch), „none“ (Tools deaktiviert). Das hilft in komplexen Workflows (mehrstufige Szenarien), wenn Sie z. B. in einem Schritt suggest_gifts zwingend aufrufen möchten, statt dem Modell freien Text zu erlauben.
Beispiel für semantisches Routing in GiftGenius
Nehmen wir an, unser Agent hat mindestens zwei Tools: suggest_gifts und get_gift_details.
- Der Nutzer schreibt: „Finde ein Geschenk für einen Kollegen bis 30 Dollar, er mag Brettspiele.“
- Der Agent erkennt Ziel „Geschenk finden“, Informationen zu Budget und Interessen. Die Beschreibung von suggest_gifts passt perfekt — dieses Tool wird aufgerufen.
- Das Tool liefert eine Liste aus fünf Geschenken mit ihren IDs, Titeln und Kurzbeschreibungen.
- Der Nutzer schreibt weiter: „Erzähl mir mehr über die dritte Option.“ Der Agent ordnet „dritte Option“ der ID aus dem vorherigen Ergebnis zu; nun passt semantisch get_gift_details — also wird dieses Tool aufgerufen.
Wichtig: Nirgends im Code haben Sie explizit geschrieben „Wenn die Anfrage das Wort ‚finde‘ enthält, rufe suggest_gifts auf“. Das übernimmt das Modell auf Basis Ihrer Beschreibungen und der Historie. Ihre Verantwortung ist es, die Wahl sowohl für das Modell als auch für Menschen offensichtlich zu machen.
6. Tool‑Fehler: kein 500, sondern ein Signal für das Modell
Erinnern Sie sich: In get_gift_details haben wir bereits notFound: true gezeigt. Das ist ein Beispiel für einen Business‑Fehler, den der Agent sehen und sinnvoll verarbeiten sollte — statt eines nackten 500.
Nun zum schmerzhaftesten Teil. Im üblichen REST‑API fällt etwas tief im Backend um — man gibt 500 Internal Server Error zurück, schreibt den Stacktrace ins Log — und der Nutzer muss klarkommen. Beim Agenten funktioniert das schlecht.
Praktische Guides und Materialien zum Agents SDK empfehlen, Tool‑Fehler als beobachtbare Ereignisse zu behandeln, nicht bloß als Abstürze. Das nennt man oft das Pattern „Error as Observation“.
Grob gesagt: Sie sollten nicht „ohne Erklärung abstürzen“, sondern dem Modell eine strukturierte Antwort zurückgeben, die erklärt, was schiefging, damit es sein Verhalten anpassen kann: Anfrage umformulieren, den Nutzer fragen, ein anderes Tool probieren usw.
Typische Fehler teilt man meist in drei Gruppen ein.
- Validierungsfehler der Argumente. Das Modell kann inkorrekte Parameter generieren: Pflichtfeld vergessen, String statt Zahl, außerhalb erlaubter Grenzen. Nutzen Sie Ihr Schema und die Validierung nicht nur, um Exceptions zu werfen, sondern auch für sinnvolle Antworten: etwa zurückgeben, welches Feld warum ungültig ist.
- Business‑Fehler. Erwartbare Situationen wie „Artikel nicht gefunden“, „Region nicht verfügbar“, „Budget zu niedrig für diesen Geschenktyp“. Aus API‑Sicht sind das auch Fehler, aber sie sollten innerhalb einer normalen Antwort zurückgegeben werden — mit verständlichem Code und Nachricht, nicht als Crash.
- Systemfehler. Timeouts externer Dienste, Netzwerkprobleme, DB‑Ausfälle. Hier reicht dem Agenten meist eine vorsichtige, allgemeine Meldung wie „Dienst vorübergehend nicht verfügbar, bitte später erneut versuchen“. Keine Stacktraces, Tabellennamen oder andere Details, die das Modell nicht braucht und sicherheitskritisch sein können.
Die offiziellen Materialien zum Agents SDK schlagen sogar einen speziellen Mechanismus failure_error_function vor, mit dem Sie den Fehlertest, den das Modell sieht, sauber formulieren können — statt eine Exception einfach den Stack hochzuwerfen.
Struktur eines „freundlichen“ Fehlers
Im Agenten‑Tool (in Ihrem Backend) können Sie vereinbaren, dass jeder Fehler z. B. als Objekt zurückgegeben wird:
type ToolError = {
code: string; // 'VALIDATION_ERROR', 'OUT_OF_STOCK', ...
message: string; // für das Modell
retryable: boolean;
};
Und das Tool‑Ergebnis als Vereinigung:
type SuggestGiftsResult =
| {
ok: true;
items: GiftSummary[];
}
| {
ok: false;
error: ToolError;
};
Das Modell (oder der Agent‑Runtime) sieht solches JSON und kann entscheiden: Ist retryable: true, kann es mit kleinen Änderungen erneut versuchen; ist es ein nicht‑wiederholbarer Business‑Fehler, ist es besser, zum Nutzer zurückzugehen und zu erklären, was nicht passt.
7. Beispiele: Validierung, Business‑Fehler und Systemfehler
Zurück zu unserem Backend/Agenten‑Tools — sehen wir uns an, wie man diese Ideen im Code umsetzen kann.
Validierungsfehler
Angenommen, suggest_gifts kommt rein, aber das Modell übergibt aus irgendeinem Grund ein negatives Budget.
async function handleSuggestGifts(input: SuggestGiftsInput)
: Promise<SuggestGiftsResult> {
if (input.budget <= 0) {
return {
ok: false,
error: {
code: "VALIDATION_ERROR",
message: "budget muss eine positive Zahl sein.",
retryable: false
}
};
}
const items = await findGiftsInDb(input);
return { ok: true, items };
}
Hier werfen wir bewusst keine Exception, sondern liefern einen strukturierten Fehler. Der Agent kann die Anfrage neu bewerten: Vielleicht stellt er fest, dass die Währung verwechselt wurde, fragt den Nutzer oder gibt zu, dass er mit diesem Budget kein Geschenk vorschlagen kann.
Business‑Fehler
Jetzt ein Beispiel mit get_gift_details. Ein Geschenk mit der angegebenen ID existiert eventuell nicht.
async function handleGetGiftDetails(input: { gift_id: string }) {
const gift = await db.gifts.findById(input.gift_id);
if (!gift) {
return {
ok: false,
error: {
code: "GIFT_NOT_FOUND",
message: "Geschenk mit dieser ID wurde nicht gefunden.",
retryable: false
}
};
}
return { ok: true, gift };
}
Vom Modell ist dann eine Antwort zu erwarten wie: „Es scheint, das gewählte Geschenk ist nicht mehr verfügbar. Soll ich einige Alternativen aus einer ähnlichen Kategorie vorschlagen?“ Dafür braucht der Agent keine SQL‑Fehler und Stacktraces — nur einen klaren code und eine message.
Systemfehler
Zum Schluss ein Systemfehler. Nehmen wir an, Ihr Tool ruft ein externes Liefer‑API auf, das gelegentlich „ausfällt“.
async function handleEstimateDelivery(input: EstimateDeliveryInput) {
try {
const eta = await callDeliveryApi(input);
return { ok: true, eta_days: eta };
} catch (e) {
return {
ok: false,
error: {
code: "DELIVERY_SERVICE_UNAVAILABLE",
message: "Der Lieferservice ist vorübergehend nicht verfügbar.",
retryable: true
}
};
}
}
Der Agent könnte entscheiden: „Der Lieferservice ist offenbar gerade nicht verfügbar. Ich zeige Ihnen trotzdem Geschenke, aber die genaue Lieferzeit kann abweichen. Möchten Sie fortfahren?“
8. Sicherheit und Idempotenz von Tools (kurzer Blick aus Tool‑Perspektive)
Ein ausführliches Gespräch über Sicherheit und Berechtigungen folgt separat, aber Tools eines Agenten sind so eng damit verbunden, dass wir es hier kurz streifen.
Erstens sollte man Lese‑ und Schreib‑Tools trennen. Geben Sie in Beschreibungen, Schemata und Berechtigungen explizit an, welche Tools nur lesen und absolut sicher sind und welche Geld abbuchen, Bestellungen ändern usw. Die Doku und Foren zu Agenten‑Szenarien sprechen explizit von der Trennung zwischen ReadOnly‑ und Mutating‑Tools.
Zweitens: Für mutierende Tools müssen Sie über Idempotenz nachdenken. Ein Agent oder MCP‑Client kann einen Aufruf wiederholen (z. B. wegen eines Netzwerkfehlers), und Sie wollen nicht, dass create_order zwei Bestellungen statt einer erzeugt. Typische Patterns sind:
- idempotency‑key, der als Tool‑Argument übergeben wird;
- Existenzprüfung der Operation vor der Ausführung;
- Aufteilung in „Bestell‑Entwurf erstellen“ und „Bestellung bestätigen“.
All das hängt eng damit zusammen, wie Sie den Tool‑Vertrag entwerfen: Wenn im JSON Schema kein Feld für den idempotency‑key vorgesehen ist, wird es später deutlich schmerzhafter, Idempotenz nachzurüsten.
9. Kurzer Blick auf das Agents SDK: so sieht es im Agent‑Runtime aus
Dieser Abschnitt ist ein Überblick für alle, die mit dem TypeScript‑orientierten Agents SDK arbeiten. Obwohl der Kurs hauptsächlich MCP behandelt, ist es hilfreich zu verstehen, wie Agents SDK ähnliche Tools sieht und wie ein typisches Tool im Runtime aussieht.
In der offiziellen Dokumentation wird oft ein „funktionales Tool“ beschrieben: Jede Funktion, die über ein Konfig‑Objekt (oder einen Helper wie tool(...)) beschrieben und mit Typen versehen ist, kann automatisch in ein Tool verwandelt werden, für das das SDK JSON Schema und Beschreibung generiert.
Konzeptionell ist das dasselbe, was wir bereits besprochen haben: Funktionsname, Parameter und Kommentar/Beschreibung entsprechen Name, Schema und Beschreibung des Tools. Der Unterschied: Den „mechanischen“ Teil übernimmt das SDK und/oder eine Schema‑Hilfsbibliothek (z. B. Zod oder JSON Schema).
Ein hypothetisches Beispiel (Pseudo‑TypeScript, vereinfacht):
type Gift = {
id: string;
title: string;
// ...
};
const suggestGifts = tool({
name: "suggest_gifts",
description: "Stellt eine Liste von Geschenken nach Empfängertyp und Budget zusammen.",
parameters: {
type: "object",
properties: {
recipient_type: {
type: "string",
description: "Wer ist der Geschenkempfänger (z. B. 'Mann', 'Frau', 'Kind')."
},
budget: {
type: "number",
description: "Maximales Budget in der Währung des Nutzers."
}
},
required: ["recipient_type", "budget"]
}
}, async (args: { recipient_type: string; budget: number }): Promise<Gift[]> => {
// Ihre Domänenlogik
return findGifts(args.recipient_type, args.budget);
});
Das SDK (oder Ihr Helper tool) baut aus dem Objekt parameters ein JSON Schema und übergibt es an den Agenten; der Runtime kümmert sich um Validierung und Marshaling der Argumente hin und zurück. Konzeptionell ist das genau das, was Sie zuvor im TypeScript‑MCP‑Server manuell gemacht haben — nur jetzt ist das Tool direkt in den Agent‑Runtime „eingehängt“.
Wichtig ist hier nicht, die Syntax des Helpers tool auswendig zu lernen, sondern die Idee zu verinnerlichen: gute Typisierung + klare Beschreibung/Kommentare = gutes Tool.
Wenn man alles zusammenführt: Ein gutes Agenten‑Tool ist eine schmale, klar beschriebene Funktion mit durchdachtem JSON Schema, verständlicher Beschreibung für das Modell und sorgfältiger Fehlerbehandlung. Semantisches Routing funktioniert nur, wenn sich Tools semantisch nicht überschneiden. Und mutierende Operationen müssen sicher und idempotent sein — sonst wird der Agent im Produktivbetrieb schnell zur Überraschungskiste.
10. Typische Fehler beim Entwerfen von Agenten‑Tools
Fehler Nr. 1: Zu breite „do_everything“-Tools.
Es ist verlockend, alles in ein einziges Tool manage_gifts zu stopfen, das sowohl Geschenke sucht als auch Details anzeigt, Bestellungen anlegt und E‑Mails sendet. Für das Modell wird es dann schwer: Die Beschreibung wird schwammig, das semantische Routing leidet, und der Agent ruft dieses Tool „zur Sicherheit“ auch dort auf, wo eine einfache Suche genügt. Besser Aufgaben in separate Tools mit einer klar verständlichen Verantwortung aufteilen.
Fehler Nr. 2: Semantisch überlappende Tools.
Wenn Sie search_gifts und find_gifts haben, die beide „Geschenke nach Interessen suchen“, wählt das Modell zufällig zwischen ihnen. Das führt zu instabilem Verhalten: Identische Anfragen landen mal hier, mal dort. Achten Sie darauf, dass jeder Name und jede Beschreibung eine eindeutige „Nische“ im semantischen Raum belegt.
Fehler Nr. 3: Schlechte oder fehlende Beschreibungen und Schemafelder.
Der Name func1, die Beschreibung „Does something“ und ein Parameter data: string — das ist der Klassiker, um einen Agenten „dumm“ zu machen. Das Modell ist nicht telepathisch und kann Ihren Quellcode nicht lesen. Es stützt sich auf description, properties und deren description im Schema. Wenn Sie nicht erklären, was recipient_type ist, muss das Modell raten — und irrt sich.
Fehler Nr. 4: Fokus nur auf den Happy Path, Fehler ignorieren.
Viele Tool‑Implementierungen unterstellen: „Es werden immer korrekte Argumente kommen und der Dienst ist verfügbar.“ In der Realität generiert das Modell leicht falsche Parameter, externe Dienste fallen aus, und die Datenbank sagt bisweilen „Timeout“. Wenn Sie Fehlerformate nicht durchdenken und dem Agenten keine sinnvolle Meldung zurückgeben, kann er sein Verhalten nicht anpassen — er stürzt still ab oder halluziniert.
Fehler Nr. 5: Rohe 500er und Stacktrace an das LLM durchreichen.
Im REST‑API sind wir es gewohnt, vollständige Stacktraces zu loggen, um schneller zu debuggen. Im Agenten‑Kontext ist ein an das Modell gegebener Stacktrace zugleich nutzlos (das Modell kennt Ihr spezifisches SQLException nicht) und potenziell gefährlich (Implementation‑Details, evtl. vertrauliche Infos). Sinnvoller ist es, die Exception abzufangen, Details zu loggen und dem Modell einen sauberen code und eine message zu senden.
Fehler Nr. 6: Fehlende Idempotenz bei mutierenden Tools.
Ein create_order ohne idempotency‑key ist eine Einladung zu Doppelbestellungen — besonders bei Netzwerkausfällen und automatischen Retries. In kommerziellen Szenarien müssen Tools rund ums Geld so gestaltet sein, dass Wiederholungen nicht zu zusätzlichen Abbuchungen oder Duplikaten führen.
Fehler Nr. 7: Geheimnisse und technische Details im Schema oder in der Beschreibung ablegen.
Mitunter schreibt ein Entwickler aus Gewohnheit in die description: „Ruft intern Dienst X unter https://internal-api.example.com auf“. Diese Information braucht das Modell nicht, der Nutzer schon gar nicht. Schemata und Beschreibungen sind Teil des Prompts, sie leben im Modellkontext — dort haben interne URLs, Namen privater Tabellen und erst recht Geheimnisse nichts zu suchen.
Fehler Nr. 8: Alles Mögliche in Tools kippen statt eines durchdachten Feldsatzes.
Die Versuchung ist groß: „Wir geben einfach den gesamten Prompt‑Text des Nutzers als String rein, innen wird das schon geparst.“ So verspielen Sie den Vorteil der Strukturierung via JSON Schema: Das Modell versteht nicht mehr, welche Teile der Anfrage für die Logik wichtig sind; Sie verlieren Validierung und Vorhersagbarkeit. Besser die relevanten Felder aus der Anfrage extrahieren (budget, interests, user_location) und als Teil des Tool‑Vertrags beschreiben.
GO TO FULL VERSION