AI Search Profile · vận hành thật

Kiểm tra backend đã hoạt động

Trang này được chính service phục vụ ở GET / — không phải một tệp tĩnh mở bằng file://, và đó là lý do mọi trạng thái bên dưới lấy được từ endpoint thật. Chạy bộ kiểm chứng runtime rồi dùng playground để đi thử luồng ngoài đời.

Kiểm soát tài liệu
Chủ tài liệu
Lê Đức Anh (Alex Le) — Chief Technology Officer, InCard
Loại tài liệu
Bảng điều khiển runtime (trang kiểm chứng)
Đối tượng đọc
Dev · QA · Vận hành
Phiên bản
v1.0
Cập nhật
2026-08-28
Phân loại
Nội bộ InCard — không phát hành ra ngoài
Chuẩn bị & chịu trách nhiệm nội dung: Lê Đức Anh (Alex Le) — CTO, InCard · anh.le@incard.biz
Đường demo 6 phút
  1. Nạp một bộ tri thức thật19 tài liệu → kho tri thức, một lần bấm, qua đúng đường khách hàng dùng
  2. Xem nó đang BIẾT gìbản đồ tri thức — chứng minh dữ liệu đã vào, không phải model tự biết
  3. Hỏi một câu khách hay hỏitrả lời đúng, kèm trích dẫn trỏ về tài liệu đã nạp
  4. Hỏi một câu nó PHẢI TỪ CHỐI“giữ phòng và giảm 20%” → nó từ chối. Đây là chỗ thuyết phục nhất
  5. Gắn một năng lựcchatbot thành agent — mở thêm việc mà KHÔNG sửa một dòng mã
  6. Điểm sẵn sàngmột con số đọc được, không cần thuật ngữ nào

DEMO 111/09 · D1 — «Trợ lý Chat trọn vẹn», đi hết A→Z ở một chỗ

Cần trước: đăng nhập role=admin  ·  Đây là khu vực duy nhất cần mở trong buổi hôm nay. Năm bước dưới đây là năm bước mà lộ trình khai cho mốc 11/9 — không phải một danh sách mới. Mỗi bước có: làm gì · bằng chứng phải thấy · nút nhảy tới màn thao tác.

Cổng của hôm nay — đạt hay không đạt, đọc bằng hai dòng
① Bậc 3 xanh
Bản khai đủ và câu ngoài biên bị TỪ CHỐI. Từ chối đúng là một nửa của bậc 3 — một trợ lý trả lời được mọi câu là một trợ lý chưa có ranh giới.
Bấm «Đo lại» để đọc
② Một kênh đã nối
Một Page/OA thật đã gắn vào một trợ lý. Nối kênh là thứ biến «chạy trên bàn demo» thành «khách nhắn được».
Bấm «Đo lại» để đọc

Khán giả hôm nay: BLĐ · PM · Sales. Mốc kế tiếp 18/9 (D2) thêm thoại và hình — không trình bày hôm nay, và hai mục đó đã được đẩy xuống sau khu vực này.

Đang đo trợ lý nào

Một workspace có nhiều trợ lý thì «đã xong mấy bước» là câu hỏi về một trợ lý cụ thể. Bản trước lấy trợ lý ĐẦU danh sách — tức phụ thuộc thứ tự nạp thư mục, và không gì trên màn hình nói con số đang thuộc về ai.

Vì sao gói vào MỘT khu vực thay vì để người trình bày tự cuộnTrước khu này, năm bước của mốc 11/9 nằm ở vị trí 6 · 12 · 17 · 18 · 21 trong một trang 31 mục — và hai mục thuộc mốc D2/D3 (voice, eyes) chen vào giữa bước ③ và bước ④. Người trình bày phải cuộn qua hai màn ngoài phạm vi để đi từ «hỏi thử» sang «bàn giao», và khán giả đọc ra là hệ đang nhảy cóc.

Khu này không sao chép một nút nào: mỗi bước chỉ nhảy tới đúng màn có thao tác thật. Sao chép nút sẽ tạo nguồn sự thật thứ hai, và bản sao sẽ lệch ngay lần sửa màn gốc kế tiếp — đúng kiểu hỏng mà _w.js vừa gây ra ở chỗ khác.

Con số ở mỗi bước là ĐO ĐƯỢC: chúng đọc getSetupProgress, getAgentList, getChannelList và bảng câu vàng — không một ô nào tự khai.

Đang có gì · thiếu gì · sắp có gì

Cần trước: —  ·  Mở được ngay, không cần đăng nhập. Hai ô ĐO ĐƯỢC đọc /version và /readyz — hai đường công khai.

Màn hình đầu tiên của một buổi trình bày. Mỗi con số dưới đây nói ra nó từ đâu ra — ĐO ĐƯỢC nghĩa là trang này vừa gọi service thật; KHAI BÁO nghĩa là một người đã gõ nó vào bản kê. Hai loại đó không được cộng lại thành một phần trăm: gộp chúng là cách một hệ mới viết xong trông y hệt một hệ đã chạy sáu tháng.

Năm mốc kiểm chứng trước ngày phát hành 30/9

Một mốc không xong vì có người tích vào ô. Nó xong khi bằng chứng ở dòng cần xanh xanh — và bằng chứng đó bấm chạy được ngay tại bước 12.

Từng mảng đang tới đâu

Một khoảng trống là việc của AI?

Ba trạng thái, ba người khác nhau phải làm — và chúng không thay thế nhau. Gộp chúng lại là cách một tính năng chưa cấu hình trông y hệt một tính năng chưa xây.

Đang đo...

Đọc từ bản kê đối chiếu ở bước 15 — KHAI BÁO. Nó chấm mã, không chấm bản đang chạy; cột bên phải là tỉ lệ mục «đã có» trên tổng số mục của nhóm.

Chưa xong — nói thẳng

Một bản trình bày chỉ có màu xanh là một bản trình bày không ai kiểm được. Đây là những mục đang dở hoặc cố ý không làm.

Vì sao không có MỘT con số phần trăm duy nhấtVì ba câu hỏi khác nhau: đã viết chưa (bản kê mã) · đang phục vụ chưa (/version khai khối nào bật, và vai trò tiến trình có nhận đường đó không) · đã chứng minh chưa (một lượt chạy thật có model + runId + usage trong trace). Một hệ có thể viết xong 100% mà phục vụ 0% — đo được 2026-08-30: bản 8 tiến trình bỏ lại 17/306 đường không ai phục vụ, không lỗi nào báo ra. Trộn ba con số thành một là xoá đúng khoảng cách mà cả bàn này tồn tại để chỉ ra.

Bước 0Bắt đầu ở đây

Cần trước: đăng nhập role=admin  ·  Bàn này có 30 mục. Bạn không cần đi hết — có ba đường, và mỗi lần bạn chỉ đi một đường.

Việc tiếp theo của bạn
Bấm «Đo trạng thái» — bàn sẽ tự nói bạn đang ở đâu.

Sáu ô dưới đây đo từ kho thật, không đọc một cờ nào. Ô nào đỏ thì đó là việc tiếp theo — đi theo thứ tự, vì ô sau chỉ có nghĩa khi ô trước xanh.

Ba đường, chọn một

ĐƯỜNG A Chuẩn bị — làm MỘT LẦN
  1. Nạp một bộ demo~20 giây · có ngay một trợ lý trả lời được
  2. Khai khoá hệ thống của kháchOnePMS · PMS khác · CRM · webhook
  3. Khai khoá kênhtuỳ chọn · widget không cần bước này
ĐƯỜNG B Trình bày cho khách
  1. Bật chế độ trình bàyrồi vào «DEMO 1 · 11/09»
  2. Cho xem nó BIẾT gìbấm «Vẽ bộ não»
  3. Hỏi thử hai câumột câu trả lời được · một câu PHẢI từ chối
  4. Gắn/tháo một năng lựchệ chạy khác ngay, không deploy
  5. Sinh widget gửi kháchmỗi trợ lý một đoạn nhúng riêng
ĐƯỜNG C Kiểm — cho đội kỹ thuật
  1. Thang sáu bậc«trợ lý NÀY chạy được chưa»
  2. Chạy tập vàng«Kiểm thử ngay» · đọc câu nào trượt
  3. Bộ kiểm runtime«cả hệ còn đúng không»

Lần đầu: A1 → B2 → B3 là đủ để thấy nó hoạt động (khoảng 3 phút). Khoá OnePMS và khoá kênh chỉ cần khi muốn tra hệ thật hoặc mở kênh thật.

Bước 0Sơ đồ vận hành core — một trang cho dev, PM và BOD

Cần trước: —  ·  Ba người đọc ba thứ khác nhau từ cùng một hệ. Màn này vẽ một sơ đồ và chú ba lớp đọc lên nó, thay vì ba bản vẽ sẽ lệch nhau sau lần sửa thứ nhất.

Đọc sơ đồ này thế nào — chọn vai của bạn
BOD
Đọc ba khối màu. Trái = thứ khách chạm. Giữa = thứ ta xây. Phải = thứ ta sở hữu (dữ liệu). Câu duy nhất cần nhớ: đổi model không phải sửa phần giữa, và đó là lý do hệ này không bị khoá vào một nhà cung cấp.
PM
Đọc các ô có số. Mỗi ô là một nhóm đường API đang chạy thật, số đọc từ /version chứ không gõ tay. Một tính năng mới rơi vào đúng một ô — nếu không rơi vào ô nào thì nó chưa có chỗ, và đó là câu hỏi thiết kế, không phải câu hỏi lịch.
Dev
Đọc mũi tên và tên hàm. Mỗi mũi tên là một lời gọi có thật trong mã; tên dưới mũi tên là chỗ đặt breakpoint. Ba hàng rào đỏ là ba chỗ một lượt chạy có thể bị chặn lại.
① Ba tầng — và ranh giới giữa chúng là ranh giới KHÔNG ĐƯỢC PHÁ

Ba gói, ba nhịp phát hành khác nhau. Mũi tên phụ thuộc chỉ đi một chiều: kernel biết thư viện AI, thư viện AI không biết kernel tồn tại. Nhờ vậy bóc aiagent-ai đặt vào một sản phẩm khác không phải sửa một dòng nào của nó — và đó là phép thử, không phải một lời hứa.

KÊNH VÀO Khách chạm vào widget trên web Messenger · Zalo bàn quản trị thoại / hình (WS) một vỏ phản hồi NHÂN + PLUGIN  — aiagent-kernel Nhân HTTP xác thực · phân quyền · vỏ phản hồi idempotency · hàng đợi · nhật ký roles.keeps() — cắt bảng định tuyến Plugin — mỗi cái một nhóm đường agents (bản khai · graph · KỸ NĂNG) chat_rag · knowledge · onboarding social · crm_sales · billing · voice identity · platform_admin · stay Tổng đường đang phục vụ: đang đọc… gọi một chiều THƯ VIỆN AI  — aiagent-ai (KHÔNG biết HTTP) Mười một SLOT tháo lắp được thêm nhà cung cấp = thêm một dòng khai, không sửa mã ① model ② embedding ③ store ④ retrieval ⑤ memory ⑥ prompt ⑦ loop ⑧ tool ⑪ skill ⑨ session ⑩ sandbox — không tắt được Hàng rào vòng lặp — chặn một lượt chạy đi quá xa ngân sách bước/công cụ/token/tiền · hạn chót · chống lặp cổng duyệt 4 sàn · dừng khẩn ESTOP · cổng nghiệm thu KHO DỮ LIỆU — mỗi kho ĐÚNG MỘT chủ ghi index/ — vector agents/ — bản khai memory/ — ký ức trace/ — nhật ký crm/ · leads/ skills/ · packs/ · tenant/ Service khác cần dữ liệu ở đây thì gọi API hoặc nghe sự kiện — không đọc thẳng kho của nhau. Vì sao: hai tiến trình cùng ghi một tệp thì hỏng theo cách không tái hiện được, và chỉ hỏng khi có tải.
Vì sao ba gói chứ không mộtNhịp đổi khác nhau ba bậc. Hợp đồng (aiagent-contract) gần như không đổi — đổi nó là đổi cho cả tám service. Nhân (aiagent-kernel) đổi theo tháng. Thư viện AI (aiagent-ai) đổi theo tuần, vì đó là chỗ nhà cung cấp model thay đổi. Gộp làm một thì mỗi lần thêm một nhà cung cấp là một lần phát hành lại toàn hệ — và đó đúng là thứ kiến trúc này tồn tại để tránh.

