---
name: Socratic Interview
slug: socratic-interview
category: AI Engineering
description: Socratic Interview crystallizes vague requirements into clear specifications through a structured Q&A process. Use it when an agent needs to clarify ambiguous project goals before generating code or plans.
github: "https://github.com/Q00/ouroboros/tree/main/skills/interview"
language: Python
stars: 5431
forks: 550
install: "npx degit https://github.com/Q00/ouroboros/tree/main/skills/interview ~/.claude/skills/interview"
installs_to: ~/.claude/skills/interview
source_path: skills/interview/SKILL.md
collection_size: 25
category_size: 2451
collection_url: "https://dirskills.com/collections/Q00/ouroboros"
added: 2026-08-16T07:00:01.140Z
last_synced: 2026-08-16T07:00:01.140Z
canonical_url: "https://dirskills.com/skills/socratic-interview"
---

# Socratic Interview

Socratic Interview crystallizes vague requirements into clear specifications through a structured Q&A process. Use it when an agent needs to clarify ambiguous project goals before generating code or plans.

**Install:**

```bash
npx degit https://github.com/Q00/ouroboros/tree/main/skills/interview ~/.claude/skills/interview
```

## README

# /ouroboros:interview

Socratic interview to crystallize vague requirements into clear specifications.


## Required Skill Capabilities

- `ask_user` — ask human-judgment questions through the active runtime's user-question surface.
- `inspect_code` — answer repo-local factual questions from exact local files before asking the user.
- `call_mcp` — use Ouroboros MCP tools for persistent interview state and seed generation.
- `run_lateral_review` — invoke lateral thinking subagents before milestone turns and direct-answer synthesis.
- `web_research` — fetch current external facts only when the interview genuinely depends on them.
- `run_shell` — run bounded local commands for version checks and repository inspection.
- `refine_answer` — confirm structured interpretations of free-text answers before forwarding them.
- `maintain_ledger` — keep ambiguity, gates, and unresolved decisions visible in the main session.
- `run_closure_gate` — audit readiness locally even when MCP reports `seed-ready`.
- `restate_goal` — restate the goal and require explicit approval before seed generation.

## Non-Skippable Gates

- Refine free-text answers that carry scope, constraints, or decisions.
- Maintain a visible ambiguity ledger in the main session.
- Treat MCP `seed-ready` as permission to audit closure, not as completion.
- Apply Seed Closer criteria before suggesting or running seed generation.
- Run the Restate gate before seed generation.
- Require explicit user approval before suggesting or running seed generation.

## Usage

```
ooo interview [topic]
/ouroboros:interview [topic]
```

**Trigger keywords:** "interview me", "clarify requirements"

## Instructions

When the user invokes this skill:

### Step 0: Version Check (runs before interview)

Before starting the interview, check if a newer version is available:

```bash
# Fetch latest release tag from GitHub (timeout 3s to avoid blocking)
curl -s --max-time 3 https://api.github.com/repos/Q00/ouroboros/releases/latest | grep -o '"tag_name": "[^"]*"' | head -1
```

Compare the result with the current version in the active runtime's local plugin metadata (for Claude installs this is `.claude-plugin/plugin.json`).
- If a newer version exists, ask the user through the active runtime's `ask_user` capability:
  ```json
  {
    "questions": [{
      "question": "Ouroboros <latest> is available (current: <local>). Update before starting?",
      "header": "Update",
      "options": [
        {"label": "Update now", "description": "Update plugin to latest version (restart required to apply)"},
        {"label": "Skip, start interview", "description": "Continue with current version"}
      ],
      "multiSelect": false
    }]
  }
  ```
  - If "Update now":
    - On Claude-plugin installs only:
      1. Run `claude plugin marketplace update ouroboros` via the active runtime's `run_shell` capability (refresh marketplace index). If this fails, tell the user "⚠️ Marketplace refresh failed, continuing…" and proceed.
      2. Run `claude plugin update ouroboros@ouroboros` via the active runtime's `run_shell` capability (update plugin/skills). If this fails, inform the user and stop — do NOT proceed to the package-manager step.
    - On non-Claude runtimes, skip Claude plugin commands and proceed directly to the package-manager step for `ouroboros-ai`; do not require Claude-only commands or tools.
    3. Detect the user's Python package manager and upgrade the MCP server:
       - Check which tool installed `ouroboros-ai` by running these in order:
         - `uv tool list 2>/dev/null | grep "^ouroboros-ai "` → if found, use `uv tool upgrade ouroboros-ai`
         - `pipx list 2>/dev/null | grep "^  ouroboros-ai "` → if found, use `pipx upgrade ouroboros-ai`
         - Otherwise, print: "Also upgrade the MCP server: `pip install --upgrade ouroboros-ai`" (do NOT run pip automatically)
    4. Tell the user: "Updated! Restart your session to apply, then run `ooo interview` again."
  - If "Skip": proceed immediately.
