Asking a human
Consumer-facing guide to ask_a_human — the structured human-in-the-loop question an agent raises when it is blocked on human judgment: a preference, a confirmation only a person knows, a pick among options. For the delegation model the escalation path rides on, see Delegating to sub-agents.
What an ask is (and is not)
ask_a_human puts exactly one structured question to the human and pauses only the asking run until it is answered. It is not a free-roaming chat pause: agents are taught to exhaust their tools first — anything a data query, knowledge-base search, or context read answers is never a valid ask.
Two shapes only:
| Shape | Agent supplies | Human answers with |
|---|---|---|
multiple_choice | question + 2-6 options labels | { "kind": "multiple_choice", "option_id": "...", "other_text": "..." } |
free_form | question only | { "kind": "free_form", "text": "..." } |
The Other write-in is guaranteed. On every multiple-choice ask the platform injects exactly one { "id": "other", "label": "Other" } option (deduping any caller-supplied "Other"). Picking other requires a non-empty other_text write-in — an empty or whitespace-only write-in is rejected at resume validation.
When the run resumes, the agent receives the answer as the tool result: { "answer": "<chosen label, write-in, or free text>", "option_id": "<id, multiple_choice only>" }.
Who pauses (escalation semantics)
Only the asking run ever blocks:
- Direct ask — the asking run transitions to
awaiting_inputwithpending_input_type: "ask_human". Any sub-agents it dispatched keep running to completion. - Sub-agent ask — the sub pauses itself and the question is escalated to its caller's event stream as a
child_needs_humanframe ({ child_run_id, question, timestamp }). Sibling sub-agents keep running; the caller is never paused by the escalation. The answer resumes the waiting sub directly — resume targets the paused child's run id.
Multiple concurrent asks on one conversation are surfaced oldest-first (FIFO); each is answered independently against its own run.
Answering
An ask is answered through the existing resume surface, targeted at the paused run:
curl -X POST https://api.amdahl.com/api/platform/v1/agents/<run_id>/resume \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{ "input": { "kind": "multiple_choice", "option_id": "other", "other_text": "SMB first, actually" } }'The body must match the run's persisted pending_input_schema (read it off the paused run row); a payload that violates the contract — unknown option_id, empty Other write-in, empty free text — is rejected with a validation error and the run stays paused for a corrected answer.
Behavior per surface
An ask behaves differently depending on how the run was started, controlled by the run's on_question mode:
| Surface / mode | What happens on an ask |
|---|---|
Interactive (console, on_question: "pause", the default) | The run pauses; the question renders as a pause widget; answer via resume. |
| REST | Reading the run shows status: "awaiting_input" + the question in pending_input_context; answer via the same resume endpoint. |
| MCP | The paused state is visible on run reads; the connected model answers via the resume tool or relays the question to its own user. |
on_question: "auto" (bare API callers running on judgment) | No pause. The tool returns { "skipped": true, "reason": "on_question_auto" } and the agent proceeds on its own judgment, stating the assumption it proceeded on. |
Routines / headless (on_question: "none") | No pause, no hang. The tool returns { "error": "no_human_in_loop" } immediately — scheduled runs must never depend on human asks. |
Limits
- One pending ask per run; a second ask in the same turn is refused with
ask_in_flight. - Multiple-choice asks take 2-6 caller options (the write-in is added on top); a question whose only option would be Other is rejected — use
free_form. - Free-form answers and Other write-ins are capped at 4000 characters.
- An answer inbox for headless runs (email notification, TTL,
on_no_answerpolicies) is a planned follow-up and not part of v1 — headless asks fail fast by design.