Claude Agent SDK · Agent Loop

Model chọn hành động. Runtime của bạn quyết định hành động đó có được chạy hay không. The model picks the action. Your runtime decides whether it is allowed to run.

Chín khái niệm dựng nên vòng lặp agent, chia theo bốn nhóm: vòng lặp, kiểm soát, giới hạn, trạng thái. Bấm vào một khái niệm để nhảy tới. Nine concepts that make up the agent loop, in four groups: loop, control, limits, state. Tap one to jump.

Agent loop Prompt goes to Claude. Claude either finishes with a result, or requests a tool. A tool request passes through six permission steps before the tool runs, and the tool result returns to Claude as input for the next decision. prompt + options Claude AssistantMessage không còn tool call no tool call left ResultMessage subtype · cost · turns Sáu bước xét quyền Six permission steps 1 hooks 2 deny · 3 ask 4 mode · 5 allow 6 canUseTool Read · Bash · MCP tool result · UserMessage gọi tool tool call được duyệt approved kết quả thành input của quyết định kế tiếp the result feeds the next decision

Nét liền: luồng cố định. Nét đứt: nhánh chỉ được quyết định lúc chạy — model chọn có gọi tool hay không, runtime chọn có cho chạy hay không. Solid: fixed flow. Dashed: branches decided only at runtime — the model chooses whether to call a tool, the runtime chooses whether to let it run.

Chọn cái nàoWhat to choose

Trước hết: rất nhiều việc không cần đến bất kỳ thứ gì bên dưới. First: a lot of work needs none of what follows.

Một lượt gọi, không tool — tóm tắt, phân loại, trích xuất, viết lại. Gọi thẳng messages.create(). Rẻ hơn, nhanh hơn, không cần cài Claude Code. One call, no tools — summarizing, classifying, extracting, rewriting. Call messages.create() directly. Cheaper, faster, no Claude Code install.

Biết trước thứ tự các bước — cái bạn cần là một hàm, không phải agent. Nhét việc xác định vào agent loop chỉ biến nó thành việc xác suất, đắt hơn vài chục lần. The step order is known in advance — you want a function, not an agent. Wrapping deterministic work in an agent loop makes it probabilistic and an order of magnitude more expensive.

Thứ tự phụ thuộc dữ liệu nhưng nhánh đếm được — viết tool use thủ công. Một vòng while ba mươi dòng quanh API là đủ, và bạn giữ toàn quyền. Order depends on data but branches are countable — hand-roll tool use. A thirty-line while loop around the API is enough, and you keep full control.

Agent SDK đáng giá từ chỗ số bước không đoán trước được, agent phải chạm filesystem thật, phiên cần dừng rồi chạy tiếp, và bạn cần hàng rào quyền mà đội bảo mật chấp nhận. The Agent SDK earns its place once the step count is genuinely unpredictable, the agent touches a real filesystem, sessions need to pause and resume, and you need a permission boundary your security team will accept.

Model có cần quyết định làm gì tiếp theo không?
├─ Không ──▶ viết hàm bình thường. Dừng.
└─ Có
   │
   Số bước có đoán trước được không?
   ├─ Có ──▶ tool use thủ công qua Messages API. Dừng.
   └─ Không
      │
      Agent có chạm file / shell / hệ thống thật không?
      ├─ Không ──▶ Agent SDK, allowed_tools = [] hoặc chỉ tool MCP của bạn
      └─ Có
         │
         Có người ngồi canh không?
         ├─ Có ──▶ permission_mode="default" + canUseTool
         └─ Không (headless)
            │
            ├─ allowed_tools    = danh sách tối thiểu
            ├─ permission_mode  = "dontAsk"
            ├─ disallowed_tools = ["Bash(rm *)", ...]   ← chốt chặn cứng
            ├─ max_turns + max_budget_usd               ← trần chi phí
            └─ hook PreToolUse                          ← luật không được thủng
