Sign in / Sign up

Understand AI investment / Closing analysis

How an AI Agent Can Stop and Ask: Four Interaction Paths and Their Conditions

Programmed gates, permission approval, model-generated questions and human intervention serve different interaction patterns. LangGraph and Claude Agent SDK document their triggers, prerequisites and resumption behavior; the useful choice depends on where your application needs input.

DisconfirmAI editorial · First published · · Last substantive update ·

Quick answer

For an application that needs human input, four documented controls cover different interactions. LangGraph's interrupt() is developer-placed, requires a checkpointer and the same thread_id for resumption, and replays its containing node; Claude Agent SDK provides condition-dependent permission callbacks, model-generated questions and streaming input for human-initiated intervention. Choose by who initiates input, when it is needed and how execution resumes; a configured mechanism does not guarantee that every ambiguity will be recognized.

01

Decide Who Initiates Input and Where Execution Waits

CuriousRose, a Hacker News user running a SaaS business, asked how to stop an AI from continuing when clarification is needed. The post describes a large automation backlog and uncertainty about where a human belongs in the workflow. That points to a concrete implementation question: where should the application obtain a person's decision or additional input?

Four Pause Mechanisms Compared

Diagram and data comparison
MechanismInitiatorPrerequisitesPause scopeDocumented limitations
LangGraph interrupt()Developer places in codeCheckpointer + thread_idGraph execution pauses at call siteFull-node replay from beginning on resume; idempotent prior effects required; sequential interrupts within one node use indexes, parallel use IDs; a handler that swallows the interrupt prevents pausing; separate interrupt from error-prone code or catch only a specific non-interrupt exception (NetworkException example)
canUseTool callbackPermission evaluation flow triggers under specific conditionsCallback registered; mode, SDK settings and preceding decisions permit reaching itSingle tool call awaits decisiondontAsk denies requests needing a prompt without calling callback; earlier decisions or SDK settings can prevent callback invocation; permissionPrompts:'none' skips callback; bare allowedTools or bypassPermissions trigger SHADOWED warning
AskUserQuestionModel initiatesInclude when an explicit tools array restricts the set; unavailable in Agent-tool subagentsModel generates structured questions awaiting answers1-4 questions and 2-4 options with free text supported; preceding rejection and interaction settings still apply; allow rules cannot pre-approve
Streaming inputHuman initiatesStreaming input mode (not single message)Mid-task interruption or additional context receivedSingle message mode lacks real-time interruption; cancel signal documented but mechanism and effect on in-flight tool unspecified; TypeScript generator exceptions show misleading error message
Based on documented capabilities, prerequisites and limitations from four framework documents. No measured effectiveness data available.

Anthropic's building-effective-agents guide describes agents pausing for human feedback at checkpoints or when encountering blockers, without specifying the API that implements that interaction. LangGraph and Claude Agent SDK documentation provides the implementation details examined in this feature.

The guide also recommends starting with a simple design and using environment feedback to assess progress. Those recommendations do not establish whether a particular action can safely proceed without a person's decision, and they do not measure a reduction in clarification frequency. Here the selection criterion is the interaction your application requires, with the documented prerequisites and failure behaviors considered alongside it.

02

LangGraph interrupt(): Developer-Placed Pause Points

LangGraph's interrupt() function pauses graph execution at any point within a node and waits for external input. Unlike static breakpoints, interrupts are dynamic: they can be placed anywhere in code and can be conditional based on application logic. When called, LangGraph saves the current graph state and waits indefinitely until execution is resumed with Command(resume=...).

Using interrupt() has two hard prerequisites: a checkpointer to persist graph state (use a durable checkpointer in production), and a thread_id in the config so the runtime knows which state to resume from. The thread_id is effectively a persistent cursor—reusing it resumes the same checkpoint; using a new value starts a brand-new thread with empty state. You must use the same thread ID when resuming that was used when the interrupt occurred.

Resumption replays the containing node from its beginning rather than continuing at the paused line. Code before interrupt() runs again, so side effects there should be idempotent or isolated in separate nodes—for example, an upsert with the same key and resulting value instead of creating a new record on every attempt. Otherwise resumption can repeat writes or other work.

Multiple sequential interrupts within one node are matched by index position: on resume the runtime replays from the node beginning, and for each interrupt encountered it checks whether a matching value exists at that index in the task's resume list. The order of interrupt calls within the node must therefore remain consistent—conditional skipping or reordering causes index mismatch. Parallel branch interrupts use ID mapping instead: each interrupt has a unique ID, and resume maps each ID to its value.

