API & SDKAnleitung
Function Calling in Python mit einer OpenAI-kompatiblen API
Sende Tools, lies tool_calls und gib das Ergebnis mit role tool zurück: eine zweistufige Function-Calling-Schleife in Python mit MiniMax-M2.7.

Auf dieser Seite
Function Calling (Tool Calling) ermöglicht es einem Modell, deinen Code aufzufordern, eine Funktion auszuführen. Du sendest eine tools-Liste mit der Anfrage, das Modell antwortet mit tool_calls statt mit Text, du führst die Funktion selbst aus und sendest ihr Ergebnis in einer Nachricht mit role: tool zurück. Das Modell schreibt dann die finale Antwort. Diese Anleitung zeigt die gesamte Schleife in Python gegen den OpenAI-kompatiblen Endpoint https:/ mit MiniMax-M2.7 (id MiniMaxAI/, 180K Kontext, bis zu 8.192 Ausgabe-Tokens pro Antwort).
Tool Calling ist für jedes Modell im Katalog als unterstützt aufgeführt (CheapTokens docs, geprüft am 22. Oktober 2026). Du brauchst einen API-Key; falls du noch keine Anfrage gestellt hast, beginne mit deiner ersten API-Anfrage.
So funktioniert Function Calling#
Das Modell führt nie etwas aus. Es erzeugt nur eine strukturierte Anfrage: "rufe get_weather mit {\"city\": \"Paris\"} auf". Dein Programm erledigt die eigentliche Arbeit und meldet zurück. Daraus ergibt sich eine Schleife aus zwei Anfragen:
- Anfrage 1. Du sendest die User-Nachricht plus die
tools-Liste. Das Modell antwortet entweder mit Text oder gibt einen oder mehreretool_callszurück. - Dein Code. Du parst jeden Aufruf, führst die passende Funktion aus und sammelst das Ergebnis.
- Anfrage 2. Du sendest die gesamte Konversation erneut: die ursprünglichen Nachrichten, die Assistant-Nachricht mit
tool_callsund einerole: tool-Nachricht pro Aufruf. Das Modell nutzt die Ergebnisse, um die finale Antwort zu schreiben.
Jede Anfrage sendet den gesamten Verlauf erneut, daher verbrauchen Tool-Schleifen mehr Input-Tokens als eine einzelne Frage. Falls das neu für dich ist, lies was ein Token ist.
Client einrichten#
Installiere das OpenAI SDK (pip install openai) und lege deinen Key in einer Umgebungsvariable statt im Quellcode ab:
export CHEAPTOKENS_API_KEY="your-key-here"Die Base-URL ist https:/. Nimm die Modell-ID aus der CheapTokens-Dokumentation: verschiedene Anbieter benennen dasselbe Modell unterschiedlich. Diese Anleitung verwendet MiniMaxAI/.
Eine Funktion deklarieren und die erste Anfrage senden#
Eine Funktion wird im tools-Array beschrieben. Jeder Eintrag hat type: function und ein function-Objekt mit einem name, einem description und parameters, geschrieben als JSON Schema. Die Beschreibung ist das, was das Modell liest, um zu entscheiden, wann es die Funktion aufruft, also schreibe sie als kurzen, konkreten Satz.
Unten steht ein vollständiges Skript. Die Wetterfunktion ist ein Stub mit Fake-Daten, damit das Beispiel keine zusätzlichen Dienste benötigt:
import json
import os
from openai import OpenAI
client = OpenAI(
base_url='https://api.cheaptokens.dev/v1',
api_key=os.environ['CHEAPTOKENS_API_KEY'],
)
MODEL = 'MiniMaxAI/MiniMax-M2.7'
def get_weather(city: str) -> dict:
# Stub with fake data: replace with a real lookup
fake = {'Paris': 14, 'Tokyo': 19}
return {'city': city, 'temp_c': fake.get(city, 10)}
FUNCTIONS = {'get_weather': get_weather}
tools = [
{
'type': 'function',
'function': {
'name': 'get_weather',
'description': 'Get the current temperature in Celsius for a city.',
'parameters': {
'type': 'object',
'properties': {
'city': {'type': 'string', 'description': 'City name, for example Paris'},
},
'required': ['city'],
},
},
}
]
messages = [{'role': 'user', 'content': 'What is the weather in Paris right now?'}]
# Step 1: the model decides whether to call a function
first = client.chat.completions.create(model=MODEL, messages=messages, tools=tools)
message = first.choices[0].message
if not message.tool_calls:
print(message.content)
raise SystemExit
# Step 2: run every requested call and send the results back
messages.append(message)
for call in message.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),
})
final = client.chat.completions.create(model=MODEL, messages=messages, tools=tools)
print(final.choices[0].message.content)Drei Details entscheiden, ob die Schleife funktioniert:
call.ist ein JSON-String, kein Dictionary. Parse ihn mitfunction. arguments json.loads.- Jede
role: tool-Nachricht muss dietool_call_iddes Aufrufs tragen, den sie beantwortet, alsocall.id. - Der
contenteiner Tool-Nachricht ist ein String. Verwendejson.dumpsfür strukturierte Ergebnisse.
Was du sehen solltest#
Wenn du die Felder nach der ersten Anfrage ausgibst, sehen sie so aus (die Call-ID unterscheidet sich bei jedem Lauf):
finish_reason: tool_calls
call.id: call_abc123
call.function.name: get_weather
call.function.arguments: {"city": "Paris"}Das Skript gibt dann die finale Antwort aus, einen einfachen Satz wie "It is currently 14 °C in Paris." Der Wortlaut ändert sich von Lauf zu Lauf; die Zahl stammt aus deiner Funktion.
Mehrere Aufrufe und längere Schleifen#
Ein Modell kann mehr als einen Aufruf in einer einzigen Antwort zurückgeben, zum Beispiel wenn du nach dem Wetter in zwei Städten fragst. Deshalb iteriert das Beispiel über message. und beantwortet jeden Aufruf mit seiner eigenen ID. Der Function-Calling-Leitfaden von OpenAI beschreibt dasselbe Verhalten: Mit dem Standard-tool_choice von auto kann das Modell null, eine oder mehrere Funktionen aufrufen (OpenAI docs, geprüft am 22. Oktober 2026; die Seite hat kein Datum der letzten Aktualisierung und beschreibt die neuere Responses-API-Form, während diese Anleitung die Chat-Completions-Form des /-Endpoints verwendet).
Agenten wiederholen die beiden Schritte, bis das Modell aufhört, nach Tools zu fragen. Wickle die Anfragen in eine Schleife und setze immer ein Schrittlimit:
for _ in range(5): # safety limit against endless loops
response = client.chat.completions.create(model=MODEL, messages=messages, tools=tools)
message = response.choices[0].message
if not message.tool_calls:
print(message.content)
break
messages.append(message)
for call in message.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)})Wenn du die Antwort Token für Token erscheinen lassen willst, kombiniere dies mit Streaming in Python.
Warum MiniMax-M2.7 für Tool-Schleifen geeignet ist#
Eine Tool-Schleife sendet viele Anfragen mit wachsendem Verlauf. Für dieses Muster bietet CheapTokens MiniMax-M2.7: 180K Kontext, bis zu 8.192 Ausgabe-Tokens pro Antwort, ein Preis zu jeder Tageszeit ohne Peak-Zeiten und ein Guthaben für alle Modelle. Input und Output zusammengerechnet ist es günstiger als OpenRouters Referenzpreis (CheapTokens Preisvergleich, geprüft am 31. Oktober 2026).
Aktuelle Preise pro 1M Tokens: Input $0.05, Output $0.15. Als Beispiel-Workload (keine Messung) kostet der obige Round Trip mit zwei Anfragen und insgesamt etwa 2.700 Input- und 350 Output-Tokens $0.00019. Die vollständige Preisliste steht auf der Preisseite.
Um ein anderes Modell auszuprobieren, ändere nur die ID; die Liste der IDs steht auf der Modellseite.
Wenn es nicht funktioniert#
message.isttool_ calls None. Das Modell hat mit Text geantwortet. Formuliere die Funktiondescriptionspezifischer und stelle sicher, dass die Frage die Funktion tatsächlich benötigt.json.beiJSONDecodeError arguments. Das Modell hat ungültiges JSON erzeugt. Wicklejson.loadsintry/exceptund sende den Fehlertext als Tool-Ergebnis zurück, damit das Modell es mit korrigierten Argumenten erneut versuchen kann.- Die zweite Anfrage schlägt fehl oder das Modell ignoriert das Ergebnis. Prüfe, dass jeder Aufruf genau eine
role: tool-Nachricht mit passendertool_call_idhat und dass die Assistant-Nachricht mittool_callsdavor im Verlauf steht. KeyErrorinFUNCTIONS[...]. Das Modell hat eine Funktion benannt, die du nicht registriert hast. Gib einen kurzen Fehler-String als Tool-Ergebnis zurück, statt abzustürzen.- Die Antwort ist abgeschnitten. Prüfe
finish_reason: Der Wertlengthbedeutet, dass das Ausgabe-Token-Limit erreicht wurde. Siehe warum eine KI-Antwort mitten im Satz stoppt. - 401 oder Authentifizierungsfehler. Prüfe, dass der Key in
CHEAPTOKENS_steht und die Base-URL mitAPI_ KEY /v1endet.
Nächste Schritte#
Ersetze den Stub durch eine echte Funktion: eine Datenbankabfrage, einen Suchaufruf oder einen Taschenrechner. Füge weitere Einträge zu tools und zu FUNCTIONS hinzu und halte jedes Funktionsergebnis kurz, denn es geht bei jeder folgenden Anfrage wieder in den Verlauf ein. Um einen Key zu erhalten und den ersten Aufruf zu machen, öffne die CheapTokens docs.