Phép thử đọc được bằng máy: aiagent-ai không import aiagent_kernel và không import service nào; có một bài kiểm canh đúng chiều import đó, nên lời hứa này không trôi được.
② Một câu hỏi của khách đi qua những gì — mười chặng

Đây là đường nóng: mỗi tin nhắn của khách đi hết mười chặng này. Con số đáng nhớ cho BOD: đúng một lần gọi model cho một câu hỏi — định tuyến và chấm điểm đều tất định, không đốt thêm lượt nào.

#ChặngLàm gìChặn được không
1Vỏ & quyềnKiểm header bắt buộc, xác thực, cắt theo vai trò tiến trìnhCó — sai quyền thì đường không tồn tại
2Che PIIBóc số điện thoại, email khỏi câu hỏi trước khi nó đi tiếp—
3Dò tiêm lệnhCâu hỏi chứa “bỏ qua hướng dẫn…” → đánh dấu, xử lý như dữ liệuĐánh dấu, không chặn
4Chốt cấu hình lượtChốt một lần: model · phiên bản prompt · thời điểm hiện tại theo múi giờ khách sạn—
5Ký ức ngắn hạnLấy vài lượt gần nhất, có trần ký tự — tất định, không gọi model—
6Truy hồiNhúng câu hỏi → tìm trong phạm vi dữ liệu của chính trợ lý đóKhông đủ bằng chứng → từ chối
7Dựng promptthời điểm → bằng chứng → lịch sử → câu hỏi, cộng “cách trả lời” của bản khai—
8Hàng rào ngân sáchTrần bước · công cụ · token · tiền · hạn chótCó — chạm trần thì dừng có lý do
9Gọi model · 1 lầnSinh câu trả lời từ bằng chứng đã có—
10Hậu kiểmChống lặp vô nghĩa · chấm bằng chứng · ghi trace · ghi cướcCó — lặp vô nghĩa thì bỏ câu trả lời

Thao tác GHI sang hệ thứ ba (đặt phòng, hoàn tiền, đẩy đơn) không đi đường này. Nó đi qua graph nhiều node và dừng ở cổng người — máy đề nghị, người bấm duyệt.

③ Năng lực mới vào hệ bằng đường nào — thang bốn nấc

Câu hỏi PM hỏi nhiều nhất: “thêm việc này mất bao lâu?” Câu trả lời phụ thuộc nấc nào, và nấc càng cao thì càng rẻ. Leo từ trên xuống, dừng ở nấc đầu tiên giải được.

NấcCáchTốn gìVí dụ vừa làm
①Thêm tri thức — nạp tài liệuVài phút. Không deploy, không sửa mã6 mảnh “quanh resort”: điểm chơi · taxi · xe ôm · thuê xe · quán ăn · mùa
②Thêm kỹ năng — một thư mục SKILL.mdThả thư mục, bấm tải lại. Không deployKỹ năng của một ngành hoặc của riêng một khách
③Thêm năng lực / công cụ — một tệp khai JSONSửa cấu hình. Không sửa mãGọi API kho của khách, tra internet
④Sửa mã lõiPhát hành lại toàn hệChỉ khi ba nấc trên đều không diễn đạt được

Vì sao thang này quan trọng với BOD: mỗi công cụ ở nấc ④ được gửi lên trong mọi lời gọi model, cho cả khách không bao giờ dùng nó — tức nó là một khoản thuế vĩnh viễn trên hoá đơn. Một kỹ năng ở nấc ② chỉ tốn một dòng. Chênh lệch đó là lý do thang tồn tại.

④ Bốn bước thiết lập — và vì sao thanh nhắc đếm bằng BẰNG CHỨNG

Thanh 0/4 ở đầu ứng dụng đọc kho thật, không đọc cờ đã lưu. Khách làm ba trong bốn việc mà không đi qua wizard — vào thẳng trang Giọng thương hiệu và tạo một cái — thì bước đó vẫn tính là xong. Đọc mỗi cờ thì thanh nhắc sẽ nói “chưa làm” trong khi màn hình ngay dưới đang liệt kê thứ vừa làm.

#BướcBằng chứng đếmĐường API
1Tạo brand voiceCó bản ghi giọng thương hiệu trong kho socialonboarding/submitBrandVoice
social/createBrandVoice
2Thiết lập Sales Chat AgentCó một bản khai trợ lý trong agents/agent/createAgent
3Kết nối tài khoản mạng xã hộiCó ít nhất một kênh đã nốionboarding/getChannelStatus
social/bindChannel
4Tạo AI Social Agent & bài đăng đầuCó trợ lý social và một bài nháponboarding/provisionWorkspace

Bước 3 bỏ qua được: nhánh skip chỉ dựng Chat Agent. Khách chưa có Page vẫn dùng được widget web ngay. Mở màn Hoàn tất thiết lập để điền cả bốn ở một chỗ thay vì đi bốn màn.

Bước 0Bàn điều khiển demo — đòn bẩy chỉnh tay khi đang trình bày

Cần trước: đăng nhập role=admin  ·  Mở sẵn tab này trong lúc demo. Mọi thứ dưới đây đổi được lúc chạy, không khởi động lại máy chủ.

Cái làm gãy một buổi demo hiếm khi là lỗi mã — nó là một hàng rào làm đúng việc của nó vào đúng lúc không nên. Cổng eval chặn bật bot, §6 chặn một miền chưa đăng ký, một câu trả lời sai vì tài liệu thiếu một dòng. Ba thứ đó đều có đường đi vòng có ghi vết — dùng đường đó, đừng tắt hàng rào.

Ba nút cứu hộ
Chưa chạy.

Ép bật KHÔNG tắt phép đo — nó ghi enabled_forced_at + lý do + người bấm vào cấu hình trợ lý. Một cổng không có đường đi vòng là một cổng sẽ bị gỡ; một đường đi vòng không để lại dấu vết là một cổng giả.

Đổi được lúc chạy — không khởi động lại
Cách trả lời của một trợ lýagent/updateAgent
Gắn/tháo năng lựccapability/attachCapability
Thêm tri thức ngay giữa buổiprofile/upsertProfile
Thêm câu mẫuagent/addExampleList
Sửa prompt đường nóngprompt/updatePrompt
Lùi prompt về bản trướcprompt/rollbackPrompt
Lùi bản khai trợ lýagent/rollbackAgent
Mở một miền ra ngoàiconnector/registerConnector
Hạ ngưỡng cổng bậtagent/setActivationThreshold
Nạp lại tri thức từ nguồnonboarding/refreshKnowledge
Mở một ngành mớithả thư mục vào AI_PACK_DIR → nạp lại

PHẢI khởi động lại: đổi model/embedding, đổi AI_WEB_SEARCH_URL, đổi danh sách miền ở mức hệ thống. Nên chốt ba thứ đó trước khi vào phòng họp, không chỉnh giữa buổi.

Bước 0Hoàn tất thiết lập — điền vào đây, không phải đi năm màn

Cần trước: một trợ lý  ·  Bảy mục của thanh nhắc, mục nào chưa xong thì mở sẵn một form ngay dưới. Xong mục nào thì nó tự gập lại.

Mỗi form gọi đúng một đường API chính chủ — không có đường tắt nào ở đây. Form nào khoá hiện tại không đủ quyền thì nó nói trước, thay vì để bạn điền xong rồi nhận 403 giữa buổi demo.

Đang đo...

Nhân sự & quyền — sửa ngay tại đây

Form ② và ③ đi qua HAI hàng rào khác nhau, và lẫn chúng là lý do phổ biến nhất khiến một admin bị từ chối:

  1. Vai — phải là role=admin. Thiếu thì lỗi là PrivilegeNeed. Sửa bằng bảng bên dưới.
  2. Chủ sở hữu — trợ lý phải thuộc tenant của bạn. Ba trợ lý ship sẵn không thuộc ai, nên không admin nào sửa được; lỗi là AgentIsSharedTemplate, và cách sửa là nhân bản (nút hiện ngay trong form ②/③), không phải xin thêm quyền.

Cổng chặn ở API chứ không chỉ ẩn nút — nên tạo tài khoản thử ở đây rồi đăng nhập bằng nó mới là phép thử thật; đổi vai xong phải đăng nhập lại vì vai nằm trong token.

Chưa tải.

Mật khẩu chỉ dùng khi TẠO MỚI. Hai việc này là hai đường khác nhau ở backend, và đó là lý do ô mật khẩu có lúc cần có lúc không:
· Email chưa có → auth/createUser, có đặt mật khẩu, và tài khoản đăng nhập được ngay. Bắt buộc điền, tối thiểu 8 ký tự.
· Email đã có → staff/upsertStaff, sửa tên và vai. Đường này không chạm tới mật khẩu — điền vào ô cũng không đổi được gì, nên nó bị bỏ qua và trang sẽ nói rõ.
· Quên mật khẩu → bề mặt admin không có đường đặt lại hộ. auth/changePassword là tự đổi (đòi mật khẩu hiện tại). Đặt lại hộ chỉ có ở bàn nền tảng: platformUser/resetPassword.

Bước 0Khoá LLM của workspace — dùng Claude/OpenAI của chính bạn

Cần trước: đăng nhập role=admin  ·  Không có khoá thì trợ lý chạy bằng cấu hình của máy chủ — chạy được, nhưng chi phí và hạn mức là của chúng tôi, không phải của bạn. Khai ở đây là workspace này gọi bằng tài khoản của chính bạn, không sửa .env và không khởi động lại service.

Khoá LLM của workspace này — đổi KHÔNG cần sửa .env, KHÔNG cần khởi động lại

Khoá lưu theo workspace, không theo máy. Có hiệu lực từ lượt chạy kế tiếp — không phải sau một lần restart. Chi phí và hạn mức tính về nhà cung cấp của chính bạn.
Khoá đi vào đây và không đi ra: mọi lần đọc lại chỉ trả set(***).

Vì sao Claude đi qua openai_compat chứ không phải một provider riêngSlot model khai bốn provider: ollama · openai_compat · llamacpp · mock. Anthropic phát một đầu tương thích giao thức OpenAI tại https://api.anthropic.com/v1, nên Claude nối được mà không thêm một dòng mã nào — đổi bên là đổi base_url.

Đó đúng là phép thử §4.6 của chuẩn: "nếu đổi model phải sửa code nghiệp vụ thì kiến trúc sai". Thêm một provider anthropic riêng sẽ là thêm mã cho một thứ đã chạy được bằng cấu hình — và mã đó phải nuôi mãi.

Giới hạn phải biết: đầu tương thích của Anthropic không phủ hết tính năng gốc (khối suy nghĩ, cache prompt theo phiên). Cần chúng thì lúc đó mới đáng bàn một provider riêng — không phải trước.

Bước 0Thiết lập ban đầu — 4 bước, chạy THẬT

Cần trước: đăng nhập role=admin  ·  Đúng bốn bước của mockup, nhưng mỗi nút ở đây gọi API thật trên máy chủ này — không một con số nào dựng sẵn. Thanh x/4 đọc từ onboarding/getState, và mỗi bước tự đo bằng chứng thay vì đọc một cờ đã lưu.

—/4
Chưa đo
Bấm «Đo trạng thái» để đọc từ máy chủ.
① Ngành của bạn

Danh sách lấy từ onboarding/getIndustryPresetList — một bảng ở backend, không phải một bản chép trong giao diện. Ba khách hàng frontend giữ ba bản là ba con số lệch nhau.

② Nguồn dữ liệu — cần ÍT NHẤT một

Ba ô THAY THẾ lẫn nhau. Thiếu cả ba thì máy chủ trả OnboardingInputNeed — không phải ParameterError, vì câu «thiếu tham số» không nói được rằng ba ô này thay nhau.

③ Đang chuẩn bị — đọc từ máy chủ, không phải hoạt hình
Chưa chạy.
Vì sao bước này đi qua HÀNG ĐỢIBò tới 5 trang web rồi gọi model một lượt vượt xa ngân sách của một request HTTP (ASYNC-01). submitInput đẩy việc vào queue.onboarding.analyzeInput rồi trả ngay analysis_id; màn này hỏi lại bằng getAnalysis.

