☰ Mục lục series
Agent và công cụ

Xây dựng tác vụ tự động bằng agent hiệu quả

Bản dịch từ claude.dev/blog/building-effective-agent-automations/

Tác giả bài gốc: Lance Martin and CJ Avilla (Member of Technical Staff). Đăng ngày 08/10/2026 trên claude.dev.

Khi AI đẩy nhanh nhịp độ công việc, việc theo kịp mọi thứ cũng ngày càng khó hơn. Tại Anthropic, chúng tôi thường dùng những tác vụ tự động đơn giản bằng agent để hỗ trợ. Chúng thường chạy theo lịch, thu thập context ở chế độ nền và chủ động cho chúng tôi biết những gì cần biết. Nhưng xây dựng tác vụ tự động bằng agent cho hiệu quả không hề dễ: chúng có thể mất quyền truy cập một nguồn mà không ai nhận ra, hoặc không làm theo các tùy chọn của chúng tôi.

Với Claude Managed Agents (beta), chúng tôi đã xây dựng một triển khai tham khảo đọc các nguồn tùy chỉnh (chẳng hạn Slack và repo GitHub) theo lịch, theo dõi những thay đổi kể từ lần chạy trước và đăng những thông tin bạn cần biết (chẳng hạn lên Slack). Trong bài này, chúng tôi sẽ đi qua từng bước, chia sẻ triển khai tham khảo và cung cấp một lệnh để chạy trong Claude Code, giúp cấu hình agent cho bạn.

Lấy code

Triển khai tham khảo nằm ở đây. Để được hướng dẫn tương tác từng bước, hãy chạy lệnh dưới đây trong Claude Code. Skill claude-api có thể giúp thiết lập agent theo hướng dẫn trong bài này:

/claude-api managed-agents-onboard https://claude.dev/blog/building-effective-agent-automations/

Với triển khai tham khảo này, bạn cần một ứng dụng Slack (tạo từ manifest) và một token GitHub. Các file được cung cấp (hiển thị bên dưới) là cấu hình cho các tài nguyên Claude API, bao gồm agent, môi trường chạy của nó, các kho bộ nhớ (memory store), kho thông tin xác thực (vault) và deployment.

daily-brief/
├── agent.md                        model, tools, instructions
├── deployment.md                   schedule, time zone, budget, input message
├── environment.yaml                network allowlist
├── memory_store_preferences.yaml   user preferences
├── memory_store_state.yaml         the agent's bookmarks, ledger, notes, and run records
├── vault.yaml                      the vault that holds the credentials
├── claude-lock.json                resource IDs, written by ant apply
└── slack/manifest.yaml             one bot app

ant apply, một lệnh trong ant CLI, đọc các file này, tạo các tài nguyên trong workspace Claude API của bạn (nơi nền tảng lưu trữ và chạy chúng), rồi ghi lại các ID vào claude-lock.json.

Chúng ta sẽ dùng lệnh này trong các phần bên dưới. Sau khi được cấu hình, tác vụ tự động chạy theo lịch trên hạ tầng của Anthropic, nên bạn không phải để bất kỳ thứ gì chạy liên tục trên máy của mình.

Tổng quan

Agent chúng ta sẽ xây dựng có sáu thành phần, được trình bày theo thứ tự sau:

  • Nguồn dữ liệu - Danh sách có đặt tên gồm những nơi cần đọc
  • Đích đến - Một nơi mà agent được phép ghi
  • Agent - Model, tool và các bước chạy trong agent.md
  • Lịch chạy - Lịch cron
  • Bộ nhớ - Các tùy chọn của bạn và bộ nhớ riêng của agent
  • Hàng rào bảo vệ (guardrail) - Quyền chỉ đọc ở mọi nơi agent chỉ cần đọc, cùng một hạn mức chi tiêu cho mỗi lần chạy

Kiến trúc của agent: lịch chạy đánh thức agent, agent đọc các nguồn dữ liệu rồi đăng một bản tin tóm tắt đến một đích duy nhất cho người đọc. Bộ nhớ lưu trạng thái của agent và các tùy chọn của người đọc; các hàng rào bảo vệ bao quanh agent.

Nguồn dữ liệu

Agent đọc hai nguồn mặc định: các kênh Slack và pull request GitHub. Các kênh và repo được liệt kê trong file preferences của bạn. Bạn có thể mở rộng mẫu này để dùng những nguồn khác.

