Learn > Claude > CCA-F Domain 1: Agentic Architecture & Orchestration

CCA-F Domain 1: Agentic Architecture & Orchestration

Ghi chú ôn thi CCA-F Domain 1: Thiết kế agentic loops, điều phối multi-agent, spawn subagents, prerequisite hooks và quản lý session state.

  • Thiết kế vòng lặp agentic loop dựa trên stop_reason ("tool_use" vs "end_turn") thay vì kiểm tra text thô.
  • Phân tách và điều phối hệ thống multi-agent theo mô hình Hub-and-Spoke với context cô lập giữa coordinator và subagents.
  • Áp dụng các hook chặn tool call để cưỡng chế quy chuẩn nghiệp vụ một cách tất định (deterministic enforcement).

TL;DRDomain 1 (chiếm 27% đề thi) tập trung vào cách thiết kế vòng lặp tự chủ (agentic loop) và cấu trúc điều phối nhiều tác nhân (multi-agent). Điểm cốt lõi cần nhớ: subagent luôn chạy trong ngữ cảnh cô lập (isolated context), và mọi cơ chế kiểm soát an toàn bắt buộc phải dùng code (hooks) thay vì chỉ dùng prompt.


Task 1.1: Thiết kế và triển khai agentic loop cho thực thi tác vụ tự chủ

Kiến thức cần nắm

  • Vòng đời agentic loop: Gửi request tới Claude, kiểm tra stop_reason ("tool_use" vs "end_turn"), thực thi tool được yêu cầu, trả kết quả về cho vòng lặp tiếp theo.
  • stop_reason KHÔNG chỉ có hai giá trị: Exam Guide chỉ liệt kê "tool_use""end_turn", nhưng Messages API trả về bảy giá trị — thêm "max_tokens", "stop_sequence", "pause_turn", "refusal""model_context_window_exceeded". Giá trị bị hỏi nhiều nhất ngoài hai cái quen thuộc là "max_tokens": nó nghĩa là output bị cắt giữa chừng, phải xử lý khác hẳn "end_turn". Nền Messages API (messages, content block, max_tokens) nằm ở note Claude API cơ bản.
  • Nối kết lịch sử: Cách tool result được nối vào lịch sử hội thoại dưới vai trò user để model suy luận bước tiếp theo.
  • Mô hình dẫn dắt (Model-driven): Phân biệt quyết định do model dẫn dắt (Claude tự suy luận nên gọi tool nào dựa trên context) với decision tree / chuỗi tool cấu hình sẵn.

Kỹ năng cần làm được

  • Kiểm soát luồng: Cài đặt control flow tiếp tục khi stop_reason"tool_use", dừng khi "end_turn".
  • Nạp ngữ cảnh: Thêm tool result vào context giữa các vòng lặp để model tận dụng thông tin mới.
  • Tránh các anti-pattern: Đừng parse text thô của assistant để quyết định dừng loop (VD: dò chữ "DONE"), đừng lấy giới hạn số vòng lặp làm cơ chế dừng chính, và đừng coi câu chữ model viết ra là dấu hiệu đã xong việc.

🧠 Phân tích & Thực tế từ Delivery Manager:

Từ góc độ vận hành, một agentic loop sai lầm sẽ đốt tiền API cực kỳ nhanh hoặc bị treo vô hạn. Để đảm bảo hệ thống production chạy ổn định, mã nguồn phải điều khiển luồng dựa vào cấu trúc dữ liệu trả về của API, tuyệt đối không dùng logic phỏng đoán.

