Public preview — Deze API is in public preview. Endpoints, schemas en limieten kunnen wijzigen vóór general availability.
API
Tools gebruiken
Een end-to-end-voorbeeld van een model dat naar web_search grijpt en hoe je dat rendert in je UI.
Tools draaien server-side en duiken op via de stream. Er is niets per request te configureren — het model beslist, het platform draait, jij kijkt mee.
Deze gids loopt één realistisch voorbeeld door: een vraag waarbij het model het web moet doorzoeken en bronnen moet citeren.
De request#
const stream = await client.responses.create({
model: "auto",
input: "What was Apple's revenue in Q4 2025? Cite your source.",
stream: true,
});
Het model heeft geen interne kennis van de resultaten van dat kwartaal. Het zal web_search aanroepen.
De event-sequence#
Je ontvangt events ongeveer in deze volgorde (sequence numbers tussen haakjes zijn illustratief):
(0) response.created
(1) response.output_item.added function_call "web_search" begins
(2) response.output_item.done function_call "web_search" completes with results
(3) response.content_part.added assistant text begins
(4) response.output_text.delta "Apple"
(5) response.output_text.delta " reported"
(...) more deltas
(N) response.output_text.done full text assembled
(N+1) response.completed
Meerdere tool calls kunnen interleaven — het model kan ook web_fetch aanroepen op een result-URL voordat het antwoordt. Gebruik output_index om ze gescheiden te houden.
Renderen#
Een redelijk chat-UI-patroon:
const state = {
tools: new Map(), // call_id -> { name, status, summary }
text: "",
};
for await (const event of stream) {
switch (event.type) {
case "response.output_item.added":
if (event.item.type === "function_call") {
state.tools.set(event.item.call_id, {
name: event.item.name,
status: "running",
});
render();
}
break;
case "response.output_item.done":
if (event.item.type === "function_call") {
const tool = state.tools.get(event.item.call_id);
if (tool) {
tool.status = event.item.status;
tool.summary = summarise(event.item.output);
}
render();
}
break;
case "response.output_text.delta":
state.text += event.delta;
render();
break;
case "response.completed":
// klaar
break;
}
}
Render de tool-pills (één per call_id) boven of naast de text. Update ze ter plekke wanneer ze overgaan van running naar completed.
De tool-output-shape#
Het output-veld op output_item.done is een string. Voor web_search en web_fetch is het een JSON-gecodeerde structuur. Je kunt het parsen als je de resultaten visueel wilt surface’n:
const tool = event.item;
if (tool.name === "web_search" && tool.status === "completed") {
const hits = JSON.parse(tool.output); // [{ title, url, snippet }, ...]
renderHits(hits);
}
Voor calculator is het het numerieke resultaat als string. Voor current_datetime is het een ISO 8601-timestamp.
Tools uitschakelen voor een request#
Er is vandaag geen per-request “geen tools”-vlag. De beste hefboom is het instructions-veld:
instructions: "Answer from your own training data only. Do not use web_search or web_fetch."
Het model voldoet meestal. Voor absolute controle: draai prompts die duidelijk niet kunnen profiteren van tools (bv. samenvatting van input die de gebruiker zelf gaf) — het model zal niet speculatief tools aanroepen.
Tool-failures#
Als een tool mid-uitvoering faalt, ontvang je response.output_item.done met status: "failed" en een beschrijving in output. Het model handelt dit af — het zal óf:
- De tool retryen met andere argumenten (je ziet dan opnieuw
output_item.addedvoor dezelfde tool-naam). - Excuseren en antwoorden zonder de tool.
- Een andere tool kiezen.
Je UI zou “search failed” gracefully moeten surface’n — de meeste gebruikers verkiezen “Ik kon niet zoeken op het web, dus dit is wat ik weet” boven een stille afwezigheid van citations.
Alles samenvoegen#
Een minimaal end-to-end-script dat naar de terminal streamt en tool-activiteit inline print:
import OpenAI from "openai";
const client = new OpenAI({
apiKey: process.env.EUGPT_API_KEY,
baseURL: "https://chat.eugpt.ai/v1",
});
const stream = await client.responses.create({
model: "auto",
input: "What's the latest news on the EU AI Act enforcement?",
stream: true,
});
for await (const event of stream) {
switch (event.type) {
case "response.output_item.added":
if (event.item.type === "function_call") {
process.stderr.write(`\n[tool] ${event.item.name} …`);
}
break;
case "response.output_item.done":
if (event.item.type === "function_call") {
process.stderr.write(` (${event.item.status})\n`);
}
break;
case "response.output_text.delta":
process.stdout.write(event.delta);
break;
case "response.completed":
process.stdout.write("\n");
break;
}
}