Kami menggunakan cookie. Cookie dan penyimpanan browser menjaga Anda tetap masuk dan mengingat preferensi Anda. Dengan izin Anda, kami juga mengukur cara situs digunakan. Anda dapat kapan saja. Lihat kebijakan cookie kami.

Panduan: agen tool-calling

Memulai

Panduan: agen tool-calling

Bangun loop agen dengan panggilan tool paralel, batas langkah, structured output, dan kontrol biaya memakai format tools OpenAI di api14.

Agen adalah sebuah loop: model membaca percakapan, memutuskan memanggil satu atau lebih tool Anda, Anda menjalankannya dan mengirim hasilnya kembali, lalu model melanjutkan sampai bisa menjawab. api14 mendukung ini dengan format tools OpenAI pada setiap model yang mampu memakai tool, sehingga kode yang sama bekerja dengan OpenAI, Anthropic, Google, dan provider lain hanya dengan mengganti ID model.

Panduan ini membangun agen kecil dengan batas langkah, eksekusi tool paralel, jawaban akhir terstruktur, dan kontrol biaya. Kode memakai paket openai resmi dengan base URL https://api14.com/api/v1.

Mendefinisikan tool

Setiap tool terdiri dari nama, deskripsi yang dibaca model, dan JSON Schema untuk argumennya. Buat deskripsi spesifik; itulah satu-satunya dokumentasi bagi model.

import json, os
from openai import OpenAI

client = OpenAI(base_url="https://api14.com/api/v1", api_key=os.environ["API14_API_KEY"])

def search_orders(customer_email: str) -> list:
    return [{"id": "A-1001", "status": "shipped"}]  # your database query

def get_shipment(order_id: str) -> dict:
    return {"order_id": order_id, "carrier": "UPS", "eta": "2026-10-09"}  # your API call

TOOLS = {"search_orders": search_orders, "get_shipment": get_shipment}

tools = [
    {"type": "function", "function": {
        "name": "search_orders",
        "description": "List a customer's orders with their status.",
        "parameters": {"type": "object", "properties": {"customer_email": {"type": "string"}},
                       "required": ["customer_email"]},
    }},
    {"type": "function", "function": {
        "name": "get_shipment",
        "description": "Carrier and estimated delivery date for one order.",
        "parameters": {"type": "object", "properties": {"order_id": {"type": "string"}},
                       "required": ["order_id"]},
    }},
]

Loop dengan batas langkah

Setiap iterasi adalah request terpisah yang ditagih, jadi selalu batasi jumlah langkah. Kembalikan error tool ke model sebagai konten alih-alih membuat program crash; model biasanya pulih dengan memperbaiki argumen.

MAX_STEPS = 8

def run_tool(call):
    try:
        args = json.loads(call.function.arguments)
        result = TOOLS[call.function.name](**args)
    except Exception as e:  # bad JSON, unknown tool, or your function failed
        result = {"error": str(e)}
    return {"role": "tool", "tool_call_id": call.id, "content": json.dumps(result)}

def agent(task, model="openai/gpt-5-mini"):
    messages = [
        {"role": "system", "content": "You are a support agent. Use tools to look things up. Be brief."},
        {"role": "user", "content": task},
    ]
    spent = 0.0
    for step in range(MAX_STEPS):
        r = client.chat.completions.create(model=model, messages=messages, tools=tools, max_tokens=1000)
        spent += r.usage.cost
        msg = r.choices[0].message
        if not msg.tool_calls:
            return msg.content, spent
        messages.append(msg)
        messages.extend(run_tool(call) for call in msg.tool_calls)
    raise RuntimeError(f"No answer after {MAX_STEPS} steps (spent ${spent:.4f})")

print(agent("Where is my order? My email is ada@example.com"))

Kirim tools pada setiap request dalam loop. Banyak provider menolak pesan tool ketika request tidak memiliki definisi tool.

Panggilan tool paralel

Dengan parallel_tool_calls (aktif secara default jika didukung), model dapat meminta beberapa panggilan dalam satu giliran, misalnya get_shipment untuk tiga pesanan. Jalankan secara bersamaan dan tambahkan satu pesan tool per panggilan, dalam urutan apa pun; tool_call_id menghubungkan setiap hasil dengan panggilannya. Di Node:

import OpenAI from "openai";

const client = new OpenAI({ baseURL: "https://api14.com/api/v1", apiKey: process.env.API14_API_KEY });
const MAX_STEPS = 8;

