Function Calling erklärt: Tools anbinden, Aufrufe prüfen
Wie Function Calling LLMs mit Tools verbindet: mit vollständigem Python-Beispiel, Schema und Validierung. OpenAI, Anthropic und Gemini im Vergleich.
Veröffentlicht am

Mit Function Calling kann ein großes Sprachmodell (LLM) die Software auffordern, eine Aufgabe auszuführen. Entscheidend ist dabei eine klare Trennung in 3 Schritten: Das Modell schlägt einen strukturierten Aufruf vor, der Anwendungscode prüft ihn und führt ihn aus, anschließend geht das Ergebnis zurück an das Modell. Eine Datenbank anzubinden bedeutet, diesen Ablauf umzusetzen – dem Modell ein Datenbankpasswort zu geben, gehört nicht dazu.
Wie funktioniert Function Calling?
Das Modell formuliert eine Anfrage. Die Anwendung führt die Operation aus. Wer ein LLM mit einer API oder Datenbank verbindet, sollte diese Trennung verstehen, bevor der erste Code entsteht.
Ein Bestellbon im Restaurant macht das Prinzip anschaulich: Die Bedienung kann ein Gericht bestellen, doch der Bon kocht nichts. Die Küche prüft die Bestellung, bereitet das Machbare zu und gibt Rückmeldung. In einer Anwendung entspricht der Tool-Aufruf dem Bon und die Funktion der Küche.
Das Modell erhält ein Tool-Schema: eine Beschreibung der verfügbaren Operation und der Eingabefelder, die sie akzeptiert. Als Antwort kann es den Funktionsnamen und Argumente liefern, also die Werte für diese Felder. Die Anwendung prüft die Anfrage, ruft die Funktion auf und übermittelt deren Ausgabe zurück. Damit kann das Modell antworten oder eine weitere Operation anfordern. Googles Leitfaden zu Function Calling weist die Ausführung ausdrücklich der Anwendung zu.
Tools können sowohl lesen als auch schreiben. Einen Bestellstatus abzufragen, eine Dokumentensammlung zu durchsuchen oder die Verfügbarkeit zu prüfen, sind auch dann Tool-Operationen, wenn sie nichts verändern. Für die erste Integration eignet sich eine eng begrenzte Abfrage: Der gesamte Ablauf lässt sich nachvollziehen, ohne eine Transaktion einzuführen, die sich gegebenenfalls rückgängig machen lassen muss.

