Agent đáng tin bắt đầu từ điểm dừng
Một playbook cho builder: thiết kế agent production bằng event, guardrail và quyền dừng, thay vì chỉ nối thêm tool rồi cầu may.
Bụi Wire“Chị ơi, agent của em chạy được rồi, nhưng demo xong ai cũng sợ bấm nút deploy.”
Đó là tin nhắn của Minh, tech lead một team SaaS nội bộ ở Sài Gòn. Team Minh có một agent xử lý yêu cầu khách hàng: đọc ticket, tra dữ liệu, đề xuất thao tác, đôi khi gọi API để cập nhật trạng thái đơn hàng. Demo thì mượt. Chat trả lời tự tin. Tool calling cũng ổn. Nhưng đến lúc hỏi: “Nếu nó chuẩn bị refund nhầm thì ai chặn?”, cả phòng im như đứng trên miệng núi lửa.
Vấn đề không nằm ở model có thông minh không. Vết đứt gãy nằm ở chỗ khác: agent production cần biết khi nào hiển thị, khi nào chờ, khi nào hỏi người, và khi nào tuyệt đối không được tự làm tiếp.
Đây là playbook mình muốn Minh dùng lại. Không phải để chạy theo protocol mới nhất, mà để đổi cách nghĩ: agent không đáng tin vì nó trả lời hay; agent đáng tin khi orchestration và guardrail được thiết kế thành luồng vận hành rõ ràng.

