Tampilan
1.2 Instructions yang Efektif
Kenapa bab ini penting
Instructions adalah satu-satunya tuas yang mengubah perilaku agent tanpa menulis kode baru. Ia juga bagian yang paling sering diremehkan, karena instruksi buruk tidak menghasilkan error — ia menghasilkan agent yang jawabannya berubah-ubah dan sulit ditebak.
Kalau kamu melewati bab ini: agent-mu akan bertanya balik saat seharusnya menjawab, menjawab panjang saat seharusnya ringkas, dan berperilaku berbeda antar pengguna tanpa kamu tahu sebabnya.
Kalau kamu tidak butuh bab ini: agent-mu hanya melayani satu jenis pertanyaan yang bentuknya selalu sama, dan kamu tidak peduli panjang jawabannya.
Eksperimen: satu pesan, tiga instruksi
Ini bukan contoh karangan. Ketiganya dijalankan sungguhan dengan openai/gpt-5-mini, pesan pengguna yang persis sama, dan hanya instructions yang berbeda.
Pesan pengguna — sengaja dibuat "malas", cuma daftar bahan tanpa pertanyaan:
text
ayam fillet 300g, brokoli, bawang putih, kecap asinVarian A — minimal
ts
instructions: 'Kamu asisten resep masakan.'Keluaran nyata:
text
Berikut resep cepat dan sederhana pakai bahan yang kamu sebutkan — Ayam
Fillet Tumis Brokoli dengan Bawang Putih dan Kecap Asin.
Porsi: 2 orang
Waktu: ~20–25 menit
Bahan
- Ayam fillet 300 g, potong dadu atau iris tipis
- Brokoli 200–250 g, potong kuntum kecil
- Bawang putih 2–3 siung, cincang halus
- Kecap asin 1–1½ sdm
[... 4 bahan lagi ...]
Langkah
1. Marinasi ayam: campur ayam dengan 1 sdm kecap asin...
[... 6 langkah lagi ...]
Tips
- Jangan overcook brokoli agar tetap renyah...
[... 3 tips lagi ...]
Saran penyajian: nasi putih hangat atau mi goreng sebagai lauk lengkap.
Mau saya buatkan versi bumbu sedikit berbeda (mis. saus tiram/jahe) atau
takaran untuk 4 porsi?Masalahnya: satu resep sangat panjang, dan ditutup dengan bertanya balik. Pengguna cuma ingin ide masakan, bukan disuruh menjawab pertanyaan.
Varian B — peran + aturan
ts
instructions: `Kamu asisten resep masakan rumahan Indonesia.
Beri saran masakan yang bisa dibuat dari bahan yang disebut pengguna.
Pakai bahasa yang ringkas.`Keluaran nyata:
text
Bahan utama cukup untuk beberapa opsi. Pilih salah satu:
1) Tumis Ayam Brokoli Kecap (cepat, favorit)
- Bahan: ayam fillet 300 g (iris tipis), brokoli ~200–300 g...
- Cara:
1. Rebus/cekok brokoli 1–2 menit, tiriskan (agar renyah).
[... 4 langkah lagi ...]
- Waktu: 15–20 menit. Porsi: 2–3 orang.
2) Ayam Brokoli Panggang Kecap (lebih "kering", cocok untuk bekal)
- Marinasi ayam dengan kecap asin + bawang putih cincang 15–30 menit.
[...]
3) Sup Ayam Brokoli Bawang Putih (ringan)
[...]
Tips singkat:
- Kalau ada kecap manis/saus tiram, tambahkan untuk rasa lebih kaya.
- Tambah merica atau cabai untuk pedas.Yang membaik: tidak bertanya balik lagi, dan memberi beberapa pilihan. Yang masih kurang: jumlah pilihan tidak terkendali (dapat 3), dan tiap pilihan masih memuat langkah lengkap sehingga tetap panjang.
Varian C — + penanganan kasus tepi
ts
instructions: `Kamu asisten resep masakan rumahan Indonesia.
Beri saran masakan yang bisa dibuat dari bahan yang disebut pengguna.
Pakai bahasa yang ringkas.
Kalau pengguna hanya mengirim daftar bahan tanpa pertanyaan, JANGAN bertanya
balik. Langsung usulkan 2 masakan: sebutkan nama masakan, bahan tambahan yang
masih diperlukan, dan waktu masak perkiraan.`Keluaran nyata — kali ini utuh, tidak dipotong:
text
1) Tumis Ayam Brokoli Kecap
- Bahan tambahan: minyak sayur, saus tiram (opsional), gula, merica, garam,
air/kaldu, maizena (opsional untuk mengental)
- Waktu masak: 15–20 menit
2) Ayam Fillet Panggang Kecap Bawang + Brokoli Kukus
- Bahan tambahan: minyak zaitun/mentega, madu atau gula merah (opsional untuk
glaze), merica, garam, perasan jeruk nipis/lemon (opsional)
- Waktu masak: 25–35 menit (termasuk marinasi singkat); brokoli kukus 5–7 menitTujuh baris. Persis dua masakan. Tiap entri memuat persis tiga hal yang diminta. Tidak ada pertanyaan balik.
Keluaran LLM tidak deterministik
Transkrip di atas adalah satu kali jalan. Kalau kamu menjalankan ulang, kalimatnya akan berbeda. Yang konsisten adalah strukturnya — dan struktur itulah yang dikendalikan instructions.
Apa yang sebenarnya berubah
| A: minimal | B: peran + aturan | C: + kasus tepi | |
|---|---|---|---|
| Token instruksi | 36 | 61 | 114 |
| Jumlah masakan | 1 | 3 (tak terkendali) | tepat 2 |
| Bertanya balik? | Ya | Tidak | Tidak |
| Panjang jawaban | ~38 baris | ~24 baris | 7 baris |
| Bisa dirender di UI kartu? | Tidak | Sulit | Ya |
Angka token instruksi itu asli dari API. Perhatikan arahnya:
Instruksi tiga kali lebih panjang menghasilkan jawaban lima kali lebih pendek.
Ini pertukaran yang penting dipahami, dan bukan yang biasanya diduga orang.
Pro dan kontra: seberapa detail instruksimu?
Ini keputusan nyata dengan dua sisi.
Instruksi pendek
| Untung | Rugi |
|---|---|
| Murah — 36 token per panggilan | Perilaku tidak terkendali |
| Cepat ditulis | Jawaban panjang → token keluaran justru membengkak |
| Mudah dibaca ulang | Kasus tepi ditangani sesuka model |
| Model bebas beradaptasi ke pertanyaan tak terduga | Sulit dirender jadi UI terstruktur |
Instruksi detail
| Untung | Rugi |
|---|---|
| Perilaku bisa ditebak dan konsisten | Mahal — dibayar setiap panggilan |
| Jawaban ringkas → hemat token keluaran | Bisa terlalu kaku untuk pertanyaan di luar dugaan |
| Bentuknya stabil, enak dirender | Panjang instruksi mudah membengkak tanpa disadari |
| Kasus tepi ditangani sesuai maumu | Perlu diuji ulang tiap kali diubah |
Cara memutuskan
Perhatikan bahwa dua kolom "rugi" saling meniadakan pada biaya:
- Instruksi pendek hemat di input, boros di output
- Instruksi detail boros di input, hemat di output
Karena instruksi dikirim ulang di setiap panggilan sementara jawaban panjang hanya terjadi sekali per pertanyaan, hitungannya bergantung pada berapa putaran loop yang terjadi. Untuk agent tanpa tool (satu putaran), instruksi detail biasanya lebih murah total. Untuk agent dengan banyak tool (lima-enam putaran), instruksi panjang dibayar lima-enam kali.
Patokan praktis:
| Situasi | Pilih |
|---|---|
| Jawaban dirender jadi UI terstruktur | Detail — bentuk harus stabil |
| Agent punya banyak tool (loop panjang) | Ringkas; pindahkan aturan ke deskripsi tool |
| Pertanyaan pengguna sangat bervariasi | Ringkas + aturan penolakan saja |
| Ada kasus tepi yang berulang mengganggu | Tambahkan aturan untuk kasus itu saja |
Posisi instructions dalam permintaan
Secara teknis, instructions adalah system message yang diletakkan sebelum seluruh pesan percakapan:
text
[system] ← instructions kamu
[user] Halo
[assistant] Halo, ada yang bisa dibantu?
[user] ayam fillet 300g, brokoli...Dua akibat langsung:
- Ikut dikirim di setiap panggilan model — bukan sekali di awal percakapan. Ini yang membuat angka 114 token tadi berlipat.
- Isinya harus stabil, bukan tempat menaruh data.
Pembagian yang perlu dihafal:
Masuk instructions | Jangan — pakai jalur lain |
|---|---|
| Identitas dan peran | Data akun pengguna → tool |
| Aturan yang selalu berlaku | Riwayat percakapan → memory |
| Gaya bahasa | Isi dokumen → RAG |
| Penanganan kasus tepi | Detail satu tugas → pesan pengguna |
| Kapan menolak |
Empat bentuk penulisan
Semua contoh di bawah sudah lolos type-check terhadap @mastra/core 1.64.0.
String — untuk instruksi pendek
ts
// src/mastra/agents/support-agent.ts
import { Agent } from '@mastra/core/agent'
export const supportAgent = new Agent({
id: 'support-agent',
name: 'Support Agent',
instructions: `Kamu membantu pelanggan memahami akun mereka.
Hari ini ${new Date().toDateString()}.
Pakai bahasa sederhana dan jangan mengarang detail akun.`,
model: 'openai/gpt-5.6-sol',
})new Date() diinterpolasi langsung karena tanggal tidak bergantung siapa penggunanya — sama untuk semua orang.
Array string — saat instruksi mulai panjang
ts
instructions: [
'Kamu adalah perwakilan layanan pelanggan.',
'Selalu jaga nada profesional dan empatik.',
'Eskalasi masalah rumit ke agen manusia bila perlu.',
]Lebih mudah menyusun ulang dan menghapus satu aturan tanpa merusak yang lain.
Objek system message — saat butuh opsi penyedia
ts
instructions: {
role: 'system',
content: 'Kamu asisten yang ahli dalam dokumentasi teknis.',
providerOptions: {
openai: { reasoningEffort: 'low' },
},
}providerOptions diatur per bagian instruksi, bukan per agent. Berguna untuk mengatur tingkat penalaran, atau strategi cache pada bagian tertentu.
Bentuk-bentuk ini bisa dicampur, dan bagian yang dipakai berulang bisa disimpan sebagai variabel:
ts
const nada = {
role: 'system' as const,
content: 'Selalu jaga nada profesional dan empatik.',
}
export const csAgent = new Agent({
id: 'cs-agent',
name: 'CS Agent',
instructions: [
{ role: 'system', content: 'Kamu perwakilan layanan pelanggan.' },
nada,
{
role: 'system',
content: 'Eskalasi masalah rumit ke agen manusia.',
providerOptions: {
anthropic: { cacheControl: { type: 'ephemeral' } },
},
},
],
model: 'anthropic/claude-sonnet-4-6',
})Menyimpan nada di satu berkas lalu memakainya di beberapa agent adalah cara sederhana menjaga suara produk tetap konsisten.
Fungsi — saat instruksi bergantung penggunanya
ts
instructions: ({ requestContext }) => {
const nama = requestContext.get('name')
return `Kamu membantu ${nama} memahami akun mereka.`
}Kapan pakai: data yang berubah per request — pengguna, tenant, locale, peran, feature flag.
Kapan jangan: nilai yang sama untuk semua orang, seperti tanggal hari ini. Interpolasi langsung sudah cukup, dan lebih murah.
RequestContext diisi dari sisi server, dibahas di 9.2.
Urutan bagian berpengaruh pada tagihan
Penyedia model bisa menggunakan ulang cache untuk awalan prompt yang sama. Kalau bagian awal permintaanmu identik dengan permintaan sebelumnya, bagian itu tidak diproses ulang dari nol — lebih murah dan lebih cepat.
Sekarang lihat apa yang terjadi kalau nama pengguna ditaruh di kalimat pertama:
text
❌ Awalan berubah tiap user ✅ Awalan sama untuk semua
┌────────────────────────┐ ┌────────────────────────┐
│ Kamu membantu Budi... │ ← beda │ Kamu perwakilan CS. │ ← sama
│ Kamu perwakilan CS. │ │ Nada profesional. │ ← sama
│ Nada profesional. │ │ Jangan mengarang data. │ ← sama
│ Jangan mengarang data. │ │ Pengguna: Budi │ ← beda
└────────────────────────┘ └────────────────────────┘
cache tidak pernah kena cache kena di 3 baris awalAturannya: bagian stabil di depan, bagian dinamis di belakang.
Kesalahan umum
Gejala: Biaya per percakapan jauh di atas perkiraan, latensi tinggi bahkan untuk pertanyaan sederhana. Penyebab: Data yang seharusnya lewat tool atau memory ikut ditulis di instruksi. Karena instruksi dikirim ulang tiap putaran loop, pembengkakannya berlipat. Perbaikan: Pindahkan data ke jalurnya. Sisakan hanya perilaku yang berlaku untuk sebagian besar panggilan.
Gejala: Agent bertanya balik padahal informasinya sudah cukup. Penyebab: Tidak ada aturan untuk kasus itu, seperti Varian A di atas. Perbaikan: Tulis aturan eksplisit untuk kasus tepi yang berulang — sebutkan apa yang harus dilakukan, bukan hanya apa yang dilarang.
Coba sendiri
Tujuannya: melihat sendiri instruksi mengubah keluaran, dengan mengulang eksperimen di atas pada domain berbeda.
Kode awal
Salin ke demo/uji-instruksi.mjs, lalu jalankan node demo/uji-instruksi.mjs.
js
// demo/uji-instruksi.mjs
import { Agent } from '@mastra/core/agent'
// Pesan uji yang SENGAJA ambigu — di sinilah instruksi menunjukkan bedanya.
const PESAN = 'laptop saya lemot'
const MODEL = 'openai/gpt-5-mini'
const varian = {
'A. Minimal': 'Kamu asisten IT helpdesk.',
// TODO 1: tambahkan peran + 2 aturan (gaya bahasa, batas cakupan)
'B. Peran + aturan': `TULIS DI SINI`,
// TODO 2: salin B, lalu tambahkan aturan untuk kasus tepi berikut —
// pengguna melapor tanpa detail apa pun. Agent harus langsung memberi
// 3 langkah pemeriksaan mandiri yang berurutan, bukan bertanya balik.
'C. + kasus tepi': `TULIS DI SINI`,
}
for (const [nama, instructions] of Object.entries(varian)) {
const agent = new Agent({ id: 'u', name: 'U', instructions, model: MODEL })
const r = await agent.generate(PESAN)
console.log('=====', nama, '=====')
console.log(r.text.trim())
console.log(`[token instruksi: ${r.usage.inputTokens} | baris jawaban: ${r.text.trim().split('\n').length}]`)
console.log('')
}Bentuk hasil yang diharapkan
Latihan ini sudah dijalankan sungguhan. Varian A menghasilkan ini — dipotong, aslinya 48 baris:
text
===== A. Minimal =====
Oke — saya bantu. Sebelum mulai, beberapa pertanyaan singkat supaya solusi tepat:
- Kamu pakai Windows, macOS, atau Linux?
- Lambatnya seperti apa: boot lama, program hang/lemot saat dipakai...
- Spesifikasi singkat kalau tahu: RAM, tipe penyimpanan (HDD/SSD)...
- Data sudah dibackup?
Sementara kamu jawab, ini daftar pemeriksaan cepat...
[... 40 baris lagi: langkah cepat, pemeriksaan lanjutan, upgrade hardware ...]
Mau mulai dari mana? Sebutkan OS dan gejala detail...
[token instruksi: 23 | baris jawaban: 48]Empat pertanyaan balik sebelum menjawab, lalu 40 baris yang tidak diminta.
Varian C — utuh, tidak dipotong:
text
===== C. + kasus tepi =====
1) Tutup semua program dan tab browser yang tidak sedang dipakai, lalu lihat
apakah laptop terasa lebih cepat.
2) Restart laptop untuk membersihkan memori sementara dan menutup proses yang
macet.
3) Hapus atau pindahkan file besar yang tidak perlu ke penyimpanan lain supaya
ruang kosong di laptop bertambah.
[token instruksi: 105 | baris jawaban: 3]Kalimatmu akan berbeda — yang harus cocok adalah strukturnya dan angkanya: 3 baris, tanpa pertanyaan balik.
Selesai kalau
- [ ] Varian A bertanya balik atau memberi jawaban umum yang panjang
- [ ] Varian C tidak bertanya balik dan memberi tepat 3 langkah
- [ ] Angka
token instruksinaik dari ~23 ke ~100 - [ ] Angka
baris jawabanturun drastis — dari puluhan jadi 3 - [ ] Kamu bisa menyebut satu kalimat di instruksi C yang menyebabkan perbedaan itu
Kalau macet
Varian C masih bertanya balik? Instruksimu kemungkinan melarang tanpa memberi pengganti. Bandingkan:
- ❌ "Jangan bertanya balik." — model tahu larangannya, tidak tahu gantinya
- ✅ "Jangan bertanya balik. Langsung beri 3 langkah pemeriksaan berurutan."
Ikhtisar
- Instructions adalah system message yang ikut dikirim di setiap panggilan model, termasuk setiap putaran loop.
- Eksperimen nyata: instruksi 36 → 114 token membuat jawaban turun dari ~38 baris jadi 7 baris, dan menghilangkan pertanyaan balik.
- Instruksi pendek hemat input tapi boros output; instruksi detail sebaliknya. Yang menang bergantung berapa putaran loop terjadi.
- Isinya aturan yang stabil, bukan data. Data lewat tool, riwayat lewat memory, dokumen lewat RAG.
- Empat bentuk: string, array string, objek system message (
providerOptions), dan fungsi (requestContext) untuk hal yang berubah per request. - Bagian stabil di depan agar cache penyedia bisa dipakai ulang.
- Aturan yang efektif menyebut apa yang harus dilakukan, bukan hanya apa yang dilarang.
Lanjut ke mana
Instruksi mengendalikan apa yang dijawab agent. Bab berikutnya soal kapan jawaban itu sampai ke pengguna, dan kenapa ada dua cara memanggilnya — 1.3 generate() dan stream().