- If versions match, the check fails (network error, timeout, rate limit 403/429), or parsing fails/returns empty: **silently skip** and proceed.

Then choose the execution path:

### Step 0.5: Load MCP Tools (Required before Path A/B decision)

The Ouroboros MCP tools are often registered as **deferred tools** that must be explicitly loaded before use. **You MUST perform this step before deciding between Path A and Path B.**

1. Use the active runtime's tool-discovery capability to find and load the interview MCP tool:
   ```
   tool discovery query: "+ouroboros interview"
   ```
   This searches for tools with "ouroboros" in the name related to "interview".

2. The tool will typically be named `mcp__plugin_ouroboros_ouroboros__ouroboros_interview` (with a plugin prefix). After runtime tool discovery returns, the tool becomes callable.

3. If the tool is callable — already exposed, or loaded by discovery — proceed to **Path A**.
   An empty discovery result for an already-exposed tool is expected, not a failure.
   Proceed to **Path B** only if the tool is genuinely absent (no Ouroboros MCP server).

**IMPORTANT**: Do NOT skip this step. Do NOT assume MCP tools are unavailable just because they don't appear in your immediate tool list. They are almost always available as deferred tools that need to be loaded first.

**CRITICAL — deferred-schema guard (prevents "Invalid tool parameters"):**
This skill makes `ouroboros_*` MCP calls across multiple turns, and each turn runs
in a fresh tool context. A deferred tool's schema loaded on one turn is NOT
guaranteed to still be loaded on the next. If you call any `ouroboros_*` MCP tool
while its schema is not loaded in the **current** turn, the runtime rejects the
call with **"Invalid tool parameters"** before it ever reaches the server.
Therefore: **immediately before EVERY `ouroboros_*` MCP call in this skill, re-run
the tool-discovery load query for the specific MCP tool you are about to call**
(idempotent — a no-op when the schema is already loaded) so the correct schema is
guaranteed present for that call. Use `"+ouroboros interview"` before
`ouroboros_interview` and `"+ouroboros lateral"` before
`ouroboros_lateral_think`. If a load ever returns no matching tool (and the tool is not already callable — an empty load for an already-exposed tool is an expected no-op, not absence), switch to the
documented fallback / Path B instead of retrying the failing call.

### Path A: MCP Mode (Preferred)

If the `ouroboros_interview` MCP tool is available (loaded via runtime tool discovery above), use it for persistent, structured interviews.

**Architecture**: MCP is a pure question generator. You (the main session) are the answerer and router.

```
MCP (question generator) ←→ You (answerer + router) ←→ User (human judgment only)
```

**Role split**:
- **MCP**: Generates Socratic questions, manages interview state, scores ambiguity. Does NOT read code.
- **You (main session)**: Receives MCP questions, answers them by reading code through the active runtime's `inspect_code` capability, or routes to the user when human judgment is needed.
- **User**: Only answers questions that require human decisions (goals, acceptance criteria, business logic, preferences).

#### Interview Flow

1. **Start a new interview**:
   ```
   Tool: ouroboros_interview
   Arguments:
     initial_context: <user's topic or idea>
     cwd: <current working directory>
     confused_terms: <optional explicit terms the user does not understand>
     references: <optional [{reference_id, label, origin, url?, excerpt?}]>
   ```
   Returns a session ID and the first question.

   `confused_terms` and `references` are structured adapter context, not
   requirements. They are queued on the start call and MUST NOT alter the first
   question. On later turns, glossary help is limited to explicitly confused
   terms and references are used only for contrast questions. Do not infer these
   arguments from vocabulary density or fetch referenced URLs/files.

