Tất cả bài

Tự build chat agent VN trong 1 ngày — bằng template open source LocDo

Walk-through 6 bước (clone repo → config endpoint → custom tool → custom persona → deploy Vercel → test) dùng template open source MIT của LocDo. Có sẵn UI + tool calling + VN persona, mất 1 ngày thật.

2 tháng 5, 2026Loc Do
TutorialAI AgentOpen SourceNext.js

Tự build chat agent VN trong 1 ngày — bằng template open source LocDo

Anh đang đọc 1 bài blog có chat widget bot trả lời live ở góc dưới phải. Đó là exact pattern bài này hướng dẫn build — và nó mã nguồn mở MIT.

github.com/locdo-freelancer/locdo-chat-agent-vn-starter

Em viết bài này vì 90% boilerplate "AI agent" trên GitHub là tiếng Anh, persona "Quý khách" cứng nhắc, và đa số assume OpenAI direct API. Team VN copy về xài → bot nói kiểu ChatGPT, đốt token, không close lead. Starter của LocDo ngược lại: VN-first persona, tool-first answers, plug bất kỳ OpenAI-compat endpoint nào.

Mục tiêu bài: từ git clone đến chat agent live trên Vercel trong 1 ngày làm việc. Không phải 1 tuần. Không phải 1 sprint.


Cái anh sẽ có sau 1 ngày

  • Chat widget góc trang (mobile + desktop) tự động xử Esc, sessionStorage, status indicator.
  • 5 tool out-of-box: searchCourses, searchProducts, getServices, listFAQ, captureLead.
  • Multi-step tool calling — model tự decide khi nào lookup, khi nào hỏi, khi nào đề xuất.
  • VN consultant persona: ngắn, sắc, không filler, anchor thị trường VN (Misa / Fast / Zalo / MoMo).
  • simulateStreamingMiddleware workaround cho gateway nào drop tool_calls trong stream (rất hay gặp).
  • MIT license — anh fork, đổi brand, dùng commercial OK.

Bước 1 — Clone + cài đặt (5 phút)

git clone https://github.com/locdo-freelancer/locdo-chat-agent-vn-starter
cd locdo-chat-agent-vn-starter
pnpm install
cp .env.example .env.local

Mở .env.local:

LLM_BASE_URL=https://api.openai.com/v1     # hoặc Anthropic, Google, OpenRouter, gateway của anh
LLM_API_KEY=sk-...
LLM_MODEL=gemini-2.5-flash

Cheap+fast cho chat agent: gemini-2.5-flash (~$0.30/M input). Đắt nhưng giỏi: claude-sonnet-4.6. Tránh alias auto — đa số gateway không resolve.

pnpm dev

Mở http://localhost:3000 → chat widget góc dưới phải. Bấm thử.


Bước 2 — Custom tool (1-2 tiếng)

Tool ở app/lib/chat/tools.ts. Pattern mỗi tool:

searchCourses: tool({
  description: "Search programming courses. Use when user asks about courses, lessons.",
  inputSchema: z.object({
    query: z.string().optional(),
    level: z.enum(["beginner", "intermediate", "advanced"]).optional(),
  }),
  execute: async ({ query, level }) => {
    // ← thay phần này bằng DB / API call của anh
    let items = MY_COURSES_FROM_DB;
    if (level) items = items.filter((c) => c.level === level);
    return { type: "courseList" as const, items };
  },
}),

3 thứ cần biết:

  1. description là model đọc để decide khi nào gọi. Viết action-oriented: "Use when user asks about X" thay vì "Returns list of X".
  2. inputSchema Zod → AI SDK tự convert sang JSON schema cho LLM. Field .optional() cho phép model bỏ trống.
  3. execute chạy server-side, return object có type discriminator → UI render thành card đẹp (sửa renderer trong ToolResultRenderer.tsx).

Ví dụ tool mới: searchProducts lookup từ Sanity CMS:

searchProducts: tool({
  description: "Search products in our catalog.",
  inputSchema: z.object({ query: z.string() }),
  execute: async ({ query }) => {
    const items = await fetch(`https://yourcms.io/api/products?q=${query}`).then(r => r.json());
    return { type: "productList" as const, items };
  },
}),

Bước 3 — Custom persona (30 phút)

