http://localhost:9858. Add -H "X-API-Key: $YUKTA_API_KEY" if your server has keys; answering needs the OPERATOR role, reading a VIEWER key. Who may answer which risk is explained in Who decides.
An input request is a typed question a node asks: a prompt, the answers on offer, a risk and a time to live. The run waits (a wait uses no tokens and no run slot beyond its own), the request appears on the event feed, and the server checks every answer against who may give it.
Steps
1
Ask from a workflow with ASK_INPUT
The kinds are
APPROVAL (approve or reject, or your own options), CHOICE, TEXT and STRUCTURED. The node adds input.decision, input.text, input.data, input.responder and input.confidence to the message metadata, so a BRANCH can route on it. Save as session.json:session.json
risk is LOW, MEDIUM (the default) or HIGH; a HIGH request is answered by people only. onTimeout is FAIL (default), CONTINUE (carries on with input.decision set to timeout) or USE_DEFAULT (answers with defaultDecision). audience limits who may answer, and route picks a route.2
Find the open request
id (the request id), executionId, kind, risk, prompt, options, tier, deadline and a version. The prompt and context are written by the asking step, often by a model, so treat them as untrusted text.3
Answer it
- REST
- CLI
- MCP
text, data, expectedVersion (the version you read, so a stale answer is refused).GET /api/events/stream?type=InputRequested.4
Ask from an AI agent
Set
"allowAskInput": true on the LLM_CALL node, which offers the model the tool ask_for_input {prompt, options?, kind?, risk?}, and on the MCP_TOOL_CALL node that runs its actions. The model chooses the question, but never a risk below inputRiskFloor (default MEDIUM). Who may answer (inputAudience), how long (inputTtlSeconds, default 3600), the route (inputRoute) and how many questions one node run may ask (inputMaxAsks, default 3) come from the node, never from the model. The answer returns to the model as a tool result, and no answer in time is a tool error, or fails the node with inputOnTimeout: FAIL. See Use tools and MCP servers.5
Or hold a message until a named approval
WAIT_FOR_SIGNAL asks a request of kind APPROVAL and risk HIGH, so only a person can answer. It holds each message, then lets it go on, drops it or fails:signal.name, signal.decision and signal.data. onTimeout: CONTINUE goes on with decision timeout; onReject: CONTINUE drops the message. Answer it exactly as above. MCP_TOOL_CALL’s requireApproval uses the same mechanism.Verify it worked
RUNNING with the confirm node waiting and the request OPEN. After approve, the request is ANSWERED and the result comes from the deployed terminal; with reject it comes from declined. The log records who answered and why.
If the answer is refused, the status says why: 403 names the rule that failed (audience, tier, risk, scope or separation) and leaves the request open, 409 means it was already answered, expired, cancelled or changed since expectedVersion, 422 means the answer does not fit the request (for a CHOICE, the decision must be an option id).
Variations
- Let a supervisor answer low-risk questions. A rules supervisor can approve
LOWrequests by policy: Write a rules supervisor. - Escalation tiers and webhooks. Supervisors first, then a person, or a chat bot with a one-time token: Route input requests.
- Pull instead of push. A script can poll
GET /api/inputswith anOPERATORkey and answer; example 15 does it with curl. - After a restart. Requests are held in memory by default: a restart cancels waiting runs and loses their open requests. With the Plus edition and PostgreSQL they survive: Persist sessions.
Related
- Who decides for risk tiers and why
HIGHis human only. - Plugin reference: routing and flow for the
ASK_INPUTandWAIT_FOR_SIGNALoptions. - REST: control and CLI reference.