Function Calling und Tool Calling: Was ist der Unterschied?
Bei selbst definierten Funktionen bezeichnen beide Begriffe häufig denselben Mechanismus. OpenAI verwendet beide Namen. Auch Anthropic erklärt, dass Tool Use ebenfalls als Function Calling bezeichnet wird. Der weiter gefasste Begriff „Tool“ kann neben selbst implementierten Funktionen auch Fähigkeiten umfassen, die beim Anbieter laufen. Wichtiger als die Bezeichnung ist der Ausführungsort: Für eine eigene Datenbankfunktion ist die Anwendung zuständig.
Die Dokumentation der drei Anbieter weiter unten macht den Unterschied greifbar. Ihre Nachrichtenformate unterscheiden sich. Anfrage und Ergebnis müssen deshalb jeweils im Format desselben Anbieters bleiben.
Function Calling in der Praxis: ein vollständiges Minimalbeispiel
Eine Funktion fragt den Bestellstatus ab und liefert ausschließlich den Status zurück, der in der Datenbank steht. Das folgende Beispiel verwendet die bewusst erfundene Bestellung ORD-1042 in einer lokalen SQLite-Datenbank. Es handelt sich um Beispieldaten zu Lernzwecken, weder um einen Kundendatensatz noch um eine tatsächlich beobachtete Modellantwort.
OpenAI Function Calling: vom Aufruf bis zum Ergebnis
Die Dokumentation zu Function Calling von OpenAI beschreibt den vollständigen Ablauf mit der Responses API: Die Anwendung deklariert die Funktion, empfängt einen function_call, führt den eigenen Code aus und gibt einen function_call_output mit derselben call_id zurück.
Zur Vorbereitung das Python-SDK mit python -m pip install openai installieren, OPENAI_API_KEY als Umgebungsvariable setzen und den folgenden Code als order_tool.py speichern. Das Beispiel verwendet gpt-6-astra, das Modell aus dem Responses-Beispiel der aktuellen Dokumentation. Damit ist nicht gemeint, dass nur dieses Modell geeignet wäre. Beim Ausführen sendet das Skript echte API-Anfragen; die Datenbank bleibt im Arbeitsspeicher.
import json
import re
import sqlite3
from openai import OpenAI
client = OpenAI()
model = "gpt-6-astra"
# Demo identity. In a web app, obtain this from your authenticated session.
tenant_id = "tenant_demo"
db = sqlite3.connect(":memory:")
db.execute("CREATE TABLE orders (tenant_id TEXT, order_id TEXT, status TEXT)")
db.execute(
"INSERT INTO orders VALUES (?, ?, ?)",
(tenant_id, "ORD-1042", "shipped"),
)
# The tool schema: a name, a purpose, and an input contract.
tool = {
"type": "function",
"name": "get_order_status",
"description": (
"Look up the current status of an existing order by order ID. "
"Use for status questions, not refunds or address changes. "
"Returns the order ID and status, or an error."
),
"strict": True,
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "The order ID supplied by the user, such as ORD-1042.",
}
},
"required": ["order_id"],
"additionalProperties": False,
},
}
def execute(name, raw_arguments):
if name != "get_order_status":
return {"error": "unknown_tool"}
try:
args = json.loads(raw_arguments)
except (json.JSONDecodeError, TypeError):
return {"error": "invalid_arguments"}
if not isinstance(args, dict) or set(args) != {"order_id"}:
return {"error": "invalid_arguments"}
order_id = args["order_id"]
if not isinstance(order_id, str) or not re.fullmatch(r"ORD-[0-9]+", order_id):
return {"error": "invalid_order_id"}
row = db.execute(
"SELECT status FROM orders WHERE tenant_id = ? AND order_id = ?",
(tenant_id, order_id),
).fetchone()
if row is None:
return {"error": "order_not_found"}
return {"order_id": order_id, "status": row[0]}
history = [{"role": "user", "content": "What is the status of order ORD-1042?"}]
response = client.responses.create(
model=model,
input=history,
tools=[tool],
tool_choice={"type": "function", "name": "get_order_status"},
parallel_tool_calls=False,
)
# Keep every output item, including any reasoning items.
history.extend(response.output)
calls = [item for item in response.output if item.type == "function_call"]
if len(calls) != 1:
raise RuntimeError("Expected one tool call; inspect the response before continuing.")
call = calls[0]
result = execute(call.name, call.arguments)
history.append({
"type": "function_call_output",
"call_id": call.call_id,
"output": json.dumps(result),
})
answer = client.responses.create(
model=model,
input=history,
tools=[tool],
tool_choice="none",
instructions="Answer from the tool result. If it contains an error, report the failure.",
)
print(answer.output_text)
db.close()Im Erfolgsfall durchläuft dieses bewusst begrenzte Beispiel 2 Modellanfragen und 1 Datenbankabfrage. Die erste Anfrage erzwingt die vorgegebene Abfrage, bei der zweiten sind weitere Tool-Aufrufe deaktiviert. So wird der Ablauf sichtbar. Ein allgemeiner Assistent müsste zusätzlich mit Anfragen umgehen können, für die kein Tool passt, Informationen fehlen oder eine weitere Abfrage nötig ist.
Die tenant_id fehlt im Tool-Schema, weil die Anwendung bereits weiß, wer angemeldet ist. Die Datenbankabfrage verwendet diese vertrauenswürdige Identität zusammen mit der angeforderten Bestell-ID. Würde das Modell die Identität als Argument liefern, ginge genau die Trennung verloren, die das Beispiel vermitteln soll.
Was das Modell anfordert und was die Anwendung zurückgibt
Anfrage und Ergebnis sind getrennte Nachrichten, die über eine Aufruf-ID zusammengehören. Ein typischer Aufruf könnte so aussehen. Kennungen und Werte dienen der Veranschaulichung; dies ist keine aufgezeichnete API-Antwort.
{
"type": "function_call",
"id": "fc_demo",
"call_id": "call_demo",
"name": "get_order_status",
"arguments": "{\"order_id\":\"ORD-1042\"}"
}Sobald die Verarbeitungsfunktion den Status aus den Beispieldaten geliefert hat, hängt die Anwendung dieses Ergebnis an den Verlauf an. Bei einer echten Antwort muss die tatsächliche call.call_id übernommen werden; eine neue Kennung darf nicht erfunden werden.
{
"type": "function_call_output",
"call_id": "call_demo",
"output": "{\"order_id\":\"ORD-1042\",\"status\":\"shipped\"}"
}Damit hat das Modell eine Grundlage für eine Antwort wie „Bestellung ORD-1042 wurde versandt.“ Der Status stammt aus der Datenbank. Das Modell hat die Anfrage in Argumente übersetzt und die zurückgegebenen Daten anschließend als Antwort formuliert.
Dasselbe Prinzip in der Dokumentation der drei Anbieter
Das Ausführungsprinzip lässt sich auf andere Anbieter übertragen; das Nachrichtenformat nicht. Die folgende Zuordnung wurde am 17. Oktober 2026 anhand der öffentlich verfügbaren Anbieterdokumentation geprüft. Sie unterscheidet die aktuellen Beispiele, statt ähnlich benannte Felder als austauschbar zu behandeln.
Wie Anthropic Tool Use umsetzt
Anthropics Dokumentation zu Tool Use definiert die Funktionseingaben über input_schema. Bei einem clientseitigen Tool verarbeitet der Anwendungscode den tool_use-Block des Assistenten und sendet einen tool_result in der nächsten Nutzernachricht zurück. Die Assistentennachricht bleibt dabei im Gesprächsverlauf erhalten.
Die Dokumentation zieht hier eine klare Grenze: Clientseitige Tools laufen in der Anwendung, serverseitige Tools auf Anthropics Infrastruktur. Ein gehostetes Suchtool belegt daher nicht, dass Claude eine private Datenbankfunktion direkt ausführen kann. Diese Implementierung muss weiterhin die Anwendung bereitstellen.
Wie Gemini Function Calling umsetzt
Auch Googles Dokumentation zu Gemini Function Calling trennt die Anfrage des Modells von der Ausführung durch die Anwendung. Der aktuelle Leitfaden verwendet die Interactions API mit den Schritten function_call und function_result sowie previous_interaction_id, um die Interaktion fortzusetzen.
Maßgeblich ist das Beispiel für die tatsächlich verwendete API. Eine Deklaration aus einer API und eine Ergebnisnachricht aus einer anderen zusammenzukopieren, schafft keine Portabilität. Die gemeinsame Operation, etwa get_order_status, kann erhalten bleiben. Ihre Deklaration und das zugehörige Ergebnisformat müssen gemeinsam angepasst werden.
Warum Tool-Aufrufe die Arbeitsschleife eines Agenten bilden
Ein Agent mit Tools entscheidet wiederholt, was zu tun ist, empfängt das Ergebnis und bestimmt den nächsten Schritt. Function Calling übernimmt die Übergabe zwischen dieser Entscheidung und einer Operation, die die Software ausführen kann.
Ein Bestellassistent könnte etwa eine Sendung abfragen, die zurückgegebene Referenz des Versanddienstleisters auswerten und anschließend Trackinginformationen anfordern, bevor er antwortet. Die zweite Operation hängt vom ersten Ergebnis ab. Diese Rückkopplung ist hilfreicher, als das Modell alle Schritte im Voraus erfinden zu lassen.
Anthropics Leitfaden zur Agentenarchitektur unterscheidet feste Workflows von Agenten, die ihren Tool-Einsatz selbst steuern. Er beschreibt außerdem Rückmeldungen der Tools und Abbruchbedingungen als Bestandteile dieser Schleife.
Die Bezeichnung „Grundlage jedes Agenten“ taugt deshalb nur bedingt als Kurzform. Aus der Dokumentation folgt nicht, dass jedes als Agent bezeichnete System eine bestimmte Function-Calling-API nutzt. Entscheidend ist die Schleife aus Modellentscheidung und Aktion. Eine einzelne Abfrage kann ein fester Workflow bleiben; dafür braucht es keinen autonomen Planer.
Drei typische Fehler im Produktivbetrieb
Schemaqualität, Tool-Auswahl und Argumentprüfung sind getrennte Probleme. Wer eines behebt, hat damit die anderen noch nicht gelöst.
Unklare Schemas: formal richtig, inhaltlich missverständlich
Ein Feld namens id verrät dem Modell nicht, ob eine Bestellnummer, eine Kundenkennung oder eine Sendungsreferenz gemeint ist. Eine beliebige Zeichenfolge namens action lädt zu Werten ein, die die Verarbeitungsfunktion möglicherweise nicht kennt. Bevor zusätzliche Anweisungen hinzukommen, sollte die Schnittstellenbeschreibung präziser werden.
Parameter brauchen eindeutige Namen und eine Beschreibung ihrer Bedeutung. Ist nur eine feste Auswahl von Werten zulässig, eignet sich ein Enum. Das erste Tool sollte so eng zugeschnitten sein, dass sein Zweck in einen einfachen Satz passt. Im Beispiel ist order_id eindeutig; die Beschreibung schließt Erstattungen und Adressänderungen aus.
OpenAIs strikter Modus verlangt bei Objekten additionalProperties: false; außerdem müssen sämtliche Eigenschaften in required stehen. Für einen Wert, der fehlen darf, lässt sich null zulassen. Der Leitfaden dokumentiert diese Anforderungen des strikten Modus. Auch Google nennt Einschränkungen für Schemas. Was ein lokaler Validator akzeptiert, wird deshalb nicht automatisch von jeder Modell-API angenommen.
Die Grenze: Ein Schema kann die Darstellungsform einschränken. Eine gültige Bestell-ID kann trotzdem auf die falsche Bestellung verweisen. Das muss die Anwendung prüfen.
Das Modell wählt das falsche Tool: gültige Argumente, falsche Aktion
Auf die Kundenfrage „Wo bleibt meine Erstattung?“ muss eine Statusabfrage folgen, keine neue Erstattung. Wenn beide Tools nur mit „bearbeitet Erstattungen“ beschrieben sind, bleibt die Auswahl mehrdeutig.
Die Beschreibung sollte erklären, wann ein Tool eingesetzt werden soll und wann nicht. Verfügbar sein sollten nur Operationen, die zur aktuellen Aufgabe und zum jeweiligen Nutzer passen. Anthropics Leitfaden zur Tool-Definition empfiehlt ausdrücklich, Zweck, Parameterbedeutung, Einsatzgrenzen und Einschränkungen zu erläutern.
Steht in der Anwendung bereits fest, welche Operation nötig ist, lässt sich die Auswahl über eine unterstützte Einstellung zur Tool-Auswahl vorgeben oder die Operation direkt aufrufen. Das Beispiel erzwingt die bekannte Abfrage zur Veranschaulichung. Daraus folgt nicht, dass jede Nutzernachricht ein Tool auslösen muss. Bei einer Begrüßung oder einer unvollständigen Frage zu einer Bestellung kann eine normale Gesprächsantwort angemessener sein.
Die Grenze: Formal korrekte Argumente sagen nichts darüber aus, ob das Modell die richtige geschäftliche Aktion gewählt hat. Die Tool-Auswahl muss anhand repräsentativer Nutzeranfragen geprüft werden – auch anhand solcher, bei denen kein Aufruf stattfinden sollte.
Ungeprüfte Argumente: korrektes Format, unzulässiger Zugriff
Die Verarbeitungsfunktion bildet eine Eingabegrenze. Sie muss den Funktionsnamen mit einer ausdrücklichen Positivliste abgleichen, die Argumente parsen, ihre Struktur und Bedeutung prüfen und Zugriffe anhand der authentifizierten Identität aus der Anwendung durchsetzen.
Für das Bestellbeispiel ist eine Bestellung eines anderen Mandanten, also eines anderen Kundenkontos, ein sinnvoller Negativtest. Die Abfrage darf sie auch dann nicht zurückgeben, wenn ihre Kennung eine vollkommen gültige Zeichenfolge ist. Weitere Testfälle sind eine fehlende Bestell-ID, ein unerwartetes Feld und die Anforderung einer Operation, die die Verarbeitungsfunktion nicht implementiert.
Anthropics Übersicht weist darauf hin, dass ein Modell bei fehlenden Informationen Argumentwerte herleiten kann. Ein Pflichtfeld beweist also nicht, dass der Nutzer den Wert angegeben hat. Bei einer folgenreichen Aktion müssen die angeforderte Operation und ihre Eingaben mit dem abgeglichen werden, was der Nutzer tatsächlich autorisiert hat.
Scheitert die Ausführung, muss ein erkennbarer Fehler zurückgegeben werden. Ein Timeout beweist nicht, dass die Operation nie stattgefunden hat. Vor dem Wiederholen eines Schreibzugriffs braucht es deshalb einen Idempotenzmechanismus auf Anwendungsebene: Er erkennt dieselbe beabsichtigte Operation und verhindert, dass ihre Wirkung mehrfach eintritt. Das sind Empfehlungen für die Implementierung, keine Garantien der Modell-API.
Wann reichen Structured Outputs aus?
Structured Outputs eignen sich für eine Antwort in einem vorgegebenen Format auf Basis bereits verfügbarer Informationen. Ein Tool wird benötigt, wenn eine externe Operation nötig ist. Ein Klassifikator für Supportnachrichten kann Kategorie und Dringlichkeit als strukturierte Ausgabe liefern. Ein Assistent, der den aktuellen Bestellstatus benötigt, muss diesen Zustand dagegen erst abfragen.
OpenAIs Leitfaden zu Structured Outputs unterscheidet entsprechend zwischen dem Anbinden von Anwendungsfunktionen und dem Formatieren der Modellantwort. Er erklärt außerdem, dass strikte Funktionsschemas intern auf Structured Outputs zurückgreifen. Die Fähigkeiten ergänzen einander; sie sind keine Produkte, die sich gegenseitig ausschließen.