interrupt() pauses execution by raising a special exception. A broad or bare handler that catches and swallows it prevents the interrupt from reaching the graph. The documentation gives two valid alternatives: separate the interrupt() call from error-prone code so no handler wraps it; or catch only a specific exception type that excludes the interrupt exception, with NetworkException given as the example. Re-raising a caught interrupt exception would also let the pause propagate, which is consistent with the mechanism, but the documentation does not explicitly list this option; it is stated here as an inference from the described behavior.

For repeated human-input validation, the documentation recommends one interrupt() per node invocation: store a new question in state after failed validation and route back with a conditional edge. A while True loop containing repeated interrupts makes later resumptions replay earlier iterations and repeat work. Keep that replay behavior in view when deciding where to place validation and side effects.

03

Claude SDK Permission Evaluation: Six-Step Conditional Routing

The Claude Agent SDK's permission evaluation is not a linear pipeline but a conditional routing graph. When Claude requests a tool, the SDK checks six steps in order, but a decision at any step does not necessarily terminate the evaluation flow—some steps' allow results continue through subsequent checks, while some steps' denials terminate immediately. Understanding this conditional routing is essential for correct pause configuration.

Claude SDK Six-Step Permission Evaluation: Conditional Routing

Diagram and data comparison
StepCondition/triggerPossible decisionsNext routeDocumented exceptions
1. HooksRuns before every tool callallow / deny / modify / deferallow does not skip deny/ask; deny blocks this call; other results follow hook and SDK semanticsallow does not skip deny and ask rules; cannot approve critical-path rm/rmdir
2. Deny rulesdeny rules from disallowed_tools and settings.jsonmatch→blockmatch→call blocked; no match→step 3Blocks even in bypassPermissions; bare-name rules remove tool from context before evaluation
3. Ask rules & interaction toolsAsk match or interaction requirement after preceding rejection checksfall through to callbackRoutes toward callback in configurations permitting interaction; not ordinary mode/allow auto-approvalPrior hook/deny can prevent arrival; dontAsk denies; org-ask connectors also fall through
4. Permission modeCurrently active modeMode-specific approval or pass-throughApprove, request confirmation or continue according to the mode; mode names are not unconditional grantsNo auto-approval for critical-path removal; acceptEdits has path/protection limits; plan writes need confirmation; auto mode uses classifier for automated approval; switching to unsupported model falls back to default
5. Allow rulesallow rules from allowed_tools and settings.jsonOrdinary matches can approve; documented exceptions cannot be auto-approvedExecutes only when approval conditions hold; exceptions follow the mode to confirmation or denialFour categories never auto-approved: AskUserQuestion, requiresUserInteraction MCP, org-ask connectors, critical-path removals; network-path reads not approved
6. canUseTool callbackLeft for a decision by preceding flow, with callback allowed by mode/SDK settingsallow / deny (per callback implementation)allow→tool executes; deny→tool does not executedontAsk skips this step and denies; TypeScript permissionPrompts:'none' skips callback; SHADOWED warning signals callback may be bypassed; scoped entries and acceptEdits do not trigger SHADOWED; settings-file rules not visible to check; dontAsk hook allow does not clear critical-path removals or network-path reads
Order and branch navigation: a step may reject, request confirmation or continue evaluation. Hook allow does not bypass deny/ask, and special actions retain their specific conditions.

Hooks run first. PreToolUse checks requests before the other permission steps and can deny, allow or modify them. A hook that returns allow does not skip the deny and ask rules below; those are evaluated regardless of the hook result. A PreToolUse hook allow also cannot approve an rm or rmdir removal targeting a critical path. Checks required before every tool call belong in the documented PreToolUse entry point, with the required decision logic actually implemented.

Step 2 is deny rules. If a deny rule matches, the tool is blocked, even in bypassPermissions mode. Bare-name deny rules like Bash remove the tool from Claude's context before this evaluation begins, so only scoped rules like Bash(rm *) are checked at this step.

Step 3 checks ask rules and tools requiring user interaction after earlier rejection checks. An ask rule can route a request toward confirmation even in bypassPermissions mode. AskUserQuestion, MCP tools marked requiresUserInteraction and organization-configured ask connectors are not ordinarily pre-approved by allow rules. The actual route still depends on mode and SDK interaction settings: dontAsk denies these requests, while the TypeScript permissionPrompts:'none' setting skips canUseTool at the final callback step and leaves a PermissionRequest hook a chance to decide.

Step 4 applies the permission mode. bypassPermissions approves everything that reaches this step except rm and rmdir removals targeting a critical path, which fall through instead. acceptEdits auto-approves file operations and filesystem commands only within its working-directory or additional-directory scope and protection conditions; it does not approve edits to arbitrary paths, protected paths or critical-path removals. In plan mode, file edits and shell commands that modify files still require the callback confirmation path. Auto mode uses a classifier model to review actions such as shell commands and network requests, allowing or blocking each one it reviews; this is automated action review rather than a request for human confirmation. If a session in auto mode switches to a model that auto mode does not support, the session changes to default mode.