Sơ đồ kiến trúc với phần Nguồn dữ liệu được làm nổi bật. Các nguồn chỉ cho phép đọc, được truy cập qua MCP hoặc HTTPS bằng thông tin xác thực từ một vault và cung cấp dữ liệu cho agent.

Cấp thông tin xác thực riêng với phạm vi quyền hạn cụ thể cho agent

Với Managed Agents, thông tin xác thực được lưu trong các vault. Agent có thể tham chiếu đến những thông tin xác thực này, nhưng giá trị thật vẫn nằm trong vault, bên ngoài sandbox nơi code của Claude chạy (xem ở đây và ở đây):

  • MCP server (GitHub). Agent gọi các tool MCP qua một proxy chạy bên ngoài sandbox. Proxy tìm thông tin xác thực trong vault có URL khớp với URL của server.

  • Shell (Slack). Agent gọi Slack API bằng curl thông qua tool bash bên trong sandbox. Sandbox chỉ giữ một giá trị giữ chỗ không tiết lộ bí mật thật, $SLACK_BOT_TOKEN. Khi request rời sandbox, nền tảng thay giá trị đó bằng token thật đối với những host bạn cho phép.

Tạo vault bằng ant CLI và file mẫu trong repo:

ant apply vault.yaml

Lệnh này tạo vault trong workspace Claude API của bạn, nơi nền tảng lưu trữ nó, rồi ghi ID của vault vào claude-lock.json. Sau đó, thêm từng thông tin xác thực vào vault bằng TypeScript SDK. Dưới đây là ví dụ thêm thông tin xác thực Slack:

const vaultId = process.env.VAULT_ID!; // the vault's ID, from claude-lock.json

await client.beta.vaults.credentials.create(vaultId, {
  display_name: "SLACK_BOT_TOKEN",
  auth: {
    type: "environment_variable",
    secret_name: "SLACK_BOT_TOKEN",
    secret_value: process.env.SLACK_BOT_TOKEN!,
    networking: { type: "limited", allowed_hosts: ["slack.com"] },
    injection_location: { header: true },
  },
});

Sau khi tạo vault và thêm từng thông tin xác thực, hãy gắn vault vào deployment. Sao chép ID vault từ claude-lock.json vào vault_ids trong file deployment, deployment.md.

Đọc tiếp từ chỗ đã dừng

Một sai lầm phổ biến là yêu cầu agent đọc một khoảng thời gian cố định như “24 giờ qua”. Một lần chạy trễ sẽ để lại khoảng trống, còn một lần chạy sớm sẽ lặp lại các mục đã đọc. Thay vào đó, hãy cho agent một dấu mốc (bookmark) cho mỗi nguồn. Cuối mỗi lần chạy, agent ghi timestamp của mục mới nhất mà nó đã đọc từ từng nguồn vào một file duy nhất, bookmarks.json, với một mục tương ứng cho mỗi nguồn: "slack": "2026-09-14T13:02:11Z".

Lần chạy tiếp theo bắt đầu từ những bookmark đó, nên khoảng thời gian được đọc sẽ dài ra hoặc ngắn lại để bao quát mọi thứ kể từ lần chạy trước. Các bookmark nằm trong memory store có tên state: một thư mục chứa các file văn bản mà nền tảng mount vào sandbox của mỗi lần chạy bên dưới /mnt/memory/ và lưu giữ giữa các lần chạy. Agent đọc và ghi thư mục này bằng các tool thao tác file thông thường; hướng dẫn trong agent.md chỉ cho nó cách làm.

Đừng nhầm lỗi đọc dữ liệu với một ngày không có gì mới

Nếu một MCP server ngừng hoạt động hoặc token của nó hết hạn, lần chạy vẫn bắt đầu, chỉ là không có các tool của server đó. Session ghi log lỗi, nhưng agent không thấy gì từ nguồn ấy và báo “không có gì mới”.

Ba quy tắc trong agent.md giúp khắc phục vấn đề này. Khi một nguồn gặp lỗi, agent sẽ: giữ nguyên bookmark của nguồn đó, viết bản tin tóm tắt từ những nguồn còn lại và kết thúc bản tin bằng một dòng nêu rõ thứ nó không đọc được (“không truy cập được pull request trong lần chạy này”), để người đọc biết.

Đích đến

Mẫu của chúng tôi đăng lên một kênh Slack duy nhất, mỗi lần chạy tạo một bài đăng có ghi ngày.

Sơ đồ kiến trúc với phần Đích đến được làm nổi bật. Sau khi kiểm tra rằng bản tin hôm nay chưa được đăng, agent đăng đến một đích duy nhất, nơi chuyển bản tin cho người đọc.

