Handle approvals and user input changedagent-sdk/user-input
Nearest release: v2.1.284, published 16 hours after upstream edited the page. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.
Upstream edited this page at 28 Sep 2026 00:43 UTC, give or take a minute or two: the time comes from Anthropic’s own sitemap rather than from a commit. This site recorded the change at 28 Sep 2026 23:37 UTC.
Upstream edited
Recorded here
Lines+33added
Lines−33removed
From line
58
where the diff opens
First seen
14 Aug 2026
this site's first read of the page
Recorded edits12to this page, all time
The whole hunk
from line 58, old and new numbered
/
from line 58
5858
5959Your callback receives three arguments:
6060
61| Argument | Description |
62| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
63| `toolName` | The name of the tool Claude wants to use (for example, `"Bash"`, `"Write"`, `"Edit"`) |
64| `input` | The parameters Claude is passing to the tool. Contents vary by tool. |
61| Argument | Description |
62| - | - |
63| `toolName` | The name of the tool Claude wants to use (for example, `"Bash"`, `"Write"`, `"Edit"`) |
64| `input` | The parameters Claude is passing to the tool. Contents vary by tool. |
6565| `options` (TS) / `context` (Python) | Additional context including optional `suggestions` (proposed `PermissionUpdate` entries to avoid re-prompting) and a cancellation signal. In TypeScript, `signal` is an `AbortSignal`; in Python, the signal field is reserved for future use. See [`ToolPermissionContext`](/docs/en/agent-sdk/python#toolpermissioncontext) for Python. |
6666
6767The `input` object contains tool-specific parameters. Common examples:
6868
69| Tool | Input fields |
70| ------- | --------------------------------------- |
71| `Bash` | `command`, `description`, `timeout` |
72| `Write` | `file_path`, `content` |
73| `Edit` | `file_path`, `old_string`, `new_string` |
74| `Read` | `file_path`, `offset`, `limit` |
69| Tool | Input fields |
70| - | - |
71| `Bash` | `command`, `description`, `timeout` |
72| `Write` | `file_path`, `content` |
73| `Edit` | `file_path`, `old_string`, `new_string` |
74| `Read` | `file_path`, `offset`, `limit` |
7575
7676See the SDK reference for complete input schemas: [Python](/docs/en/agent-sdk/python#tool-input%2Foutput-types) | [TypeScript](/docs/en/agent-sdk/typescript#tool-input-types).
7777
from line 202
202202
203203Your callback returns one of two response types:
204204
205| Response | Python | TypeScript |
206| --------- | ------------------------------------------ | ------------------------------------- |
205| Response | Python | TypeScript |
206| - | - | - |
207207| **Allow** | `PermissionResultAllow(updated_input=...)` | `{ behavior: "allow", updatedInput }` |
208| **Deny** | `PermissionResultDeny(message=...)` | `{ behavior: "deny", message }` |
208| **Deny** | `PermissionResultDeny(message=...)` | `{ behavior: "deny", message }` |
209209
210210When allowing, the tool runs with the input Claude requested unless you return a modified input, `updatedInput` in TypeScript or `updated_input` in Python. Before v2.1.207, Claude Code rejected an allow result that omitted `updatedInput` and denied the tool call with a validation error.
211211
from line 502
502502 <Step title="Return answers to Claude">
503503 Build the `answers` object as a record where each key is the `question` text and each value is the selected option's `label`:
504504
505 | From the question object | Use as |
506 | ------------------------------------------------------------------- | ------ |
507 | `question` field (for example, `"How should I format the output?"`) | Key |
508 | Selected option's `label` field (for example, `"Summary"`) | Value |
505 | From the question object | Use as |
506 | - | - |
507 | `question` field (for example, `"How should I format the output?"`) | Key |
508 | Selected option's `label` field (for example, `"Summary"`) | Value |
509509
510510 For multi-select questions, pass an array of labels or join them with `", "`. If you [support free-text input](#support-free-text-input), use the user's custom text as the value.
511511
from line 542
542542
543543The input contains Claude's generated questions in a `questions` array. Each question has these fields:
544544
545| Field | Description |
546| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
547| `question` | The full question text to display |
548| `header` | Short label for the question (max 12 characters) |
549| `options` | Array of 2-4 choices, each with `label` and `description`. TypeScript: optionally `preview`. See [Option previews](#option-previews-typescript). |
550| `multiSelect` | If `true`, users can select multiple options |
545| Field | Description |
546| - | - |
547| `question` | The full question text to display |
548| `header` | Short label for the question (max 12 characters) |
549| `options` | Array of 2-4 choices, each with `label` and `description`. TypeScript: optionally `preview`. See [Option previews](#option-previews-typescript). |
550| `multiSelect` | If `true`, users can select multiple options |
551551
552552The structure your callback receives:
553553
from line 571
571571
572572`toolConfig.askUserQuestion.previewFormat` adds a `preview` field to each option so your app can show a visual mockup alongside the label. Without this setting, Claude does not generate previews and the field is absent.
573573
574| `previewFormat` | `preview` contains |
575| :-------------- | :------------------------------------------------------------------------------------------------------------ |
576| unset (default) | Field is absent. Claude does not generate previews. |
577| `"markdown"` | ASCII art and fenced code blocks |
578| `"html"` | A styled `<div>` fragment (the SDK rejects `<script>`, `<style>`, and `<!DOCTYPE>` before your callback runs) |
574| `previewFormat` | `preview` contains |
575| :- | :- |
576| unset (default) | Field is absent. Claude does not generate previews. |
577| `"markdown"` | ASCII art and fenced code blocks |
578| `"html"` | A styled `<div>` fragment (the SDK rejects `<script>`, `<style>`, and `<!DOCTYPE>` before your callback runs) |
579579
580580The format applies to all questions in the session. Claude includes `preview` on options where a visual comparison helps (layout choices, color schemes) and omits it where one wouldn't (yes/no confirmations, text-only choices). Check for `undefined` before rendering.
581581
from line 612
612612
613613Return an `answers` object mapping each question's `question` field to the selected option's `label`:
614614
615| Field | Description |
616| ----------- | ------------------------------------------------------------------------------------ |
617| `questions` | Pass through the original questions array (required for tool processing) |
618| `answers` | Object where keys are question text and values are selected labels |
619| `response` | Optional freeform reply the user typed instead of answering the structured questions |
615| Field | Description |
616| - | - |
617| `questions` | Pass through the original questions array (required for tool processing) |
618| `answers` | Object where keys are question text and values are selected labels |
619| `response` | Optional freeform reply the user typed instead of answering the structured questions |
620620
621621For multi-select questions, pass an array of labels or join them with `", "`. For per-question free text such as an "Other" option, put the user's text in `answers[question]` as shown in [Support free-text input](#support-free-text-input). Set `response` only when your UI lets the user dismiss the question card and type a general reply that isn't an answer to any specific question. When `response` is set, Claude receives "The user responded: …" instead of the per-question answer list.
622622
No line in this hunk matches that.