Skip to content

0.3 Proyek Pertama & Model Router

Tujuan bab

Setelah bab ini kamu bisa:

  • Membuat proyek Mastra baru, lewat CLI maupun secara manual
  • Menjelaskan format model router provider/model dan kenapa Mastra memakainya
  • Mengatur API key lewat .env tanpa menghardcode rahasia ke dalam kode
  • Menjalankan Mastra Studio dan memakainya untuk menguji agent
  • Mengenali dua kesalahan konfigurasi yang paling sering menghentikan pemula di langkah pertama

Prasyarat

Dua jalan membuat proyek

Mastra menyediakan CLI yang membuatkan seluruh struktur untukmu:

bash
npm create mastra@latest

Perintah ini interaktif — ia akan bertanya nama proyek, komponen apa saja yang ingin dibuatkan, dan penyedia model mana yang kamu pakai. Kalau kamu memakai package manager lain, padanannya pnpm create mastra@latest, yarn create mastra@latest, atau bun create mastra@latest.

Dua flag yang berguna:

bash
npm create mastra@latest --no-example              # tanpa agent contoh
npm create mastra@latest --template <nama-template> # dari template tertentu

Untuk belajar, saya sarankan jalan kedua: membangun manual. Bukan karena CLI-nya buruk, tapi karena enam langkah berikut memperlihatkan persis apa yang dibutuhkan sebuah proyek Mastra — dan itu pengetahuan yang terpakai saat suatu saat kamu harus menambahkan Mastra ke proyek yang sudah ada, di mana CLI tidak bisa membantu.

Langkah 1 — Direktori dan package.json

bash
mkdir my-first-agent && cd my-first-agent
npm init -y

Langkah 2 — Dependensi

bash
npm install -D typescript @types/node mastra@latest
npm install @mastra/core@latest zod@^4

Perhatikan pembagiannya. mastra (CLI) dan typescript masuk sebagai devDependencies karena hanya dipakai saat pengembangan dan build. @mastra/core dan zod masuk sebagai dependencies karena dibutuhkan saat aplikasi berjalan.

Langkah 3 — Script

Tambahkan ke package.json:

json
{
  "type": "module",
  "scripts": {
    "dev": "mastra dev",
    "build": "mastra build"
  }
}

"type": "module" bukan opsional. Mastra berjalan sebagai ES module; tanpa baris ini kamu akan menabrak error modul di langkah pertama.

Langkah 4 — TypeScript

Buat tsconfig.json:

json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ES2022",
    "moduleResolution": "bundler",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true,
    "allowImportingTsExtensions": true,
    "noEmit": true,
    "outDir": "dist"
  },
  "include": ["src/**/*"]
}

Ini bukan tsconfig yang bisa kamu ganti sesuka hati

"module": "ES2022" dan "moduleResolution": "bundler" adalah keharusan. Dokumentasi resmi menyatakan CommonJS akan menyebabkan error. Kalau kamu menyalin tsconfig.json dari proyek Node lama yang memakai "module": "commonjs", proyek Mastra-mu tidak akan jalan.

"allowImportingTsExtensions": true yang membuat impor ./tool.ts diterima compiler — dan sebentar lagi kamu akan lihat kenapa ekstensi itu penting.

Langkah 5 — API key

Buat file .env di akar proyek:

ini
OPENAI_API_KEY=sk-ganti-dengan-key-punyamu

Lalu pastikan .env masuk .gitignore:

.env
node_modules
.mastra

Nama variabelnya mengikuti penyedia yang kamu pakai — ini dibahas di bagian berikutnya.

Langkah 6 — Tool, agent, dan titik masuk

Tiga file. Pertama tool:

ts
// src/mastra/tools/weather-tool.ts
import { createTool } from '@mastra/core/tools'
import { z } from 'zod'

export const weatherTool = createTool({
  id: 'get-weather',
  description: 'Ambil cuaca terkini untuk sebuah kota',
  inputSchema: z.object({
    location: z.string().describe('Nama kota'),
  }),
  outputSchema: z.object({
    location: z.string(),
    temperatureCelsius: z.number(),
    conditions: z.string(),
  }),
  execute: async ({ location }) => {
    return { location, temperatureCelsius: 21, conditions: 'cerah' }
  },
})

Isinya masih data palsu, dan itu disengaja — bab ini soal menjalankan proyek, bukan soal tool. Tool sungguhan dibahas di Bagian 2.

Kedua, agent:

ts
// src/mastra/agents/weather-agent.ts
import { Agent } from '@mastra/core/agent'
import { weatherTool } from '../tools/weather-tool.ts'

