Gib Modellen Zugriff auf neue Funktionen und Daten, mit denen sie Anweisungen befolgen und auf Prompts antworten können.
Responses
Funktionsaufrufe (auch Tool-Aufrufe genannt) bieten OpenAI-Modellen eine leistungsfähige und flexible Möglichkeit, mit externen Systemen zu interagieren und auf Daten außerhalb ihrer Trainingsdaten zuzugreifen. Dieser Leitfaden zeigt dir, wie du ein Modell mit Daten und Aktionen verbindest, die deine Anwendung bereitstellt. Wir zeigen dir, wie du Funktionstools (definiert durch ein JSON-Schema) und benutzerdefinierte Tools verwendest, die mit frei formulierten Textein- und -ausgaben arbeiten.
Verwende für Sitzungen der Agents API Funktionen, um Funktionen zu registrieren und Aktionsanfragen in Sitzungen zu verarbeiten. Die Beispiele in diesem Leitfaden zeigen die Integrationen mit der Responses API und Chat Completions.
Wenn deine Anwendung viele Funktionen oder umfangreiche Schemas hat, kannst du Funktionsaufrufe mit der Tool-Suche kombinieren. So werden selten verwendete Tools erst geladen, wenn das Modell sie benötigt. Nur gpt-5.4 und neuere Modelle unterstützen tool_search.
GPT-6 Astra benötigt für Tool-Aufrufe die Responses API. Die Beispiele für Chat Completions verwenden
aus Kompatibilitätsgründen GPT-5.6. Im Leitfaden zur
Migration erfährst du, wie du eine bestehende
Integration aktualisierst.
So funktioniert es
Zunächst klären wir einige wichtige Begriffe rund um Tool-Aufrufe. Auf dieser Grundlage zeigen wir dir anschließend anhand praktischer Beispiele, wie du Tool-Aufrufe umsetzt.
Eine Funktion oder ein Tool bezeichnet allgemein eine Funktionalität, von der wir dem Modell mitteilen, dass es darauf zugreifen kann. Während ein Modell eine Antwort auf einen Prompt generiert, kann es feststellen, dass es Daten oder Funktionen eines Tools benötigt, um die Anweisungen im Prompt zu befolgen.
Du könntest dem Modell Zugriff auf Tools geben, die:
das heutige Wetter für einen Ort abrufen
Kontodetails für eine bestimmte Nutzer-ID abrufen
Rückerstattungen für eine verloren gegangene Bestellung veranlassen
Oder alles andere, was das Modell beim Beantworten eines Prompts wissen oder tun können soll.
Wenn wir eine API-Anfrage mit einem Prompt an das Modell senden, können wir eine Liste von Tools mitgeben, deren Nutzung das Modell in Betracht ziehen kann. Soll das Modell beispielsweise Fragen zum aktuellen Wetter an einem beliebigen Ort auf der Welt beantworten können, könnten wir ihm Zugriff auf ein Tool namens get_weather geben, das location als Argument entgegennimmt.
Ein Funktionsaufruf oder Tool-Aufruf ist eine besondere Art von Antwort, die wir vom Modell erhalten können. Das Modell gibt sie zurück, wenn es nach Prüfung eines Prompts feststellt, dass es eines der bereitgestellten Tools aufrufen muss, um die Anweisungen im Prompt zu befolgen.
Erhält das Modell in einer API-Anfrage einen Prompt wie „Wie ist das Wetter in Paris?“, könnte es darauf mit einem Aufruf des Tools get_weather antworten und dabei Paris als Wert für das Argument location übergeben.
Die Ausgabe eines Funktionsaufrufs oder Ausgabe eines Tool-Aufrufs bezeichnet die Antwort, die ein Tool anhand der Eingabe aus einem Tool-Aufruf des Modells erzeugt. Diese Ausgabe kann als strukturiertes JSON oder als reiner Text vorliegen. Sie sollte einen Verweis auf einen bestimmten Tool-Aufruf des Modells enthalten (in den folgenden Beispielen über call_id).
Vervollständigen wir unser Wetterbeispiel:
Das Modell hat Zugriff auf ein Tool namens get_weather, das location als Argument entgegennimmt.
Als Antwort auf einen Prompt wie „Wie ist das Wetter in Paris?“ gibt das Modell einen Tool-Aufruf zurück, der das Argument location mit dem Wert Paris enthält
Die Ausgabe des Tool-Aufrufs könnte ein JSON-Objekt (z. B. {"temperature": "25", "unit": "C"} für eine aktuelle Temperatur von 25 Grad), Bildinhalte oder Dateiinhalte zurückgeben.
Anschließend senden wir die Tool-Definition, den ursprünglichen Prompt, den Tool-Aufruf des Modells und die Ausgabe des Tool-Aufrufs zusammen zurück an das Modell. So erhalten wir schließlich eine Textantwort wie:
The weather in Paris today is 25C.
Eine Funktion ist eine bestimmte Art von Tool, die durch ein JSON-Schema definiert wird. Eine Funktionsdefinition ermöglicht es dem Modell, Daten an deine Anwendung zu übergeben. Dort kann dein Code auf Daten zugreifen oder vom Modell vorgeschlagene Aktionen ausführen.
Neben Funktionstools gibt es benutzerdefinierte Tools, die mit frei formulierten Textein- und -ausgaben arbeiten. Auch diese werden in diesem Leitfaden beschrieben.
Tool-Aufrufe sind ein mehrstufiger Dialog zwischen deiner Anwendung und einem Modell über die OpenAI API. Der Ablauf umfasst fünf wesentliche Schritte:
Sende eine Anfrage an das Modell mit Tools, die es aufrufen könnte
Empfange einen Tool-Aufruf vom Modell
Führe auf Anwendungsseite Code mit der Eingabe aus dem Tool-Aufruf aus
Sende eine zweite Anfrage mit der Tool-Ausgabe an das Modell
Empfange eine abschließende Antwort vom Modell (oder weitere Tool-Aufrufe)
Mit Responses kann deine Anwendung diesen Ablauf für so viele Tool-Aufrufe fortsetzen, wie die Aufgabe erfordert. Wenn du ein Framework suchst, das wiederkehrende Orchestrierungsaufgaben rund um diese Schleife übernimmt, lies den Vergleich der Responses API mit dem Agents SDK.
Beispiel für ein Funktionstool
Sehen wir uns den vollständigen Ablauf eines Tool-Aufrufs für die Funktion get_horoscope an, die ein Tageshoroskop für ein Sternzeichen abruft.
Vollständiges Beispiel für einen Tool-Aufruf
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70import OpenAI from "openai";const openai = new OpenAI();// 1. Define a list of callable tools for the modelconst tools = [ { type: "function", function: { name: "get_horoscope", description: "Get today's horoscope for an astrological sign.", parameters: { type: "object", properties: { sign: { type: "string", description: "An astrological sign like Taurus or Aquarius", }, }, required: ["sign"], additionalProperties: false, }, strict: true, }, },];function getHoroscope(sign) { return `${sign}: Next Tuesday you will befriend a baby otter.`;}const messages = [ { role: "user", content: "What is my horoscope? I am an Aquarius." },];// 2. Prompt the model with tools definedlet response = await openai.chat.completions.create({ model: "gpt-5.6", messages, tools,});messages.push(response.choices[0].message);for (const toolCall of response.choices[0].message.tool_calls ?? []) { if (toolCall.type !== "function") continue; if (toolCall.function.name === "get_horoscope") { // 3. Execute the function logic for get_horoscope const args = JSON.parse(toolCall.function.arguments); const horoscope = getHoroscope(args.sign); // 4. Provide function call results to the model messages.push({ role: "tool", tool_call_id: toolCall.id, content: JSON.stringify({ horoscope }), }); }}response = await openai.chat.completions.create({ model: "gpt-5.6", messages, tools,});// 5. The model should be able to give a response!console.log(response.choices[0].message.content);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67from openai import OpenAIimport jsonclient = OpenAI()# 1. Define a list of callable tools for the modeltools = [ {"type": "function","function": {"name": "get_horoscope","description": "Get today's horoscope for an astrological sign.","parameters": {"type": "object","properties": {"sign": {"type": "string","description": "An astrological sign like Taurus or Aquarius", }, },"required": ["sign"],"additionalProperties": False, },"strict": True, }, },]defget_horoscope(sign):returnf"{sign}: Next Tuesday you will befriend a baby otter."messages = [{"role": "user", "content": "What is my horoscope? I am an Aquarius."}]# 2. Prompt the model with tools definedresponse = client.chat.completions.create(model="gpt-5.6",messages=messages,tools=tools,)messages.append(response.choices[0].message)for tool_call in response.choices[0].message.tool_calls or []:if tool_call.function.name =="get_horoscope":# 3. Execute the function logic for get_horoscope args = json.loads(tool_call.function.arguments) horoscope = get_horoscope(args["sign"])# 4. Provide function call results to the model messages.append( {"role": "tool","tool_call_id": tool_call.id,"content": json.dumps({"horoscope": horoscope}), } )response = client.chat.completions.create(model="gpt-5.6",messages=messages,tools=tools,)# 5. The model should be able to give a response!print(response.choices[0].message.content)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77import OpenAI from "openai";import { toResponseInputItems } from "openai/lib/responses/ResponseInputItems";const openai = new OpenAI();// 1. Define a list of callable tools for the modelconst tools = [ { type: "function", name: "get_horoscope", description: "Get today's horoscope for an astrological sign.", parameters: { type: "object", properties: { sign: { type: "string", description: "An astrological sign like Taurus or Aquarius", }, }, required: ["sign"], additionalProperties: false, }, strict: true, },];function getHoroscope(sign) { return `${sign}: Next Tuesday you will befriend a baby otter.`;}// Create a running input list we will add to over timelet input = [ { role: "user", content: "What is my horoscope? I am an Aquarius." },];// 2. Prompt the model with tools definedlet response = await openai.responses.create({ model: "gpt-6-astra", tools, input,});// Preserve model output for the next turninput.push(...toResponseInputItems(response.output));for (const item of response.output) { if (item.type !== "function_call") continue; if (item.name === "get_horoscope") { // 3. Execute the function logic for get_horoscope const { sign } = JSON.parse(item.arguments); const horoscope = getHoroscope(sign); // 4. Provide function call results to the model input.push({ type: "function_call_output", call_id: item.call_id, output: horoscope, }); }}console.log("Final input:");console.log(JSON.stringify(input, null, 2));response = await openai.responses.create({ model: "gpt-6-astra", instructions: "Respond only with a horoscope generated by a tool.", tools, input,});// 5. The model should be able to give a response!console.log("Final output:");console.log(response.output_text);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72from openai import OpenAIimport jsonclient = OpenAI()# 1. Define a list of callable tools for the modeltools = [ {"type": "function","name": "get_horoscope","description": "Get today's horoscope for an astrological sign.","parameters": {"type": "object","properties": {"sign": {"type": "string","description": "An astrological sign like Taurus or Aquarius", }, },"required": ["sign"], }, },]defget_horoscope(sign):returnf"{sign}: Next Tuesday you will befriend a baby otter."# Create a running input list we will add to over timeinput_list = [{"role": "user", "content": "What is my horoscope? I am an Aquarius."}]# 2. Prompt the model with tools definedresponse = client.responses.create(model="gpt-6-astra",tools=tools,input=input_list,)# Save function call outputs for subsequent requestsinput_list += response.outputfor item in response.output:if item.type =="function_call":if item.name =="get_horoscope":# 3. Execute the function logic for get_horoscope sign = json.loads(item.arguments)["sign"] horoscope = get_horoscope(sign)# 4. Provide function call results to the model input_list.append( {"type": "function_call_output","call_id": item.call_id,"output": horoscope, } )print("Final input:")print(input_list)response = client.responses.create(model="gpt-6-astra",instructions="Respond only with a horoscope generated by a tool.",tools=tools,input=input_list,)# 5. The model should be able to give a response!print("Final output:")print(response.model_dump_json(indent=2))print("\n"+ response.output_text)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75package mainimport ( "context" "encoding/json" "fmt" "github.com/openai/openai-go/v3" "github.com/openai/openai-go/v3/responses")func main() { client := openai.NewClient() tool := horoscopeResponseTool() response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{ Model: "gpt-6-astra", Input: responses.ResponseNewParamsInputUnion{OfString: openai.String("What is my horoscope? I am an Aquarius.")}, Tools: []responses.ToolUnionParam{tool}, }) if err != nil { panic(err) } var functionOutput responses.ResponseInputItemUnionParam for _, output := range response.Output { if output.Type != "function_call" { continue } call := output.AsFunctionCall() if call.Name != "get_horoscope" { continue } var arguments struct { Sign string `json:"sign"` } if err := json.Unmarshal([]byte(call.Arguments), &arguments); err != nil { panic(err) } functionOutput = responses.ResponseInputItemParamOfFunctionCallOutput(getHoroscope(arguments.Sign)) functionOutput.OfFunctionCallOutput.CallID = openai.String(call.CallID) } if functionOutput.OfFunctionCallOutput == nil { panic("the model did not call get_horoscope") } response, err = client.Responses.New(context.Background(), responses.ResponseNewParams{ Model: "gpt-6-astra", PreviousResponseID: openai.String(response.ID), Instructions: openai.String("Respond only with a horoscope generated by a tool."), Input: responses.ResponseNewParamsInputUnion{OfInputItemList: responses.ResponseInputParam{functionOutput}}, Tools: []responses.ToolUnionParam{tool}, }) if err != nil { panic(err) } fmt.Println(response.OutputText())}func horoscopeResponseTool() responses.ToolUnionParam { parameters := map[string]any{ "type": "object", "properties": map[string]any{ "sign": map[string]any{"type": "string", "description": "An astrological sign like Taurus or Aquarius"}, }, "required": []string{"sign"}, "additionalProperties": false, } tool := responses.ToolParamOfFunction("get_horoscope", parameters, true) tool.OfFunction.Description = openai.String("Get today's horoscope for an astrological sign.") return tool}func getHoroscope(sign string) string { return fmt.Sprintf("%s: Next Tuesday you will befriend a baby otter.", sign)}
Beachte: Bei Reasoning-Modellen wie GPT-5 oder o4-mini müssen alle Reasoning-Elemente, die das Modell zusammen mit Tool-Aufrufen in seinen Antworten zurückgibt, auch zusammen mit den Ausgaben der Tool-Aufrufe zurückgesendet werden.
Funktionen definieren
Funktionen werden üblicherweise im Parameter tools jeder API-Anfrage deklariert. Mit der Tool-Suche kann deine Anwendung zunächst zurückgestellte Funktionen auch später im Verlauf der Interaktion laden. In beiden Fällen verwendet jede aufrufbare Funktion dieselbe Schemastruktur. Eine Funktionsdefinition hat die folgenden Eigenschaften:
Feld
Beschreibung
type
Der Wert sollte immer function sein
name
Der Name der Funktion (zum Beispiel get_weather)
description
Angaben dazu, wann und wie die Funktion verwendet werden soll
parameters
JSON-Schema, das die Eingabeargumente der Funktion definiert
strict
Ob der strikte Modus für den Funktionsaufruf erzwungen werden soll
Hier ist eine beispielhafte Definition für die Funktion get_weather
12345678910111213141516171819202122{ "type": "function", "name": "get_weather", "description": "Retrieves current weather for the given location.", "parameters": { "type": "object", "properties": { "location": { "type": "string", "description": "City and country e.g. Bogotá, Colombia" }, "units": { "type": "string", "enum": ["celsius", "fahrenheit"], "description": "Units the temperature will be returned in." } }, "required": ["location", "units"], "additionalProperties": false }, "strict": true}
Da parameters durch ein JSON-Schema definiert werden, kannst du dessen vielfältige Möglichkeiten nutzen, etwa Eigenschaftstypen, Enums, Beschreibungen sowie verschachtelte und rekursive Objekte.
Namensräume definieren
Verwende Namensräume, um zusammengehörige Tools nach Fachgebiet zu gruppieren, etwa crm, billing oder shipping. Namensräume helfen, ähnliche Tools zu organisieren. Sie sind besonders nützlich, wenn das Modell zwischen Tools für unterschiedliche Systeme oder Zwecke wählen muss, zum Beispiel einem Suchtool für dein CRM und einem weiteren für dein Support-Ticketsystem.
Wenn du dem Modell Zugriff auf ein umfangreiches Ökosystem von Tools geben möchtest, kannst du mit tool_search das Laden einiger oder aller Tools auf später verschieben. Mit dem Tool tool_search kann das Modell nach relevanten Tools suchen, sie seinem Kontext hinzufügen und anschließend verwenden. Nur gpt-5.4 und neuere Modelle unterstützen dies. Weitere Informationen findest du im Leitfaden zur Tool-Suche.
Wir empfehlen dir, deine Funktionsschemas direkt zu definieren. Unsere SDKs bieten aber auch Hilfsfunktionen, um Objekte aus pydantic und zod in Schemas umzuwandeln. Nicht alle Funktionen von pydantic und zod werden unterstützt.
Objekte zur Darstellung des Funktionsschemas definieren
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26import OpenAI from "openai";import { z } from "zod";import { zodFunction } from "openai/helpers/zod";const openai = new OpenAI();const GetWeatherParameters = z.object({ location: z.string().describe("City and country e.g. Bogotá, Colombia"),});const tools = [ zodFunction({ name: "getWeather", parameters: GetWeatherParameters }),];const messages = [ { role: "user", content: "What's the weather like in Paris today?" },];const response = await openai.chat.completions.create({ model: "gpt-5.6", messages, tools, store: true,});console.log(response.choices[0].message.tool_calls);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19from openai import OpenAI, pydantic_function_toolfrom pydantic import BaseModel, Fieldclient = OpenAI()classGetWeather(BaseModel): location: str= Field(..., description="City and country e.g. Bogotá, Colombia")tools = [pydantic_function_tool(GetWeather)]completion = client.chat.completions.create(model="gpt-5.6",messages=[{"role": "user", "content": "What's the weather like in Paris today?"}],tools=tools,)print(completion.choices[0].message.tool_calls)
Bewährte Methoden zum Definieren von Funktionen
Formuliere Funktionsnamen, Parameterbeschreibungen und Anweisungen klar und ausführlich.
Beschreibe ausdrücklich den Zweck der Funktion und jedes Parameters (sowie dessen Format) und erläutere, was die Ausgabe bedeutet.
Beschreibe im System-Prompt, wann die einzelnen Funktionen verwendet werden sollen und wann nicht. Sage dem Modell grundsätzlich genau , was es tun soll.
Füge Beispiele und Ausnahmefälle hinzu, insbesondere um wiederkehrende Fehler zu beheben. (Hinweis: Zusätzliche Beispiele können die Leistung von Reasoning-Modellen beeinträchtigen.)
Gib bei Tools, die erst bei Bedarf geladen werden, ausführliche Hinweise in der Funktionsbeschreibung und halte die Beschreibung des Namensraums kurz. Der Namensraum hilft dem Modell bei der Auswahl dessen, was es laden soll. Die Funktionsbeschreibung hilft ihm, das geladene Tool korrekt zu verwenden.
Wende bewährte Methoden der Softwareentwicklung an.
Verwende Enums und die Objektstruktur, um ungültige Zustände zu verhindern. Beispielsweise lässt toggle_light(on: bool, off: bool) ungültige Aufrufe zu.
Bestehe den Test mit einer Person im Praktikum. Kann eine Person im Praktikum oder ein anderer Mensch die Funktion allein mit den Informationen korrekt verwenden, die du dem Modell gegeben hast? (Falls nicht: Welche Fragen stellt sie dir? Ergänze die Antworten im Prompt.)
Entlaste das Modell und verwende nach Möglichkeit Code.
Lass das Modell keine Argumente ausfüllen, deren Werte du bereits kennst. Wenn dir beispielsweise aus einem vorherigen Menü bereits eine order_id vorliegt, füge keinen Parameter order_id hinzu. Definiere stattdessen submit_refund() ohne Parameter und übergib die order_id in deinem Code.
Fasse Funktionen zusammen, die immer nacheinander aufgerufen werden. Wenn du beispielsweise immer mark_location() nach query_location() aufrufst, verlagere die Markierungslogik einfach in den Aufruf der Abfragefunktion.
Halte die Anzahl der anfangs verfügbaren Funktionen klein, um die Genauigkeit zu erhöhen.
Bewerte die Leistung mit unterschiedlich vielen Funktionen.
Stelle zu Beginn eines Durchgangs möglichst weniger als 20 Funktionen gleichzeitig bereit. Das ist allerdings nur ein Richtwert.
Verwende die Tool-Suche , um umfangreiche oder selten verwendete Teile deines Tool-Angebots erst bei Bedarf zu laden, statt alles von Anfang an bereitzustellen.
Nutze die Ressourcen von OpenAI.
Erstelle Funktionsschemas und verbessere sie schrittweise im Playground.
Ziehe Fine-Tuning in Betracht, um die Genauigkeit von Funktionsaufrufen zu erhöhen , wenn du viele Funktionen oder schwierige Aufgaben hast. (Cookbook)
Token-Nutzung
Im Hintergrund werden Funktionen in einer Syntax in die Systemnachricht eingefügt, auf die das Modell trainiert wurde. Die Definitionen aufrufbarer Funktionen zählen daher zum Kontextlimit des Modells und werden als Eingabetoken abgerechnet. Wenn du an Token-Limits stößt, empfehlen wir, anfangs weniger Funktionen zu laden, Beschreibungen nach Möglichkeit zu kürzen oder die Tool-Suche zu verwenden, damit zurückgestellte Tools erst bei Bedarf geladen werden.
Wenn du viele Funktionen in deiner Tool-Spezifikation definiert hast, kannst du auch mit Fine-Tuning die Anzahl der verwendeten Token reduzieren.
Funktionsaufrufe verarbeiten
Wenn das Modell eine Funktion aufruft, musst du sie ausführen und das Ergebnis zurückgeben. Da Modellantworten keinen, einen oder mehrere Aufrufe enthalten können, solltest du grundsätzlich mit mehreren Aufrufen rechnen.
Die Antwort enthält ein Array von tool_calls. Jeder Eintrag hat eine id (die später zur Übermittlung des Funktionsergebnisses verwendet wird) und ein function-Objekt mit einem name und JSON-kodierten arguments.
Das output-Array der Antwort enthält einen Eintrag, dessen type den Wert function_call hat. Jeder Eintrag enthält eine call_id (die später zur Übermittlung des Funktionsergebnisses verwendet wird), einen name und JSON-kodierte arguments.
Wenn du die Tool-Suche verwendest, können vor einem function_call auch Elemente vom Typ tool_search_call und tool_search_output erscheinen. Sobald die Funktion geladen ist, verarbeitest du den Funktionsaufruf genauso wie hier gezeigt.
Funktionsaufrufe ausführen und Ergebnisse anhängen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16def call_function(name, arguments) case name when "get_weather" FunctionCallingExample.get_weather( arguments.fetch("latitude"), arguments.fetch("longitude") ) when "send_email" FunctionCallingExample.send_email( arguments.fetch("to"), arguments.fetch("body") ) else raise ArgumentError, "Unknown function: #{name}" endend
Ergebnisse formatieren
Das Ergebnis, das du in der function_call_output-Nachricht übergibst, sollte in der Regel ein String sein. Das Format kannst du selbst wählen (JSON, Fehlercodes, Klartext usw.). Das Modell interpretiert diesen String nach Bedarf.
"It's about 15°C in Paris, 18°C in Bogotá, and I've sent that email to Bob."
Weitere Konfigurationen
Tool-Auswahl
Standardmäßig entscheidet das Modell, wann und wie viele Tools es verwendet. Mit dem Parameter tool_choice kannst du ein bestimmtes Verhalten erzwingen.
Automatisch: (Standard) Keine, eine oder mehrere Funktionen aufrufen. tool_choice: "auto"
Erforderlich: Eine oder mehrere Funktionen aufrufen.
tool_choice: "required"
Zulässige Tools: Die Tool-Aufrufe des Modells auf eine Teilmenge
der verfügbaren Tools beschränken.
Wann du allowed_tools verwenden solltest
Eine allowed_tools-Liste kann sinnvoll sein, wenn du bei Modellanfragen nur
eine Teilmenge der Tools verfügbar machen möchtest, ohne die übergebene Tool-Liste zu ändern. So kannst du die Einsparungen durch Prompt-Caching maximieren.
Du kannst tool_choice auch auf "none" setzen, um dasselbe Verhalten zu erzielen, als würdest du keine Funktionen übergeben.
Wenn du die Tool-Suche verwendest, gilt tool_choice weiterhin für die Tools, die im aktuellen Durchgang aufrufbar sind. Das ist besonders nützlich, wenn du eine Teilmenge der Tools geladen hast und das Modell auf diese Teilmenge beschränken möchtest.
Parallele Funktionsaufrufe
Bei unterstützten Modellen ab GPT-5 können Funktionen auch dann parallel aufgerufen werden,
wenn integrierte Tools verfügbar sind. Integrierte Tools
können jedoch nicht Teil einer Gruppe paralleler Funktionsaufrufe sein.
Das Modell kann sich entscheiden, mehrere Funktionen in einem einzigen Durchgang aufzurufen. Du kannst dies verhindern, indem du parallel_tool_calls auf false setzt. Dadurch wird sichergestellt, dass entweder kein oder genau ein Tool aufgerufen wird.
Hinweis: Wenn du ein durch Fine-Tuning angepasstes Modell verwendest und dieses mehrere Funktionen in einem Durchgang aufruft, wird der strikte Modus derzeit für diese Aufrufe deaktiviert.
Hinweis zu gpt-4.1-nano-2025-04-14: Dieser Snapshot von gpt-4.1-nano kann gelegentlich mehrere Aufrufe desselben Tools enthalten, wenn parallele Tool-Aufrufe aktiviert sind. Wir empfehlen, diese Funktion bei Verwendung dieses Snapshots zu deaktivieren.
Strikter Modus
Wenn du strict auf true setzt, halten sich Funktionsaufrufe zuverlässig an das Funktionsschema, statt dessen Einhaltung nur nach bestem Bemühen anzustreben. Wir empfehlen, den strikten Modus immer zu aktivieren.
Der strikte Modus nutzt intern unsere Funktion für strukturierte Ausgaben. Daraus ergeben sich einige Anforderungen:
additionalProperties muss für jedes Objekt in parameters auf false gesetzt werden.
Alle Felder in properties müssen als required gekennzeichnet sein.
Du kannst optionale Felder kennzeichnen, indem du null als Option für type hinzufügst (siehe Beispiel unten).
Wenn du strict: true übergibst und dein Schema die oben genannten Anforderungen nicht erfüllt,
wird die Anfrage mit Angaben zu den fehlenden Einschränkungen abgelehnt.
Wenn du strict weglässt, hängt das Standardverhalten von der API ab: Bei Responses-Anfragen wird
nach Möglichkeit versucht, dein Schema für den strikten Modus zu normalisieren.
Lässt sich das Schema nicht mit dem strikten Modus kompatibel machen, werden Funktionsaufrufe
ohne strikte Schemaeinhaltung nach bestem Bemühen ausgeführt. In diesem Fall zeigt das Tool in der Antwort
strict: false an. Bei Chat Completions-Anfragen bleibt der strikte Modus standardmäßig deaktiviert.
Um den strikten Modus in Responses zu deaktivieren und Funktionsaufrufe weiterhin ohne strikte Schemaeinhaltung
nach bestem Bemühen auszuführen, setze ausdrücklich strict: false.
Strikter Modus aktiviert
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24{"type": "function","function": {"name": "get_weather","description": "Retrieves current weather for the given location.","strict": true,"parameters": {"type": "object","properties": {"location": {"type": "string","description": "City and country e.g. Bogotá, Colombia" },"units": {"type": ["string", "null"],"enum": ["celsius", "fahrenheit"],"description": "Units the temperature will be returned in." } },"required": ["location", "units"],"additionalProperties": false } }}
Strikter Modus deaktiviert
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22{"type": "function","function": {"name": "get_weather","description": "Retrieves current weather for the given location.","parameters": {"type": "object","properties": {"location": {"type": "string","description": "City and country e.g. Bogotá, Colombia" },"units": {"type": "string","enum": ["celsius", "fahrenheit"],"description": "Units the temperature will be returned in." } },"required": ["location"], } }}
Strikter Modus aktiviert
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22{"type": "function","name": "get_weather","description": "Retrieves current weather for the given location.","strict": true,"parameters": {"type": "object","properties": {"location": {"type": "string","description": "City and country e.g. Bogotá, Colombia" },"units": {"type": ["string", "null"],"enum": ["celsius", "fahrenheit"],"description": "Units the temperature will be returned in." } },"required": ["location", "units"],"additionalProperties": false }}
Strikter Modus deaktiviert
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20{"type": "function","name": "get_weather","description": "Retrieves current weather for the given location.","parameters": {"type": "object","properties": {"location": {"type": "string","description": "City and country e.g. Bogotá, Colombia" },"units": {"type": "string","enum": ["celsius", "fahrenheit"],"description": "Units the temperature will be returned in." } },"required": ["location"], }}
Bei allen Schemas, die im
Playground erstellt werden, ist der strikte Modus aktiviert.
Wir empfehlen, den strikten Modus zu aktivieren. Er hat jedoch einige Einschränkungen:
Einige Funktionen von JSON Schema werden nicht unterstützt. (Siehe unterstützte Schemas.)
Speziell für durch Fine-Tuning angepasste Modelle gilt:
Schemas werden bei der ersten Anfrage zusätzlich verarbeitet und anschließend zwischengespeichert. Wenn sich deine Schemas von Anfrage zu Anfrage unterscheiden, kann dies zu höheren Latenzen führen.
Schemas werden aus Leistungsgründen zwischengespeichert und können daher nicht unter die Regelung „keine Datenaufbewahrung“ fallen.
Streaming
Mit Streaming kannst du den Fortschritt sichtbar machen: Du kannst anzeigen, welche Funktion aufgerufen wird, während das Modell ihre Argumente ausfüllt, und sogar die Argumente in Echtzeit darstellen.
Das Streaming von Funktionsaufrufen funktioniert ähnlich wie das Streaming regulärer Antworten: Du setzt stream auf true und erhältst Datenblöcke mit delta-Objekten.
Funktionsaufrufe streamen
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40import { OpenAI } from "openai";const openai = new OpenAI();const tools = [ { type: "function", function: { name: "get_weather", description: "Get current temperature for a given location.", parameters: { type: "object", properties: { location: { type: "string", description: "City and country e.g. Bogotá, Colombia", }, }, required: ["location"], additionalProperties: false, }, strict: true, }, },];const stream = await openai.chat.completions.create({ model: "gpt-5.6", messages: [ { role: "user", content: "What's the weather like in Paris today?" }, ], tools, stream: true, store: true,});for await (const chunk of stream) { const delta = chunk.choices[0].delta; console.log(delta.tool_calls);}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36from openai import OpenAIclient = OpenAI()tools = [ {"type": "function","function": {"name": "get_weather","description": "Get current temperature for a given location.","parameters": {"type": "object","properties": {"location": {"type": "string","description": "City and country e.g. Bogotá, Colombia", } },"required": ["location"],"additionalProperties": False, },"strict": True, }, }]stream = client.chat.completions.create(model="gpt-5.6",messages=[{"role": "user", "content": "What's the weather like in Paris today?"}],tools=tools,stream=True,)for chunk in stream: delta = chunk.choices[0].deltaprint(delta.tool_calls)
Du führst die Datenblöcke jedoch nicht zu einer einzelnen content-Zeichenfolge zusammen, sondern zu einem codierten JSON-Objekt für arguments.
Wenn das Modell eine oder mehrere Funktionen aufruft, wird das Feld tool_calls in jedem delta-Objekt befüllt. Jedes tool_call-Objekt enthält die folgenden Felder:
Feld
Beschreibung
index
Gibt an, zu welchem Funktionsaufruf delta gehört
id
ID des Tool-Aufrufs.
function
Delta des Funktionsaufrufs (name und arguments)
type
Typ von tool_call (bei Funktionsaufrufen immer function)
Viele dieser Felder werden nur im ersten delta-Objekt jedes Tool-Aufrufs gesetzt, etwa id, function.name und type.
Der folgende Codeausschnitt zeigt, wie du die deltas zu einem vollständigen tool_calls-Objekt zusammenfügst.
Mit Streaming kannst du den Fortschritt sichtbar machen: Du kannst anzeigen, welche Funktion aufgerufen wird, während das Modell ihre Argumente ausfüllt, und sogar die Argumente in Echtzeit darstellen.
Das Streaming von Funktionsaufrufen funktioniert ganz ähnlich wie das Streaming regulärer Antworten: Du setzt stream auf true und erhältst verschiedene event-Objekte.
Die einzelnen Teile fügst du dabei jedoch nicht zu einer einzigen content-Zeichenfolge zusammen, sondern zu einem kodierten JSON-Objekt für arguments.
Wenn das Modell eine oder mehrere Funktionen aufruft, wird für jeden Funktionsaufruf ein Ereignis vom Typ response.output_item.added mit den folgenden Feldern ausgegeben:
Feld
Beschreibung
response_id
Die ID der Antwort, zu der der Funktionsaufruf gehört
output_index
Der Index des Ausgabeelements in der Antwort. Damit werden die einzelnen Funktionsaufrufe in der Antwort identifiziert.
item
Das noch unvollständige Funktionsaufrufelement mit den Feldern name, arguments und id
Anschließend erhältst du eine Reihe von Ereignissen vom Typ response.function_call_arguments.delta, die jeweils das delta des Felds arguments enthalten. Diese Ereignisse haben folgende Felder:
Feld
Beschreibung
response_id
Die ID der Antwort, zu der der Funktionsaufruf gehört
item_id
Die ID des Funktionsaufrufelements, zu dem das Delta gehört
output_index
Der Index des Ausgabeelements in der Antwort. Damit werden die einzelnen Funktionsaufrufe in der Antwort identifiziert.
delta
Das Delta des Felds arguments.
Der folgende Codeausschnitt zeigt, wie du die deltas zu einem vollständigen tool_call-Objekt zusammenfügst.
Wenn das Modell die Funktionsaufrufe abgeschlossen hat, wird ein Ereignis vom Typ response.function_call_arguments.done ausgegeben. Dieses Ereignis enthält den vollständigen Funktionsaufruf einschließlich der folgenden Felder:
Feld
Beschreibung
response_id
Die ID der Antwort, zu der der Funktionsaufruf gehört
output_index
Der Index des Ausgabeelements in der Antwort. Damit werden die einzelnen Funktionsaufrufe in der Antwort identifiziert.
item
Das Funktionsaufrufelement mit den Feldern name, arguments und id.
Benutzerdefinierte Tools
Benutzerdefinierte Tools funktionieren ähnlich wie Funktionstools, die auf einem JSON-Schema basieren. Du gibst dem Modell jedoch nicht explizit vor, welche Eingabe dein Tool benötigt. Stattdessen kann das Modell eine beliebige Zeichenfolge als Eingabe an dein Tool übergeben. So vermeidest du es, eine Antwort unnötig in JSON zu verpacken, oder kannst eine benutzerdefinierte Grammatik auf die Antwort anwenden (mehr dazu weiter unten).
Das folgende Codebeispiel zeigt, wie du ein benutzerdefiniertes Tool erstellst, das als Antwort eine Zeichenfolge mit Python-Code erwartet.
Beispiel für den Aufruf eines benutzerdefinierten Tools
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16import OpenAI from "openai";const client = new OpenAI();const response = await client.responses.create({ model: "gpt-6-astra", input: "Use the code_exec tool to print hello world to the console.", tools: [ { type: "custom", name: "code_exec", description: "Executes arbitrary Python code.", }, ],});console.log(response.output);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16from openai import OpenAIclient = OpenAI()response = client.responses.create(model="gpt-6-astra",input="Use the code_exec tool to print hello world to the console.",tools=[ {"type": "custom","name": "code_exec","description": "Executes arbitrary Python code.", } ],)print(response.output)
Wie zuvor enthält das Array output einen vom Modell generierten Tool-Aufruf. Diesmal wird die Eingabe für den Tool-Aufruf jedoch als reiner Text übergeben.
Eine kontextfreie Grammatik (CFG) ist ein Regelwerk, das festlegt, wie gültiger Text in einem bestimmten Format erzeugt wird. Für benutzerdefinierte Tools kannst du eine CFG angeben, die die zulässigen Texteingaben des Modells für das jeweilige Tool einschränkt.
Wenn du ein benutzerdefiniertes Tool konfigurierst, kannst du über den Parameter grammar eine eigene CFG angeben. Derzeit unterstützen wir zwei CFG-Syntaxvarianten zur Definition von Grammatiken: lark und regex.
Grammatiken werden mit einer Variante von Lark definiert. LLGuidance schränkt das Sampling des Modells ein. Einige Funktionen von Lark werden nicht unterstützt:
Lookarounds in regulären Ausdrücken des Lexers
Nicht-gierige Modifikatoren (*?, +?, ??) in regulären Ausdrücken des Lexers
Prioritäten von Terminalsymbolen
Vorlagen
Importe (außer dem integrierten %import common)
%declare-Deklarationen
Wir empfehlen die Lark IDE, um mit eigenen Grammatiken zu experimentieren.
Komplexität der Grammatik begrenzen
Beschränke deine Grammatik auf die Regeln und Muster, die dein Tool benötigt. Die OpenAI API kann einen Fehler zurückgeben, wenn die Grammatik zu komplex ist. Prüfe daher vor der Verwendung in der API, ob deine gewünschte Grammatik kompatibel ist.
Lark-Grammatiken zu perfektionieren kann schwierig sein. Weniger komplexe Grammatiken funktionieren am zuverlässigsten. Bei komplexen Grammatiken musst du häufig die Grammatikdefinition selbst, den Prompt und die Tool-Beschreibung schrittweise überarbeiten, damit das Modell keine Ausgaben außerhalb seiner Trainingsverteilung erzeugt.
Gehe NICHT so vor (Aufteilung auf mehrere Regeln oder Terminals). Hier wird versucht, Freitext durch Regeln auf Terminals aufzuteilen. Der Lexer erfasst die Freitextabschnitte nach dem Greedy-Prinzip, sodass du die Kontrolle verlierst:
Kleingeschriebene Regeln beeinflussen nicht, wie Terminals aus der Eingabe abgegrenzt werden. Das bestimmen allein die Terminaldefinitionen. Wenn du „Freitext zwischen Ankern“ brauchst, fasse ihn in einem einzigen großen Regex-Terminal zusammen. So erfasst ihn der Lexer genau einmal mit der von dir vorgesehenen Struktur.
Terminals und Regeln im Vergleich
Lark verwendet Terminals für Lexer-Token (konventionsgemäß UPPERCASE) und Regeln für Parser-Produktionen (konventionsgemäß lowercase). Am einfachsten bleibst du innerhalb des unterstützten Funktionsumfangs und vermeidest Überraschungen, indem du deine Grammatik explizit definierst, unnötige Komplexität vermeidest und die Zuständigkeiten von Terminals und Regeln klar trennst.
Der Lexer erfasst Terminals nach dem Greedy-Prinzip (der längste Treffer gewinnt), bevor die Logik der CFG-Regeln angewendet wird. Wenn du versuchst, ein Terminal durch Aufteilung auf mehrere Regeln zu „formen“, können diese Regeln den Lexer nicht steuern. Das können nur die regulären Ausdrücke der Terminals.
Verwende möglichst ein einzelnes Terminal, um Text aus frei formulierten Abschnitten zu extrahieren
Wenn du ein Muster erkennen musst, das in beliebigen Text eingebettet ist (zum Beispiel natürliche Sprache mit „beliebigem Inhalt“ zwischen Ankern), drücke es als einzelnes Terminal aus. Versuche nicht, Freitext-Terminals mit Parser-Regeln zu verschachteln. Der gierige Lexer hält die von dir vorgesehenen Grenzen nicht ein, und das Modell wird mit hoher Wahrscheinlichkeit Ausgaben außerhalb seiner Trainingsverteilung erzeugen.
Verwende Regeln, um einzelne Token zusammenzusetzen
Regeln eignen sich ideal, um explizit abgegrenzte Terminals (Zahlen, Schlüsselwörter, Satzzeichen) zu größeren Strukturen zusammenzusetzen. Sie eignen sich nicht dazu, „den Inhalt dazwischen“, also zwischen zwei Terminals, einzuschränken.
Halte Terminals auf eine Aufgabe beschränkt, begrenzt und in sich geschlossen
Bevorzuge explizite Zeichenklassen und begrenzte Quantifizierer ({0,10}, statt überall unbegrenztes * zu verwenden). Wenn du „beliebigen Text bis zu einem Punkt“ erfassen möchtest, verwende beispielsweise /[^.\n]{0,10}*\./ statt /.+\./, um unkontrolliertes Wachstum zu vermeiden.
Verwende Regeln, um Token zu kombinieren, nicht um das interne Verhalten regulärer Ausdrücke zu steuern
Beispiel für einen sinnvollen Einsatz von Regeln:
start: exprNUMBER: /[0-9]+/PLUS: "+"MINUS: "-"expr: term (("+"|"-") term)*term: NUMBER
Behandle Whitespace explizit
Verlasse dich nicht auf unbegrenzte %ignore-Direktiven. Unbegrenzte Ignore-Direktiven können die Grammatik zu komplex machen und/oder dazu führen, dass sich das Modell außerhalb seiner erlernten Verteilung bewegt. Füge stattdessen überall dort explizite Terminals ein, wo Whitespace erlaubt ist.
Fehlerbehebung
Wenn die API die Grammatik als zu komplex ablehnt, vereinfache die Regeln und Terminals und entferne unbegrenzte %ignore-Direktiven.
Wenn benutzerdefinierte Tools mit unerwarteten Token aufgerufen werden, prüfe, ob sich Terminals überschneiden, und überprüfe das Greedy-Verhalten des Lexers.
Wenn sich das Modell außerhalb seiner erlernten Verteilung bewegt (erkennbar an übermäßig langen oder repetitiven Ausgaben, die syntaktisch gültig, aber semantisch falsch sind):
Schränke die Grammatik stärker ein.
Überarbeite den Prompt schrittweise (füge Few-Shot-Beispiele hinzu) und passe die Tool-Beschreibung an (erkläre die Grammatik und weise das Modell an, sie zu durchdenken und einzuhalten).
Experimentiere mit einem höheren Reasoning-Aufwand (z. B. durch einen Wechsel von Mittel auf Hoch).
Regex-CFG
Beispiel für eine kontextfreie Grammatik mit Regex
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25import OpenAI from "openai";const client = new OpenAI();const grammar = "^(?P<month>January|February|March|April|May|June|July|August|September|October|November|December)\\s+(?P<day>\\d{1,2})(?:st|nd|rd|th)?\\s+(?P<year>\\d{4})\\s+at\\s+(?P<hour>0?[1-9]|1[0-2])(?P<ampm>AM|PM)$";const response = await client.responses.create({ model: "gpt-6-astra", input: "Use the timestamp tool to save a timestamp for August 7th 2025 at 10AM.", tools: [ { type: "custom", name: "timestamp", description: "Saves a timestamp in date + time in 24-hr format.", format: { type: "grammar", syntax: "regex", definition: grammar, }, }, ],});console.log(response.output);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23from openai import OpenAIclient = OpenAI()grammar =r"^(?P<month>January|February|March|April|May|June|July|August|September|October|November|December)\s+(?P<day>\d{1,2})(?:st|nd|rd|th)?\s+(?P<year>\d{4})\s+at\s+(?P<hour>0?[1-9]|1[0-2])(?P<ampm>AM|PM)$"response = client.responses.create(model="gpt-6-astra",input="Use the timestamp tool to save a timestamp for August 7th 2025 at 10AM.",tools=[ {"type": "custom","name": "timestamp","description": "Saves a timestamp in date + time in 24-hr format.","format": {"type": "grammar","syntax": "regex","definition": grammar, }, } ],)print(response.output)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28package mainimport ( "context" "fmt" "github.com/openai/openai-go/v3" "github.com/openai/openai-go/v3/responses" "github.com/openai/openai-go/v3/shared")func main() { client := openai.NewClient() grammar := `^(?P<month>January|February|March|April|May|June|July|August|September|October|November|December)\s+(?P<day>\d{1,2})(?:st|nd|rd|th)?\s+(?P<year>\d{4})\s+at\s+(?P<hour>0?[1-9]|1[0-2])(?P<ampm>AM|PM)$` tool := responses.ToolParamOfCustom("timestamp") tool.OfCustom.Description = openai.String("Saves a timestamp in date and time format.") tool.OfCustom.Format = shared.CustomToolInputFormatParamOfGrammar(grammar, "regex") response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{ Model: "gpt-6-astra", Input: responses.ResponseNewParamsInputUnion{OfString: openai.String("Use the timestamp tool to save a timestamp for August 7th 2025 at 10AM.")}, Tools: []responses.ToolUnionParam{tool}, }) if err != nil { panic(err) } fmt.Println(response.Output)}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27import com.openai.client.OpenAIClient;import com.openai.client.okhttp.OpenAIOkHttpClient;import com.openai.models.CustomToolInputFormat;import com.openai.models.responses.CustomTool;import com.openai.models.responses.ResponseCreateParams;String grammar = "^(January|February|March|April|May|June|July|August|September|October|November|December) " + "\\d{1,2}(st|nd|rd|th)? \\d{4} at (0?[1-9]|1[0-2])(AM|PM)$";ResponseCreateParams params = ResponseCreateParams.builder() .model("gpt-6-astra") .input("Use timestamp to save August 7th 2025 at 10AM.") .addTool( CustomTool.builder() .name("timestamp") .description("Saves a timestamp in date and time format.") .format( CustomToolInputFormat.Grammar.builder() .syntax(CustomToolInputFormat.Grammar.Syntax.REGEX) .definition(grammar) .build()) .build()) .build();client.responses().create(params).output().forEach(System.out::println);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22require "openai"client = OpenAI::Client.newgrammar = "^(January|February|March|April|May|June|July|August|September|October|November|December) \\d{1,2}(st|nd|rd|th)? \\d{4} at (0?[1-9]|1[0-2])(AM|PM)$"response = client.responses.create( model: "gpt-6-astra", input: "Use timestamp to save August 7th 2025 at 10AM.", tools: [ { type: :custom, name: "timestamp", description: "Saves a timestamp in date and time format.", format: { type: :grammar, syntax: :regex, definition: grammar } } ])puts(response.output)
Die Ausgabe des Tools sollte dann der von dir definierten Regex-CFG entsprechen:
Wenn du einen Zeilenumbruch in der Eingabe erkennen musst, verwende die Escape-Sequenz \n. Verwende nicht den Verbose-/Extended-Modus, der mehrzeilige Muster erlaubt.
Gib den regulären Ausdruck als einfache Zeichenfolge mit dem Muster an