Does the model need to decide what happens next?
├─ No ──▶ write an ordinary function. Stop.
└─ Yes
   │
   Is the number of steps predictable?
   ├─ Yes ──▶ hand-rolled tool use on the Messages API. Stop.
   └─ No
      │
      Does the agent touch real files / shell / systems?
      ├─ No ──▶ Agent SDK, allowed_tools = [] or your MCP tools only
      └─ Yes
         │
         Is a human watching?
         ├─ Yes ──▶ permission_mode="default" + canUseTool
         └─ No (headless)
            │
            ├─ allowed_tools    = the minimum list
            ├─ permission_mode  = "dontAsk"
            ├─ disallowed_tools = ["Bash(rm *)", ...]   ← hard stops
            ├─ max_turns + max_budget_usd               ← cost ceiling
            └─ a PreToolUse hook                        ← rules that cannot leak

Chạy headless mà thiếu bất kỳ dòng nào trong bốn dòng cuối thì chưa sẵn sàng cho production. Running headless without any of those last four lines means you are not production-ready.

Tra cứuReference

Chín khái niệm, mỗi khái niệm một câu đánh đổi. Nine concepts, one trade-off sentence each.

vòng lặploop

Vòng lặp agentThe agent loop query()

Một async generator sở hữu toàn bộ chu trình model → tool → model, và stream mọi message trung gian ra cho bạn xem. An async generator that owns the whole model → tool → model cycle and streams every intermediate message back to you.

Dùng choUse for

  • Bot sửa build đỏ trong CIA bot that fixes red CI builds
  • Migration qua hàng trăm repo khác cấu trúcMigrations across hundreds of differently shaped repos
  • Trợ lý tự viết và chạy script để lấy số thậtAn assistant that writes and runs scripts to get real numbers

ĐượcYou gain

  • Bộ tool đã mài giũa qua Claude CodeA toolset hardened by Claude Code
  • Transcript JSONL ghi sẵn ra đĩaJSONL transcripts written to disk by default
  • Chi phí thật trong mỗi runReal spend reported per run

MấtYou lose

  • Phụ thuộc binary Claude Code, khó debugA Claude Code binary dependency, hard to debug
  • Mặc định mở toàn bộ toolThe default opens every tool
  • Transcript chứa mọi thứ agent nhìn thấyTranscripts hold everything the agent saw

Chọn query() là đổi quyền kiểm soát từng bước của vòng lặp lấy việc không bao giờ phải bảo trì nó. Choosing query() trades step-by-step control of the loop for never having to maintain it.

Dấu hiệu: bạn đang tự viết vòng while quanh messages.create() để nối kết quả tool. Tell: you are writing a while loop around messages.create() to splice tool results back in.

vòng lặploop

Lượt — đơn vị đếmThe turn — the unit of counting

Một vòng khép kín: model quyết định, tool chạy, kết quả quay về model. Đếm theo mỗi lần quay lại model, không phải mỗi lần gọi tool. One closed circuit: the model decides, a tool runs, the result returns. It counts per return to the model, not per tool call.

Dùng choUse for

  • Trần cho agent chạy không người canhA ceiling on unattended agents
  • Phát hiện agent kẹt vòng lặpDetecting stuck loops
  • So sánh hai bản promptComparing two prompt versions

ĐượcYou gain

  • Một số chặn được cả tiền lẫn thời gianOne number caps both money and time
  • Có sẵn trong mọi ResultMessagePresent in every ResultMessage
  • Chỉ số hồi quy tốt khi đổi promptA good regression signal for prompt changes

MấtYou lose

  • Lượt sau luôn đắt hơn lượt trướcLater turns always cost more than earlier ones
  • Chạm trần là cắt ngang, không kết thúc gọnHitting the ceiling cuts mid-work
  • Không phản ánh khối lượng việc thậtIt does not reflect real work done

