diff --git a/.changeset/ask-user-question-forms.md b/.changeset/ask-user-question-forms.md
index 3eab8ae..d59a062 100644
--- a/.changeset/ask-user-question-forms.md
+++ b/.changeset/ask-user-question-forms.md
@@ -2,4 +2,4 @@
"@jmfederico/pi-web": patch
---
-Add an `ask_user` session tool that lets agents post structured question sets as one chat-native browser form. The form uses the transcript's single scroll area, keeps its header visible, and always gives every question a Custom free-text answer. Agents end their run while the form waits; users can submit full or partial answers, unanswered questions are reported explicitly, pending forms survive browser and web/API reconnects, and closed forms remain readable in the transcript. Disable the tool with `askUser: false` or `PI_WEB_ASK_USER=false`.
+Add an `ask_user` session tool that lets agents post structured question sets as one chat-native browser form. The form uses the transcript's single scroll area, keeps its header visible, and always gives every question a Custom free-text answer. Agents end their run while the form waits; users can submit full or partial answers, unanswered questions are reported explicitly, pending forms survive browser and web/API reconnects, and closed forms remain readable in the transcript. Disable the tool from **Settings → Session daemon**, with `askUser: false`, or with `PI_WEB_ASK_USER=false`.
diff --git a/docs/config.html b/docs/config.html
index 44d2105..da45276 100644
--- a/docs/config.html
+++ b/docs/config.html
@@ -270,7 +270,7 @@
it, and whether project-local config overrides or merges with global config. Rows with JSON key
— are runtime-only environment variables, not config-file keys. Global means
machine-global. In Settings, selected-machine-safe global keys (pathAccess, uploads,
- maxUploadBytes, agent, spawnSessions, subsessions, and plugins)
+ maxUploadBytes, agent, spawnSessions, subsessions, askUser, and plugins)
are edited for the selected machine; gateway host/port/allowed-hosts, keyboard shortcuts, and machine
registry/tokens stay local.
true; set it to false, or set PI_WEB_ASK_USER=false, to remove the
tool. The environment override accepts 0|1|true|false and takes precedence over the config file.
+
+ Use Settings → Session daemon → Allow agents to ask questions to change
+ askUser on the selected machine. An environment override makes the toggle read-only.
+
The tool accepts one set of 1–20 questions. Each question has a unique id, its
question text, optional supporting detail, up to 12 options with stable values and
diff --git a/docs/config.md b/docs/config.md
index 76ebfcb..f28cf05 100644
--- a/docs/config.md
+++ b/docs/config.md
@@ -102,7 +102,7 @@ Plugins may own separate project files, such as `.pi-web/tasks.json` for the bui
## Configuration matrix
-Rows with JSON key `—` are runtime-only environment variables, not config-file keys. `Global` means machine-global. In Settings, selected-machine-safe global keys (`pathAccess`, `uploads`, `maxUploadBytes`, `agent`, `spawnSessions`, `subsessions`, and `plugins`) are edited for the selected machine; gateway host/port/allowed-hosts, keyboard shortcuts, and machine registry/tokens stay local.
+Rows with JSON key `—` are runtime-only environment variables, not config-file keys. `Global` means machine-global. In Settings, selected-machine-safe global keys (`pathAccess`, `uploads`, `maxUploadBytes`, `agent`, `spawnSessions`, `subsessions`, `askUser`, and `plugins`) are edited for the selected machine; gateway host/port/allowed-hosts, keyboard shortcuts, and machine registry/tokens stay local.
| Config | JSON key | Env var | Scope | Project-local behavior | Applies / restart |
| --- | --- | --- | --- | --- | --- |
@@ -275,6 +275,8 @@ In **Settings → Session daemon**, these keys are saved on the selected machine
`askUser` controls whether agents receive the core `ask_user` tool. It defaults to `true`; set it to `false`, or set `PI_WEB_ASK_USER=false`, to remove the tool. The environment override accepts `0|1|true|false` and takes precedence over the config file.
+Use **Settings → Session daemon → Allow agents to ask questions** to change `askUser` on the selected machine. An environment override makes the toggle read-only.
+
The tool accepts one set of 1–20 questions. Each question has a unique `id`, its `question` text, optional supporting `detail`, up to 12 options with stable values and user-facing labels, and an optional `multiple` flag. The browser always adds a **Custom** free-text answer, including when the model supplies no options. No question is required: the user may leave any of them unanswered.
Calling `ask_user` posts the whole set as one browser form and ends the current agent run instead of waiting for the user. The open form is owned by the session daemon, so it survives a browser disconnect, browser reload, or web/API restart while that daemon keeps running. When the user submits, the answers arrive as a follow-up that wakes the session; each question is reported with its selected option values or free text, or explicitly as unanswered.
diff --git a/src/client/src/components/settings/SettingsSessiondPanel.askUser.test.ts b/src/client/src/components/settings/SettingsSessiondPanel.askUser.test.ts
new file mode 100644
index 0000000..24a50fb
--- /dev/null
+++ b/src/client/src/components/settings/SettingsSessiondPanel.askUser.test.ts
@@ -0,0 +1,78 @@
+// @vitest-environment happy-dom
+
+import { beforeEach, describe, expect, it, vi } from "vitest";
+import type { PiWebConfigResponse } from "../../api";
+import { SettingsSessiondPanel } from "./SettingsSessiondPanel";
+
+beforeEach(() => {
+ document.body.replaceChildren();
+});
+
+describe("SettingsSessiondPanel Ask Questions setting", () => {
+ it("lets the user disable ask_user with a daemon config patch", async () => {
+ const panel = new SettingsSessiondPanel();
+ const onSave = vi.fn();
+ panel.configResponse = configResponse(true);
+ panel.onSave = onSave;
+ document.body.append(panel);
+ await panel.updateComplete;
+
+ const toggle = askUserToggle(panel);
+ expect(toggle.checked).toBe(true);
+ expect(toggle.disabled).toBe(false);
+
+ toggle.click();
+ await Promise.resolve();
+
+ expect(onSave).toHaveBeenCalledWith({ askUser: false });
+ });
+
+ it("keeps an environment-overridden setting read-only", async () => {
+ const panel = new SettingsSessiondPanel();
+ panel.configResponse = configResponse(true, true);
+ document.body.append(panel);
+ await panel.updateComplete;
+
+ const toggle = askUserToggle(panel);
+ expect(toggle.checked).toBe(true);
+ expect(toggle.disabled).toBe(true);
+ });
+
+ it("does not offer an unsupported setting from an older selected machine", async () => {
+ const panel = new SettingsSessiondPanel();
+ panel.configResponse = configResponse(undefined);
+ document.body.append(panel);
+ await panel.updateComplete;
+
+ const toggle = askUserToggle(panel);
+ expect(toggle.checked).toBe(false);
+ expect(toggle.disabled).toBe(true);
+ });
+});
+
+function askUserToggle(panel: SettingsSessiondPanel): HTMLInputElement {
+ const toggle = panel.shadowRoot?.querySelectorspawn_subsession, list_subsessions, check_subsession, read_subsession) and are notified when a child finishes. Requires "Allow agents to start sessions". Off by default.
+ Desired after environment overrides
@@ -151,6 +175,7 @@ export class SettingsSessiondPanel extends LitElement {