Tampilan
7.2 Goals, Schedules & Signals
Tujuan bab
Setelah bab ini kamu bisa:
- Menetapkan tujuan yang bertahan untuk sebuah thread dengan
setObjective() - Membedakan
goaldanisTaskComplete, serta memilih di antaranya - Menjadwalkan agent berjalan pada cron dengan
mastra.schedules - Mengirim pesan dan sinyal ke thread yang sedang berjalan atau menganggur
- Menjelaskan peran signal providers
Prasyarat
- 7.1 Durable Agents
- Storage terpasang, dan thread yang didukung memory
Tiga cara agent bekerja tanpa diminta
Ketiga kemampuan di bab ini menjawab pertanyaan yang berbeda:
| Kemampuan | Pertanyaannya | Pemicunya |
|---|---|---|
| Goals | Kapan agent boleh berhenti? | Penilaian model terhadap tujuan |
| Schedules | Kapan agent mulai bekerja? | Waktu, lewat cron |
| Signals | Apa yang membuat agent tahu ada hal baru? | Peristiwa dari luar |
Goals — tujuan yang bertahan
Sebuah goal adalah tujuan yang durable dan terikat pada thread: instruksi tetap yang terus dikejar agent melintasi iterasi loop, sampai sebuah model penilai memutuskan tujuan itu tercapai — atau sampai anggaran run habis.
ts
// src/mastra/agents/worker.ts
import { Agent } from '@mastra/core/agent'
export const worker = new Agent({
id: 'worker',
name: 'worker',
instructions: 'Kamu menyelesaikan tugas perangkat lunak dari awal sampai akhir.',
model: 'openai/gpt-5.6-sol',
memory,
goal: {
judge: 'openai/gpt-5-mini',
maxRuns: 50,
},
})
await worker.setObjective('Tambahkan dan uji endpoint /health', {
threadId,
resourceId,
})Dua properti pada konfigurasi goal:
judge— model yang menilai apakah tujuan sudah tercapai. Dokumentasi menyebutnya wajib: tanpa judge, goal tidak melakukan apa-apa.maxRuns— anggaran run. Ini rem darurat; tanpanya, agent yang tidak pernah dinilai selesai bisa berputar tanpa batas.
Tujuannya dipersistensi di thread state, sehingga bertahan melewati reload dan dievaluasi di dalam loop — bahkan ketika pesan baru datang di tengah giliran yang sedang berjalan.
goal atau isTaskComplete?
Keduanya memakai mesin yang sama: LLM-as-judge yang menilai keluaran agent tiap iterasi dan menentukan apakah loop lanjut. Perbedaannya di tempat tinggal kriteria itu:
goal | isTaskComplete | |
|---|---|---|
| Disimpan di | Thread state (durable) | Opsi per pemanggilan stream() |
| Bertahan melewati restart | Ya | Tidak |
| Diatur lewat | Method Agent seperti setObjective() | Opsi pada tiap panggilan |
| Cocok untuk | Tujuan tetap yang dikejar lintas banyak pesan | Pemeriksaan sekali jalan |
Aturannya sederhana: kalau kriteria keberhasilannya harus disebut ulang di setiap panggilan, kamu sebenarnya butuh goal.
Goals memerlukan storage dan memory
Dokumentasi menyebut keduanya sebagai prasyarat: backend storage yang terkonfigurasi, dan thread yang didukung memory. Masuk akal — tujuan yang "bertahan" harus punya tempat bertahan.
Schedules — pekerjaan yang berulang
Sebuah schedule menjalankan agent pada irama cron. Setiap kali menyala, Mastra mengirim prompt — bisa sebagai signal ke sebuah thread, atau sebagai run agent.generate() tanpa thread.
ts
// src/mastra/index.ts
import { Mastra } from '@mastra/core'
import { Agent } from '@mastra/core/agent'
import { LibSQLStore } from '@mastra/libsql'
const pinger = new Agent({
id: 'pinger',
name: 'Pinger',
instructions: 'Laporkan status sistem saat ini dalam satu kalimat.',
model: 'openai/gpt-5.6-sol',
})
export const mastra = new Mastra({
agents: { pinger },
storage: new LibSQLStore({ id: 'mastra-storage', url: 'file:./mastra.db' }),
})
await mastra.schedules.create({
agentId: 'pinger',
cron: '0 * * * *',
prompt: 'Beri saya pembaruan status.',
})Schedule di atas berjalan tiap jam. Karena tidak menyebut thread, tiap penyalaan adalah run agent.generate() yang terisolasi.
Hal-hal yang perlu diketahui:
- Schedule dipersistensi, sehingga bertahan melewati restart dan redeploy
- Mastra menyalakan penjadwal saat schedule pertama dibuat
mastra.schedulesadalah permukaan CRUD kanonik untuk mengelolanya saat runtime- Permukaan yang sama juga mengelola schedule untuk workflow — berikan
workflowIdalih-alihagentId
Tidak semua storage adapter mendukung schedules
Dokumentasi mencatat bahwa schedules memerlukan storage adapter yang mengimplementasikan domain schedules. Ingat dari 0.2 bahwa storage Mastra terbagi menjadi domain, dan dukungan tiap adapter berbeda-beda. Periksa dulu sebelum merancang di atasnya.
Dua bentuk penyalaan
Tanpa thread: Dengan thread:
cron menyala cron menyala
↓ ↓
agent.generate() signal masuk ke thread
↓ ↓
hasil berdiri sendiri agent melanjutkan percakapan
dengan konteks yang sudah adaBentuk pertama untuk pekerjaan yang berdiri sendiri — ringkasan harian, pemeriksaan berkala. Bentuk kedua untuk "dorongan terjadwal" ke dalam percakapan yang sedang berlangsung, misalnya agent yang mengingatkan sesuatu di tengah sesi kerja panjang.
Signals — memberi tahu agent ada hal baru
Signals membalik cara kamu berinteraksi dengan agent. Alih-alih memulai tiap interaksi dengan agent.stream(), kamu berlangganan ke sebuah thread lalu mengirim pesan atau sinyal ke sana.
ts
// run.mjs
import { Agent } from '@mastra/core/agent'
const agent = new Agent({
id: 'support-agent',
name: 'Support Agent',
instructions: 'Bantu pengguna membandingkan pilihan.',
model: 'openai/gpt-5.6-sol',
})
const thread = {
resourceId: 'user_123',
threadId: 'thread_456',
}
const subscription = await agent.subscribeToThread(thread)
await agent.sendMessage('Bandingkan itu dengan pilihan sebelumnya.', thread)
for await (const chunk of subscription.stream) {
console.log(chunk)
}Yang dilakukan Mastra saat pesan tiba: membangunkan agent yang menganggur, atau mengantarkan masukan ke loop yang sedang berjalan — atau mengantrikannya untuk giliran berikutnya.
Empat cara mengirim, empat maksud berbeda
| Method | Untuk | Contoh |
|---|---|---|
sendMessage() | Masukan yang ditulis pengguna | "Bandingkan dengan yang tadi" |
queueMessage() | Masukan pengguna, ditahan untuk giliran berikutnya | Pesan susulan saat agent sibuk |
sendSignal() | Konteks sistem tingkat rendah | Notifikasi background task, pengingat kebijakan |
sendStateSignal() | Jalur state yang durable | Perubahan keadaan yang harus bertahan |
sendNotificationSignal() | Peristiwa yang harus menjadi catatan inbox durable | Peringatan yang perlu dilacak |
Garis pemisah utamanya: sendMessage() untuk yang ditulis manusia, sendSignal() untuk konteks yang dihasilkan sistem. Memakai sendMessage() untuk notifikasi mesin membuat riwayat percakapan tercemar hal-hal yang tidak pernah dikatakan siapa pun.
Signal providers — jembatan ke dunia luar
Kemampuan terakhir menutup lingkarannya. Signal provider memantau sistem eksternal — GitHub, Slack, CI — lewat polling atau webhook, lalu meneruskan peristiwa yang cocok ke thread agent.
GitHub PR di-merge
↓
Signal provider (webhook)
↓
Signal masuk ke thread
↓
Agent bangun dan menindaklanjutiIni yang membuat agent SRE atau agent go-to-market yang disebut di pengantar bagian ini mungkin dibangun: agent tidak menunggu ditanya, ia bereaksi terhadap perubahan.
Ketiganya bersama
Pembagiannya: schedule dan signal menentukan kapan agent mulai; goal menentukan kapan ia boleh berhenti.
Kesalahan umum
Gejala: goal dikonfigurasi tapi agent berperilaku seperti biasa — tidak ada pengejaran tujuan sama sekali. Penyebab: judge tidak diberikan. Dokumentasi menyatakan model penilai wajib ada agar goal berfungsi. Perbaikan: Tambahkan judge pada konfigurasi goal, dan pastikan storage serta memory terpasang.
Gejala: Riwayat percakapan penuh pesan yang tidak pernah ditulis pengguna — notifikasi sistem, pembaruan status, pengingat internal. Penyebab: Memakai sendMessage() untuk konteks yang dihasilkan sistem, padahal itu tugas sendSignal(). Perbaikan: Pisahkan keduanya. sendMessage() hanya untuk yang benar-benar ditulis manusia; segala konteks mesin lewat sendSignal() atau variannya.
Coba sendiri
Tantangan: Bangun monitor-agent yang memantau sesuatu secara berkala, mengejar tujuan yang bertahan, dan bisa dibangunkan dari luar.
Ketentuan:
- Buat agent dengan memory dan storage terpasang
- Konfigurasikan
goaldenganjudgeberupa model ringan danmaxRunsyang sengaja kecil, misalnya 5 - Tetapkan objective lewat
setObjective()— sesuatu yang jelas kriterianya, misalnya "kumpulkan tiga sumber terpercaya tentang topik X dan ringkas masing-masing dalam dua kalimat" - Buat schedule cron yang menyala tiap menit dan mengirim prompt ke thread yang sama dengan objective itu
- Berlangganan thread tersebut, dan amati apa yang terjadi selama beberapa penyalaan
- Dari skrip terpisah, kirim
sendSignal()berisi konteks sistem — misalnya "sumber dari domain contoh.com sedang tidak dapat diakses" - Amati apakah agent memperhitungkan sinyal itu
- Naikkan
maxRunsdan bandingkan perilakunya
Checklist penerimaan:
- [ ] Agent berhenti setelah tujuan dinilai tercapai — bukan setelah satu giliran
- [ ] Dengan
maxRuns: 5, agent berhenti karena anggaran habis kalau tujuannya belum tercapai — dan kamu bisa membedakan kedua sebab berhenti itu - [ ] Schedule menyala sesuai cron dan masuk ke thread yang benar
- [ ] Sinyal dari langkah 6 sampai ke agent dan terlihat pengaruhnya
- [ ] Sinyal itu tidak muncul sebagai pesan pengguna di riwayat
- [ ] Kamu bisa menjelaskan kenapa kasus ini memakai
goaldan bukanisTaskComplete
Petunjuk: Ketentuan 2 dengan maxRuns kecil disengaja. Anggaran run adalah pengaman yang paling mudah diabaikan sampai kamu pernah melihat agent berputar dua puluh kali karena judge tidak pernah puas. Lihat sendiri batas itu bekerja selagi murah — dan perhatikan bahwa "berhenti karena selesai" dan "berhenti karena kehabisan anggaran" adalah dua hasil yang sangat berbeda.
Ikhtisar
- Goal adalah tujuan durable yang terikat thread, dinilai oleh model
judgetiap iterasi sampai tercapai ataumaxRunshabis.judgewajib; storage dan memory adalah prasyarat. - Bedanya dari
isTaskComplete: goal bertahan di thread state,isTaskCompletediberikan per pemanggilan. - Schedule menjalankan agent pada cron, dan dikelola lewat
mastra.schedules. Ia dipersistensi, dan penjadwal menyala saat schedule pertama dibuat. - Schedule bisa berupa run terisolasi (tanpa thread) atau signal ke thread yang ada. Ia juga bisa menjadwalkan workflow lewat
workflowId. - Tidak semua storage adapter mendukung domain
schedules— periksa dulu. - Signals membalik alur: berlangganan thread, lalu kirim masukan.
sendMessage()untuk manusia,sendSignal()untuk sistem — jangan tertukar, atau riwayat percakapanmu tercemar. - Signal providers memantau sistem eksternal lewat polling atau webhook dan meneruskan peristiwa ke thread.
Lanjut ke mana
Sejauh ini satu agent yang bekerja lebih lama. Bab berikutnya membagi pekerjaan ke beberapa agent yang lebih spesialis: 7.3 Subagents & Skills.