---
title: "Cách để website đạt Agent Ready - Chỉ có llms.txt hay render Markdown là chưa đủ"
description: "llms.txt và bản Markdown mới là phần dễ thấy. Website Agent Ready còn cần twin đúng quyền, negotiation an toàn, cache không nhầm và UI cho Agent dùng browser."
canonical: "https://200lab.io/blog/cach-de-website-dat-agent-ready"
published: "2026-10-05T16:02:09Z"
updated: "2026-10-06T01:52:38Z"
authors: ["Việt Trần"]
tags: ["Agent", "AI", "Frontend"]
reading_minutes: 18
access: "public"
---

Mình đã xây dựng các hệ thống và website để phù hợp với cả người dùng lẫn AI Agent, trong đó có hệ thống website của 200Lab.

Trong quá trình làm theo hướng Agent/AI Native, mình vừa áp dụng, vừa collect lại các quy tắc thành một bộ skill: agent-ready-web. Mục đích là để coding Agent có hướng dẫn đầy đủ khi xây dựng mới hoặc audit một website.

Link download skill nằm ở cuối bài.

Bây giờ cứ nhắc tới chuyện làm website cho AI Agent là gần như ai cũng nghĩ ngay tới hai việc: thêm file **llms.txt**, và cho mỗi trang một bản Markdown. Hai việc này đúng, nên làm, mình cũng làm. Nhưng làm xong hai việc đó mới chỉ xong phần dễ thấy nhất. Agent vẫn có thể đọc được nội dung mà nó không có quyền xem, browser của người dùng vẫn có thể nhận nhầm một trang Markdown từ cache, và một Agent đang điều khiển browser vẫn có thể kẹt ở cái nút không có tên.

Bài này đi qua những phần còn lại, theo cách bộ skill chia việc.

## Agent ghé website theo hai cách

Câu hỏi đầu tiên không phải là "thêm file gì", mà là: Agent nào đang đến, và nó đến bằng cách nào. Có hai kiểu rất khác nhau:

- **Reader**: fetch URL bằng HTTP thuần, không chạy JavaScript. Đó là crawler, fetch tool bên trong các trợ lý AI, answer engine. Mỗi token tụi nó đọc vào đều tốn tiền.
- **Operator**: điều khiển một browser thật, nhìn trang qua accessibility tree và screenshot, rồi click, gõ, cuộn như người thật.

