00 · Lộ trình AI agent mức senior — đọc gì, theo thứ tự nào, trả lời phỏng vấn ra sao

Series 9 bài này dành cho Senior Backend / Tech Lead ở công ty sản phẩm muốn đưa tính năng AI vào sản phẩm (stack Laravel + PostgreSQL) và dùng coding agent trong team. Mỗi bài trả lời đủ 10 mục: bài toán gốc, mô hình tư duy, internals, đảm bảo/giới hạn, failure modes (có lab), vận hành, so sánh, góc nhìn tech lead, anti-pattern, câu hỏi phụ. Trang này là bản đồ: đọc theo thứ tự nào, lab chạy ra sao, và một bài system design tổng hợp để luyện trả lời phỏng vấn.

Trang điều hướng — không phải bài về một công nghệ, nên không theo khung 10 mục. Nếu chưa từng gọi API LLM hay chưa biết agent loop là gì, đọc trước AI và AI agent từ số 0.

Bản đồ series

flowchart TB
  B0["Nền: AI agent từ số 0"] --> B1["01 LLM internals: token, KV cache, sampling"]
  B1 --> B2["02 Tool use và agent loop: giao thức, idempotency"]
  B1 --> B3["03 Context engineering: cache, context rot, compaction"]
  B2 --> B5["05 Workflow và multi-agent"]
  B3 --> B4["04 RAG với pgvector"]
  B2 --> B6["06 MCP chuyên sâu"]
  B2 --> B8["08 Bảo mật agent"]
  B6 --> B8
  B4 --> B7["07 Eval và observability"]
  B5 --> B7
  B7 --> B9["09 Vận hành production"]
  B8 --> B9
  B3 --> B9
BàiCâu hỏi cốt lõi bài trả lờiLab nổi bật (chạy thật)
01 · LLM dưới nắp capoVì sao output đắt hơn input, vì sao temperature 0 không tất định, vì sao tiếng Việt đắtTiếng Việt có dấu 40 token vs tiếng Anh 12; float cộng khác thứ tự ra khác; KV cache nhanh ~7×
02 · Tool use và agent loopAgent là gì ở mức giao thức; làm sao không hoàn tiền hai lầnCrash sau side effect: khoá theo tool_use_id vẫn hoàn 2 lần khi retry từ đầu; khoá nghiệp vụ thì 1
03 · Context engineeringQuản lý context và prompt cache thế nàoGiờ hiện tại trong system prompt → chỉ 2% dùng lại cache; dọn context mỗi lượt tăng chi phí 1,7×
04 · RAG với pgvectorRAG hỏng ở đâu, pgvector đủ tới đâuRecall 0,81 ở ef_search mặc định; WHERE tenant 1% trả 0–2/10 dòng; build thiếu RAM chậm 8×
05 · Workflow và multi-agentKhi nào tách agent, trả giá bao nhiêu20 bước × 95% = 36%; fan-out 10 worker p50 4 s → 9,8 s; 20 worker → 43% bị 429
06 · MCP chuyên sâuGiao thức trên dây, spec 2026-07-28, rủi roJSON-RPC thô; stateless server/discover; mô tả tool độc đi nguyên văn vào context
07 · Eval và observabilityLàm sao biết thay đổi là tốt hơnEval 50 câu chọn sai prompt 34% số lần; trace theo OTel GenAI
08 · Bảo mật agentPrompt injection, bộ ba chết ngườiCommonMark vẫn render ảnh rò dữ liệu; IDOR qua tool; SSRF với IP viết lạ; cổng taint
09 · Vận hành productionRetry, timeout, capacity, chi phíTimeout của SDK PHP không được áp; retry-after 12 s khoá worker; 1 lời gọi = 3 request

Kế hoạch học 4 tuần

TuầnĐọcLàm tayTự kiểm: nói được trong 2 phút
101, 02Chạy lab tokenizer, sampling; chạy run_agent_loop_lab.sh, tự thêm một tool và một kịch bản crashAgent loop ở mức giao thức; vì sao exactly-once không có; prefill vs decode
203, 04Sửa cache_prefix.php thêm một "silent invalidator" của riêng bạn; chạy pgvector_lab.py, thử m/ef_construction khácPrompt cache là prefix match; bẫy WHERE + HNSW và 3 cách xử lý
305, 06, 08Chạy raw_client.py, đọc từng message; thêm một tool ghi vào ToolGate và phân loại nóKhi nào KHÔNG dùng multi-agent; bộ ba chết người; MCP 2026-07-28 đổi gì
407, 09Chạy run_retry_lab.sh; viết một bộ eval 30 câu cho một tính năng thật ở công ty cũThiết kế trọn bài system design ở mục dưới trong 30 phút

Bài system design tổng hợp: agent CSKH cho shop Laravel

Đề (hay gặp ở vòng tech lead): "Shop thương mại điện tử 50 000 đơn/ngày, stack Laravel + PostgreSQL + Redis. Thiết kế trợ lý CSKH trả lời tình trạng đơn, chính sách đổi trả, và xử lý yêu cầu hoàn tiền nhỏ." Số liệu dưới đây là ví dụ minh hoạ để luyện cách lập luận.

1. Làm rõ yêu cầu (đừng nhảy vào kiến trúc)

2. Chọn mức: workflow trước, agent chỗ cần

Router (một lần gọi model rẻ hoặc structured outputs) phân loại ý định: hỏi đơn / hỏi chính sách / hoàn-đổi / khác. Hỏi đơn là workflow (tool tra đơn + trả lời). Hỏi chính sách là RAG. Hoàn-đổi cần nhiều bước có điều kiện → agent với tool hẹp. Không multi-agent: luồng phụ thuộc chặt, không song song hoá được (bài 05).

