Series 5 - Bài 1: Observability cho Agent
Monitoring service thông thường đo latency và error rate. Agent cần biết tại sao LLM quyết định gì. Đây là sự khác biệt căn bản trong observability design.
Nghe bài viết này dưới dạng podcastKhi service của bạn fail, bạn nhìn vào logs và thấy exception. Bạn biết cái gì fail.
Khi agent của bạn cho ra kết quả sai, logs thông thường không giúp được nhiều. Bạn thấy tool được gọi, thấy kết quả trả về — nhưng không biết tại sao LLM quyết định gọi tool đó, không biết tại sao nó bỏ qua context quan trọng, không biết tại sao nó chọn approach này thay vì approach kia.
Đây là sự khác biệt căn bản: service observability đo what happened, agent observability đo why it happened.
Tại sao standard metrics không đủ
Traditional service metrics:
Latency: P50: 120ms, P99: 450ms
Error rate: 0.1%
Throughput: 1,200 req/s
CPU: 45%
→ Bạn biết system có healthy không
→ Nhưng không biết agent có làm đúng không
Agent-specific questions:
Tại sao agent gọi read_file 3 lần cho cùng 1 file?
Tại sao agent ignore constraint "không thêm deps"?
Tại sao task này tốn 15 turns thay vì 5?
Tại sao agent chọn approach A thay vì B?
Token nào trong context đang drive decisions?
→ Không thể trả lời bằng latency/error rate
→ Cần reasoning trace
Reasoning Trace: Core của Agent Observability
Mọi LLM call cần được captured như một span đầy đủ:
Reasoning Span:
{
span_id: "span_abc123",
timestamp: "2025-05-25T10:30:15Z",
type: "llm_call",
input: {
messages_count: 12,
total_tokens: 8,450,
// snapshot của messages[] — không full content
// mà là summary để giảm storage
context_summary: {
system_prompt_tokens: 1200,
history_turns: 8,
tool_results_count: 4,
current_message_preview: "Fix the loan validation..."
}
},
output: {
stop_reason: "tool_use",
output_tokens: 145,
decision: {
type: "tool_use",
tool: "read_file",
rationale_preview: "Need to see current implementation..."
// Nếu LLM có thinking/reasoning field
}
},
metrics: {
latency_ms: 1240,
input_tokens: 8450,
output_tokens: 145,
cost_usd: 0.0127
}
}
Tool Execution Spans
Mỗi tool call là một span riêng:
Tool Span:
{
span_id: "span_def456",
parent_span_id: "span_abc123", // linked to LLM call
type: "tool_execution",
tool: "read_file",
input: { path: "src/loan.service.ts" },
output: {
success: true,
result_size_bytes: 8240,
result_lines: 287
// Không log full content — privacy và storage
},
metrics: {
latency_ms: 45,
file_size_bytes: 8240
}
}
Trace Tree: Visualize agent reasoning
Một agent session nhìn như trace tree:
[Session: fix-loan-validation]
├── [Turn 1]
│ ├── LLM Call (8,450 tokens → tool_use)
│ │ └── Tool: read_file(loan.service.ts) → 45ms
│ └── LLM Call (12,100 tokens → tool_use)
│ └── Tool: read_file(loan.spec.ts) → 38ms
│
├── [Turn 2]
│ ├── LLM Call (18,500 tokens → tool_use)
│ │ └── Tool: write_file(loan.service.ts) → confirmed → 52ms
│ └── LLM Call (22,000 tokens → tool_use)
│ └── Tool: run_command(npm test) → 2300ms
│
└── [Turn 3]
└── LLM Call (25,400 tokens → end_turn)
└── Response: "Completed refactor..."
Metrics:
Total turns: 3
Total LLM calls: 5
Total tool calls: 4
Total tokens: 86,450
Total cost: $0.13
Total duration: 8.2s
Với trace tree, bạn thấy ngay: 5 LLM calls cho 3 turns, 2 read_file trước khi write — hợp lý. Nếu có 20 LLM calls mà chỉ 1 write, đó là signal có gì bất thường.
Metrics đặc thù cho Agent
Agent-specific metrics cần track:
Efficiency metrics:
turns_per_task → agent có direct hay looping?
tool_calls_per_turn → có gọi tools không cần thiết?
tokens_per_task → cost indicator
redundant_tool_calls → cùng tool + cùng input > 1 lần
Quality metrics:
task_completion_rate → agent hoàn thành task không?
user_confirmation_rate → user có approve actions không?
rollback_rate → action phải undo bao nhiêu?
Reliability metrics:
consecutive_errors → agent có stuck không?
timeout_rate → task có hit timeout không?
guardrail_triggers → guardrails có fire không?
Cost metrics:
cost_per_task → avg cost mỗi task
token_efficiency → output quality / tokens used
model_distribution → % calls trên mỗi model
Alerting: Khi nào cần alert
Alert thresholds (ví dụ):
CRITICAL:
consecutive_errors >= 3 → agent stuck
task_timeout → task chạy quá lâu
cost_per_task > $5.00 → runaway cost
WARNING:
turns_per_task > 20 → efficiency thấp
redundant_tool_calls > 3 → looping behavior
guardrail_triggers > 2 → permission violations
INFO:
session_start
task_completion
model_fallback_triggered → primary model fail
Storage: Balance detail vs cost
Lưu full reasoning trace tốn storage. Cần balance:
Retention strategy:
Hot storage (30 ngày):
Full trace với all spans
Searchable, fast query
Warm storage (90 ngày):
Aggregated metrics
Session summaries
Error details
Cold storage (1 năm):
Session metadata only
Cost aggregations
Audit trail
Cost optimization:
Không log full message content (tốn kém)
Log summaries và previews
Sample verbose traces (10% full, 100% aggregated)
Trade-off: Full Observability vs Performance
Full tracing:
+ Complete picture của agent reasoning
+ Debug bất kỳ decision nào
- Storage cost cao
- Latency overhead ~5-10ms mỗi span
- Privacy concerns (tool results có thể chứa PII)
Minimal logging:
+ Cheap, fast
- Khó debug
- Không biết tại sao agent fail
Production recommendation: Full tracing cho 10-20% sessions (sampling), minimal cho phần còn lại. Full tracing cho mọi session có error hoặc user report.
Kết luận
- Agent observability cần reasoning trace, không chỉ latency/error rate.
- Mỗi LLM call và tool execution là một span trong trace tree.
- Agent-specific metrics: turns per task, redundant calls, cost per task, completion rate.
- Alerting theo 3 levels: critical (stuck/runaway), warning (inefficiency), info (operational).
- Balance storage cost với observability depth bằng sampling strategy.
- Full tracing cho errors và sampled sessions — không full trace mọi thứ.
Chưa có bình luận
Để lại bình luận
Bình luận sẽ được phê duyệt trước khi hiển thị.