export const weatherAgent = new Agent({
  id: 'weather-agent',
  name: 'Weather Agent',
  instructions: 'Kamu asisten cuaca. Pakai weatherTool untuk data cuaca.',
  model: 'openai/gpt-5.6-sol',
  tools: { weatherTool },
})

Ketiga, titik masuk:

ts
// src/mastra/index.ts
import { Mastra } from '@mastra/core'
import { weatherAgent } from './agents/weather-agent.ts'

export const mastra = new Mastra({
  agents: { weatherAgent },
})

Tiga file itu sudah cukup. Sekarang bagian yang paling perlu dipahami dari seluruh bab ini.

Model router: provider/model

Perhatikan baris ini:

ts
model: 'openai/gpt-5.6-sol',

Model ditulis sebagai string biasa dengan format provider/model-name. Tidak ada paket penyedia yang diimpor, tidak ada objek klien yang dibuat, tidak ada konfigurasi API key di dalam kode. Mekanisme ini disebut model router.

Yang dilakukan Mastra dari string itu ada dua: menentukan penyedia mana yang dihubungi, dan mencari sendiri environment variable yang sesuai untuk penyedia tersebut. Menulis openai/... berarti Mastra akan mencari OPENAI_API_KEY di environment.

Nilainya baru terasa saat kamu ingin berganti model:

ts
model: 'openai/gpt-5.6-sol'        // sebelum
model: 'anthropic/claude-sonnet-5' // sesudah

Satu baris, tanpa mengubah impor, tanpa memasang paket baru. Kalau kamu pernah memakai pustaka yang mengharuskan import OpenAI from 'openai' lalu new OpenAI({ apiKey }), kamu tahu berapa banyak kode yang biasanya ikut berubah.

Format yang salah

Ini bagian yang paling sering keliru, karena beberapa pustaka lain memakai tanda titik dua:

PenulisanStatus
'openai/gpt-5.6-sol'✅ Benar
'openai:gpt-5.6-sol'❌ Salah — pemisahnya garis miring, bukan titik dua
openai('gpt-5.6-sol')❌ Salah — jangan impor atau memanggil objek penyedia

Environment variable per penyedia

PenyediaPrefix modelEnvironment variable
OpenAIopenai/OPENAI_API_KEY
Anthropicanthropic/ANTHROPIC_API_KEY
Googlegoogle/GOOGLE_API_KEY

Satu catatan verifikasi yang jujur

Untuk Google, dua sumber resmi yang saya periksa tidak seragam: dokumentasi agent menyebut GOOGLE_API_KEY, sementara panduan pembuatan proyek menyebut GOOGLE_GENERATIVE_AI_API_KEY. Saya tidak bisa memastikan mana yang berlaku untuk versimu tanpa mencobanya.

Kalau kamu memakai Google, cek daftar resmi di https://mastra.ai/models/environment-variables. Untuk OpenAI dan Anthropic, kedua sumber sepakat, jadi tabel di atas aman.

Memastikan nama model, bukan menebaknya

Nama model berubah cukup sering, dan menebak dari ingatan hampir selalu meleset. Daftar lengkap yang berlaku ada di https://mastra.ai/models.

Beberapa yang terverifikasi saat materi ini ditulis:

  • openai/gpt-5.6-sol, openai/gpt-5-mini
  • anthropic/claude-sonnet-5, anthropic/claude-opus-5, anthropic/claude-haiku-4-5
  • google/gemini-3.8-flash, google/gemini-2.5-flash

Untuk belajar, model kelas menengah seperti openai/gpt-5-mini biasanya sudah cukup dan jauh lebih murah untuk dipakai berulang kali.

Menjalankan dan menguji

Dari akar proyek:

bash
npm run dev

Yang berjalan di baliknya adalah mastra dev. Perintah ini menyalakan server pengembangan sekaligus Mastra Studio. Buka:

http://localhost:4111

Studio adalah antarmuka untuk membangun, menguji, dan memeriksa agent tanpa menulis satu pun kode pemanggil. Kamu memilih agent dari daftar, mengetik pesan, dan melihat balasannya — beserta tool apa saja yang dipanggil di belakang layar.

Kemampuan terakhir itu yang membuat Studio layak dibuka sejak hari pertama. Saat agent memberi jawaban aneh, pertanyaan pertama selalu "dia sebenarnya memanggil apa?", dan Studio menjawabnya tanpa perlu menambahkan satu pun console.log.

Server yang sama juga mengekspos API untuk agent, tool, dan workflow-mu:

http://localhost:4111/api

Ini yang nanti dipakai frontend untuk berbicara dengan agent-mu, dibahas di 9.2.

Menjalankan tanpa Studio

