# Q&A File Protocol
This document is the single source of truth for the question/answer file format used by the o7 workflow engine.
## Overview
During workflow execution, an agent harness (e.g., `claude-code`) may need to ask the user clarifying questions before proceeding. The Q&A protocol defines a file-based mechanism for agents to pose questions and receive answers without blocking the harness process itself.
## File Location
All Q&A files reside in the `qa/` subdirectory of the per-run state directory:
```
<run-state-dir>/qa/
q-out-001.json # questions from agent, batch 1
q-answers-001.json # user answers to batch 1
q-out-002.json # questions from agent, batch 2
q-answers-002.json # user answers to batch 2
...
```
The run state directory is provided to harnesses via the `RUN_STATE_DIR` environment variable (e.g., `.7/runs/<run-id>/`).
## Sequence Numbers
- Sequence numbers are **3-digit zero-padded integers** in filenames (e.g., `001`, `002`, `042`).
- The JSON `seq` field contains the **plain integer** value (e.g., `1`, `2`, `42`).
- Sequences start at **001** / `1`.
- When parsing sequence numbers from filenames in bash scripts, always force decimal interpretation to avoid the bash octal bug with zero-padded numbers: `$((10#$seq_str))`.
## `q-out-NNN.json` — Agent Question Output
Written by the agent harness when it needs information from the user.
### Schema
```json
{
"seq": 1,
"questions": [
{
"id": "string (unique within this batch)",
"type": "choose-one | choose-many | free-write | yes-no",
"prompt": "string (the question text shown to the user)",
"preview": {
"type": "markdown | ascii",
"content": "string (optional rendered preview content)"
},
"options": ["string", "..."]
}
]
}
```
### Question Types
| `choose-one` | User selects exactly one option from the list | Yes |
| `choose-many` | User selects one or more options from the list | Yes |
| `free-write` | User types a free-form text answer | No |
| `yes-no` | User answers yes or no (binary choice) | No |
### Fields
- **`seq`** *(integer, required)*: The sequence number for this batch of questions. Must match the NNN in the filename.
- **`questions`** *(array, required)*: One or more question objects. Must be non-empty.
- **`id`** *(string, required)*: Unique identifier for the question within this batch. Used to correlate answers.
- **`type`** *(string, required)*: One of the question types listed above.
- **`prompt`** *(string, required)*: The question text displayed to the user.
- **`options`** *(array of strings, conditional)*: Required for `choose-one` and `choose-many` types. Must be omitted or empty for `free-write` and `yes-no`.
- **`preview`** *(object, optional)*: An optional preview block to display before the question.
- **`type`**: `"markdown"` or `"ascii"`.
- **`content`**: The preview content string.
## `q-answers-NNN.json` — User Answer Input
Written by the TUI (or another answer provider) once the user has answered all questions in the corresponding `q-out-NNN.json` batch. The original questions are echoed back for traceability.
### Schema
```json
{
"seq": 1,
"answers": [
{
"id": "string (matches question id)",
"type": "choose-one | choose-many | free-write | yes-no",
"prompt": "string (echoed from the original question)",
"options": ["string", "..."],
"answer": "string | [\"string\", ...] | true | false"
}
],
"questions": [
{ "...": "original question object echoed from q-out-NNN.json" }
]
}
```
### Fields
- **`seq`** *(integer, required)*: Must match the `seq` of the corresponding `q-out-NNN.json`.
- **`answers`** *(array, required)*: One entry per question in the batch. Each answer echoes back the original question fields for self-contained traceability.
- **`id`** *(string)*: Matches the `id` from the question.
- **`type`** *(string)*: Echoed from the original question.
- **`prompt`** *(string)*: Echoed from the original question.
- **`options`** *(array of strings, conditional)*: Echoed from the original question if present.
- **`answer`**: The user's response. Type depends on question type:
- `choose-one`: a single `string` matching one option.
- `choose-many`: an array of strings, each matching an option.
- `free-write`: a `string`.
- `yes-no`: `true` or `false`.
- **`questions`** *(array, required)*: The original question objects from `q-out-NNN.json`, echoed verbatim for traceability and context.
## Detection Mechanism
The TUI watches the `<run-state-dir>/qa/` directory for new `q-out-NNN.json` files using filesystem events (`fs.watch` or `inotify`). A polling fallback (e.g., every 500ms) is used when fs watch is unavailable or unreliable.
## Queuing Behavior
Multiple `q-out-NNN.json` files may accumulate if the agent writes them faster than the user answers. The TUI processes them **in ascending sequence order**. It will not present batch N+1 to the user until `q-answers-N.json` has been written.
## Example
### `qa/q-out-001.json`
```json
{
"seq": 1,
"questions": [
{
"id": "output-format",
"type": "choose-one",
"prompt": "What output format should the workflow produce?",
"options": ["JSON", "CSV", "plain text"]
},
{
"id": "description",
"type": "free-write",
"prompt": "Describe the workflow you want to generate in a few sentences."
}
]
}
```
### `qa/q-answers-001.json`
```json
{
"seq": 1,
"answers": [
{
"id": "output-format",
"type": "choose-one",
"prompt": "What output format should the workflow produce?",
"options": ["JSON", "CSV", "plain text"],
"answer": "JSON"
},
{
"id": "description",
"type": "free-write",
"prompt": "Describe the workflow you want to generate in a few sentences.",
"answer": "A workflow that fetches data from an API and stores results."
}
],
"questions": [
{
"id": "output-format",
"type": "choose-one",
"prompt": "What output format should the workflow produce?",
"options": ["JSON", "CSV", "plain text"]
},
{
"id": "description",
"type": "free-write",
"prompt": "Describe the workflow you want to generate in a few sentences."
}
]
}
```