Chọn giới hạn lượt là đổi khả năng hoàn thành việc dài bất thường lấy sự chắc chắn rằng không run nào chạy vô hạn. A turn limit trades the ability to finish unusually long tasks for the certainty that no run continues forever.

Dấu hiệu: hoá đơn tăng nhanh hơn số việc agent làm được. Tell: the bill grows faster than the work the agent completes.

vòng lặploop

Bốn loại messageThe four message types

System khởi tạo phiên, Assistant là Claude nói hoặc đòi tool, User là kết quả tool đưa ngược vào, Result là message cuối cùng. System sets up the session, Assistant is Claude speaking or requesting a tool, User carries a tool result back in, Result is the last message.

Dùng choUse for

  • Hiển thị tiến trình theo thời gian thựcLive progress instead of a spinner
  • Audit trail từng lời gọi toolAn audit trail of every tool call
  • Lấy session_id ngay lượt đầuCapturing session_id on the first pass

ĐượcYou gain

  • Bốn loại, ranh giới rõ, không trạng thái ẩnFour types, clean boundaries, no hidden state
  • UI streaming không cần API riêngStreaming UIs with no separate API
  • Cùng hình dạng ở Python và TypeScriptThe same shapes in Python and TypeScript

MấtYou lose

  • Nội dung là mảng block, luôn phải duyệtContent is an array of blocks, always iterate
  • Kết quả tool mang vai "user", dễ nhầmTool results carry the "user" role, which misleads
  • Trường có sẵn khác nhau giữa các subtypeAvailable fields differ across subtypes

Chọn đọc cả luồng message là đổi code xử lý dài dòng hơn lấy khả năng nhìn thấy mọi thứ agent làm, không chỉ kết quả. Consuming the whole stream trades more handling code for seeing everything the agent does, not just its answer.

Dấu hiệu: code có messages[-1].result mà không kiểm tra subtype. Tell: your code has messages[-1].result with no subtype check.

kiểm soátcontrol

Phạm vi toolTool scope allowed_tools

Hai danh sách không đối xứng. Đây là hiểu nhầm tốn kém nhất trong cả chủ đề. Two asymmetric lists. This is the most expensive misunderstanding in the whole subject.

allowed_tools=["Read","Grep"]      Read, Grep tự duyệt.
                                   Tool khác VẪN CÒN, rơi xuống
                                   permission_mode.

disallowed_tools=["Bash"]          Định nghĩa Bash bị gỡ khỏi request.
                                   Claude không nhìn thấy.

disallowed_tools=["Bash(rm *)"]    Bash vẫn còn. Lệnh khớp bị chặn ở
                                   MỌI mode, kể cả bypassPermissions.
allowed_tools=["Read","Grep"]      Read and Grep auto-approved.
                                   Other tools STILL EXIST, falling
                                   through to permission_mode.

disallowed_tools=["Bash"]          The Bash definition is stripped.
                                   Claude never sees it.

disallowed_tools=["Bash(rm *)"]    Bash stays. Matching calls denied in
                                   EVERY mode, bypassPermissions too.

Dùng choUse for

  • Agent chỉ đọc: allow list + dontAskRead-only agents: an allow list plus dontAsk
  • Chặn vĩnh viễn nhóm lệnh phá huỷPermanently blocking destructive commands
  • Giới hạn agent vào đúng một MCP serverRestricting an agent to one MCP server

ĐượcYou gain

  • Luật deny thắng cả bypassPermissionsDeny rules beat even bypassPermissions
  • Deny tên trần còn giảm token system promptBare-name denies also cut prompt tokens
  • Khai báo được trong settings, review như codeDeclarable in settings and reviewable like code

MấtYou lose

  • Sự bất đối xứng gây hiểu nhầm âm thầmThe asymmetry misleads silently
  • Glob chỉ có tác dụng sau tiền tố mcp__Globs only work after an mcp__ prefix
  • Luật Write(path) không bao giờ khớpWrite(path) rules never match

