AnthropicClaude Certified Architect – Foundations2026-101.4 Implement multi-step workflows with enforcement and handoff patterns
Enforce prerequisites before executing a tool
Completed by the knowledge check
Learning objective
Enforce mandatory tool prerequisites in application logic or hooks rather than relying on prompt ordering.
Core idea
When you design a customer-support agent, a prompt can explain that get_customer must precede process_refund. The execution layer must enforce that rule. Claude proposes tool calls; your application decides whether a client tool runs. A sentence in the system prompt helps Claude plan a valid sequence, but it does not establish that a prerequisite actually succeeded. Prompt instructions alone have a non-zero failure rate, so a step requiring deterministic compliance needs an execution-layer check.
The deciding question is whether an invalid sequence can reach the downstream operation. If the answer is yes, stronger wording leaves the defect intact. Put the check at the point that dispatches process_refund, or in an Agent SDK PreToolUse hook that blocks the corresponding tool. Record prerequisite completion from the trusted tool result, rather than from Claude’s statement that verification is complete.
This Bite owns workflow ordering. See 1.4.2 for the separate identity, authorization, and business-policy checks that determine whether an otherwise correctly ordered operation is permitted.
How it works
Enforce the sequence in a Messages dispatcher
With Messages API client tools, Claude returns a tool_use block containing name and input. Your application owns execution. A dispatcher can inspect the proposed tool, look up trusted case state, and refuse to invoke its handler until the prerequisite is satisfied. get_customer and process_refund here are illustrative application tools, not Anthropic built-in tools.
For this support workflow, define successful prerequisite completion as a validated get_customer result containing a verified customer ID for the active case. Calling get_customer is insufficient: a failed lookup or an unverified record does not satisfy the gate. Store the validated result in application-owned case state and bind it to the customer the refund targets.
If Claude requests process_refund too early, do not execute it. Return a matching tool_result with is_error: true and a concise explanation of the missing prerequisite. Preserve the assistant’s tool call and correlate the response through tool_use_id; see 1.1.2 for the history contract. The error gives Claude information it can use to repair its plan without allowing the prohibited action.
A response can contain both get_customer and process_refund. Their presence in one batch does not establish a valid dependency. The API leaves execution order to you. You can execute dependent calls sequentially, validate the first result, and evaluate the second against the resulting state. Alternatively, decline the premature downstream call and let Claude request it after receiving verification. If you skip a call, still return its error result.
Block before execution in the Agent SDK
The Agent SDK runs the tool loop, so insert the gate through options.hooks.PreToolUse in TypeScript or ClaudeAgentOptions(hooks={...}) with HookMatcher in Python. Both SDKs support PreToolUse. The hook receives tool_name and tool_input, which identify the proposed operation and its arguments.
MCP tool names use mcp__<server>__<action>. If your configured server is support, the illustrative refund tool can be named mcp__support__process_refund. Register a matcher for that actual tool name, rather than the unqualified business-operation label.
The hook’s denial output has this shape:
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": "Verified customer lookup is required."
}
}The hook reads trusted state in your application process before returning that object. It does not infer completion from the request’s customer_id alone. A PostToolUse hook can observe a completed lookup and validate its result before updating that state. Its event means a tool returned a result, not that your business prerequisite is satisfied automatically.
Keep this gate blocking. SDK callbacks wait by default, but an async output such as TypeScript { async: true } tells execution to continue without waiting. Async hook outputs cannot block or modify the operation. They fit logging, not prerequisite enforcement.
Key distinctions and trade-offs
The mechanisms solve different problems:
| Mechanism | What it contributes | What it does not establish |
|---|---|---|
| System prompt describing the order | Guidance for planning and recovery | Successful completion of a prerequisite |
| Dispatcher check before invoking the handler | Enforcement for application-owned client tools | Coverage of execution paths outside that dispatcher |
Blocking PreToolUse hook | Enforcement at the first step of SDK permission evaluation | Correctness of the trusted state your callback reads |
PostToolUse hook | Observation of a completed tool result | Prevention of an operation that already ran |
tool_choice.disable_parallel_tool_use: true with type: "auto" | At most one proposed tool per response | Correct ordering across successive responses |
Restricting parallel proposals can simplify a workflow, but it is not the gate. Claude can still request the sensitive tool first on a later turn. Keep planning controls separate from execution checks.
Choose a dispatcher when you own the Messages loop and need direct control over dependent calls. Choose a hook when the Agent SDK owns that loop. Explain the prerequisite in the prompt in either design so Claude can avoid predictable denials; retain the deterministic check for the cases where it does not.
Not every ordering preference needs a gate. Ask what one skipped step costs:
| Ordering rule | Cost of skipping it once | Where it belongs |
|---|---|---|
| Look up the order before quoting a delivery estimate | One wrong estimate, corrected next turn | Prompt |
| Verify the customer before reading order details | Another customer’s data disclosed | Gate |
Verify the customer before process_refund | Money sent on an unverified identity | Gate |
| Refunds above a ceiling go to a human | An unauthorized payment that has to be clawed back | Gate (see 1.5.1) |
A financial, privacy, or irreversible consequence puts the rule in code; a recoverable one can stay in the prompt. See 1.5.3 for that cost-of-failure rule.
Architecture / decision scenario
A customer asks for a refund on an order. The support agent’s prompt says to retrieve and verify the customer first. A trace shows Claude proposing get_customer and process_refund together, and the existing dispatcher starts both concurrently.
Move the prerequisite check into the refund dispatch path. The dispatcher runs the lookup, validates whether the returned customer is verified for the case, and only then considers the refund request. If the lookup fails, it returns an error result for the refund without calling the payment handler. If the refund’s customer ID differs from the verified record, the gate also rejects it.
In an Agent SDK implementation, register a blocking PreToolUse matcher for mcp__support__process_refund and make the same check there. A validated lookup result supplies trusted state; an unsuccessful result leaves the gate closed. The denial reason tells Claude to complete the missing lookup, while the tool executor prevents the payment operation. A post-execution audit hook can record the outcome, but cannot replace this prevention step.
Common exam traps
- Treating emphatic prompt wording as a deterministic prerequisite gate.
- Recording completion when a tool is requested rather than when its result is validated.
- Running a lookup and its dependent refund concurrently because Claude batched them.
- Returning no result for a blocked client-tool call.
- Using
PostToolUseto prevent a side effect that has already happened. - Making the enforcement hook asynchronous so execution proceeds before the decision.
- Treating logs of skipped verification as a prompt problem: stronger wording, worked examples, or a self-check instruction make
get_customermore likely to run first, never certain to. - Narrowing each request to a subset of tools to fix a skipped step. Tool selection decides what Claude may call; the gate decides whether
get_customerhas already succeeded.
What to remember
Claude’s proposed order is a plan. The dispatcher or blocking PreToolUse hook enforces whether execution can proceed. Validate prerequisite results, bind them to the target case, and return an explicit failure when the gate remains closed.
Knowledge check
Production logs show that in a small share of conversations the support agent calls process_refund without calling get_customer first, although the system prompt says verification is mandatory. Some refunds have reached the wrong account. Which change makes the ordering hold in every conversation?
process_refund in the dispatcher until a verified lookup result existsget_customer more likely to run first, never certain to, and a refund on an unverified identity needs certainty. A check in the dispatch path refuses execution whatever Claude proposes. Narrowing the tool set decides what Claude may call, not whether the lookup has already succeeded, and a statement in the reply is more model output, not evidence.Claude returns get_customer and process_refund as two tool_use blocks in one response. Your Messages API dispatcher currently runs every block of a response concurrently. The refund must not run unless the lookup returns a verified customer for the case. How should the dispatcher handle this response?
tool_result — with is_error: true — correlated by its tool_use_id .A PreToolUse hook gates mcp__support__process_refund on a verified customer lookup. Which evidence should the hook accept as proof that the prerequisite is satisfied?
customer_id value present in the refund call’s tool_inputget_customer earlier in the sessionget_customer is not the prerequisite: a failed lookup or an unverified record leaves the gate closed. The hook reads trusted state written from a validated result and bound to the customer the refund targets. A customer_id in the refund input is part of Claude’s proposal, and a sentence claiming verification is model output rather than evidence.An Agent SDK support agent must never run mcp__support__process_refund before a verified customer lookup. Which hook implementation prevents the refund from running when the lookup has not succeeded?
PreToolUse callback that sets hookSpecificOutput.permissionDecision: "deny"PreToolUse callback that returns { async: true } and checks in the backgroundPostToolUse callback on the refund tool that reports the missing lookupPreToolUse callback that logs the missing lookup and returns {}PreToolUse decision stands between the proposal and execution. An async hook output lets the agent continue without waiting, so it cannot block anything; PostToolUse fires after the refund has already run; and returning {} makes no permission decision, so the call continues through the normal permission flow.References
- Anthropic, Parallel tool use
- Anthropic, Control execution with hooks
- Anthropic, Configure permissions
- Anthropic, Automate actions with hooks
- Anthropic, Claude Certified Architect – Foundations Exam Guide