dailytutorfor.you
Web Development

Tutorial Lengkap: Membangun AI Coding Agent Internal dengan Next.js (2026)

Panduan end-to-end membangun AI coding agent internal berbasis Next.js, AI SDK, dan arsitektur sandbox yang aman. Lengkap dengan konsep, diagram, implementasi runnable, best practices, serta kesalahan umum yang wajib dihindari.

9 menit baca

Tutorial Lengkap: Membangun AI Coding Agent Internal dengan Next.js (2026)

Durasi baca: ±15 menit
Target pembaca: Web developer yang ingin membangun AI agent internal untuk workflow engineering.

1) Introduction — What and Why

Pernah kepikiran, “Kenapa bug sederhana masih makan waktu 2-3 jam?” atau “Kenapa context issue di Slack/Linear/GitHub sering tercecer?”

Di 2026, tren engineering bergerak ke internal coding agents: bot/agent yang bisa membaca issue, menjalankan command di environment terisolasi, membuat perubahan kode, lalu membuka PR secara otomatis.

Dari riset tren:

  • GitHub Trending menunjukkan lonjakan proyek agentic engineering (mis. langchain-ai/open-swe)
  • X Explore ramai diskusi soal agent orchestration, sandboxing, dan reliability
  • DEV Community menonjolkan topik #ai, #webdev, #automation, #typescript

Artinya jelas: developer bukan cuma butuh “chatbot”, tapi agent yang bisa kerja dengan batas aman.

Di tutorial ini, kamu akan membangun versi sederhana namun production-minded dari AI coding agent berbasis Next.js App Router + AI SDK. Fokus kita:

  1. Arsitektur aman (sandbox-first)
  2. Tool calling yang terkontrol
  3. Alur issue → eksekusi → hasil yang bisa diaudit

2) Prerequisites

Sebelum mulai, siapkan:

  • Node.js 20+ (disarankan 22)
  • pnpm atau npm
  • Pemahaman dasar Next.js App Router
  • Familiar dengan REST API dan async/await
  • API key LLM provider (contoh: OpenAI/Vercel AI Gateway)

Opsional tapi sangat membantu:

  • Docker (untuk sandbox command runner)
  • Redis/Postgres (untuk queue dan persistence)

3) Core Concepts — Fundamental dengan Analogi

Bayangkan kamu punya manajer proyek junior super cepat:

  • Dia baca issue
  • Dia rencanakan langkah
  • Dia delegasi tugas kecil
  • Dia lapor hasil

Tapi kalau kamu kasih akses root ke server production, ini bahaya. Jadi konsep intinya:

a) Orchestrator

Otak utama yang memutuskan urutan kerja agent. Ibarat “konduktor orkestra”.

b) Tools

Tangan agent. Contoh: baca file, jalankan command, fetch URL, create PR.

c) Sandbox

Ruang kerja terisolasi. Kalau ada error, “ledakannya” tidak kena sistem utama.

d) Memory & Context

Agent perlu context issue, komentar, dan aturan repo (AGENTS.md atau policy internal).

e) Guardrails

Aturan pagar: command allowlist, batas waktu, batas token, path yang boleh diubah.

Tanpa guardrails, agent bisa cepat tapi liar. Dengan guardrails, agent mungkin sedikit lebih lambat tapi jauh lebih aman.

4) Architecture / Diagram

Berikut arsitektur yang kita implementasikan:

┌─────────────────────────────────────────────────────────┐ │ Frontend (Next.js) │ │ Chat UI / Issue Input / Execution Timeline / Logs │ └───────────────────────┬─────────────────────────────────┘ │ POST /api/agent/run ▼ ┌─────────────────────────────────────────────────────────┐ │ Agent Orchestrator API │ │ - Build prompt/context │ │ - Call LLM (stream) │ │ - Parse tool calls │ │ - Enforce policies │ └───────────────┬───────────────────────┬─────────────────┘ │ │ ▼ ▼ ┌─────────────────────┐ ┌────────────────────────┐ │ Tool Executor │ │ Context Provider │ │ - read/write file │ │ - issue details │ │ - run command │ │ - repo rules │ │ - git diff summary │ │ - conversation memory │ └──────────┬──────────┘ └────────────────────────┘ │ ▼ ┌──────────────────────┐ │ Isolated Sandbox │ │ (ephemeral runtime) │ └──────────────────────┘

Flow singkat:

  1. User kirim task
  2. Orchestrator minta rencana dari model
  3. Model memanggil tools seperlunya
  4. Tool dieksekusi di sandbox
  5. Hasil dirangkum + dikembalikan ke UI

5) Step-by-Step Implementation (Runnable)

Kita buat project minimal tapi jalan penuh.

Step 1 — Inisialisasi project

