Workflow enforcement and handoff: CCAR-F task statement 1.4
CCAR-F · Agentic Architecture & Orchestration (27% of the exam)
Task statement 1.4 sits in Agentic Architecture & Orchestration, 27% of the CCAR-F exam. It tests three things: making sure required steps happen in the right order, handling a request that contains several problems, and handing a case to a person with everything they need to act.
What the official guide covers
The Claude Certified Architect Foundations exam guide (version 1.0, effective July 2026) lists this under task statement 1.4, "Implement multi-step workflows with enforcement and handoff patterns":
| Knowledge of | Skills in |
|---|---|
| Programmatic enforcement (hooks, prerequisite gates) compared with prompt guidance for the order of steps | Building prerequisites in code that block later tool calls until earlier steps are complete, such as no refund until a verified customer ID exists |
| When compliance must be deterministic, such as identity checks before financial actions, prompt instructions alone still fail some of the time | Splitting a request with several concerns into separate items, investigating each in parallel with shared context, then giving one combined resolution |
| Structured handoff protocols for escalation mid-process: customer details, root cause, recommended action | Writing structured handoff summaries (customer ID, root cause, refund amount, recommended action) for human agents who cannot see the transcript |
Prompt guidance or code enforcement?
A system prompt can say "always verify the customer before touching their account". Claude follows that most of the time. The guide's point is that "most of the time" is not good enough when a skipped step moves money or exposes someone else's data. For those steps, put a gate in code that the agent cannot get past.
| The requirement | Use | Why |
|---|---|---|
| A step must always come before another (verify, then refund) | Prerequisite gate in code | The later call is blocked until the earlier one has succeeded |
| A single action must never exceed a limit | PreToolUse hook on that tool | Checked on every call (see 1.5 Agent SDK hooks) |
| A preferred order that is fine to vary | Prompt guidance | Flexibility helps; an occasional miss costs little |
| The steps never change and need no judgement | Fixed workflow in your own code | No agent decision is needed (see 1.1) |
Who owns each step: Claude, code or a person
Before placing gates, split the workflow into steps and give each one an owner. Three questions decide it: can a wrong call be undone, what does a wrong call cost, and who has to answer for it?
- Claude owns language work: reading a free-text complaint, investigating across tools, drafting the reply.
- Code or an existing system owns rules that must give the same answer every time (thresholds, eligibility, identity checks) and lookups of live data.
- A person owns decisions that are costly, hard to reverse, or need someone accountable.
A worked example shows why the split matters. A lender's agent routes loan applications, and any application above 250,000 must go to a senior underwriter. The team asks Claude to read the amount and route the case. It works on every test case. In production, some applicants write the amount in words or as a range ("roughly a quarter of a million"), and a few of those land in the standard queue. Nothing raises an error; an audit finds them months later. The better design keeps the parts apart: Claude extracts the amount into a structured field, code applies the threshold, and a missing or uncertain amount goes to a person.
Building a prerequisite gate
A prerequisite gate has two parts. One part records that the earlier step succeeded. The other part checks that record before the later tool runs. In the Claude Agent SDK you can build both with hooks: a PostToolUse hook on get_customer stores the verified ID, and a PreToolUse hook on the order and refund tools denies the call if no verified ID exists for this session.
from claude_agent_sdk import ClaudeAgentOptions, HookMatcher
verified_ids = {} # session_id -> verified customer ID
def deny(reason):
return {"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": reason,
}}
async def record_verification(input_data, tool_use_id, context):
# your parser: returns the customer ID only if get_customer confirmed identity
customer_id = parse_verified_id(input_data["tool_response"])
if customer_id:
verified_ids[input_data["session_id"]] = customer_id
return {}
async def require_verified_customer(input_data, tool_use_id, context):
verified = verified_ids.get(input_data["session_id"])
if verified is None:
return deny("Verify the customer with get_customer before order or refund actions.")
if input_data["tool_input"].get("customer_id") != verified:
return deny("This action must use the verified customer ID from get_customer.")
return {}
options = ClaudeAgentOptions(hooks={
"PostToolUse": [HookMatcher(matcher="mcp__support__get_customer",
hooks=[record_verification])],
"PreToolUse": [HookMatcher(matcher="mcp__support__lookup_order|mcp__support__process_refund",
hooks=[require_verified_customer])],
})
Three details matter. The gate checks that verification succeeded, not just that get_customer was called. It also checks that the later call uses the same customer ID. And each denial gives Claude a clear reason, so it goes back and runs the missing step instead of retrying the blocked call. Hook syntax and options are covered on the 1.5 page; this page is about where the gates go.
Requests with several problems
Customers often raise more than one issue in a message: "My order arrived damaged, I was charged twice, and I can't log in." Treat it as three items, not one.
- Split. List each concern as its own item with what needs to be found out.
- Investigate in parallel. Look up each item. Independent lookups can go out as several tool calls in one response, and they share the same conversation, so a fact found for one item (the customer ID, the order) is available to the others.
- Resolve together. Write one reply that answers every item, says what was done for each and flags any item being escalated.
The common failure is answering only the first concern, or answering each one in a separate reply that contradicts the others.
Where a human gate goes
Not every step needs a person. Ask what the worst outcome is if the step runs unchecked, and gate only where that outcome is costly or permanent.
| Point in the workflow | What triggers the gate | Example |
|---|---|---|
| Before an action that cannot be undone | The agent is about to pay, delete, send or change a live record | A refund above the agent's limit |
| After a plan, before it runs | The agent has proposed a multi-step change | Closing and reopening 40 customer accounts |
| On an unexpected result | An empty result, an error flag, or a value out of the expected range | One email address matches two customers |
Low-cost, reversible steps (looking up an order, drafting a reply that a person sends) need no gate. Gating them only slows the work.
Timing matters as much as placement. The gate sits on the specific call, at the moment the agent proposes it. One approval at the start of a session cannot cover an action nobody has seen yet, and a review after the write (in the next pull request, say) approves something that has already happened. In the Agent SDK, the canUseTool callback asks a person about a specific call; if they deny it, Claude receives your message and can tell the customer or take another route. The callback never fires for tools that a permission rule or mode already approves, so a check that must run on every call belongs in a PreToolUse hook. And a gate is only real if someone staffs it: a "Claude drafts, a person approves" step with no reviewer assigned is an automated step.
Handing off to a person
When the agent escalates, the person who picks up the case usually cannot see the conversation. The handoff must stand on its own. Send a structured summary, not "customer is unhappy, please help" and not the raw transcript.
{
"customer_id": "C-48213",
"verified": true,
"issue": "Duplicate charge on order 99187",
"root_cause": "Payment retried after a gateway timeout; both captures succeeded",
"evidence": ["Two captures 40 seconds apart on the same card", "Only one shipment"],
"actions_taken": ["Confirmed duplicate with lookup_order", "Refund blocked: above agent limit"],
"refund_amount": 640.00,
"recommended_action": "Approve refund of the second capture",
"customer_told": "A specialist will confirm the refund within one business day"
}
Each field answers a question the human would otherwise have to ask: who is this, what went wrong, why, what has already been done, and what should happen next. The customer_told field stops the human from promising something different.
Rules that decide exam answers
- Required order means code. If a step must always come first, choose the prerequisite gate or hook. More emphatic prompt wording or extra examples still leave a failure rate.
- Gate on success, not on attempt, and say why. A gate that only checks whether the verification tool was called lets a failed verification through. A denial with a clear reason lets Claude run the missing step instead of retrying.
- Approve before the action, not after. A human gate sits on the specific risky call before it executes. A single approval at session start, or a review after the write, is the wrong answer.
- Split multi-issue requests. Decompose, investigate each item, then give one combined resolution. Options that handle only the first issue are wrong.
- Handoffs must stand alone. The human cannot see the transcript. Choose the structured summary with customer ID, root cause, amount and recommended action.
- Give the rule to code, not to Claude. When a fixed threshold must route cases every time, let Claude extract the value and let code apply the rule. An option that asks Claude to "apply the threshold carefully" still leaves a failure rate.
Where it appears in the exam
Domain 1 is a primary domain in three of the six exam scenarios: Customer Support Resolution Agent, Multi-Agent Research System and Developer Productivity with Claude. Prerequisite gates, multi-concern requests and handoffs fit the Customer Support Resolution Agent scenario, which uses get_customer, lookup_order, process_refund and escalate_to_human. The guide's preparation exercise "Build a Multi-Tool Agent with Escalation Logic" reinforces this domain.
Two sample questions
These are original Timo practice questions. They are not official exam questions.
Build exercise
- Build a support agent with
get_customer,lookup_orderandprocess_refundtools, and add the two hooks above. - Ask for a refund without giving any details. Confirm the refund is denied with a reason and that Claude then calls
get_customer. - Make
get_customerreturn a failed verification and confirm the gate still blocks the refund. - Send a message with three separate problems. Check that the agent investigates all three and replies once. Then force an escalation and check the handoff contains every field in the JSON above.
Practise this topic
- Claude Certified Architect practice exam: free, 20 questions, no sign-up
- Claude Certified Architect hub
- CCAR-F study guide: all topics
- Worked example: Claude Agent SDK hooks
- Same topic in another exam: CCDV-F Agent Construction with Claude
- Previous topic: 1.3 Subagent invocation and context passing
- Next topic: 1.5 Agent SDK hooks
Sources
- Claude Certified Architect Foundations Exam Guide, version 1.0, effective July 2026 (Anthropic), task statement 1.4
- Claude Agent SDK documentation: Intercept and control agent behavior with hooks
- Claude Agent SDK documentation: Configure permissions
- Claude Agent SDK documentation: Handle approvals and user input
- Anthropic documentation: Parallel tool use
By Amotion AI