Sơ đồ tóm tắt ý chính của bài viết.
Mục tiêu: đừng build chatbot, build mặt điều khiển
Nhiều team bắt đầu bằng câu: “Cho agent chat với user trước đã.” Nghe hợp lý, nhưng dễ kéo cả hệ thống vào một cái hố: mọi thứ bị nén thành text.
Trong production, user không chỉ cần câu trả lời. Họ cần:
- thấy agent đang làm bước nào;
- kiểm tra dữ liệu agent dùng;
- duyệt trước hành động rủi ro;
- sửa input giữa chừng;
- xem bằng chứng sau khi agent hoàn tất.
AG-UI, viết đầy đủ là Agent-User Interaction Protocol, giải quyết đúng lớp giao tiếp này: backend agent gửi các event động cho frontend, để UI có thể render chart, cập nhật shared state, hoặc tạm dừng chờ human approval. Trong bối cảnh Amazon Bedrock AgentCore, AG-UI được đặt cạnh các protocol khác: MCP nối agent với tool, A2A nối agent với agent, còn AG-UI nối agent với user.
Nói thẳng ra thì: MCP là đường agent gọi đồ nghề; AG-UI là bảng điều khiển để người vận hành thấy và can thiệp đúng lúc.
Với team Minh, mục tiêu không phải “agent trả lời xong ticket”. Mục tiêu đúng hơn là: mỗi hành động có rủi ro phải có trạng thái quan sát được, điều kiện dừng, và bằng chứng để review.
Checklist trước khi nối frontend vào agent
Trước khi chọn React, Vue, Angular, AgentCore hay tự host, team nên trả lời 6 câu này. Nếu chưa trả lời được, khoan vẽ UI đẹp.
1. Agent có bao nhiêu loại event?
Tối thiểu nên có:
thinking: agent đang phân tích;tool_started: bắt đầu gọi tool;tool_result: kết quả tool trả về;state_update: thay đổi shared state;approval_required: cần người duyệt;final: kết quả cuối;error: lỗi có phân loại.
2. Hành động nào cần human-in-the-loop?
Human-in-the-loop nghĩa là con người được đặt vào luồng quyết định, không chỉ xem log sau khi chuyện đã rồi.
Ví dụ cụ thể: agent được phép đọc lịch sử đơn hàng và đề xuất refund, nhưng nếu số tiền vượt ngưỡng nội bộ hoặc khách thuộc nhóm nhạy cảm, nó phải phát event approval_required.
3. Shared state nằm ở đâu?
Shared state là trạng thái chung giữa agent và UI: form đang điền, chart đang xem, ticket đang xử lý. Nếu state chỉ nằm trong prompt, frontend rất khó phục hồi khi refresh, timeout, hoặc user chuyển tab.
4. Ai xác thực request?
AgentCore Runtime có thể đứng làm proxy, xử lý authentication như SigV4 hoặc OAuth 2.0 qua Cognito, session isolation, scaling và observability. Nếu bạn không dùng AgentCore, vẫn cần câu trả lời tương đương: ai cấp quyền, ai tách session, ai ghi log?
5. Demo có bằng chứng tự động không?
Ở đây nguồn từ Simon Willison rất đáng học: để coding agent tự tạo video demo bằng shot-scraper video dựa trên storyboard YAML. Ý hay không nằm ở video cho vui, mà ở việc agent phải chứng minh thao tác của nó trên giao diện thật.
6. Có reviewer “chỉ đọc” cho việc quan trọng không?
Mô hình worker + advisor từ Fireworks gợi ý một pattern đáng dùng: worker làm việc chính, advisor chỉ review, không có quyền sửa file hay gọi tool. Với agent production, vai trò “chỉ đọc nhưng được quyền chặn” đôi khi an toàn hơn một agent toàn năng.
Playbook một buổi: dựng luồng event trước, UI sau
Nếu là team Minh, mình sẽ không bắt đầu bằng “chọn framework agent nào”. Mình sẽ bắt đầu bằng một lát cắt nhỏ đủ thật.
Bước 1: chọn một use case có rủi ro vừa phải
Đừng chọn “agent vận hành toàn bộ CSKH”. Chọn một luồng hẹp:
Agent đọc ticket, tra đơn hàng, đề xuất phản hồi, và nếu cần refund thì tạo yêu cầu chờ duyệt.
Kết quả mong muốn trong buổi đầu không phải agent thông minh hơn. Kết quả là bạn nhìn thấy rõ các điểm dừng.
Bước 2: định nghĩa event contract
Tạo một file nhỏ, ví dụ agent-events.ts:
type AgentEvent =
| { type: "thinking"; message: string }
| { type: "tool_started"; tool: string; inputSummary: string }
| { type: "tool_result"; tool: string; outputSummary: string }
| { type: "state_update"; key: string; value: unknown }
| { type: "approval_required"; action: string; risk: "low" | "medium" | "high"; payload: unknown }
| { type: "final"; answer: string }
| { type: "error"; code: string; recoverable: boolean; message: string };
Đừng xem đây là chi tiết frontend. Đây là lớp trầm tích của hệ thống: về sau mọi UI, log, test, review đều dựa lên nó.
Bước 3: gắn guardrail vào orchestration
Orchestration là cách điều phối nhiều bước, nhiều tool, nhiều quyết định. Guardrail là rào kiểm soát để agent không vượt quyền.
Pseudo-flow:
receive ticket
→ classify intent
→ retrieve order data
→ draft response
→ if refund_needed:
calculate risk
if risk != low:
emit approval_required
wait for human decision
else:
create refund request
→ emit final
Điểm quan trọng: approval_required không phải popup trang trí. Nó là trạng thái chính thức trong workflow. Backend phải biết dừng. Frontend chỉ là nơi hiện cái dừng đó ra.
Bước 4: tạo proof-of-work cho agent
Mượn tinh thần từ shot-scraper video: bắt agent hoặc pipeline tạo bằng chứng sau mỗi thay đổi quan trọng.
Ví dụ storyboard tối giản:
steps:
- visit: http://localhost:3000/tickets/123
- click: "Run agent"
- wait_for_text: "Approval required"
- click: "Approve refund request"
- wait_for_text: "Final response ready"
Bạn không nhất thiết phải dùng đúng tool này. Ý chính là: agent làm gì trên UI thì phải có dấu vết kiểm chứng được, không chỉ log dài như dung nham tràn qua terminal.
Bước 5: thêm reviewer chỉ đọc cho bước nhạy cảm
Với các hành động như refund, đổi quyền user, gửi email hàng loạt, hãy thử pattern:
- worker agent phân tích và đề xuất;
- reviewer model đọc transcript, diff state, payload hành động;
- reviewer trả về
pass,warn, hoặcblockkèm checklist; - worker không được tự bỏ qua kết quả
block.
Điểm này khác với multi-agent cho vui. Reviewer không cần “có tay”. Nó chỉ cần mắt tốt và quyền kéo phanh.
Hai bẫy làm agent UI trông xịn nhưng vận hành yếu
Bẫy 1: render mọi thứ từ model output
Generative UI rất hấp dẫn: agent có thể render chart, form, canvas ngay trong hội thoại. Nhưng nếu mọi component đều sinh từ text model trả về, bạn sẽ khó kiểm soát permission, validation và audit.
Cách an toàn hơn: model phát intent hoặc event có schema; frontend map sang component đã được kiểm soát.
Ví dụ:
{
"type": "state_update",
"key": "refund_preview",
"value": {
"orderId": "A123",
"amount": "pending_server_calculation",
"requiresApproval": true
}
}
Đừng để model tự quyết số tiền cuối nếu số tiền đó phải đến từ backend nghiệp vụ.
Bẫy 2: xem approval như nút “OK cho có”
Nếu người duyệt chỉ thấy “Agent muốn refund, đồng ý không?”, đó không phải human-in-the-loop. Đó là nhờ người ký giấy trong bóng tối.
Một approval tốt cần có:
- agent định làm gì;
- dữ liệu nào dẫn tới quyết định;
- tool nào sẽ được gọi;
- hậu quả có thể đảo ngược không;
- nút reject kèm lý do;
- log ai duyệt, lúc nào.
Chấn tâm của lỗi production thường không nằm ở câu trả lời sai đầu tiên. Nó nằm ở hành động sai được hệ thống cho đi qua quá dễ.
Minh đã đổi thiết kế thế nào?
Sau một buổi, team Minh bỏ plan “chat-first”. Họ giữ chat, nhưng biến nó thành một phần của control surface.
Luồng mới có ba vùng:
- Conversation: user trao đổi với agent.
- Work panel: hiển thị event, tool call, dữ liệu đang dùng.
- Decision tray: nơi các hành động cần duyệt xuất hiện, có payload và lý do.
Backend không trả một cục text cuối cùng nữa. Nó stream event có schema. Frontend không đoán ý model. Nó render theo contract. Reviewer model chỉ đọc các bước nhạy cảm. Demo tự động ghi lại đường đi quan trọng để team review trước khi merge.
Đây không phải kiến trúc hoành tráng. Nó chỉ làm rõ một quyết định: agent không được phép biến mọi thứ thành hội thoại rồi tự trôi tiếp.
Sau bài này, bạn nên nghĩ khác điều gì?
Nếu bạn đang build agent production, đừng hỏi đầu tiên: “Model nào mạnh nhất?” Hỏi câu này trước:
“Trong luồng này, điểm nào agent phải dừng lại để hệ thống, UI hoặc con người kiểm tra?”
Từ câu hỏi đó mới chọn protocol, runtime, framework, reviewer, và demo automation. AG-UI đáng chú ý vì nó đưa phần tương tác agent-user ra khỏi mớ text tự phát. AgentCore đáng chú ý vì nó đặt runtime, auth, session isolation và observability vào cùng một mặt phẳng vận hành. Nhưng quyết định quan trọng vẫn thuộc về bạn: thiết kế điểm dừng trước khi thiết kế màn pháo hoa.
Agent hay không phải agent nói được bao nhiêu, mà là nó biết im đúng lúc — núi lửa đẹp nhất vẫn là núi lửa không phun ngay dưới phòng server.
---
Bụi Wire — nghiện đọc release notes lúc 2 giờ sáng
Nguồn tham khảo
- Build generative UI for AI agents on Amazon Bedrock AgentCore with the AG-UI protocol | Artificial Intelligence
- Have your agent record video demos of its work with shot-scraper video
- How to Build an AI Agent That Runs its Own LLM Experiments with autoresearch
- Frontier AI at a fraction of the cost: open-source worker agents with a closed-source advisor.