Chọn danh sách tool tối thiểu là đổi một số việc agent lẽ ra làm được lấy một bề mặt tấn công đủ nhỏ để đọc hết trong một lần. A minimal tool list trades some things the agent could do for an attack surface small enough to read in one sitting.

Dấu hiệu: bạn nói "agent này chỉ đọc thôi" nhưng config không có dòng disallowed_tools nào. Tell: you say "this agent only reads" and your config has no disallowed_tools line.

kiểm soátcontrol

Permission mode và thứ tự xét quyềnPermission modes and evaluation order

Mode chỉ là một trong sáu bước. Thứ tự sáu bước mới là thứ quyết định hành vi thật. The mode is only one of six steps. The order of those steps is what actually determines behavior.

1 hook        deny ở đây thắng tất cả; allow KHÔNG bỏ qua bước 2, 3
2 deny        khớp → chặn, kể cả trong bypassPermissions
3 ask         khớp → rơi xuống canUseTool
4 mode        bypassPermissions duyệt ngay tại đây
5 allow       allowed_tools + settings.json
6 canUseTool  callback của bạn; dontAsk bỏ qua bước này và từ chối

hệ quả: tool được duyệt sớm KHÔNG BAO GIỜ chạm tới canUseTool
1 hooks       a deny here beats all; an allow does NOT skip steps 2, 3
2 deny        match → blocked, even under bypassPermissions
3 ask         match → falls through to canUseTool
4 mode        bypassPermissions approves right here
5 allow       allowed_tools + settings.json
6 canUseTool  your callback; dontAsk skips it and denies instead

consequence: anything approved early NEVER reaches canUseTool

Dùng choUse for

  • Headless production: allow list + dontAskHeadless production: allow list plus dontAsk
  • Có người canh: default + canUseToolHuman in the loop: default plus canUseTool
  • Review trước khi thực thi: planReview before execution: plan

ĐượcYou gain

  • Một tham số đổi được thái độ cả hệ thốngOne parameter shifts the whole system's posture
  • Đổi mode giữa phiên khi đã tin agentMid-session mode changes as trust builds
  • dontAsk biến "không ai trả lời" thành từ chốidontAsk turns "nobody is here" into a denial

MấtYou lose

  • Thứ tự phản trực giác, runtime không cảnh báoA counterintuitive order with no runtime warning
  • canUseTool bị vô hiệu âm thầm với tool đã allowcanUseTool silently skipped for allow-listed tools
  • Subagent thừa kế mode lỏng, không siết lại đượcSubagents inherit loose modes and cannot be tightened

Chọn một mode dễ dãi là đổi khả năng kiểm soát từng hành động lấy tốc độ chạy không gián đoạn — và cái giá đó phải trả bằng môi trường cách ly, không phải bằng niềm tin. A permissive mode trades control over individual actions for uninterrupted speed — a price to be paid with an isolated environment, not with trust.

Dấu hiệu: bạn dùng bypassPermissions trên máy có dữ liệu bạn không sẵn sàng mất. Tell: you run bypassPermissions on a machine holding data you are not prepared to lose.

kiểm soátcontrol

Hooks

Callback của bạn, chạy trong process của bạn, gọi tại các mốc trong vòng đời agent. Bạn không thuyết phục model nữa; bạn chặn nó. Your callbacks, running in your process, invoked at points in the agent lifecycle. You are no longer persuading the model; you are stopping it.

Dùng choUse for

  • Chặn đọc .env và đường dẫn credentialBlocking .env and credential paths
  • Ép mọi thao tác ghi vào thư mục sandboxForcing all writes into a sandbox directory
  • Lưu transcript trước khi PreCompact xoá bớtArchiving transcripts before PreCompact trims them

ĐượcYou gain

  • Chạy trước mọi bước; deny thắng mọi modeThey run first; a deny beats every mode
  • Không tốn context tokenThey cost no context tokens
  • Truy cập được DB, IAM, secret store của bạnAccess to your DB, IAM, and secret store

