Learn > Claude > Claude Code: routine, headless & Agent SDK

Claude Code: routine, headless & Agent SDK

Giao việc lặp cho Claude trên một dải: routine (ít phải build nhất), headless mode với cờ -p và output có cấu trúc, tới Agent SDK chạy Claude Code bằng code.

  • Giao việc lặp cho Claude nằm trên một DẢI: đầu ít-phải-build nhất là routine (chạy trên hạ tầng Anthropic), đầu kia là headless mode + Agent SDK (chạy từ code của bạn). Routine = một prompt được lưu, gói 3 thứ (prompt + repository + connectors) rồi chạy trên cloud khi được kích hoạt — không script, không server, không máy nào của bạn phải thức, không workflow file phải maintain. Ba trigger: cron schedule (VD 9am mỗi sáng), HTTP POST tới API endpoint của nó, và GitHub event (VD có PR mới). Tạo bằng web claude.ai/code/routines hoặc lệnh /schedule ngay trong Claude Code (VD "/schedule daily dependency audit at 9am").
  • ⚠️ Ba giới hạn của routine: (1) đang là research preview — hành vi/limit còn đổi; (2) recurring schedule chạy nhiều nhất MỖI GIỜ một lần, cần dày hơn thì routine không phải công cụ; (3) mỗi run bắt đầu từ fresh clone của default branch và chỉ push được lên branch prefix claude/ trừ khi nới theo từng repo — guardrail giữ cho lần chạy tự chủ không viết đè main. Docs 09/2026 đã nới: prompt chỉ định branch khác thì Claude vẫn push được, trừ khi branch đó được bảo vệ trên GitHub, đang có PR của người khác, hoặc chứa commit của người khác.
  • Headless mode dùng khi việc cần môi trường của bạn hoặc cần logic bọc quanh: cờ -p (--print) chạy Claude Code như lệnh one-shot không UI, đọc stdin ghi stdout nên pipe được như mọi tool shell. Theo khoá, -p bỏ auto-discovery của hook/skill/ plugin/MCP server/CLAUDE.md nên khởi động nhanh hơn (⚠️ docs hiện hành gán việc này cho --bare, còn -p trơn vẫn nạp context như session tương tác). Muốn dữ liệu có cấu trúc: --output-format json + --json-schema → object khớp schema nằm ở field structured_output, móc ra bằng jq. Nhiều bước thì bắt session_id từ JSON rồi claude --resume "$(jq -r .session_id /tmp/plan.json)" — script này khởi động, script kia resume với đầy đủ context. CI cần kết quả lặp lại được thì dùng --bare (deterministic mode — tất định ở đây là môi trường chạy, không nạp cấu hình riêng của máy; câu trả lời của model thì vẫn có thể khác nhau). Thứ tự chọn: routine mặc định → -p khi cần pipeline của bạn → --bare cho CI → Agent SDK khi việc thuộc về sản phẩm của bạn.
  • Agent SDK: chạy Claude Code programmatically từ app/script của bạn (TypeScript + Python), trao đúng agent loop CLI dùng (đọc/sửa file, tool use) dưới quyền bạn. Package = @anthropic-ai/claude-agent-sdk (KHÔNG phải @anthropic-ai/claude-code — đó là CLI, không import được). Dùng query({ prompt }) như async iterator, stream ra JSON message (tool call, tool result, text). Khoá dạy giới hạn tool bằng options.allowedTools (VD ["Read","Glob"]) = bản SDK của --allowedTools; docs 09/2026 nói allowedTools chỉ TỰ DUYỆT tool được liệt kê, tool khác vẫn dùng được — giới hạn thật thì dùng tools / disallowedTools, hoặc ghép allowedTools với permissionMode "dontAsk". SDK hỗ trợ đủ như CLI: custom system prompt, MCP, hooks, subagents, session resumption. Đây là thứ query_hook.js dùng để một Claude review một Claude khác.

TL;DR — Giao việc lặp nằm trên một dải, không phải một lựa chọn: routine ít phải build nhất (nhưng còn research preview, 3 giới hạn phải biết) → headless -p khi cần môi trường của bạn hoặc logic bọc quanh → Agent SDK khi cần chạy Claude Code từ chính app của bạn. Chọn sai đầu dải là tự dựng thứ đã có sẵn.

