Register and share your invite link to earn from video plays and referrals.

cv usk
@cv_usk
AI / Software Research Notes AI Agent, LLMOps, MLOps, Software Architecture ๆŠ•็จฟใฏๅ€‹ไบบใฎๆ„่ฆ‹ใงใ™ใ€‚
Joined May 2026
258 Following    220 Followers
# Useful but Little-Known Features of Claude Agent SDK ๐ŸŒ Permission evaluation is a 5-stage pipeline. Understanding what happens where makes security design dramatically clearer. Hooks, deny rules, permission mode, allow rules, and callback -- evaluated strictly in order. ๐Ÿ“Œ Title: 5-Stage Permission Evaluation Order ๐Ÿ”— URL: ๐Ÿงฉ Overview Claude Agent SDK tool permissions are evaluated in a 5-stage pipeline: (1) Hooks: PreToolUse hooks run first and can deny. However, returning "allow" does NOT skip subsequent evaluation stages. (2) Deny rules: checks disallowed_tools. Bare tool names (e.g., "Bash") remove the tool definition from context entirely. Scoped rules (e.g., "Bash(rm *)") block even in bypassPermissions mode. (3) Permission mode: bypassPermissions approves everything reaching this stage. acceptEdits approves file operations. (4) Allow rules: matched allowed_tools entries are approved. (5) canUseTool callback: called for anything not resolved above. Priority order: deny > defer > ask > allow. ๐Ÿ›  How to Use ```python import asyncio from claude_agent_sdk import ( ClaudeSDKClient, ClaudeAgentOptions, HookMatcher, ) # Stage 1: Hook to block dangerous operations async def block_dangerous_commands(input_data, tool_use_id, context): if input_data.get("tool_name") == "Bash": command = input_data["tool_input"].get("command", "") if "rm -rf" in command: return { "hookSpecificOutput": { "hookEventName": input_data["hook_event_name"], "permissionDecision": "deny", "permissionDecisionReason": "rm -rf is prohibited", } } return {} async def main(): options = ClaudeAgentOptions( # Stage 1: Hooks hooks={ "PreToolUse": [ HookMatcher(matcher="Bash", hooks=[block_dangerous_commands]) ], }, # Stage 2: Deny rules (bare name = removed from context entirely) disallowed_tools=["WebFetch"], # Stage 3: Permission mode permission_mode="acceptEdits", # Auto-approve file operations # Stage 4: Allow rules allowed_tools=["Read", "Glob", "Grep", "Edit", "Write"], ) # Stage 5: canUseTool is configured separately via query() or ClaudeSDKClient async with ClaudeSDKClient(options=options) as client: await client.query("Improve the code") async for message in client.receive_response(): print(message) ``` Lockdown configuration example: ```python # Principle of least privilege: only allowed tools, everything else denied options = ClaudeAgentOptions( allowed_tools=["Read", "Glob", "Grep"], permission_mode="dontAsk", # Deny unapproved tools without prompting ) ``` ๐Ÿ— Integration into Production Systems - allowed_tools does NOT constrain bypassPermissions. Even with only "Read" in allowed_tools, bypassPermissions approves all tools - Use disallowed_tools to completely block specific tools (effective even in bypassPermissions) - For least privilege, combine allowed_tools with permission_mode="dontAsk" - A hook returning "allow" means "this hook is OK with it" -- it does not override subsequent deny rules or mode evaluation ๐Ÿ’ก Use Cases ๐Ÿ”’ Least-privilege agent: allow only Read/Glob/Grep with dontAsk to deny everything else ๐Ÿ›ก Progressive trust: start in default mode, escalate to acceptEdits after review ๐Ÿšซ Eliminate dangerous ops: remove Bash entirely via disallowed_tools, or scope-block with Bash(rm *) ๐Ÿ” Audited approvals: log all requests via hooks while auto-deciding via rules โš ๏ธ Caveats - Tools not in allowed_tools are "unresolved," not "denied" -- they proceed to the next stage - Bare tool names in disallowed_tools remove the tool definition from context; the agent won't even know the tool exists - bypassPermissions is inherited by subagents, which may have different system prompts -- use with caution - When multiple hooks register for the same event, the most restrictive decision wins โœจ Master the 5-stage permission pipeline for robust security design! #ClaudeAgentSDK# #AIAgent#
Show more