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.