2. **For each question from MCP, apply the routing paths below:**

   **Parent-session question handoff**:
   If an MCP response includes `meta.status="parent_question_required"` or
   `meta.ask_user_directly=true`, treat it as a normal interview continuation,
   not as an MCP/provider/tool failure. Do **not** tell the user MCP failed, do
   not expose `reason_code`, and do not retry the MCP question generator. Ask
   exactly one natural Socratic clarification question yourself, using the same
   routing judgement as any other interview turn. Save the exact user-facing
   question text. When the user answers, call:
   ```
   Tool: ouroboros_interview
   Arguments:
     session_id: <meta.session_id>
     answer: <user answer>
     last_question: <exact question you asked the user>
   ```
   `last_question` is required on this path so MCP can persist the real
   transcript even though the parent session generated the question.

   **Question-first advisory fanout**:
   If an MCP response includes `meta.question_advisory_request`, show the
   interview question to the user first, then use the advisory request as a
   parent-session assist layer. The advisory exists to help the human answer;
   it must not hide, replace, or delay the question itself.

   Run the advisory lanes through your runtime's native subagent mechanism when
   one exists. For Claude Code this is the Task/Agent tool; for Codex, explicitly
   start a native subagent workflow in natural language. Spawn one subagent per
   lane, pass that lane's payload prompt, wait for all agents, then synthesize.
   If the runtime has no parallel primitive, process payloads sequentially per
   `dispatch_mode="sequential"` and the request's `sequential_fallback`
   semantics. The standard lanes are:
   - `code_context` — inspect repo-local facts and reuse
     `meta.code_investigation_request` when present.
   - `web_context` — browse/search only when current external facts genuinely
     affect the answer.
   - `data_context` — take the measurements that inform the question.
     This lane takes the measurement; see "Data measurements" below.
   - `ambiguity_contrarian` — find hidden assumptions, vague terms, missing
     decisions, and risky defaults.
   - `answer_simplifier` — turn the question into 2-3 easy choices or one
     concise draft answer.
   - `architecture_implications` — check whether the answer changes ownership,
     interfaces, rollout, or system shape.

   Synthesize advisory results into a compact helper for the user: 2-3 answer
   options, one recommended draft, or a short "I found these ambiguities" note.
   Do not forward advisory output to `ouroboros_interview` until the user
   approves, edits, or explicitly asks you to auto-confirm a safe answer.
   When `meta.question_advisory_subagents` is present you MUST fan out: treat
   each entry as a spawn-ready advisory payload with `title`, `agent`, `prompt`,
   and `context`, and dispatch every payload through your host's native subagent
   mechanism (Claude Code → one Task/Agent call per payload in one parallel
   batch; Codex → explicitly spawn one Codex subagent per payload, wait for all
   results, then synthesize; runtimes without a parallel primitive → process
   payloads sequentially per `dispatch_mode="sequential"`) instead of
   reconstructing prompts from prose. This
   is required regardless of dispatch mode: the payloads themselves are the
   spawn signal.
   Treat `meta.question_advisory_host_action=spawn_subagents`, when present, as
   a reinforcing cue for host-driven runtimes such as Codex or Claude Code, not
   as a prerequisite. The only time you skip spawning is when the host has no
   subagent primitive at all (then use `sequential_fallback`).
   Preserve the original question text while advisory children run.

   **Submitting fan-out results back (re-entry)**:
   When the originating `meta` carries a `fanout_id` (e.g.
   `meta.question_advisory_fanout_id`, or a `fanout_id` in a lateral persona
   panel dispatch), after all advisory/persona subagents return, call
   `ouroboros_submit_fanout_results` with:
   - `session_id`: the session the fan-out was issued under. Required whenever
     the producer ran with one — an omitted session is refused rather than
     waived, because this is what binds a submission to its owner. Contracted
     lanes assert no session of their own; this argument is the binding.
   - `fanout_id`: the stamped id from that meta,
   - `correlation_key`: the stamped `result_correlation_key`
     (`context.lane_id`, `context.persona`, or `code_facts`). Omitting it is
     refused the same way whenever the fan-out recorded one — send back what the
     meta stamped rather than leaving it out,
   - `results`: one `{ "key": <correlation value>, "content": <child output> }`
     per subagent, where `key` is that child's correlation value (its lane id,
     persona, or `code_facts`).
   Every result must be either `{ "key": <lane>, "content": ... }` or exactly
   `{ "key": <lane>, "undispatched": true }` — the literal `true`, no `content`
   beside it, and never an entry carrying neither. One entry per lane: a lane
   reported twice is two statements about it, and nothing here picks between
   them by list position. Anything else comes back as
   `status="invalid_result_entry"` with `invalid_keys`, listing every bad entry
   at once so one resubmission fixes them all.

   A complete set returns a bounded artifact envelope. Call
   `ouroboros_fetch_artifact` with its `contract_id`, then continue from the
   correlated synthesis in the fetched `body`. This explicit MCP fetch is
   required even when the host has no shell. A partial
   set returns `status="partial"` with `missing_required_keys`. **Retry with
   every lane you hold, not only the missing ones** — no submitted output is
   kept between calls, so each call is judged on what it carries. (The record
   stores only what was *asked*; retaining what children *answered* is durable
   result state, deferred with its sanitization duties to a later slice.)
   Sequential hosts submit after processing payloads one-by-one — same tool,
   same contract, so accumulate the outputs on your side and send the growing
   set. Continue the interview from the fetched synthesis; keep the
   user-facing question visible throughout.

   Only lanes marked `required: true` in the request block completion. A lane
   you ran that had nothing to say still submits its output — that is an answer.
   A lane you could **not spawn at all** (no capability for it, the child died,
   the user cancelled it) is submitted as
   `{ "key": <lane id>, "undispatched": true }`. Never invent output for a lane
   you did not run: a fabricated finding is worse than a missing one, and this
   is exactly why the declaration exists.

   **Data measurements**:
   The `data_context` lane discovers what data tools this host exposes, takes
   the measurement itself, and returns the aggregate it read.
   You do not confirm anything before it runs and you do not run anything after
   — it has already happened by the time you read the result. There is nothing
   to approve because the approval already exists: the user registered these
   tools, and registering one is the willingness to have it called. That is the
   standing every other advisory lane runs on, and this lane was the only one
   asked to hold a line in prose that its siblings did not.

   When its output carries measurements:
   - Show the numbers **beside** the question as material for the user's
     judgment. They are never the answer. The user answers in their own words
     on the ordinary `[from-user]` path; there is no `[from-data]` answer to
     forward. This is now the whole of the boundary: the lane carries real
     values, so the only thing standing between a measurement and the Seed is
     that you put it next to the question instead of into the answer.
   - Carry the aggregate as the lane reported it, with its `metric` and the
     decision it informs. Do not re-derive, re-scale, or combine numbers across
     measurements; you did not run the read and cannot know what would survive
     the arithmetic.
   - If the user has already answered the question by the time the measurement
     arrives, drop it. Do not re-open a decision the user has made, and do not
     present the numbers as a reason to reconsider — evidence informs a
     decision, it does not revisit one.

   When `data_needed` is false the lane looked and found nothing to measure.
   Every reason it can give is a statement about the lane, never about the
   user's infrastructure — a subagent sees what reached it, not what is
   connected, so it is not positioned to tell anyone a data path is missing.
   Read them accordingly:
   - `not_a_measurement` / `question_too_ambiguous_to_measure` — about the
     question. Nothing to relay beyond moving on.
   - `answer_would_not_be_an_aggregate` — about the shape of the answer.
   - `no_data_store_described` — nothing the lane was shown holds this answer.
     Worth mentioning only if you know the store exists and the lane was not
     told about it; otherwise it is ordinary.
   - `store_described_but_not_callable` — **this one is yours to handle, not
     the user's to hear.** A store exists and the child could not reach it. You
     see the environment and it does not: check whether the tool is available to
     you, take the read yourself, or re-dispatch the lane. Do not surface it as
     a missing data path. This constant exists because its predecessor was
     relayed to a user as a fact about their own infrastructure while the store
     in question sat described in the child's prompt.

   `no_evidence_reason` is one of a fixed set of constants, so say it in your
   own words rather than pasting the constant.

   What this lane can reach is not classified by anyone. The child names the
   tool it used; it cannot prove that tool was read-only, and MCP carries no
   cost or mutation metadata for you to check against. That risk is accepted
   knowingly and is the same one the sibling advisory lanes already run under.
   Do not manufacture a disclaimer about it: a warning attached to every
   measurement is one users learn to click through, and it would be
   describing a check nothing performed.

   **Milestone lateral-review dispatch**:
   If an MCP response includes `meta.lateral_review_recommended=true`, treat it
   as a required lightweight subagent review for that turn. The interview just
   crossed an ambiguity milestone such as `initial -> progress`,
   `progress -> refined`, or `refined -> ready`, which is exactly when hidden
   assumptions tend to matter.

   After showing the returned question to the user:
   - Tell the user briefly that a few perspectives are checking the question.
   - Call `ouroboros_lateral_think` with `meta.lateral_review_tool_args` when
     present. If only the legacy advisory fields are present, call it with
     `personas=["researcher","contrarian","simplifier"]`, a problem context
     containing the current interview session/milestone/question, and a current
     approach describing the next interview-routing decision.
   - Fold only concrete, user-safe findings into the next answer or user
     question. Do not present every subagent note as a report.
   - If lateral tooling is unavailable, continue the interview and say the
     review could not be run; do not restart the interview.

   The MCP interview tool is still the question generator and source of
   persistent state. Lateral review is a main-session assist layer: it helps the
   user feel supported, but it does not by itself change requirements or mark the
   interview complete.

   **Main-session direct-answer assistance**:
   Use lateral review frequently when the main session would otherwise answer
   the MCP question directly or compress the user's free-text into a decision.
   This i
