Funktionsaufrufe (auch als Tool-Aufrufe oder Tool-Nutzung bezeichnet) ermöglichen es Ihnen, einem Modell Zugriff auf Ihren Code zu geben. Sie beschreiben Funktionen wie „eine Bestellung nachschlagen“ oder „Versandkosten berechnen“. Das Modell entscheidet, welche Funktion mit welchen Argumenten aufgerufen werden soll; Ihr Code führt sie aus und sendet das Ergebnis zurück. Jeder Agent, von einem Support-Bot für einen Onlineshop bis zu Claude Code, basiert auf dieser Schleife.
Auf der GetVibe API funktionieren Funktionsaufrufe über den standardmäßigen Endpunkt /v1/chat/completions im OpenAI-Format sowie über /v1/messages im Anthropic-Format. Im Folgenden sehen Sie eine vollständige Schleife, die wir mit drei Modellen von drei verschiedenen Anbietern ausgeführt haben.
So funktioniert die Schleife
- Sie senden Nachrichten zusammen mit einer Liste von
tools. Jedes Tool verfügt über einen Namen, eine Beschreibung und ein JSON Schema für seine Parameter. - Statt Text gibt das Modell
tool_callszurück: welche Funktion mit welchen Argumenten aufgerufen werden soll.finish_reasonisttool_calls. - Ihr Code führt die Funktionen aus und fügt pro Aufruf eine Nachricht mit der Rolle
toolhinzu, die dieselbetool_call_identhält. - Sie senden den Verlauf erneut. Das Modell fordert entweder weitere Aufrufe an oder antwortet dem Benutzer in Textform.
Das Modell führt selbst nichts aus. Es fordert lediglich einen Aufruf an. Was tatsächlich ausgeführt wird und mit welchen Berechtigungen, entscheidet Ihr Code.
Ein vollständiges Beispiel: ein Support-Assistent für einen Onlineshop
Zwei Funktionen: Bestellstatus und ein Versandkostenangebot. Der Benutzer fragt gleichzeitig nach beidem, und das Modell ruft beide Funktionen in einem einzigen Durchgang auf.
import json
import os
from openai import OpenAI
client = OpenAI(base_url="https://getvibeapi.com/v1", api_key=os.environ["GETVIBE_API_KEY"])
MODEL = "gpt-6-luna"
def get_order_status(order_id: str) -> dict:
# Ihre Datenbank- oder CRM-Abfrage kommt hierhin
return {"order_id": order_id, "status": "out for delivery", "eta": "2026-10-24"}
def get_shipping_quote(zip_code: str) -> dict:
return {"zip_code": zip_code, "price_usd": 7.5, "days": 2}
TOOLS = [
{"type": "function", "function": {
"name": "get_order_status",
"description": "Look up an order by its ID",
"parameters": {"type": "object",
"properties": {"order_id": {"type": "string", "description": "Order ID, e.g. A-1042"}},
"required": ["order_id"]}}},
{"type": "function", "function": {
"name": "get_shipping_quote",
"description": "Courier shipping price and delivery time to a US ZIP code",
"parameters": {"type": "object",
"properties": {"zip_code": {"type": "string"}},
"required": ["zip_code"]}}},
]
FUNCTIONS = {"get_order_status": get_order_status, "get_shipping_quote": get_shipping_quote}
messages = [
{"role": "system", "content": "Sie sind ein Support-Assistent für einen Onlineshop. Fassen Sie sich kurz."},
{"role": "user", "content": "Wo ist meine Bestellung A-1042? Und wie viel kostet der Versand nach 94110?"},
]
for _ in range(5): # die Anzahl der Durchläufe begrenzen
resp = client.chat.completions.create(model=MODEL, messages=messages, tools=TOOLS)
msg = resp.choices[0].message
if not msg.tool_calls:
print(msg.content)
break
messages.append(msg.model_dump(exclude_none=True))
for call in msg.tool_calls:
args = json.loads(call.function.arguments)
result = FUNCTIONS[call.function.name](**args)
messages.append({"role": "tool", "tool_call_id": call.id, "content": json.dumps(result)})
Wir haben diesen Code unverändert mit gpt-6-luna, deepseek-v4.1-flash und claude-haiku-5.5 ausgeführt und lediglich MODEL geändert. Im ersten Durchlauf riefen alle drei Modelle beide Funktionen auf: get_order_status mit A-1042 und get_shipping_quote mit 94110. Im zweiten Durchlauf antworteten alle drei in Textform mit dem Lieferstatus, der voraussichtlichen Lieferzeit, dem Preis von 7.50 und der Lieferzeit von zwei Tagen.
Worauf es in diesem Code ankommt
- Fügen Sie die Tool-Aufrufnachricht des Modells vollständig zum Verlauf hinzu. Andernfalls beantwortet Ihre
tool-Nachricht einen Aufruf, den das Modell nicht sehen kann. Viele Modelle rufen dann einfach dieselbe Funktion erneut auf, sodass die Schleife sich im Kreis dreht. - Eine
tool-Nachricht pro Aufruf mit der passendentool_call_id. Das Modell kann mehrere Aufrufe gleichzeitig anfordern, wie in diesem Beispiel. - Argumente kommen als String an.
argumentsist JSON innerhalb eines Strings. Parsen und validieren Sie den Inhalt, da das Modell einen Wert falsch bestimmen kann. - Begrenzen Sie die Anzahl der Durchläufe. Ohne Limit kann ein Fehler in einer Funktion die Schleife endlos laufen lassen – und eine endlose Token-Rechnung verursachen.
tool_choice: wenn ein Aufruf verpflichtend ist
Standardmäßig entscheidet das Modell, ob es ein Tool aufruft oder in Textform antwortet ("auto"). tool_choice ändert dieses Verhalten:
"none"— niemals Tools aufrufen;"required"— mindestens ein Tool aufrufen;{"type": "function", "function": {"name": "..."}}— diese spezifische Funktion aufrufen.
Die letzte Form ist für die Datenextraktion nützlich. Das Parameterschema der Funktion legt die Struktur der Antwort fest:
curl https://getvibeapi.com/v1/chat/completions \
-H "Authorization: Bearer $GETVIBE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-v4.1-flash",
"messages": [{"role": "user", "content": "Jane Doe, [email protected], möchte am Donnerstag eine Demo"}],
"tools": [{
"type": "function",
"function": {
"name": "save_lead",
"description": "Save a sales lead to the CRM",
"parameters": {
"type": "object",
"properties": {"name": {"type": "string"}, "email": {"type": "string"}, "request": {"type": "string"}},
"required": ["name", "email", "request"]
}
}
}],
"tool_choice": {"type": "function", "function": {"name": "save_lead"}}
}'
Die Antwort bestand aus einem Aufruf von save_lead mit name „Jane Doe“, email „[email protected]“ und request „Möchte am Donnerstag eine Demo“.
Ein wichtiger Hinweis: Einige Claude-Modelle, darunter Claude Sonnet 5.5 und Claude Opus 5.5, akzeptieren keine erzwungene Tool-Auswahl. GetVibe wandelt eine solche Anfrage in auto mit denselben Tools um. Sie erhalten dadurch statt eines Fehlers eine Antwort, aber das Modell entscheidet dann selbst, ob es einen Aufruf tätigt. Für striktes JSON mit diesen Modellen verwenden Sie strukturierte Ausgaben.
Das Anthropic-Format: /v1/messages
Mit dem Anthropic SDK sehen Tools etwas anders aus: Das Parameterschema wird in input_schema angegeben, und der Aufruf wird als tool_use-Inhaltsblock zurückgegeben.
curl https://getvibeapi.com/v1/messages \
-H "x-api-key: $GETVIBE_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-haiku-5.5",
"max_tokens": 512,
"tools": [{
"name": "get_order_status",
"description": "Look up an order by its ID",
"input_schema": {"type": "object", "properties": {"order_id": {"type": "string"}}, "required": ["order_id"]}
}],
"messages": [{"role": "user", "content": "Wo ist die Bestellung A-1042?"}]
}'
Die Antwort enthielt stop_reason tool_use sowie einen tool_use-Block, der get_order_status mit order_id A-1042 aufrief. Sie senden das Ergebnis in der nächsten Benutzernachricht als tool_result-Block zurück, mit derselben tool_use_id.
Welches Modell Sie für Tools verwenden sollten
- Bots mit hohem Volumen und einfache Tools — DeepSeek V4.1 Flash ($0.0112 Eingabe · $0.0445 Ausgabe pro 1 Mio. Tokens) oder Claude Haiku 5.5 ($0.0267 Eingabe · $0.1334 Ausgabe pro 1 Mio. Tokens).
- Agenten mit vielen Tools und langen Plänen — GPT-6 Luna ($0.0055 Eingabe · $0.0274 Ausgabe pro 1 Mio. Tokens) oder Claude Sonnet 5.5.
Agentenschleifen senden in jedem Durchlauf dasselbe lange Präfix erneut. Daher ist Prompt-Caching hier besonders wichtig. Weitere Informationen zu den Anfragefeldern finden Sie in der Dokumentation zu Tool-Aufrufen.