Phần 4/7 của ghi chú khoá Claude Code in Action — đề thi thử 219 câu (chấm điểm + giải thích) nằm ở tab "Đề thi thử" trên trang tổng quan.

Routine & headless — giao hẳn việc lặp cho Claude

Khi đã tin Claude làm được một task, nước đi kế tiếp là thôi tự tay làm nó. Cùng một prompt chạy trên một trigger lặp lại thì không việc gì phải ngồi bấm mỗi lần. Có hai đường giao việc, và chúng nằm trên một dải (spectrum):

  • Đầu này: routine — chạy trên hạ tầng của Anthropic, bạn không build gì cả.
  • Đầu kia: headless mode + Agent SDK — chạy Claude Code từ code của chính bạn, toàn quyền kiểm soát.

Bắt đầu từ đầu ít-phải-build nhất.

Routine — một prompt được lưu, chạy trên cloud

Routine là cách trực tiếp nhất để tự động hoá một task: không script, không server. Nó gói ba thứ: một prompt, repository nó làm việc trên đó, và các connector nó cần — rồi chạy cái gói đó trên cloud mỗi khi được kích hoạt.

Điểm mấu chốt: hạ tầng là của Anthropic. Không có máy nào của bạn phải bật suốt đêm, không có workflow file nào phải maintain. Mô tả công việc một lần, rồi nó cứ chạy.

Ba loại trigger:

Trigger Ví dụ
Cron schedule mỗi sáng 9am
HTTP POST tới API endpoint của nó code của bạn tự kích hoạt
GitHub event có pull request mới

Cái gì cùng một prompt trên một trigger lặp lại đều hợp: morning dependency audit, PR triager (fire khi có PR mới), quét Sentry ticket hằng ngày để biết cái nào gấp nhất.

Hai cách tạo routine

  • Từ web tại claude.ai/code/routines: đặt tên → viết instruction mô tả Claude phải làm gì trong mỗi session → chọn repository → chọn trigger.
  • Từ trong Claude Code, khỏi rời terminal — lệnh /schedule + mô tả bằng lời thường:
/schedule daily dependency audit at 9am

Cùng một thứ, hai cửa vào — chọn cửa nào hợp nếp làm việc của bạn.

🆕 Cửa thứ ba (khoá chưa nhắc, tự quan sát 25/07/2026): bản app Claude Code đã có mục Routines ngay trên sidebar (More → Routines, cạnh Artifacts) — mở ra xem/sửa routine khỏi cần vào web. Cùng một thứ với hai cách trên, chỉ khác lối vào. Đi thi thì nhớ web + /schedule theo lời khoá.

⚠️ Ba giới hạn phải biết TRƯỚC khi dựa vào routine

  1. Routine đang là research preview — hành vi và giới hạn còn đổi, đừng ngạc nhiên.
  2. Recurring schedule chạy nhiều nhất là MỖI GIỜ một lần. Cần dày hơn → routine không phải công cụ cho việc đó.
  3. Mỗi run bắt đầu từ một fresh clone của default branch, và chỉ push được lên branch có prefix claude/ trừ khi bạn nới ra theo từng repo. Đây chính là guardrail giữ cho một lần chạy tự chủ không viết đè lên main.

⚡ Docs 09/2026 — giới hạn thứ ba đã nới. Branch claude/… vẫn luôn được nhận, nhưng khi prompt chỉ định branch khác thì Claude vẫn push được — Claude Code chỉ chặn nếu branch đó được bảo vệ trên GitHub, đang có PR mở của người khác, hoặc chứa commit của người khác. Nghĩa là guardrail giờ nằm ở branch protection của repo, không còn nằm hẳn ở routine: muốn chắc main không bị đụng thì bật protection cho main. Và "bắt đầu từ default branch" là mặc định — prompt chỉ định branch khác thì Claude bắt đầu từ đó.

Headless mode — khi công việc cần môi trường của bạn

Routine hợp khi việc vừa vặn với cloud. Nhưng có lúc việc cần môi trường của bạn, hoặc cần logic bọc quanh lần chạy — đó là lúc tụt xuống headless mode.

Cốt lõi là cờ -p (viết tắt của --print): chạy Claude Code như một lệnh one-shot, không UI tương tác. Nó đọc stdin, ghi stdout → pipe được như mọi tool shell khác:

claude -p "summarize the changes in this diff"

