Một tác nhân mã hóa AI chạy một script, thấy script thành công, rồi phát hiện bảng cơ sở dữ liệu production biến mất. Bài hậu sự cố viral trên Hacker News kết luận đúng: “AI không xóa cơ sở dữ liệu của bạn, mà là bạn.” Tác nhân chỉ làm theo định nghĩa công cụ, công cụ gọi endpoint thật, endpoint không có guardrails, và con người đã cấp quyền ghi cho một quy trình không biết dừng lại khi thấy DELETE FROM users. Một câu chuyện khác trên r/ClaudeAI mô tả tác nhân trong vòng lặp thanh toán tiêu tốn hàng trăm đô la token trước khi ai đó nhận ra. Khác bề mặt, cùng một lỗi gốc: API không được kiểm thử đủ kỹ cho tác nhân AI.
💡 Nếu bạn đang triển khai tác nhân tự động gọi API, hãy coi bài này như checklist triển khai. Bạn sẽ thiết lập mock endpoint cho phát triển, sandbox thao tác phá hủy, contract test cho schema công cụ, budget limit cho mỗi tác nhân và replay kịch bản lỗi trong CI. Ví dụ dùng Apidog vì công cụ này hỗ trợ OpenAPI, mock server và scenario test trong cùng một project.
Tóm tắt
Tác nhân AI thường gây sự cố production không phải vì mô hình “ngu”, mà vì API phía sau thiếu guardrails:
- Không có rate limit.
- Không có idempotency.
- Cho phép hot delete.
- Schema công cụ lệch khỏi OpenAPI.
- Không có sandbox cho thao tác ghi.
Cách xử lý thực tế:
- Contract-test định nghĩa công cụ của tác nhân với OpenAPI.
- Mock các endpoint phá hủy trong quá trình phát triển.
- Bắt buộc idempotency key và soft delete cho thao tác ghi.
- Đặt budget limit cho token, request, tiền và độ sâu gọi công cụ.
- Replay kịch bản lỗi trong CI.
Apidog giúp gom các bước này vào một workflow: import OpenAPI, tạo mock server, viết scenario test và chạy từ CI.
Vì sao lỗi tác nhân AI thường là lỗi API
Trước đây, “kiểm thử tác nhân AI” thường nghĩa là gửi prompt cho Claude/GPT rồi chấm điểm câu trả lời. Cách đó không còn đủ.
Tác nhân hiện nay gọi tool. Tool gọi API. API chạm vào database, payment processor, email service hoặc dịch vụ bên thứ ba. Vì vậy, một tool schema sai hoặc một endpoint thiếu rate limit có thể trở thành sự cố production.
Một số pattern lỗi phổ biến:
Prompt injection gọi nhầm endpoint
Người dùng upload PDF chứa hướng dẫn ẩn. Tác nhân đọc file, tin nội dung đó, rồi gọi:
POST /admin/users
Content-Type: application/json
{
"delete_all": true
}
Vấn đề không nên được giải quyết chỉ bằng prompt engineering. API phải kiểm tra quyền theo ngữ cảnh người dùng thật. Nếu session gốc không được phép truy cập /admin/users, tác nhân đại diện cho session đó cũng không được phép.
Tool schema lệch khỏi OpenAPI
OpenAPI nói amount là integer tính bằng cents:
{
"amount": {
"type": "integer",
"description": "Amount in cents"
}
}
Nhưng tool definition của tác nhân lại mô tả amount là float tính bằng dollars:
{
"amount": {
"type": "number",
"description": "Amount in dollars"
}
}
Kết quả: hoàn tiền 19 cents có thể thành 19 dollars. Mô hình không sai; nó dùng schema bạn đưa. Lỗi nằm ở contract bị lệch.
Retry loop không có rate limit
Tác nhân gọi email API, nhận lỗi timeout, rồi retry liên tục vì planner nghĩ bước đó chưa hoàn thành. Trong vài phút, bạn có thể có:
- Hàng nghìn email bị gửi.
- Chi phí tăng đột biến.
- Provider gắn cờ tài khoản.
- Người dùng bị spam.
API phải có rate limit và budget limit. Đừng để planner tự quyết định khi nào nên dừng.
Thiếu idempotency
Tác nhân gọi:
POST /payments
Request timeout. Tác nhân retry. Nếu lần đầu thực ra đã charge thành công, khách hàng bị tính phí hai lần.
Idempotency key giải quyết lỗi này ở lớp API. Tác nhân tạo một UUID cho một thao tác logic và dùng lại UUID đó khi retry.
Bốn guardrail bắt buộc cho tích hợp tác nhân-API
1. Contract test tool schema với OpenAPI
OpenAPI nên là nguồn sự thật cho API. Tool definition của tác nhân phải được kiểm tra tự động với OpenAPI trong CI.
Ví dụ Python tối thiểu:
import json
from jsonschema import Draft202012Validator
def validate_tool_against_openapi(tool_def: dict, openapi_spec: dict) -> list[str]:
"""Return mismatch errors. Empty list means pass."""
errors = []
op = openapi_spec["paths"][tool_def["path"]][tool_def["method"].lower()]
api_schema = op["requestBody"]["content"]["application/json"]["schema"]
tool_schema = tool_def["input_schema"]
api_props = set(api_schema.get("properties", {}).keys())
tool_props = set(tool_schema.get("properties", {}).keys())
for missing in api_props - tool_props:
if missing in api_schema.get("required", []):
errors.append(f"Tool missing required field: {missing}")
for extra in tool_props - api_props:
errors.append(f"Tool defines field not in API: {extra}")
for prop, api_def in api_schema.get("properties", {}).items():
if prop not in tool_schema.get("properties", {}):
continue
tool_def_prop = tool_schema["properties"][prop]
if api_def.get("type") != tool_def_prop.get("type"):
errors.append(
f"Type mismatch on {prop}: "
f"API={api_def.get('type')} tool={tool_def_prop.get('type')}"
)
return errors
Gợi ý tích hợp CI:
python scripts/validate_tools.py openapi.json tools/*.json
Nếu có mismatch, fail build. Đừng chỉ cảnh báo.
2. Mock và sandbox endpoint phá hủy
Mọi endpoint thay đổi trạng thái đều cần môi trường an toàn để tác nhân “tập chạy”:
POSTPUTPATCHDELETE
Pattern triển khai:
| Môi trường | Tác nhân được làm gì |
|---|---|
| Local/dev | Gọi mock server |
| Staging | Gọi sandbox database |
| Production | Chỉ gọi endpoint có guardrails và quyền phù hợp |
Apidog có thể tạo mock từ OpenAPI, bao gồm response theo schema. Trong quá trình phát triển, trỏ base URL của tác nhân về mock server thay vì production.
Ví dụ:
AGENT_API_BASE_URL=https://mock.apidog.com/m1/your-project-id/
Khi tác nhân gọi:
DELETE /users/{id}
mock server trả về response giả theo schema, còn database production không bị chạm.
Tham khảo thêm: phát triển theo hợp đồng trước.
3. Bắt buộc idempotency key và soft delete
Mọi write endpoint mà tác nhân có thể gọi nên yêu cầu header:
Idempotency-Key: <uuid>
Ví dụ middleware Express:
const idempotencyCache = new Map();
function idempotency(req, res, next) {
const key = req.headers["idempotency-key"];
if (!key) {
return res.status(400).json({
error: "Missing Idempotency-Key header"
});
}
if (idempotencyCache.has(key)) {
const cached = idempotencyCache.get(key);
return res.status(cached.status).json(cached.body);
}
const originalJson = res.json.bind(res);
res.json = function (body) {
idempotencyCache.set(key, {
status: res.statusCode,
body
});
setTimeout(() => {
idempotencyCache.delete(key);
}, 24 * 60 * 60 * 1000);
return originalJson(body);
};
next();
}
app.post("/payments", idempotency, createPayment);
Trong production, thay Map bằng Redis hoặc database có TTL.
Với delete endpoint, mặc định dùng soft delete:
UPDATE users
SET deleted_at = NOW()
WHERE id = $1;
Hard delete nên là endpoint riêng, yêu cầu phê duyệt của con người.
4. Budget limit cho mỗi tác nhân
Mỗi tác nhân cần budget rõ ràng:
- Token mỗi session.
- API call mỗi phút.
- Chi phí tối đa.
- Thời gian chạy tối đa.
- Độ sâu gọi tool.
Ví dụ policy ban đầu:
agent_budget:
max_tokens_per_session: 50000
max_api_calls_per_minute: 30
max_cost_cents_per_task: 500
max_tool_call_depth: 10
Khi vượt budget, API gateway nên trả về:
HTTP/1.1 429 Too Many Requests
Retry-After: 60
X-Budget-Exceeded: max_api_calls_per_minute
Content-Type: application/json
{
"error": "Budget exceeded",
"limit": "max_api_calls_per_minute"
}
Tác nhân phải dừng, log sự kiện và chuyển cho người xử lý.
Kiểm thử cuộc gọi API của tác nhân với Apidog
Dưới đây là workflow triển khai trong Apidog.
Bạn cần:
- OpenAPI spec cho API mà tác nhân gọi.
- Danh sách tool definition của tác nhân.
- Một môi trường test hoặc mock.
Bước 1: Import OpenAPI
Tạo project mới trong Apidog và import OpenAPI 3.x.
Apidog sẽ parse:
- Paths.
- Request body.
- Response schema.
- Examples.
- Authentication.
- Parameters.
Nếu API chưa có OpenAPI, hãy tạo spec trước. Tác nhân cần một hợp đồng rõ ràng để tool schema không bị viết tay tùy tiện.
Tham khảo: hướng dẫn design-first API workflow.
Bước 2: Tạo mock response cho endpoint ghi
Tìm tất cả endpoint thay đổi dữ liệu:
POST /payments
PATCH /users/{id}
DELETE /tickets/{id}
POST /notifications
Với mỗi endpoint:
- Mở endpoint trong Apidog.
- Thêm mock response.
- Dùng schema từ OpenAPI.
- Ghi đè dữ liệu để phân biệt rõ mock với production.
Ví dụ response mock:
{
"id": "mock_user_1970_001",
"email": "mock_user@example.test",
"deleted_at": "1970-01-01T00:00:00.000Z"
}
Sau đó khởi động mock server và trỏ tác nhân vào URL mock.
Tham khảo thêm: phát triển theo hợp đồng trước.
Bước 3: Viết scenario mô phỏng chuỗi gọi tool
Scenario test nên mô phỏng đúng chuỗi tác nhân sẽ gọi trong thực tế.
Ví dụ với tác nhân phân loại ticket:
-
POST /auth/tokenđể lấy bearer token. -
GET /tickets?status=openđể lấy ticket đầu tiên. -
POST /tickets/{id}/triagevới category do tác nhân chọn. -
POST /notificationsđể gửi thông báo. - Assert status code, schema và nội dung response.
Ví dụ assertion nên có:
status == 200
response.assignee != null
response.category in ["billing", "technical", "account"]
notification.message matches /ticket #[0-9]+/
Nếu schema ticket thay đổi hoặc tác nhân gửi category không hợp lệ, scenario fail trước khi chạm production.
Tham khảo: kiểm thử API cho kỹ sư QA.
Bước 4: Chạy scenario từ CI
Kết nối scenario test vào pipeline PR.
Ví dụ lệnh:
apidog run -t scenario-id --env test
Ví dụ GitHub Actions:
name: Agent API Tests
on:
pull_request:
paths:
- "openapi/**"
- "agents/**"
- "tools/**"
jobs:
test-agent-api:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Apidog scenario
run: apidog run -t scenario-id --env test
Mục tiêu: mọi thay đổi vào OpenAPI hoặc tool definition đều phải replay kịch bản trước khi merge.
Bước 5: So sánh hành vi giữa hai model
Khi đổi model, ví dụ từ model A sang model B, đừng chỉ so sánh câu trả lời. Hãy so sánh request body mà model tạo cho tool call.
Quy trình:
- Chạy cùng scenario với model A.
- Ghi trace tool call.
- Chạy lại với model B.
- Diff request body.
- Kiểm tra field bị thiếu, enum khác, format ngày khác hoặc thứ tự call thay đổi.
Ví dụ khác biệt cần bắt:
{
- "priority": "medium",
+ "priority": "urgent",
"category": "billing"
}
Đây là lỗi hành vi có thể không lộ ra nếu chỉ đọc output text.
Tham khảo: tích hợp API GPT-5.5.
Kỹ thuật nâng cao
Cố định temperature trong test
Khi kiểm thử tool call, đặt temperature về 0.
Bạn đang kiểm thử:
- Tool selection.
- Argument generation.
- API contract.
- Retry behavior.
Không phải khả năng sáng tạo của model.
Snapshot trace gọi tool
Mỗi test run nên lưu:
{
"tool": "update_user",
"method": "PATCH",
"path": "/users/123",
"body": {
"subscription_status": "active"
}
}
So sánh snapshot mới với baseline. Nếu tác nhân bắt đầu gọi /users hai lần thay vì một lần, CI nên báo trước khi hóa đơn hoặc dữ liệu production bị ảnh hưởng.
Không cấp credential production trực tiếp cho tác nhân
Tác nhân nên dùng service account có scope hẹp.
Không nên để production token trong:
.env
agent_config.json
prompt.md
Nếu cần gọi production, cho tác nhân đi qua proxy ký request bằng token sống ngắn.
Tách API key đọc và ghi
Phần lớn tác vụ của tác nhân là đọc. Hãy cấp read-only key theo mặc định.
Chỉ cấp write key khi:
- Có workflow phê duyệt.
- Endpoint có idempotency.
- Endpoint có budget/rate limit.
- Có audit log.
Dùng HTTP 423 cho endpoint cần người phê duyệt
Khi tác nhân gọi thao tác cần xác nhận, trả về:
HTTP/1.1 423 Locked
Content-Type: application/json
{
"error": "Human approval required",
"confirmation_url": "https://app.example.com/approvals/abc123"
}
423 Locked rõ hơn 403 Forbidden: tác nhân chưa được làm, không phải vĩnh viễn không được làm.
Fail build khi schema drift
Nếu tool schema không khớp OpenAPI, fail CI.
Đừng dùng warning cho lỗi có thể gây hoàn tiền sai, xóa nhầm dữ liệu hoặc gọi sai endpoint.
Nếu hệ thống của bạn gồm nhiều microservice, xem thêm các mẫu kiểm thử microservices.
Lỗi phổ biến cần tránh
- Hard-code mock URL vào prompt. Hãy dùng biến môi trường.
- Chỉ thêm idempotency cho payment nhưng bỏ qua email, CRM hoặc ticket update.
- Log toàn bộ request body trong production, làm rò rỉ PII.
- Cho tác nhân truy cập database trực tiếp thay vì qua API.
- Tin vào confidence score của model như một chỉ báo an toàn.
- Dùng production credential cho test run.
- Không replay scenario khi đổi model.
So sánh công cụ
| Phương pháp | Thời gian thiết lập | Điểm mạnh | Điểm yếu | Phù hợp nhất cho |
|---|---|---|---|---|
| Unit test tự viết | Thấp | Kiểm soát hoàn toàn, không phụ thuộc vendor | Bảo trì cao, dễ lệch khỏi API thật | Dự án nhỏ, đội một developer |
| LangSmith / LangGraph eval | Trung bình | Replay trace tốt, có metric theo model | Mạnh ở lớp tác nhân, nhẹ ở lớp API | Đội AI tập trung vào eval |
| Postman + Postbot | Trung bình | Giao diện quen thuộc, nhiều template | Mock server là tiện ích trả phí, scripting cũ | Đội đã dùng Postman lâu năm |
| Apidog scenario + mock | Trung bình | OpenAPI-native, mock server, CLI cho CI | Ít phổ biến hơn Postman | Đội muốn thiết kế, mock và test trong một project |
Nếu bạn đã dùng LangSmith tốt ở lớp prompt/model, vẫn nên thêm một lớp kiểm thử API riêng. Nếu bạn đang tìm lựa chọn thay thế Postman, xem Apidog là một sự thay thế mạnh mẽ.
Nhiều đội dùng kết hợp: LangSmith cho eval cấp prompt, Apidog cho contract test, mock server và scenario replay.
Use case thực tế
Tác nhân cập nhật database production
Một đội chăm sóc khách hàng xây tác nhân cập nhật field tài khoản từ ticket hỗ trợ.
Trước khi launch, họ:
- Bắt buộc idempotency key cho mọi write endpoint.
- Chạy 200 replay scenario trong Apidog trên sandbox database.
- Validate enum ở API layer.
Kết quả: test phát hiện tác nhân cố gắng đặt subscription_status thành chuỗi không nằm trong enum. Đội thêm schema validation và triển khai không sự cố.
Tác nhân gọi payment API
Một đội fintech xây tác nhân hoàn tiền tự động.
Guardrails:
- Tối đa 5 refund mỗi session.
- Tối đa 50 USD mỗi refund.
- Bắt buộc idempotency trên mỗi call.
- Chạy contract test suite với OpenAPI trên mỗi PR.
Sau sáu tháng, họ xử lý 12.000 refund mà không có charge trùng lặp.
Tác nhân phân loại GitHub issues
Một đội platform xây tác nhân triage issue lấy cảm hứng từ Clawsweeper.
Họ:
- Mock GitHub API trong Apidog.
- Chạy 50 scenario test.
- Bao phủ issue đã xóa, thiếu label, input sai format.
- Phát hiện ba lỗi trước launch.
Tác nhân hiện xử lý triage trên repository công khai có 5.000 issue mở.
Checklist triển khai
Trước khi cho tác nhân gọi API thật, hãy kiểm tra:
- [ ] OpenAPI là nguồn sự thật duy nhất.
- [ ] Tool schema được contract-test với OpenAPI.
- [ ] Mock server có response cho mọi write endpoint.
- [ ] Staging dùng sandbox database.
- [ ] Mọi write endpoint yêu cầu
Idempotency-Key. - [ ] Delete mặc định là soft delete.
- [ ] Hard delete yêu cầu phê duyệt người dùng.
- [ ] API gateway có rate limit và budget limit.
- [ ] CI replay scenario khi OpenAPI hoặc tool definition thay đổi.
- [ ] Trace tool call được snapshot và diff.
- [ ] Production credential không nằm trong prompt hoặc
.envcủa tác nhân. - [ ] Read key và write key được tách riêng.
Kết luận
Nếu chỉ nhớ một ý: tác nhân không phải vấn đề chính. API mới là nơi sự cố xảy ra hoặc bị chặn lại.
Năm việc nên làm ngay:
- Coi tool schema là contract.
- Mock endpoint phá hủy trong development.
- Bắt buộc idempotency key trên mọi write endpoint.
- Đặt budget limit cho mỗi tác nhân.
- Replay scenario trong CI cho mọi thay đổi API hoặc tool.
Các sự cố viral sẽ còn tiếp diễn. Đội phục hồi nhanh là đội đã có guardrails trước khi tác nhân chạm production. Tải xuống Apidog và bắt đầu bằng mock server. Để xem góc nhìn QA, đọc công cụ kiểm thử API cho kỹ sư QA. Để viết tool definition an toàn hơn cho tác nhân, xem cách viết tệp AGENTS.md.
Câu hỏi thường gặp
Làm cách nào kiểm thử API call của tác nhân AI mà không tốn token?
Chạy tác nhân trên mock server trong development. Mock URL của Apidog trả về response theo schema mà không gọi API thật. Cố định temperature về 0 và dùng bộ prompt test nhỏ. Xem thêm checklist kiểm thử của kỹ sư QA.
Khác biệt giữa kiểm thử tác nhân và kiểm thử API là gì?
Kiểm thử tác nhân kiểm tra model có chọn đúng tool và điền argument đúng không. Kiểm thử API kiểm tra endpoint có xử lý request đúng không. Bạn cần cả hai lớp: tác nhân đúng gọi API lỗi vẫn gây lỗi; API đúng nhưng tác nhân gọi sai cũng gây lỗi.
Tôi có cần idempotency key trên mọi endpoint không?
Có, trên mọi write endpoint. Read endpoint vốn idempotent. Write endpoint thì không, và tác nhân sẽ retry khi gặp timeout hoặc lỗi 5xx.
Làm sao ngăn prompt injection kích hoạt API call nguy hiểm?
Đừng chỉ dựa vào prompt. API phải enforce authorization theo user context gốc. Nếu người dùng không có quyền gọi /admin/delete-all-users, tác nhân đại diện người dùng đó cũng không được gọi.
Có thể dùng Apidog trực tiếp với Claude hoặc GPT không?
Bạn có thể trỏ base URL trong tool configuration sang mock URL của Apidog khi test. Khi chuyển sang staging hoặc production, đổi biến môi trường base URL.
Budget limit phù hợp cho một tác nhân là bao nhiêu?
Bắt đầu chặt, rồi nới theo dữ liệu. Một cấu hình khởi điểm hợp lý:
- 50.000 token mỗi session.
- 30 API call mỗi phút.
- 5 USD mỗi task.
- 10 tool call lồng nhau.
Theo dõi trong hai tuần, rồi điều chỉnh.
Làm sao phát hiện schema drift giữa tool của tác nhân và API?
Chạy schema diff trong CI trên mọi PR. So sánh JSON schema trong tool definition với request body schema trong OpenAPI cho cùng endpoint. Nếu khác biệt, fail build. Đoạn Python ở phần guardrails có thể dùng làm điểm bắt đầu.
Top comments (0)