MấtYou lose

  • Có thể không kịp bắn khi chạm max_turnsThey may not fire when max_turns is hit
  • Matcher chỉ khớp tên tool, không khớp tham sốMatchers match tool names only, not arguments
  • Exception không bắt có thể ngắt cả agentAn uncaught exception can interrupt the agent

Chọn hook là đổi việc phải viết và bảo trì code kiểm soát thật lấy những đảm bảo mà lời nhắc không bao giờ cho được. Hooks trade writing and maintaining real control code for guarantees a prompt can never give you.

Dấu hiệu: trong system prompt của bạn có câu "tuyệt đối không được sửa file trong X" — đó là một luật, và luật thuộc về hook. Tell: your system prompt says "never modify files under X" — that is a rule, and rules belong in hooks.

giới hạnlimits

Ngân sáchBudgets max_turns · max_budget_usd

Hai cầu dao, không phải bộ điều tốc. Chúng không làm agent tiết kiệm hơn; chúng cắt điện khi vượt ngưỡng. Two circuit breakers, not governors. They do not make the agent thriftier; they cut power past a threshold.

Dùng choUse for

  • Agent chạy theo lịch, ban đêm, không người canhScheduled overnight agents with nobody watching
  • Sản phẩm cho người dùng cuốiEnd-user products
  • Thử agent mới trên dữ liệu thật, trần thấpTrying a new agent on real data with a low ceiling

ĐượcYou gain

  • Chi phí xấu nhất là con số biết trướcWorst-case cost becomes a known number
  • total_cost_usd cho số thật để hiệu chỉnhtotal_cost_usd gives real figures to calibrate against
  • Hai trục độc lập: lượt và tiềnTwo independent axes: turns and money

MấtYou lose

  • Cắt ngang; trạng thái dở dang là bình thườngA mid-work cut; partial state is the norm
  • Chỉ tính chi phí đã phát sinh, không phải sắp phát sinhThey count cost already spent, never cost about to be
  • Trần quá chặt tạo tiếng ồn cảnh báoTight ceilings create alert noise

Chọn trần chi phí là đổi khả năng hoàn tất những việc đắt bất thường lấy việc không bao giờ phải giải thích một hoá đơn. A cost ceiling trades finishing unusually expensive tasks for never having to explain an invoice.

Dấu hiệu: bạn không trả lời ngay được câu "một run tốn nhiều nhất bao nhiêu". Tell: you cannot immediately answer "what is the most one run can cost?"

giới hạnlimits

Kết thúcTermination ResultMessage

Message cuối cùng mang theo lý do dừng. Đây là chỗ ứng dụng của bạn phân nhánh. The last message carries the reason it stopped. This is where your application branches.

success                             xong → đọc result
error_max_turns                     chạm trần lượt → resume, trần cao hơn
error_max_budget_usd                chạm trần tiền → resume, trần cao hơn
error_during_execution              hỏng thật → điều tra, đừng retry mù
error_max_structured_output_retries schema sai → sửa schema

chỉ đọc `result` khi subtype == "success"
success                             done → read result
error_max_turns                     turn ceiling → resume, higher ceiling
error_max_budget_usd                spend ceiling → resume, higher ceiling
error_during_execution              really broke → investigate, no blind retry
error_max_structured_output_retries bad schema → fix the schema

only read `result` when subtype == "success"

Dùng choUse for

  • Retry có điều kiện thay vì bắt exception chungConditional retries instead of a generic catch
  • Bảng theo dõi sức khoẻ agent theo ngàyA daily agent health dashboard
  • Phát hiện quyền sai qua permission_denialsSpotting bad permissions via permission_denials

ĐượcYou gain

  • Phân loại lỗi sẵn có, không parse chuỗiError classification with no string parsing
  • session_id có ngay trong message lỗisession_id ships inside the error message
  • Chi phí và thời lượng cùng chỗ với trạng tháiCost and duration sit next to status