![Reader đọc bản Markdown qua HTTP, Operator điều khiển browser qua accessibility tree.](https://assets.200lab.io/sha256/48/48108f4e63639d2d524ec937514ad263b1ddd84afd3f7e11f6eb5b285fe51283/generations/7645fe322fb83af1676e04d74a5069b9244fc6e11e5692a684ebe17df3f28df5)

| | Reader | Operator |
|---|---|---|
| Cách ghé | HTTP request, không JS | Browser thật |
| Cần | Nội dung sạch, ít token, URL ổn định | Nút có tên, trạng thái nhìn thấy được, URL phản ánh trạng thái |
| Gặp khó khi | Phải nuốt HTML đầy menu, script, banner | Gặp div bấm được, nút chỉ có icon, thao tác chỉ có khi hover |

llms.txt và Markdown chỉ phục vụ nhóm thứ nhất. Nhóm thứ hai không cần Markdown. Thứ nó cần là một giao diện có tên nút, trạng thái và URL phản ánh đúng chức năng. Nên nếu chỉ dừng ở llms.txt thì coi như mới lo được cho một trong hai kiểu Agent.

Với Reader, chi phí token là chuyện có thật. Mình đo thử trên chính 200Lab: trang chủ trả về khoảng 960 KB HTML, bản Markdown **/index.md** chỉ khoảng 18 KB. Bài blog về Hexagonal Architecture thì khoảng 650 KB HTML, so với 13 KB Markdown. Đây là byte chưa nén chứ chưa phải token, và nhiều fetch tool cũng tự lọc bớt HTML trước khi đưa cho model. Nhưng chênh nhau cỡ 50 lần thì phần thừa vẫn rất lớn.

## llms.txt chỉ là cái mục lục

llms.txt (theo llmstxt.org) là thứ Agent đọc đầu tiên: một file ngắn để Agent biết site có gì và lên kế hoạch trước khi crawl. Cấu trúc của nó đơn giản: `# Tên site` là phần bắt buộc duy nhất, một dòng `>` tóm tắt, rồi các khối `## Section` gồm những dòng `- [Tiêu đề](URL): ghi chú`.

Cái khó không nằm ở format mà nằm ở mấy quy tắc đi kèm:

- **Link phải là URL tuyệt đối và trỏ thẳng vào bản Markdown.** Mục lục trỏ về HTML thì Agent đọc mục lục xong lại phải quay về nuốt HTML, vậy là mục lục mất tác dụng.
- **Không bịa summary.** Item nào chưa có mô tả thì để trống, section rỗng thì bỏ. Một câu mô tả do code tự chế ra còn tệ hơn không có.
- **Có giới hạn dung lượng.** Site lớn thì llms.txt liệt kê vài mục mới nhất rồi link sang danh sách và sitemap, chứ không nhồi mọi thứ vào một file.
- **Chỉ nội dung public.** Nghe hiển nhiên, nhưng file này thường được generate từ một query riêng, và query riêng là chỗ dễ quên điều kiện lọc.

Có hai file hay đi chung mà nhiều người hiểu nhầm. **llms-full.txt** thực ra không nằm trong spec. Nó là quy ước bắt nguồn từ Mintlify rồi được nhiều nơi làm theo: gộp toàn văn các trang quan trọng vào một file. Có thì tốt, nhưng phải đặt giới hạn dung lượng cứng, và chỉ nhắc tới nó khi file thật sự tồn tại. Còn /index.md là trang chủ ở dạng Markdown, kết thúc bằng danh sách các tài liệu dành cho máy đọc. Đây là thứ được trả về khi có request xin chính trang chủ ở dạng Markdown.

Một chi tiết nhỏ nhưng hay sai: mỗi trang HTML nên trỏ tới llms.txt bằng `rel="describedby"` chứ không phải `rel="alternate"`. llms.txt mô tả cả site, nó không phải một phiên bản khác của trang đang xem. Còn bản Markdown của chính trang đó mới là alternate.

Riêng **robots.txt** cũng có một cái bẫy: group `User-agent: GPTBot` không kế thừa luật của `User-agent: *`. Bạn viết luật chặn /checkout cho group `*` rồi thêm một group riêng cho GPTBot thì GPTBot không còn bị chặn /checkout nữa. Ngoài ra, nên quyết định chặn hay cho phép theo từng nhóm Agent: crawler để train, crawler để search, và fetcher do người dùng kích hoạt. Chặn nhóm cuối là làm hỏng luôn tính năng "đọc giúp mình trang này" trong các trợ lý.

## Markdown twin: một nguồn dữ liệu, hai cách render

Bộ skill gọi bản Markdown của mỗi trang là twin. Quy ước URL: lấy path của trang rồi thêm .md, ví dụ /blog/post có twin là /blog/post.md, trang chủ có twin là /index.md. Trang HTML khai báo twin của mình bằng header Link và thẻ `<link rel="alternate" type="text/markdown">`.

![HTML và Markdown twin dựng từ cùng dữ liệu, đi qua cùng một bước kiểm tra quyền.](https://assets.200lab.io/sha256/0d/0d25cdb183924e836709d399a025230c1558ca60c9cdd2834db079c696b4a2e5/generations/eb5ab38c8ad2638201e802f289bf34939158b603a6b1d95ae97307fdc1bae71a)

> 💡 **One truth, two renderings.** HTML cho người và Markdown cho Agent được dựng từ cùng một nguồn dữ liệu. Ưu tiên render từ dữ liệu domain thay vì convert từ HTML. Nếu buộc phải convert từ HTML thì kiểm tra lại kết quả.

Vì sao không convert HTML cho nhanh? Vì HTML đã trộn nội dung với mọi thứ khác: menu, footer, banner, widget, tracking. Convert ra thì Markdown kéo theo hết đống đó, hoặc rơi mất đúng phần quan trọng. Trong khi twin lại cần những thứ HTML không thể hiện gọn gàng: các thông tin mà Agent dùng để lọc. Bộ skill đặt chúng vào YAML front matter: title, description, canonical, ngày published/updated dạng ISO, authors, tags, lang, access, và với trang bán hàng thì thêm giá, tiền tệ, tình trạng còn hàng.

Phần nội dung của twin tuân theo vài quy tắc:

- Một H1, nội dung theo đúng thứ tự đọc, không menu, không footer, không tracking.
- Mọi link là URL tuyệt đối, và trỏ vào twin .md khi có.
- Kết thúc bằng các hành động tiếp theo: bài liên quan, bài trước và sau, danh sách cha, cách mua hay đăng ký. Cách mua là một URL, không bao giờ là một form.
- Trang danh sách thì mỗi item một dòng: link, tóm tắt, vài fact chính. Không có tóm tắt thì bỏ, không bịa.

Chỗ nguy hiểm nhất là nội dung giới hạn quyền truy cập. Twin là một renderer mới, chạy song song với HTML, nên đây là chỗ dễ rò nội dung trả phí nhất: người viết twin quên gọi đúng hàm kiểm tra quyền mà trang HTML đang gọi. Quy tắc là twin kiểm tra quyền y hệt trang HTML: người gọi được xem phần nào thì chỉ đưa phần đó, rồi thêm một dòng nói rõ phần nào đang bị ẩn, kèm link. Twin trả cho người đã đăng nhập phải gửi `private, no-store`, và không bao giờ xuất hiện trong file export dùng chung.

Và khi một nội dung chuyển từ public sang có phí, hay ngược lại, thì phải làm mới (invalidate) tất cả các bản: HTML, twin, các file export, bản trên CDN. Bộ skill còn ghi một chi tiết dễ bỏ qua: một response đang xử lý dở vẫn có thể ghi lại vào cache ngay sau khi bạn vừa purge. Vì vậy với nội dung có thể bị khóa, hãy để TTL của cache dùng chung ngắn, hoặc purge thêm một lần nữa khi mọi thứ đã ổn định.

## Content negotiation: tiện, nhưng browser không được chịu thiệt

Ngoài URL .md, còn một cách nữa: cùng một URL, Agent gửi `Accept: text/markdown` thì nhận Markdown, browser gửi Accept bình thường thì nhận HTML. Đây là content negotiation, và nó rất tiện cho Agent không biết quy ước .md.

Nhưng bộ skill đặt nó đúng vị trí, theo nguyên tắc **explicit beats sniffed**: khai báo rõ ràng luôn tốt hơn đoán. Mỗi twin phải có URL riêng và được khai báo bằng link. Negotiation chỉ là lớp tiện lợi đặt trên URL đó, không bao giờ là lối vào duy nhất.

Việc chuyển sang Markdown chỉ áp dụng cho request GET/HEAD xin document của trang có twin, không bao giờ áp dụng cho request lấy data của framework, prefetch, asset hay API. Trong phạm vi đó, trả Markdown khi Accept ưu tiên text/markdown, khi edge xác nhận đây là AI reader, hoặc khi User-Agent chứa token của một AI fetcher đã biết. Riêng client đã loại text/markdown bằng `q=0` thì không bao giờ nhận Markdown:

![Khi nào trả Markdown: chỉ cho document có twin, không bao giờ cho client đã loại text/markdown.](https://assets.200lab.io/sha256/4d/4df5d0affe1cc66afe25137c9ec070bf2671333231b62e46f432eb6a9e8ebf8c/generations/194893870f286a2a5a30b7045f316ce6386bde36df111ee0432368d47e4b0560)

Mấy điểm đáng chú ý:

- So sánh Accept theo q-value. Hai bên ngang nhau thì giữ HTML là mặc định an toàn. Một số coding Agent đặt text/markdown lên đầu, còn đa số chat product vẫn xin HTML.
- Giữ HTML cho search engine crawler, bot tạo link preview, và đặc biệt là Agent điều khiển browser, vì tụi nó cần UI thật.
- Trả về 302 sang URL .md với `Cache-Control: no-store`, thay vì trả hai nội dung khác nhau trên cùng một URL. Lý do nằm ở phần cache bên dưới.
- URL đích được dựng từ bảng route của chính bạn, không bao giờ từ header Host, header forwarded hay một query parameter. Lấy từ những chỗ đó là tự tạo lỗ hổng open redirect.

Còn tín hiệu "AI reader đã xác minh" từ edge thì chỉ tin khi nó đến từ proxy của bạn, và chỉ dùng để chọn định dạng trả về. Không bao giờ dùng nó để cấp quyền, đổi giá hay miễn rate limit.

## CDN: chỗ dễ làm hỏng nhất

Một nguyên tắc quan trọng khác của bộ skill là **browsers never lose**: cache dùng chung không bao giờ được trả cho browser một response vốn dành cho Agent.

Nghe thì hiển nhiên, nhưng hãy thử kịch bản này. Origin trả Markdown cho request có `Accept: text/markdown` ngay trên URL gốc và đặt `Vary: Accept` đàng hoàng. Một Agent ghé vào, CDN cache lại response đó theo URL. Người dùng tiếp theo mở trang bằng browser và nhận về một trang chữ thô. Lý do: mặc định Cloudflare bỏ qua Vary, trừ Accept-Encoding. Origin làm đúng chuẩn HTTP, nhưng CDN không đọc header đó.

![CDN bỏ qua Vary: Accept nên browser nhận nhầm bản Markdown đã cache cho Agent.](https://assets.200lab.io/sha256/fe/fed9b514f5ea818b56d034ce1648da4900a80c030ffc1ef1513b21eeaf951118/generations/bfab54f43e5e2f7bae8695719ed609adc6f67467aff1ea7bb500740c9f6a2ebc)

> ⚠️ Đừng trông cậy vào Vary khi chưa kiểm tra trên chính zone Cloudflare của bạn. Khi còn nghi ngờ, redirect sang một URL riêng thay vì trả hai nội dung khác nhau trên cùng một URL.

Với Cloudflare, bộ skill ghi lại mấy điều mình thấy khi làm thật:

- **Nhận diện Agent làm được trên mọi gói.** Một Transform Rule gắn giá trị `cf.verified_bot_category` vào một header gửi về origin. Khi giá trị rỗng thì header bị xóa, nên bản giả mạo do client tự gửi cũng bị xóa theo.
- **Nhưng Cache Rule thì không dùng được field bot** nếu không có Bot Management. Trên một zone Free, Cloudflare trả lỗi khi rule dùng field đó. Vì vậy rule cache HTML phải bỏ qua cache cho mọi trường hợp có thể dẫn tới Markdown, bằng những field mà rule match được: Accept có text/markdown, danh sách User-Agent, header data request của framework, cookie đăng nhập.
- **TTL mặc định ở edge.** Rule chọn "Respect origin" sẽ dùng TTL mặc định của Cloudflare khi origin không gửi header cache. Còn ép TTL cố định thì có thể cache luôn response có Set-Cookie. Chỉ cache khi chính origin cho phép chia sẻ.
- **Markdown for Agents** của Cloudflare (gói Pro trở lên, đang beta) tự convert HTML sang Markdown ở edge. Đây là cách làm nhanh khi origin chưa có twin. Nhưng nó chỉ convert HTML, và làm mất ETag. Twin dựng từ origin vẫn tốt hơn: nội dung được chọn lọc, đúng quyền truy cập, có front matter, có hành động tiếp theo.

Purge cũng phải đi theo cặp: HTML và twin của nó cùng lúc, sau mỗi lần deploy và mỗi lần nội dung thay đổi.

## Framework cũng có bẫy riêng

Phần pitfall trong bộ skill gom những lỗi đã gặp trên production, vài lỗi trong đó rất khó đoán nếu chưa từng dính.

**Client router.** Next.js và các framework tương tự gửi request data riêng khi bạn bấm link (RSC, prefetch, JSON route). Nếu middleware rewrite nhầm các request đó sang route Markdown hay route khác, thì bấm link sẽ đổi URL trên thanh địa chỉ nhưng nội dung không đổi. Tệ hơn, một số phiên bản framework tự xóa header đánh dấu của nó trước khi request tới hook của bạn: proxy của Next.js 16.2 giấu `RSC`, `Next-Router-*` và `_rsc`. Nên phải log xem hook thật sự nhận được gì, đừng đoán theo tài liệu. Sau mỗi rewrite mà client router chạm tới được, test lại ba trường hợp: mở trang trực tiếp (cold load), chuyển trang đã prefetch, và link chỉ đổi query.

**Header bị ghi đè.** Hai lớp cùng set header Link (ví dụ headers() của framework và proxy) sẽ đè lên nhau. Hãy gộp lại và chỉ gửi một header.

**Lỗi mềm.** Trang không tồn tại và .md không tồn tại đều phải trả 404. Query sai format thì 400. Query hợp lệ mà không có kết quả thì là một trang rỗng bình thường.

**Cắt bớt mà không báo.** Danh sách hay file export bị giới hạn số lượng thì phải nói rõ đã bỏ những gì và link sang phần tiếp theo. Agent không biết mình đang đọc một danh sách bị cắt thì sẽ kết luận sai.

## Agent điều khiển browser cần gì

Quay lại nhóm Operator. Một câu tóm được gần hết: cái gì làm khó screen reader, hay đòi con trỏ chuột chính xác, thì cũng làm khó Agent. Nên phần lớn việc ở đây chính là accessibility, chỉ là giờ có thêm một lý do rất thực tế để làm cho đàng hoàng.

Những quy tắc chính:

- **Dùng element HTML gốc.** Link thì là `<a href>`, hành động thì là `<button>`, input có `<label>`. Không có div bấm được. Bộ lọc và phân trang là link thật, JS chỉ bổ sung trải nghiệm.
- **Accessible name nói rõ hành động.** Nút chỉ có icon thì có aria-label. Hai nút trên cùng màn hình không được trùng tên nếu làm hai việc khác nhau: "Thêm vào giỏ - Khóa A", không phải hai nút "Thêm" trơn.
- **Trạng thái nằm trong URL.** Filter, sort, tab, tìm kiếm, phân trang là query param. Khi đổi ngay trong trang thì cập nhật URL bằng `history.pushState` và lấy dữ liệu phía client, không render lại cả trang. Reload hay gửi link cho người khác thì ra đúng trạng thái đó.
- **Trạng thái phải hiện ra trong accessibility tree.** aria-pressed, aria-selected, aria-expanded, aria-current. Một nút bật tắt chỉ đổi màu thì vô hình trong accessibility tree.
- **Không có thao tác chỉ làm được bằng hover hay cử chỉ.** Cái gì mở được bằng hover, kéo, vuốt thì cũng phải làm được bằng click hoặc bàn phím.
- **Không đặt CAPTCHA ở các trang chỉ để đọc.** Muốn giới hạn thì trả 429 kèm Retry-After.

Cách kiểm cũng không cần gì đặc biệt: lấy accessibility snapshot của trang, rồi thử đi hết các tác vụ chính (tìm, lọc, mở, mua, đăng ký) chỉ dựa vào snapshot đó. Bước nào không có role và tên rõ ràng là bước Agent phải đoán.

## Xong là khi kiểm được từ bên ngoài

Nguyên tắc cuối của bộ skill: **prove it from outside**. Công việc chỉ được tính là xong khi các bài kiểm tra black-box đạt trên origin đã deploy và qua cả CDN, chứ không phải khi code compile được.

Vì vậy bộ skill đi kèm một script audit. Script này chỉ dùng thư viện chuẩn của Python, chỉ gửi GET/HEAD, không đăng nhập, không gửi form, và chỉ gọi đúng origin bạn đưa vào. Bạn chạy nó với một URL cho mỗi loại trang, và nó kiểm những thứ như: trang HTML có đủ title, description, lang, một H1, canonical và JSON-LD hợp lệ chưa; twin có được khai báo không, có đúng content type, link tuyệt đối, canonical trỏ về HTML không; HEAD có trả body không; negotiation xử lý đúng các trường hợp `q=0`, ưu tiên ngang nhau, `*/*`, Accept của browser không; llms.txt đúng shape và link có trỏ vào Markdown không; trang và .md không tồn tại có trả 404 không.

Mình chạy nó trên chính 200Lab với trang chủ và một bài blog: 0 FAIL, 2 WARN, 70 PASS. Hai WARN là twin của bài blog chưa gửi header Link rel=canonical về trang HTML. Tức là chính mình cũng còn việc phải làm, và đó đúng là lý do cần một script chạy từ bên ngoài.

Script cũng nói rõ giới hạn của nó: nó lấy mẫu chứ không chứng minh. Nó không chứng minh được cache trên CDN đã tách riêng cho Agent và browser, không kiểm được nội dung sau đăng nhập, cũng không kiểm được accessibility của trang sau khi render. Những phần đó nằm trong checklist kiểm tay. Khi báo cáo audit, bộ skill chia kết quả thành ba nhóm: FAIL (Agent nhận nội dung sai hoặc bị rò, hoặc browser có thể nhận như vậy), WARN (tốn token, thiếu discovery, cache yếu) và IDEA. Sửa FAIL trước.

## Tự làm hay lấy bộ skill

Đọc tới đây thì bạn đã có đủ khung để tự dựng phần lớn: hai kiểu Agent, mục lục llms.txt, twin dựng từ cùng nguồn dữ liệu, negotiation chỉ là lớp tiện lợi, CDN không được đưa nhầm Markdown cho browser, UI cho Operator, và kiểm từ bên ngoài.

Bộ skill tiết kiệm cho bạn phần còn lại, là phần tốn thời gian nhất: chi tiết từng header, từng trường hợp biên và những lỗi chỉ thấy khi chạy thật. Trong file có:

- **SKILL.md**: 6 nguyên tắc, quy trình 6 bước từ kiểm kê loại trang tới verify, danh sách pitfall đã gặp trên production, và cách viết báo cáo audit.
- **references/markdown-twins.md**: quy ước URL kể cả các tài liệu có query như /search.md, đầy đủ header của twin, ETag và 304, TTL cho bản public và bản cần đăng nhập, quy tắc cho nội dung có phí, format danh sách và phân trang, byte budget, danh sách test cần có.
- **references/discovery-files.md**: llms.txt, llms-full.txt, /index.md, header Link, robots.txt theo từng nhóm Agent kèm Content-Signal, sitemap, JSON-LD theo từng loại trang, noindex và hreflang, cách trỏ tới MCP server hay API (kể cả metadata OAuth theo RFC 9728).
- **references/edge-and-cloudflare.md**: điều kiện route đầy đủ, khi nào được tin header từ edge, các rule Cloudflare cụ thể (nhận diện bot, bypass cache, TTL ở edge, cấu hình Vary, Markdown for Agents, purge, tự động hóa rule bằng script), cách áp dụng cho CDN khác, và ghi chú theo framework.
- **references/browser-agent-ui.md**: 13 quy tắc UI cho Agent điều khiển browser và cách kiểm từng cái.
- **references/checklist.md**: checklist cho Reader, Operator và Edge/cache, đánh dấu mục nào script tự kiểm, mục nào phải kiểm tay.
- **scripts/audit-agent-readiness.py**: script audit black-box khoảng 340 dòng, chỉ cần Python, trả exit code 1 khi có FAIL nên gắn được vào CI.

Cách dùng: chép thư mục agent-ready-web vào thư mục skills của coding Agent bạn đang dùng (với Claude Code là .claude/skills/), rồi giao việc như "audit 200lab.io theo agent-ready-web" hoặc "làm markdown twin cho trang blog theo agent-ready-web". Agent sẽ tự đọc phần reference cần cho từng bước.

**Bộ skill agent-ready-web: xây mới và audit website cho AI Agent**

Bộ skill cho coding Agent (Claude Code, Codex...) để xây mới hoặc audit website theo hướng Agent Ready: markdown twin, llms.txt, content negotiation, cache và CDN, UI cho Agent điều khiển browser. Kèm checklist và script audit black-box bằng Python.

- Định dạng: ZIP · 1 tệp · 18,7 KB
- Giá: 19.000 ₫ · mua một lần
- Truy cập: tải về sau khi mua, cần đăng nhập
- Mua: https://200lab.io/blog/cach-de-website-dat-agent-ready#artifact-01a10cc5-adf9-79fa-98f2-1adf8f1a6166

## Đọc thêm

- [Claude Mythos 5 vượt phạm vi trong bài thử của UK AISI: chuyện gì đã xảy ra](https://200lab.io/blog/claude-mythos-5-uk-aisi-vuot-pham-vi.md): Claude Mythos 5 đã làm việc ngoài phạm vi ở 9/43 lượt chạy trong bài thử của UK AISI. Lỗi không đến từ ác ý, mà từ việc quá muốn hoàn thành nhiệm vụ.
- [Thử dùng Grok Bot vận hành shop online và bài học chia quyền](https://200lab.io/blog/quan-ly-shop-online-bang-grok-bot.md): Quản lý shop online bằng Grok Bot từ chấm việc, viết sổ tay đến chia quyền. Điều mình rút ra: luật thiếu chỗ nào thì bot cũng thiếu chỗ đó.
- [Làm công ty một người, bạn thực sự cần mấy nhân viên AI?](https://200lab.io/blog/cong-ty-mot-nguoi-can-may-nhan-vien-ai.md): Làm công ty một người, bạn cần mấy nhân viên AI? Đừng vội mua bot, hãy bắt đầu từ danh sách việc của chính bạn.
- [Tạo skill cho bot: đừng để AI agent tự biên tự diễn với khách](https://200lab.io/blog/skill-la-gi-so-tay-cho-bot-ai.md): Không có sổ tay, AI agent trả lời khách dè dặt, ca nào cũng chờ chủ shop. Mình thử viết skill như sổ tay cho bot và rút ra 4 cách viết để bot làm đúng.
- [Lỗ hổng PHP nghiêm trọng: chủ website nên nhắn hosting vá ngay](https://200lab.io/blog/lo-hong-php-thang-10-2026-chu-website-can-lam-gi.md): Hai lỗ hổng PHP nghiêm trọng ảnh hưởng nhiều website WordPress. Xem bạn có bị không, cần cập nhật PHP bản nào và tin nhắn mẫu gửi hosting.
- [Mọi bài viết chủ đề Agent](https://200lab.io/blog/tags/agent.md)

Toàn bộ nội dung: https://200lab.io/llms.txt
