Skip to content

4.4 Agent & Tool di Workflow

Tujuan bab

Setelah bab ini kamu bisa:

  • Memanggil agent dari dalam execute() sebuah langkah
  • Menyusun agent langsung sebagai langkah dengan createStep(agent)
  • Memilih antara kedua pendekatan itu
  • Memakai structuredOutput supaya keluaran agent bisa disambung ke langkah berikutnya dengan aman
  • Menjelaskan schema default yang dipakai agent saat menjadi langkah

Prasyarat

Mengembalikan penilaian ke dalam alur yang pasti

Workflow memberimu determinisme, dan itu yang kamu inginkan untuk sebagian besar langkah. Tapi sebagian pekerjaan memang butuh penilaian: mengklasifikasi keluhan, meringkas dokumen, menyusun kalimat.

Di sinilah kedua dunia bertemu. Alurnya tetap kamu yang tentukan; satu-dua langkah di dalamnya diserahkan ke model.

┌─────────┐   ┌─────────────────┐   ┌─────────┐   ┌─────────┐
│validasi │──▶│ klasifikasi     │──▶│ routing │──▶│ simpan  │
│ (kode)  │   │ (agent)         │   │ (kode)  │   │ (kode)  │
└─────────┘   └─────────────────┘   └─────────┘   └─────────┘

              hanya di sini model
              diberi kebebasan

Mastra menyediakan dua cara melakukannya.

Cara pertama: memanggil agent dari dalam execute()

ts
// src/mastra/workflows/ringkas-workflow.ts
import { createStep } from '@mastra/core/workflows'
import { z } from 'zod'

const step1 = createStep({
  id: 'step-1',
  inputSchema: z.object({ message: z.string() }),
  outputSchema: z.object({ list: z.string() }),
  execute: async ({ inputData, mastra }) => {
    const { message } = inputData

    const testAgent = mastra.getAgent('testAgent')
    const response = await testAgent.generate(
      `Ubah pesan ini menjadi poin-poin: ${message}`,
      {
        memory: {
          thread: 'user-123',
          resource: 'test-123',
        },
      },
    )

    return { list: response.text }
  },
})

Perhatikan parameter mastra pada execute. Runtime menyediakannya, dan dari situ kamu bisa mengambil agent mana pun yang terdaftar — persis seperti yang kamu lakukan di skrip biasa.

Cara ini dipakai saat kamu perlu mengendalikan bagaimana agent dipanggil. Contoh di atas menunjukkan satu alasannya: meneruskan opsi memory supaya percakapan tercatat pada thread tertentu. Alasan lain: menyusun prompt dari beberapa sumber, atau mengolah respons sebelum meneruskannya.

Cara kedua: agent sebagai langkah

Kalau kamu tidak perlu mengubah cara agent dipanggil, ada bentuk yang jauh lebih ringkas:

ts
// src/mastra/workflows/ringkas-workflow.ts
import { createWorkflow, createStep } from '@mastra/core/workflows'
import { testAgent } from '../agents/test-agent.ts'

const step1 = createStep(testAgent)

export const testWorkflow = createWorkflow({ /* ... */ })
  .map(async ({ inputData }) => {
    const { message } = inputData
    return {
      prompt: `Ubah pesan ini menjadi poin-poin: ${message}`,
    }
  })
  .then(step1)
  .then(step2)
  .commit()

createStep(testAgent) mengubah agent menjadi langkah. Tapi ada satu hal yang harus dipahami sebelum ini bekerja.

Schema default agent sebagai langkah

Saat tidak ada opsi structuredOutput, agent yang dipakai sebagai langkah memakai schema bawaan:

ts
{
  inputSchema: {
    prompt: string
  },
  outputSchema: {
    text: string
  }
}

Artinya langkah itu mengharapkan properti prompt dan mengembalikan properti text.

Inilah kenapa contoh di atas memakai .map() sebelum .then(step1). Keluaran langkah sebelumnya bernama message, sementara agent menuntut prompt. .map() yang menjembatani — sekaligus menjadi tempat kamu menyusun kalimat prompt-nya.