MấtYou lose

  • success không có nghĩa là agent làm đúng việcsuccess does not mean the agent did the right thing
  • Tập trường khác nhau giữa các subtypeField sets differ across subtypes
  • error_during_execution gộp nhiều nguyên nhânerror_during_execution collapses many causes

Chọn phân nhánh theo subtype là đổi thêm code xử lý lỗi lấy khả năng phân biệt "hết hạn mức" với "hỏng thật" — hai thứ cần hai cách chữa ngược nhau. Branching on subtype trades extra error-handling code for telling "out of budget" apart from "actually broken" — two conditions with opposite remedies.

Dấu hiệu: log lỗi của bạn chỉ có một dòng "agent failed". Tell: your error log has one line, "agent failed".

trạng tháistate

PhiênSessions session_id · resume · fork

Mỗi lần chạy tích luỹ một phiên và SDK ghi nó ra đĩa dưới dạng JSONL. session_id là chìa khoá quay lại. Every run accumulates a session and the SDK writes it to disk as JSONL. The session_id is your key back in.

Dùng choUse for

  • Chạy tiếp sau khi chạm trần, không trả tiền lạiContinuing after a ceiling without paying twice
  • Việc nhiều giai đoạn qua nhiều ngàyMulti-stage work across days
  • Fork để thử hai hướng từ cùng điểm khảo sátForking to try two approaches from one starting point

ĐượcYou gain

  • Resume rẻ hơn chạy lại rất nhiềuResuming is far cheaper than rerunning
  • Transcript trên đĩa là audit trail có sẵnThe on-disk transcript is a ready-made audit trail
  • continue xử lý ca phổ biến, khỏi quản idcontinue covers the common case with no id management

MấtYou lose

  • Transcript là dữ liệu nhạy cảm, không mã hoáTranscripts are sensitive data, unencrypted
  • Nén lịch sử làm mất chi tiết, khó kiểm soát lúc nàoCompaction loses detail on a schedule you do not control
  • Phiên dài mang theo cả sai lầm cũLong sessions carry old mistakes with them

Chọn phiên bền là đổi việc phải quản lý và bảo vệ trạng thái trên đĩa lấy khả năng dừng lại, suy nghĩ, rồi đi tiếp mà không mất những gì đã làm. Durable sessions trade managing and protecting state on disk for the ability to stop, think, and continue without losing work.

Dấu hiệu: agent đọc lại cùng một tập file ở mỗi lần chạy. Tell: your agent rereads the same set of files on every run.

Đối chiếuComparison

Trục thật của chủ đề không phải nhanh hay rẻ, mà là: chặn được ở đâu, và có sống sót qua bypassPermissions không. The real axes here are not speed or cost, but: where it blocks, and whether it survives bypassPermissions.

Cơ chếMechanism Chặn ở bướcBlocks at step Chạy ở đâuRuns where Tốn contextCosts context Sống qua bypassSurvives bypass Giá phải trảPrice
System promptSystem prompt không chặn, chỉ khuyêndoesn't block, advises trong contextin context có, nhiềuyes, a lot khôngno model có thể lờ đithe model can ignore it
allowed_tools bước 5, chỉ tự duyệtstep 5, auto-approval only cấu hình tĩnhstatic config khôngno khôngno dễ tưởng nhầm là giới hạneasily mistaken for a restriction
disallowed_tools (tên trần)(bare name) trước bước 1, gỡ toolbefore step 1, tool removed cấu hình tĩnhstatic config tiết kiệmsaves tokens cóyes agent mất hẳn năng lực đóthe capability is gone entirely
disallowed_tools (có phạm vi)(scoped) bước 2step 2 cấu hình tĩnhstatic config khôngno cóyes phải viết đúng mẫuthe pattern must be right
permission_mode bước 4step 4 cấu hình tĩnhstatic config khôngno chính nóit is the mode toàn cục, không tinhglobal, not fine-grained
canUseTool bước 6step 6 process của bạnyour process khôngno phần lọt xuốngfor what falls through bị bỏ qua với tool đã allowskipped for allow-listed tools
PreToolUse hook bước 1step 1 process của bạnyour process không, trừ phần trả vềno, except what it returns cóyes phải viết và bảo trì codecode you write and maintain
max_turns · max_budget_usd chặn phiên, không chặn toolends the session, not the tool runtime khôngno cóyes cắt ngang giữa chừngcuts mid-work

