Skip to content

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 asin

Varian 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 menit

Tujuh 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: minimalB: peran + aturanC: + kasus tepi
Token instruksi3661114
Jumlah masakan13 (tak terkendali)tepat 2
Bertanya balik?YaTidakTidak
Panjang jawaban~38 baris~24 baris7 baris
Bisa dirender di UI kartu?TidakSulitYa

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

UntungRugi
Murah — 36 token per panggilanPerilaku tidak terkendali
Cepat ditulisJawaban panjang → token keluaran justru membengkak
Mudah dibaca ulangKasus tepi ditangani sesuka model
Model bebas beradaptasi ke pertanyaan tak terdugaSulit dirender jadi UI terstruktur

Instruksi detail

UntungRugi
Perilaku bisa ditebak dan konsistenMahal — dibayar setiap panggilan
Jawaban ringkas → hemat token keluaranBisa terlalu kaku untuk pertanyaan di luar dugaan
Bentuknya stabil, enak direnderPanjang instruksi mudah membengkak tanpa disadari
Kasus tepi ditangani sesuai maumuPerlu 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:

SituasiPilih
Jawaban dirender jadi UI terstrukturDetail — bentuk harus stabil
Agent punya banyak tool (loop panjang)Ringkas; pindahkan aturan ke deskripsi tool
Pertanyaan pengguna sangat bervariasiRingkas + aturan penolakan saja
Ada kasus tepi yang berulang menggangguTambahkan 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:

  1. Ikut dikirim di setiap panggilan model — bukan sekali di awal percakapan. Ini yang membuat angka 114 token tadi berlipat.
  2. Isinya harus stabil, bukan tempat menaruh data.

Pembagian yang perlu dihafal:

Masuk instructionsJangan — pakai jalur lain
Identitas dan peranData akun pengguna → tool
Aturan yang selalu berlakuRiwayat percakapan → memory
Gaya bahasaIsi dokumen → RAG
Penanganan kasus tepiDetail 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 awal

Aturannya: 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 instruksi naik dari ~23 ke ~100
  • [ ] Angka baris jawaban turun 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().

Materi belajar mandiri. Bukan dokumentasi resmi Mastra.