pnpm create next-app@latest ai-coding-agent --ts --app --eslint cd ai-coding-agent pnpm add ai @ai-sdk/openai zod

Buat .env.local:

OPENAI_API_KEY=your_api_key_here AGENT_MAX_STEPS=6

Step 2 — Definisikan policy dan tool schema

Buat file lib/agent-policy.ts:

// lib/agent-policy.ts export const ALLOWED_COMMANDS = [ "npm test", "pnpm test", "npm run lint", "pnpm lint", "npm run build", "pnpm build", ] as const; export function isAllowedCommand(cmd: string): boolean { return ALLOWED_COMMANDS.some((allowed) => cmd.trim().startsWith(allowed)); } export function sanitizePath(inputPath: string): string { if (inputPath.includes("..")) { throw new Error("Path traversal terdeteksi"); } return inputPath.replace(/^\/+/, ""); }

Step 3 — Buat tool executor dengan error handling

Buat lib/tools.ts:

// lib/tools.ts import { promises as fs } from "fs"; import path from "path"; import { exec as execCb } from "child_process"; import { promisify } from "util"; import { isAllowedCommand, sanitizePath } from "./agent-policy"; const exec = promisify(execCb); const WORKSPACE_ROOT = path.join(process.cwd(), "workspace"); export async function readFileTool(filePath: string): Promise<string> { const safePath = sanitizePath(filePath); const fullPath = path.join(WORKSPACE_ROOT, safePath); try { const content = await fs.readFile(fullPath, "utf8"); return content; } catch (error) { throw new Error(`Gagal membaca file: ${String(error)}`); } } export async function writeFileTool(filePath: string, content: string): Promise<string> { const safePath = sanitizePath(filePath); const fullPath = path.join(WORKSPACE_ROOT, safePath); try { await fs.mkdir(path.dirname(fullPath), { recursive: true }); await fs.writeFile(fullPath, content, "utf8"); return `Berhasil menulis ${safePath}`; } catch (error) { throw new Error(`Gagal menulis file: ${String(error)}`); } } export async function runCommandTool(command: string): Promise<string> { if (!isAllowedCommand(command)) { throw new Error(`Command tidak diizinkan oleh policy: ${command}`); } try { const { stdout, stderr } = await exec(command, { cwd: WORKSPACE_ROOT, timeout: 60_000, env: { ...process.env, CI: "true" }, maxBuffer: 2 * 1024 * 1024, }); return [stdout, stderr].filter(Boolean).join(" ").trim() || "Command selesai tanpa output"; } catch (error) { throw new Error(`Eksekusi command gagal: ${String(error)}`); } }

Step 4 — Route API agent dengan tool calling

Buat app/api/agent/run/route.ts:

// app/api/agent/run/route.ts import { openai } from "@ai-sdk/openai"; import { generateText, tool } from "ai"; import { z } from "zod"; import { readFileTool, writeFileTool, runCommandTool } from "@/lib/tools"; const SYSTEM_PROMPT = ` Kamu adalah AI coding agent internal. Prioritas: keamanan, kejelasan, reproducibility. Selalu jelaskan rencana sebelum eksekusi. Jangan gunakan command di luar allowlist. `; export async function POST(req: Request) { try { const body = await req.json(); const task = String(body?.task ?? "").trim(); if (!task) { return Response.json({ error: "Task wajib diisi" }, { status: 400 }); } const result = await generateText({ model: openai("gpt-5.1"), system: SYSTEM_PROMPT, prompt: `Task: ${task}`, tools: { read_file: tool({ description: "Baca file dari workspace", inputSchema: z.object({ path: z.string().min(1) }), execute: async ({ path }) => { return await readFileTool(path); }, }), write_file: tool({ description: "Tulis file ke workspace", inputSchema: z.object({ path: z.string().min(1), content: z.string() }), execute: async ({ path, content }) => { return await writeFileTool(path, content); }, }), run_command: tool({ description: "Jalankan command yang diizinkan policy", inputSchema: z.object({ command: z.string().min(1) }), execute: async ({ command }) => { return await runCommandTool(command); }, }), }, maxSteps: Number(process.env.AGENT_MAX_STEPS ?? 6), }); return Response.json({ ok: true, text: result.text, steps: result.steps?.length ?? 0, }); } catch (error) { console.error("[agent-run-error]", error); return Response.json( { ok: false, error: error instanceof Error ? error.message : "Unknown error" }, { status: 500 } ); } }

Step 5 — UI sederhana untuk menguji agent

Buat app/page.tsx:

