Skip to documentation
Documentation navigation

Documentation navigation

Documentation / guides

AskUser

Ask the human a question through the Harness loop input seam.

developer

AskUser pauses a turn and asks the human a question. It optionally supplies a fixed choices list. The answer must equal one of those choices or the literal other, which is the escape hatch for free text. With no choices, any answer, including an empty answer, is accepted.

Contract

The JSON shape is {"question":"...","choices":["..."]}. question must be non-empty. Info exposes the AskUser name, schema, and a description that states the tool has no filesystem or network access.

Preparation is pure: PrepareCall returns a request with no requirements and a nil artifact. The question travels through the loop.RequestUserInput seam, so asking the user is not placed behind a second permission prompt. The tool still implements the common CallPreparer contract so Harness can validate the call boundary.

// AskUser has no workspace or network dependency. The loop provides the
// user-input callback through the invocation context.
ask := standardtools.AskUserDefinition()
built, err := ask.Build(ctx, tool.Bindings{SessionID: sessionID, LoopID: loopID})
if err != nil {
	panic(err)
}
answer, err := built[0].InvokableRun(ctx, `{"question":"Continue?","choices":["yes","no"]}`)

Parsing, a missing question, an answer outside the choice list, a canceled turn, or a provider failure becomes a tool-result error string. AuditSummary includes the question because the user sees it directly. It does not expose hidden gate state.

See Tool Definitions, Preparation, and Results for the common lifecycle and Harness’s tool calls and results for the surrounding turn.

Source

Proof

← back to documentation