Skip to content

API Layer: Hono on Cloudflare Workers

Để cung cấp các API endpoint bảo mật, xử lý webhook và trao đổi dữ liệu với ứng dụng client (Frontend), Hanoi Agents sử dụng framework Hono chạy trực tiếp trên môi trường Cloudflare Workers.


1. Why Choose Hono for Serverless Projects?

Hono là một web framework thế hệ mới được thiết kế tối ưu riêng cho môi trường biên (Edge) và Serverless nhờ các đặc tính:

  • Siêu nhẹ và Siêu nhanh: Kích thước bundle cực nhỏ, thời gian khởi động lạnh (Cold Start) gần như bằng không.
  • TypeScript Native: Hỗ trợ kiểu dữ liệu (Types) an toàn từ đầu vào (request validation) đến đầu ra (response JSON).
  • Chuẩn Web tiêu chuẩn (Web Standards): Sử dụng trực tiếp các đối tượng tiêu chuẩn như Request, Response, và Fetch API của trình duyệt thay vì phụ thuộc vào Node.js API truyền thống.
  • Dễ dàng tích hợp Cloudflare Bindings: Hono truy cập trực tiếp vào các tài nguyên Cloudflare như KV, D1, Queue, và Durable Objects thông qua biến môi trường env.

2. Hono API Routing Structure

Dưới đây là mã nguồn cấu hình router API chính của dự án:

typescript
import { Hono } from "hono";
import { cors } from "hono/cors";

// Khai báo kiểu biến môi trường (Cloudflare Bindings)
type Bindings = {
  DB: D1Database;
  LEARNER_AGENTS: DurableObjectNamespace;
  EVALUATION_WORKFLOW: WorkflowNamespace;
  KV: KVNamespace;
};

const app = new Hono<{ Bindings: Bindings }>();

// Kích hoạt CORS hỗ trợ Frontend kết nối đa nền tảng
app.use("*", cors());

// Endpoint 1: Tiếp nhận bài làm mới từ học viên
app.post("/api/v1/submissions", async (c) => {
  const body = await c.req.json();
  const { learnerId, taskId, submissionContent } = body;

  // 1. Lưu bản ghi bài nộp tạm thời vào D1
  const { meta } = await c.env.DB.prepare(
    "INSERT INTO submissions (learner_id, task_id, content, status) VALUES (?, ?, ?, 'pending')"
  ).bind(learnerId, taskId, submissionContent).run();

  // 2. Gọi Learner Agent tương ứng để thông báo trạng thái
  const id = c.env.LEARNER_AGENTS.idFromName(learnerId);
  const agent = c.env.LEARNER_AGENTS.get(id);
  await agent.fetch(new Request("https://agent/event", {
    method: "POST",
    body: JSON.stringify({ type: "TASK_SUBMITTED", taskId })
  }));

  // 3. Khởi chạy Cloudflare Workflow chấm bài bất đồng bộ
  const instance = await c.env.EVALUATION_WORKFLOW.create({
    params: { learnerId, submissionId: meta.last_row_id }
  });

  return c.json({
    success: true,
    message: "Bài nộp đã được tiếp nhận và đang tiến hành chấm điểm.",
    workflowInstanceId: instance.id
  }, 202);
});

// Endpoint 2: Truy vấn thông tin tóm tắt năng lực của học viên
app.get("/api/v1/learners/:id/summary", async (c) => {
  const learnerId = c.req.param("id");

  // Truy cập trực tiếp Durable Object của Agent để lấy trạng thái bộ nhớ đệm
  const id = c.env.LEARNER_AGENTS.idFromName(learnerId);
  const agent = c.env.LEARNER_AGENTS.get(id);
  const response = await agent.fetch(new Request("https://agent/summary"));
  const summary = await response.json();

  return c.json(summary);
});

export default app;

Tài liệu được phân phối nội bộ phục vụ Hackathon 2026.