Pemanggilan fungsi: perbandingan Responses API dan Chat Completions
Perbandingan tingkat protokol untuk definisi fungsi, ID panggilan, hasil, argumen yang dialirkan, otorisasi, idempotensi, dan kompatibilitas jalur.

Responses dan Chat Completions sama-sama dapat meminta aplikasi menjalankan fungsi, tetapi merepresentasikan siklus alat secara berbeda. Chat Completions mendefinisikan fungsi di tools[].function, mengembalikan message.tool_calls, dan menerima hasil sebagai pesan role: "tool". Responses menggunakan definisi datar, item keluaran bertipe function_call, dan function_call_output yang dihubungkan oleh call_id.
Model tidak menjalankan fungsi aplikasi. Kode Anda harus memvalidasi argumen, mengotorisasi operasi, menjalankannya, mengembalikan hasil, dan mencegah efek samping ganda saat permintaan dicoba kembali.
Empat langkah siklus alat
1. Deklarasikan fungsi yang diizinkan beserta skema argumennya
2. Terima satu atau beberapa panggilan fungsi yang diusulkan model
3. Validasi, otorisasi, dan eksekusi di aplikasi
4. Kembalikan hasil menggunakan ID korelasi setiap panggilan
Model baru dapat menghasilkan jawaban berdasarkan hasil alat setelah langkah keempat. Alat berikutnya memulai iterasi dengan ID panggilan baru. Panduan OpenAI Function Calling menjelaskannya sebagai pertukaran bertahap.
Bandingkan kontrak transport
| Aspek | Responses API | Chat Completions |
|---|---|---|
| Definisi | Item datar di tools[] |
Bidang di tools[].function |
| Panggilan dari model | Item keluaran function_call |
tool_calls[] pada pesan asisten |
| Korelasi | call_id |
id, hasil memakai tool_call_id |
| Nama | function_call.name |
tool_calls[].function.name |
| Argumen | String JSON di function_call.arguments |
String JSON di tool_calls[].function.arguments |
| Hasil | function_call_output |
Pesan role: "tool" |
| Streaming | Peristiwa argumen bertipe | Fragmen delta.tool_calls[] |
| Teks akhir | Item keluaran / fungsi bantu SDK | choices[0].message.content |
Jangan hubungkan panggilan berdasarkan posisi larik. Panggilan paralel dan fragmen dapat selesai dalam urutan berbeda. ID panggilan yang eksplisit adalah kunci penghubung yang stabil.
Definisikan skema fungsi yang ketat
{
"type": "object",
"properties": {
"order_id": {
"type": "string",
"pattern": "^ORDER-[0-9]{4}$"
}
},
"required": ["order_id"],
"additionalProperties": false
}
strict: true meminta model mengikuti skema, tetapi aplikasi tetap harus menguraikan dan memvalidasi argumen. Dukungan pattern berbeda di setiap penyedia, sehingga gunakan pemeriksaan kompatibilitas yang sama dengan Structured Outputs.
Implementasi dengan Responses API
import OpenAI from "openai";
const client = new OpenAI({
apiKey: process.env.MODELFLARE_API_KEY,
baseURL: "https://modelflare.dev/v1",
});
const model = process.env.MODEL_ID;
if (!model) throw new Error("MODEL_ID wajib diisi");
const orders = new Map([
["ORDER-1001", { status: "in_transit", eta: "2026-08-06" }],
]);
const tools = [
{
type: "function",
name: "get_delivery_status",
description: "Mengembalikan status pengiriman terkini untuk satu pesanan.",
parameters: {
type: "object",
properties: {
order_id: { type: "string", pattern: "^ORDER-[0-9]{4}$" },
},
required: ["order_id"],
additionalProperties: false,
},
strict: true,
},
];
function executeTool(name, rawArguments) {
if (name !== "get_delivery_status") {
throw new Error(`Alat tidak diizinkan: ${name}`);
}
const args = JSON.parse(rawArguments);
if (!/^ORDER-[0-9]{4}$/.test(args.order_id)) {
throw new Error("order_id tidak valid");
}
return orders.get(args.order_id) ?? { status: "not_found" };
}
const first = await client.responses.create({
model,
input: "Di mana pesanan ORDER-1001?",
tools,
parallel_tool_calls: false,
});
const calls = first.output.filter((item) => item.type === "function_call");
if (calls.length === 0) {
console.log(first.output_text);
process.exit(0);
}
const toolOutputs = 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, ...toolOutputs],
tools,
parallel_tool_calls: false,
});
console.log(final.output_text);
call.call_id harus sama dengan call_id hasil. Dalam pertukaran tanpa status, item keluaran sebelumnya dikirim kembali bersama hasil. Jangan mengasumsikan semua rute yang kompatibel dengan OpenAI menyimpan status respons.
Implementasi dengan Chat Completions
import OpenAI from "openai";
const client = new OpenAI({
apiKey: process.env.MODELFLARE_API_KEY,
baseURL: "https://modelflare.dev/v1",
});
const model = process.env.MODEL_ID;
if (!model) throw new Error("MODEL_ID wajib diisi");
const orders = new Map([
["ORDER-1001", { status: "in_transit", eta: "2026-08-06" }],
]);
const tools = [
{
type: "function",
function: {
name: "get_delivery_status",
description: "Mengembalikan status pengiriman terkini untuk satu pesanan.",
parameters: {
type: "object",
properties: {
order_id: { type: "string", pattern: "^ORDER-[0-9]{4}$" },
},
required: ["order_id"],
additionalProperties: false,
},
strict: true,
},
},
];
function executeTool(name, rawArguments) {
if (name !== "get_delivery_status") {
throw new Error(`Alat tidak diizinkan: ${name}`);
}
const args = JSON.parse(rawArguments);
if (!/^ORDER-[0-9]{4}$/.test(args.order_id)) {
throw new Error("order_id tidak valid");
}
return orders.get(args.order_id) ?? { status: "not_found" };
}
const messages = [
{ role: "user", content: "Di mana pesanan ORDER-1001?" },
];
const first = await client.chat.completions.create({
model,
messages,
tools,
parallel_tool_calls: false,
});
const assistant = first.choices[0].message;
const calls = assistant.tool_calls ?? [];
if (calls.length === 0) {
console.log(assistant.content);
process.exit(0);
}
messages.push(assistant);
for (const call of calls) {
const result = executeTool(call.function.name, call.function.arguments);
messages.push({
role: "tool",
tool_call_id: call.id,
content: JSON.stringify(result),
});
}
const final = await client.chat.completions.create({
model,
messages,
tools,
parallel_tool_calls: false,
});
console.log(final.choices[0].message.content);
Pesan asisten yang memuat panggilan harus ditambahkan sebelum hasil alat. Pesan yang hilang atau tool_call_id yang tidak cocok membuat riwayat percakapan tidak valid.
Perlakukan argumen streaming sebagai fragmen
{"order adalah JSON yang belum lengkap, bukan JSON tidak valid. Simpan penyangga per panggilan, tambahkan setiap perubahan, tunggu hingga argumen atau respons selesai, uraikan string lengkap satu kali, lalu validasi dan jalankan. Responses memakai peristiwa bertipe; Chat Completions memakai choices[].delta.tool_calls[]. Jangan menjalankan fungsi pada fragmen pertama. Lihat Panduan Streaming AI API.
Buat eksekusi aman dan idempoten
- izinkan hanya nama fungsi yang terdaftar;
- batasi ukuran dan validasi skema lengkap;
- otorisasi pengguna atau beban kerja untuk mengakses sumber daya;
- pisahkan alat baca-saja dari alat yang memiliki efek samping;
- hapus rahasia dari hasil;
- tetapkan tenggat dan batasi percobaan ulang ke layanan dependen;
- simpan referensi operasi yang aman.
Untuk efek samping, buat kunci idempotensi dari permintaan aplikasi yang stabil dan ID panggilan. Simpan hasil sebelum mengembalikannya. Percobaan ulang harus mengembalikan hasil tersimpan, bukan menjalankan pengembalian dana, pesan, deployment, atau perubahan basis data untuk kedua kalinya.
Nama fungsi dan argumen dari model adalah masukan yang tidak tepercaya. Skema valid tidak memberi izin dan tidak menggantikan batas transaksi.
Tentukan cara menangani beberapa panggilan
parallel_tool_calls: false menyederhanakan mesin status. Jika mode paralel diaktifkan, hubungkan hasil dengan ID panggilan, batasi jumlah dan konkurensi, tentukan dampak kegagalan, kembalikan satu hasil per panggilan, dan jalankan secara berurutan efek samping yang bergantung pada urutan. Mode paralel mempercepat pembacaan independen, tetapi memperumit otorisasi, percobaan ulang, dan kegagalan sebagian.
Pahami batas kompatibilitas Modelflare
Modelflare mempertahankan definisi fungsi yang ketat dan memetakan bentuk panggilan yang didukung antara Responses dan Chat Completions pada rute OpenAI/Codex yang memenuhi syarat. Pemetaan ini sengaja lebih sempit daripada seluruh kemampuan alat di Responses.
Fungsi yang ditentukan aplikasi dapat direpresentasikan dalam kedua format. Alat terkelola seperti pencarian atau eksekusi kode yang dijalankan penyedia tidak ekuivalen. Untuk keluarga lain yang kompatibel dengan OpenAI, Chat Completions diteruskan tanpa transformasi sampai diverifikasi; kontrak penyedia menentukan dukungan tools, strict, panggilan paralel, argumen streaming, dan tool_choice.
| Pengujian | Bukti wajib |
|---|---|
| Panggilan baca-saja | Nama, argumen, ID panggilan, hubungan hasil, teks akhir |
| Argumen tidak valid | Kesalahan eksplisit tanpa eksekusi |
| Fungsi tidak dikenal | Ditolak oleh daftar yang diizinkan |
| Tanpa alat | Teks normal tanpa panggilan palsu |
| Streaming | Argumen lengkap dan ID benar |
| Permintaan berulang | Satu efek samping atau hasil tersimpan |
| Beberapa panggilan | Hubungan tidak bergantung pada urutan selesai |
| Rute cadangan | Model, protokol, skema, dan kontrak yang sama |
Gunakan Perutean AI API yang Andal agar perubahan rute eksplisit dan Keamanan Kunci AI API untuk memisahkan beban kerja dan izin.
Pilih format sesuai kontrak aplikasi
Gunakan Responses untuk item keluaran bertipe, model peristiwa, kelanjutan status, atau kemampuan Responses yang telah diverifikasi. Gunakan Chat Completions bila aplikasi memiliki riwayat pesan yang stabil dan kontrak alat penyedia telah diuji. Lihat Responses API dan Chat Completions.
Standarnya sama: daftar alat yang diizinkan secara eksplisit, skema argumen yang ketat, validasi aplikasi, otorisasi sebelum eksekusi, hubungan dengan ID panggilan, idempotensi efek samping, dan hasil lengkap untuk model. Kontrol ini, bukan nama endpoint, membuat alur kerja andal.