# Vòng lặp Agentic Loop chuẩn — điều khiển theo stop_reason
while True:
    response = client.messages.create(
        model="claude-sonnet-5",
        max_tokens=4096,          # BẮT BUỘC — thiếu là API trả lỗi, không phải tuỳ chọn
        messages=messages,
        tools=tools
    )
    # Ghi nhận phản hồi của trợ lý vào lịch sử
    messages.append({"role": "assistant", "content": response.content})

    if response.stop_reason == "tool_use":
        # Trích xuất và chạy các tool call được yêu cầu
        tool_results = []
        for block in response.content:
            if block.type == "tool_use":
                result = run_tool(block.name, block.input)
                tool_results.append({
                    "type": "tool_result",
                    "tool_use_id": block.id,
                    "content": result
                })
        # Gửi kết quả tool ngược lại cho Claude dưới vai trò user
        messages.append({"role": "user", "content": tool_results})
    elif response.stop_reason == "end_turn":
        break                     # Hoàn thành thật
    else:
        # max_tokens / stop_sequence / refusal / pause_turn...
        # Lượt này CHƯA XONG — xử lý riêng, tuyệt đối không coi như end_turn
        handle_incomplete(response.stop_reason)
        break
  • ⚠️ else: break là bẫy, không phải tắt cho gọn. Viết if tool_use ... else break nghĩa là mọi stop_reason không phải "tool_use" đều bị gộp chung với "end_turn". Khi model bị cắt vì chạm trần max_tokens, đoạn code đó coi câu trả lời cụt là hoàn thành rồi ghi thẳng vào kết quả — bug này im lặng, chỉ lộ ra ở production dưới dạng "thỉnh thoảng câu trả lời mất đuôi". Đề thi hỏi thẳng tình huống này: phải tách nhánh max_tokens ra và đánh dấu lượt đó là chưa hoàn tất.
  • Bẫy câu hỏi cần lưu ý: Đề thi sẽ hỏi về anti-pattern điều khiển vòng lặp. Luôn chọn đáp án tránh parse text thô (như if "DONE" in response.text) và tránh việc chỉ dùng giới hạn lặp làm logic dừng chính.

Task 1.2: Điều phối hệ multi-agent theo pattern coordinator–subagent

Kiến thức cần nắm

  • Kiến trúc Hub-and-Spoke: Coordinator quản lý toàn bộ giao tiếp giữa các subagent, xử lý lỗi và định tuyến thông tin.
  • Context cô lập: Subagent hoạt động với context cô lập — không tự động thừa hưởng lịch sử hội thoại hay memory của coordinator.
  • Vai trò coordinator: Phân rã task, uỷ quyền, gom kết quả, quyết định gọi subagent nào theo độ phức tạp câu hỏi.
  • Rủi ro phân rã quá hẹp: Coordinator chia nhỏ task quá sâu làm các subagent mất tầm nhìn tổng quan, dẫn tới bỏ sót phạm vi khi chủ đề nghiên cứu rộng.

Kỹ năng cần làm được

  • Chọn subagent động: Thiết kế coordinator phân tích yêu cầu và chọn subagent động thay vì luôn chạy cứng nhắc đủ cả pipeline.
  • Phân chia phạm vi: Chia phạm vi nghiên cứu giữa các subagent để giảm trùng lặp (giao subtopic hoặc loại nguồn tài liệu riêng cho từng agent).
  • Vòng lặp tinh chỉnh: Coordinator đánh giá output tổng hợp xem có lỗ hổng (gaps) không, uỷ quyền lại cho search/analysis với truy vấn nhắm đích, gọi lại synthesis đến khi đủ độ phủ.
  • Quan sát (Observability): Định tuyến mọi giao tiếp của subagent qua coordinator để có logging tập trung, xử lý lỗi nhất quán và kiểm soát luồng thông tin.

🧠 Phân tích & Thực tế từ Delivery Manager:

Trong các dự án lớn, việc gom tất cả prompt vào một agent duy nhất luôn dẫn đến việc agent bị "quá tải sự chú ý" và hoạt động chập chờn. Giải pháp Hub-and-Spoke giúp cô lập trách nhiệm. Tuy nhiên, rủi ro lớn nhất là điều phối (orchestration) kém: coordinator phân việc quá vụn vặt khiến báo cáo cuối cùng thiếu tính tổng hợp.


Task 1.3: Cấu hình gọi subagent, truyền context và spawning

