Function calling (juga disebut tool calling atau penggunaan tool) adalah cara memberi model akses ke kode Anda. Anda mendeskripsikan fungsi seperti "mencari pesanan" atau "menghitung tarif pengiriman". Model menentukan fungsi mana yang akan dipanggil dan dengan argumen apa; kode Anda menjalankannya dan mengirimkan kembali hasilnya. Setiap agent, mulai dari bot dukungan toko hingga Claude Code, dibangun berdasarkan loop ini.
Di GetVibe API, function calling bekerja melalui endpoint standar /v1/chat/completions dalam format OpenAI dan melalui /v1/messages dalam format Anthropic. Di bawah ini adalah loop lengkap yang kami jalankan pada tiga model dari tiga pembuat yang berbeda.
Cara kerja loop
- Anda mengirim messages beserta daftar
tools. Setiap tool memiliki nama, deskripsi, dan JSON Schema untuk parameternya. - Alih-alih teks, model mengembalikan
tool_calls: fungsi yang harus dipanggil dan argumennya.finish_reasonbernilaitool_calls. - Kode Anda menjalankan fungsi-fungsi tersebut dan menambahkan satu message dengan role
tooluntuk setiap pemanggilan, dengan membawatool_call_idyang sama. - Anda mengirim ulang history tersebut. Model kemudian meminta pemanggilan tambahan atau menjawab pengguna dalam bentuk teks.
Model tidak pernah menjalankan apa pun sendiri. Model hanya meminta pemanggilan. Apa yang benar-benar dijalankan dan dengan izin apa ditentukan oleh kode Anda.
Contoh lengkap: asisten dukungan toko
Dua fungsi: status pesanan dan tarif pengiriman. Pengguna menanyakan keduanya sekaligus, dan model memanggil kedua fungsi dalam satu turn.
import json
import os
from openai import OpenAI
client = OpenAI(base_url="https://getvibeapi.com/v1", api_key=os.environ["GETVIBE_API_KEY"])
MODEL = "gpt-6-luna"
def get_order_status(order_id: str) -> dict:
# pencarian di database atau CRM Anda dilakukan di sini
return {"order_id": order_id, "status": "out for delivery", "eta": "2026-10-24"}
def get_shipping_quote(zip_code: str) -> dict:
return {"zip_code": zip_code, "price_usd": 7.5, "days": 2}
TOOLS = [
{"type": "function", "function": {
"name": "get_order_status",
"description": "Look up an order by its ID",
"parameters": {"type": "object",
"properties": {"order_id": {"type": "string", "description": "Order ID, e.g. A-1042"}},
"required": ["order_id"]}}},
{"type": "function", "function": {
"name": "get_shipping_quote",
"description": "Courier shipping price and delivery time to a US ZIP code",
"parameters": {"type": "object",
"properties": {"zip_code": {"type": "string"}},
"required": ["zip_code"]}}},
]
FUNCTIONS = {"get_order_status": get_order_status, "get_shipping_quote": get_shipping_quote}
messages = [
{"role": "system", "content": "Anda adalah asisten dukungan toko. Jawab dengan singkat."},
{"role": "user", "content": "Di mana pesanan saya A-1042? Dan berapa biaya pengiriman ke 94110?"},
]
for _ in range(5): # batasi jumlah putaran
resp = client.chat.completions.create(model=MODEL, messages=messages, tools=TOOLS)
msg = resp.choices[0].message
if not msg.tool_calls:
print(msg.content)
break
messages.append(msg.model_dump(exclude_none=True))
for call in msg.tool_calls:
args = json.loads(call.function.arguments)
result = FUNCTIONS[call.function.name](**args)
messages.append({"role": "tool", "tool_call_id": call.id, "content": json.dumps(result)})
Kami menjalankan kode ini tanpa perubahan pada gpt-6-luna, deepseek-v4.1-flash, dan claude-haiku-5.5, dengan hanya mengubah MODEL. Pada putaran pertama, ketiganya memanggil kedua fungsi: get_order_status dengan A-1042 dan get_shipping_quote dengan 94110. Pada putaran kedua, ketiganya menjawab dalam bentuk teks dengan status pengiriman, ETA, harga 7.50, dan waktu pengiriman dua hari.
Hal penting dalam kode ini
- Tambahkan message tool-call dari model ke history secara lengkap. Tanpanya, message
toolAnda menjawab pemanggilan yang tidak dapat dilihat model, dan banyak model akan memanggil fungsi yang sama lagi, sehingga loop terus berputar. - Satu message
tooluntuk setiap pemanggilan, dengantool_call_idyang sesuai. Model dapat meminta beberapa pemanggilan sekaligus, seperti yang terjadi di sini. - Argumen diterima sebagai string.
argumentsadalah JSON di dalam sebuah string. Parse dan validasikan, karena model dapat memberikan nilai yang salah. - Batasi jumlah putaran. Tanpa batas, bug dalam suatu fungsi dapat mengubah loop menjadi loop tanpa akhir, sekaligus menghasilkan tagihan token tanpa akhir.
tool_choice: kapan pemanggilan wajib dilakukan
Secara default, model menentukan apakah akan memanggil tool atau menjawab dalam bentuk teks ("auto"). tool_choice mengubah perilaku tersebut:
"none"— jangan pernah memanggil tool;"required"— panggil setidaknya satu tool;{"type": "function", "function": {"name": "..."}}— panggil fungsi tertentu ini.
Bentuk terakhir berguna untuk ekstraksi data. Schema parameter fungsi menjadi bentuk jawaban:
curl https://getvibeapi.com/v1/chat/completions \
-H "Authorization: Bearer $GETVIBE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-v4.1-flash",
"messages": [{"role": "user", "content": "Jane Doe, [email protected], ingin demo pada hari Kamis"}],
"tools": [{
"type": "function",
"function": {
"name": "save_lead",
"description": "Save a sales lead to the CRM",
"parameters": {
"type": "object",
"properties": {"name": {"type": "string"}, "email": {"type": "string"}, "request": {"type": "string"}},
"required": ["name", "email", "request"]
}
}
}],
"tool_choice": {"type": "function", "function": {"name": "save_lead"}}
}'
Responsnya adalah pemanggilan save_lead dengan name "Jane Doe", email "[email protected]", dan request "Ingin demo pada hari Kamis".
Satu catatan: beberapa model Claude, termasuk Claude Sonnet 5.5 dan Claude Opus 5.5, tidak menerima tool choice yang dipaksakan. GetVibe mengubah permintaan tersebut menjadi auto dengan tools yang sama, sehingga Anda mendapatkan jawaban alih-alih error, tetapi model kemudian menentukan sendiri apakah akan melakukan pemanggilan. Untuk JSON strict dari model-model tersebut, gunakan structured outputs.
Format Anthropic: /v1/messages
Dengan Anthropic SDK, tools terlihat sedikit berbeda: schema parameter ditempatkan di input_schema, dan pemanggilan dikembalikan sebagai content block tool_use.
curl https://getvibeapi.com/v1/messages \
-H "x-api-key: $GETVIBE_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-haiku-5.5",
"max_tokens": 512,
"tools": [{
"name": "get_order_status",
"description": "Look up an order by its ID",
"input_schema": {"type": "object", "properties": {"order_id": {"type": "string"}}, "required": ["order_id"]}
}],
"messages": [{"role": "user", "content": "Di mana pesanan A-1042?"}]
}'
Respons memiliki stop_reason tool_use dan block tool_use yang memanggil get_order_status dengan order_id A-1042. Anda mengirimkan hasilnya kembali sebagai block tool_result dalam user message berikutnya, dengan tool_use_id yang sama.
Model mana yang digunakan untuk tools
- Bot bervolume tinggi dan tools sederhana — DeepSeek V4.1 Flash ($0.0112 input · $0.0445 output per 1 juta token) atau Claude Haiku 5.5 ($0.0267 input · $0.1334 output per 1 juta token).
- Agent dengan banyak tools dan rencana panjang — GPT-6 Luna ($0.0055 input · $0.0274 output per 1 juta token) atau Claude Sonnet 5.5.
Loop agent mengirim ulang prefix panjang yang sama pada setiap putaran, jadi prompt caching sangat penting di sini. Detail lebih lanjut tentang field request tersedia di dokumentasi tool calling.