Cờ quá hạn do BACKEND tính, không do giao diện: trần 90 giây là lời hứa của backend, và ba khách hàng frontend giữ ba con số sẽ mở đường tự điền ở ba thời điểm khác nhau — không cái nào khớp thứ backend làm.

Worker phải CÓ MẶT: AI_SERVICE_ROLE=all hoặc một tiến trình vai trò worker. Không có worker thì việc nằm trong hàng đợi và màn này quay mãi — nên ô bên cạnh đọc luôn trạng thái worker.
④ Hỏi thử — câu trả lời phải KÈM TRÍCH DẪN
Chưa hỏi.

Không có trích dẫn mà vẫn khẳng định là ảo giác (§1.1). Màn này hiện thẳng grounded và danh sách citations để bạn thấy nó dựa vào đâu — hoặc thấy nó KHÔNG dựa vào đâu.

Ba việc còn lại

Hai nhánh, không phải một nút có hộp chọn: full dựng cả AI Social Agent và một bài nháp; skip chỉ dựng Chat Agent — dành cho khách bỏ qua bước nối kênh. Gọi lại khi đã có thì không dựng con thứ hai: nó trả về đúng con đang có, vì bấm hai lần do mạng chậm là chuyện xảy ra thật.

Chưa chạy.

«Để sau» KHÁC «hoàn tất», và khác biệt đó nhìn thấy được: skipped vẫn giữ thanh nhắc, completed thì ẩn. Gộp hai trạng thái là mất đúng thông tin «khách đã bấm để sau».

Bước 3Nguồn dữ liệu (source plugin, §4.6.1)

Cần trước: —  ·  Có dữ liệu thì trợ lý mới có gì để trả lời. Chưa nạp thì /readyz báo indexHasDocuments:false — đó là bình thường, không phải hỏng.

Nạp hồ sơ từ một sidecar bên ngoài (vd LinkedIn qua Apify) vào index — chỉ hoạt động khi server được bật với AI_SOURCE_PROVIDER=sidecar và AI_SOURCE_MANIFEST trỏ tới một plugin.json hợp lệ. Không bật thì nút bên dưới sẽ báo lỗi rõ ràng thay vì im lặng không làm gì.

Kết quả gần nhất
Chưa chạy.

Bước 4Bộ não trợ lý — nó đang biết gì

Cần trước: bước 3  ·  Xem nó biết gì trước khi trách nó trả lời sai.

Mạng lưới bên dưới là bộ nhớ nghiệp vụ của trợ lý: khái niệm nó thấy trong dữ liệu, hồ sơ đứng sau từng khái niệm, bài đã được dạy, câu học từ người soát, chỗ đang hỏng, và chủ đề khách hỏi lặp lại. Bấm vào một điểm để xem chi tiết — hồ sơ thì đọc được đúng đoạn tài liệu đã đưa vào prompt.

Kéo nền để di chuyển · lăn chuột để phóng · bấm một điểm để xem chi tiết · kéo một điểm để ghim nó ra chỗ khác. Bấm vào ô màu ở trên để ẩn/hiện từng nhóm.
Chi tiết

Bấm “Vẽ bộ não”, rồi bấm vào một điểm.

Bản đồ này KHÔNG phải neuron của model
Bản đồ đang nói gì

Đếm từ chính mạng lưới ở trên, không phải từ phỏng đoán. Bấm một dòng để soi đúng vùng đó trên bản đồ.

Bấm “Vẽ bộ não” để đọc.

Nó học được gì

“Học được” ở đây không phải gradient của model — là chuỗi việc có dấu vết: một lượt vào hàng đợi soát, người soát duyệt hoặc loại, rồi câu đã duyệt thành một bài kiểm chạy mãi.

Bấm “Vẽ bộ não” để đọc.

Chu trình tri thức — kho có còn khớp nguồn không

Bộ não ở trên trả lời “nó đang biết gì”. Khối này trả lời câu đắt hơn: “thứ nó biết có còn đúng không”. Trước bản này, thiết lập ban đầu chạy đúng một lần — khách đổi bảng giá trên website thì kho vẫn giữ bảng giá cũ, và trợ lý báo giá cũ với giọng chắc chắn, có trích dẫn, grounded=true. Không phép kiểm nào đỏ, không dòng log nào bất thường. Nay nguồn được đọc lại theo nhịp, và trang đã biến mất khỏi website bị gỡ khỏi kho chứ không nằm lại để bị trích dẫn.

Trạng thái chu trình

Chưa đọc.

“Làm mới ngay” đi qua hàng đợi, không chạy trong request: nó bò web rồi có thể gọi model — hai thứ ASYNC-01 cấm đặt trên đường nóng. Bấm xong thì đọc lại trạng thái.

Giọng thương hiệu — ai đang giữ

Chưa đọc.

Chu trình không bao giờ đè giọng khách đã sửa tay. Khách bỏ nửa buổi chỉnh câu chữ, một tuần sau job nền trích lại từ website rồi ghi đè — không ai báo, họ chỉ thấy trợ lý bỗng nói khác đi. Nên kho tri thức tự cập nhật, còn giọng thì chỉ đề xuất và chờ người bấm.

Chi tiết kỹ thuậtBốn đường: POST /aiagent-admin/onboarding/getKnowledgeCycle · refreshKnowledge · setKnowledgeCycle · applyBrandVoiceSuggestion. Nhịp mặc định 7 ngày, tự hẹn lượt kế tiếp bằng run_at của hàng đợi — không cron, nên nhịp tim nằm trong thứ đã có sẵn sổ lỗi và overdue(). Vân tay nội dung chạy TRƯỚC khi gọi model: nguồn không đổi thì dừng, không tốn token. Khách sửa liên tục thì gộp bằng cửa sổ 120 giây (khoá idempotency theo tenant + mốc đã làm tròn). Một lượt làm mất quá 50% số trang thì không gỡ và báo người — “toàn bộ nguồn vừa biến mất” gần như luôn là đọc hỏng, không phải khách xoá. Cần role=admin.

Bước 5Kết nối ra ngoài

Cần trước: —  ·  Chỉ cần khi trợ lý phải gọi ra ngoài. Mở ra: năng lực api.connector ở bước 7. Chưa có kết nối nào thì bước 6 sẽ chặn mẫu «Nối API bên thứ ba».

Tự sinh — không khai tay từng đường

Phần khó của việc nối một hệ bên thứ ba chưa bao giờ là kỹ thuật — nó là bốn mươi lần gõ tay, mỗi lần một cơ hội sai một ký tự. Hai đường dưới đây đọc hộ bạn: địa chỉ đầy đủ, chỗ gắn khoá, đọc hay ghi, và tham số bắt buộc.

Thường kết thúc bằng /openapi.json, /swagger.json hoặc /v3/api-docs.

Đây là nơi duy nhất một địa chỉ ra ngoài đi vào hệ thống. Người tạo trợ lý ở mục trên không bao giờ gõ một URL — họ chỉ chọn id trong danh sách này. Ranh giới đó là toàn bộ lý do mục này tồn tại: một ô văn bản nhận URL trong wizard là một cổng SSRF do người dùng điền, và họ trỏ sai không vì có ý xấu mà vì dán sai.

Khoá không bao giờ đọc lại được qua API — danh sách bên phải chỉ hiện set(***) hoặc unset, đúng hai trạng thái mà /version dùng cho mọi bí mật. Xoá một kết nối đang có trợ lý gắn vào sẽ bị chặn, và xoá là ghi một bản ghi vô hiệu hoá chứ không mất lịch sử.

Đã đăng ký

Chưa tải.

Tra internet
Chưa tải.

Nối OnePMS — một lần khai, sáu đường tra

OnePMS xác thực bằng một header tính lại mỗi lời gọi: Authentication: CryptoJS.AES.encrypt("email:password", secretKey). CryptoJS sinh salt ngẫu nhiên nên chuỗi đó khác nhau ở từng lời gọi — một khoá tĩnh không diễn đạt được, nên sổ kết nối có thêm lược đồ xác thực cryptojs_aes. Khoá bạn khai ở đây không bao giờ đi ra: đường đọc trả set(***).

Khai một lần

Đúng ba ô. Ô hotelID trước đây nằm ở đây đã được bỏ: không đường mã nào đọc nó — nó là một ô bắt người dùng đi tìm một giá trị mà hệ không dùng tới.

Chưa chạy. Điền ba ô rồi bấm «Nối OnePMS» — nó ghi sáu đường vào sổ, mở hàng rào cho host của chúng, rồi gọi thật một lần để xem khoá có đúng không. Một lần bấm, không có bước hai.
Ba ô này là ĐỦ — và hàng rào ra ngoài tự mở, không sửa .envBa tham số, đúng bằng hệ cũ. opKhoa() ghép email:mật khẩu thành authAccount và giữ secretKey riêng; cả sáu đường dùng chung đúng bộ ba đó. Đây là nghĩa của «một lần khai, sáu đường tra» — không phải sáu lần khai.

Địa chỉ gốc — ĐÃ đối chứng bằng một lời gọi thật. us-central1-neutron-pms.cloudfunctions.net lấy từ tài liệu «TÍCH HỢP ONEPMS API 3.4», và ngày 11/09 nó trả về {"result":"001","message":"Account authentication failed"} — JSON của OnePMS. Một tên hàm bịa ra ở cùng host trả về trang HTML 404 của Google. Hai thứ đó khác nhau, nên có một phép phân biệt chắc chắn: thân phản hồi có result ⇒ đã tới đúng ứng dụng, đường dẫn đúng, bất kể mã HTTP.

OnePMS trả lỗi nghiệp vụ kèm HTTP 404 — không giống chuẩn của ta (API-06 trả 200 kèm code), nhưng đó là thứ bên kia làm, và bộ chẩn đoán phải mô tả thế giới chứ không mong thế giới cư xử cho đúng. Đọc mã HTTP mà không đọc thân là cách chắc chắn để kết luận ngược hướng.

Không phải app.onepms.net (giao diện web Flutter, nói thẳng với Firestore project onepms---test) và không phải api.onepms.net (không phân giải). Ô địa chỉ vẫn sửa được — đổi môi trường không phải đổi mã.

Hàng rào Egress mặc định TỪ CHỐI, nhưng nó KHÔNG chỉ đọc biến môi trường. build_outbound() dựng allowlist bằng hợp của AI_WEB_SEARCH_ALLOWED_HOSTS với host của mọi kết nối đã đăng ký, và _rebuild_outbound() chạy lại ngay ở mỗi lần ghi sổ. Nên bấm «Đăng ký 6 đường» là đã mở hàng rào cho host trên — không sửa .env, không khởi động lại service.

Việc đăng ký tự cấp quyền cho chính host của nó không nới hàng rào: đường ghi sổ là bề mặt của role=admin, và §6 cấm URL đến từ NGƯỜI GỌI lúc chạy, không cấm đích mà quản trị viên đã khai có chủ ý.

Vậy «ghi đủ 6 đường mà vẫn không gọi được» còn hai lớp nguyên nhân, và thứ tách chúng ra là THÂN phản hồi, không phải mã HTTP: có result ⇒ đường đúng, xét tiếp result ("00" xong · "001" là khoá); không có result mà 404 ⇒ mới là chuyện đường dẫn. Bấm «Tra cơ sở» và đọc result — "00" là đúng khoá; 401 hoặc result khác là sai khoá, hoặc tài khoản chưa được OnePMS cấp quyền gọi API. Nút «Kiểm hàng rào» phân định đúng hai khả năng đó.
Sáu đường — và bốn đường CÒN THIẾU
Danh sách cơ sởapi-fetchHotelList
Hạng phòng + giá niêm yếtapi-getRoomTypes
Danh sách phòng theo tầngapi-getRooms
Bảng dịch vụ 5 nhómapi-getServices
Phương thức thanh toánapi-getPaymentMethods
Phòng trống + giá theo ngàyapi-checkAvailabilityAndRate

Cả sáu đều CHỈ ĐỌC (writes=false) nên chúng chạy thẳng, không qua cổng người — một lượt đọc không để lại gì để hoàn tác.

