TROISINH
Phát triển AgentHooks & Quality Control

Post-action Hooks: Auto-format, log, notify sau mỗi action — Tự động hóa sau khi agent hành động

Post-action hooks giúp auto-format code, gửi log và thông báo ngay sau khi agent hoàn thành hành động, tách biệt logic chính và xử lý phụ trợ.

Khi agent vừa ghi xong một file code hoặc gọi xong một tool, bạn muốn tự động chạy linter để format lại, gửi thông báo lên Slack cho team, và ghi log vào hệ thống monitoring. Nếu nhét tất cả những việc này vào cùng một function xử lý chính, code sẽ nhanh chóng biến thành "spaghetti" khó test và khó bảo trì. Post-action hooks giải quyết vấn đề này bằng cách tách biệt "làm việc" và "dọn dẹp" theo thời gian.

Vấn đề

Trong hệ thống AI agent truyền thống, khi một action (gọi tool, sửa file, gửi message) hoàn thành, các tác vụ "đi kèm" thường được nhét trực tiếp vào logic chính:

def agent_edit_file(file_path, content):
    # Logic chính: ghi file
    with open(file_path, 'w') as f:
        f.write(content)
    
    # Logic phụ: format code (có thể fail)
    try:
        subprocess.run(["black", file_path])
    except Exception as e:
        logger.error(f"Format failed: {e}")
    
    # Logic phụ: gửi Slack
    slack.notify(f"Edited {file_path}")
    
    # Logic phụ: update metrics
    metrics.increment("file_edits")
    
    return result

Vấn đề của cách tiếp cận "inline" này:

  • Coupling chặt chẽ: Muốn thêm kênh thông báo (chuyển từ Slack sang Discord) phải sửa code lõi của agent
  • Khó test: Unit test cho "ghi file" bị lẫn với test cho "gửi Slack"
  • Failure modes phức tạp: Nếu Slack bị lỗi mạng, action chính (ghi file) có nên rollback không? Hay đã thành công nhưng coi như thất bại?
  • Bloat context: Trong agent systems như OpenClaw, việc nhét nhiều logic phụ vào main loop làm tăng token count và giảm hiệu suất reasoning

Các framework cũ thường dùng "hardcoded callbacks" hoặc "middleware chains" cố định, nhưng chúng thiếu tính linh hoạt để user tự định nghĩa hành vi sau action mà không đụng đến core.

Ý tưởng cốt lõi

Post-action hooks dựa trên nguyên tắc Temporal Separation of Concerns (tách biệt theo thời gian). Thay vì agent vừa làm vừa dọn, chúng ta chia thành hai giai đoạn rõ rệt:

  1. Main Action: Transaction chính (ghi file, gọi API, compute)
  2. Post-Action Phase: Các tác vụ phụ trợ (format, log, notify) chạy sau khi state đã được persist

Cơ chế hoạt động giống như "Kitchen Pass" (bếp trưởng nấu xong thì giao cho expediter):

Cấu trúc Hook System

Trong môi trường agent hiện đại (OpenClaw, Claude Code, hay custom frameworks), post-action hooks được cấu hình qua các file markdown hoặc YAML:

# hooks.yml hoặc trong SOUL.md
hooks:
  post_file_write:
    - name: auto_format
      priority: 10
      action: "run_command"
      command: "prettier --write {{file_path}}"
      blocking: false  # Không chờ kết quả
    
    - name: audit_log
      priority: 20
      action: "webhook"
      url: "https://audit.company.com/log"
      payload:
        event: "file_modified"
        agent: "{{agent_id}}"
        timestamp: "{{now}}"
    
    - name: notify_team
      priority: 30
      action: "slack"
      channel: "#ai-ops"
      message: "Agent {{agent_name}} vừa sửa file {{file_path}}"
      condition: "{{is_production}}"  # Chỉ chạy ở prod

Priority Queue (Hàng đợi ưu tiên)

Các hooks không chạy ngẫu nhiên. Chúng được sắp xếp theo priority (số nhỏ chạy trước):

  • Priority 1-10: Các tác vụ "cleanup" ngay lập tức (format code, validate syntax)
  • Priority 11-20: Logging và audit (ghi vào database, gửi telemetry)
  • Priority 21+: Thông báo async (Slack, email, SMS)

Ví dụ cụ thể trong Claude Code:

// .claude/hooks/post-action.ts (conceptual)
export default {
  name: "post_file_edit",
  priority: 5,
  async execute(context: ActionContext) {
    // Auto-format chỉ chạy với file .ts và .js
    if (context.filePath.match(/\.(ts|js)$/)) {
      await context.runCommand("eslint --fix", context.filePath);
    }
    
    // Log vào LangSmith
    await langsmith.trace({
      action: "file_edit",
      input: context.diff,
      agent: context.agentId,
      timestamp: Date.now()
    });
  }
};

Blocking vs Non-blocking

Blocking hooks: Chạy đồng bộ, chờ kết thúc mới trả control về cho agent. Dùng cho quality gates (ví dụ: "nếu format fail thì coi như action fail").