Theo khoá: -p bỏ qua auto-discovery của hook, skill, plugin, MCP server và CLAUDE.md → bạn có Claude + đúng bộ tool bạn cho phép tường minh, không dính thứ môi trường local tình cờ nạp vào; đổi lại khởi động nhanh hơn nhiều.

⚠️ Freshness — chỗ này docs nói khác: theo docs hiện hành, chính --bare mới là cờ bỏ auto-discovery (hook, skill, plugin, MCP server, auto memory, CLAUDE.md); còn claude -p trơn vẫn nạp đúng lượng context như một session tương tác, gồm mọi thứ cấu hình trong thư mục làm việc hoặc ~/.claude. Docs cũng ghi --bare sẽ thành mặc định của -p ở bản sau — nhiều khả năng khoá đang mô tả trạng thái tương lai đó. Đi thi thì theo lời khoá; đi làm thì nhớ gõ --bare cho chắc.

Lấy output có cấu trúc

Vì headless pipe như tool shell, bạn thường muốn nhận lại dữ liệu có cấu trúc thay vì văn xuôi. Ghép một JSON schema với JSON output format → Claude ràng buộc output khớp schema của bạn.

Object khớp schema nằm ở field structured_output trong JSON response → móc ra bằng jq rồi đẩy vào database hay script khác:

claude -p "Extract the exported function names from src/core/style.js" \
  --output-format json \
  --json-schema '{"type":"object","properties":{"functions":{"type":"array","items":{"type":"string"}}},"required":["functions"]}' \
  | jq '.structured_output.functions'

→ Được một mảng sạch để đưa cho bước tiếp theo.

Tự động hoá nhiều bước bằng session

Việc trải qua nhiều bước thì khỏi nhồi hết vào một lệnh. Bắt lấy session ID từ JSON output rồi resume sau:

claude --resume "$(jq -r .session_id /tmp/plan.json)"

Một script khởi động công việc; một script khác resume nó sau, giữ nguyên context. Rất hợp khi lượt đầu ra một plan còn lượt sau thi hành plan đó.

--bare — chạy tất định cho CI

Khi CI cần đúng một kết quả ở mọi lần chạy, có một mode làm sẵn cho việc đó: cờ --bare = deterministic mode. Đây là lựa chọn đúng khi chạy Claude Code bên trong pipeline và bạn muốn output lặp lại được, đoán trước được, thay vì thứ đổi theo từng lần chạy.

⚠️ Hiểu đúng chữ "tất định" (docs 09/2026): --bare làm môi trường tất định chứ không làm câu trả lời tất định. Nó bỏ auto-discovery của hook, skill, custom command, subagent, plugin, MCP server, auto memory và CLAUDE.md → lần chạy không dính cấu hình riêng của máy chạy CI và khởi động nhanh hơn. Nhưng model vẫn có thể trả lời khác nhau giữa hai lần chạy cùng input — cần kết quả ổn định thì ràng bằng --json-schema và kiểm output ở bước sau. Docs gọi --bare là mode khuyên dùng cho script và SDK, và sẽ thành mặc định của -p ở bản sau.

Chọn cái nào?

Dùng Khi nào
Routine Mặc định cho việc lặp — chạy trên hạ tầng Anthropic, không phải host gì
Headless -p Việc cần pipeline của bạn, muốn đẩy dữ liệu qua một script
--bare CI cần đúng một kết quả mỗi lần chạy
Agent SDK Việc thuộc về sản phẩm của bạn (nhúng hẳn vào app — mục ngay dưới)

Nguyên tắc: bắt đầu bằng routine; chỉ tụt xuống dải dưới khi công việc thật sự cần thêm quyền kiểm soát.