inputData: { message: "..." }

     .map()  ← menyusun prompt

      { prompt: "Ubah pesan ini menjadi poin-poin: ..." }

   createStep(testAgent)

      { text: "- poin satu\n- poin dua" }

Agent dengan keluaran terstruktur

Keluaran bertipe { text: string } sulit disambung ke langkah berikutnya dengan aman. Langkah setelahnya harus mengurai teks itu — dan kita sudah membahas di 1.4 kenapa itu ide buruk.

Solusinya: berikan structuredOutput saat membuat langkah.

ts
// src/mastra/workflows/artikel-workflow.ts
import { createStep } from '@mastra/core/workflows'
import { z } from 'zod'
import { testAgent } from '../agents/test-agent.ts'

const articleSchema = z.object({
  title: z.string(),
  summary: z.string(),
  tags: z.array(z.string()),
})

const agentStep = createStep(testAgent, {
  structuredOutput: { schema: articleSchema },
})

Sekarang outputSchema langkah itu mengikuti schema yang kamu berikan, sehingga langkah berikutnya menerima data bertipe — dan sambungannya diverifikasi compiler seperti langkah biasa.

Ini pola yang layak dijadikan default. Agent di tengah workflow hampir selalu lebih berguna kalau keluarannya terstruktur, karena langkah setelahnya adalah kode, bukan manusia.

Memilih di antara keduanya

Panggil dari execute()createStep(agent)
Kendali atas pemanggilanPenuhTerbatas pada opsi createStep
Jumlah kodeLebih banyakRingkas
Opsi memoryBisaTidak langsung
Keluaran terstrukturLewat generate()Lewat opsi structuredOutput
Cocok untukKasus khususSebagian besar kasus

Saran praktis: mulai dengan createStep(agent), dan pindah ke pemanggilan manual hanya saat kamu benar-benar butuh sesuatu yang tidak disediakannya.

Tool di dalam workflow

Tool juga bisa dipanggil dari langkah workflow. Perlu diingat perbedaan mendasarnya dari pemakaian tool oleh agent:

  • Agent memanggil tool karena ia memutuskan tool itu relevan
  • Workflow memanggil tool karena kamu menuliskannya di alur

Dalam konteks workflow, tool pada dasarnya adalah fungsi bertipe yang bisa dipakai ulang. Kalau logika itu hanya dipakai di satu workflow dan tidak pernah oleh agent, seringkali lebih sederhana menulisnya langsung sebagai step — tanpa perlu description yang memang tidak akan dibaca siapa pun.

Arah sebaliknya: workflow dipanggil agent

Ingat dari 2.1 bahwa hubungan ini bisa dibalik. Sebuah workflow yang didaftarkan pada agent lewat konfigurasi workflows otomatis menjadi tool bernama workflow-<key>:

ts
export const researchAgent = new Agent({
  id: 'research-agent',
  name: 'Research Agent',
  instructions: 'Kamu asisten riset.',
  model: 'openai/gpt-5.6-sol',
  workflows: { researchWorkflow },
})

Pola ini sangat berguna dalam praktik: agent menangani percakapan dan memutuskan kapan sebuah proses perlu dijalankan; workflow memastikan proses itu berjalan dengan urutan yang benar setiap kali.

Kamu mendapat keluwesan agent di lapisan percakapan, dan determinisme workflow di lapisan eksekusi.

Kesalahan umum

Gejala: Error tipe pada .then(agentStep) yang menyebut properti prompt tidak ditemukan. Penyebab: Agent yang dipakai sebagai langkah memakai schema bawaan yang mengharapkan { prompt: string }, sementara langkah sebelumnya menghasilkan nama properti yang berbeda. Perbaikan: Sisipkan .map() sebelum langkah agent untuk membentuk objek berisi prompt. Ini juga tempat yang tepat untuk menyusun kalimat prompt-nya.

