[DOCS] Python: Synchronous `input()` in `can_use_tool` examples blocks async event loop

Resolved 💬 3 comments Opened Jan 17, 2026 by coygeek Closed Feb 28, 2026

Documentation Type

Unclear/confusing documentation

Documentation Location

URL: https://platform.claude.com/docs/en/agent-sdk/user-input

Section/Topic

The Python code examples within the sections "Handle tool approval requests" and "Complete example" (specifically the handle_ask_user_question function).

Current Documentation

The documentation provides Python examples for handling user input during an asynchronous agent session. Specifically, it uses the built-in input() function:

# From "Handle tool approval requests" section
# Get user approval
response = input("Allow this action? (y/n): ")

# From "Complete example" section (handle_ask_user_question)
response = input("Your choice: ").strip()

What's Wrong or Missing?

The input() function in Python is a synchronous, blocking call. Because the Claude Agent SDK is built on anyio and operates within an asynchronous event loop, calling input() directly inside an async def function will freeze the entire execution thread.

This causes several issues:

  1. Heartbeat/Control Protocol Failure: The event loop cannot process background tasks.
  2. Timeout Risks: The documentation explicitly states that the callback must return within 60 seconds. If the event loop is blocked by input(), the SDK may be unable to track the passage of time or handle internal signals correctly, leading to unexpected session drops or the model assuming a denial before the user even types.
  3. Architecture Inconsistency: Since the SDK uses anyio, it is a bad practice to show blocking I/O in the primary documentation examples.

Suggested Improvement

The examples should be updated to use a non-blocking way to get terminal input. Since the SDK already has a dependency on anyio, the most consistent fix is to wrap the input() call in anyio.to_thread.run_sync.

Suggested Text/Code update:

# Replace:
# response = input("Your choice: ").strip()

# With:
import anyio

response = await anyio.to_thread.run_sync(input, "Your choice: ")
response = response.strip()

This should be applied to both the can_use_tool implementation and the handle_ask_user_question implementation in the Python tabs.

Impact

High - Prevents users from using a feature

Additional Context

  • Links to related documentation: The documentation already mentions a "60-second timeout" requirement on this same page. Blocking the thread makes meeting this requirement reliably impossible in complex async applications.
  • Example from other projects: Similar async frameworks (like FastAPI or Tornado) explicitly warn against using input() or time.sleep() in async handlers for this exact reason. Given that this is the "Agent SDK," users are likely to integrate this into larger async systems where a blocked thread would be catastrophic.

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