Áp dụng thực tế: đọc mục này tôi thấy đúng một trục quen: ai chịu trách nhiệm vận hành. Routine = thuê ngoài trọn gói — không máy phải thức, không workflow phải nuôi; đổi lại chấp nhận research preview và trần 1 lần/giờ, nên tôi sẽ không đặt vào đó thứ mà delivery phụ thuộc theo phút. Ba giới hạn đó không phải chi tiết vụn: "fresh clone + chỉ push branch claude/" chính là least-privilege cho bot, cùng tinh thần allowed_tools bên GitHub Actions — con người vẫn giữ cửa merge. (Từ khi docs nới giới hạn này, bot chỉ không chạm được main nếu main được bảo vệ — nên branch protection giờ là việc phải làm, không phải tuỳ chọn.) Với repo này thì routine hợp mấy việc định kỳ mà không gấp: quét link chết, soát updated của note /learn đã cũ, rà dependency. Còn headless -p là thứ tôi thấy dùng được ngay và không cần cloud: nó biến Claude thành một mắt xích trong pipeline — git diff | claude -p ... | jq — nghĩa là AI trở thành một bước có input/output rõ ràng, kiểm được, thay vì một cuộc trò chuyện. Và --json-schema + structured_output mới là chỗ đáng giá nhất với dân delivery: văn xuôi thì không tự động hoá được, JSON thì được — có schema là có hợp đồng dữ liệu, có hợp đồng thì mới ghép được vào hệ khác. --bare cho CI khớp với bài học "đừng để môi trường mỗi máy mỗi khác": cùng input, cùng cấu hình → hành vi đoán trước được, không phụ thuộc hook trong ~/.claude của một ông đồng đội nào đó (câu trả lời của model thì vẫn phải kiểm ở bước sau).

Agent SDK — chạy Claude Code bằng code

Agent SDK cho phép chạy Claude Code programmatically từ app/script của bạn — có cho TypeScript và Python. Nó trao đúng agent loop mà CLI dùng (đọc file, sửa file, tool use) nhưng dưới quyền điều khiển của bạn. Đây chính là thứ query_hook.js (bài "hai hook thực chiến") dùng để một Claude review một Claude khác.

⚠️ Freshness — tên package đã đổi: video khoá dùng tên cũ không còn chạy. Package hiện hành là @anthropic-ai/claude-agent-sdk. Đừng nhầm với @anthropic-ai/claude-code — đó là CLI, không import được.

Cài đặt

mkdir sdk-demo && cd sdk-demo
npm init -y
npm install @anthropic-ai/claude-agent-sdk

Ví dụ tối giản

Tạo index.mjs:

import { query } from "@anthropic-ai/claude-agent-sdk";

const prompt = "List the files in the current directory";

for await (const message of query({ prompt })) {
  console.log(JSON.stringify(message, null, 2));
}

Chạy node index.mjs → thấy một stream JSON messages — đúng các conversation event như trong CLI: tool call, tool result, và text của Claude. (query() trả về một async iterator, for await để duyệt.)

Giới hạn tool — allowedTools

Mặc định SDK có full tool set. Thu hẹp bằng allowedTools:

for await (const message of query({
  prompt,
  options: { allowedTools: ["Read", "Glob"] },
})) {
  // ...
}

Đây là bản SDK của flag --allowedTools trên CLI (và cùng tinh thần allowed_tools trong GitHub Actions).

⚠️ Đính chính (docs 09/2026) — allowedTools KHÔNG thu hẹp tool set. Đây là chỗ khoá nói ngược với docs, và là loại sai nguy hiểm vì nó tạo cảm giác an toàn giả. allowedTools là danh sách tự duyệt: tool có tên trong đó chạy không cần hỏi; tool không liệt kê vẫn khả dụng, lời gọi tới nó rơi về permission mode (có thể được hỏi, có thể chạy luôn). Ví dụ trên vì thế không giới hạn agent chỉ còn Read + Glob. Ba cách giới hạn thật:

  • tools — chỉ định bộ tool built-in có mặt trong session (tương đương cờ --tools trên CLI).
  • disallowedTools — đưa tên tool vào đây để chặn hẳn, Claude không với tới được.
  • allowedTools + permissionMode: "dontAsk" — tool trong danh sách được duyệt, mọi lời gọi khác lẽ ra phải hỏi thì bị từ chối. Lưu ý các thao tác vốn không cần hỏi (đọc file trong working directory, lệnh Bash read-only) vẫn chạy.
options: {
  allowedTools: ["Read", "Glob"],
  permissionMode: "dontAsk",
}

Cùng một bẫy có ở CLI: docs của --allowedTools ghi rõ "To restrict which tools are available, use --tools instead".

Còn gì nữa

SDK làm được mọi thứ CLI làm: custom system prompts, MCP servers, hooks, subagents, và session resumption. Xem Agent SDK documentation cho reference đầy đủ.