Kiến thức cần nắm

  • Task tool: Đây là công cụ hệ thống để coordinator spawn (khởi tạo) subagent. Exam Guide viết allowedTools của coordinator bắt buộc phải chứa "Task" mới gọi được subagent — đi thi cứ trả lời theo câu này. Hai điểm cần biết thêm để không lệch với docs thật: tool nay đã đổi tên thành Agent (Task vẫn chạy như alias), và allowedToolstự động duyệt chứ không phải công tắc bật/tắt — xem đính chính ở cuối mục.
  • Context passing: Context của subagent phải được truyền tường minh trong prompt của nó — subagent không tự thừa hưởng context cha, không chia sẻ memory giữa các lần gọi.
  • Cấu hình AgentDefinition: description, system prompt, giới hạn tool (tools) cho từng loại subagent.
  • fork_session: Tạo nhánh độc lập từ một baseline phân tích chung để khám phá các hướng khác nhau.

Kỹ năng cần làm được

  • Truyền dữ liệu đầy đủ: Đưa đầy đủ kết quả của agent trước trực tiếp vào prompt của subagent (VD: truyền kết quả web search + phân tích tài liệu cho synthesis subagent).
  • Dữ liệu có cấu trúc: Dùng định dạng dữ liệu có cấu trúc tách nội dung khỏi metadata (URL nguồn, tên tài liệu, số trang) khi truyền context giữa agent để giữ provenance (nguồn gốc dữ liệu).
  • Spawning song song: Spawn subagent song song bằng cách phát nhiều Task tool call trong một response của coordinator, thay vì rải ra nhiều lượt chat.
  • Prompt định hướng mục tiêu: Viết prompt coordinator nêu mục tiêu nghiên cứu + tiêu chí chất lượng thay vì chỉ dẫn từng bước, để subagent linh hoạt thích ứng.

⚠️ Đính chính (docs 08/2026) — tên tool đã đổi, và allowedTools không phải điều kiện tồn tại. Hai gạch đầu dòng trên viết theo Exam Guide v1.0, cần đọc kèm ba chỉnh sau.

1. TaskAgent. Từ Claude Code v2.1.63, tool spawn subagent tên là Agent. Task vẫn còn làm alias ở một số bề mặt tương thích (danh sách tool trong system:init, result.permission_denials[].tool_name), nên code kiểm tra tool_use nên bắt cả hai tên. Trong phòng thi cứ nhận diện theo mô tả cơ chế, đừng bám chữ.

2. allowedTools là TỰ ĐỘNG DUYỆT, không phải công tắc bật/tắt tool. Exam Guide viết "allowedTools must include Task", dễ đọc thành "không có thì tool không tồn tại" — sai chiều. Thiếu Agent trong allowedTools thì lời gọi rơi xuống callback canUseTool; chỉ khi chạy permissionMode: "dontAsk" mà không có callback nào thì nó mới bị từ chối thẳng. Điều kiện kiến trúc thật là: tool phải khả dụng lời gọi phải được duyệt.

3. Ba field, ba việc khác nhau — đây là chỗ bank đề và nhiều tài liệu hay trộn:

Field Ở đâu Làm gì
allowedTools (top-level) option của query() tự động duyệt lời gọi tool của coordinator
AgentDefinition.tools trong từng định nghĩa subagent tập tool của riêng subagent đó; bỏ trống thì kế thừa toàn bộ
AgentDefinition.disallowedTools trong từng định nghĩa subagent gỡ tool khỏi tập trên (nhận cả pattern mcp__server__*)

Cấp MCP server riêng cho một subagent thì dùng AgentDefinition.mcpServers. AgentDefinition không có field allowedTools — thấy chữ đó trong một option đề thi thì gần như chắc chắn là distractor.

4. Subagent giờ spawn được subagent con. Không còn giới hạn một tầng: mặc định sâu 3 tầng (CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH), tối đa 20 subagent chạy đồng thời (CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS), và chặn chi bằng maxBudgetUsd. Option nào nói "subagent không thể spawn subagent" là sai.

🧠 Phân tích & Thực tế từ Delivery Manager:

Để giảm latency tối đa cho người dùng cuối, lập trình viên phải biết cách cấu hình spawn subagent song song. Nếu gọi tuần tự, thời gian chờ sẽ là tổng thời gian của các agent con.

