Hook event 11 of 33

PostToolBatch

Runs once after every call in a parallel tool batch resolves and before Claude Code makes the next model request.

Exit code veto
Exit 2 blocks
Matchers
none
if filter
Does not apply
Docs checked
2026-08-29

Once per batch, after the per-call hooks

When Claude calls several tools at once, each call gets its own PostToolUse or PostToolUseFailure. You might want to react to the whole batch as a unit, not to each call in isolation. That is what this event is for. After all of them resolve, and before Claude Code sends the next request to the model, PostToolBatch fires once. There is no matcher.

Results as the model sees them

The payload carries permission_mode and tool_calls, an array with one entry per call: tool_name, tool_input, tool_use_id, and tool_response. That last field is serialised, meaning it is the text form the model receives, and not the structured object PostToolUse hands a hook for a single call. The hooks reference states the difference.

Context once, or stop the loop

Exit 0 proceeds to the next model call. A valid hookSpecificOutput.additionalContext is injected once for the whole batch, not once per call. Exit 1 proceeds too, unless valid JSON stops it.

Exit 2 stops the agentic loop, the cycle of model request, tool calls, next model request, before the next request goes out. The warning Claude keeps is the JSON reason or stopReason when present and stderr otherwise, and it stays in the conversation so Claude sees it if work continues. Two JSON paths stop the loop at the same point: a top-level decision: "block" with reason, or continue: false with stopReason.

The mistake most people make first

You copy a PostToolUse hook here to check every result in the batch, and it reads tool_response as the object it got on the other event.

It fails on the first entry, because tool_response here is the serialised text form, and exits 1 with a traceback on stderr. The loop proceeds. The transcript shows a hook error with the first line of the traceback, Claude carries on, and none of the batch was checked.

Read each tool_response as text on this event, or leave the per-call logic on PostToolUse and keep this hook for the question only the whole batch can answer.