Tampilan
1.1 Agent Pertama
Tujuan bab
Setelah bab ini kamu bisa:
- Membuat agent dengan
new Agent()dan menjelaskan fungsi tiap properti wajibnya - Membedakan
iddanname, serta tahu mana yang dipakai untuk mengambil agent dari kode - Mendaftarkan agent ke instance Mastra dan menjelaskan apa yang didapat dari pendaftaran itu
- Memanggil agent lewat
mastra.getAgentById()danmastra.getAgent(), dan tahu bedanya - Menjelaskan kenapa satu panggilan
generate()bisa berarti beberapa panggilan ke model
Prasyarat
- Bagian 0 selesai, dengan proyek yang bisa dijalankan
- Paket
@mastra/coredanzodterpasang
Agent paling sederhana yang mungkin
Kita mulai dari bentuk paling telanjang: tanpa tool, tanpa memory, tanpa apa pun.
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: 'Jawab pertanyaan support dengan jelas dan ringkas.',
model: 'openai/gpt-5.6-sol',
})Empat properti, dan tiap satunya menjawab satu pertanyaan berbeda:
| Properti | Menjawab pertanyaan | Dipakai oleh |
|---|---|---|
id | Bagaimana kode memanggil agent ini? | Programmu, lewat getAgentById() |
name | Bagaimana manusia mengenali agent ini? | Studio, log, antarmuka |
instructions | Bagaimana agent ini harus berperilaku? | Model, sebagai system prompt |
model | Model mana yang menjalankan penalarannya? | Model router Mastra |
id dan name bukan hal yang sama
Ini terlihat sepele sampai kamu menghabiskan setengah jam mencari kenapa getAgentById('Support Agent') tidak menemukan apa-apa.
idadalah pengenal teknis. Pakaikebab-case, jaga tetap stabil, dan perlakukan seperti primary key — mengubahnya berarti mengubah semua kode yang memanggilnya.nameadalah label untuk manusia. Boleh berspasi, boleh berkapital, boleh diubah kapan saja tanpa merusak apa pun.
Aturan praktis: kalau string itu muncul di dalam kode, itu id. Kalau muncul di layar untuk dibaca orang, itu name.
Mendaftarkan agent
Agent yang sudah dibuat belum berarti dikenali. Ia harus masuk ke instance Mastra:
ts
// src/mastra/index.ts
import { Mastra } from '@mastra/core'
import { supportAgent } from './agents/support-agent.ts'
export const mastra = new Mastra({
agents: { supportAgent },
})Pendaftaran ini bukan formalitas. Yang kamu dapatkan darinya:
- Agent muncul di Studio dan bisa diuji tanpa menulis kode pemanggil
- Agent bisa diambil lewat
mastra.getAgentById()di mana pun dalam aplikasi - Agent mewarisi konfigurasi tingkat instance — storage, logger, dan observability yang kamu pasang di
new Mastra()berlaku untuknya
Poin terakhir itu yang paling sering luput. Saat nanti kamu memasang storage di Bagian 3 dan tracing di Bagian 8, keduanya dikonfigurasi sekali di instance Mastra dan otomatis berlaku ke semua agent yang terdaftar. Agent yang tidak terdaftar tidak kebagian apa pun dari itu.
Memanggil agent
ts
// run.mjs
import { mastra } from './src/mastra/index.ts'
const agent = mastra.getAgentById('support-agent')
const response = await agent.generate('Bagaimana cara reset password saya?')
console.log(response.text)Jalankan dengan node run.mjs. Hasilnya kira-kira seperti ini:
text
Untuk mereset password, buka halaman login lalu pilih "Lupa password".
Masukkan email terdaftar, dan kami akan mengirim tautan reset yang berlaku
selama 30 menit.Dua cara mengambil agent
Mastra menyediakan dua method yang mudah tertukar:
ts
mastra.getAgentById('support-agent') // dicari berdasarkan properti id
mastra.getAgent('supportAgent') // dicari berdasarkan key saat didaftarkanPerhatikan argumennya berbeda. getAgent() memakai key pada objek agents di new Mastra({ agents: { supportAgent } }) — yaitu nama variabelnya. getAgentById() memakai nilai properti id pada konstruktor agent.
Yang mana yang sebaiknya dipakai? getAgentById(), dengan satu alasan praktis: ia lebih toleran. Dokumentasi menyebut bahwa getAgentById() mula-mula mencari berdasarkan agent.id, dan kalau tidak ketemu, ia jatuh kembali ke getAgent() dan memperlakukan nilai itu sebagai key registry. Jadi getAgentById() menangani kedua kasus, sementara getAgent() hanya satu.
Konsistenkan sejak awal
Cara termudah menghindari kebingungan ini: buat id dan key registry-mu selalu merujuk ke agent yang sama secara konsisten, dan pakai getAgentById() di seluruh aplikasi. Satu kebiasaan, nol pertanyaan.
Agent adalah loop, bukan satu panggilan
Ini konsep yang paling penting dari seluruh bab, dan paling mudah terlewat karena kodenya terlihat seperti satu panggilan biasa.
Saat kamu menulis await agent.generate('...'), yang terjadi di dalam bukan satu request ke model lalu selesai. Yang terjadi adalah loop:
Untuk agent di bab ini yang belum punya tool, loop itu berputar tepat sekali — model tidak punya apa pun untuk dipanggil, jadi ia langsung menghasilkan jawaban. Begitu kamu menambahkan tool di Bagian 2, loop ini mulai berputar beberapa kali untuk satu pesan.
Konsekuensi praktis yang perlu kamu sadari sekarang:
- Satu pesan bisa berarti beberapa panggilan model, dan biayanya bertambah sesuai itu
- Waktu respons tidak sebanding dengan panjang jawaban, karena sebagian besar waktu bisa habis di putaran-putaran tool
- Loop ini bisa dibatasi.
generate()menerima opsimaxStepsuntuk membatasi jumlah langkah, danstopWhenuntuk kondisi berhenti yang lebih spesifik seperti batas jumlah langkah atau batas token
Pemahaman ini yang membuat trace di Bagian 8 langsung masuk akal saat pertama kali kamu membukanya.
Menguji lewat Studio
Sebelum menulis kode pemanggil, biasakan menguji lewat Studio dulu:
bash
npm run devBuka http://localhost:4111, pilih Support Agent dari daftar, dan kirim beberapa pesan. Yang kamu dapat dari sini dan tidak kamu dapat dari console.log: tampilan langkah demi langkah dari apa yang dilakukan agent.
Untuk agent tanpa tool, tampilannya masih sederhana. Tapi biasakan sekarang, karena saat agent-mu punya lima tool dan memberi jawaban aneh, Studio adalah tempat pertama yang kamu buka.
Kesalahan umum
Gejala: mastra.getAgentById('...') melempar error bahwa agent tidak ditemukan, padahal file agent-nya jelas ada dan sudah di-export. Penyebab: Agent belum didaftarkan di new Mastra({ agents: { ... } }). Membuat objek Agent dan mendaftarkannya adalah dua langkah terpisah — yang kedua sering terlupa saat menambah agent kedua dan seterusnya. Perbaikan: Impor dan tambahkan ke objek agents di src/mastra/index.ts. Kalau sudah terdaftar tapi tetap gagal, periksa apakah kamu memasukkan name ("Support Agent") padahal yang diminta id ("support-agent").
Gejala: Agent berjalan jauh lebih lama dan jauh lebih mahal dari perkiraan, padahal jawaban akhirnya pendek. Penyebab: Loop agent berputar berkali-kali. Ini normal saat ada tool, tapi tanpa batas ia bisa berputar lebih lama dari yang kamu inginkan — misalnya karena instruksi yang ambigu membuat model terus mencoba pendekatan baru. Perbaikan: Batasi dengan maxSteps atau stopWhen pada opsi generate(). Lalu buka trace untuk melihat di putaran mana waktunya habis; seringkali akar masalahnya di instruksi, bukan di batas langkah.
Coba sendiri
Tantangan: Buat agent bernama resep-agent yang membantu pengguna menemukan ide masakan dari bahan yang tersedia di kulkas. Agent ini belum boleh punya tool — seluruh perilakunya harus datang dari instructions saja.
Ketentuan:
idmemakaikebab-case,namememakai bentuk yang enak dibaca manusia- Agent harus menolak dengan sopan kalau ditanya hal di luar urusan masakan
- Daftarkan ke
src/mastra/index.ts - Uji lewat Studio dengan tiga pesan: satu pertanyaan masakan yang wajar, satu pertanyaan di luar topik, dan satu pesan yang hanya berisi daftar bahan tanpa pertanyaan apa pun
- Panggil juga dari skrip memakai
getAgentById(), cetakresponse.text
Checklist penerimaan:
- [ ] Agent muncul di Studio dengan
nameyang terbaca rapi - [ ] Pertanyaan di luar topik ditolak dengan sopan, bukan dijawab
- [ ] Pesan berisi daftar bahan saja tetap menghasilkan saran yang berguna, tanpa agent balik bertanya "apa yang bisa saya bantu?"
- [ ] Skrip pemanggil berhasil mencetak jawaban lewat
getAgentById() - [ ] Kamu bisa menjelaskan, dalam satu kalimat, kenapa agent ini hanya memutar loop satu kali per pesan
Petunjuk: Ketentuan nomor 4 yang paling menguji instruksimu. Model cenderung membalas daftar bahan telanjang dengan pertanyaan balik. Kalau itu terjadi, masalahnya bukan pada model — instruksimu belum memberitahu apa yang harus dilakukan saat pengguna mengirim data tanpa pertanyaan eksplisit.
Ikhtisar
- Agent dibuat dengan
new Agent({ id, name, instructions, model }).iduntuk kode,nameuntuk manusia. - Membuat agent tidak sama dengan mendaftarkannya. Pendaftaran di
new Mastra({ agents })yang membuatnya muncul di Studio, bisa diambil dari kode, dan mewarisi storage serta observability tingkat instance. getAgentById()mencari berdasarkan propertiiddan jatuh kembali ke key registry kalau tidak ketemu;getAgent()hanya memakai key registry. Pakai yang pertama.- Agent adalah loop, bukan satu panggilan model. Tanpa tool loop berputar sekali; dengan tool ia bisa berputar berkali-kali. Batasi dengan
maxStepsataustopWhenbila perlu. - Biasakan menguji lewat Studio sejak agent paling sederhana, supaya kebiasaannya sudah terbentuk saat agent-mu jadi rumit.
Lanjut ke mana
Agent-mu sudah jalan, tapi perilakunya masih ditentukan satu kalimat instruksi. Bab berikutnya membahas bagian yang paling menentukan kualitas sebuah agent dan paling sering diremehkan: 1.2 Instructions yang Efektif.