Orchestration cho agent — playbook dựng guardrail trước khi scale

Orchestration cho agent — playbook dựng guardrail trước khi scale

Agent gắn 7 tool nghe oai, nhưng không có orchestration rõ ràng thì production sẽ dạy bạn bài học đắt. Playbook này giúp builder thiết lập lớp điều phối đúng từ đầu.

Tuần trước, một team 4 người ở Sài Gòn khoe mình trên group: "Agent research của tụi mình gắn được 7 tool, chạy sub-agent, có cả long-term memory." Hai ngày sau, cũng người đó hỏi: "Tại sao agent cứ gọi web search trong vòng lặp vô hạn rồi burn hết credit Groq?"

Câu trả lời ngắn: agent có nhiều khả năng không đồng nghĩa với agent chạy đúng. Thiếu orchestration — lớp điều phối quyết định ai làm gì, khi nào dừng, lỗi thì xử lý ra sao — thì mỗi tool thêm vào chỉ tăng thêm một chiều hỗn loạn.

Mục tiêu của playbook này

Giúp bạn dựng một agent workflow có kiểm soát, cụ thể là:

Nói thẳng ra: bạn đang xây một dàn nhạc, không phải tuyển thêm nhạc công. Thêm người mà không có nhạc trưởng thì chỉ ra tiếng ồn.

Checklist trước khi bắt tay

Trước khi code dòng đầu tiên, kiểm tra 5 điều:

| # | Câu hỏi | Nếu chưa có → |
|---|---------|----------------|
| 1 | Agent có bao nhiêu tool? Mỗi tool có mô tả rõ ràng không? | Viết docstring cho từng tool, dưới 2 câu |
| 2 | Có giới hạn số bước (max iterations) không? | Set cứng, ví dụ max 8 bước |
| 3 | Tool nào có side-effect (ghi file, gọi API trả phí)? | Đánh dấu riêng, thêm confirmation step |
| 4 | Sub-agent có scope cố định hay "làm gì cũng được"? | Mỗi sub-agent chỉ nhận 1-2 tool |
| 5 | Memory lưu gì, lưu ở đâu, ai được đọc? | Tách read/write permission rõ ràng |

Từng bước: dựng orchestration layer

Bước 1 — Chọn graph framework thay vì loop đơn

Thay vì dùng vòng while True để agent tự quyết bước tiếp theo, hãy dùng state graph. LangGraph là một lựa chọn phổ biến — bạn định nghĩa từng node (gọi model, gọi tool, delegate cho sub-agent) và các cạnh có điều kiện.

from langgraph.graph import StateGraph, END

graph = StateGraph(AgentState)
graph.add_node("reason", call_model)
graph.add_node("act", call_tool)
graph.add_node("delegate", call_sub_agent)

# Điều kiện chuyển tiếp — không để model tự quyết vô hạn
graph.add_conditional_edges("reason", route_decision)
graph.add_edge("act", "reason")
graph.add_edge("delegate", "reason")

Điểm khác biệt: mỗi lần agent muốn chuyển trạng thái, nó phải đi qua một hàm route_decision do bạn viết. Bạn kiểm soát luật chơi, không phải model.

Bước 2 — Gắn guardrail cho từng tool

Mỗi tool cần ba thứ: timeout, retry limit, và output validator.

@tool(max_retries=2, timeout=30)
def web_search(query: str) -> str:
    # Guardrail: chỉ trả max 3 kết quả, strip HTML
    results = duckduckgo_search(query, max_results=3)
    return sanitize(results)

Giả sử team bạn 3 người, dùng Groq inference endpoint miễn phí — mỗi phút chỉ được vài chục request. Nếu agent gọi search 20 lần trong một turn, bạn bị rate-limit ngay. Guardrail ở đây không phải "nice to have" mà là điều kiện để chạy được.

Bước 3 — Sub-agent nhận brief, không nhận quyền

Khi delegate cho sub-agent, hãy nghĩ như giao việc cho junior: brief rõ, scope hẹp, deadline cứng.

sub_agent_config = {
    "tools": ["web_search"],  # Chỉ 1 tool
    "max_steps": 3,           # Tối đa 3 bước
    "output_schema": {"type": "object", "properties": {"summary": {"type": "string"}}}
}

Sub-agent không được gọi tool ghi file, không được delegate tiếp cho agent khác. Nguyên tắc: mỗi tầng delegation giảm quyền, không tăng.

Bước 4 — Memory có policy, không phải dump mọi thứ

Long-term memory (bộ nhớ dài hạn — thông tin agent giữ lại qua nhiều phiên) nghe hấp dẫn, nhưng nếu không có policy thì memory nhanh chóng thành bãi rác.

Quy tắc đơn giản: chỉ lưu fact đã verifypreference của user. Không lưu intermediate reasoning, không lưu raw search results.

Bẫy mà builder hay bước vào

Bẫy 1: "Thêm tool cho oai"

Một anh lead ở Hà Nội kể: team gắn tool Python execution vào agent research, nghĩ "lỡ cần tính toán thì có sẵn." Kết quả? Agent bắt đầu viết script để parse HTML thay vì dùng tool fetch có sẵn — vì model thấy Python execution "linh hoạt hơn." Thêm tool không cần thiết = thêm đường để agent đi lạc.

Bẫy 2: "Agent đã chạy đúng 10 lần, chắc ổn"

Agent là hệ thống stochastic — cùng input, khác lần chạy có thể khác output. 10 lần thành công không chứng minh gì. Bạn cần test với input edge-case, input dài, input mơ hồ. Đừng nhầm demo thành production.

Bẫy 3: "Dùng model mạnh nhất thì orchestration đơn giản hơn"

Không. Model mạnh hơn chỉ giảm lỗi reasoning, không giảm lỗi hệ thống. Agent gọi API timeout, sub-agent trả format sai, memory bị corrupt — model giỏi mấy cũng không tự fix được những thứ đó. Orchestration layer phải handle failure ở tầng infra, không phải tầng ngôn ngữ.

Bước tiếp theo

Nếu bạn đang có một agent prototype chạy kiểu loop:

  1. Vẽ ra state graph trên giấy trước — mỗi node là gì, điều kiện chuyển là gì, đâu là điểm dừng.
  2. Thêm max_iterations ngay hôm nay. Con số cụ thể tùy use case, nhưng có còn hơn không.
  3. Mỗi tool side-effect (ghi file, gọi API trả phí) phải qua một bước confirm — dù chỉ là log rồi chờ 2 giây.

Agent workflow giống một bản phối: mỗi nhạc cụ hay riêng lẻ, nhưng không có bản tổng phổ thì khán giả chỉ nghe thấy hỗn độn. Orchestration chính là bản tổng phổ đó — và bạn là người viết nó, không phải model.

---

Bụi Wire — nghiện đọc release notes lúc 2 giờ sáng

Nguồn tham khảo