Gejala: Langkah setelah agent menerima teks yang bentuknya berubah-ubah, sehingga logika pengurainya kadang berhasil kadang gagal. Penyebab: Agent memakai schema keluaran bawaan { text: string }, dan langkah berikutnya mencoba mengurai prosa bebas. Perbaikan: Berikan structuredOutput pada createStep(agent, { ... }) sehingga keluaran langkah itu bertipe dan tervalidasi. Jangan mengurai teks bebas di dalam workflow.

Coba sendiri

Tantangan: Bangun keluhan-workflow yang memproses keluhan pelanggan dari teks bebas menjadi tiket yang terstruktur dan terarah.

Alur yang diminta:

  1. bersihkan — langkah kode: rapikan teks masukan
  2. klasifikasi — langkah agent dengan structuredOutput: hasilkan kategori, urgensi 1–5, dan ringkasan satu kalimat
  3. routing — langkah kode: tentukan tim tujuan berdasarkan kategori dan urgensi
  4. balasan — langkah agent: susun draf balasan untuk pelanggan
  5. simpan — langkah kode: gabungkan semuanya menjadi objek tiket

Ketentuan:

  1. Langkah 2 memakai createStep(agent, { structuredOutput }), didahului .map()
  2. Langkah 4 memakai pemanggilan manual dari dalam execute(), karena ia perlu menyusun prompt dari dua sumber: keluhan asli dan hasil klasifikasi
  3. Langkah 3 tidak boleh memanggil model sama sekali — ini aturan bisnis murni
  4. Simpan hasil klasifikasi ke workflow state, supaya langkah 5 bisa membacanya tanpa dioper melalui langkah 4
  5. Jalankan tiga keluhan berbeda dan periksa hasilnya

Checklist penerimaan:

  • [ ] Langkah 2 menghasilkan objek bertipe, bukan teks — dan langkah 3 membacanya tanpa mengurai string
  • [ ] Langkah 3 murni kode; tidak ada panggilan model di dalamnya
  • [ ] Langkah 4 berhasil menyusun prompt dari dua sumber
  • [ ] Langkah 5 membaca hasil klasifikasi dari state, bukan dari inputData
  • [ ] Kamu bisa menjelaskan kenapa langkah 2 dan 4 memakai cara berbeda
  • [ ] Di Studio, kelima langkah terlihat terpisah dengan durasinya masing-masing

Petunjuk: Ketentuan 3 adalah yang paling penting secara desain, dan paling mudah dilanggar. Ada godaan untuk menyerahkan routing ke model juga — toh ia sudah dipanggil di langkah sebelumnya. Tahan godaan itu. Aturan seperti "urgensi 5 selalu ke tim eskalasi" adalah kebijakan perusahaan, dan kebijakan tidak seharusnya bervariasi antar pemanggilan.

Ikhtisar

  • Dua cara memakai agent dalam workflow: memanggil dari dalam execute() lewat parameter mastra, atau createStep(agent).
  • Panggil dari execute() saat perlu mengendalikan pemanggilan — opsi memory, prompt dari banyak sumber, atau pengolahan respons.
  • Agent sebagai langkah memakai schema bawaan { prompt } masuk, { text } keluar — karena itu hampir selalu didahului .map().
  • Berikan structuredOutput supaya keluaran agent bertipe dan bisa disambung dengan aman. Jangan mengurai teks bebas di dalam workflow.
  • Tool bisa dipanggil dari langkah, tapi kalau logikanya hanya dipakai di satu workflow, menulisnya langsung sebagai step lebih sederhana.
  • Arah sebaliknya juga berlaku: workflow yang didaftarkan pada agent menjadi tool workflow-<key>agent untuk keluwesan, workflow untuk determinisme.

Lanjut ke mana

Satu kemampuan workflow yang paling khas belum dibahas: berhenti di tengah jalan, menunggu manusia selama berhari-hari, lalu melanjutkan dari titik yang sama — 4.5 Suspend & Resume.

Materi belajar mandiri. Bukan dokumentasi resmi Mastra.