{"slug": "pretooluse-or-posttooluse-where-to-put-a-check-in-the-claude-agent-sdk", "title": "PreToolUse or PostToolUse? Where to Put a Check in the Claude Agent SDK", "summary": "A developer explains that in the Claude Agent SDK, checks that must prevent a side effect belong in the PreToolUse hook, since PostToolUse runs after the tool executes and cannot undo it. The writeup notes that async hooks cannot gate actions, that returning 'ask' alone does not create an approval screen, and that the tool service must still repeat authorization and business validation with an idempotency key.", "body_md": "If an agent can trigger a business action, the most important design question is where each check runs. In the Claude Agent SDK, hooks give you two points around every tool call. Only one of them can stop the action.\n\n**A check that must prevent a side effect belongs in `PreToolUse`.** It runs before the tool executes and returns a decision. `PostToolUse` runs after execution. It can add context, replace the result the agent sees, or record an event, but it cannot undo what the tool already did.\n\n| Decision | Use it when | What happens | \n|---|---|---|\n| `deny` | Required data is missing or a business rule fails | The tool does not run. Return a reason the agent and the operator can act on | \n| `ask` | The request is valid but needs a person's approval | Your approval handler ( `canUseTool` in TypeScript,`can_use_tool` in Python) gets the decision. Returning`ask` alone does not create an approval screen | \n| allow | The request meets the hook's policy | The call continues to the tool service | \n\nA `PreToolUse` hook can also return changed input. Use that sparingly and log it, because the tool then runs something the agent did not ask for.\n\n**Async hooks cannot gate.** A callback that returns `async: true` (`async_: True` in Python) cannot block the tool or change its input. A hook that gates an action must return its decision before execution.\n\n**The hook is not the last line.** The hook does not own the business record. The tool service must repeat authorization and business validation, and use an idempotency key so a retry cannot create a duplicate. Passing the hook shows the request looked acceptable, not that the action is correct.\n\nThe event names overlap, but the owners differ. Agent SDK hooks are registered by the application running the agent, through `ClaudeAgentOptions` in Python or the SDK options in TypeScript. Claude Code hooks are configured in the Claude Code environment. Exam questions and real incidents both turn on this difference.\n\nReview the blocked paths as carefully as the successful one.", "url": "https://wpnews.pro/news/pretooluse-or-posttooluse-where-to-put-a-check-in-the-claude-agent-sdk", "canonical_source": "https://dev.to/poorna_reddy/pretooluse-or-posttooluse-where-to-put-a-check-in-the-claude-agent-sdk-36fh", "published_at": "2026-10-05 22:55:18+00:00", "updated_at": "2026-10-05 23:18:11.861094+00:00", "lang": "en", "topics": ["ai-agents", "developer-tools", "ai-tools"], "entities": ["Claude Agent SDK", "Claude Code", "Anthropic"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/pretooluse-or-posttooluse-where-to-put-a-check-in-the-claude-agent-sdk", "markdown": "https://wpnews.pro/news/pretooluse-or-posttooluse-where-to-put-a-check-in-the-claude-agent-sdk.md", "text": "https://wpnews.pro/news/pretooluse-or-posttooluse-where-to-put-a-check-in-the-claude-agent-sdk.txt", "jsonld": "https://wpnews.pro/news/pretooluse-or-posttooluse-where-to-put-a-check-in-the-claude-agent-sdk.jsonld"}}