Non-blocking hooks: Fire-and-forget. Agent không chờ kết quả. Dùng cho analytics và notifications. Nếu Slack API timeout, agent vẫn tiếp tục workflow.

Tại sao nó hoạt động

Inversion of Temporal Control

Thay vì main function "pull" các dependencies (gọi logger, gọi notifier), nó chỉ "push" một signal action_completed. Các subscribers (hooks) tự "pull" signal này và quyết định xử lý.

Điều này tạo ra orthogonal axes (trục trực giao):

  • Thay đổi formatter (Prettier → Black) không ảnh hưởng đến notifier
  • Thêm kênh thông báo (thêm Discord) không cần sửa code action chính
  • Tắt logging trong môi trường test chỉ cần unregister hook, không cần mock object phức tạp

Semantic vs Syntactic Separation

Trong kiến trúc agent, post-action hooks chiếm vị trí "syntactic layer" (how) tách biệt với "semantic layer" (what) của main action:

  • Pre-action hooks (xem thêm Pre-action Hooks) kiểm soát "có được phép làm không" — đây là permission
  • Post-action hooks xử lý "làm xong rồi thì dọn dẹp thế nào" — đây là hygiene

Sự tách biệt này phản ánh nguyên tắc Unix: "Do one thing and do it well". Agent làm nhiệm vụ chuyên môn, hooks lo phụ trợ.

Trade-off với Pre-action

Pre-action HooksPost-action Hooks
Thời điểmTrước state mutationSau state mutation
Mục đíchValidation, gatekeepingCleanup, notification
Failure handlingBlock action (fail-closed)Log error, alert human (fail-open)
Latency impactThêm vào critical pathCó thể async, không ảnh hưởng UX

Ý nghĩa thực tế

Tác động đến Production

  • Code hygiene: Giảm 60-80% boilerplate trong agent core logic (theo benchmarks từ WordPress core: ~0.1-0.5ms overhead per callback, negligible so với LLM latency 2-5s)
  • Observability: Tự động trace mọi action vào LangSmith, Langfuse, hoặc custom dashboard mà không cần sửa code tool
  • Compliance: Audit logs tự động ghi lại "ai đã làm gì vào lúc nào" cho GDPR/SOC2

Ví dụ thực chiến

1. Code Review Agent

  • Action: Agent sửa file .py
  • Post-hook priority 10: Chạy blackisort để format
  • Post-hook priority 20: Chạy pytest quick check trên file đó (smoke test)
  • Post-hook priority 30: Gửi diff lên Slack channel #code-review

2. Financial Data Agent

  • Action: Agent cập nhật forecast trong spreadsheet
  • Post-hook: Ghi log vào immutable ledger (blockchain hoặc WORM storage) cho audit trail
  • Post-hook: Nếu số tiền > threshold, trigger Human-in-the-Loop

3. Multi-agent Teams

  • Action: Agent A handoff task sang Agent B
  • Post-hook: Update shared task board (Notion/Trello)
  • Post-hook: Nếu B không accept trong 5 phút, notify manager (escalation pattern)

Hạn chế và Anti-patterns

Debugging complexity: Stack trace không còn linear. Khi lỗi xảy ra, bạn phải trace qua nhiều callback functions. Giải pháp là implement structured logging trong mỗi hook với correlation ID.

Race conditions: Nếu hook async chạy sau khi state đã bị modify bởi action tiếp theo (ví dụ: hook log chưa chạy xong thì agent đã xóa file). Giải pháp: Đảm bảo hooks được await (blocking) cho đến khi persist hoàn tất, hoặc dùng immutable state snapshots.

Circular traps: Post-hook A trigger action X, mà action X lại có post-hook B trigger action Y... tạo thành infinite loop. Cần circuit breaker (max recursion depth) hoặc idempotency keys.

Không dùng cho: Latency-critical path. Nếu user đang chờ response real-time (voice agent, trading), post-hooks nên để sang background job (Celery, BullMQ) thay vì chạy sync.

Đào sâu hơn

Tài liệu chính thức:

  • WordPress Action Hooks — Pattern gốc của hệ thống hook trong software architecture
  • Git Hooks — Post-commit, post-push patterns cho version control automation
  • OpenClaw Hooks Documentation — Implementation cụ thể cho AI agents (tham khảo từ các nguồn cộng đồng Reddit r/OpenClaw)

Bài liên quan TroiSinh:

Cùng cụm (Hooks & Quality Control):

Hooks: 25+ lifecycle events để tự động hóa

Tổng quan toàn bộ hệ thống hooks trong agent lifecycle

Pre-action Hooks

Chặn hành động nguy hiểm trước khi chạy — gatekeepers vs janitors

Quality Gates

Không cho agent skip bước — deterministic validation sau action

Đọc tiếp:

Human-in-the-Loop

Khi nào cần người phê duyệt? Kết hợp post-hook với escalation

Agent Teams

Handoff và delegation giữa các agent — post-hooks cho cross-agent notification

Mở rộng:

On this page