Ask User a Question
ask_userDestructive
Request an unresolved decision or missing input from the user through Pushary. Supports confirm, select and input questions. Delivery and waiting follow the account policy; a call waits at most 55 seconds and may return immediately. Returns the question state, answer when available, delivery information and handoff fields. answerUrl is optional. Use wait_for_answer to read a pending result and cancel_question to retract it. Sends a real question; it does not grant permission for other actions.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| env | No | Set to "test" from a test suite. The question is stored and returned as pending, and nothing is delivered to a phone, browser or Slack. The X-Pushary-Env: test header does the same for every call on the connection. | |
| tags | No | Deliver only to subscribers that have any of these tags. | |
| type | No | Question type: confirm renders yes/no buttons, select renders the options list, input renders a free-text field. | confirm |
| wait | No | true (default) blocks until the user answers or the timeout fires. Set false to return immediately with a pending correlationId and poll it yourself via wait_for_answer. | |
| action | No | The concrete operation about to happen, one line. Shown as the Action line. Cut to 500 chars. | |
| intent | No | The user's stated task (from their last prompt), one line. Shown as the Intent line so the user can see why the agent stopped. Cut to 500 chars. | |
| blocker | No | The single gating reason the agent stopped, one line. Shown as the Blocker line. Cut to 500 chars. | |
| context | No | One or two sentences about what the agent is working on, shown above the question so the user can decide without opening the terminal. | |
| options | No | The 2 to 6 choices for a select question. Required when type is "select", ignored otherwise. The answered value is the chosen option string. | |
| repoKey | No | Stable repository identity for the working directory, e.g. "github.com/acme/api". Lets an approval routing rule scoped to one repository avoid governing another. Optional; omit it and only workspace-wide routing rules apply. | |
| question | Yes | The complete question, up to 8000 characters. Preserve every point. Notifications show a short preview; the answer interface shows the full question. | |
| toolName | No | The tool this approval is for (e.g. "Bash"), so the user can choose to always-allow it. | |
| toolPath | No | MACHINE-POPULATED. Exact absolute Write file_path from the runtime, for diagnostic correlation only. Models must omit it. | |
| agentName | No | Name of the agent asking, format "{Agent} - {project}" (e.g. "Claude Code - myproject"). Shown in the notification title so the user knows which session needs them. Falls back to the MCP client name if omitted. Cut to 100 chars. | |
| machineId | No | Stable machine id of the asking agent, so two machines never collapse into one session. | |
| questions | No | ONE question, in the richer Claude-compatible shape: a header, per-option descriptions, multiSelect, and an optional write-in. Exactly one keeps already-installed clients answerable; asking several means several calls. Runtime-populated; ordinary callers should omit it and use question/type/options. | |
| requestId | No | MACHINE-POPULATED. The CALLER's own identifier for one logical invocation, used only when the runtime supplies no toolUseId. Mint it once, outside your retry loop, and send the same value on every attempt, so three retries of one ask become one decision. Do NOT derive it from the question text or reuse it across two deliberate asks: both collapse a real second question into the first one's answer. If you are a model deciding to call this tool, omit this field. | |
| scopePath | No | Set ONLY when this approval exists because the path falls outside the scope the user ratified via propose_scope. Approving then widens the run scope to include this exact path, so the user is not asked again for the same area. | |
| sessionId | No | Opaque per-session id of the asking agent, so parallel sessions are attributed separately. | |
| timeoutMs | No | How long this call blocks, in milliseconds (max 55000). Defaults to the site policy timeout. Ordinary questions stay open until answered or cancelled. A timeout ends this poll only; follow up with wait_for_answer. | |
| toolUseId | No | MACHINE-POPULATED. The agent RUNTIME's own identifier for the tool call this approval gates, forwarded verbatim by a hook that received it. Do NOT invent, guess, derive, or reuse a value: two different questions sent under the same id collapse into one, and the second one never reaches a human. If you are a model deciding to call this tool, omit this field. | |
| actionBody | No | The diff (Edit/Write) or full command (Bash/apply_patch), secret-redacted and size-capped. Rendered as a collapsible detail block; never used as the push body. | |
| toolTarget | No | Compact target of the tool call (e.g. the command head "git push" for Bash, or a file extension like ".ts" for Edit/Write). Used to mine policy suggestions. | |
| waitEndsAt | No | MACHINE-POPULATED. When the agent hook stops waiting live and hands control back to the terminal. The question may remain answerable after this time. Ordinary callers should omit it. | |
| callbackUrl | No | Webhook URL that receives a POST with the answer when the user responds, signed with the X-Pushary-Signature header. Useful when the agent process may exit before the answer arrives. | |
| externalIds | No | Deliver only to subscribers matching these external IDs. | |
| pausedAware | No | MACHINE-POPULATED. true from a hook that ends a paused approval exactly as the same approval unanswered after its full wait. Any other value is ignored. If you are a model deciding to call this tool, omit this field. | |
| placeholder | No | Hint text shown inside the free-text field for input questions | |
| questionOwner | No | MACHINE-POPULATED. Ownership supplied by the supported personal Codex bridge. Models must omit this field. | |
| subscriberIds | No | Deliver only to these subscriber IDs. Omit all targeting fields to reach every connected device. | |
| permissionMode | No | MACHINE-POPULATED. The agent runtime's own permission or approval mode for the tool call this approval gates, recorded with the decision. Any other value is ignored. If you are a model deciding to call this tool, omit this field. | |
| sessionToolAware | No | MACHINE-POPULATED. Set by a Pushary hook whose engine applies a session tool grant with its risky-command ceiling, so the grant is only offered where it takes effect. If you are a model deciding to call this tool, omit this field. | |
| localSurfaceAvailable | No | MACHINE-POPULATED. false from a hook that cannot show its own approval prompt for this call, so the phone is asked every time and never spared for presence at the keyboard. Any other value is ignored. If you are a model deciding to call this tool, omit this field. |
Output Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| env | No | Echoed when the call was test traffic. | |
| held | No | Present when the question was stored but deliberately not delivered: test traffic, or a permission ask with no toolName and no sessionId. | |
| hint | No | What to do next, when there is a next step. | |
| mode | No | The site delivery mode that stopped this call from waiting. | |
| note | No | Free text the user added alongside their answer. | |
| type | Yes | The question type that was rendered. | |
| value | No | The user's answer: "yes" or "no" for confirm, the chosen option for select, the typed text for input. | |
| paused | No | True when nothing was sent because the last approvals in this session went unanswered. Withdraw the question, then end the call as it would end unanswered. | |
| status | No | The question state. Only pending is a live unanswered wait; cancelled, expired, missing, and unavailable must not be described as timeouts. | |
| warning | No | Present only when no channel is connected, naming what the user has to connect. | |
| answered | No | True once the user responded. Absent on the wait:false path, where nothing was awaited. | |
| delivery | No | Per-channel reach for the push carrying this question. | |
| question | Yes | The question exactly as the user saw it. | |
| timedOut | No | True when the initial wait ended while the question was still live. Poll once with wait_for_answer, then follow handoffAction when present, otherwise nextAction. | |
| answerUrl | No | Optional signed-in dashboard page where the user can answer this question. | |
| noDevices | No | True when no phone, browser, or Slack channel could receive the question. Do not wait; follow handoffAction immediately. | |
| nextAction | No | Backward-compatible next step: keep waiting while pending or ask in the current client. Follow handoffAction first when present. | |
| suppressed | No | True when the PHONE push was deliberately held because a terminal on this machine is active. It says nothing about the notch, the dashboard or Slack, which are unaffected and may still be showing this question. A caller with no screen of its own should treat it as the terminal's to answer; a caller that can render the question itself should keep waiting. | |
| waitEndsAt | No | When the agent hook stops waiting live. On an idempotent replay this is the original question's deadline, which the hook must reuse. | |
| answerSource | No | Recorded answering surface, when known. Missing provenance is not proof of a phone answer; sandbox is simulated. | |
| deliveryMode | No | Effective delivery policy for this decision. | |
| correlationId | Yes | Id of the question that was created. Pass it to wait_for_answer to keep waiting, or to cancel_question to retract it. | |
| handoffAction | No | Race-safe directive for updated clients. Takes precedence over nextAction: cancel before asking in the current client, or stop the handoff. | |
| policyTimeoutMs | No | Policy wait window in milliseconds. Callers must also honor their host deadline. | |
| expiresInSeconds | No | How long the question stays answerable. |