Step 5 checks allow rules. Ordinary matches can approve calls, but four categories are never auto-approved: AskUserQuestion, MCP tools marked requiresUserInteraction, connector tools your organization set to ask, and rm/rmdir removals targeting a critical path. A general allow rule also does not approve a read from a network path. Whether an exception proceeds to confirmation or is denied depends on the applicable permission mode.

Step 6 is the canUseTool callback for requests left for a decision. dontAsk skips this step and denies the tool directly. In supported TypeScript SDK configurations, permissionPrompts:'none' skips the callback at this step, but a PermissionRequest hook still gets a chance to decide; if it does not, the call is denied. If you pass a canUseTool callback in a configuration where the TypeScript SDK expects auto-approval to shadow it (such as bypassPermissions mode or bare allowedTools entries), the SDK emits a CLAUDE_SDK_CAN_USE_TOOL_SHADOWED warning at query construction. Entries with a specifier such as Bash(ls *) and the acceptEdits mode do not trigger this warning, and allow rules coming from settings files are not visible to the check. In dontAsk mode, a PreToolUse hook allow does not clear a critical-path removal or a read from a network path either.

04

Model-Initiated and Application-Authored Questions

AskUserQuestion is the Claude SDK mechanism for model-initiated clarification. When Claude encounters multiple valid approaches during task execution and needs user direction, it calls this tool to generate structured questions. Each call supports 1 to 4 questions with 2 to 4 options each, and users may provide free-text responses in addition to selecting predefined options.

Check AskUserQuestion availability separately. If a tools array explicitly restricts the tool set, it must include AskUserQuestion; otherwise the model silently loses the ability to initiate clarification. The tool is also not currently available in subagents spawned via the Agent tool. Allow rules cannot pre-approve it, but earlier rejection checks, modes such as dontAsk and applicable SDK settings still affect the actual interaction path.

Model-initiated questioning is not the only path to user input. The user-input documentation explicitly records alternatives: developers can ask their own questions separately in application logic, outside the canUseTool flow; custom tools can build forms, wizards or multi-step workflows beyond AskUserQuestion's multiple-choice format; and streaming input allows humans to proactively send information mid-task without waiting for the model to ask.

For long-running processes where user response time may exceed process lifetime, the documentation recommends registering a PreToolUse hook that returns the defer decision instead of waiting in the callback. This allows the process to exit and resume later from the persisted session. The documentation does not specify the serialization format or storage mechanism for the persisted session that enables later resumption.

05

Streaming Input: Human-Initiated Interruption

Claude Agent SDK's streaming input mode provides human-initiated mid-task intervention capability without waiting for the model to request input. The documentation lists three use cases: interrupting the agent mid-task by sending a cancel signal or changing direction while Claude is working; providing additional context without waiting for the model to ask; and building chat interfaces where users send follow-up messages during long-running operations. Streaming input operates as a persistent session handling incoming messages, permission requests and session state, with messages queued sequentially.

The user-input documentation explicitly names sending a cancel signal as a use case, but the signal format, delivery mechanism and effect on an in-flight tool call are not specified in any loaded document. Queueing a message is not the same operation as canceling an executing tool. Single-message input mode does not support dynamic message queueing or real-time interruption; it suits one-shot requests or environments that do not need mid-task intervention. It can still continue through session state and resumption, so it is not inherently stateless.

Streaming input has a documented debugging trap: in the TypeScript SDK, if your message generator throws—for example when a file it reads is missing—the stream ends with an error that reads 'Claude Code process aborted by user' instead of the original error. Check the code inside your generator first when you see that message. The error may be preceded by a long minified line of bundled SDK source, so read to the end of the output for the error text. In the Python SDK, a generator exception is logged at debug level and the session stalls without raising, so if a streaming session hangs with no output, enable debug logging and check your generator.

06

What These Controls Cannot Do

This comparison concerns documented behavior and integration conditions. The cited material does not supply comparable pause-frequency, ambiguity-detection or mechanism-effectiveness measurements, so it does not establish a framework reliability ranking. Selection is based on interaction-pattern fit, not performance ordering.

Failure Modes: Missing Prerequisites and Implementation Errors