Agent đăng lên Slack bằng tool bash trong sandbox của nó, dùng cùng token bot mà nó dùng để đọc.

Không cần bước phê duyệt bài đăng. Agent gửi bài bằng một lệnh bash, và mặc định tool bash tích hợp chạy mà không yêu cầu phê duyệt. slack.com cũng nằm trong danh sách cho phép của môi trường của agent, tức sandbox nơi nó chạy. Việc đăng chỉ cần một request:

curl -s https://slack.com/api/chat.postMessage \
  -H "Authorization: Bearer $SLACK_BOT_TOKEN" \
  -H "Content-Type: application/json; charset=utf-8" \
  -d '{"channel": "C0123456789", "text": "Daily brief, Tue Sep 15 ..."}'

Xác nhận bài đã được đăng trước khi ghi nhận

Sau khi xác nhận bài đã được đăng, agent cập nhật sổ theo dõi (ledger) các mục đã báo và các bookmark. Nếu những bản ghi này không khớp với nội dung thực sự đã đăng, hai vấn đề có thể xảy ra. Nếu agent ghi nhận một bài chưa từng được đăng thành công, các bookmark sẽ tiến lên và những mục đó sẽ không bao giờ được báo. Nếu nó đăng lại vì không chắc bài đầu tiên đã được đăng thành công hay chưa, người đọc sẽ nhận cùng một bản tin hai lần.

Ba quy tắc trong agent.md ngăn chuyện này xảy ra. Thứ nhất, agent tìm tiêu đề của hôm nay trong các tin nhắn gần đây của kênh và không đăng nếu bản tin đó đã có. Thứ hai, bài đăng chỉ được tính là đã gửi nếu Slack trả về "ok": true và một ts của tin nhắn. Thứ ba, agent chỉ cập nhật ledger và bookmark sau xác nhận đó. Nếu kết quả không rõ ràng, nó đánh dấu lần chạy là “có thể đã đăng” và không thay đổi gì khác, để không bỏ sót thông tin.

Agent lưu một bản ghi lần chạy trong memory store (runs/<date>.md). Nó đánh dấu lần chạy là “đang đăng” trước khi đăng, rồi chuyển thành “đã đăng” kèm ID tin nhắn, hoặc “có thể đã đăng”.

Agent

Trong Claude Managed Agents, một agent là một cấu hình được quản lý phiên bản: một model, một system prompt và các tool. Mỗi lần chạy thực hiện các bước đã định rồi dừng lại.

Sơ đồ kiến trúc với phần Agent được làm nổi bật: một model cùng một prompt chứa vòng lặp thực thi và các quy tắc đánh giá.

Trong triển khai tham khảo của chúng tôi, cấu hình agent nằm trong agent.md:

---
name: Daily brief
model: claude-sonnet-5-5
mcp_servers:
  - type: url
    name: github
    url: https://api.githubcopilot.com/mcp/
tools:
  - type: agent_toolset_20260401
    configs:
      - name: web_search
        enabled: false
      - name: web_fetch
        enabled: false
  - type: mcp_toolset
    mcp_server_name: github
    default_config:
      permission_policy:
        type: always_allow
---

[Eight numbered run steps; the full text is in agent.md in the repo.]

Frontmatter cung cấp tên agent, model, tool và các MCP server. Phần thân chứa hướng dẫn cho agent. Mặc định, tool MCP yêu cầu phê duyệt nhưng không có ai ở đó để phê duyệt, nên bộ tool GitHub được đặt thành always_allow và token GitHub là read-only.

Giữ bản tin ngắn gọn

agent.md hướng Claude đến sự ngắn gọn:

4. Decide. An item earns a line when the reader would act on it today, or it changes a decision they are about to make. When unsure, leave it out. Most days that is a few items, sometimes none. A count ("12 open reviews") is not an item; link the ones that are blocked. An item already in the ledger and still open is carried as one marked line ("still waiting, day 3"), not re-reported; a closed item is dropped without comment. Do not bring back a topic the preferences file has retired.

Kiểm tra lại mọi mục còn mở ngay trước khi đăng

Các mục có thể thay đổi từ lúc agent đọc nguồn dữ liệu đến lúc nó đăng bài. Ngay trước khi đăng, agent.md hướng dẫn agent kiểm tra lại trạng thái hiện tại của từng mục:

5. Verify. The world moved while you read. For every item you will report, re-check its live source just before posting: resolved since you read it, drop it; still open but changed, fix the line; cannot confirm, drop it and list it in the run record's cuts. One stale "still waiting on you" costs more trust than ten missing items, so never hedge an item's status: assert it or drop it. Every link is copied from the source's own link field (a pull request's html_url, a Slack permalink), never assembled by hand.

Lịch chạy

Với Claude Managed Agents, agent chỉ là một file cấu hình; một deployment sẽ chạy nó. Deployment chỉ định agent, môi trường và tin nhắn đầu tiên của mỗi lần chạy. Nó cũng chứa lịch chạy, vault, các memory store và ngân sách. Mỗi khi đến lịch, nền tảng khởi tạo một session agent mới.

Sơ đồ kiến trúc với phần Lịch chạy được làm nổi bật: một deployment theo lịch đánh thức agent cho mỗi lần chạy.

Trong mẫu của chúng tôi, deployment được mô tả trong deployment.md, với tin nhắn đầu tiên làm phần thân:

---
name: Daily brief
agent: ./agent.md
environment_id: ./environment.yaml
schedule:
  type: cron
  expression: "32 7 * * 1-5"
  timezone: America/New_York
vault_ids: [vlt_...]   # the vault you create under Sources
resources:
  - path: ./memory_store_preferences.yaml
    access: read_only
    instructions: The reader's preferences. Re-read them every run. Never write here.
  - path: ./memory_store_state.yaml
    access: read_write
    instructions: Your state. Bookmarks, ledger, notes, proposals, and run records.

---

Write today's brief.
The reader's time zone is America/New_York. Work out every date in that zone.

Follow your run steps in order. Today's edition is titled "Daily brief, <weekday> <month> <day>".

Lệnh dưới đây tạo deployment cùng agent, môi trường và các memory store mà nó chỉ định bằng đường dẫn.

ant apply deployment.md

Để thử mà không phải đợi đến lịch, hãy bắt đầu một lần chạy thủ công bằng ant beta:deployments run --deployment-id <id>, sử dụng ID trong claude-lock.json.

Tính ngày theo múi giờ của bạn

Một lỗi phổ biến là agent gọi sáng nay là “hôm qua” vì nó tính ngày theo múi giờ của server. Trong deployment.md, trường timezone đặt thời điểm kích hoạt lần chạy, còn dòng thứ hai trong phần thân cho agent biết phải dùng múi giờ nào khi tính ngày.

Bộ nhớ

Mỗi lần chạy bắt đầu trong một sandbox mới, không nhớ gì về lần trước. Không có bộ nhớ thì phản hồi của bạn không được ghi nhớ. Tuy nhiên, bộ nhớ lỗi thời có thể khiến agent nhầm lẫn: nó báo một mục vẫn đang chờ dù đã được giải quyết, hoặc bỏ qua một mục vẫn còn mở vì mục đó “đã được báo”.

Sơ đồ kiến trúc với phần Bộ nhớ được làm nổi bật. Trạng thái là phần agent đọc và ghi, còn Tùy chọn là phần người đọc ghi và agent chỉ đọc.

Mẫu của chúng tôi duy trì hai memory store, là các thư mục được mount bên dưới /mnt/memory/ (xem phần Nguồn dữ liệu):

  • preferences (của bạn, agent chỉ có quyền đọc): những kênh và repo cần đọc, nội dung cần bỏ qua, giới hạn độ dài, đích đến và khi nào cần dừng.

  • state (của agent, có quyền đọc và ghi): các bookmark, ledger ghi những gì nó đã báo, một bản ghi cho mỗi lần chạy, những thay đổi nó đề xuất cho các tùy chọn của bạn và ghi chú về cách hoạt động của từng nguồn (“chỉ trả về 50 mục mới nhất”).

ant apply deployment.md tạo store chứa các tùy chọn, nhưng không tạo file bên trong. Trước lần chạy đầu tiên, hãy ghi file preferences.md của bạn vào đó bằng scripts/seed-preferences.sh trong repo.

Đọc lại các tùy chọn của bạn khi bắt đầu mỗi lần chạy

Một vấn đề thường gặp xảy ra khi bản sao các tùy chọn được nhúng cố định vào prompt, khiến agent tiếp tục áp dụng những quy tắc bạn đã thay đổi. Hãy để agent đọc lại file từ đầu trong mỗi lần chạy. Nếu không đọc được file, nó nên dừng lại và báo rõ thay vì chạy theo các giá trị mặc định.