✅ Đúng: Coordinator trả về 2 Task calls song song trong cùng 1 response:
[Task: "Search mảng Nhạc"] và [Task: "Search mảng Phim"]

❌ Sai: Coordinator gọi Task search nhạc → Chờ kết quả → Lượt sau mới gọi Task search phim.

Task 1.4: Triển khai workflow nhiều bước với enforcement và handoff pattern

Kiến thức cần nắm

  • Chặn nghiệp vụ lập trình: Khác biệt giữa enforcement lập trình (hooks, cổng điều kiện tiên quyết) và hướng dẫn qua prompt cho thứ tự workflow.
  • Tính tất định (Determinism): Khi cần tuân thủ tất định (VD: xác minh danh tính trước khi hoàn tiền), chỉ dẫn prompt luôn có tỷ lệ thất bại khác 0.
  • Handoff protocol: Giao thức bàn giao có cấu trúc khi escalate giữa chừng: gồm thông tin khách hàng, phân tích nguyên nhân gốc, hành động đề xuất.

Kỹ năng cần làm được

  • Prerequisite lập trình: Cài đặt prerequisite chặn tool call downstream đến khi bước tiên quyết hoàn thành (VD: chặn process_refund cho tới khi get_customer trả về customer ID đã xác minh).
  • Xử lý song song: Phân rã yêu cầu khách hàng nhiều vấn đề thành từng mục riêng, điều tra song song với context chung, rồi tổng hợp thành một giải pháp thống nhất.
  • Bàn giao có cấu trúc: Soạn handoff summary có cấu trúc (customer ID, nguyên nhân gốc, số tiền hoàn, hành động đề xuất) khi escalate cho nhân viên — người không xem được transcript hội thoại.
[HANDOFF SUMMARY]
- Customer ID: C-88213 (Đã xác minh qua get_customer)
- Vấn đề: Đơn #A-1023 giao thiếu 1 món ($34.50)
- Nguyên nhân: Lỗi đóng gói kho — ngoài chính sách tự xử lý của Agent
- Đề xuất: Nhân viên duyệt gửi bù hàng hoặc hoàn tiền thẻ gốc

Task 1.5: Áp dụng Agent SDK hooks để chặn tool call và chuẩn hoá dữ liệu

Kiến thức cần nắm

  • PreToolUse vs PostToolUse — chọn theo THỜI ĐIỂM: PreToolUse can thiệp vào lời gọi (chặn, sửa/chuẩn hoá tham số, ghi đè giá trị model đưa vào, từ chối). PostToolUse can thiệp vào kết quả trước khi nó vào context (chuẩn hoá, che dữ liệu nhạy cảm, bơm metadata). Phép thử nhanh: "để nó chạy xong rồi mới xử thì đã muộn chưa?" — chặn lệnh ghi database: muộn rồi → Pre. Che số tài khoản trong kết quả: chưa muộn, vì thứ cần chặn là dữ liệu vào contextPost.
  • Một đề bài có thể cần cả hai: Dạng câu hỏi hay gặp là ghép hai yêu cầu vào một tình huống (VD: che số tài khoản trong mọi tool result chặn mọi lời gọi ghi vào production) — đáp án đúng đặt mỗi việc ở một mốc khác nhau, không dồn cả hai về cùng một hook.
  • Deterministic vs Probabilistic: Hooks đem lại bảo đảm tất định (luôn đúng 100%), trong khi prompt chỉ đem lại tuân thủ xác suất.
  • Hook thấy lời gọi, không thấy động cơ: Hook nhận được tên tool và tham số, chứ không biết model định làm gì hay vì sao. Mọi quy tắc cưỡng chế phải phát biểu được thuần tuý trên tham số, nếu không thì hook không phải chỗ để cài nó.
  • Hook trên coordinator không quản subagent: Hook đăng ký ở coordinator chỉ chi phối các tool call của chính coordinator. Subagent chạy vòng lặp tool riêng của nó, nên guard phải được gắn ở tầng đó nữa — đây là lỗ hổng rất dễ bỏ sót trong hệ multi-agent.
  • Hook không phải lúc nào cũng đúng chỗ: Nếu tool là của mình và mình sửa được thì chuẩn hoá ngay trong tool. Hook sinh ra cho trường hợp không đụng được vào nguồn (MCP server bên thứ ba, tool dùng chung).