Đặt vào dải tự động hoá ở mục trên, SDK là nấc cuối — dùng khi công việc thuộc về sản phẩm của bạn. Cả TypeScript và Python đều phơi ra cùng một hàm query và cùng bộ primitive như CLI: truyền vào prompt + options (allowedTools để tự duyệt tool, tools / disallowedTools để giới hạn tool, một system prompt, và một permission mode), rồi lặp qua các message Claude stream về và xử lý theo cách app của bạn cần. Cùng một engine với CLI, chỉ khác là gọi được từ bên trong sản phẩm.

Áp dụng thực tế: SDK là cái seam biến Claude Code từ công cụ tương tác thành building block nhúng được vào hệ thống của mình. Ba góc tôi ghim: (1) vòng khép kín với bài hooks — query_hook.js nhúng thẳng SDK bên trong một hook, tức Claude Code gọi Claude Code; "AI reviews AI" chỉ là API này, không có gì huyền bí; (2) least-privilege cho agent phải đặt đúng cần gạt — allowedTools nghe như danh sách giới hạn, và khoá cũng dạy như vậy, nhưng nó chỉ tự duyệt. Cần gạt thu hẹp thật là tools / disallowedTools (CLI: --tools / --disallowedTools), hoặc allowedTools ghép dontAsk. Bài học delivery ở đây là tên tham số không phải hợp đồng — với thứ liên quan quyền, đọc docs của đúng tham số đó trước khi tin; (3) kỷ luật chi phí — mỗi query() là một lượt model tính tiền; một hook gọi query() mỗi lần edit (như query_hook) nhân chi phí âm thầm, nên production phải bọc rate/spend guard. Và cái bẫy tên package claude-code (CLI) vs claude-agent-sdk (thư viện) đúng bằng comment cảnh báo trong sdk.ts của sandbox — import nhầm là fail ngay.


Phần tiếp theo: Claude Code: custom command & skill

Nguồn: Claude Code in Action (Anthropic Academy) — Copyright Anthropic. Phần đề thi thử cho khoá này nằm ở tab "Đề thi thử" trên trang tổng quan khoá.

Câu hỏi thường gặp

