Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.blobhub.io/llms.txt

Use this file to discover all available pages before exploring further.

Claude Code and Codex occasionally pause to ask the user something — for approval before running a risky command, to pick from a list of options, or for free-text input. The worker surfaces these as structured thread items and resolves the user’s reply back to the agent. In v1 users answer with plain text in the standard thread widget. The structured metadata preserves the agent’s full prompt payload so a future native renderer (approval buttons, choice pickers, multi-question forms) can pick it up without protocol changes.

Prompt kinds

The underlying agent SDKs emit three kinds. The worker preserves the kind in metadata.prompt.kind.
kindWhen emitted
textFree-text question. Answer is a single string.
approvalYes/no approval (typically before a destructive or sensitive tool call).
ask_user_questionStructured question(s) with options (single- or multi-select). May carry multiple questions.
A kind: approval prompt is the user-facing side of the agent’s permissions: approval setting: when an agent runs under approval, each sensitive action is routed here for a human decision before it proceeds. If no human answers — for example, the worker shuts down with the prompt still open — the action is denied. Under permissions: autonomous there is no approval gate, so the agent does not raise these prompts. See the permissions setting for how it is resolved.

pending_prompt (worker → thread)

Posted when the agent’s turn pauses for input. The user is expected to reply by posting one or more thread items.
content:
  - type: text
    text: |
      ❓ Provide input:
      What's the deployment target?
        1. staging — push to staging.example.com
        2. production — push to www.example.com
      Reply with a number, the option text, or free text.
metadata:
  type: pending_prompt
  prompt:
    prompt_id: prm_01J...
    kind: ask_user_question
    prompt_state: pending
    questions:
      - question: "What's the deployment target?"
        multiSelect: false
        options:
          - { label: staging, description: "push to staging.example.com" }
          - { label: production, description: "push to www.example.com" }
The agent’s turn blocks at the tool call awaiting the answer; no further thread items are emitted until the prompt resolves. There is at most one active prompt per thread at any time.

pending_prompt_resolved (worker → thread, audit)

Posted once the prompt has been answered, cancelled, or failed. Audit-only — the worker has already delivered the answer to the agent before this item lands.
content:
  - type: text
    text: "✓ Answered: staging"
metadata:
  type: pending_prompt_resolved
  prompt:
    prompt_id: prm_01J...
    kind: ask_user_question
    prompt_state: answered            # answered | cancelled | failed
    answers:
      - question: "What's the deployment target?"
        answer: [staging]
    reason: null                      # populated when prompt_state is cancelled or failed

Answer correlation

The worker correlates the user’s reply to the active prompt in two ways:
  1. Positional (MVP, works with the standard thread widget). While a thread has an active pending_prompt, the next inbound user item is the answer. Its text is mapped per kind (below).
  2. Forward-compat structured (free). If an inbound user item carries metadata.prompt.prompt_id matching the active prompt and a structured answers array, the worker uses it verbatim. A future native widget posts this shape — no backend changes needed.
Items posted while no prompt is active are queued for the next agent turn as usual.

Text → answer mapping (per kind)

kindmapping
textanswer = [<raw user text>].
approvalAffirmative tokens (approve, approved, yes, y, ok, allow, 1) → ["Approve"]. Negative tokens (deny, denied, no, n, reject, 2) → ["Deny"]. Unrecognized input → ["Deny"] (defensive deny-on-uncertainty).
ask_user_question (single question)A bare number N → the Nth option’s label. A case-insensitive match to an option label → that label. Otherwise the raw text (the “Other” / free-text path). With multiSelect: true, comma- or space-separated numbers select multiple options.
ask_user_question (multi-question)Best-effort line-prefixed parse (1) … 2) …, matching the format the prompt’s content.text shows). Unparseable replies fall back to each question receiving the raw text as free text — best-effort until the native widget ships.
The “Other” path for ask_user_question preserves the user’s typed text as the free-text answer for that question.

Lifecycle and audit

  • Answered — the user provided a valid answer; agent receives it and continues. Audit item prompt_state: answered.
  • Cancelled — the prompt was abandoned (worker shutdown, worker restart, agent turn cancelled). Audit item prompt_state: cancelled with reason.
  • Failed — the prompt couldn’t be resolved due to an internal error. Audit item prompt_state: failed with reason.

Worker restart

An unresolved prompt does not survive a worker restart. On recovery the worker posts a pending_prompt_resolved audit item with prompt_state: cancelled, reason: worker_restart. When the agent resumes, it re-asks if it still needs the input. This is conservative — a future iteration may persist enough context to honor an answer posted while the worker was down.

See also