Kỹ năng cần làm được

  • Chuẩn hoá dữ liệu: Dùng PostToolUse hook chuẩn hoá dữ liệu hỗn tạp (Unix timestamp, ISO 8601, mã trạng thái số) từ các MCP tool khác nhau trước khi agent xử lý.
  • Chặn hành động vi phạm: Cài hook chặn hành động vi phạm chính sách (VD: hoàn tiền > $500) và chuyển hướng sang workflow thay thế (escalate cho người).
  • Viết message cho quyết định block: Khi chặn, trả về message nêu rõ ngưỡngtrỏ sang đường đi hợp lệ (VD: escalate_to_human) để lượt hội thoại đi tiếp theo hướng được duyệt, thay vì chỉ báo "bị từ chối" rồi để agent tự mò.
  • Đọc tham số theo tên field: Lấy giá trị từ input đã parse theo đúng tên trường, đừng regex trên payload đã serialize — và khi không tìm thấy trường cần kiểm thì chặn, đừng cho qua.
  • Chuẩn hoá tham số ở PreToolUse: Ngoài chặn, PreToolUse còn dùng để canonicalise tham số trước khi thực thi (VD: giải path rồi từ chối nếu nó nằm ngoài project root) và để ghi đè giá trị model đưa vào bằng giá trị từ cấu hình session (VD: tự set brand_id, bất kể model điền gì).
  • Thứ tự hook có ý nghĩa: Khi nhiều hook cùng chạm một kết quả, thứ tự quyết định tính đúng đắn — hook che dữ liệu phải chạy trước hook ghi audit, nếu không bản lưu lại chính là bản chưa che.
  • Giới hạn phạm vi matcher: Chỉ đăng ký hook trên đúng những tool cần nó, thay vì bắt mọi tool call. Vừa đỡ chi phí, vừa tránh chạm nhầm vào output không liên quan.
  • Biết khi nào dùng permission settings thay hook: Với nhu cầu chặn thẳng theo pattern, một deny rule trong permission settings đạt cùng mục tiêu mà không phải viết và bảo trì code hook.
# Ví dụ hook chặn tool call đi ra
def pre_tool_use_hook(tool_name, tool_input):
    # Quy tắc bắt buộc: hoàn tiền > $500 phải qua người duyệt
    if tool_name == "process_refund" and tool_input["amount"] > 500:
        return {
            "block": True,
            "message": "Số tiền vượt ngưỡng $500. Hãy chuyển hướng sang escalate_to_human."
        }
    return {"block": False}

Task 1.6: Thiết kế chiến lược phân rã task cho workflow phức tạp

Kiến thức cần nắm

  • Chaining vs Adaptive: Khi nào dùng pipeline tuần tự cố định (prompt chaining) vs phân rã động thích ứng theo phát hiện trung gian.
  • Prompt chaining: Chia review thành các bước tuần tự (VD: phân tích từng file riêng, rồi chạy một pass tích hợp cross-file).

Kỹ năng cần làm được

  • Chọn đúng pattern: Prompt chaining cho review nhiều khía cạnh dễ đoán, phân rã động cho điều tra mở rộng.
  • Tránh loãng attention: Chia code review lớn thành pass phân tích cục bộ từng file + một pass tích hợp cross-file riêng để tránh loãng attention của mô hình.
  • Lập kế hoạch thích ứng: Phân rã task mở (VD: "thêm test toàn diện cho codebase legacy"): map cấu trúc trước, xác định vùng tác động cao, rồi lập kế hoạch ưu tiên có thể điều chỉnh khi phát hiện dependency mới.

Task 1.7: Quản lý session state, resume và fork