Routine trong Claude Code là gì và nó gói những gì?
Routine là cách trực tiếp nhất để tự động hoá một task lặp lại: không script, không server. Nó gói ba thứ — một prompt, repository nó làm việc trên đó, và các connector nó cần — rồi chạy cái gói đó trên cloud mỗi khi được kích hoạt. Điểm mấu chốt là hạ tầng thuộc về Anthropic: không có máy nào của bạn phải bật suốt đêm và không có workflow file nào phải maintain. Nó fire theo ba loại trigger: cron schedule (ví dụ 9 giờ sáng mỗi ngày), HTTP POST tới API endpoint của nó để code của bạn tự kích hoạt, hoặc GitHub event như có pull request mới.
Tạo một routine bằng cách nào?
Hai cửa vào, cùng một thứ. Từ web tại claude.ai/code/routines: đặt tên, viết instruction mô tả Claude phải làm gì trong mỗi session, chọn repository, chọn trigger. Hoặc ngay trong Claude Code khỏi rời terminal: chạy lệnh /schedule rồi mô tả bằng lời thường, ví dụ "/schedule daily dependency audit at 9am".
Ba giới hạn cần biết trước khi dựa vào routine là gì?
Một, routine đang là research preview nên hành vi và giới hạn sẽ còn thay đổi. Hai, một recurring schedule chạy nhiều nhất là mỗi giờ một lần — cần dày hơn thì routine không phải công cụ cho việc đó. Ba, mỗi lần chạy bắt đầu từ một fresh clone của default branch và chỉ push được lên các branch có prefix claude/ trừ khi bạn nới ra theo từng repo; đây chính là guardrail giữ cho một lần chạy tự chủ không viết đè lên main. Docs 09/2026 đã nới vế cuối: khi prompt chỉ định branch khác, Claude vẫn push được, trừ khi branch đó được bảo vệ trên GitHub, đang có PR mở của người khác, hoặc chứa commit của người khác — nên muốn giữ main an toàn thì bật branch protection.
Headless mode là gì và cờ -p làm gì?
Headless mode dùng khi công việc cần môi trường của chính bạn, hoặc cần logic bọc quanh lần chạy — thứ mà routine chạy trên cloud không lo được. Cốt lõi là cờ -p (viết tắt của --print): nó chạy Claude Code như một lệnh one-shot không có UI tương tác, đọc standard in và ghi standard out, nên pipe được như mọi tool shell khác. Theo khoá, -p còn bỏ qua auto-discovery của hook, skill, plugin, MCP server và CLAUDE.md, nên bạn chỉ có Claude cộng đúng bộ tool cho phép tường minh và khởi động nhanh hơn nhiều. Lưu ý freshness: docs hiện hành gán việc bỏ auto-discovery cho cờ --bare, còn claude -p trơn vẫn nạp context như một session tương tác — đi làm thì gõ --bare cho chắc.
Làm sao nhận lại dữ liệu có cấu trúc từ headless mode?
Ghép một JSON schema với JSON output format: --output-format json cùng --json-schema. Claude sẽ ràng buộc output khớp schema của bạn, và object khớp schema nằm ở field structured_output trong JSON response. Móc nó ra bằng jq (ví dụ jq '.structured_output.functions') rồi đẩy vào database hay script khác. Đây là điểm mấu chốt để tự động hoá: văn xuôi thì không ghép vào hệ khác được, JSON có schema thì được.
Khi nào dùng routine, khi nào -p, khi nào --bare, khi nào Agent SDK?
Routine là mặc định cho việc lặp — chạy trên hạ tầng Anthropic, không phải host gì. Headless -p dành cho lúc công việc cần pipeline của bạn và bạn muốn đẩy dữ liệu qua một script. --bare là deterministic mode, dùng khi CI cần đúng một kết quả ở mọi lần chạy — hiểu đúng là môi trường tất định (không nạp hook, plugin, CLAUDE.md của máy chạy), còn câu trả lời của model vẫn có thể khác nhau giữa các lần. Agent SDK dành cho khi công việc thuộc về sản phẩm của bạn, nhúng Claude Code vào app TypeScript hoặc Python. Nguyên tắc: bắt đầu bằng routine, chỉ tụt xuống dải dưới khi công việc thật sự cần thêm quyền kiểm soát.
Làm sao chạy một automation nhiều bước bằng headless mode?
Khỏi nhồi mọi thứ vào một lệnh. Bắt lấy session ID từ JSON output rồi resume nó sau: claude --resume "$(jq -r .session_id /tmp/plan.json)". Một script khởi động công việc, một script khác resume nó sau với đầy đủ context. Rất hợp khi lượt đầu sinh ra một plan còn lượt sau thi hành plan đó.
Agent SDK là gì và dùng được với ngôn ngữ nào?
Agent SDK cho phép chạy Claude Code programmatically từ chính app hay script của bạn — có cho TypeScript và Python. Nó trao đúng agent loop mà CLI dùng (đọc file, sửa file, tool use) nhưng dưới quyền điều khiển của bạn. Bạn gọi query({ prompt }) và duyệt kết quả như một async iterator; nó stream ra các JSON message giống hệt event trong CLI: tool call, tool result, và text của Claude. SDK hỗ trợ đủ những gì CLI làm: custom system prompt, MCP server, hooks, subagents, và session resumption.
Package Agent SDK tên là gì, và điểm dễ nhầm ở đâu?
Package hiện hành là @anthropic-ai/claude-agent-sdk (cài bằng npm install @anthropic-ai/claude-agent-sdk). Điểm dễ nhầm: gói tên gần giống @anthropic-ai/claude-code CHÍNH LÀ CLI, không import được vào code. Video cũ của khoá dùng tên package cũ nay đã đổi và không còn chạy — nhớ dùng claude-agent-sdk.
Làm sao giới hạn tool khi dùng Agent SDK?
Khoá dạy: mặc định SDK có full tool set, muốn thu hẹp thì truyền options.allowedTools, ví dụ ["Read", "Glob"], như bản SDK của flag --allowedTools. Nhưng theo docs 09/2026, allowedTools chỉ là danh sách TỰ DUYỆT: tool có tên trong đó chạy không cần hỏi, còn tool không liệt kê vẫn khả dụng và rơi về permission mode. Muốn giới hạn thật thì dùng option tools để chỉ định bộ tool built-in có mặt, thêm tool vào disallowedTools để chặn hẳn, hoặc ghép allowedTools với permissionMode "dontAsk" để mọi thứ ngoài danh sách bị từ chối thay vì hỏi.