Function Calling: Responses API vs Chat Completions
Perbandingan Function Definition, Call ID, result, streaming arguments, authorization, idempotency, dan kompatibilitas route.
Responses dan Chat Completions sama-sama dapat meminta aplikasi menjalankan fungsi, tetapi merepresentasikan Tool Loop secara berbeda. Chat Completions mendefinisikan fungsi di tools[].function, mengembalikan message.tool_calls, dan menerima hasil sebagai pesan role: "tool". Responses menggunakan definisi flat, typed function_call output item, dan function_call_output yang dihubungkan oleh call_id.
Model tidak menjalankan fungsi aplikasi. Kode Anda harus memvalidasi arguments, mengotorisasi operasi, mengeksekusinya, mengembalikan hasil, dan mencegah side effect ganda saat retry.
Empat langkah Tool Loop
1. Deklarasikan fungsi yang diizinkan dan Argument Schema
2. Terima satu atau beberapa Function Call yang diusulkan model
3. Validasi, otorisasi, dan eksekusi di aplikasi
4. Kembalikan hasil menggunakan Correlation ID setiap Call
Model baru dapat menghasilkan jawaban berdasarkan Tool Result setelah langkah keempat. Tool berikutnya memulai iterasi dengan Call ID baru. Panduan OpenAI Function Calling menjelaskannya sebagai pertukaran multi-step.
Bandingkan Wire Contract
| Aspek | Responses API | Chat Completions |
|---|---|---|
| Definisi | Item flat di tools[] |
Field di tools[].function |
| Call dari model | function_call output item |
Assistant tool_calls[] |
| Korelasi | call_id |
id, hasil memakai tool_call_id |
| Nama | function_call.name |
tool_calls[].function.name |
| Arguments | JSON string di function_call.arguments |
JSON string di tool_calls[].function.arguments |
| Result | function_call_output |
Pesan role: "tool" |
| Streaming | Typed argument events | Fragment delta.tool_calls[] |
| Final text | Output items / helper | choices[0].message.content |
Jangan korelasikan berdasarkan posisi Array. Parallel Call dan chunk dapat selesai dalam urutan berbeda. Call ID eksplisit adalah join key yang stabil.
Definisikan Function Schema yang strict
{
"type": "object",
"properties": {
"order_id": { "type": "string", "pattern": "^ORDER-[0-9]{4}$" }
},
"required": ["order_id"],
"additionalProperties": false
}
strict: true meminta model mengikuti Schema, tetapi aplikasi tetap harus parse dan validate. Dukungan pattern berbeda per provider, sehingga gunakan gate yang sama dengan Structured Outputs.
Implementasi dengan Responses API
const tools = [{
type: "function",
name: "get_delivery_status",
description: "Return the current delivery status for one order.",
parameters: {
type: "object",
properties: { order_id: { type: "string", pattern: "^ORDER-[0-9]{4}$" } },
required: ["order_id"], additionalProperties: false,
},
strict: true,
}];
const first = await client.responses.create({
model, input: "Where is ORDER-1001?", tools, parallel_tool_calls: false,
});
const calls = first.output.filter(item => item.type === "function_call");
const outputs = calls.map(call => ({
type: "function_call_output",
call_id: call.call_id,
output: JSON.stringify(executeTool(call.name, call.arguments)),
}));
const final = await client.responses.create({
model, input: [...first.output, ...outputs], tools, parallel_tool_calls: false,
});
call.call_id harus sama dengan call_id hasil. Dalam exchange stateless, output item sebelumnya dikirim kembali bersama result. Jangan mengasumsikan semua route OpenAI-compatible menyimpan Response State.
Implementasi dengan Chat Completions
const tools = [{
type: "function",
function: {
name: "get_delivery_status",
description: "Return the current delivery status for one order.",
parameters: {
type: "object",
properties: { order_id: { type: "string", pattern: "^ORDER-[0-9]{4}$" } },
required: ["order_id"], additionalProperties: false,
},
strict: true,
},
}];
const first = await client.chat.completions.create({ model, messages, tools });
const assistant = first.choices[0].message;
messages.push(assistant);
for (const call of assistant.tool_calls ?? []) {
messages.push({
role: "tool",
tool_call_id: call.id,
content: JSON.stringify(executeTool(call.function.name, call.function.arguments)),
});
}
Assistant Message yang memuat Call harus ditambahkan sebelum Tool Result. Pesan yang hilang atau tool_call_id yang tidak cocok membuat transcript invalid.
Perlakukan Streaming Arguments sebagai fragment
{"order adalah JSON yang belum lengkap, bukan invalid. Simpan buffer per Call, tambahkan delta, tunggu Arguments Done atau Completed, parse string lengkap satu kali, lalu validate dan execute. Responses memakai typed events; Chat Completions memakai choices[].delta.tool_calls[]. Jangan menjalankan fungsi pada fragment pertama. Lihat Panduan AI API Streaming.
Buat eksekusi aman dan idempotent
- izinkan hanya Function Name terdaftar;
- batasi ukuran dan validasi Schema lengkap;
- otorisasi User atau Workload untuk resource;
- pisahkan Read-only Tool dan side effect;
- hapus secrets dari result;
- gunakan Deadline dan bounded downstream retry;
- simpan Operation Reference yang aman.
Untuk side effect, buat Idempotency Key dari stable application request dan Call ID. Simpan result sebelum mengembalikannya. Replay harus mengembalikan result tersimpan, bukan menjalankan refund, pesan, deployment, atau DB mutation kedua.
Function Name dan Arguments dari model adalah untrusted input. Schema valid tidak memberi izin dan tidak menggantikan transaction boundary.
Tentukan cara menangani Multiple Call
parallel_tool_calls: false menyederhanakan State Machine. Jika parallel diaktifkan, korelasikan dengan Call ID, batasi jumlah dan concurrency, definisikan dampak kegagalan, kembalikan satu result per Call, dan serialize side effect yang bergantung urutan. Parallel mempercepat pembacaan independen tetapi memperumit authorization, retry, dan partial failure.
Pahami batas kompatibilitas Modelflare
Modelflare mempertahankan strict function definition dan memetakan bentuk yang didukung antara Responses dan Chat Completions pada route OpenAI/Codex eligible. Mapping sengaja lebih sempit daripada seluruh Responses Tool Surface.
Application-defined Function dapat direpresentasikan di kedua format. Hosted Tool seperti search atau code execution dari provider tidak ekuivalen. Keluarga OpenAI-compatible lain tetap Raw Chat Completions Pass-through sampai diverifikasi; upstream menentukan tools, strict, parallel call, streaming arguments, dan tool_choice.
| Pengujian | Bukti wajib |
|---|---|
| Read-only Call | Nama, arguments, Call ID, result linkage, final text |
| Invalid Arguments | Error eksplisit tanpa eksekusi |
| Unknown Function | Ditolak allowlist |
| No Tool | Teks normal tanpa Call palsu |
| Streaming | Arguments lengkap dan ID benar |
| Repeated Request | Satu side effect atau cached result |
| Multiple Calls | Korelasi terlepas urutan selesai |
| Route Fallback | Model, protocol, Schema, contract sama |
Gunakan Reliable AI API Routing agar perubahan route eksplisit dan AI API Key Security untuk memisahkan Workload dan permission.
Pilih format sesuai kontrak aplikasi
Gunakan Responses untuk Typed Output Items, Event Model, State Continuation, atau kemampuan Responses terverifikasi. Gunakan Chat Completions bila aplikasi memiliki Message Transcript stabil dan Tool Contract provider telah diuji. Lihat Responses API vs Chat Completions.
Standarnya sama: Tool Allowlist eksplisit, Strict Argument Schema, validasi aplikasi, authorization sebelum execute, correlation dengan Call ID, idempotency side effect, dan result lengkap untuk model. Kontrol ini, bukan nama endpoint, membuat workflow andal.