Skip to content

Interactive Questions Pattern

Planu tools are designed to act autonomously by default. When a tool cannot proceed without user input — because an action is irreversible, ambiguous, or policy-blocked — it returns an InteractiveQuestion[] instead of blocking the call or making a silent assumption.

Why Tools Return Questions

The autopilot-first design means tools choose the safest default and proceed whenever possible. But some decisions must be explicit:

  • Destructive actions. Deploying to production, deleting a spec, overwriting locked content.
  • Ambiguous inputs. Multiple specs match a search term; the tool cannot pick for you.
  • Policy gates. Approving a spec with 0 passing criteria requires explicit confirmation.

Rather than throwing an error or hanging, the tool returns an array of structured questions. The LLM receives this array in the tool response, relays each question to the user via AskUserQuestion, collects the answers, and re-invokes the tool with the answers supplied as arguments.

No blocking I/O

Tools never block on user input. The call always returns immediately — either with a result or with InteractiveQuestion[]. This makes tools safe to use in async pipelines and agent loops.

The InteractiveQuestion Type

json
{
  "id": "confirm-target-env",
  "question": "Which environment should this deploy to?",
  "type": "choice",
  "options": ["staging", "production"],
  "default": "staging"
}
FieldTypeDescription
idstringUnique identifier — used to match answers to questions on re-invocation
questionstringHuman-readable question text
typeenumchoice / multiChoice / text / confirm
optionsstring[]Valid options for choice and multiChoice types
defaultanyPre-selected value — used in autonomous mode
requiredbooleanIf false, the tool can proceed with the default if the user skips

Question Types

TypeBehavior
choiceSingle selection from a fixed options list
multiChoiceMultiple selections from a fixed options list
textFree-text input — validated against pattern if provided
confirmBoolean yes/no — maps to true / false

How the LLM Relays Questions

1. LLM invokes tool (e.g. update_status("SPEC-NNN", "approved"))
2. Tool detects gate condition (0 passing criteria)
3. Tool returns { interactiveQuestions: [ { id: "confirm-low-criteria", ... } ] }
4. LLM reads the array
5. LLM calls AskUserQuestion with the question text
6. User answers "yes"
7. LLM re-invokes: update_status("SPEC-NNN", "approved", { answers: { "confirm-low-criteria": true } })
8. Tool proceeds past the gate

In Claude Code, the relay mechanism is the built-in AskUserQuestion tool. In other hosts, the pattern is the same but the relay mechanism differs (e.g. an HTTP endpoint or a chat UI input field).

When to Expect Questions

ToolWhen it returns questions
create_specWhen the spec title matches an existing spec (duplicate check)
update_status(approved)When check_readiness returns 0 passing criteria
update_status(done)When validate finds unmet acceptance criteria
deploy_specWhen the target environment is production
delete_specAlways — deletion is irreversible
lock_specWhen the spec is in draft status (unusual to lock early)

Autonomous Mode and Questions

In Autonomous Mode, Planu uses the default field of each question instead of relaying it to the user. This allows fully unattended pipeline runs. If a question has no default and required is true, autonomous mode will block the transition and surface the question to the operator.


Join the communityAsk questions, share feedback, and connect with other developers using Planu.
Join Discord