Đọc theo cột "sống qua bypass": chỉ ba cơ chế là ràng buộc cứng — luật deny, hook, và trần ngân sách. Mọi thứ còn lại là thoả thuận. Read the "survives bypass" column: only three mechanisms are hard constraints — deny rules, hooks, and budget ceilings. Everything else is an agreement.

Anti-patterns

Sáu sai lầm gặp nhiều nhất, và cách sửa. The six most common mistakes, and how to fix them.

Sai lầmMistake Vì sao saiWhy it's wrong Sửa thế nàoFix
Dùng allowed_tools như danh sách giới hạnUsing allowed_tools as a restriction list Nó là danh sách tự duyệt; tool không có tên trong đó vẫn tồn tạiIt is an auto-approval list; unlisted tools still exist Thêm disallowed_tools, hoặc dùng dontAskAdd disallowed_tools, or use dontAsk
allowed_tools=["Read"] kèm bypassPermissionsallowed_tools=["Read"] with bypassPermissions Bypass duyệt ở bước 4, trước cả luật allow; Bash và Write vẫn chạyBypass approves at step 4, before allow rules; Bash and Write still run Đổi sang dontAsk, hoặc liệt kê deny cụ thểSwitch to dontAsk, or list explicit denies
Viết luật an toàn vào system promptWriting safety rules into the system prompt Prompt là gợi ý, không phải ràng buộcA prompt is a suggestion, not a constraint Chuyển thành hook PreToolUse trả denyMove it into a PreToolUse hook that denies
Đặt kiểm tra bảo mật trong canUseToolPutting security checks in canUseTool Tool đã được luật allow duyệt không bao giờ tới bước 6Tools approved by an allow rule never reach step 6 Chuyển sang hook PreToolUseMove the check into a PreToolUse hook
Dọn dẹp trong hook StopCleaning up in a Stop hook Hook có thể không kịp bắn khi phiên bị cắt vì max_turnsIt may not fire when the session is cut by max_turns Dọn ở phía gọi, sau khi luồng message kết thúcClean up on the calling side, after the stream ends
Retry từ đầu khi chạm trầnRetrying from scratch after a ceiling error Trả tiền hai lần và có thể lặp lại thao tác ghiPays twice and may repeat writes resume đúng phiên với trần cao hơnresume the same session with a higher ceiling

Ba câu cần nhớThree sentences to remember

Nếu chỉ giữ lại được ba câu. If you keep only three.

  1. Model chọn hành động, runtime của bạn quyết định hành động đó có được chạy hay không. Mọi thứ khác chỉ là chi tiết của câu này. The model picks the action and your runtime decides whether it runs. Everything else is detail attached to that sentence.
  2. allowed_tools là danh sách tự duyệt chứ không phải danh sách giới hạn. Muốn cấm thật thì dùng disallowed_tools hoặc hook, vì chỉ hai thứ đó sống sót qua bypassPermissions. allowed_tools is an auto-approval list, not a restriction list. Real prohibitions need disallowed_tools or hooks, because only those survive bypassPermissions.
  3. Luật an toàn thuộc về code, không thuộc về prompt: hook chạy trước mọi bước xét quyền, không tốn context token, và một lệnh deny ở đó thắng mọi permission mode. Safety rules belong in code, not prompts: hooks run before every permission step, cost no context tokens, and a deny there beats every mode.