Diagram and data comparison
MechanismMissing prerequisite or implementation errorFailure behavior
LangGraph interrupt()No checkpointerCannot use the described checkpoint-based interrupt/resume mechanism
LangGraph interrupt()Different thread_idStarts a new empty thread instead of resuming the original checkpoint
LangGraph interrupt()Broad or bare handler catches and swallows the interrupt exceptionPause is lost if the exception is swallowed; separate interrupt from error-prone code, or catch only a specific non-interrupt exception (NetworkException example)
LangGraph interrupt()Non-idempotent side effects before interrupt()Duplicate execution on every resume; may create duplicate records or repeat writes
LangGraph interrupt()Conditional skipping or reordering of interrupt calls within a nodeIndex mismatch; resume values returned to wrong interrupt calls
AskUserQuestionAskUserQuestion omitted when an explicit tools array restricts the setModel silently loses ability to initiate clarification
AskUserQuestionIn Agent-tool subagentTool unavailable
canUseTool callbackdontAsk mode activeCallback never invoked; unapproved tools denied directly
canUseTool callbackTypeScript SDK permissionPrompts:'none'Callback not called at step 6; PermissionRequest hook still decides, otherwise denied
Streaming inputUsing single message modeReal-time interruption and message queueing not supported
Streaming inputTypeScript message generator throws exceptionStream ends with 'Claude Code process aborted by user' instead of the original error
Both missing prerequisites and implementation errors cause silent bypass or unintended denial. Sources: four framework documents.

Programmed gates only stop at covered conditions. They cannot guarantee the model recognizes every ambiguity, that requirements are sound, or that completed work is correct. Anthropic's building-effective-agents post recommends finding the simplest solution possible and only increasing complexity when it demonstrably improves outcomes, and emphasizes that agents should gain ground truth from the environment at each step—such as tool call results or code execution—to assess progress.

Pauses, task structure and independent verification complement one another. Where results can be checked independently, tests or tool feedback can supplement gates; where verification is difficult, decisions about which actions need prior human judgment require more care. This is a control-design judgment, not a measured interrupt-effectiveness result, and a pause is not proof that the work is correct.

Update record
  • 2026-10-18: Initial publication. Based on complete reading of four framework documents covering LangGraph interrupt(), Claude SDK permission evaluation (including auto mode, SHADOWED warning and non-triggering conditions), AskUserQuestion, and streaming input as four distinct pause mechanisms. Added upstream decision framework (simplicity-first and ground-truth verification), streaming debugging trap, SHADOWED non-triggering conditions and dontAsk hook limitation. Failure-mode matrix covers both missing prerequisites and implementation errors.
Sources and notes

This page contains no financial data. All mechanism descriptions come from framework documentation; no cost, latency or return-on-investment measurements are included.

  1. Ask HN: Those running agents 24/7, what's your workflow and what are they doing?
    Ask HN: Those running agents 24/7, what's your workflow and what are they doing? ↗

    Reader question motivating the article; individual anecdote from a SaaS business owner, not a measured prevalence study

    Original section · CuriousRose's original question about preventing AI from running without asking for clarity

    Read on: 2026-10-17
  2. Building effective agents
    Building effective agents ↗

    Design recommendation acknowledging pause need without specifying implementation; simplicity-first guidance and ground-truth verification principle

    Original section · Agent execution flow section describing pause for human feedback; simplicity and ground-truth principles

    Read on: 2026-10-17
  3. LangGraph Interrupts
    LangGraph Interrupts ↗

    Complete mechanism documentation for developer-placed pause with checkpoint persistence and full-node replay

    Original section · Complete interrupt() documentation: prerequisites, resume semantics, index matching, exception rules, validation patterns

    Read on: 2026-10-17
  4. Claude Agent SDK: Input and output — Handle approvals and user input
    Claude Agent SDK: Input and output — Handle approvals and user input ↗

    Complete user-input documentation covering callback mechanics, structured questions, alternatives and limitations

    Original section · canUseTool callback, AskUserQuestion handling, streaming input alternatives, custom tools, defer decision

    Read on: 2026-10-17
  5. Claude Agent SDK: Configure permissions
    Claude Agent SDK: Configure permissions ↗

    Complete permission evaluation documentation with conditional routing, mode-specific behavior, exception categories and deployment warnings

    Original section · Six-step permission evaluation flow, mode details including auto mode, allow/deny rule exceptions, dontAsk behavior, SHADOWED warning

    Read on: 2026-10-18
  6. Claude Agent SDK: Streaming Input
    Claude Agent SDK: Streaming Input ↗

    Complete streaming input documentation covering mid-task interruption, mode comparison, debugging trap and limitations

    Original section · Streaming vs single message input modes, interruption capability, queued messages, error-handling gotcha, limitations

    Read on: 2026-10-18

DisconfirmAI editorial · researched and compiled with AI. Sources and calculation scope are listed above.

Continue the investigation

Related collections

Research topics →