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.
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:
- Arsitektur aman (sandbox-first)
- Tool calling yang terkontrol
- 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:
- User kirim task
- Orchestrator minta rencana dari model
- Model memanggil tools seperlunya
- Tool dieksekusi di sandbox
- 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
-
Sandbox-first, permission-later
Jangan pernah eksekusi command agent langsung di host production. -
Tool curation > tool quantity
Lebih baik 5 tool yang solid daripada 30 tool yang ambigu. -
Deterministic middleware
Tambahkan langkah pasti setelah run (mis. always summarize diff, always attach logs). -
Observability wajib
Simpan trace: prompt, tool call, stdout/stderr, durasi, token usage. -
Policy versioning
Simpan kebijakan allowlist sebagai file berversi agar audit mudah. -
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:
- Generate patch
- Run test/lint
- Generate changelog
- 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:
- Tambah sandbox container runtime (Docker/Firecracker)
- Tambah observability + trace dashboard
- Integrasi issue tracker (Linear/Jira) dan GitHub PR automation
- Implementasi role-based approval
Ingat: agent yang bagus bukan yang “paling pintar”, tapi yang paling bisa diandalkan.
10) References
- GitHub Trending: https://github.com/trending
- Open SWE (repo): https://github.com/langchain-ai/open-swe
- Open SWE announcement: https://blog.langchain.com/open-swe-an-open-source-framework-for-internal-coding-agents/
- LangGraph Overview: https://docs.langchain.com/oss/python/langgraph/overview
- Vercel AI SDK Next.js Quickstart: https://ai-sdk.dev/docs/getting-started/nextjs-app-router
- GitHub Copilot Agents docs: https://docs.github.com/en/copilot/how-tos/use-copilot-agents
- OpenAI Agents guide: https://developers.openai.com/api/docs/guides/agents
- MCP Introduction: https://modelcontextprotocol.io/introduction
Kalau kamu mau, setelah ini kita bisa bikin Part 2: implementasi “issue-to-PR automation” lengkap dengan draft PR generator dan reviewer checklist otomatis.