Belajar AI Engineer - Structured Output & Tool Use
Episode 5 of 28

Belajar AI Engineer - Structured Output & Tool Use

Membuat output model dapat dipakai mesin: JSON mode, structured output, dan function calling. Kalian membangun agent pertama yang bisa memanggil tools, memahami kapan output bebas vs terstruktur, serta pola loop tool-calling yang menjadi dasar agentic systemstype: text

AI Agent
AI AgentAugust 16, 2026
0 views
3 min read

Pendahuluan

Di episode 4 kalian mengandalkan prompt untuk mengarahkan format jawaban model — pendekatan yang rapuh di produksi. Episode ini mengganti fondasi itu dengan mekanisme bawaan API: structured output dan tool use (function calling). Dua fitur inilah yang mengubah LLM dari mesin tulis teks menjadi komponen yang bisa diintegrasikan ke sistem.

Mengapa episode ini penting? Karena produk AI nyata tidak menampilkan teks mentah ke pengguna — mereka memproses hasilnya: menyimpan ke database, memicu action, atau mengisi UI. Tanpa output terstruktur, kalian akan menghabiskan waktu men-parse teks bebas dengan regex yang rapuh. Tanpa function calling, kalian tidak akan bisa membangun agent (episode 11).

Kapan Perlu Output Terstruktur

SituasiPendekatan yang Tepat
Jawaban bebas untuk dibaca manusiaTeks biasa
Ekstraksi data, isi form, output ke DBJSON mode / structured output
Menentukan satu tindakan dari daftar opsiTool calling
Flow multi-langkah dengan keputusanTool calling + loop

Aturannya sederhana: jika hasilnya akan diproses kode, jadikan terstruktur. Teks bebas adalah perangkap — satu perubahan format model membuat parser kalian rusak.

JSON Mode dan Structured Output

Semua penyedia LLM besar punya mode JSON. Dengan pydantic, kalian mendefinisikan skema dan model mengikuti skema tersebut:

PythonStructured output dengan pydantic
from typing import Literal
from pydantic import BaseModel
from openai import OpenAI
 
client = OpenAI()
 
class Transaksi(BaseModel):
    jenis: Literal["belanja", "pemasukan", "transfer"]
    nominal: int
    keterangan: str
 
r = client.beta.chat.completions.parse(
    model="gpt-4o-mini",
    messages=[
        {"role": "system", "content": "Ekstrak transaksi dari teks pengguna."},
        {"role": "user", "content": "Tadi siang transfer ke Rina 150 ribu buat utang."},
    ],
    response_format=Transaksi,
)
 
tx = r.choices[0].message.parsed
print(tx.jenis, tx.nominal, tx.keterangan)

Keuntungannya besar: skema divalidasi otomatis, tipe data aman (int, enum), dan tidak ada parsing manual. Ini adalah cara modern mengganti few-shot + regex dari episode 4.

Important

Structured output memastikan format valid, tetapi tidak menjamin isi benar. Model bisa menghasilkan JSON yang sesuai skema dengan nilai yang keliru secara faktual. Validasi konten tetap tanggung jawab kalian (episode 9 dan 19).

Function Calling: Memberi Model "Tangan"

Tool calling adalah kemampuan model untuk memilih dan meminta pemanggilan fungsi yang kalian definisikan. Model tidak mengeksekusi fungsi — ia hanya mengembalikan argumen; kalian yang mengeksekusinya lalu mengirim balik hasilnya.

PythonDefinisikan tools
import json
from openai import OpenAI
 
client = OpenAI()
 
TOOLS = [{
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "Cek cuaca sebuah kota.",
        "parameters": {
            "type": "object",
            "properties": {
                "city": {"type": "string", "description": "Nama kota"}
            },
            "required": ["city"],
        },
    },
}]
 
def get_weather(city: str) -> str:
    return json.dumps({"city": city, "suhu": "32C", "kondisi": "cerah"})

Sekarang jalankan loop tool-calling — pola yang menjadi jantung semua agent:

PythonLoop tool-calling
messages = [{"role": "user", "content": "Cuaca hari ini di Bandung gimana?"}]
 
for _ in range(5):
    r = client.chat.completions.create(
        model="gpt-4o-mini", messages=messages, tools=TOOLS
    )
    msg = r.choices[0].message
    if msg.tool_calls:
        messages.append(msg)
        for call in msg.tool_calls:
            if call.function.name == "get_weather":
                result = get_weather(json.loads(call.function.arguments)["city"])
            messages.append({
                "role": "tool",
                "tool_call_id": call.id,
                "content": result,
            })
    else:
        print(msg.content)
        break

Alurnya: model meminta get_weather dengan argumen {"city": "Bandung"}, kalian mengeksekusi, lalu mengembalikan hasil sebagai pesan ber-role tool. Loop berhenti saat model memberi jawaban final. Ini adalah ReAct tanpa label — dan akan kita perluas menjadi agent sungguhan di episode 11.

Menangani Error dan Fallback

Tool call bisa gagal di lapisan nyata: API eksternal down, argumen aneh, atau timeout. Pola yang benar: kembalikan pesan error ke model sebagai hasil tool, bukan langsung melempar exception:

PythonTool dengan error handling
def get_weather(city: str) -> str:
    try:
        result = cuaca_api(city)  # placeholder
        return json.dumps(result)
    except Exception as e:
        return json.dumps({"error": str(e), "city": city})

Dengan pola ini, model bisa memutuskan sendiri: mencoba kota lain, meminta klarifikasi, atau memberi jawaban parsial. Inilah sumber robustness agent — topik kita dalami di episode 25.

Common Pitfalls

  • Tool description ditulis asal: deskripsi tool adalah "petunjuk pemakaian" bagi model. Deskripsi yang jelek membuat model salah memilih tool.
  • Menjalankan tool tanpa otorisasi: tool yang menulis DB atau mengirim email harus punya lapisan konfirmasi & izin (episode 18, 20).
  • Loop tanpa batas: selalu pasang maksimum iterasi (di contoh: 5) agar agent tidak berputar selamanya.
  • Mengabaikan argumen: validasi argumen tool sebelum eksekusi — model bisa menghasilkan argumen yang tidak valid.

Penutup

Inti yang harus dibawa pulang:

  • Output yang akan diproses kode wajib terstruktur: JSON mode / structured output + pydantic.
  • Function calling: model memilih fungsi, kalian mengeksekusi, hasilnya dikembalikan dengan role tool.
  • Loop tool-calling = fondasi agent; selalu batasi iterasi dan tangani error di dalam hasil tool.
  • Deskripsi tool yang baik = antarmuka yang baik bagi model.

Di episode 6 selanjutnya kita membangun kemampuan knowledge: embeddings & vector database — mengubah teks menjadi vektor, mencari dengan kesamaan semantik, dan menyiapkan pipeline embeddings untuk RAG. Sampai jumpa di episode 6!

Belajar AI Engineer - Structured Output & Tool Use | Belajar AI Engineer