Kadang kamu hanya ingin memanggil agent dari skrip. Node.js 22.18 ke atas bisa menjalankan file TypeScript secara langsung:

ts
// run.mjs
import { mastra } from './src/mastra/index.ts'

const agent = mastra.getAgentById('weather-agent')
const response = await agent.generate('Cuaca di Surabaya')
console.log(response.text)
bash
node run.mjs

Perhatikan getAgentById('weather-agent') — yang dipakai adalah nilai id pada konstruktor agent, bukan nama variabelnya dan bukan name.

Alur setup, diringkas

Kesalahan umum

Gejala: Aplikasi gagal jalan saat runtime dengan ERR_MODULE_NOT_FOUND yang menunjuk ke file lokalmu sendiri — padahal npx tsc --noEmit bersih tanpa satu error pun. Penyebab: Impor lokal ditulis tanpa ekstensi, misalnya from '../tools/weather-tool'. Dengan "moduleResolution": "bundler", TypeScript menerima penulisan itu tanpa mengeluh — tapi Node.js sebagai ES module tetap memerlukan ekstensi saat benar-benar memuat file. Perbaikan: Tulis from '../tools/weather-tool.ts'. Perlakukan ini sebagai kebiasaan tetap, karena type-check tidak akan menyelamatkanmu di sini. Inilah satu-satunya kelas kesalahan di bab ini yang lolos dari compiler.

Gejala: Error autentikasi dari penyedia model, atau pesan bahwa API key tidak ditemukan, padahal file .env sudah ada dan isinya benar. Penyebab: Biasanya salah satu dari tiga: nama variabel tidak cocok dengan penyedia yang dipakai (OPENAI_API_KEY padahal model-nya anthropic/...); format model memakai titik dua alih-alih garis miring sehingga penyedia tidak terdeteksi; atau .env tidak berada di akar proyek. Perbaikan: Cocokkan prefix model dengan nama variabelnya lewat tabel di atas, pastikan pemisahnya /, dan pastikan .env sejajar dengan package.json.

Coba sendiri

Tantangan: Buat proyek Mastra dari nol secara manual — tanpa npm create mastra — lalu buktikan ia jalan. Jangan pakai domain cuaca; buat agent penerjemah sederhana bernama translator-agent yang menerjemahkan teks ke bahasa yang diminta pengguna.

Ketentuan:

  1. Ikuti keenam langkah manual di bab ini
  2. Agent-mu tidak perlu tool sama sekali — cukup instructions dan model
  3. Jalankan npm run dev, buka Studio, dan uji dengan minimal tiga pesan
  4. Setelah berhasil, ganti nilai model ke penyedia yang berbeda, sesuaikan .env, lalu jalankan ulang

Checklist penerimaan:

  • [ ] npm run dev jalan tanpa error dan Studio terbuka di localhost:4111
  • [ ] translator-agent muncul di daftar agent Studio
  • [ ] Agent membalas dengan benar untuk tiga pesan uji
  • [ ] Setelah mengganti penyedia, agent tetap jalan — dan satu-satunya yang berubah di kode adalah satu baris model
  • [ ] .env tidak ikut ter-commit ke git

Petunjuk: Langkah 4 adalah inti latihan ini. Kalau kamu mendapati diri mengubah lebih dari satu baris untuk berganti penyedia, kemungkinan ada impor paket penyedia yang tidak seharusnya ada — model router justru dibuat supaya impor semacam itu tidak diperlukan.

Ikhtisar

  • Proyek Mastra bisa dibuat lewat npm create mastra@latest yang interaktif, atau manual dalam enam langkah. Cara manual mengajarkan apa yang sebenarnya dibutuhkan.
  • "type": "module", "module": "ES2022", dan "moduleResolution": "bundler" bersifat wajib. CommonJS menyebabkan error.
  • Model ditulis sebagai string provider/model — pemisahnya garis miring. Mastra mencari sendiri environment variable penyedia yang bersangkutan, jadi berganti model cukup mengubah satu baris.
  • Nama model berubah sering; verifikasi di https://mastra.ai/models alih-alih mengandalkan ingatan.
  • npm run dev menyalakan Studio di localhost:4111 — tempat kamu menguji agent dan melihat tool apa yang dipanggil, tanpa menulis kode pemanggil.
  • Impor lokal wajib berekstensi .ts. Type-check tidak menangkap pelanggaran ini; Node yang akan gagal saat runtime.

Lanjut ke mana

Lingkungan kerjamu sudah siap. Bagian 0 selesai — sekarang kita masuk ke primitif pertama dan bekerja serius dengannya: Bagian 1 — Agent.

Materi belajar mandiri. Bukan dokumentasi resmi Mastra.