Skip to lesson

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:

MechanismWhat it contributesWhat it does not establish
System prompt describing the orderGuidance for planning and recoverySuccessful completion of a prerequisite
Dispatcher check before invoking the handlerEnforcement for application-owned client toolsCoverage of execution paths outside that dispatcher
Blocking PreToolUse hookEnforcement at the first step of SDK permission evaluationCorrectness of the trusted state your callback reads
PostToolUse hookObservation of a completed tool resultPrevention of an operation that already ran
tool_choice.disable_parallel_tool_use: true with type: "auto"At most one proposed tool per responseCorrect 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 ruleCost of skipping it onceWhere it belongs
Look up the order before quoting a delivery estimateOne wrong estimate, corrected next turnPrompt
Verify the customer before reading order detailsAnother customer’s data disclosedGate
Verify the customer before process_refundMoney sent on an unverified identityGate
Refunds above a ceiling go to a humanAn unauthorized payment that has to be clawed backGate (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 PostToolUse to 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_customer more 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_customer has 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

References