GPT-6 Astra Function Calling ist der Motor von KI-Agenten: Das Modell entscheidet, welches Tool aufgerufen wird und welche Argumente übergeben werden; die Laufzeit führt den Seiteneffekt aus; das Ergebnis fließt zurück ins Modell, das weiter schlussfolgert. Wenn dieser Loop korrekt ist, kann Astra eigenständig APIs abfragen, Datenbanken lesen und benutzerdefinierte Logik ausführen. Wenn er fehlerhaft ist, hängt der Loop, oder Tool-Berechtigungen übersteigen das Gewollte. Was Function Calling ist, erklärt der Protokollvergleich; wie man einen API-Key holt, das API-Tutorial. Dieser Artikel deckt die drei Tool-Muster ab, die aus "es läuft" ein "es ist sicher deploybar" machen.
Schritt 1: Ein Tool-Schema definieren
Ein Tool-Schema ist ein JSON-Objekt, das dem Modell sagt, wie das Tool heißt, was es tut und welche Parameter es erwartet. Beispiel: ein Tool, das eine Wetter-HTTP-API aufruft.
import json
from openai import OpenAI
client = OpenAI()
tools = [
{
"type": "function",
"name": "get_weather",
"description": "Get current weather for a city via HTTP API.",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "City name, e.g. Tokyo, London, Shanghai",
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "Temperature unit. Default celsius.",
},
},
"required": ["city"],
"additionalProperties": False,
},
}
]
Die description sollte beschreiben, was das Tool tut — nicht nur seinen Namen wiederholen. Das Modell liest dieses Feld, um zu entscheiden, ob es das Tool aufrufen soll. Pflichtfelder kommen in required; optionale Felder in properties, aber nicht in required. additionalProperties: false verringert die Wahrscheinlichkeit, dass das Modell unerwartete Schlüssel übergibt. Mehrere Tools kommen in dieselbe Liste; das Modell wählt eines oder mehrere basierend auf dem Gespräch. Wenn das Modell mehrere Tools parallel aufruft, muss der Loop alle Ergebnisse verarbeiten, bevor er weiterläuft.
Schritt 2: Der vollständige Tool-Loop
Das Muster lautet: Request senden → function_call-Einträge in output prüfen → ausführen → Ergebnisse an input anhängen → erneut senden, bis keine neuen function_call-Einträge mehr erscheinen. Der Loop muss ein while True sein. Ein if-Einmal-Loop lässt die Abschlussantwort des Modells nie ankommen.
import json
import requests
from openai import OpenAI
client = OpenAI()
def call_weather_api(city: str, unit: str = "celsius") -> dict:
"""Replace with your real HTTP endpoint."""
url = "https://api.example.com/weather"
r = requests.get(url, params={"city": city, "unit": unit}, timeout=5)
r.raise_for_status()
return r.json() # e.g. {"city": "Tokyo", "temp": 22, "condition": "sunny"}
# Initial request — model may call tools
response = client.responses.create(
model="gpt-6-astra",
input="What is the weather in Tokyo right now?",
tools=tools,
reasoning={"effort": "low"},
)
# Tool loop: keep going until model stops calling tools
while True:
tool_calls = [o for o in response.output if o.type == "function_call"]
if not tool_calls:
break # model is done — final answer is in response.output_text
tool_results = []
for call in tool_calls:
args = json.loads(call.arguments)
if call.name == "get_weather":
result = call_weather_api(**args)
else:
result = {"error": f"Unknown tool: {call.name}"}
tool_results.append({
"type": "function_call_output",
"call_id": call.call_id,
"output": json.dumps(result, ensure_ascii=False),
})
# Append history + results and continue
response = client.responses.create(
model="gpt-6-astra",
input=response.output + tool_results,
tools=tools,
reasoning={"effort": "low"},
)
print(response.output_text)
Wichtige Implementierungsdetails. Erstens enthält response.output eine Liste mit gemischten Typen; nur type == "function_call" filtern. Zweitens beim Fortfahren response.output + tool_results als input übergeben; nur tool_results zu senden, verliert den Konversationsverlauf. Drittens muss die call_id im Ergebnis zur call_id des jeweiligen Tool-Calls passen. Viertens Tool-Rückgabewerte mit json.dumps serialisieren — kein rohes Python-Dict übergeben.
name-Feld gegen eine Allowlist validieren. Argumenttypen prüfen. HTTP-Tools brauchen ein Timeout und eine Domain-Allowlist. DB-Tools führen nur vordefinierte SQL-Statements aus — niemals Modell-Output direkt in SQL konkatenieren. Tools, die auf Disk schreiben oder Shell-Befehle ausführen, gehören auf einen isolierten, wegwerfbaren Remote-Mac.
Schritt 3: Ein schreibgeschütztes Datenbank-Tool
Drei Anforderungen für ein sicheres DB-Tool: Nur-Lese-Verbindung (kein INSERT, UPDATE, DELETE), parametrisierte Queries (kein SQL-Injection), SQL-Allowlist (kein beliebiges SQL).
import sqlite3
from typing import Any
# Only these parameterized queries can be executed — no raw user SQL
ALLOWED_QUERIES: dict[str, str] = {
"get_order": "SELECT id, status, total, created_at FROM orders WHERE id = ?",
"list_orders": "SELECT id, status, total FROM orders WHERE user_id = ? LIMIT 20",
}
def query_db(query_name: str, params: list[Any]) -> list[dict]:
"""Execute an allowlisted, parameterized read-only query.
Never accepts raw SQL strings from the model.
"""
sql = ALLOWED_QUERIES.get(query_name)
if sql is None:
raise ValueError(f"Query '{query_name}' not in allowlist")
con = sqlite3.connect("orders.db", check_same_thread=False)
con.row_factory = sqlite3.Row
try:
rows = con.execute(sql, params).fetchall()
return [dict(r) for r in rows]
finally:
con.close()
# Schema exposed to the model
db_tool = {
"type": "function",
"name": "query_db",
"description": "Query the orders DB. Only read-only allowlisted queries.",
"parameters": {
"type": "object",
"properties": {
"query_name": {
"type": "string",
"enum": list(ALLOWED_QUERIES.keys()),
"description": "Name of the allowlisted query",
},
"params": {
"type": "array",
"items": {"type": ["string", "number"]},
"description": "Positional parameters for the query",
},
},
"required": ["query_name", "params"],
},
}
In Produktion ergänzt man: Connection Pool (kein Connect/Close pro Tool-Call), Query-Timeout, Zeilenanzahl-Limit in jeder SQL (kein SELECT * ohne Limit), Maskierung sensibler Felder. Das Tool-Ergebnis soll eine Zusammenfassung sein, kein roher Tabellen-Dump — denn jede zurückgegebene Zeile kostet Input-Token im nächsten Request.
Funktions-Tools vs. gehostete Tools
| Dimension | Funktions-Tools (type: function) | Gehostete Tools (OpenAI-betrieben) |
|---|---|---|
| Ausführungsort | Eigene Laufzeit (lokal / Remote-Mac) | OpenAI-Infrastruktur |
| Geeignet für | Private APIs, interne DBs, Custom-Logik | Websuche, Code Interpreter, Shell, Computer Use |
| Entwicklungsaufwand | Schema + Ausführungsfunktion + Loop selbst schreiben | Toolnamen angeben, OpenAI erledigt den Rest |
| Abrechnung | Nur Token | Token + Tool-Gebühr pro Aufruf |
| Isolierungsanforderung | Schreibende Tools brauchen isolierte Umgebung | OpenAI verwaltet Sandbox; Datensicherheit obliegt Ihnen |
Beide Typen können in einem Request kombiniert werden. Gehostete Tool-Ergebnisse fließen automatisch in den Konversationsverlauf ein; kein manuelles Einreichen notwendig. Funktions-Tool-Ergebnisse müssen manuell als function_call_output übermittelt werden.
Entscheidungsmatrix
| Wenn Sie benötigen | Wählen Sie | Begründung |
|---|---|---|
| Internes REST-API aufrufen | Funktions-Tool | Privates Netz von OpenAI-Infra nicht erreichbar |
| Interne DB lesen (nur lesen) | Funktions-Tool + SQL-Allowlist | Private Daten; Zugriffsrechte selbst verwalten |
| Öffentliche Web-Suche in Echtzeit | Gehostetes web_search_preview | Crawling und Ranking übernimmt OpenAI |
| Modell soll Python ausführen | Gehostetes code_interpreter | Läuft in OpenAI-Sandbox; kein lokaler Ressourcenverbrauch |
| Modell soll Desktop/Browser steuern | Gehostetes computer_use + isolierter Mac | Sichtbarer Desktop nötig; Isolation verhindert Versehen |
| Shell-Befehle mit Disk-Schreibzugriff | Funktions-Tool + Remote-Mac-Isolierung | Schreibrechte nur auf wegwerfbarem Host |
Empfohlene Setups
A — Solo-Entwickler/Prototyp: lokale Maschine, Funktions-Tools für HTTP-APIs (kein Disk-Write). Schema schreiben, Loop stabilisieren, call_id loggen. Erst nach stabilen Einzel-Tool-Aufrufen auf Mehrfach-Tools erweitern.
B — Kleines Team/Produkt: Funktions-Tools hinter internen Services mit Token-Auth. DB-Tool: read-only, Connection Pool, Query-Timeout. Gehostete Tools je nach Aufgabe aktivieren. Tool-Logik mit Unit-Tests abdecken; Rückgabewerte schema-validieren.
C — Enterprise: Alle Tool-Aufrufe über API-Gateway mit Audit-Log. DB: read-only Replica + Row-Level Security. Computer Use auf wegwerfbaren isolierten Mac-Nodes. Account und Liefergrenzen im Hilfecenter; Monatspreis für Nodes auf Mac-mini-Preise.
Häufige Fehler
- Loop nur einmal ausführen (if statt while): Die abschließende Textantwort des Modells kommt nie an.
- Ergebnisse ohne Verlauf einreichen: Nur tool_results als input übergeben — das Modell verliert den Kontext.
- Modell-Output direkt in SQL/Shell konkatenieren: Allowlist + parametrisierte Queries eliminieren die Angriffsfläche.
- Kein Timeout für HTTP-Tools: Ein hängender Downstream-Service friert die gesamte Agentensitzung ein.
- Große Daten-Dumps aus Tools zurückgeben: Zeilen verbrauchen Prompt-Token und können den 272K-Uplift auslösen.
Aktionsplan: 7 Schritte
- Zuerst den reinen Textpfad bestätigen (siehe API-Tutorial). Tools bauen darauf auf.
- Erstes Funktions-Tool-Schema schreiben. description als Verb-Phrase, required befüllen, additionalProperties: false.
- Ausführungsfunktion implementieren. HTTP-Tools: Timeout. DB-Tools: Allowlist + parametrisierte Queries.
- Responses-Request mit tools-Parameter senden; response.output ausgeben und function_call-Eintrag bestätigen.
- while-True-Loop implementieren. call_id korrekt abbilden, function_call_output einreichen, Verlauf mitgeben.
- Gehostete Tools (web_search, code_interpreter) hinzufügen, falls nötig. Deren Ergebnisse nicht manuell einreichen.
- Disk-schreibende, Shell-ausführende oder Browser-steuernde Tools auf einen isolierten Remote-Mac auslagern und Workspace am Sitzungsende vernichten.
FAQ
Ist die Responses API für Function Calling Pflicht?
Ja. Tool-Aufrufe, gehostete Tools und asynchrone Loops erfordern Responses. Chat Completions gibt bei gehosteten Tools HTTP 400 zurück.
Wie viele Tools pro Request?
Keine strenge kleine Obergrenze, aber mehr Tools = mehr Prompt-Token. Nur aufgabenrelevante Tools übergeben.
SQL-Injection verhindern?
Parametrisierte Queries mit ?-Platzhaltern kombiniert mit einer SQL-Allowlist. Modell-Output niemals direkt in SQL einfügen.
Funktions-Tool oder gehostetes Tool?
Private API, interne DB, Custom-Logik → Funktions-Tool. Websuche, Code-Interpreter, Computer Use → gehostetes Tool.
Finale Antwort nach Tool-Aufrufen streamen?
Ja. Erst den nicht-streamenden Loop stabilisieren, dann stream=True hinzufügen.
Fazit
Die drei Grundlagen von GPT-6 Astra Function Calling: ein Schema mit klarer description und vollständigen Parametern, ein while-Loop mit vollständigem Verlauf beim Einreichen, und DB-Tools mit Allowlist und parametrisierten Queries — write-fähige Tools auf einem isolierten Mac. Remote-Mac-Nodes finden Sie auf der Miet- und Preisseite; Kontodetails im Hilfecenter.
Weiterlesen
- GPT-6 Astra API aufrufen: Python vom Key zum ersten Request →
- Was ist Function Calling: OpenAI, Gemini, Claude im Vergleich →
- Was ist GPT-6 Astra: Release, Preis und Agenten →
Tools, die echte APIs aufrufen? Auf einem isolierten Cloud-Mac ausführen
Einen öffentlichen HTTP-Endpunkt lokal aufzurufen ist in Ordnung. Sobald ein Tool Dateien schreibt, Repos bearbeitet oder einen Browser steuert, darf es den Alltags-Laptop nicht teilen. Remote-Macs isolieren einen Workspace pro Sitzung.