Chưa có: đặt phòng · nhận phòng (check-in) · thêm thanh toán · huỷ đơn. Tài liệu được cấp (TÍCH HỢP ONEPMS API 3.4) chỉ tới trang 19 trong 59, và bốn API đó nằm ở phần còn thiếu. Đoán tham số của một API GHI vào hệ thật của khách là cách tạo đơn rác trong một hệ đang chạy — nên chúng bị để trống có chủ ý, không phải bỏ sót.

Chi tiết kỹ thuậtBốn đường: getConnectorList · registerConnector · deleteConnector · testConnector, tất cả /aiagent-admin/connector/* và đòi role=admin. Mọi lời gọi ra ngoài đi qua Egress.check() — so trên host đã phân tích chứ không trên chuỗi thô, và mặc định TỪ CHỐI. Nút "Thử" gọi thật một lần ngay lúc đăng ký, khi còn có người nhìn màn hình: một đích sai chỉ lộ ra lúc có khách đang chờ trả lời là kiểu hỏng đắt nhất. Lý lẽ đầy đủ + miễn trừ §3.4 của vòng ReAct: docs/specs/react-web-augmented.md.

Chiều ngược lại: để bên thứ ba GỌI VÀO

Hai chiều, hai cơ chế, đừng lẫn. Kết nối ở trên là trợ lý gọi ra — ta cầm khoá của họ. Đầu vào dưới đây là họ gọi vào — họ cầm bí mật của ta và ký từng lời gọi. Dùng khi CiHMS/CukCuk/Base muốn đẩy sự kiện sang (đơn mới · bill mới · trạng thái đổi) thay vì để ta hỏi liên tục.

Bí mật hiện đúng một lần, ngay sau khi cấp — cùng luật với khoá API. Hiện lại được về sau nghĩa là nó nằm trong lịch sử trình duyệt của mọi người từng mở màn này. Mất thì cấp lại; thao tác đó rẻ và để lại một dòng trong sổ.

Đầu vào đã cấp

Chưa tải.

Chi tiết kỹ thuậtBa đường /aiagent-admin/hook/* — getHookList · registerHook · revokeHook. Bên kia POST tới /aiagent-internal/hook/receiveHook kèm hai header: AiAgent-Hook-Id và AiAgent-Signature: sha256=<hmac-sha256(bí mật, thân THÔ)>. Thân THÔ, không phải bản đã định dạng lại — chuẩn hoá JSON đổi thứ tự khoá và chữ ký sẽ không bao giờ khớp. Hook không tồn tại và hook ký sai trả cùng một câu: xác nhận sự tồn tại là đủ để dò danh sách id của người khác. Thu hồi ghi một dòng vô hiệu hoá, không xoá lịch sử.

Chiều thứ ba: TA bắn sự kiện về hệ của khách

Khi có đơn mới · thanh toán thành công · bắt được khách tiềm năng, hệ tự POST sang CRM/ERP của bạn theo bản đồ trường bạn tự khai. Ta cầm bí mật và ký từng lời gọi để bên kia phân biệt được ta với người lạ biết URL của họ.

Dữ liệu cá nhân: mặc định KHÔNG gửi. Trường nào có nguồn trông như dữ liệu cá nhân (điện thoại · email · hộ chiếu · địa chỉ · ngày sinh) chỉ đi ra khi bạn khai tường minh. Không khai thì nó bị bỏ, và ô kết quả nói rõ đã bỏ trường nào — bạn thấy ngay lúc khai, không phải đợi tới lần bắn đầu tiên.

Trong ví dụ trên, tel sẽ bị bỏ vì nguồn $.phone là dữ liệu cá nhân mà không khai "pii": true; guestName thì đi qua vì đã khai. Bí mật ký hiện đúng một lần sau khi đăng ký.

Sự kiện đã nối

Chưa tải.

Chi tiết kỹ thuậtBốn đường /aiagent-admin/outHook/*. Gửi qua hàng đợi, không trên đường request — một CRM chậm không được làm chậm chính luồng trả lời khách. Thử lại lùi theo cấp số nhân có trần (5 lần); hết trần thì vào thư chết, đọc được ở bảng sự cố. Mọi đích đi qua Egress.check() — mặc định TỪ CHỐI, và kiểm lúc gửi chứ không lúc đăng ký, nên một đích bị thu quyền sau đó không được thừa hưởng quyền cũ. Nhật ký xuất ghi tên trường, không ghi giá trị (SEC-02).

Bước 19Loại AI Agent — super admin khai

Cần trước: role=platform + quyền agentType.write  ·  Mở ra: người dùng ở bước 6 chỉ việc chọn một loại đã khai — họ không bao giờ chọn năng lực trực tiếp.

Một loại là một bó năng lực: gắn một hoặc nhiều. Hai loại không được cùng bộ năng lực — chúng làm được đúng những việc như nhau, chỉ khác cái tên, và người tạo trợ lý sẽ chọn nhầm rồi đi tìm một khác biệt không tồn tại.

Loại đã khai

Chưa tải.

Khai một loại mới

Tích các năng lực rồi bấm «Khai loại». Trùng bộ năng lực với một loại đã có thì trang báo ngay khi bạn tích, không đợi bấm.
Chi tiết kỹ thuậtBốn đường /aiagent-platform/capabilityPack/*, đòi role=platform và khoá quyền agentType.read/.write (ghi: chỉ Super Admin). Ở bề mặt platform chứ không admin là một quyết định phân quyền: "sản phẩm này cho phép dùng những loại trợ lý nào" là câu hỏi cấp nền tảng — một tenant admin tự khai được loại mới nghĩa là tự cấp cho mình quyền gọi ra ngoài. Khoá định danh của một loại là TẬP năng lực (frozenset), không phải id: [a,b] và [b,a] là cùng một agent. Loại ship sẵn thì đọc được, sửa không được — sửa qua API sẽ tạo bản ghi đè ở tầng dữ liệu mà make check không đối chiếu.

Bước 6Tạo trợ lý của riêng bạn

Cần trước: bước 3 (và bước 5 nếu chọn mẫu ra ngoài)  ·  Mẫu là một bó năng lực. Mẫu nào chưa dùng được sẽ hiện lý do ngay ở bước 1 của wizard.

Không cần biết lập trình. Trả lời 4 câu bên dưới là xong — phần kỹ thuật (phạm vi dữ liệu, quyền, ngân sách, bộ kiểm) do mẫu điền sẵn và vẫn phải qua đúng bộ kiểm của bản khai §11, giống như khi kỹ sư viết tay.

Bước 1 Trợ lý này tên gì và làm loại việc gì?
Đang tải mẫu...
Bước 2 Nói bằng lời thường: nó làm gì, không làm gì
Bước 3 Chỉ dùng một phần dữ liệu? (không cần thì bỏ qua)
Bước 4 Cho vài ví dụ để biết trợ lý còn đúng hay đã hỏng

Mỗi ví dụ là một lời khẳng định: câu này trợ lý phải trả lời được, hoặc câu này phải nói không biết. Ví dụ loại thứ hai là thứ duy nhất bắt được một trợ lý bắt đầu bịa — mẫu đã điền sẵn một câu như vậy, bạn chỉ cần sửa cho sát việc của mình.

Kết quả
Chưa tạo gì. Sau khi tạo, trợ lý dùng được NGAY — không phải khởi động lại máy chủ.
Chi tiết kỹ thuậtNút này gọi POST /agents. Nó sinh ra agents/<id>/agent.json + agents/<id>/eval/golden.jsonl từ chính các ví dụ bạn nhập, rồi nạp lại file đó bằng đúng load_declaration — bản khai không hợp lệ thì thư mục vừa tạo bị xoá, không để lại trợ lý nửa vời. Wizard KHÔNG mở egress_allowlist: một trợ lý tạo qua trang web không được phép gọi ra internet (CLAUDE.md §6) — muốn mở phải sửa file tay, có người đọc lại. Cần role=admin.

Bước 7Năng lực — gắn plugin để AI gốc thành agent

Cần trước: bước 6  ·  Đây là chỗ chatbot thành agent: gắn năng lực → tools · graph · egress đều suy ra lại.

AI gốc là một chatbot bình thường: trả lời theo tài liệu đã nạp, không ra ngoài, không luồng nhiều bước. Gắn một năng lực vào là nó thành agent — và ranh giới đó là một phép tính, không một công tắc ai phải nhớ bật. Mỗi năng lực là một tệp capabilities/<id>.json: thêm một loại trợ lý mới không sửa một dòng mã nào.

Bản khai đến từ BỐN lớp, yếu → mạnh: builtin (ship kèm slot loop) → service (ship kèm repo) → pack — GÓI NGÀNH → tenant — riêng một khách. Hai lớp cuối là DỮ LIỆU: mở một lĩnh vực mới = thả một thư mục vào AI_PACK_DIR rồi bấm “Đọc lại thư mục khai báo” — không deploy, không khởi động lại. Trước đó, thêm một năng lực cho một ngành là sửa cây mã aiagent-ai và phát hành cho tất cả khách, tức mỗi khách mới trong một ngành mới là một thay đổi bán kính toàn hệ.

Id ở hai lớp dữ liệu bắt buộc mang tiền tố (<gói>. hoặc t.<khách>.), nên một khách không diễn đạt được việc ghi đè năng lực dùng chung — đó là hàng rào theo kiểu, không phải một phép kiểm có thể quên ở đường thứ hai. Mỗi bản khai còn mang version + vân tay nội dung: sửa does_not mà quên nâng số thì nhãn phiên bản im lặng nói dối, vân tay thì không.

Năng lực khai trong hệ

Chưa tải.

ready=false kèm lý do và lệnh cài — một công tắc không biết mình có chạy được hay không là một công tắc sẽ bật rồi im lặng.

Gắn / tháo cho một trợ lý
Chọn một trợ lý rồi gắn/tháo năng lực. Bản khai ghi thành một phiên bản mới, nên lùi lại được.
Đích ra ngoài của trợ lý này

Gắn năng lực chưa đủ cho một năng lực phải gọi ra ngoài: nó còn cần đích. Wizard hỏi câu này lúc tạo; ở đây là chỗ đổi sau đó — nếu không thì gắn hotel.booking cho một trợ lý đã tạo là một việc không làm được trên bàn.

Chưa tải.

Bạn không gõ địa chỉ ở đây — đích do admin đăng ký ở Mở đường ra ngoài. egress_allowlist suy ra từ host của chính những đích này, nên không có ô nhập thứ hai để lệch. Bỏ chọn hết = thu hồi mọi đích.

Chạy tập vàng của trợ lý — ví dụ riêng của nó cộng ví dụ của từng năng lực vừa gắn (§10.2). Chấm tất định: câu phải trả lời đạt khi có bằng chứng, câu phải từ chối đạt khi không có. Tốn credit — mỗi câu là một lần gọi model thật.

Chưa chạy.
Chi tiết kỹ thuậtGắn năng lực là sửa bản khai, không phải bật một cờ: tools · egress_allowlist · connectors · graph đều SUY RA từ bản khai của các năng lực đã gắn, rồi bản khai mới đi qua đúng load_declaration như khi kỹ sư gõ tay. Hai năng lực đòi hai graph khác nhau thì bị chặn (CapabilityGraphConflict) chứ không tự chọn một cái — tự chọn nghĩa là luồng thật của trợ lý phụ thuộc thứ tự chữ cái của id.

Bước 8Dạy trợ lý

Cần trước: bước 6  ·  Dạy bằng ví dụ, sửa cách trả lời, thử ngay. Mỗi lần sửa là một phiên bản mới — lùi lại được.

Sửa cách trả lời, thêm ví dụ, thử ngay, và lùi lại bản cũ nếu bản mới tệ hơn. Mỗi lần sửa là một phiên bản mới — không có bản sửa nào đè mất bản trước.

Hai nút "Dạy" thêm câu đang gõ vào bộ kiểm của trợ lý này. Chúng không đổi câu trả lời ngay — chúng ghi lại điều trợ lý phải làm được, để lần sau bạn sửa cách trả lời thì biết ngay là tốt lên hay tệ đi.
Trả lời gần nhất
Chưa hỏi gì.
Bộ kiểm của trợ lý này
Lịch sử bản sửa

Bước 0Vì sao trợ lý trả lời như vậy — truy tới tận nguồn

Cần trước: một lượt chạy đã có run_id  ·  Dán run_id vào đây để thấy: nó đọc tài liệu nào, chạy bằng bản khai prompt nào, gọi model nào, và — thứ không màn nào khác trả lời được — tài liệu đó có bị sửa SAU khi trả lời không.

Tra một lượt chạy
Ba trạng thái của một căn cứ, và vì sao phải tách «chưa đo»khớp — vân tay nội dung y nguyên, căn cứ còn đứng vững.
đã đổi — nội dung bị sửa SAU khi trả lời. Câu trả lời có thể vẫn đúng, nhưng không còn được chứng minh bằng tài liệu này.
mất — tài liệu không còn; trích dẫn trỏ vào hư không.
chưa đo — lượt chạy ghi trước khi hệ lưu vân tay. Nó không được hiển thị thành «khớp»: «chưa đo» và «đã đo và khớp» là hai điều khác nhau, và gộp chúng là biến một khoảng trống dữ liệu thành một lời bảo đảm — rồi lời bảo đảm đó sẽ được dùng để kết luận về một tranh chấp thật.

Vân tay bỏ qua thay đổi khoảng trắng: một cảnh báo kêu lên ở mọi thay đổi vô nghĩa là một cảnh báo không ai còn đọc.
Căn cứ đã dùng
Chưa tra.

Bước 12Duyệt hành động chờ người — ca trực, không phải màn giám sát

Cần trước: bước 7 (một năng lực có công cụ GHI)  ·  Đây nằm trên đường đi của một lượt chạy thật: công cụ GHI dừng ở đây và không đi tiếp cho tới khi có người bấm.

Trợ lý được phép đề nghị ghi sang hệ của bạn — tạo đơn, phát mã thanh toán — nhưng nó không được tự làm. Mỗi đề nghị dừng ở đây, kèm đúng những tham số sẽ được gửi đi. Không có màn này thì năng lực booking.create và payment.qr gắn vào rồi treo vĩnh viễn, và triệu chứng bạn thấy chỉ là «trợ lý không làm gì».

Đang chờ bạn quyết

Chưa tải.

Hết hạn thì lượt chạy TỪ CHỐI, không mặc định cho qua. Đồng hồ đếm ngược ở mỗi thẻ là thời gian còn lại trước khi điều đó xảy ra.

Đọc lại một lượt đã xong
Mỗi bước của một lượt chạy được ghi chỉ-thêm: đọc lại được toàn bộ, không chỉ bản mới nhất. Đây là thứ trả lời câu «vì sao luồng đi đường đó» sáu tháng sau.
Chi tiết kỹ thuậtBốn đường /aiagent-admin/graph/*: getPendingList · decideRun · expireRun · getRunHistory. Quyền chặn ở API, không chỉ ẩn nút: bản khai graph nói approvers: ["admin","platform"], nên một khoá role=staff gọi decideRun nhận 403 dù trang này có hiện nút. Tham số hiện trên thẻ là tham số ĐÃ KIỂM (đúng kiểu, đúng miền giá trị), không phải thứ model vừa sinh — được dựng ở node planner chứ không ở action_gate, vì engine park một node hitl trước khi handler của nó chạy, nên nếu dựng ở action_gate thì lúc dừng lại chờ bạn sẽ chưa có gì để trình ra. Sau khi bạn bấm duyệt, action_gate kiểm lại — hai lần kiểm không trùng lặp: cái đầu quyết định bạn thấy gì, cái sau quyết định có gọi ra ngoài không.

Bước 9Gắn trợ lý vào kênh Social

Cần trước: bước 6 · worker bật  ·  Một Page gắn một trợ lý. Worker tắt thì tin nhắn vào hàng đợi mà không ai trả lời.

Một Page/OA được gắn với một trợ lý. Mọi tin nhắn đến Page đó sẽ được trả lời bằng đúng phạm vi dữ liệu và cách trả lời của trợ lý đó — không gắn thì trợ lý lõi trả lời như trước. Đây là đường để thử một trợ lý bạn vừa tạo trên một Page thật mà không phải sửa dòng cấu hình nào.

① Khai khoá kênh của khách — làm TRƯỚC khi gắn

Đây là chỗ trả lời câu "trăm khách thì điền vào đâu". Mỗi khách nạp khoá của CHÍNH HỌ: từ giây này webhook của kênh đó được xác thực bằng App Secret của tenant này, không bằng biến môi trường của máy. Chưa khai khoá thì bậc 5 của thang sáu bậc còn đỏ, và một tin nhắn thật sẽ không vào được.

Khai khoá
Chưa chạy. Khoá đi vào server MỘT lần rồi ở lại — đường đọc không bao giờ trả lại giá trị thật.
Ba bước để một tin nhắn THẬT đi vào
  1. Khai khoá ở form bên cạnhApp ID · App Secret · Verify Token
  2. Dán URL webhook vào MetaURL hiện ra sau khi bấm «Lưu khoá»
  3. Gắn Page với một trợ lýform «Gắn trợ lý vào kênh» bên dưới

Chưa có khoá Meta thì bậc 5 còn đỏ, và đó là trạng thái ĐÚNG — không phải một lỗi cần vòng qua. Ba bậc dưới (hệ · model · tri thức) và bản khai vẫn xanh, nên phần demo hỏi–đáp chạy đủ; chỉ đường ra kênh thật là chưa.

② Widget nhúng — gửi cho khách dùng thật

Đây là đường nhanh nhất để khách dùng thật: một thẻ <script> dán vào website của họ, không cần Meta, không cần chờ duyệt app. Mỗi trợ lý một đoạn riêng — khoá gắn với tenant, data-agent trỏ tới đúng trợ lý.

Sinh đoạn nhúng

Một lần bấm mở CORS cho tên miền đó và ràng khoá vào đúng nó — bỏ trống thì đoạn nhúng chạy được ở mọi website, và trang khách vẫn bị trình duyệt chặn.

Chưa chạy. Chọn trợ lý ①, điền tên miền ②, rồi bấm ③ — đoạn <script> hoàn chỉnh hiện ở đây. Khoá hiện đúng MỘT LẦN.
Ba điều đoạn nhúng này đã đúng
  1. Giữ mạch một phiênsessionId lưu ở máy khách, sống qua reload
  2. Trỏ đúng trợ lývà đúng phạm vi dữ liệu của trợ lý đó
  3. Khoá hẹp, thu hồi đượcrole=widget · revokeApiKey khi cần

Tên miền khai ở ô bên cạnh, không ở biến môi trường: khai bằng env nghĩa là bán widget cho một khách mới phải khởi động lại máy chủ cho mọi khách đang chạy. Trang /widget-try cùng nguồn gốc với API nên nó tách được «trợ lý sai» khỏi «CORS chặn».

② Gắn trợ lý vào kênh đã khai

Gắn tới một trợ lý không tồn tại bị chặn NGAY tại đây (AgentIdNotExist) chứ không đợi tới lúc có khách nhắn — một binding hỏng chỉ lộ ra khi khách đang chờ trả lời là kiểu hỏng đắt nhất.
Đang gắn

Chưa tải.

Thử một tin nhắn đến (không cần Page thật)
Chưa gửi.
Nút này gọi đúng webhook nội bộ mà Meta/Zalo sẽ gọi, nên nó đi qua đúng đường thật: webhook → hàng đợi → trợ lý đã gắn → hội thoại. Phần gửi tin trả lời ra ngoài chỉ chạy khi đã cấu hình token của kênh.

Bước 13Trợ lý đã chạy được chưa — thang sáu bậc

Cần trước: bước 6 (đã có trợ lý)  ·  Khác bước 13 ở ĐỐI TƯỢNG: bước 13 hỏi «cả hệ còn đúng hợp đồng không», bước này hỏi «trợ lý NÀY đã chạy được chưa» và đi từ hạ tầng lên tới kênh thật. Bậc trên chỉ có nghĩa khi bậc dưới xanh — có bậc đỏ thì sửa bậc THẤP NHẤT trước.

chưa chạy

Bốn cái bẫy thang này được dựng lên để tránh, cả bốn đã sập một lần trong lúc xây nó: degraded rỗng KHÔNG phải bằng chứng LLM chạy được — bằng chứng là một lượt chạy có model và runId; nội dung nằm trong data và khoá là camelCase, đọc ở gốc cho ra rỗng rồi báo đỏ trong khi hệ khoẻ; một câu trả lời RỖNG nghĩa là lời gọi hỏng, KHÔNG phải «agent đang hứa» — một phép kiểm buộc tội sai thì lần sau không ai tin nó; và bậc 12 này chỉ xét các mục THUỘC BẢN KHAI, mục «đã nối kênh» để bậc 9 xét, nếu không thì bậc thấp phụ thuộc bậc cao.

Bước 10Nói chuyện với agent

Cần trước: engine STT/TTS  ·  Kênh tiếng. Thiếu engine thì mục này nói thiếu gì và cài bằng lệnh nào.

Bấm “Bắt đầu”, rồi cứ nói bình thường.

Trình duyệt sẽ xin quyền dùng microphone.

Chi tiết kỹ thuật
audio gửi: 0 KBaudio trả: 0 KBmicro: —mức to nhất: —
Micro mở liên tục cho tới khi bấm Kết thúc. Server tự nhận ra bạn đã nói xong bằng VAD + endpointing (im lặng ~320 ms), xử lý, trả lời, rồi nghe tiếp — trang này KHÔNG bấm nút nào để chốt lượt. Vì micro vẫn mở lúc agent đang nói nên nói chen vào là agent im ngay (barge-in).
Đường đi: microphone → PCM16 → WebSocket /voice/stream → VAD → STT → agent → TTS, không dùng nhận dạng giọng nói của trình duyệt hay dịch vụ nào ngoài máy này.
Khi agent nghe sai: micro nên là 16000 Hz và mức to nhất trên −25 dBFS. Agent nghe thành chữ gì thì đọc transcript_final trong trace của từng lượt.
Máy này nghe và đọc được bằng gì

Voice chạy trên macOS, Linux và Windows. Cái khó không phải là bật lên, mà là "máy của tôi thiếu gì và cài bằng lệnh nào" — bấm nút dưới đây là trả lời được, kèm đúng lệnh cho hệ điều hành đang chạy.

Chưa kiểm tra.

Thử TỪNG BƯỚC — trước khi thử cả luồng

Khung thoại phía trên chạy cả chuỗi nghe → hiểu → trả lời → đọc. Khi kết quả tệ, chuỗi đó có bốn chỗ hỏng được và nó không nói chỗ nào. Hai phép thử dưới đây cắt hai đầu ra để đo riêng.

① Máy NGHE được gì

Thu một câu ngắn — nên đọc một tên riêng và một con số (vd «Đặt phòng deluxe cho chị Lan, số 0901234567»). Đó là hai thứ engine nghe sai nhiều nhất, và cũng là hai thứ nghiệp vụ cần đúng nhất.

chưa thu
Bấm thu, rồi đọc câu của bạn.
② Máy ĐỌC nghe thế nào

Không phép kiểm tự động nào chấm được «nghe có tự nhiên không» — tai bạn chấm. Thử một câu có dấu hỏi và một con số: hai chỗ giọng máy lộ ra rõ nhất.

Ngôn ngữ tự nhận từ chính đoạn chữ — không có ô chọn, vì một ô chọn là một ô sẽ bị để nguyên mặc định. Thử dán một câu tiếng Anh vào đây rồi bấm đọc: nhãn ngôn ngữ phải đổi theo.

Chưa đọc.

Hai đường này không gọi model và không ghi vào bộ nhớ hội thoại — một phép đo phải đo đúng một thứ. Đo xong hai cái này rồi mới bấm «Bắt đầu» ở khung thoại: lúc đó nếu còn sai thì cái sai nằm ở hiểu hoặc trả lời, và đã loại được hai nghi phạm.

Cách nó hoạt động
  1. Bấm Bắt đầu — micro mở và giữ mở.
  2. Nói. Ngừng khoảng nửa giây là agent hiểu bạn đã nói xong.
  3. Agent trả lời ra loa, rồi tự nghe tiếp — không phải bấm gì.
  4. Nói câu tiếp theo. Cứ thế tới khi bấm Kết thúc.

Nghe không rõ thì agent hỏi lại, tối đa 2 lần, rồi chuyển sang người thật thay vì đoán bừa. Nói “xin chào” thì nó chào lại và hỏi bạn cần tìm ai. Nói “tạm biệt” hoặc “cảm ơn nhé” là nó kết thúc phiên.

Bước 11Mắt — đọc chữ trong ảnh, nhận vật thể, camera realtime

Cần trước: engine OCR/vision  ·  Kênh hình. Khung camera trả nhãn thô; bấm Hỏi mới chạy graph đầy đủ.

Ba năng lực (vision.ocr · vision.detect · vision.realtime) dùng chung hai engine ở slot session — cùng chỗ với tai (STT/TTS), vì cùng loại: engine tri giác của một phiên.

Máy này đọc ảnh được bằng gì
Chưa kiểm tra.
Kết quả
Chưa chạy.
Camera realtime
chưa mở

Khung hình đi lên liên tục và trả nhãn thô — nhanh, không graph. Bấm Hỏi mới chạy graph đầy đủ một lần trên khung mới nhất, có bước evaluator chấm. Hai nhịp khác nhau nên là hai đường: chạy graph cho mỗi khung là 2 lần gọi model × 2 khung/giây, và câu trả lời có căn cứ sẽ đến sau khi camera đã quay sang chỗ khác.

Bấm "Mở camera" — trình duyệt xin quyền, rồi khung hình đi lên qua WebSocket và nhãn hiện ở đây.
Chi tiết kỹ thuậtKhung đi lên bằng WebSocket binary tới GET /aiagent-user/vision/openStream, kết quả về bằng khung TEXT (JSON). Server bỏ khung cũ: sau mỗi lần xử lý nó vét socket và chỉ lấy khung mới nhất — chỉ giới hạn nhịp là không đủ, vì xử lý một khung mất vài giây nên hàng đợi sẽ trả nhãn về một khung của vài chục giây trước. Trần thứ hai là AI_VISION_MAX_FPS ở biên. Không lưu khung nào xuống đĩa.

Bước 0Kịch bản demo — 5 chặng, theo thứ tự sản phẩm

Cần trước: —  ·  Lối đi bên dưới sắp theo hình dạng phụ thuộc (máy sống → dựng → dùng thật → kiểm chứng). Màn này sắp theo hình dạng sản phẩm — thứ tự bạn đi khi trình bày.

Hai luồng, hai vai trò — đừng trộn khi trình bày

Một buổi demo trộn hai vai trò làm người xem không biết đang nhìn ai. Luồng ADMIN là người của bạn dựng trợ lý; luồng KHÁCH là thứ người dùng cuối gặp. Hai luồng dùng hai tài khoản khác nhau — admin cần role=admin, khách đi qua widget hoặc kênh, không đăng nhập. Trỏ chuột vào từng bước để đọc nó là gì và vì sao nó có.

LUỒNG ADMIN Người của bạn dựng và vận hành
  1. Nạp tri thức của kháchbấm «Nạp toàn bộ» ở bước 0, hoặc thêm nguồn ở bước 3
  2. Xem nó đang BIẾT gìbấm «Vẽ bộ não», rồi «Soi chùm sáng» với một câu thật
  3. Nối hệ thống của kháchOnePMS: điền email · mật khẩu · secretKey → «Đăng ký 6 đường»
  4. Chọn loại trợ lýsuper admin khai loại · người dùng chỉ chọn
  5. Tạo trợ lý và khai giới hạnđiền does · does_not · cách trả lời
  6. Gắn / tháo năng lựcbật một cái → hỏi lại cùng câu → tắt → hỏi lần nữa
  7. Dạy bằng câu mẫuthêm cả câu phải trả lời VÀ câu phải từ chối
  8. Đo trước khi bậtbấm «Kiểm thử ngay», đọc câu nào trượt và vì sao
  9. Bật và nối kênhnối một Page → tin nhắn thật đi vào
LUỒNG KHÁCH Người dùng cuối gặp gì
  1. Hỏi một câu trong phạm vivd «mấy giờ phải trả phòng» → trả lời + trích dẫn
  2. Hỏi một câu nó PHẢI TỪ CHỐIvd «giảm 20% nhé» → nó từ chối, có lý do
  3. Việc cần ghi sang hệ thậttrợ lý đề nghị → người trực duyệt hoặc từ chối
  4. Đòi gặp nhân viênbàn giao kèm ngữ cảnh → nhân viên nhận ca

Mỗi chặng nói một con số ĐO được, không một ô nào tự khai. Chặng nào chưa có màn trên bàn này thì nó nói ra — một dấu tích cho một thứ không tồn tại là thứ hỏng đúng lúc có người đang nhìn.

chưa đo

Bấm «Đo lại tất cả» — hoặc chờ, trang tự đo một lần khi mở.

Chặng ③ hiện vàng khi có đề nghị đang chờ duyệt. Đó không phải lỗi — đó là đúng thứ cần cho xem trong một buổi demo: trợ lý đề nghị ghi sang hệ thật, và một người quyết.

Chi tiết kỹ thuậtSáu đường đọc, chạy song song: overview/getSetupProgress · overview/getSummary · agent/getAgentList · capability/getCapabilityList · graph/getPendingList · staff/getStaffList. Đường nào 404 ở tiến trình đang trả lời thì chặng đó ghi «tiến trình này không phục vụ» — ARCH-01: một đường không thuộc vai của tiến trình thì nó không tồn tại, trả 404 chứ không 403, nên đó là một câu trả lời hợp lệ chứ không phải một sự cố. Đường nào 403 thì ghi «khoá hiện tại không đủ quyền», vì đó là hai chuyện khác nhau và trộn chúng lại sẽ làm người demo đi sửa nhầm chỗ.

Bước 0Bộ demo — chọn một ngành, nạp một lần, chạy được ngay

Cần trước: đăng nhập role=admin  ·  Dựng sẵn một trợ lý THẬT từ tài liệu của một ngành: tri thức, câu vàng (gồm câu PHẢI TỪ CHỐI), bản khai và PHẠM VI DỮ LIỆU riêng của nó.

Nút này không có đường tắt nào: nó gọi đúng những đường mà một khách hàng thật gọi — upsertProfile cho từng tài liệu, createAgent, addExampleList. Nếu bộ này chạy được thì một khách hàng làm y hệt cũng chạy được; nếu nó gãy ở bước nào thì đó là chỗ khách sẽ gãy.

Nạp bộ demo
chưa chạy
Bấm «Xem trước» để đọc thứ sắp được nạp — tài liệu, câu vàng và một bản khai của ĐÚNG bộ đang chọn. Không gọi ghi gì.

Chạy lại không tạo trợ lý thứ hai: nó tìm theo tên trước. Tài liệu ghi theo id cố định (Green Bio 9001–9036, khách sạn 8001+) nên nạp lại là ghi đè, không nhân bản. Mỗi khách hàng cần ba trợ lý — trước, trong và sau bán hàng — nên nhóm nào hiện còn GỘP cả ba giai đoạn là nhóm chưa tách xong, không phải nhóm đã đủ.

Thử ngay sau khi nạp

Sáu câu lấy thẳng từ tài liệu — ba câu trợ lý phải trả lời được, ba câu nó phải từ chối. Bấm một câu là gửi thật vào trợ lý vừa nạp.

Chưa hỏi câu nào.

Câu «phải từ chối» mà trợ lý báo giá hoặc cam kết diệt 100% là hỏng — đó là hai điều tài liệu cấm tuyệt đối, và nó là thứ đáng kiểm nhất trong cả bộ.

Nhúng lên website của khách

Ba bước. Website của khách không phải sửa gì.

Khoá chỉ chạy trên tên miền đã khai, và nó hiện đúng một lần.

Vì sao phải khai tên miềnMột lần bấm làm hai việc, và thiếu việc nào thì widget cũng không nói được câu nào.

① Mở CORS. JS chạy trên trang của KHÁCH gọi chéo nguồn gốc, nên trình duyệt đòi header Access-Control-Allow-Origin mang đúng origin đó. Chưa khai thì khách nhận No 'Access-Control-Allow-Origin' header is present — một thông báo không nói gì về danh sách nào cần khai. Đã xảy ra trên site khách thật h-holding.vn.

② Ràng khoá. Khoá role=widget nằm trong JS công khai, nên ai xem source cũng đọc được. Phạm vi của nó đã hẹp — đúng hai đường hỏi đáp (SEC-05), lộ khoá không kéo theo CRM và không kéo theo cước — nhưng nó vẫn chạy: dán sang website thứ hai, thứ ba, và cả ba site tiêu cước model của một khách. Ràng tên miền là thứ chặn việc đó.

Nói thẳng giới hạn: nó chặn được lạm dụng bằng trình duyệt (mọi lần nhúng đều gửi Origin), không chặn được curl. Với curl thì hàng rào vẫn là phạm vi hẹp của khoá và hạn mức cước.

Xem và bỏ tên miền đã khai ở Widget nhúng → «Xem tên miền đã khai».

Đi theo thứ tự này

Hai mươi mục dưới đây xếp theo thứ tự phụ thuộc, không theo thứ tự chúng được viết ra. Bước sau cần bước trước — và chỗ nào cần thì mục đó nói thẳng ở dòng «Cần trước».

A · Máy này sống chưa

Chưa cần làm gì. Đỏ ở đây thì mọi bước sau vô nghĩa.

bước 1–2

B · Dựng một trợ lý

Nạp dữ liệu → mở đường ra ngoài → tạo → gắn năng lực → dạy. Thứ tự này không hoán đổi được.

bước 3–8

C · Đưa vào dùng thật

Ba kênh khách chạm tới: chữ (Social), tiếng (voice), hình (camera).

bước 9–11

D · Kiểm chứng & vận hành

Đọc khi cần trả lời câu «nó còn đúng không».

bước 12–20
Vì sao thứ tự này, không phải thứ tự khácBản trước xếp theo lịch sử viết ra, và thanh điều hướng lại xếp theo một thứ tự thứ hai — bấm một mục thì nhảy tới chỗ không đoán được. Tệ hơn: «Kết nối ra ngoài» nằm SAU «Năng lực», trong khi năng lực api.connector bị chặn cho tới khi có một kết nối — chính thông báo chặn bảo người dùng quay lại một mục nằm phía trước. Nay hai thứ tự là MỘT, và nó là thứ tự phụ thuộc thật: mục nào cần gì thì nói ra ở dòng «Cần trước», nên bạn không phải học thuộc sơ đồ này.

Bước 0AI từ A đến Z — bắt đầu ở đây

Cần trước: —  ·  Đọc 2 phút, rồi bấm Hỏi thử ở cuối mục. Nếu câu trả lời hiện ra kèm bằng chứng thì máy này đã dùng được, và bạn có thể bỏ qua phần lớn 20 mục bên dưới.

Nó là cái gì — năm câu, không thuật ngữ
  1. Bạn đưa dữ liệu vào: hồ sơ, tài liệu, câu hỏi–đáp có sẵn.
  2. Khách hỏi một câu — bằng chữ, bằng tiếng nói, hoặc bằng ảnh.
  3. Hệ tìm những mẩu dữ liệu gần nghĩa nhất với câu hỏi đó.
  4. Model viết câu trả lời dựa trên mấy mẩu ấy, và chỉ ra đã dựa vào mẩu nào. Đó là cột «bằng chứng» bạn sẽ thấy ở dưới.
  5. Không tìm được gì hợp lý thì nó nói không biết — không bịa. Đây là lựa chọn thiết kế, không phải giới hạn kỹ thuật.

Một «trợ lý» ở đây không phải một model riêng. Nó là một bản khai: làm gì · không làm gì · được dùng công cụ nào · lấy dữ liệu từ đâu. Cùng một model, hai bản khai khác nhau cho ra hai trợ lý cư xử khác hẳn nhau. Câu «không làm gì» là câu quan trọng nhất trong bản khai — thiếu nó thì vai trò của trợ lý trôi dần theo thời gian.

Máy này đang ở đâu — sáu việc, đọc thật từ runtime

Không phải danh sách viết sẵn. Mỗi dòng gọi một đường thật lúc bạn mở trang. Dòng nào báo «vai trò này không phục vụ» thì không phải lỗi: tiến trình đang phục vụ trang này được giao một bề mặt hẹp hơn — xem Bước 20.

ViệcMáy nàyLàm ở đâu
…Máy còn sốngđang đọc…Bước 1
…Có dữ liệu để trả lờiđang đọc…Bước 3 · agentctl ingest
…Model thật, không phải bản giảđang đọc…Bước 16
…Đã có trợ lýđang đọc…Bước 6
…Nghe và nói đượcđang đọc…Bước 10
…Trả lời được câu hỏi thậtbấm «Hỏi thử» bên dướiBước 13
Hỏi thử ngay — một câu, để thấy nó chạy
Chưa hỏi.

Câu trả lời kèm bằng chứng — danh sách hồ sơ mà nó đã dựa vào. Không có bằng chứng nào mà vẫn có câu trả lời trôi chảy là dấu hiệu xấu, không phải tốt: xem Bước 4 để biết nó đang thật sự biết gì.

Bước 1Trạng thái runtime

Cần trước: —  ·  Nếu Liveness hay Readiness đỏ thì đừng đọc tiếp; sửa nó trước.

Liveness
Đang kiểm tra
GET /health
Readiness
Đang kiểm tra
GET /readyz
Build
Đang kiểm tra
GET /version
Index
Đang kiểm tra
documents
Nguồn dữ liệu
Đang kiểm tra
GET /version

Bước 2Các khối đã nối vào server

Cần trước: bước 1  ·  Khối nào tắt ở đây thì mục tương ứng bên dưới sẽ báo lý do, không im lặng.

Đang tải...

Đọc cấu hình thật từ /version

Bước 14Bộ kiểm chứng runtime

Cần trước: server đang chạy  ·  72 phép kiểm gọi endpoint thật. Không thay python3 -m aiagent_portfolio.eval.

chưa chạy

Khi API_KEY được đặt, middleware chặn mọi endpoint trừ /health và /metrics — điền khoá vào ô ở mục “Thử API” trước khi chạy, nếu không tất cả sẽ đỏ vì 401. Mỗi phép kiểm nối với một điều khoản của AI_AGENT_STANDARD hoặc một luật trong CLAUDE.md §2; khi đỏ, thông báo nói rõ điều khoản nào đang bị vi phạm và sửa ở đâu. Các phép kiểm gọi endpoint thật, tự dọn hồ sơ tạm mình tạo ra. “Chỉ phép kiểm nhanh” bỏ những phép phải gọi model local (mỗi lần gọi tốn 9–40 s). Trang này không thay python3 -m aiagent_portfolio.eval: nó nói “còn sống và còn đúng hợp đồng”, eval mới nói “còn đúng chất lượng”.

Chưa chạy.

Bước 15Playground: gọi API bằng tay

Cần trước: bước 3  ·  Gọi tay từng đường khi cần soi một tham số cụ thể.

Hai khoá làm hai việc khác nhau. X-API-Key chỉ mở /aiagent-admin/auth/* (tạo tenant · user · api-key) — nó không tạo “principal”, nên mọi đường khác trả 401 nếu thiếu khoá tenant. X-Tenant-Api-Key mở phần còn lại, và role của nó quyết định bề mặt nào: role=admin → /aiagent-admin/*, role=platform → /aiagent-platform/*. Một khoá mang một role, nên getAgentTypeList cần khoá platform riêng.
/chat cần index + runtime AI. /recommend có thể trả fallback nhưng phải nói rõ trạng thái. Bộ lọc áp dụng cho cả hai — để trống mọi ô lọc thì không lọc gì.
Kết quả gần nhất
Chưa có request. Kết quả JSON và run_id sẽ hiện ở đây.

Bước 17Đối chiếu tính năng với agentic-mockup

Cần trước: —  ·  Đối chiếu với mockup — chấm theo endpoint có thật, không theo việc UI mô phỏng được.

Bảng này chấm mã, không chấm bản triển khai — nên nhóm «0 · Bản triển khai» được thêm vào để bịt đúng khoảng cách đó. Một tính năng có đủ route, qua đủ phép kiểm, vẫn có thể 404 ở mọi cổng nếu không tiến trình nào trong bản đang chạy nhận vai trò phục vụ tiền tố của nó. Đo 2026-08-30: bản 8 service bỏ lại 17/306 đường không ai phục vụ — 12 tiền tố quản trị của conversation, hai đường đọc của platform_admin, và ba đường WebSocket. Không lỗi nào báo ra; chúng chỉ đơn giản không tồn tại ở đó.

Bảng này khoá theo cấu trúc mockup hiện tại — 7 khu vực · 32 màn · wizard 5 bước — chứ không theo bản 26/08 (khi đó mockup chia AI Chat Agent · AI Social Agent · AI CS Agent; nay là AI Agents · AI Sales Agent · AI Marketing Agent cộng ba khu vực mới: Nhân viên, Cài đặt, Quản trị hệ thống).

Chấm theo endpoint có thật và gọi được, không theo việc UI mô phỏng được — và "có thật" ở đây nghĩa là đã gọi thử, không phải đã có mặt trong bảng định tuyến. Phân biệt đó không phải tiểu tiết: ngày 30/08, ba màn (Brand Voice, Tổng quan Sales, Thiết lập ban đầu) có đủ route, qua đủ mọi phép kiểm, và vẫn trả HTTP 500 — handler gọi một phương thức mà kho của nó không có. Nay test/contract/test_read_surface.py gọi thật mọi đường ĐỌC nên lớp lỗi đó không lọt lại được.

Bảy dòng "Một phần" là bảy chỗ CẦN hạ tầng hoặc dữ liệu bên ngoài, không phải bảy chỗ chưa làm: reach/impressions chỉ tồn tại ở Meta/Zalo Insights; sinh ảnh cần một model chưa cấu hình ở đây; làm mới token cần một App đã được nền tảng duyệt. Ba thứ đó không được làm giả — bịa một con số reach là đúng thứ toàn bộ hệ thống này từ chối làm, và một generateImage trả ảnh placeholder sẽ làm frontend dựng xong, demo chạy, rồi hỏng đúng lúc có khách thật. Mỗi dòng nói rõ "CÒN THIẾU" là gì.

Bước 18Cấu hình đang chạy (bằng lời thường)

Cần trước: —  ·  Cấu hình đang chạy, đọc từ /version. Bí mật chỉ hiện set(***).

Không phải bảng biến môi trường — đây là những gì máy chủ đang thực sự dùng lúc này, mỗi dòng kèm chỗ để đổi và có phải khởi động lại hay không. Đọc từ GET /version, không phải chữ viết sẵn.

Đang chạy bằng gì
Đang tải...
File .env
Đang tải...
Vì sao “tôi sửa .env mà không thấy gì đổi”Biến môi trường thật LUÔN thắng file .env — cần như vậy để AI_VOICE_ENABLED=false python3 -m aiagent_portfolio.main thắng được một file .env cũ trên máy. Mặt sau của luật đó chính là câu hỏi trên, nên ô này nói rõ: đã nạp file nào, đặt được bao nhiêu biến, và biến nào bị môi trường đè lên.

Khoá LLM của workspace đã chuyển ra khu demo → Khoá LLM của workspace. Nó nằm ở đây vì đây là màn «cấu hình», nhưng người cần nó là khách đang được onboard — và họ không bao giờ mở tới bước 18 của khu kỹ thuật.

Bước 20Bàn quản trị nền tảng — aiagent-platform

Cần trước: role=platform  ·  Bề mặt đọc chéo tenant. role=admin của một tenant không qua được.

Bề mặt thứ hai của hệ: bàn của người vận hành InCard, không phải bàn của chủ shop. Nó đọc chéo mọi tenant, nên nó là audience riêng ở đường dẫn (/aiagent-platform/) chứ không phải một nhánh if trong tầng phân quyền — nhìn path là biết một khoá chạm tới được những gì. Một khoá role=admin của tenant gọi bất kỳ đường nào dưới đây đều nhận PrivilegeNeed.
Ba nhóm ở đây: Đối chiếu hợp đồng (85 đường của tài liệu ⟂ bảng định tuyến thật), Quét đường đọc (gọi thật, xem mã trả về), và Gọi tay (dựng form từ chính bản khai tham số).

chưa quét

“Quét đường đọc” chỉ gọi những hành động bắt đầu bằng get — đúng tập mà token đăng nhập hộ được phép gọi, và cũng đúng tập không đổi gì. Các đường ghi phải bấm tay ở phần “Gọi tay” bên dưới, có chủ đích: một nút “chạy tất cả” quét qua setRate, refundTransaction và reembedAll là một nút không ai dám bấm.
“Nạp dữ liệu mẫu” chạy trọn một vòng đời: khách báo chuyển khoản → kế toán xác nhận → doanh thu và credit xuất hiện; cộng thêm một khoản còn chờ, một ticket, một yêu cầu xoá và một thông báo nháp, để bốn màn tiền và hàng đợi việc có số thật mà nhìn thay vì toàn số 0. Nó nạp qua chính những đường mà luồng thật đi qua (kể cả đường của bàn khách), không ghi thẳng vào kho — dữ liệu mẫu có hình dạng mà không luồng nào tạo ra được sẽ làm màn hình đẹp trong khi luồng thật vẫn hỏng. Nó ghi — chỉ chạy trên máy chạy thử.

Gọi tay một đường bất kỳ
Phản hồi gần nhất
Chưa gọi đường nào.
Đối chiếu hợp đồng — 85 đường · 24 module

Cột Bảng định tuyến đọc từ chính /version của binary đang chạy, không phải từ một danh sách chép tay ở trang này. Một dòng đỏ nghĩa là tài liệu hợp đồng và bảng định tuyến đã trôi khỏi nhau — và đó là thứ duy nhất mà bảng này tồn tại để phát hiện.

Bước 21Quan sát và kiểm chứng

Cần trước: —  ·  /metrics và các lệnh kiểm tra đề xuất.

Metrics snapshot
Đang tải...
Lệnh kiểm tra đề xuất
python3 -m unittest discover -p "test_*.py"python3 -m aiagent_portfolio.evalpython3 -m aiagent_portfolio.voice_eval

Bộ unittest kiểm hợp đồng offline, không cần server. `python3 -m aiagent_portfolio.eval`/`voice_eval` và bộ "Bộ kiểm chứng runtime" ở trên mới là kiểm đầu-cuối nên cần server, index và runtime AI đang sống.

Bước 22Bản đồ kiến trúc runtime

Cần trước: bước 1  ·  Mục này trả lời một câu: tiến trình đang phục vụ trang này là ai trong hệ, và nó KHÔNG phục vụ những gì. Số liệu đọc từ /health + /version, không gõ vào trang.

Vai trò tiến trình
Đang đọc
AI_SERVICE_ROLE
Bề mặt được phục vụ
Đang đọc
/version → service.serves
Đường trong bảng định tuyến
Đang đọc
sau khi roles.keeps() lọc
Một ảnh, nhiều cách chạy — chỗ bảng định tuyến bị cắt

Cùng một bản mã, cùng một ảnh triển khai. Thứ quyết định tiến trình này phục vụ đường nào là một biến môi trường, và việc cắt xảy ra ở roles.keeps() — trước khi có request nào tới. Vì thế một khoá quản trị bị lộ không mở được gì trên một tiến trình user: đường đó không tồn tại ở đó, nên nó trả 404 chứ không phải 403.

Người gọi widget · Messenger Zalo · quản trị viên WebSocket tiếng/hình Biên danh sách CHO PHÉP chỉ bề mặt người dùng + 2 đường webhook Bảng định tuyến đầy đủ /aiagent-user/* /aiagent-admin/* /aiagent-platform/* /aiagent-internal/* roles.keeps() Tiến trình này phục vụ đang đọc… đang đọc… 4 đường hạ tầng có ở MỌI vai trò Plugin đã nối vào đang đọc… mỗi plugin mang theo đường của nó wiring chủ sở hữu: ghi không sở hữu: chỉ đọc Kho trên đĩa đang đọc… mỗi kho một biến riêng Hàng đợi + worker đang đọc… Việc bền trong sqlite — nó sống lại sau khi khởi động lại, nên tắt worker KHÔNG mất tin, chỉ là không ai xử lý.
Bảy vai trò — bản khai, không phải số đo

Bảng này chép từ aiagent-kernel/aiagent_kernel/roles.py; nó là hợp đồng, không phải trạng thái. Dòng được tô là vai trò tiến trình này đang chạy — phần đó đọc từ /version. Gõ sai tên vai trò thì tiến trình từ chối khởi động chứ không âm thầm rơi về all.

AI_SERVICE_ROLEPhục vụ tiền tốWebSocketWorker
alluser · admin · platform · internal✓✓
useruser——
adminadmin——
platformplatform——
webhookinternal——
longconnkhông đường text nào✓—
workerkhông cổng nghiệp vụ—✓
Plugin đang nối vào tiến trình này

Đọc từ /version. Cột bỏ đi thì mất gì là lời khai của chính plugin — nó tồn tại để một quyết định gỡ plugin không phải là một phép đoán.

Đang đọc…

GET /version

Kho trên đĩa mà tiến trình này đang mở

Mỗi kho đọc biến riêng của nó, và mặc định là đường tương đối — nên chúng rơi vào ./data/ của thư mục đang đứng. Không có biến gom nào; danh sách dưới đây là đường thật đang dùng, lấy từ /version.

đang đọc…
Chín tiến trình của một bản triển khai — bản khai, không phải số đo

Trang này chỉ nói chắc chắn được về tiến trình đang phục vụ nó — trình duyệt không gọi được sang cổng khác (nguồn gốc khác). Bảng dưới là bản khai, và nguồn sự thật của nó là ops/agentctl cộng ENV trong Dockerfile của từng kho. Dòng được tô là tiến trình đang phục vụ trang này, so theo cổng đọc từ /version.

Tiến trìnhCổngVai tròSở hữu / vai trò trong hệ
conversation7077userbề mặt người dùng cuối — hỏi đáp, tiếng, hình
identity7101admindanh tính, tenant, nhân sự, khoá API
knowledge7102adminchủ ghi của index/ — nạp và lưu tri thức
platform7103platformbàn quản trị nền tảng — đọc chéo tenant
webhook7104webhookingress công khai — xác minh chữ ký rồi phát việc
conversation-admin7105adminCÙNG ảnh với 7077, đổi vai trò. Không chạy nó thì 12 tiền tố quản trị không có ai phục vụ
crm7106adminkhách hàng, cơ hội, chuyển người thật
social7107adminkênh, chiến dịch, hội thoại mạng xã hội
billing7108adminsổ credit, bảng định mức

Ba chủ sở hữu kho gọi nhau qua mạng khi chạy nhiều tiến trình. Không khai địa chỉ nào thì nhân dùng bản gọi trong tiến trình — đúng cho bản một tiến trình, nhưng ở bản nhiều tiến trình nó nghĩa là mỗi service tự trả lời chính mình, và câu hỏi chéo chủ sở hữu trả về rỗng mà không có lỗi nào.

Service tự phục vụ trang này qua GET / (aiagent_kernel/http.py:_dashboard). Không CDN, không framework frontend, không dependency mới — runtime thật do GET /health khai, hiện ở góc trên bên trái. API key không được lưu vào localStorage.

Bước 0Tổng quan

Cần trước: đăng nhập role=admin  ·  Màn này gọi /aiagent-user/overview/getSummary. Rỗng ở đây là rỗng CÓ THẬT, không phải dữ liệu mẫu.

Đang dựng…

Bước 0Agent của tôi

Cần trước: đăng nhập · một trợ lý đã tạo ở bước 6  ·  Màn này gọi /aiagent-admin/agent/getAgentList. Rỗng ở đây là rỗng CÓ THẬT, không phải dữ liệu mẫu.

Đang dựng…

Bước 0Kho kiến thức

Cần trước: đăng nhập · nguồn đã nạp ở bước 3  ·  Màn này gọi /aiagent-admin/source/getSourceList. Rỗng ở đây là rỗng CÓ THẬT, không phải dữ liệu mẫu.

Đang dựng…

Bước 0Brand Voice

Cần trước: đăng nhập · brand voice tạo ở bước thiết lập  ·  Màn này gọi /aiagent-admin/social/getBrandVoiceList. Rỗng ở đây là rỗng CÓ THẬT, không phải dữ liệu mẫu.

Đang dựng…

Bước 0Kênh kết nối

Cần trước: đăng nhập · một Page đã gắn ở bước 9  ·  Màn này gọi /aiagent-admin/channel/getChannelBindingList. Rỗng ở đây là rỗng CÓ THẬT, không phải dữ liệu mẫu.

Đang dựng…

Bước 0AI Growth

Cần trước: đăng nhập · đã có lượt hỏi để duyệt  ·  Màn này gọi /aiagent-admin/feedback/getFeedbackList. Rỗng ở đây là rỗng CÓ THẬT, không phải dữ liệu mẫu.

Đang dựng…

Bước 0Tổng quan Chat

Cần trước: đăng nhập · plugin social bật  ·  Màn này gọi /aiagent-admin/analytics/getOverview. Rỗng ở đây là rỗng CÓ THẬT, không phải dữ liệu mẫu.

Đang dựng…

Bước 0Hội thoại

Cần trước: đăng nhập · một kênh đã nối ở bước 9  ·  Màn này gọi /aiagent-admin/conversation/getConversationList. Rỗng ở đây là rỗng CÓ THẬT, không phải dữ liệu mẫu.

Đang dựng…

Bước 0Pipeline

Cần trước: đăng nhập  ·  Màn này gọi /aiagent-admin/crm/getStageList. Rỗng ở đây là rỗng CÓ THẬT, không phải dữ liệu mẫu.

Đang dựng…

Bước 0Tổng quan CS

Cần trước: đăng nhập  ·  Màn này gọi /aiagent-admin/cs/getCsatSummary. Rỗng ở đây là rỗng CÓ THẬT, không phải dữ liệu mẫu.

Đang dựng…

Bước 0Lời nhắc

Cần trước: đăng nhập · một trợ lý đã có kênh  ·  Màn này gọi /aiagent-admin/cs/getReminderRuleList. Rỗng ở đây là rỗng CÓ THẬT, không phải dữ liệu mẫu.

Đang dựng…

Bước 0Chiến dịch vòng đời

Cần trước: đăng nhập · khách đã có đơn (mốc vòng đời tính từ lần mua)  ·  Màn này gọi /aiagent-admin/cs/getLifecycleCampaignList. Rỗng ở đây là rỗng CÓ THẬT, không phải dữ liệu mẫu.

Đang dựng…

Bước 0Phản hồi & CSAT

Cần trước: đăng nhập  ·  Màn này gọi /aiagent-admin/cs/getCsatSummary. Rỗng ở đây là rỗng CÓ THẬT, không phải dữ liệu mẫu.

Đang dựng…

Bước 0Tổng quan Marketing

Cần trước: đăng nhập · plugin social bật  ·  Màn này gọi /aiagent-admin/analytics/getOverview. Rỗng ở đây là rỗng CÓ THẬT, không phải dữ liệu mẫu.

Đang dựng…

Bước 0Lịch đăng

Cần trước: đăng nhập · một bài đã lên lịch  ·  Màn này gọi /aiagent-admin/social/getSchedule. Rỗng ở đây là rỗng CÓ THẬT, không phải dữ liệu mẫu.

Đang dựng…

Bước 0Bài viết

Cần trước: đăng nhập  ·  Màn này gọi /aiagent-admin/social/getPostList. Rỗng ở đây là rỗng CÓ THẬT, không phải dữ liệu mẫu.

Đang dựng…

Bước 0Thư viện ảnh

Cần trước: đăng nhập  ·  Màn này gọi /aiagent-admin/asset/getAssetList. Rỗng ở đây là rỗng CÓ THẬT, không phải dữ liệu mẫu.

Đang dựng…

Bước 0Chiến dịch

Cần trước: đăng nhập  ·  Màn này gọi /aiagent-admin/social/getCampaignList. Rỗng ở đây là rỗng CÓ THẬT, không phải dữ liệu mẫu.

Đang dựng…

Bước 0Lead từ comment

Cần trước: đăng nhập · một Page đã gắn  ·  Màn này gọi /aiagent-admin/commentLead/getRuleList. Rỗng ở đây là rỗng CÓ THẬT, không phải dữ liệu mẫu.

Đang dựng…

Bước 0Phân tích

Cần trước: đăng nhập · đã có bài đăng và đơn để dựng phễu  ·  Màn này gọi /aiagent-admin/analytics/getFunnel. Rỗng ở đây là rỗng CÓ THẬT, không phải dữ liệu mẫu.

Đang dựng…

Bước 0Quản lý công việc

Cần trước: đăng nhập  ·  Màn này gọi /aiagent-admin/crm/getTaskList. Rỗng ở đây là rỗng CÓ THẬT, không phải dữ liệu mẫu.

Đang dựng…

Bước 0Khách tiềm năng

Cần trước: đăng nhập · lead vào từ chat hoặc nhập tay  ·  Màn này gọi /aiagent-admin/crm/getLeadList. Rỗng ở đây là rỗng CÓ THẬT, không phải dữ liệu mẫu.

Đang dựng…

Bước 0Khách hàng

Cần trước: đăng nhập  ·  Màn này gọi /aiagent-admin/crm/getCustomerList. Rỗng ở đây là rỗng CÓ THẬT, không phải dữ liệu mẫu.

Đang dựng…

Bước 0Nhóm khách hàng

Cần trước: đăng nhập · đã có khách để chia nhóm  ·  Màn này gọi /aiagent-admin/crm/getSegmentList. Rỗng ở đây là rỗng CÓ THẬT, không phải dữ liệu mẫu.

Đang dựng…

Bước 0Đơn hàng

Cần trước: đăng nhập  ·  Màn này gọi /aiagent-admin/crm/getOrderList. Rỗng ở đây là rỗng CÓ THẬT, không phải dữ liệu mẫu.

Đang dựng…

Bước 0Sản phẩm

Cần trước: đăng nhập  ·  Màn này gọi /aiagent-admin/crm/getProductList. Rỗng ở đây là rỗng CÓ THẬT, không phải dữ liệu mẫu.

Đang dựng…

Bước 0Danh sách nhân viên

Cần trước: đăng nhập role=admin — danh sách này là của MỘT tenant  ·  Màn này gọi /aiagent-admin/staff/getStaffList. Rỗng ở đây là rỗng CÓ THẬT, không phải dữ liệu mẫu.

Đang dựng…

Bước 0Bảng điểm nhân viên

Cần trước: đăng nhập · đã có hội thoại để AI chấm  ·  Màn này gọi /aiagent-admin/coach/getScorecardList. Rỗng ở đây là rỗng CÓ THẬT, không phải dữ liệu mẫu.

Đang dựng…

Bước 0Tiêu chuẩn đánh giá

Cần trước: đăng nhập role=admin  ·  Màn này gọi /aiagent-admin/coach/getRubric. Rỗng ở đây là rỗng CÓ THẬT, không phải dữ liệu mẫu.

Đang dựng…

Bước 0Gói & Thanh toán

Cần trước: đăng nhập · đã có ít nhất một lần nạp hoặc gia hạn  ·  Màn này gọi /aiagent-admin/billing/getInvoiceList. Rỗng ở đây là rỗng CÓ THẬT, không phải dữ liệu mẫu.

Đang dựng…

Bước 0Chi tiết credit

Cần trước: đăng nhập · đã có lượt gọi model để trừ credit  ·  Màn này gọi /aiagent-admin/billing/getUsageSummary. Rỗng ở đây là rỗng CÓ THẬT, không phải dữ liệu mẫu.

Đang dựng…

Bước 0Tích hợp

Cần trước: đăng nhập role=admin  ·  Màn này gọi /aiagent-admin/integration/getCatalog. Rỗng ở đây là rỗng CÓ THẬT, không phải dữ liệu mẫu.

Đang dựng…

Bước 0Giới thiệu & hoa hồng

Cần trước: đăng nhập  ·  Màn này gọi /aiagent-admin/referral/getSummary. Rỗng ở đây là rỗng CÓ THẬT, không phải dữ liệu mẫu.

Đang dựng…

Bước 0Hồ sơ của tôi

Cần trước: đăng nhập — đường này đọc hồ sơ của CHÍNH token đang cầm  ·  Màn này gọi /aiagent-admin/auth/getSelfProfile. Rỗng ở đây là rỗng CÓ THẬT, không phải dữ liệu mẫu.

Đang dựng…