Tracing agent — playbook ngừng debug bằng linh cảm

Tracing agent — playbook ngừng debug bằng linh cảm

Agent system không đáng tin nếu bạn không trace được từng bước nó quyết định. Playbook thiết lập tracing từ zero trong một buổi chiều.

Phần lớn team đang vận hành agent system theo cách này: nhìn output cuối cùng, thấy sai, rồi đoán xem lỗi nằm ở đâu giữa 5-7 bước mà agent tự quyết định. Đó là cách một thám tử phá án mà không có hiện trường — chỉ có kết quả, không có bằng chứng.

Bài này là playbook cho builder muốn chuyển từ "đoán" sang "thấy". Một buổi chiều, từ zero đến có tracing hoạt động.

Mục tiêu: từ output đúng/sai sang biết tại sao đúng/sai

Khi agent chỉ gọi một LLM rồi trả kết quả, log request/response là đủ. Nhưng agent thật — loại gọi tool, rẽ nhánh, spawn sub-agent — tạo ra cây quyết định mà log phẳng không thể hiện được.

Tracing (theo dõi thực thi theo cấu trúc cây, ghi lại quan hệ cha-con giữa các bước) giải quyết đúng vấn đề này. Mỗi bước agent thực hiện trở thành một span — một đoạn có thời gian bắt đầu, kết thúc, input, output. Các span lồng vào nhau tạo thành trace tree.

Với trace tree, khi agent trả kết quả sai, bạn mở trace ra và thấy ngay: retrieval trả về document không liên quan ở bước 2, hay model bỏ qua context ở bước 4. Không cần đoán.

Checklist: 5 thứ cần có trước khi bắt tay

Test case cố định quan trọng hơn bạn nghĩ. Nếu vừa thêm tracing vừa đổi prompt, bạn sẽ không tách được đâu là thay đổi do code, đâu là behavior khác của model.

Bốn bước thiết lập

Bước 1 — Chọn backend

Ba lựa chọn open-source phổ biến:

| Tool | Điểm mạnh | Phù hợp khi |
|------|-----------|-------------|
| MLflow Tracing | Trace + evaluation trong cùng hệ sinh thái | Team đã quen MLflow hoặc cần eval pipeline |
| Langfuse | UI trực quan, self-host dễ dàng | Team muốn dashboard nhanh, ít config |
| Phoenix (Arize) | Nhẹ, focus LLM observability | Chỉ cần trace LLM call, không cần ML ops |

Giả sử team bạn 4 người, Python-based, chưa có tracing nào — MLflow ít ma sát nhất vì trace data luôn nằm local, không gửi đi đâu.

Bước 2 — Instrument ba điểm quyết định

Instrument (gắn code theo dõi vào các điểm quan trọng) không cần phủ toàn bộ. Ba điểm bắt buộc:

import mlflow

mlflow.set_tracking_uri("http://localhost:5000")
mlflow.set_experiment("agent-prod")

@mlflow.trace
def run_agent(query: str):
    # Điểm 1: mỗi lần gọi tool
    with mlflow.start_span(name="web_search") as span:
        results = search_tool(query)
        span.set_inputs({"query": query})
        span.set_outputs({"result_count": len(results)})

    # Điểm 2: mỗi lần gọi LLM
    with mlflow.start_span(name="llm_reasoning") as span:
        answer = llm_call(query, results)
        span.set_inputs({"context_tokens": count_tokens(results)})
        span.set_outputs({"answer": answer[:200]})

    # Điểm 3: guardrail check
    with mlflow.start_span(name="guardrail") as span:
        passed = validate_output(answer)
        span.set_attributes({"guardrail_passed": passed})
        if not passed:
            span.set_status("ERROR")
            return fallback()

    return answer

Guardrail (rào chắn kiểm tra output trước khi trả về user) được trace cùng luồng — khi nó trigger, trace tree hiện rõ span nào bị ERROR thay vì bạn phải grep log.

Bước 3 — Khởi động và chạy test case

# Terminal 1: tracking server
uvx mlflow server --port 5000

# Terminal 2: chạy agent với test case cố định
python run_agent.py --query "tổng hợp email tuần này"

Mở localhost:5000, vào tab Traces. Bạn sẽ thấy trace tree với timing từng span. Ví dụ cụ thể: nếu web_search mất 3 giây nhưng llm_reasoning chỉ mất 800ms — bottleneck nằm ở tool, không phải model.

Bước 4 — Gắn budget limit qua AI Gateway

Agent tự quyết định khi nào gọi LLM. Không có rào chắn, một retry loop có thể đốt hết quota trong vài phút. MLflow AI Gateway đặt giữa agent và LLM provider, cho phép set budget limit toàn cục — bất kể agent gọi bao nhiêu lần.

Ba cái bẫy team hay sập

Bẫy 1: Trace 40 span cho agent 3 bước

Một team ở Hà Nội từng instrument mọi hàm helper — kết quả là trace tree 4 tầng sâu, đọc mất 10 phút mỗi lần. Không ai đọc nữa. Bắt đầu với 3-5 span ở điểm quyết định, thêm dần khi thật sự cần.

Bẫy 2: Không ghi token count vào span

Agent chậm — nhưng chậm do LLM hay do tool? Nếu span không có token_countlatency riêng biệt, bạn lại quay về đoán mò. Giống có camera giám sát nhưng quên bật ghi hình — có mặt tại hiện trường mà không thu được manh mối nào.

Bẫy 3: Tắt tracing khi lên production

Nhiều team chỉ trace lúc dev. Nhưng production mới là nơi trace có giá trị nhất — vì input từ user thật đa dạng hơn test case gấp nhiều lần. Overhead của tracing rất nhỏ so với chi phí debug một incident không có dữ liệu. Giữ trace ở production, sample nếu cần (ví dụ trace 20% request), nhưng đừng tắt hoàn toàn.

Bước tiếp: từ trace sang evaluation tự động

Sau khi trace chạy ổn, nước đi tự nhiên tiếp theo:

  1. Xuất trace thành dataset — MLflow hỗ trợ sẵn việc này
  2. Viết evaluator đơn giản — output đúng format không? Có hallucination (bịa thông tin) không? Có bỏ sót context không?
  3. Chạy evaluation trên mỗi batch trace mới — thay vì đợi user báo bug

Đây là lúc hệ thống chuyển từ "chạy được" sang "đáng tin". Mỗi dấu vết trong trace được kiểm chứng tự động — orchestration (điều phối các bước) rõ ràng vì bạn thấy nó, guardrail rõ ràng vì bạn đo được nó.

Bản chất là: agent đáng tin không phải vì model giỏi, mà vì bạn biết chính xác khi nào nó không giỏi.

---

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

Nguồn tham khảo