Kiến thức cần nắm

  • Resume session: Dùng --resume <session-name> để tiếp tục một cuộc hội thoại cụ thể.
  • fork_session: Tạo nhánh độc lập từ baseline phân tích chung để thử các hướng khác nhau.
  • Stale files: Tầm quan trọng của việc báo cho agent biết file đã phân tích trước đó bị thay đổi khi resume sau khi sửa code.
  • Bắt đầu mới kèm summary: Tại sao bắt đầu session mới kèm bản tóm tắt có cấu trúc đáng tin hơn resume với tool result đã cũ (stale).

Kỹ năng cần làm được

  • Resume/Fork thực tế: Dùng --resumefork_session phục vụ việc so sánh 2 chiến lược test hoặc refactor từ cùng một phân tích codebase gốc.
  • Báo file thay đổi: Chỉ rõ cho session được resume về những file cụ thể đã thay đổi để mô hình tiến hành phân tích lại có mục tiêu, tránh việc agent sử dụng ngữ cảnh cũ đã lỗi thời.

Quay lại Trang Hub ôn thi CCA-F.

Nguồn: Claude Certified Architect – Foundations Certification Exam Guide (Anthropic, Version 1.0 — hiệu lực 07/2026) — Copyright Anthropic. Phần đề thi thử cho kỳ thi này nằm ở tab "Đề thi thử" trên trang hub ôn thi.

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

Nên dừng agentic loop dựa vào `stop_reason` hay đặt giới hạn số vòng lặp?
Điều kiện dừng chính phải là `stop_reason` do API trả về: tiếp tục khi `"tool_use"`, thoát khi `"end_turn"`. Giới hạn số vòng lặp chỉ là van an toàn chống chạy vô hạn, không được dùng làm logic dừng chính. Parse text thô của assistant (VD: tìm chữ "DONE") để quyết định dừng là anti-pattern kinh điển được cài làm đáp án nhiễu.
Subagent có tự thừa hưởng context và memory của coordinator không?
Không. Subagent chạy trong context cô lập (isolated context) — nó không tự thừa hưởng lịch sử hội thoại hay memory của coordinator, và không chia sẻ memory giữa các lần gọi. Mọi thông tin subagent cần phải được truyền tường minh trong prompt của chính nó.
Kết quả tổng hợp thiếu hẳn một mảng thông tin dù subagent nào cũng chạy đúng — lỗi nằm ở đâu?
Lỗi nằm ở khâu phân rã task của coordinator, không phải ở subagent downstream. Khi coordinator chia phạm vi quá hẹp, từng subagent vẫn hoàn thành đúng phần việc được giao nhưng mất tầm nhìn tổng quan nên cả hệ bỏ sót phạm vi. Cách xử lý là để coordinator đánh giá output tổng hợp tìm gaps rồi uỷ quyền lại với truy vấn nhắm đích.
Làm sao spawn nhiều subagent chạy song song thay vì tuần tự?
Coordinator phát nhiều Task tool call trong **cùng một response**, thay vì rải mỗi lần gọi ra một lượt chat riêng. Gọi tuần tự khiến tổng thời gian chờ bằng tổng thời gian của tất cả agent con. Hai đính chính so với Exam Guide v1.0: tool này đã đổi tên `Task` → `Agent` từ Claude Code v2.1.63, và `allowedTools` của coordinator là lớp tự động duyệt chứ không phải điều kiện để tool tồn tại — thiếu nó thì lời gọi rơi xuống callback `canUseTool`, chỉ bị từ chối thẳng khi chạy `permissionMode: "dontAsk"` mà không có callback.
Khi nào phải dùng hooks thay vì viết chỉ dẫn trong prompt để ép thứ tự workflow?
Khi quy tắc nghiệp vụ bắt buộc phải tuân thủ tất định — ví dụ xác minh danh tính trước khi hoàn tiền, hoặc chặn refund vượt ngưỡng $500. Chỉ dẫn qua prompt luôn có tỷ lệ thất bại khác 0 (tuân thủ mang tính xác suất), trong khi hook là code nên bảo đảm tất định 100%.