Đêm 11/11 năm ngoái, tôi ngồi trước ba màn hình Grafana, mồ hôi lạnh chảy dọc sống lưng. Hệ thống CSKH AI của shop mỹ phẩm tôi vận hành đang phải gồng gánh 47.312 ticket trong vòng 6 tiếng. Stack cũ dùng Anthropic Claude gọi trực tiếp, vỡ vụn ở 4.200 RPM, latency P95 vọt lên 3,8 giây, khách hàng bắt đầu livestream chửi. Chính đêm đó tôi phải thiết kế lại toàn bộ: Agent Skills để phân tách năng lực, MCP (Model Context Protocol) để chuẩn hoá giao tiếp giữa tool và model, và một gateway trung gian để chuyển mạch giữa các nhà cung cấp. Bài viết này là phiên bản production-ready mà tôi đã chạy ổn định 8 tháng qua, giá trị đầu tư đã được kiểm chứng trên đồng tiền.
1. Vì sao Agent Skills phải đi đôi với MCP
Agent Skills là đơn vị năng lực độc lập (phân loại, tra cứu, gọi API nội bộ...) được đóng gói thành "kỹ năng" mà agent có thể kích hoạt theo ngữ cảnh. MCP chuẩn hoá cách các skill này được khai báo, xác thực và truyền tải qua JSON-RPC. Trước đây tôi viết function calling kiểu "tự chế", mỗi agent một format khác nhau, mỗi lần thêm tool phải sửa code cả backend lẫn frontend. Giờ mọi thứ là SKILL.md + mcp_servers: thêm năng lực mới chỉ cần drop file vào thư mục, agent tự dò tìm qua discovery.
- Tách năng lực khỏi lời gọi LLM: skill có thể thay thế, swap nhà cung cấp mà không phải viết lại prompt.
- Khám phá động (dynamic discovery): agent hỏi MCP server
tools/list, nhận schema ngay khi khởi động. - Giám sát tập trung: một gateway log hết lời gọi skill, dễ truy vết khi sự cố.
- Đa mô hình (model-agnostic): cùng một skill chạy được trên Claude, GPT-4.1, Gemini, DeepSeek.
Trong kiến trúc tôi triển khai, mọi request LLM đều chui qua gateway HolySheep AI (Đăng ký tại đây) với base_url=https://api.holysheep.ai/v1. Đây là điểm mấu chốt giúp tôi chuyển mạch nhà cung cấp không downtime, đồng thời tận dụng tỷ giá đồng ¥1=$1 (không phí chuyển đổi), hỗ trợ thanh toán WeChat/Alipay, độ trễ trung bình <50ms ở cổng Singapore và nhận tín dụng miễn phí ngay khi đăng ký để test workload thực tế.
2. So sánh chi phí: chuyển mạch model qua gateway tiết kiệm 97,2%
Bảng dưới là giá output trên mỗi triệu token (MTok) tại HolySheep, cập nhật 2026. Tôi dùng song song hai nhóm: Claude Sonnet 4.5 cho tác vụ phức tạp (escalation, đàm phán), DeepSeek V3.2 cho phân loại thô và FAQ.
| Mô hình | Giá / MTok (USD) | 10 triệu token / tháng | So với Claude trực tiếp |
|---|---|---|---|
| Claude Sonnet 4.5 (qua HolySheep) | $15,00 | $150,00 | tiết kiệm ~85% phí FX + billing |
| GPT-4.1 (qua HolySheep) | $8,00 | $80,00 | rẻ hơn 47% |
| Gemini 2.5 Flash (qua HolySheep) | $2,50 | $25,00 | rẻ hơn 83% |
| DeepSeek V3.2 (qua HolySheep) | $0,42 | $4,20 | rẻ hơn 97,2% |
Với hệ thống 47k ticket, tôi phân bổ: 30% ticket khó (đổi trả, khiếu nại) chạy Claude Sonnet 4.5, 70% còn lại chạy DeepSeek V3.2. Chi phí thực tế hàng tháng rơi vào khoảng $47,94 thay vì $150 nếu dùng toàn Claude — tiết kiệm $102,06/tháng (68%) chỉ riêng một shop. Nhân lên cho 5 shop thì đủ trả lương một kỹ sư mid.
3. Kiến trúc tổng quan
- Tầng 1 - Kênh khách hàng: Zalo OA, Shopee Chat, website widget → webhook đẩy về queue.
- Tầng 2 - Agent Orchestrator: đọc ticket, quyết định skill, gọi MCP server tương ứng.
- Tầng 3 - MCP Servers: 3 server độc lập (classify, lookup_order, refund) chạy
streamable-http. - Tầng 4 - Model Gateway (HolySheep): nhận request OpenAI/Anthropic compatible, route tới Claude/GPT/Gemini/DeepSeek.
- Tầng 5 - Observability: Loki + Prometheus đo latency, cost, success rate mỗi skill.
4. Triển khai code (đã chạy production)
4.1 MCP Server cho skill phân loại ticket
# server/classify_server.py
import os
import httpx
from fastmcp import FastMCP, Context
from anthropic import AsyncAnthropic
mcp = FastMCP("holysheep-classify")
QUAN TRỌNG: base_url PHẢI trỏ về gateway HolySheep
HOLYSHEEP_BASE = "https://api.holysheep.ai/v1"
HOLYSHEEP_KEY = os.environ["HOLYSHEEP_API_KEY"]
client = AsyncAnthropic(
api_key=HOLYSHEEP_KEY,
base_url=HOLYSHEEP_BASE,
timeout=httpx.Timeout(connect=2.0, read=8.0, write=2.0, pool=2.0),
)
@mcp.tool()
async def classify_ticket(text: str, ctx: Context) -> dict:
"""Phân loại ticket CSKH vào 4 nhóm, trả về JSON chuẩn."""
prompt = (
"Phân loại ticket sau vào đúng 1 nhóm: "
"[doi_tra, hoan_tien, tu_van, khac]. "
'Trả về JSON {{"nhom":"...","do_tin_cay":0.0-1.0}}.\n\n'
f"Ticket: {text}"
)
resp = await client.messages.create(
model="claude-sonnet-4-5",
max_tokens=200,
messages=[{"role": "user", "content": prompt}],
)
raw = resp.content[0].text
return {"raw": raw, "input_tokens": resp.usage.input_tokens,
"output_tokens": resp.usage.output_tokens}
if __name__ == "__main__":
# Chạy MCP qua streamable-http, host 0.0.0.0 cho docker
mcp.run(transport="streamable-http", host="0.0.0.0", port=8765)
4.2 Khai báo Agent Skill (SKILL.md) cho orchestrator
---
skills/customer_service_router/SKILL.md
name: customer_service_router
version: 1.4.2
description: Định tuyến ticket CSKH tới model phù hợp theo độ phức tạp
triggers:
- new_ticket
- ticket_escalated
mcp_servers:
- name: holysheep-classify
transport: streamable-http
url: http://classify:8765/mcp
routing_policy:
simple:
condition: "len(text) < 280"
model: deepseek-v3.2
max_tokens: 128
cost_per_mtok: 0.42
complex:
condition: "len(text) >= 280 OR sentiment == 'angry'"
model: claude-sonnet-4-5
max_tokens: 1024
cost_per_mtok: 15.00
fallback_chain:
- claude-sonnet-4-5
- gpt-4.1
- gemini-2.5-flash
- deepseek-v3.2
sla:
p95_latency_ms: 800
success_rate_min: 0.995
monthly_budget_usd: 60
---
4.3 Orchestrator với failover và đo cost theo từng lời gọi
# orchestrator.py
import os, asyncio, time
from dataclasses import dataclass
from typing import List
import httpx
HOLYSHEEP_BASE = "https://api.holysheep.ai/v1"
API_KEY = os.environ["HOLYSHEEP_API_KEY"]
PRICING_USD_PER_MTOK = { # 2026
"claude-sonnet-4-5": 15.00,
"gpt-4.1": 8.00,
"gemini-2.5-flash": 2.50,
"deepseek-v3.2": 0.42,
}
@dataclass
class ModelResult:
content: str
model: str
latency_ms: float
cost_usd: float
async def call_model(model: str, prompt: str, max_tokens: int = 512) -> ModelResult:
t0 = time.perf_counter()
async with httpx.AsyncClient(base_url=HOLYSHEEP_BASE, timeout=10.0) as c:
r = await c.post(
"/chat/completions",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"model": model,
"max_tokens": max_tokens,
"messages": [{"role": "user", "content": prompt}],
"temperature": 0.2,
},
)
r.raise_for_status()
data = r.json()
u = data["usage"]
cost = (u["prompt_tokens"] + u["completion_tokens"]) / 1_000_000 * PRICING_USD_PER_MTOK[model]
return ModelResult(
content=data["choices"][0]["message"]["content"],
model=model,
latency_ms=(time.perf_counter() - t0) * 1000,
cost_usd=cost,
)
async def route_ticket(text: str) -> ModelResult:
primary = "deepseek-v3.2" if len(text) < 280 else "claude-sonnet-4-5"
chain: List[str] = [primary, "claude-sonnet-4-5", "gpt-4.1", "gemini-2.5-flash"]
seen, last_err = set(), None
for model in chain:
if model in seen: continue
seen.add(model)
try:
return await call_model(model, f"Trả lời CSKH ngắn gọn: {text}")
except httpx.HTTPStatusError as e:
last_err = e
if e.response.status_code in (429, 529):
await asyncio.sleep(0.4)
continue
raise
raise RuntimeError(f"Mọi model đều lỗi: {last_err}")
if __name__ == "__main__":
res = asyncio.run(route_ticket("Đơn #A9123 giao 5 ngày chưa nhận được, shop hẹn 2 ngày mà chưa ship"))
print(f"[{res.model}]