Liegt der Bestelldatensatz bereits vor und benötigt die Oberfläche nur noch {order_id, status, explanation}, genügt eine strukturierte Antwort. Fehlt der Datensatz oder muss er aktualisiert werden, kommt zuerst die Abfrage. Auch danach lässt sich die endgültige Antwort strukturiert ausgeben.
Ein JSON-Objekt mit der Aussage, eine E-Mail sei versandt worden, bleibt zunächst ein Ausgabeobjekt. Zum tatsächlichen Versand gehören eine ausgeführte Operation und ein überprüfbares Ergebnis.
Function Calling und MCP: Wie hängen sie zusammen?
Function Calling vermittelt die Operationsanfrage des Modells. Das Model Context Protocol (MCP) stellt eine gemeinsame Schnittstelle bereit, über die Tools und weiterer Kontext kompatiblen Anwendungen zugänglich werden. Eine Funktion lässt sich direkt in eine Anwendung einbinden, bevor ein separater Tool-Server hinzukommt.
MCP und Tool Calling: Wann lohnt sich die gemeinsame Nutzung?
Benötigen mehrere Anwendungen dieselbe Bestellabfrage, kann ein MCP-Server das Tool zum Auffinden und Aufrufen bereitstellen. Die MCP-Architekturdokumentation beschreibt dafür tools/list zum Auffinden und tools/call für Ausführungsanfragen. Der Server braucht weiterhin eine Implementierung und Zugriffsprüfungen.
Für den nächsten Schritt lohnt sich der Überblick: Was ist MCP, und wie spielen Host, Client und Server zusammen?. Sobald die direkte Abfrage funktioniert, zeigt der Leitfaden zur Implementierung eines MCP-Servers, wie sich Funktionen zur Wiederverwendung bereitstellen lassen. Auch mit MCP muss jede angeforderte Operation geprüft werden.
Was die Versprechen nicht abdecken
Eine erfolgreiche Schemaprüfung bestätigt eine Formatvorgabe, keine erledigte Aufgabe. Die Operation kann ungeeignet, der Datensatz unzugänglich oder der zugrunde liegende Dienst nicht verfügbar sein. Ein flüssig formulierter Antwortsatz klärt keine dieser Fragen.
Ebenso wenig macht eine Tool-Liste allein schon einen Agenten aus. Es braucht weiterhin Regeln dafür, welche Tools verfügbar sind, wie Ergebnisse in den Gesprächsverlauf gelangen, wann Schluss ist und was nach einem Fehler passiert. Ein Framework kann diese Arbeit bündeln; die Regeln für die Ausführung bleiben eine Entwurfsentscheidung.
Das erste sinnvolle Etappenziel ist überschaubar: Eine Anfrage erreicht die vorgesehene Verarbeitungsfunktion, nur erlaubte Daten kommen zurück, und die Antwort gibt dieses Ergebnis korrekt wieder. Dieser Ablauf sollte nachvollziehbar sein, bevor das System weiter reichende Befugnisse erhält.
Womit die erste Umsetzung beginnen sollte
Am Anfang steht eine rein lesende Operation, die eine wiederkehrende Nutzerfrage beantwortet. Das Bestellstatusbeispiel eignet sich als Muster, weil sich das erwartete Ergebnis und die Zugriffsgrenze leicht prüfen lassen.
Für Entwicklungsteams lohnt sich die Umsetzung, wenn die Antwort von Daten abhängt, die die Anwendung zuverlässig abrufen kann. Steht die nächste Operation bereits fest, genügt weiterhin ein fester Workflow. Vom Modell ausgewählte Schreibzugriffe sollten erst hinzukommen, wenn ausdrückliche Berechtigungen, Fehlerbehandlung und ein Schutz gegen wiederholte Auswirkungen vorhanden sind.
Für Betriebsteams zählt, was ausgeführt wurde und was zurückkam. Zu protokollieren sind das gewählte Tool, das Validierungsergebnis, der Ausführungsstatus und die Zuordnung zum jeweiligen Aufruf. Sensible Argumente gehören nicht in gewöhnliche Protokolle. Timeouts und eine zur Aufgabe passende Höchstzahl an Tool-Runden setzen der Gesprächsschleife die nötigen Grenzen.
Einkaufsverantwortliche sollten sich vom Implementierungsteam neben einer erfolgreichen Antwort auch eine verweigerte Abfrage und eine fehlgeschlagene Operation zeigen lassen. Fasst das Produkt lediglich bereits bereitgestellte Informationen zusammen, ist Function Calling möglicherweise unnötig. Eine strukturierte Ausgabe oder gewöhnliche Textgenerierung kann ausreichen.
Der konkrete Schritt für Montag: eine eng begrenzte Abfrage implementieren, sie mit einem erlaubten Datensatz, einem nicht zugänglichen Datensatz und einer unvollständigen Anfrage ausprobieren und jeweils das an das Modell zurückgegebene Ergebnis prüfen. Die Tool-Liste sollte erst wachsen, wenn sich für jede Anfrage erklären lässt, warum sie angenommen oder abgelehnt wurde.
Häufige Fragen
Was ist Function Calling?
Function Calling ist ein Mechanismus, mit dem ein Modell eine Operation anfordert, indem es eine Funktion benennt und Argumente übergibt. Bei einer selbst definierten Funktion übernimmt die Anwendung die Ausführung und führt das Ergebnis in den Gesprächsverlauf zurück.
Was unterscheidet Tool Calling bei LLMs von Function Calling?
Bei selbst definierten Funktionen verwenden die Anbieter die Begriffe häufig synonym. Tool-Nutzung kann auch Fähigkeiten umfassen, die beim Anbieter laufen. Entscheidend ist deshalb, wo die Ausführung stattfindet; die Bezeichnung allein legt das nicht fest.
Wie sieht ein Beispiel für einen Funktionsaufruf aus?
Ein Modell fordert get_order_status an und setzt order_id auf ORD-1042. Der Anwendungscode validiert die Anfrage, prüft den Zugriff, fragt die Bestellung ab und gibt ihren Status zurück. Bestellung und Status in diesem Artikel sind erfundene Beispieldaten.
Wie lässt sich Function Calling mit GPT-5 nutzen?
Dafür dient der dokumentierte Responses-Ablauf mit einem geeigneten Modell, das im jeweiligen Projekt verfügbar ist: Tool-Definitionen senden, Ausgabeelemente für Funktionsaufrufe verarbeiten und Ergebnisse mit den passenden Aufruf-IDs zurückgeben. Beim Fortsetzen des Gesprächs müssen Reasoning-Elemente erhalten bleiben. Das ausführbare Beispiel oben verwendet das Modell aus dem aktuellen Leitfaden, statt vorauszusetzen, dass im jeweiligen Konto ein bestimmtes GPT-5-Modell freigeschaltet ist.
Praktische Anleitungen zur Entwicklung mit KI gibt es im Newsletter.
- Veröffentlicht
- Kategorie
- Build
- Sprache