async function agent(messages, tools, impl, model = "openai/gpt-5-mini") {
  for (let step = 0; step < MAX_STEPS; step++) {
    const res = await client.chat.completions.create({ model, messages, tools, max_tokens: 1000 });
    const msg = res.choices[0].message;
    if (!msg.tool_calls?.length) return msg.content;

    messages.push(msg);
    const results = await Promise.all(msg.tool_calls.map(async (call) => {
      let content;
      try {
        content = JSON.stringify(await impl[call.function.name](JSON.parse(call.function.arguments)));
      } catch (err) {
        content = JSON.stringify({ error: String(err) });
      }
      return { role: "tool", tool_call_id: call.id, content };
    }));
    messages.push(...results);
  }
  throw new Error(`No answer after ${MAX_STEPS} steps`);
}

Jika tool Anda memiliki efek samping yang harus terjadi berurutan (buat, lalu perbarui), atur parallel_tool_calls: false agar model meminta satu panggilan per giliran.

Keluaran akhir terstruktur

Saat jawaban agen dipakai oleh kode lain, minta JSON yang sesuai dengan skema. Pola sederhana dan portabel adalah satu panggilan tambahan setelah loop mengumpulkan fakta (messages di sini adalah percakapan dari loop; kembalikan dari agent() bersama jawabannya):

schema = {
    "type": "object",
    "properties": {
        "order_id": {"type": "string"},
        "status": {"type": "string", "enum": ["processing", "shipped", "delivered", "unknown"]},
        "eta": {"type": ["string", "null"]},
        "reply": {"type": "string"},
    },
    "required": ["order_id", "status", "eta", "reply"],
    "additionalProperties": False,
}

final = client.chat.completions.create(
    model="openai/gpt-5-mini",
    messages=messages + [{"role": "user", "content": "Summarize the result for our ticket system."}],
    tools=tools,
    tool_choice="none",
    response_format={"type": "json_schema", "json_schema": {"name": "ticket", "strict": True, "schema": schema}},
)
ticket = json.loads(final.choices[0].message.content)

tool_choice: "none" mempertahankan tools dalam request (diperlukan karena riwayat berisi pesan tool) sambil menghentikan panggilan lebih lanjut. Selalu validasi JSON hasil parsing. Lihat Structured outputs.

Memilih model

  • Kemampuan: model harus mencantumkan tools di supported_parameters. Periksa dengan GET /models, lihat Model. Untuk langkah akhir, cari structured_outputs atau response_format.
  • Routing: tambahkan provider: { "require_parameters": true } (di Python, lewat extra_body) agar request hanya dikirim ke provider yang mendukung setiap parameter yang Anda kirim. Lihat Provider routing.
  • Ukuran: model kecil seperti openai/gpt-5-mini menangani beberapa tool yang dideskripsikan dengan baik secara andal dan murah. Pindah ke model yang lebih besar ketika agen memiliki banyak tool, rencana multi-langkah yang panjang, atau terus memilih tool yang salah.
  • Uji dengan tool Anda: jalankan 20–50 tugas nyata yang sama pada dua atau tiga model kandidat dan bandingkan tingkat keberhasilan, langkah per tugas, dan total usage.cost.
curl -s "https://api14.com/api/v1/models?category=text" \
  | jq -r '.data[] | select(.supported_parameters | index("tools")) | "\(.id)  \(.pricing.prompt)"'

Mengontrol biaya

Agen dapat membuat banyak request untuk satu tugas, dan seluruh percakapan dikirim ulang di setiap langkah. Batasi pengeluaran di beberapa tingkat:

  • Batas langkah (MAX_STEPS) dan max_tokens per request, seperti di atas.
  • Anggaran per tugas: jumlahkan usage.cost di seluruh langkah dan berhenti saat melewati ambang Anda.
  • Hasil tool yang singkat: kembalikan hanya field yang dibutuhkan model. Output tool yang besar dibayar sebagai token input di setiap langkah berikutnya.
  • Batas USD harian per key: buat key khusus untuk agen di API key dan atur batas harian. Saat tercapai, request mengembalikan 429 daily_limit_reached sampai hari UTC berikutnya; tangani kode itu dengan menghentikan agen, bukan dengan mengulang.
  • Allowlist model: batasi key ke model yang telah Anda uji; selain itu mengembalikan 403 model_not_allowed.
  • Prompt caching: jaga system prompt dan definisi tool tetap identik dan berada di awal setiap request agar diskon prefiks cache berlaku. Lihat Prompt caching.

Lihat Tool calling, Batas laju, dan Error.