"use client"; import { useState } from "react"; export default function HomePage() { const [task, setTask] = useState("Buat ringkasan struktur project dan rekomendasi perbaikan awal"); const [result, setResult] = useState(""); const [loading, setLoading] = useState(false); const [error, setError] = useState(""); async function runAgent() { setLoading(true); setError(""); setResult(""); try { const res = await fetch("/api/agent/run", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ task }), }); const data = await res.json(); if (!res.ok || !data.ok) { throw new Error(data.error ?? "Gagal menjalankan agent"); } setResult(data.text); } catch (err) { setError(err instanceof Error ? err.message : "Terjadi error"); } finally { setLoading(false); } } return ( <main style={{ maxWidth: 860, margin: "32px auto", fontFamily: "sans-serif" }}> <h1>AI Coding Agent Internal</h1> <p>Masukkan task engineering, lalu jalankan agent dengan batas aman.</p> <textarea value={task} onChange={(e) => setTask(e.target.value)} rows={6} style={{ width: "100%", padding: 12 }} /> <button onClick={runAgent} disabled={loading} style={{ marginTop: 12, padding: "10px 16px" }}> {loading ? "Menjalankan..." : "Run Agent"} </button> {error && <p style={{ color: "crimson" }}>Error: {error}</p>} {result && ( <section style={{ marginTop: 24 }}> <h2>Hasil</h2> <pre style={{ whiteSpace: "pre-wrap", background: "#f5f5f5", padding: 12 }}>{result}</pre> </section> )} </main> ); }

Jalankan:

mkdir -p workspace pnpm dev

Buka http://localhost:3000, lalu uji task sederhana seperti:

  • “Baca package.json dan jelaskan dependency utama”
  • “Jalankan pnpm lint dan ringkas errornya”

6) Best Practices — Tips dari Industri

  1. Sandbox-first, permission-later
    Jangan pernah eksekusi command agent langsung di host production.

  2. Tool curation > tool quantity
    Lebih baik 5 tool yang solid daripada 30 tool yang ambigu.

  3. Deterministic middleware
    Tambahkan langkah pasti setelah run (mis. always summarize diff, always attach logs).

  4. Observability wajib
    Simpan trace: prompt, tool call, stdout/stderr, durasi, token usage.

  5. Policy versioning
    Simpan kebijakan allowlist sebagai file berversi agar audit mudah.

  6. Human-in-the-loop untuk high-risk action
    Untuk perubahan sensitif (auth, billing, security), wajib approval manual.

7) Common Mistakes — Yang Sering Bikin Gagal

Mistake 1: Memberi akses shell tanpa batas

Dampak: agent bisa menjalankan command destruktif.
Solusi: allowlist command + timeout + maxBuffer.

Mistake 2: Tidak membatasi path file

Dampak: path traversal (../../).
Solusi: sanitize path, pakai root workspace eksplisit.

Mistake 3: Prompt terlalu umum

Dampak: output “halusinasi” atau tidak actionable.
Solusi: tambah context issue, constraints, definition of done.

Mistake 4: Tidak ada retry strategy

Dampak: run gagal karena error sementara.
Solusi: retry terkontrol untuk network/tool transient error.

Mistake 5: Mengabaikan biaya token

Dampak: cost bengkak tanpa nilai bisnis.
Solusi: batasi max steps, ringkas context, cache hasil retrieval.

8) Advanced Tips — Untuk yang Mau Lebih Dalam

a) Multi-agent pattern

Pisahkan role:

  • Planner agent (membuat rencana)
  • Executor agent (menjalankan tools)
  • Reviewer agent (quality gate)

b) Event-driven queue

Gunakan queue (BullMQ/Kafka/SQS) agar task agent tidak memblokir request web utama.

c) PR-ready workflow

Tambahkan pipeline otomatis:

  1. Generate patch
  2. Run test/lint
  3. Generate changelog
  4. Open draft PR

d) Memory jangka panjang

Simpan lesson learned per repo (mis. pola arsitektur, style rule) untuk run berikutnya.

e) Safety scoring

Beri skor risiko setiap action (read-only, write, command, network). Wajib approval jika skor tinggi.

9) Summary & Next Steps

Kita sudah membangun fondasi AI coding agent internal yang:

  • Berbasis Next.js modern
  • Memakai tool calling terstruktur
  • Memiliki guardrails keamanan dasar
  • Bisa dijalankan dan diuji secara nyata

Kalau kamu ingin lanjut ke level production, urutan prioritasnya:

  1. Tambah sandbox container runtime (Docker/Firecracker)
  2. Tambah observability + trace dashboard
  3. Integrasi issue tracker (Linear/Jira) dan GitHub PR automation
  4. Implementasi role-based approval

Ingat: agent yang bagus bukan yang “paling pintar”, tapi yang paling bisa diandalkan.

10) References


Kalau kamu mau, setelah ini kita bisa bikin Part 2: implementasi “issue-to-PR automation” lengkap dengan draft PR generator dan reviewer checklist otomatis.