Operator questions, forwarded
Agent questions become blocking operator modals — never silent defaults.
When a dispatched agent agent asks a question, kitsoki parks the turn and forwards it to the operator: the web UI raises a hard modal with the agent's question, listed choices, and a custom-answer path for single-select prompts, and the answer flows back to unblock the agent. No headless auto-resolution, no silent landmines.
What happens when a headless agent asks a human-only question?
The agent parks, the operator answers a blocking modal, and the run resumes.
Kitsoki refuses silent default answers at human decision points.
Key beats
Every run begins here, in the story library — each card is a deterministic story graph kitsoki runs the same way every time. We'll demonstrate operator-ask forwarding on the bug-fix pipeline.

This story hands a ticket to a dispatched `claude -p` autofix agent. Here's the landmine kitsoki defuses: run that agent headless and its AskUserQuestion doesn't block — the tool silently auto-resolves to an *empty* answer, so the agent sails past the fork on a non-decision you never see. kitsoki hard-denies that tool and forwards the question back to the operator instead — the agent turn parks, blocking, until a human answers.

Click New session to create a fresh run of the pipeline — the surface where the operator drives the run and where a forwarded question will surface.

This is the session view: the operator drives the pipeline turn by turn. Somewhere inside, the dispatched autofix agent is running native execution — and it's about to hit a decision it can't make alone.

The agent forwarded an AskUserQuestion. kitsoki surfaces it as a hard, blocking modal — no dismiss, no backdrop close — because a real agent goroutine is parked on the answer. The header names the question; below it are the agent's own options plus a custom-answer escape hatch for single-select prompts.

Full recorded walkthrough (13 steps)
Each option is exactly what the agent offered — its label and an optional description. This is a single-select question: the operator can pick a listed path or use Custom answer when none of the choices quite fit.

When the listed choices are close but not right, Custom answer opens a small input inside the same modal. The agent is still blocked; the operator gets to send the precise instruction instead of forcing a bad option.

The custom field is gated just like the listed choices: Send answer stays disabled while it is empty, then enables once the operator types a concrete instruction. The answer still returns as a single string keyed by the original question.

Send answer echoes the operator's custom instruction back to the backend keyed by the question_id, which unblocks the exact parked agent goroutine — and the modal dismisses. The agent resumes with the operator's decision.

An agent can forward a multi-select question — 'choose any that apply'. The same modal renders checkboxes instead of radios; the operator can pick several before sending. Here the agent asks which checks to run before it ships.

Toggle as many options as apply — the marks switch from radios to checkboxes. Multi-select answers travel back as a list; single-select answers travel back as one string, whether it came from a listed label or custom text.

Send answer forwards the full selection set back, the second parked goroutine unblocks, and the queue empties — the modal closes for good. That's the full operator-ask round-trip.

You've seen the full round-trip: a dispatched agent forwards a question, kitsoki parks the agent turn and surfaces a blocking modal, the operator answers with a listed choice, custom text, or a multi-select list, and Send answer echoes that decision back to unblock the exact parked goroutine. The headless default would have let the agent guess on an empty answer — here a human decides the fork instead, and the runtime never moves until they do.
