--- title: "Interviews" description: "How Arc collects human input during workflow execution" --- When a workflow reaches a [human gate](/workflows/human-in-the-loop), it needs to pause and wait for a person to respond. The **interviewer** is the abstraction that makes this work — it presents a question, collects an answer, and returns it to the engine so execution can continue. Arc ships with several interviewer implementations for different environments: an interactive terminal prompt for the CLI, a web-based queue for the API server and web UI, an auto-approve mode for CI, and record/replay support for testing. ## Question types Every human interaction is modeled as a `Question` with a type that determines how it's presented: | Type | Description | CLI presentation | |---|---|---| | `YesNo` | Binary yes/no decision | `[Y/N]` prompt | | `Confirmation` | Confirm an action (like YesNo) | `[Y/N]` prompt | | `MultipleChoice` | Pick one option from a list | Arrow-key selector or numbered list | | `MultiSelect` | Pick one or more from a list | Checkbox selector | | `Freeform` | Open-ended text input | `>` prompt | ### Question structure Each question carries metadata beyond the prompt text: | Field | Description | |---|---| | `text` | The question displayed to the user | | `question_type` | One of the types above | | `options` | List of `{key, label}` pairs for choice questions | | `allow_freeform` | Whether free-text input is accepted in addition to fixed options | | `default` | Default answer used on timeout | | `timeout_seconds` | How long to wait before using the default or timing out | | `stage` | The node ID that generated this question | | `metadata` | Arbitrary key-value metadata for integrations | ## Answer values Answers are one of six variants: | Value | Meaning | |---|---| | `Yes` | Affirmative response to a yes/no or confirmation question | | `No` | Negative response | | `Selected(key)` | A specific option was chosen (carries the option key) | | `Text(string)` | Free-text input | | `Skipped` | The user dismissed the question without answering | | `Timeout` | The question's timeout elapsed without a response | An answer can also carry a `selected_option` (the full `{key, label}` pair) and a `text` field for freeform input. ## How human gates build questions When the engine reaches a human gate node (`shape=hexagon`), the [human handler](/workflows/human-in-the-loop) builds a question from the node's outgoing edges: 1. Each edge becomes an option, with the accelerator key parsed from the label (e.g. `[A] Approve` → key `A`, label `[A] Approve`) 2. Edges with `freeform=true` are excluded from the option list and enable free-text fallback 3. The question text comes from the node's `label` attribute The handler then passes the question to the interviewer, waits for an answer, and maps it back to an edge for [transition](/workflows/transitions#human-gate-transitions). ## Channels The `Interviewer` trait has a simple interface — `ask(question) → answer` — and Arc provides implementations for each delivery channel: ### Console The default for CLI runs. On a TTY, the console interviewer uses interactive widgets (arrow-key selection, checkbox multi-select, confirm prompts) via `dialoguer`. When stdin is piped (non-TTY), it falls back to a line-based reader with numbered options. ```bash arc run workflow.dot # At a human gate: # ? Approve Plan # [1] A - [A] Approve # [2] R - [R] Revise # Select: ``` ### Web The default for API server runs. The web interviewer holds questions in a queue until answers are submitted externally — typically by the web UI or a REST API call. Each question gets a unique ID (e.g. `q-1`), and the `ask()` call blocks on a oneshot channel until `submit_answer(id, answer)` is called. This decoupling means the workflow engine and the user interface can run in different processes. The web UI polls for pending questions and posts answers back to the API. ### Slack Arc's Slack integration uses the web interviewer under the hood. When a human gate fires, the pending question is rendered as a Slack message with interactive buttons. When a user clicks a button, the Slack event handler calls `submit_answer()` on the web interviewer, unblocking the workflow. ### Auto-approve For fully automated runs or CI pipelines, the auto-approve interviewer answers every question without human input: - `YesNo` / `Confirmation` → `Yes` - `MultipleChoice` / `MultiSelect` → first option - `Freeform` → `"auto-approved"` Enable it with the `--auto-approve` flag: ```bash arc run workflow.dot --auto-approve ``` ## Timeouts Questions can have a `timeout_seconds` field. When set, Arc wraps the interviewer call with a timeout: - If the user answers before the deadline, their answer is used normally - If the timeout elapses and a `default` answer is set on the question, the default is used - If the timeout elapses with no default, the answer is `Timeout` The human handler then checks the node's `human.default_choice` attribute. If set, execution continues to the default target. Otherwise, the stage retries. ```dot approve [shape=hexagon, label="Approve?", human.default_choice="deploy"] ```