3. Kiến trúc

flowchart LR
  W["Web chat"] -->|"POST, nhận run_id"| API["Laravel (FPM)"]
  API --> Q[("Queue llm")]
  Q --> WK["Worker: LlmGateway + agent loop"]
  WK -->|"stream"| RV["Reverb / SSE"] --> W
  WK --> CL["Claude API (Opus/Sonnet theo route)"]
  WK --> T1["Tool get_order (authz theo session)"]
  WK --> T2["Tool search_policy (pgvector + FTS)"]
  WK --> T3["Tool refund (idempotency key nghiệp vụ, ngưỡng, duyệt)"]
  T1 --> PG[("PostgreSQL")]
  T2 --> PG
  T3 --> PAY["Cổng thanh toán (idempotency key)"]
  WK --> TR[("agent_runs: checkpoint, usage, trace")]
  WK --> H["Chuyển nhân viên"]

4. Quyết định then chốt và lý do

Quyết địnhLý doBài
Chạy trong queue, stream qua Reverb3 lượt/s × ~10 s = 30 đồng thời (Little's law), không giữ FPM; TTFT thấp09
Guzzle timeout tường minh, maxRetries theo route, một tầng retryTimeout của SDK không tự áp; tránh retry nhân chồng09
System prompt + tool cố định, sắp theo tên; dữ liệu động ở cuốiPrompt cache — đòn bẩy chi phí lớn nhất03
Tool nhận order_id nhưng user lấy từ sessionChống IDOR qua agent08
Refund: khoá refund:{order_id}:{request_id}, truyền xuống cổng thanh toán, checkpoint trước khi chạy toolAt-least-once + idempotent; lab cho thấy khoá theo tool_use_id không đủ02
Trên ngưỡng hoặc phiên đã đọc nội dung khách viết (ghi chú đơn, ảnh) → duyệtCắt bộ ba chết người, hành động không đảo ngược08
Chính sách qua RAG pgvector + FTS unaccent, trích dẫn nguồn, cho phép "không có thông tin"Không để model "nhớ" chính sách (Air Canada); khách gõ không dấu04
Render trả lời qua sanitizer allowlist ảnh + CSPChặn rò dữ liệu qua ảnh markdown08
max_iter 8, ngân sách token/hội thoại, phát hiện lặpChặn đuôi chi phí02, 09
Eval 200 ca (outcome grader kiểm bảng refunds) chạy trong CI; review 30 transcript/tuầnĐổi prompt/model có số liệu07
Trace OTel GenAI, dashboard chi phí/hội thoại, cache hit ratio, % chuyển ngườiPhát hiện "chi phí tăng im lặng"07, 09

5. Ước lượng chi phí (minh hoạ)

Giả định: mỗi hội thoại 4 lượt; tiền tố system + tool 6k token dùng chung mọi người (cache luôn ấm); mỗi lượt thêm ~1,5k token input mới (câu hỏi + tool result) và 300 token output. Trên Sonnet 5.5 ($2 input, $10 output, đọc cache $0,20, ghi cache 1,25× = $2,50 / 1M token):

→ ~$0,036/hội thoại (≈ 950đ ở tỉ giá ~26 000đ/USD); 5 000 hội thoại/ngày ≈ $180/ngày. Router đẩy câu hỏi đơn giản sang Haiku và rút gọn tool result sẽ kéo xuống. Con số thật phải đo từ usage.

6. Rủi ro và phương án

Checklist "nói được" trước buổi phỏng vấn

Chạy lab

Toàn bộ lab nằm trong labs/ai/ của repo; output gốc đã chạy nằm trong labs/ai/out/. Không cần API key: agent loop dùng mock server (mock_anthropic.py) nói đúng giao thức Messages API, nên SDK chính thức chạy thật nhưng "model" là kịch bản cố định.

# Python (tokenizer, sampling, KV cache, chi phí, pgvector, multi-agent, eval, OTel, MCP)
python3 -m venv .venv && . .venv/bin/activate
pip install numpy tokenizers anthropic mcp opentelemetry-sdk "psycopg[binary]"

# PHP (agent loop, retry/timeout, streaming, prompt cache, bảo mật)
cd labs/ai/php && composer install && cd ..

# Mock server
./mockctl.sh start cskh            # policy: cskh | parallel | echo
./mockctl.sh stop

# PostgreSQL + pgvector tạm (xem phụ lục bài 04)
Thư mục / fileBàiNội dung
py/tokenizer_vi_en.py, py/sampling.py, py/kv_cache.py01Token tiếng Việt, sampling, float, KV cache
php/agent_loop.php, php/run_agent_loop_lab.sh02Vòng lặp, max_iter, crash/resume, idempotency
php/cache_prefix.php, py/context_cost.py03Silent invalidator, mô hình chi phí
py/pgvector_lab.py, sql/hybrid_search_vi.sql04HNSW, lọc, FTS tiếng Việt, RRF
py/multiagent_sim.py05Lỗi cộng dồn, fan-out, rate limit
mcp/shop_server.py, mcp/raw_client.py, mcp/http_probe.sh06JSON-RPC thô, 2026-07-28, tool poisoning
py/eval_stats.py, py/otel_agent_trace.py07Thống kê eval, trace GenAI
php/security_lab.php08Ảnh markdown, IDOR, SSRF, taint
php/retry_timeout.php, php/run_retry_lab.sh, php/stream_ttft.php09Retry, timeout, TTFT

Giới hạn của series (đọc trước khi trích dẫn số liệu)

Bắt đầu: 01 · LLM dưới nắp capo.