Lưu sổ theo dõi những gì đã báo và chỉ báo thay đổi

Agent duy trì một ledger, ledger.md, ghi lại mọi mục nó đã báo để bản tin không lặp lại nội dung. Mỗi dòng ghi thời điểm mục đó được báo, nguồn của nó, một ID không thay đổi (timestamp của tin nhắn Slack hoặc số pull request) và trạng thái được biết gần nhất:

2026-09-09 slack:C0123456789 1788963600.000100 refund thread: customer waiting on a decision
2026-09-11 github 481 review blocked, day 2 (still waiting)
2026-09-11 slack:C0234567891 1789117333.000300 enterprise escalation: owner named, in progress

Hàng rào bảo vệ

Vì tác vụ tự động của chúng tôi chạy “nền” theo lịch, chúng tôi đặt giới hạn cho những gì agent được làm và số tiền nó có thể chi.

Sơ đồ kiến trúc với phần Hàng rào bảo vệ được làm nổi bật: một ranh giới bao quanh agent với giới hạn về số lượt, thời gian và chi tiêu, cùng tín hiệu báo hoạt động được một người theo dõi.

Giới hạn những gì agent được làm

Agent đọc các tin nhắn và issue do người khác viết, và phần văn bản đó có thể bị hiểu thành hướng dẫn. Hãy giới hạn những gì agent có thể làm nếu nó làm theo những hướng dẫn ấy. Trong ví dụ của chúng tôi, token GitHub và store preferences đều chỉ cho phép đọc, còn môi trường chỉ truy cập được các host trong danh sách cho phép. Một chỉ dẫn được cài vào dữ liệu vẫn có thể thay đổi nội dung bản tin, kể cả thông qua những ghi chú agent lưu giữ giữa các lần chạy. Nhưng nó không thể ghi lên GitHub hay chỉnh sửa các quy tắc của bạn.

Slack là ngoại lệ: cùng một token được dùng để đăng bài, nên chỉ mời bot vào những nơi nó cần đọc hoặc đăng.

Đặt hạn mức chi tiêu dựa trên các lần chạy thực tế

Hạn mức chi tiêu bảo vệ bạn trước chi phí tăng mất kiểm soát. Hãy bắt đầu ở mức gấp ba đến năm lần chi phí của một lần chạy bình thường, rồi siết lại khi bạn có số liệu thực tế. Một lần chạy chạm hạn mức sẽ tạm dừng thay vì thất bại, nên đặt hạn mức quá thấp có thể khiến bạn tưởng bản tin đột nhiên ngừng cập nhật. Hạn mức này là budget trong deployment.md. Mỗi lần chạy được cấp toàn bộ số tiền này, và lần chạy chạm hạn mức sẽ tạm dừng với lý do dừng budget_reached:

budget:
  type: limit
  max_list_cost:
    amount: "500" # a string, in cents: "500" is $5.00
    currency: USD

Bắt đầu

Triển khai tham khảo của chúng tôi có thể gói gọn trong sáu quy tắc:

  • Đọc từng nguồn từ một bookmark, không phải một khoảng thời gian cố định.
  • Báo rõ khi không đọc được nguồn, đừng bao giờ coi đó là một ngày không có gì mới.
  • Kiểm tra lại từng mục ngay trước khi đăng.
  • Chỉ tính bài đăng là đã gửi khi Slack xác nhận, rồi mới cập nhật bookmark và ledger.
  • Đọc lại các tùy chọn của bạn trong mỗi lần chạy, từ một store mà agent không thể chỉnh sửa.
  • Cấp quyền chỉ đọc ở mọi nơi agent chỉ cần đọc, và giới hạn chi tiêu cho mỗi lần chạy.

Claude Code có thể hướng dẫn bạn từng bước theo nội dung trong bài này. Trước tiên, hãy cập nhật:

claude update

Sau đó, dùng skill claude-api:

/claude-api managed-agents-onboard https://claude.dev/blog/building-effective-agent-automations/

Skill claude-api đọc bài này, đề xuất cách thiết lập, ghi các file vào một thư mục agents/ trong dự án của bạn và tạo các tài nguyên bằng ant apply. Hãy coi đây là điểm khởi đầu, rồi tùy chỉnh agent theo các nguồn dữ liệu, đích đến hoặc tùy chọn về bộ nhớ của bạn.

Nội dung gốc: claude.dev Blog © Anthropic, PBC, giấy phép đăng lại có sự cho phép của Anthropic. Bản dịch và ghi chú: Lê Văn Dũng.