System prompt ở app/lib/chat/system-prompt.ts. Cấu trúc giữ nguyên, chỉ đổi nội dung trong các block:

  • PHẠM VI: dịch vụ / sản phẩm / khóa học của anh.
  • CÁCH TƯ VẤN: 4 bước (HỎI → DỮ LIỆU → ĐỀ XUẤT → CHỐT). Đừng đổi structure — đó là phần làm bot không bán hàng cứng.
  • CẤM TUYỆT ĐỐI: list filler. Thêm những cụm shop cũ hay nói nhưng anh ghét.

Tip: 80% chất lượng đến từ ✅ và ❌ ví dụ trong prompt. Ví dụ "❌ Bạn cần làm gì cụ thể? · ✅ Anh đang dùng Misa, Fast hay Excel?" làm bot hỏi sắc hơn 5x so với generic instruction.


Bước 4 — Lead capture wiring (1 tiếng)

Tool captureLead trong template hiện chỉ console.log. Anh wire:

  1. Vào DB: Postgres / Supabase / Notion / Airtable — POST insert.
  2. Email notify team: nodemailer + Gmail app password (free) hoặc Resend (free 100/ngày).
  3. Slack notify: webhook URL → POST channel.

Pattern fire-and-forget — đừng để email fail làm fail UX:

execute: async (lead) => {
  await db.insert("leads", lead);
  void sendEmail(lead).catch(console.error);   // không block
  return { type: "leadConfirm", ok: true, message: "Đã ghi nhận! Team sẽ liên hệ trong 24h." };
},

Bước 5 — Deploy Vercel (15 phút)

pnpm vercel

Sau khi link project, set env trên Vercel dashboard hoặc CLI:

vercel env add LLM_BASE_URL production
vercel env add LLM_API_KEY production
vercel env add LLM_MODEL production

Push master → deploy auto.


Bước 6 — Test + iterate (2 tiếng)

5 prompt em chạy lần đầu kiểu nào cũng:

  1. Greeting — "Chào bạn" → bot có vào persona không, hay default "Hi! How can I help"?
  2. Tool intent — "Cho mình xem khóa học" → có call searchCourses không, hay text rỗng?
  3. Pricing question — "Bao nhiêu tiền?" → có call listFAQ rồi mới hỏi clarifying không?
  4. Out-of-scope — "Hôm nay thời tiết Hà Nội" → có refuse + redirect không?
  5. Lead intent — "Mình muốn tư vấn" → có chủ động xin email + gọi captureLead không?

Nếu (3) hoặc (5) fail → tweak system prompt cứng hơn (xem ví dụ ✅/❌ trong file). 90% bug "bot không gọi tool" sửa bằng prompt, không phải code.


Cảnh báo

  1. Đừng dùng stream: true mặc định nếu gateway không hỗ trợ tool_calls trong chunks. Cliproxy, OpenRouter cũ, một số self-host stack đều dính. Template đã wrap simulateStreamingMiddleware để workaround.
  2. generateTextstreamText: nếu dùng generateText cho non-streaming, mất 5-10s đầu hiển thị "...". Dùng streamText + middleware là balance tốt nhất.
  3. Rate limit per IP — template có sẵn (in-memory). Production cần Vercel KV hoặc Redis.
  4. Tool call không reliable với model nhỏgpt-5-nano, gemini-flash-lite hay miss instruction. Dev test với flash/haiku, prod scale lên.

Khi nào nên hire LocDo build thay tự build?

Self-build OK nếu anh là dev + có 1 ngày + scope đơn giản (chat thông tin + lead capture).

Hire LocDo khi:

  • Cần tích hợp Misa / Fast / SAP / Salesforce — anh không muốn debug OAuth + rate limit nhà người ta.
  • Cần RAG trên knowledge base 100+ trang — chunking strategy không trivial.
  • Cần multi-channel (web + Zalo + email) — Zalo OA template approval mất 3-5 ngày.
  • Cần audit log + RLS + multi-tenant — cho enterprise customer.
  • Cần SLA + on-call — bot down lúc 2h sáng anh không muốn fix.

Range giá em viết chi tiết trong bài "AI agent VN giá bao nhiêu?".

Hỏi LocDo Assistant ở góc dưới phải nếu cần hỗ trợ — em có thể quote sơ bộ trong vài tin.

— Loc Do, founder LocDo.Tech

Có dự án muốn ước tính chi phí?